| Index: src/ports/SkFontHost_mac.cpp
|
| diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
|
| index 8db318b3ff5238798e91740f8bd616aeba2f59a7..772fe74f487a940d7adc74dd9c6a796863274b33 100644
|
| --- a/src/ports/SkFontHost_mac.cpp
|
| +++ b/src/ports/SkFontHost_mac.cpp
|
| @@ -684,9 +684,6 @@ private:
|
| SkMatrix fFUnitMatrix;
|
|
|
| Offscreen fOffscreen;
|
| - AutoCFRelease<CTFontRef> fCTFont;
|
| - CGAffineTransform fTransform;
|
| - CGAffineTransform fInvTransform;
|
|
|
| /** Unrotated variant of fCTFont.
|
| *
|
| @@ -698,8 +695,19 @@ private:
|
| * This makes kCTFontDefaultOrientation dangerous, because the metrics from
|
| * kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation.
|
| * With kCTFontVerticalOrientation the advances must be unrotated.
|
| + *
|
| + * Sometimes, creating a copy of a CTFont with the same size but different trasform will select
|
| + * different underlying font data. As a result, avoid ever creating more than one CTFont per
|
| + * SkScalerContext to ensure that only one CTFont is used.
|
| + *
|
| + * As a result of the above (and other constraints) this font contains the size, but not the
|
| + * transform. The transform must always be applied separately.
|
| */
|
| - AutoCFRelease<CTFontRef> fCTUnrotatedFont;
|
| + AutoCFRelease<CTFontRef> fCTFont;
|
| +
|
| + /** The transform without the font size. */
|
| + CGAffineTransform fTransform;
|
| + CGAffineTransform fInvTransform;
|
|
|
| AutoCFRelease<CGFontRef> fCGFont;
|
| SkAutoTMalloc<GlyphRect> fFBoundingBoxes;
|
| @@ -764,10 +772,8 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
|
| // The transform contains everything except the requested text size.
|
| // Some properties, like 'trak', are based on the text size (before applying the matrix).
|
| CGFloat textSize = ScalarToCG(scale.y());
|
| -
|
| - fCTFont.reset(ctfont_create_exact_copy(ctFont, textSize, &fTransform));
|
| + fCTFont.reset(ctfont_create_exact_copy(ctFont, textSize, nullptr));
|
| fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, nullptr));
|
| - fCTUnrotatedFont.reset(ctfont_create_exact_copy(ctFont, textSize, nullptr));
|
|
|
| // The fUnitMatrix includes the text size (and em) as it is used to scale the raw font data.
|
| SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont)));
|
| @@ -914,7 +920,7 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
|
| // So always make the font transform identity and place the transform on the context.
|
| point = CGPointApplyAffineTransform(point, context.fInvTransform);
|
|
|
| - ctFontDrawGlyphs(context.fCTUnrotatedFont, &glyphID, &point, 1, fCG);
|
| + ctFontDrawGlyphs(context.fCTFont, &glyphID, &point, 1, fCG);
|
|
|
| SkASSERT(rowBytesPtr);
|
| *rowBytesPtr = rowBytes;
|
| @@ -926,16 +932,17 @@ void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
|
| // Lion and Leopard return cgVertOffset in CG units (pixels, y up).
|
| CGSize cgVertOffset;
|
| CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1);
|
| -
|
| - SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
|
| if (isSnowLeopard()) {
|
| + SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
|
| // From FUnits (em space, y up) to SkGlyph units (pixels, y down).
|
| fFUnitMatrix.mapPoints(&skVertOffset, 1);
|
| - } else {
|
| - // From CG units (pixels, y up) to SkGlyph units (pixels, y down).
|
| - skVertOffset.fY = -skVertOffset.fY;
|
| + *offset = skVertOffset;
|
| + return;
|
| }
|
| -
|
| + cgVertOffset = CGSizeApplyAffineTransform(cgVertOffset, fTransform);
|
| + SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
|
| + // From CG units (pixels, y up) to SkGlyph units (pixels, y down).
|
| + skVertOffset.fY = -skVertOffset.fY;
|
| *offset = skVertOffset;
|
| }
|
|
|
| @@ -1024,16 +1031,16 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
|
| // The following block produces cgAdvance in CG units (pixels, y up).
|
| CGSize cgAdvance;
|
| if (fVertical) {
|
| - CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontVerticalOrientation,
|
| + CTFontGetAdvancesForGlyphs(fCTFont, kCTFontVerticalOrientation,
|
| &cgGlyph, &cgAdvance, 1);
|
| // Vertical advances are returned as widths instead of heights.
|
| SkTSwap(cgAdvance.height, cgAdvance.width);
|
| cgAdvance.height = -cgAdvance.height;
|
| } else {
|
| - CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontHorizontalOrientation,
|
| + CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation,
|
| &cgGlyph, &cgAdvance, 1);
|
| }
|
| - cgAdvance = CGSizeApplyAffineTransform(cgAdvance, CTFontGetMatrix(fCTFont));
|
| + cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
|
| glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width);
|
| glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height);
|
|
|
| @@ -1078,6 +1085,7 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
|
| CGRect cgBounds;
|
| CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation,
|
| &cgGlyph, &cgBounds, 1);
|
| + cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
|
|
|
| // BUG?
|
| // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
|
| @@ -1336,10 +1344,10 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
|
| void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) {
|
| AUTO_CG_LOCK();
|
|
|
| - CTFontRef font = fCTFont;
|
| SkScalar scaleX = SK_Scalar1;
|
| SkScalar scaleY = SK_Scalar1;
|
|
|
| + CGAffineTransform xform = fTransform;
|
| /*
|
| * For subpixel positioning, we want to return an unhinted outline, so it
|
| * can be positioned nicely at fractional offsets. However, we special-case
|
| @@ -1367,12 +1375,12 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) {
|
| break;
|
| }
|
|
|
| - CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY);
|
| - font = ctfont_create_exact_copy(fCTFont, 1, &xform);
|
| + CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY)));
|
| + xform = CGAffineTransformConcat(fTransform, scale);
|
| }
|
|
|
| CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID();
|
| - AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, nullptr));
|
| + AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont, cgGlyph, &xform));
|
|
|
| path->reset();
|
| if (cgPath != nullptr) {
|
| @@ -1383,8 +1391,6 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) {
|
| SkMatrix m;
|
| m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
|
| path->transform(m);
|
| - // balance the call to ctfont_create_exact_copy
|
| - CFSafeRelease(font);
|
| }
|
| if (fVertical) {
|
| SkPoint offset;
|
|
|