Index: src/ports/SkFontHost_mac.cpp |
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp |
index 842c5e6b71747fa40ecff7e92fbcc663f56b8caa..0440639336edc79d4246f715b6b15ffbbb7bce54 100644 |
--- a/src/ports/SkFontHost_mac.cpp |
+++ b/src/ports/SkFontHost_mac.cpp |
@@ -534,32 +534,57 @@ private: |
typedef SkTypeface INHERITED; |
}; |
-/** Creates a typeface without searching the cache. Takes ownership of the CTFontRef. */ |
-static SkTypeface* NewFromFontRef(CTFontRef fontRef, CFTypeRef resourceRef, bool isLocalStream) { |
- SkASSERT(fontRef); |
+static bool find_by_CTFontRef(SkTypeface* cached, void* context) { |
+ CTFontRef self = (CTFontRef)context; |
+ CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; |
- AutoCFRelease<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(fontRef)); |
- SkFontStyle style = fontstyle_from_descriptor(desc); |
+ return CFEqual(self, other); |
+} |
+ |
+/** Creates a typeface, searching the cache if isLocalStream is false. |
+ * Takes ownership of the CTFontRef and CFTypeRef. |
+ */ |
+static SkTypeface* create_from_CTFontRef(CTFontRef f, CFTypeRef r, bool isLocalStream) { |
+ SkASSERT(f); |
+ AutoCFRelease<CTFontRef> font(f); |
+ AutoCFRelease<CFTypeRef> resource(r); |
+ |
+ if (!isLocalStream) { |
+ SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)font.get()); |
+ if (face) { |
+ return face; |
+ } |
+ } |
- CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(fontRef); |
+ AutoCFRelease<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font)); |
+ SkFontStyle style = fontstyle_from_descriptor(desc); |
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); |
bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait); |
- return new SkTypeface_Mac(fontRef, resourceRef, style, isFixedPitch, isLocalStream); |
+ |
+ SkTypeface* face = new SkTypeface_Mac(font.release(), resource.release(), |
+ style, isFixedPitch, isLocalStream); |
+ if (!isLocalStream) { |
+ SkTypefaceCache::Add(face); |
+ } |
+ return face; |
} |
-static bool find_by_CTFontRef(SkTypeface* cached, void* context) { |
- CTFontRef self = (CTFontRef)context; |
- CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; |
+/** Creates a typeface from a descriptor, searching the cache. */ |
+static SkTypeface* create_from_desc(CTFontDescriptorRef desc) { |
+ AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); |
+ if (!ctFont) { |
+ return nullptr; |
+ } |
- return CFEqual(self, other); |
+ return create_from_CTFontRef(ctFont.release(), nullptr, false); |
} |
-/** Creates a typeface from a name, searching the cache. */ |
-static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theStyle) { |
+static CTFontDescriptorRef create_descriptor(const char familyName[], const SkFontStyle& style) { |
CTFontSymbolicTraits ctFontTraits = 0; |
- if (theStyle.weight() >= SkFontStyle::kBold_Weight) { |
+ if (style.weight() >= SkFontStyle::kBold_Weight) { |
ctFontTraits |= kCTFontBoldTrait; |
} |
- if (theStyle.slant() != SkFontStyle::kUpright_Slant) { |
+ if (style.slant() != SkFontStyle::kUpright_Slant) { |
ctFontTraits |= kCTFontItalicTrait; |
} |
@@ -590,24 +615,16 @@ static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theSt |
CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); |
CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); |
- AutoCFRelease<CTFontDescriptorRef> ctFontDesc( |
- CTFontDescriptorCreateWithAttributes(cfAttributes)); |
- if (!ctFontDesc) { |
- return nullptr; |
- } |
+ return CTFontDescriptorCreateWithAttributes(cfAttributes); |
+} |
- AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(ctFontDesc, 0, nullptr)); |
- if (!ctFont) { |
+/** Creates a typeface from a name, searching the cache. */ |
+static SkTypeface* create_from_name(const char familyName[], const SkFontStyle& style) { |
+ AutoCFRelease<CTFontDescriptorRef> desc(create_descriptor(familyName, style)); |
+ if (!desc) { |
return nullptr; |
} |
- |
- SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)ctFont.get()); |
- if (face) { |
- return face; |
- } |
- face = NewFromFontRef(ctFont.release(), nullptr, false); |
- SkTypefaceCache::Add(face); |
- return face; |
+ return create_from_desc(desc); |
} |
SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); |
@@ -617,7 +634,7 @@ static SkTypeface* GetDefaultFace() { |
static SkTypeface* gDefaultFace; |
if (nullptr == gDefaultFace) { |
- gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); |
+ gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()); |
} |
return gDefaultFace; |
} |
@@ -634,17 +651,11 @@ CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { |
* not found, returns a new entry (after adding it to the cache). |
*/ |
SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef, CFTypeRef resourceRef) { |
- SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)fontRef); |
- if (face) { |
- return face; |
- } |
CFRetain(fontRef); |
if (resourceRef) { |
CFRetain(resourceRef); |
} |
- face = NewFromFontRef(fontRef, resourceRef, false); |
- SkTypefaceCache::Add(face); |
- return face; |
+ return create_from_CTFontRef(fontRef, resourceRef, false); |
} |
static const char* map_css_names(const char* name) { |
@@ -1502,7 +1513,7 @@ static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) { |
return nullptr; |
} |
CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr); |
- return ct ? NewFromFontRef(ct, nullptr, true) : nullptr; |
+ return ct ? create_from_CTFontRef(ct, nullptr, true) : nullptr; |
} |
// Web fonts added to the the CTFont registry do not return their character set. |
@@ -2190,22 +2201,6 @@ static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) { |
sqr((a.slant() != b.slant()) * 900); |
} |
-static SkTypeface* createFromDesc(CTFontDescriptorRef desc) { |
- AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); |
- if (!ctFont) { |
- return nullptr; |
- } |
- |
- SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)ctFont.get()); |
- if (face) { |
- return face; |
- } |
- |
- face = NewFromFontRef(ctFont.release(), nullptr, false); |
- SkTypefaceCache::Add(face); |
- return face; |
-} |
- |
class SkFontStyleSet_Mac : public SkFontStyleSet { |
public: |
SkFontStyleSet_Mac(CTFontDescriptorRef desc) |
@@ -2242,14 +2237,14 @@ public: |
SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray)); |
CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); |
- return createFromDesc(desc); |
+ return create_from_desc(desc); |
} |
SkTypeface* matchStyle(const SkFontStyle& pattern) override { |
if (0 == fCount) { |
return nullptr; |
} |
- return createFromDesc(findMatchingDesc(pattern)); |
+ return create_from_desc(findMatchingDesc(pattern)); |
} |
private: |
@@ -2338,10 +2333,26 @@ protected: |
return sset->matchStyle(fontStyle); |
} |
- virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, |
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], |
+ const SkFontStyle& style, |
const char* bcp47[], int bcp47Count, |
SkUnichar character) const override { |
- return nullptr; |
+ AutoCFRelease<CTFontDescriptorRef> desc(create_descriptor(familyName, style)); |
+ AutoCFRelease<CTFontRef> currentFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); |
+ |
+ // kCFStringEncodingUTF32 is BE unless there is a BOM. |
+ // Since there is no machine endian option, explicitly state machine endian. |
+#ifdef SK_CPU_LENDIAN |
+ constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE; |
+#else |
+ constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE; |
+#endif |
+ AutoCFRelease<CFStringRef> string(CFStringCreateWithBytes( |
+ kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character), |
+ encoding, false)); |
+ CFRange range = CFRangeMake(0, CFStringGetLength(string)); // in UniChar units. |
+ AutoCFRelease<CTFontRef> fallbackFont(CTFontCreateForString(currentFont, string, range)); |
+ return create_from_CTFontRef(fallbackFont.release(), nullptr, false); |
} |
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, |
@@ -2497,11 +2508,11 @@ protected: |
cgVariant.reset(cg.release()); |
} |
- CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr); |
+ AutoCFRelease<CTFontRef> ct(CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr)); |
if (!ct) { |
return nullptr; |
} |
- return NewFromFontRef(ct, cg.release(), true); |
+ return create_from_CTFontRef(ct.release(), cg.release(), true); |
} |
static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) { |
@@ -2580,11 +2591,11 @@ protected: |
cgVariant.reset(cg.release()); |
} |
- CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr); |
+ AutoCFRelease<CTFontRef> ct(CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr)); |
if (!ct) { |
return nullptr; |
} |
- return NewFromFontRef(ct, cg.release(), true); |
+ return create_from_CTFontRef(ct.release(), cg.release(), true); |
} |
SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { |
@@ -2604,7 +2615,7 @@ protected: |
familyName = FONT_DEFAULT_NAME; |
} |
- SkTypeface* face = NewFromName(familyName, style); |
+ SkTypeface* face = create_from_name(familyName, style); |
if (face) { |
return face; |
} |