本文整理汇总了C++中SkMatrix::getSkewX方法的典型用法代码示例。如果您正苦于以下问题:C++ SkMatrix::getSkewX方法的具体用法?C++ SkMatrix::getSkewX怎么用?C++ SkMatrix::getSkewX使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkMatrix
的用法示例。
在下文中一共展示了SkMatrix::getSkewX方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: refBitmapShader
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const {
SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
SkMatrix m;
m.setConcat(matrix, this->getLocalMatrix());
if (localM) {
m.preConcat(*localM);
}
// Use a rotation-invariant scale
SkPoint scale;
if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) {
// Decomposition failed, use an approximation.
scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()),
SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY()));
}
SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height());
SkISize tileSize = scaledSize.toRound();
if (tileSize.isEmpty()) {
return NULL;
}
// The actual scale, compensating for rounding.
SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(),
SkIntToScalar(tileSize.height()) / fPicture->height());
SkAutoMutexAcquire ama(fCachedBitmapShaderMutex);
if (!fCachedBitmapShader || tileScale != fCachedTileScale) {
SkBitmap bm;
if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) {
return NULL;
}
bm.eraseColor(SK_ColorTRANSPARENT);
SkCanvas canvas(bm);
canvas.scale(tileScale.width(), tileScale.height());
canvas.drawPicture(fPicture);
fCachedTileScale = tileScale;
SkMatrix shaderMatrix = this->getLocalMatrix();
shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix));
}
// Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
// Otherwise, the pointer may have been overwritten on a different thread before the object's
// ref count was incremented.
fCachedBitmapShader.get()->ref();
return fCachedBitmapShader;
}
示例2: parsePath
void GrCCPathParser::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
SkRect* devBounds45) {
const SkPoint* pts = SkPathPriv::PointData(path);
int numPts = path.countPoints();
SkASSERT(numPts + 1 <= fLocalDevPtsBuffer.count());
if (!numPts) {
devBounds->setEmpty();
devBounds45->setEmpty();
this->parsePath(path, nullptr);
return;
}
// m45 transforms path points into "45 degree" device space. A bounding box in this space gives
// the circumscribing octagon's diagonals. We could use SK_ScalarRoot2Over2, but an orthonormal
// transform is not necessary as long as the shader uses the correct inverse.
SkMatrix m45;
m45.setSinCos(1, 1);
m45.preConcat(m);
// X,Y,T are two parallel view matrices that accumulate two bounding boxes as they map points:
// device-space bounds and "45 degree" device-space bounds (| 1 -1 | * devCoords).
// | 1 1 |
Sk4f X = Sk4f(m.getScaleX(), m.getSkewY(), m45.getScaleX(), m45.getSkewY());
Sk4f Y = Sk4f(m.getSkewX(), m.getScaleY(), m45.getSkewX(), m45.getScaleY());
Sk4f T = Sk4f(m.getTranslateX(), m.getTranslateY(), m45.getTranslateX(), m45.getTranslateY());
// Map the path's points to device space and accumulate bounding boxes.
Sk4f devPt = SkNx_fma(Y, Sk4f(pts[0].y()), T);
devPt = SkNx_fma(X, Sk4f(pts[0].x()), devPt);
Sk4f topLeft = devPt;
Sk4f bottomRight = devPt;
// Store all 4 values [dev.x, dev.y, dev45.x, dev45.y]. We are only interested in the first two,
// and will overwrite [dev45.x, dev45.y] with the next point. This is why the dst buffer must
// be at least one larger than the number of points.
devPt.store(&fLocalDevPtsBuffer[0]);
for (int i = 1; i < numPts; ++i) {
devPt = SkNx_fma(Y, Sk4f(pts[i].y()), T);
devPt = SkNx_fma(X, Sk4f(pts[i].x()), devPt);
topLeft = Sk4f::Min(topLeft, devPt);
bottomRight = Sk4f::Max(bottomRight, devPt);
devPt.store(&fLocalDevPtsBuffer[i]);
}
SkPoint topLeftPts[2], bottomRightPts[2];
topLeft.store(topLeftPts);
bottomRight.store(bottomRightPts);
devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(), bottomRightPts[0].x(),
bottomRightPts[0].y());
devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), bottomRightPts[1].x(),
bottomRightPts[1].y());
this->parsePath(path, fLocalDevPtsBuffer.get());
}
示例3: setProperty
bool SkDrawMatrix::setProperty(int index, SkScriptValue& scriptValue) {
SkScalar number = scriptValue.fOperand.fScalar;
switch (index) {
case SK_PROPERTY(translate):
// SkScalar xy[2];
SkASSERT(scriptValue.fType == SkType_Array);
SkASSERT(scriptValue.fOperand.fArray->getType() == SkType_Float);
SkASSERT(scriptValue.fOperand.fArray->count() == 2);
// SkParse::FindScalars(scriptValue.fOperand.fString->c_str(), xy, 2);
fMatrix.setTranslateX((*scriptValue.fOperand.fArray)[0].fScalar);
fMatrix.setTranslateY((*scriptValue.fOperand.fArray)[1].fScalar);
return true;
case SK_PROPERTY(perspectX):
fMatrix.setPerspX(SkScalarToPersp((number)));
break;
case SK_PROPERTY(perspectY):
fMatrix.setPerspY(SkScalarToPersp((number)));
break;
case SK_PROPERTY(rotate): {
SkMatrix temp;
temp.setRotate(number, 0, 0);
fMatrix.setScaleX(temp.getScaleX());
fMatrix.setScaleY(temp.getScaleY());
fMatrix.setSkewX(temp.getSkewX());
fMatrix.setSkewY(temp.getSkewY());
}
break;
case SK_PROPERTY(scale):
fMatrix.setScaleX(number);
fMatrix.setScaleY(number);
break;
case SK_PROPERTY(scaleX):
fMatrix.setScaleX(number);
break;
case SK_PROPERTY(scaleY):
fMatrix.setScaleY(number);
break;
case SK_PROPERTY(skewX):
fMatrix.setSkewX(number);
break;
case SK_PROPERTY(skewY):
fMatrix.setSkewY(number);
break;
case SK_PROPERTY(translateX):
fMatrix.setTranslateX(number);
break;
case SK_PROPERTY(translateY):
fMatrix.setTranslateY(number);
break;
default:
SkASSERT(0);
return false;
}
fConcat = fMatrix;
return true;
}
示例4: effective_matrix_scale_sqrd
static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) {
SkPoint v1, v2;
v1.fX = mat.getScaleX();
v1.fY = mat.getSkewY();
v2.fX = mat.getSkewX();
v2.fY = mat.getScaleY();
return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd());
}
示例5: SkASSERT
GrCCPathCache::MaskTransform::MaskTransform(const SkMatrix& m, SkIVector* shift)
: fMatrix2x2{m.getScaleX(), m.getSkewX(), m.getSkewY(), m.getScaleY()} {
SkASSERT(!m.hasPerspective());
Sk2f translate = Sk2f(m.getTranslateX(), m.getTranslateY());
Sk2f transFloor;
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
// On Android framework we pre-round view matrix translates to integers for better caching.
transFloor = translate;
#else
transFloor = translate.floor();
(translate - transFloor).store(fSubpixelTranslate);
#endif
shift->set((int)transFloor[0], (int)transFloor[1]);
SkASSERT((float)shift->fX == transFloor[0]); // Make sure transFloor had integer values.
SkASSERT((float)shift->fY == transFloor[1]);
}
示例6: calculate_translation
static void calculate_translation(bool applyVM,
const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY,
const SkMatrix& currentViewMatrix, SkScalar currentX,
SkScalar currentY, SkScalar* transX, SkScalar* transY) {
if (applyVM) {
*transX = newViewMatrix.getTranslateX() +
newViewMatrix.getScaleX() * (newX - currentX) +
newViewMatrix.getSkewX() * (newY - currentY) -
currentViewMatrix.getTranslateX();
*transY = newViewMatrix.getTranslateY() +
newViewMatrix.getSkewY() * (newX - currentX) +
newViewMatrix.getScaleY() * (newY - currentY) -
currentViewMatrix.getTranslateY();
} else {
*transX = newX - currentX;
*transY = newY - currentY;
}
}
示例7: dump
void SkFlatMatrix::dump() const {
const SkMatrix* matrix = (const SkMatrix*) fMatrixData;
char pBuffer[DUMP_BUFFER_SIZE];
char* bufferPtr = pBuffer;
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"matrix: ");
SkScalar scaleX = matrix->getScaleX();
SkMatrix defaultMatrix;
defaultMatrix.reset();
if (scaleX != defaultMatrix.getScaleX())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"scaleX:%g ", SkScalarToFloat(scaleX));
SkScalar scaleY = matrix->getScaleY();
if (scaleY != defaultMatrix.getScaleY())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"scaleY:%g ", SkScalarToFloat(scaleY));
SkScalar skewX = matrix->getSkewX();
if (skewX != defaultMatrix.getSkewX())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"skewX:%g ", SkScalarToFloat(skewX));
SkScalar skewY = matrix->getSkewY();
if (skewY != defaultMatrix.getSkewY())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"skewY:%g ", SkScalarToFloat(skewY));
SkScalar translateX = matrix->getTranslateX();
if (translateX != defaultMatrix.getTranslateX())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"translateX:%g ", SkScalarToFloat(translateX));
SkScalar translateY = matrix->getTranslateY();
if (translateY != defaultMatrix.getTranslateY())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"translateY:%g ", SkScalarToFloat(translateY));
SkScalar perspX = matrix->getPerspX();
if (perspX != defaultMatrix.getPerspX())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"perspX:%g ", SkFractToFloat(perspX));
SkScalar perspY = matrix->getPerspY();
if (perspY != defaultMatrix.getPerspY())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
"perspY:%g ", SkFractToFloat(perspY));
SkDebugf("%s\n", pBuffer);
}
示例8: computeMatrices
void SkScalerContextRec::computeMatrices(PreMatrixScale preMatrixScale, SkVector* s, SkMatrix* sA,
SkMatrix* GsA, SkMatrix* G_inv, SkMatrix* A_out)
{
// A is the 'total' matrix.
SkMatrix A;
this->getSingleMatrix(&A);
// The caller may find the 'total' matrix useful when dealing directly with EM sizes.
if (A_out) {
*A_out = A;
}
// If the 'total' matrix is singular, set the 'scale' to something finite and zero the matrices.
// All underlying ports have issues with zero text size, so use the matricies to zero.
// Map the vectors [0,1], [1,0], [1,1] and [1,-1] (the EM) through the 'total' matrix.
// If the length of one of these vectors is less than 1/256 then an EM filling square will
// never affect any pixels.
SkVector diag[4] = { { A.getScaleX() , A.getSkewY() },
{ A.getSkewX(), A.getScaleY() },
{ A.getScaleX() + A.getSkewX(), A.getScaleY() + A.getSkewY() },
{ A.getScaleX() - A.getSkewX(), A.getScaleY() - A.getSkewY() }, };
if (diag[0].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero ||
diag[1].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero ||
diag[2].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero ||
diag[3].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero)
{
s->fX = SK_Scalar1;
s->fY = SK_Scalar1;
sA->setScale(0, 0);
if (GsA) {
GsA->setScale(0, 0);
}
if (G_inv) {
G_inv->reset();
}
return;
}
// GA is the matrix A with rotation removed.
SkMatrix GA;
bool skewedOrFlipped = A.getSkewX() || A.getSkewY() || A.getScaleX() < 0 || A.getScaleY() < 0;
if (skewedOrFlipped) {
// h is where A maps the horizontal baseline.
SkPoint h = SkPoint::Make(SK_Scalar1, 0);
A.mapPoints(&h, 1);
// G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
SkMatrix G;
SkComputeGivensRotation(h, &G);
GA = G;
GA.preConcat(A);
// The 'remainingRotation' is G inverse, which is fairly simple since G is 2x2 rotational.
if (G_inv) {
G_inv->setAll(
G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
-G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
}
} else {
GA = A;
if (G_inv) {
G_inv->reset();
}
}
// At this point, given GA, create s.
switch (preMatrixScale) {
case kFull_PreMatrixScale:
s->fX = SkScalarAbs(GA.get(SkMatrix::kMScaleX));
s->fY = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
break;
case kVertical_PreMatrixScale: {
SkScalar yScale = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
s->fX = yScale;
s->fY = yScale;
break;
}
case kVerticalInteger_PreMatrixScale: {
SkScalar realYScale = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
SkScalar intYScale = SkScalarRoundToScalar(realYScale);
if (intYScale == 0) {
intYScale = SK_Scalar1;
}
s->fX = intYScale;
s->fY = intYScale;
break;
}
}
// The 'remaining' matrix sA is the total matrix A without the scale.
if (!skewedOrFlipped && (
(kFull_PreMatrixScale == preMatrixScale) ||
(kVertical_PreMatrixScale == preMatrixScale && A.getScaleX() == A.getScaleY())))
{
// If GA == A and kFull_PreMatrixScale, sA is identity.
// If GA == A and kVertical_PreMatrixScale and A.scaleX == A.scaleY, sA is identity.
sA->reset();
//.........这里部分代码省略.........
示例9: switch
SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc)
: SkScalerContext_FreeType_Base(typeface, desc)
{
SkMatrix matrix;
fRec.getSingleMatrix(&matrix);
cairo_font_face_t* fontFace = static_cast<SkCairoFTTypeface*>(typeface)->getFontFace();
cairo_matrix_t fontMatrix, ctMatrix;
cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
cairo_matrix_init_scale(&ctMatrix, 1.0, 1.0);
// We need to ensure that the font options match for hinting, as generateMetrics()
// uses the fScaledFont which uses these font options
cairo_font_options_t *fontOptions = cairo_font_options_create();
FT_Int32 loadFlags = FT_LOAD_DEFAULT;
if (SkMask::kBW_Format == fRec.fMaskFormat) {
// See http://code.google.com/p/chromium/issues/detail?id=43252#c24
loadFlags = FT_LOAD_TARGET_MONO;
if (fRec.getHinting() == SkPaint::kNo_Hinting) {
cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
loadFlags = FT_LOAD_NO_HINTING;
}
} else {
switch (fRec.getHinting()) {
case SkPaint::kNo_Hinting:
loadFlags = FT_LOAD_NO_HINTING;
cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
break;
case SkPaint::kSlight_Hinting:
loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_SLIGHT);
break;
case SkPaint::kNormal_Hinting:
cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_MEDIUM);
if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags = FT_LOAD_FORCE_AUTOHINT;
}
break;
case SkPaint::kFull_Hinting:
cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL);
if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags = FT_LOAD_FORCE_AUTOHINT;
}
if (isLCD(fRec)) {
if (SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag)) {
loadFlags = FT_LOAD_TARGET_LCD_V;
} else {
loadFlags = FT_LOAD_TARGET_LCD;
}
}
break;
default:
SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
break;
}
}
fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
loadFlags |= FT_LOAD_NO_BITMAP;
}
// Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
// advances, as fontconfig and cairo do.
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
#ifdef FT_LOAD_COLOR
loadFlags |= FT_LOAD_COLOR;
#endif
fLoadGlyphFlags = loadFlags;
}
示例10: computeShapeMatrix
bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
{
// Compute a shape matrix compatible with Cairo's _compute_transform.
// Finds major/minor scales and uses them to normalize the transform.
double scaleX = m.getScaleX();
double skewX = m.getSkewX();
double skewY = m.getSkewY();
double scaleY = m.getScaleY();
double det = scaleX * scaleY - skewY * skewX;
if (!std::isfinite(det)) {
fScaleX = fRec.fTextSize * fRec.fPreScaleX;
fScaleY = fRec.fTextSize;
fHaveShape = false;
return false;
}
double major = det != 0.0 ? hypot(scaleX, skewY) : 0.0;
double minor = major != 0.0 ? fabs(det) / major : 0.0;
// Limit scales to be above 1pt.
major = SkTMax(major, 1.0);
minor = SkTMax(minor, 1.0);
// If the font is not scalable, then choose the best available size.
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
if (face && !FT_IS_SCALABLE(face)) {
double bestDist = DBL_MAX;
FT_Int bestSize = -1;
for (FT_Int i = 0; i < face->num_fixed_sizes; i++) {
// Distance is positive if strike is larger than desired size,
// or negative if smaller. If previously a found smaller strike,
// then prefer a larger strike. Otherwise, minimize distance.
double dist = face->available_sizes[i].y_ppem / 64.0 - minor;
if (bestDist < 0 ? dist >= bestDist : fabs(dist) <= bestDist) {
bestDist = dist;
bestSize = i;
}
}
if (bestSize < 0) {
fScaleX = fRec.fTextSize * fRec.fPreScaleX;
fScaleY = fRec.fTextSize;
fHaveShape = false;
return false;
}
major = face->available_sizes[bestSize].x_ppem / 64.0;
minor = face->available_sizes[bestSize].y_ppem / 64.0;
fHaveShape = true;
} else {
fHaveShape = !m.isScaleTranslate();
}
fScaleX = SkDoubleToScalar(major);
fScaleY = SkDoubleToScalar(minor);
if (fHaveShape) {
// Normalize the transform and convert to fixed-point.
double invScaleX = 65536.0 / major;
double invScaleY = 65536.0 / minor;
fShapeMatrix.xx = (FT_Fixed)(scaleX * invScaleX);
fShapeMatrix.yx = -(FT_Fixed)(skewY * invScaleX);
fShapeMatrix.xy = -(FT_Fixed)(skewX * invScaleY);
fShapeMatrix.yy = (FT_Fixed)(scaleY * invScaleY);
}
return true;
}
示例11: fLcdFilter
SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc,
cairo_font_face_t* fontFace, FcPattern* pattern)
: SkScalerContext_FreeType_Base(typeface, desc)
, fLcdFilter(FT_LCD_FILTER_NONE)
{
SkMatrix matrix;
fRec.getSingleMatrix(&matrix);
cairo_matrix_t fontMatrix, ctMatrix;
cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
cairo_matrix_init_identity(&ctMatrix);
cairo_font_options_t *fontOptions = cairo_font_options_create();
fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
computeShapeMatrix(matrix);
#ifdef CAIRO_HAS_FC_FONT
resolvePattern(pattern);
#endif
FT_Int32 loadFlags = FT_LOAD_DEFAULT;
if (SkMask::kBW_Format == fRec.fMaskFormat) {
if (fRec.getHinting() == SkPaint::kNo_Hinting) {
loadFlags |= FT_LOAD_NO_HINTING;
} else {
loadFlags = FT_LOAD_TARGET_MONO;
}
loadFlags |= FT_LOAD_MONOCHROME;
} else {
switch (fRec.getHinting()) {
case SkPaint::kNo_Hinting:
loadFlags |= FT_LOAD_NO_HINTING;
break;
case SkPaint::kSlight_Hinting:
loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
break;
case SkPaint::kNormal_Hinting:
if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags |= FT_LOAD_FORCE_AUTOHINT;
}
break;
case SkPaint::kFull_Hinting:
if (isLCD(fRec)) {
if (fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag) {
loadFlags = FT_LOAD_TARGET_LCD_V;
} else {
loadFlags = FT_LOAD_TARGET_LCD;
}
}
if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags |= FT_LOAD_FORCE_AUTOHINT;
}
break;
default:
SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
break;
}
}
// Disable autohinting to disable hinting even for "tricky" fonts.
if (!gFontHintingEnabled) {
loadFlags |= FT_LOAD_NO_AUTOHINT;
}
if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
loadFlags |= FT_LOAD_NO_BITMAP;
}
// Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
// advances, as fontconfig and cairo do.
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
}
#ifdef FT_LOAD_COLOR
loadFlags |= FT_LOAD_COLOR;
#endif
fLoadGlyphFlags = loadFlags;
}
示例12: setSave
void SkSVGPaint::setSave(SkSVGParser& parser) {
SkTDArray<SkString*> clips;
SkSVGPaint* walking = parser.fHead;
int index;
SkMatrix sum;
sum.reset();
while (walking != NULL) {
for (index = kInitial + 1; index < kTerminal; index++) {
SkString* lastAttr = (*walking)[index];
if (lastAttr->size() == 0)
continue;
if (index == kTransform) {
const char* str = lastAttr->c_str();
SkASSERT(strncmp(str, "matrix(", 7) == 0);
str += 6;
const char* strEnd = strrchr(str, ')');
SkASSERT(strEnd != NULL);
SkString mat(str, strEnd - str);
SkSVGParser::ConvertToArray(mat);
SkScalar values[6];
SkParse::FindScalars(mat.c_str() + 1, values, 6);
SkMatrix matrix;
matrix.reset();
matrix.setScaleX(values[0]);
matrix.setSkewY(values[1]);
matrix.setSkewX(values[2]);
matrix.setScaleY(values[3]);
matrix.setTranslateX(values[4]);
matrix.setTranslateY(values[5]);
sum.setConcat(matrix, sum);
continue;
}
if ( index == kClipPath)
*clips.insert(0) = lastAttr;
}
walking = walking->fNext;
}
if ((sum == parser.fLastTransform) == false) {
SkMatrix inverse;
bool success = parser.fLastTransform.invert(&inverse);
SkASSERT(success == true);
SkMatrix output;
output.setConcat(inverse, sum);
parser.fLastTransform = sum;
SkString outputStr;
outputStr.appendUnichar('[');
outputStr.appendScalar(output.getScaleX());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getSkewX());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getTranslateX());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getSkewY());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getScaleY());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getTranslateY());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getPerspX());
outputStr.appendUnichar(',');
outputStr.appendScalar(output.getPerspY());
outputStr.append(",1]");
parser._startElement("matrix");
parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size());
parser._endElement();
}
#if 0 // incomplete
if (parser.fTransformClips.size() > 0) {
// need to reset the clip when the 'g' scope is ended
parser._startElement("add");
const char* start = strchr(current->f_clipPath.c_str(), '#') + 1;
SkASSERT(start);
parser._addAttributeLen("use", start, strlen(start) - 1);
parser._endElement(); // clip
}
#endif
}
示例13: ac
SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
: SkScalerContext(desc), fFTSize(NULL) {
SkAutoMutexAcquire ac(gFTMutex);
FT_Error err;
if (gFTCount == 0) {
err = FT_Init_FreeType(&gFTLibrary);
// SkDEBUGF(("FT_Init_FreeType returned %d\n", err));
SkASSERT(err == 0);
}
++gFTCount;
// load the font file
fFaceRec = ref_ft_face(fRec.fFontID);
fFace = fFaceRec ? fFaceRec->fFace : NULL;
// compute our factors from the record
SkMatrix m;
fRec.getSingleMatrix(&m);
#ifdef DUMP_STRIKE_CREATION
SkString keyString;
SkFontHost::GetDescriptorKeyString(desc, &keyString);
printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
fRec.fHints, fRec.fMaskFormat, keyString.c_str());
#endif
// now compute our scale factors
SkScalar sx = m.getScaleX();
SkScalar sy = m.getScaleY();
if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
// sort of give up on hinting
sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
sx = sy = SkScalarAve(sx, sy);
SkScalar inv = SkScalarInvert(sx);
// flip the skew elements to go from our Y-down system to FreeType's
fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
} else {
fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
fMatrix22.xy = fMatrix22.yx = 0;
}
fScaleX = SkScalarToFixed(sx);
fScaleY = SkScalarToFixed(sy);
// compute the flags we send to Load_Glyph
{
uint32_t flags = FT_LOAD_DEFAULT;
uint32_t render_flags = FT_LOAD_TARGET_NORMAL;
// we force autohinting at the moment
switch (fRec.fHints) {
case kNo_Hints:
flags |= FT_LOAD_NO_HINTING;
break;
case kSubpixel_Hints:
flags |= FT_LOAD_FORCE_AUTOHINT;
render_flags = FT_LOAD_TARGET_LIGHT;
break;
case kNormal_Hints:
flags |= FT_LOAD_FORCE_AUTOHINT;
#ifdef ANDROID
/* Switch to light hinting (vertical only) to address some chars
that behaved poorly with NORMAL. In the future we could consider
making this choice exposed at runtime to the caller.
*/
render_flags = FT_LOAD_TARGET_LIGHT;
#endif
break;
}
if (SkMask::kBW_Format == fRec.fMaskFormat)
render_flags = FT_LOAD_TARGET_MONO;
else if (SkMask::kLCD_Format == fRec.fMaskFormat)
render_flags = FT_LOAD_TARGET_LCD;
fLoadGlyphFlags = flags | render_flags;
}
// now create the FT_Size
{
FT_Error err;
err = FT_New_Size(fFace, &fFTSize);
if (err != 0) {
//.........这里部分代码省略.........
示例14: mustRegenerate
bool GrAtlasTextBlob::mustRegenerate(const SkPaint& paint,
GrColor color, const SkMaskFilter::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// If we have LCD text then our canonical color will be set to transparent, in this case we have
// to regenerate the blob on any color change
// We use the grPaint to get any color filter effects
if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
fPaintColor != color) {
return true;
}
if (fInitialViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
return true;
}
if (fInitialViewMatrix.hasPerspective() && !fInitialViewMatrix.cheapEqualTo(viewMatrix)) {
return true;
}
// We only cache one masked version
if (fKey.fHasBlur &&
(fBlurRec.fSigma != blurRec.fSigma ||
fBlurRec.fStyle != blurRec.fStyle ||
fBlurRec.fQuality != blurRec.fQuality)) {
return true;
}
// Similarly, we only cache one version for each style
if (fKey.fStyle != SkPaint::kFill_Style &&
(fStrokeInfo.fFrameWidth != paint.getStrokeWidth() ||
fStrokeInfo.fMiterLimit != paint.getStrokeMiter() ||
fStrokeInfo.fJoin != paint.getStrokeJoin())) {
return true;
}
// Mixed blobs must be regenerated. We could probably figure out a way to do integer scrolls
// for mixed blobs if this becomes an issue.
if (this->hasBitmap() && this->hasDistanceField()) {
// Identical viewmatrices and we can reuse in all cases
if (fInitialViewMatrix.cheapEqualTo(viewMatrix) && x == fInitialX && y == fInitialY) {
return false;
}
return true;
}
if (this->hasBitmap()) {
if (fInitialViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
fInitialViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
fInitialViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
fInitialViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
return true;
}
// We can update the positions in the cachedtextblobs without regenerating the whole blob,
// but only for integer translations.
// This cool bit of math will determine the necessary translation to apply to the already
// generated vertex coordinates to move them to the correct position
SkScalar transX = viewMatrix.getTranslateX() +
viewMatrix.getScaleX() * (x - fInitialX) +
viewMatrix.getSkewX() * (y - fInitialY) -
fInitialViewMatrix.getTranslateX();
SkScalar transY = viewMatrix.getTranslateY() +
viewMatrix.getSkewY() * (x - fInitialX) +
viewMatrix.getScaleY() * (y - fInitialY) -
fInitialViewMatrix.getTranslateY();
if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) {
return true;
}
} else if (this->hasDistanceField()) {
// A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
// distance field being generated, so we have to regenerate in those cases
SkScalar newMaxScale = viewMatrix.getMaxScale();
SkScalar oldMaxScale = fInitialViewMatrix.getMaxScale();
SkScalar scaleAdjust = newMaxScale / oldMaxScale;
if (scaleAdjust < fMaxMinScale || scaleAdjust > fMinMaxScale) {
return true;
}
}
// It is possible that a blob has neither distanceField nor bitmaptext. This is in the case
// when all of the runs inside the blob are drawn as paths. In this case, we always regenerate
// the blob anyways at flush time, so no need to regenerate explicitly
return false;
}
示例15: ac
SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
: SkScalerContext(desc) {
SkAutoMutexAcquire ac(gFTMutex);
if (gFTCount == 0) {
if (!InitFreetype()) {
sk_throw();
}
}
++gFTCount;
// load the font file
fFTSize = NULL;
fFace = NULL;
fFaceRec = ref_ft_face(fRec.fFontID);
if (NULL == fFaceRec) {
return;
}
fFace = fFaceRec->fFace;
// compute our factors from the record
SkMatrix m;
fRec.getSingleMatrix(&m);
#ifdef DUMP_STRIKE_CREATION
SkString keyString;
SkFontHost::GetDescriptorKeyString(desc, &keyString);
printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
fRec.getHinting(), fRec.fMaskFormat, keyString.c_str());
#endif
// now compute our scale factors
SkScalar sx = m.getScaleX();
SkScalar sy = m.getScaleY();
if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
// sort of give up on hinting
sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
sx = sy = SkScalarAve(sx, sy);
SkScalar inv = SkScalarInvert(sx);
// flip the skew elements to go from our Y-down system to FreeType's
fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
} else {
fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
fMatrix22.xy = fMatrix22.yx = 0;
}
fScaleX = SkScalarToFixed(sx);
fScaleY = SkScalarToFixed(sy);
// compute the flags we send to Load_Glyph
{
FT_Int32 loadFlags = FT_LOAD_DEFAULT;
if (SkMask::kBW_Format == fRec.fMaskFormat) {
// See http://code.google.com/p/chromium/issues/detail?id=43252#c24
loadFlags = FT_LOAD_TARGET_MONO;
if (fRec.getHinting() == SkPaint::kNo_Hinting)
loadFlags = FT_LOAD_NO_HINTING;
} else {
switch (fRec.getHinting()) {
case SkPaint::kNo_Hinting:
loadFlags = FT_LOAD_NO_HINTING;
break;
case SkPaint::kSlight_Hinting:
loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
break;
case SkPaint::kNormal_Hinting:
if (fRec.fFlags & SkScalerContext::kAutohinting_Flag)
loadFlags = FT_LOAD_FORCE_AUTOHINT;
else
loadFlags = FT_LOAD_NO_AUTOHINT;
break;
case SkPaint::kFull_Hinting:
if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) {
loadFlags = FT_LOAD_FORCE_AUTOHINT;
break;
}
loadFlags = FT_LOAD_TARGET_NORMAL;
if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat ||
SkMask::kLCD16_Format == fRec.fMaskFormat) {
loadFlags = FT_LOAD_TARGET_LCD;
} else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat) {
loadFlags = FT_LOAD_TARGET_LCD_V;
}
break;
default:
SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
break;
//.........这里部分代码省略.........