aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bungeman <bungeman@google.com>2016-08-24 08:29:50 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-24 08:29:50 -0700
commitbea9748449e9d0ab6e2e17fe206931afd81613e5 (patch)
tree5a98a040c24126288fb1bac226cdafa4cdd1bb49 /src
parent95243ebb68cae9ff4821ea57b9a32a194f2a87cf (diff)
Add simple font fallback on Mac.
Implement SkFontMgr_Mac::onMatchFamilyStyleCharacter. This is a simple implementation which provides basic fallback. This also renames and refactors several static functions to reduce code duplication. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2268663002 Review-Url: https://codereview.chromium.org/2268663002
Diffstat (limited to 'src')
-rw-r--r--src/ports/SkFontHost_mac.cpp139
1 files changed, 75 insertions, 64 deletions
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 93255df920..d3e7ab0a06 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) {
@@ -1508,7 +1519,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.
@@ -2196,22 +2207,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)
@@ -2248,14 +2243,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:
@@ -2344,10 +2339,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,
@@ -2503,11 +2514,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) {
@@ -2586,11 +2597,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 {
@@ -2610,7 +2621,7 @@ protected:
familyName = FONT_DEFAULT_NAME;
}
- SkTypeface* face = NewFromName(familyName, style);
+ SkTypeface* face = create_from_name(familyName, style);
if (face) {
return face;
}