aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bungeman <bungeman@google.com>2015-10-29 09:30:32 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-29 09:30:32 -0700
commitef27ce3730d4032515e27e5aa7b31b2088969237 (patch)
tree6eb091acf6db202526caffede91bb2eaa9886009
parent129319ff55f4be826419ffa04e772e21c6b12400 (diff)
Use only one CGFont/CTFont per scaler context on Mac.
The unrotated CTFont was introduced to fix color emoji scaling. Use only the unrotated CTFont and apply the rotations manually. This allows removal of one CTFont and allows us to apply (correctly) the transformation CoreText would otherwise need to apply (which it appears to do inconsistently). Review URL: https://codereview.chromium.org/1360663002
-rw-r--r--src/ports/SkFontHost_mac.cpp52
1 files changed, 29 insertions, 23 deletions
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 8db318b3ff..772fe74f48 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;