From 7cbeaae8bb42c386145cd020f714f0eac8021dc2 Mon Sep 17 00:00:00 2001 From: bungeman Date: Tue, 22 Sep 2015 09:54:56 -0700 Subject: Avoid CTFontCreateCopyWithAttributes. It appears that CTFontCreateCopyWithAttributes and CTFontCreateCopyWithSymbolicTraits share similar issues with the default font on OSX10.10. CTFontCreateWithFontDescriptor cannot be used as it will not work with webfonts. Since this is all low-level use, create the CTFonts from the underlying CGFonts directly. BUG=chromium:524646 Committed: https://skia.googlesource.com/skia/+/d3296717b9d0930237be3502b82ab94d0b4d177f Review URL: https://codereview.chromium.org/1344213004 --- src/ports/SkFontHost_mac.cpp | 92 ++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 7d90d84695..c10d830715 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -714,6 +714,65 @@ private: typedef SkScalerContext INHERITED; }; +// CTFontCreateCopyWithAttributes or CTFontCreateCopyWithSymbolicTraits cannot be used on 10.10 +// as they appear to be buggy with respect to the default font. It is not possible to use +// descriptors with CTFontCreateWithFontDescriptor, since that does not work with non-system +// fonts. As a result, create the strike specific CTFonts from the underlying CGFont. +static CTFontRef ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize, + const CGAffineTransform* transform, bool setVertical) +{ + AutoCFRelease baseExtraDescriptor; + AutoCFRelease baseCGFont(CTFontCopyGraphicsFont(baseFont, &baseExtraDescriptor)); + + // Make a mutable copy of baseExtraDescriptor attributes. + AutoCFRelease newAttributes([](CTFontDescriptorRef descriptor) -> + CFMutableDictionaryRef { + if (nullptr == descriptor) { + return CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + AutoCFRelease attributes(CTFontDescriptorCopyAttributes(descriptor)); + return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, attributes); + }(baseExtraDescriptor)); + + // Copy all of the attributes out of the CTFont. + AutoCFRelease baseDescriptor(CTFontCopyFontDescriptor(baseFont)); + AutoCFRelease baseAttributes(CTFontDescriptorCopyAttributes(baseDescriptor)); + CFDictionaryApplyFunction(baseAttributes, [](CFTypeRef key, CFTypeRef value, void* context) { + CFMutableDictionaryRef self = static_cast(context); + CFDictionarySetValue(self, key, value); + }, newAttributes.get()); + + // Set the text size in attributes. + AutoCFRelease cfTextSize( + CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &textSize)); + CFDictionarySetValue(newAttributes, kCTFontSizeAttribute, cfTextSize); + + // Set the transform in attributes. + if (nullptr == transform) { + CFDictionaryRemoveValue(newAttributes, kCTFontMatrixAttribute); + } else { + AutoCFRelease cfMatrixData(CFDataCreate( + kCFAllocatorDefault, reinterpret_cast(transform), sizeof(*transform))); + CFDictionarySetValue(newAttributes, kCTFontMatrixAttribute, cfMatrixData); + } + + // Set vertical orientation to attributes if requested. + if (setVertical) { + CTFontOrientation ctOrientation = kCTFontVerticalOrientation; + AutoCFRelease cfVertical( + CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); + CFDictionarySetValue(newAttributes, kCTFontOrientationAttribute, cfVertical); + } + + // Create the new CTFont from the baseCGFont. + AutoCFRelease newDescriptor( + CTFontDescriptorCreateWithAttributes(newAttributes)); + return CTFontCreateWithGraphicsFont(baseCGFont, textSize, transform, newDescriptor); + +} + SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, const SkDescriptor* desc) : INHERITED(typeface, desc) @@ -740,30 +799,13 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, fTransform = MatrixToCGAffineTransform(skTransform); fInvTransform = CGAffineTransformInvert(fTransform); - AutoCFRelease ctFontDesc; - if (fVertical) { - // Setting the vertical orientation here is required for vertical metrics on some versions. - AutoCFRelease cfAttributes(CFDictionaryCreateMutable( - kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - if (cfAttributes) { - CTFontOrientation ctOrientation = kCTFontVerticalOrientation; - AutoCFRelease cfVertical(CFNumberCreate( - kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); - CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVertical); - ctFontDesc.reset(CTFontDescriptorCreateWithAttributes(cfAttributes)); - } - } - // 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(CTFontCreateCopyWithAttributes(ctFont, textSize, &fTransform, ctFontDesc)); + fCTFont.reset(ctfont_create_exact_copy(ctFont, textSize, &fTransform, fVertical)); fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, nullptr)); - fCTUnrotatedFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, - &CGAffineTransformIdentity, nullptr)); + fCTUnrotatedFont.reset(ctfont_create_exact_copy(ctFont, textSize, nullptr, false)); // The fUnitMatrix includes the text size (and em) as it is used to scale the raw font data. SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont))); @@ -1345,7 +1387,7 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { * The way we remove hinting is to scale the font by some value (4) in that * direction, ask for the path, and then scale the path back down. */ - if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { + if (fDoSubPosition) { SkMatrix m; fRec.getSingleMatrix(&m); @@ -1364,8 +1406,7 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { } CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY); - // need to release font when we're done - font = CTFontCreateCopyWithAttributes(fCTFont, 1, &xform, nullptr); + font = ctfont_create_exact_copy(fCTFont, 1, &xform, false); } CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(); @@ -1380,7 +1421,7 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { SkMatrix m; m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); path->transform(m); - // balance the call to CTFontCreateCopyWithAttributes + // balance the call to ctfont_create_exact_copy CFSafeRelease(font); } if (fVertical) { @@ -1561,8 +1602,9 @@ SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( AUTO_CG_LOCK(); CTFontRef originalCTFont = fFontRef.get(); - AutoCFRelease ctFont(CTFontCreateCopyWithAttributes( - originalCTFont, CTFontGetUnitsPerEm(originalCTFont), nullptr, nullptr)); + AutoCFRelease ctFont(ctfont_create_exact_copy( + originalCTFont, CTFontGetUnitsPerEm(originalCTFont), nullptr, false)); + SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; { -- cgit v1.2.3