Index: src/ports/SkFontHost_mac.cpp |
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp |
index 5eaf7df6036b281fe08560d07baeef9e418fa7fe..b42f348c9b92c9cafc502c212948fa8c1c958811 100755 |
--- a/src/ports/SkFontHost_mac.cpp |
+++ b/src/ports/SkFontHost_mac.cpp |
@@ -466,6 +466,7 @@ public: |
protected: |
int onGetUPEM() const override; |
SkStreamAsset* onOpenStream(int* ttcIndex) const override; |
+ SkFontData* onCreateFontData() const override; |
void onGetFamilyName(SkString* familyName) const override; |
SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; |
int onGetTableTags(SkFontTableTag tags[]) const override; |
@@ -1764,6 +1765,102 @@ SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { |
return stream; |
} |
+#include <limits> |
+ |
+struct Context { |
+ SkFontData::Axis* axes; |
+ int index; |
+ CFArrayRef ctAxes; |
+}; |
+static void accumulateAxes(CFTypeRef key, CFTypeRef value, void* context) { |
+ Context* c = static_cast<Context*>(context); |
+ |
+ // The key is supposed to be a CFNumber 'FourCharCode'. |
+ // However, if the font was originally selected by style, the key is a CFString with a name. |
+ // See http://lists.apple.com/archives/coretext-dev/2012/Aug/msg00006.html . |
+ // This issue observed in 10.10.3. |
+ // So if the key is a CFString convert it into CFNumber by going throught the axis information. |
+ // Amusingly, if a CFString is specified as the key on the descriptor on a request, |
+ // an uncaught exception is thrown (normally causing a crash). |
+ SkFourByteTag tag = 0; |
+ if (CFGetTypeID(key) == CFStringGetTypeID()) { |
+ CFStringRef keyString = static_cast<CFStringRef>(key); |
+ for (CFIndex i = 0; i < CFArrayGetCount(c->ctAxes); ++i) { |
+ CFTypeRef variations = CFArrayGetValueAtIndex(c->ctAxes, i); |
+ if (CFGetTypeID(variations) != CFDictionaryGetTypeID()) { |
+ continue; |
+ } |
+ |
+ CFDictionaryRef variationsDict = static_cast<CFDictionaryRef>(variations); |
+ CFTypeRef axisName; |
+ if (!CFDictionaryGetValueIfPresent(variationsDict, kCTFontVariationAxisNameKey, &axisName)) { |
+ continue; |
+ } |
+ if (CFGetTypeID(axisName) != CFStringGetTypeID()) { |
+ continue; |
+ } |
+ CFStringRef axisNameString = static_cast<CFStringRef>(axisName); |
+ if (CFStringCompare(keyString, axisNameString, 0) == kCFCompareEqualTo) { |
+ CFTypeRef axisIdentifier; |
+ if (!CFDictionaryGetValueIfPresent(variationsDict, kCTFontVariationAxisIdentifierKey, &axisIdentifier)) { |
+ continue; |
+ } |
+ if (CFGetTypeID(axisIdentifier) != CFNumberGetTypeID()) { |
+ continue; |
+ } |
+ CFNumberRef axisIdentifierNumber = static_cast<CFNumberRef>(axisIdentifier); |
+ int64_t axisIdentifier64; |
+ if (CFNumberGetValue(axisIdentifierNumber, CFNumberType::kCFNumberSInt64Type, &axisIdentifier64) |
+ && 0 <= axisIdentifier64 && axisIdentifier64 <= std::numeric_limits<uint32_t>::max()) |
+ { |
+ tag = axisIdentifier64; |
+ break; |
+ } |
+ } |
+ } |
+ } else if (CFGetTypeID(key) == CFNumberGetTypeID()) { |
+ CFNumberRef axisIdentifierNumber = static_cast<CFNumberRef>(key); |
+ int64_t axisIdentifier64; |
+ if (CFNumberGetValue(axisIdentifierNumber, CFNumberType::kCFNumberSInt64Type, &axisIdentifier64) |
+ && 0 <= axisIdentifier64 && axisIdentifier64 <= std::numeric_limits<uint32_t>::max()) |
+ { |
+ tag = axisIdentifier64; |
+ } |
+ } |
+ |
+ SkFixed valueFixed = SK_Fixed1; // should this be SK_FixedNaN? |
+ if (CFGetTypeID(value) == CFNumberGetTypeID()) { |
+ CFNumberRef valueNumber = static_cast<CFNumberRef>(value); |
+ double valueDouble; |
+ if (CFNumberGetValue(valueNumber, CFNumberType::kCFNumberDoubleType, &valueDouble) |
+ && SkFixedToDouble(SK_FixedMin) <= valueDouble && valueDouble <= SkFixedToDouble(SK_FixedMax)) // better check? |
+ { |
+ valueFixed = SkDoubleToFixed(valueDouble); |
+ } |
+ } |
+ c->axes[c->index].fTag = tag; |
+ c->axes[c->index].fValue = valueFixed; |
+ ++c->index; |
+} |
+SkFontData* SkTypeface_Mac::onCreateFontData() const { |
+ int index; |
+ SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index)); |
+ |
+ AutoCFRelease<CFDictionaryRef> variations(CTFontCopyVariation(fFontRef)); |
+ // If a font has no variations CTFontCopyVariation returns NULL instead of an empty dict. |
+ if (variations.get()) { |
+ CFIndex variationCount = CFDictionaryGetCount(variations); |
+ SkAutoSTMalloc<4, SkFontData::Axis> axes(variationCount); |
+ AutoCFRelease<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef)); |
+ Context c = { axes.get(), 0, ctAxes.get() }; |
+ CFDictionaryApplyFunction(variations, accumulateAxes, &c); |
+ axes[0].fValue = 4 * SK_Fixed1; |
bungeman-skia
2015/04/23 21:16:34
This is a test to see what happens when a variatio
|
+ return new SkFontData(stream.detach(), index, variationCount, axes.get()); |
+ } else { |
+ return new SkFontData(stream.detach(), index, 0, NULL); |
+ } |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////////////////// |
@@ -2267,6 +2364,49 @@ protected: |
return create_from_dataProvider(pr); |
} |
+ SkTypeface* onCreateFromFontData(SkFontData* fontData) const override { |
+ AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(fontData->transferStream())); |
+ if (NULL == provider) { |
+ return NULL; |
+ } |
+ AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); |
+ if (NULL == cg) { |
+ return NULL; |
+ } |
+ SkAutoSTMalloc<4, CFTypeRef> keys(fontData->getAxisCount()); |
+ SkAutoSTMalloc<4, CFTypeRef> values(fontData->getAxisCount()); |
+ |
+ for (int i = 0; i < fontData->getAxisCount(); ++i) { |
+ int64_t key = fontData->getAxis()[i].fTag; |
+ keys[i] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &key); |
+ |
+ double value = SkFixedToDouble(fontData->getAxis()[i].fValue); |
+ values[i] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value); |
+ } |
+ AutoCFRelease<CFDictionaryRef> variations(CFDictionaryCreate(kCFAllocatorDefault, keys.get(), values.get(), fontData->getAxisCount(), |
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); |
+ CFDictionaryRef variationLValue = variations.get(); |
+ AutoCFRelease<CFDictionaryRef> attributes(CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontVariationAttribute, (const void**)&variationLValue, 1, |
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); |
+ AutoCFRelease<CTFontDescriptorRef> descriptor(CTFontDescriptorCreateWithAttributes(attributes)); |
+ //AutoCFRelease<CGFontRef> cgWithAxes(CGFontCreateCopyWithVariations(cg, variations)); |
+ CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, descriptor); |
bungeman-skia
2015/04/23 21:16:34
So this starts the buggy. This will create a CTFon
|
+ if (!ct) { |
+ return NULL; |
+ } |
+ AutoCFRelease<CFDictionaryRef> ctvariations(CTFontCopyVariation(ct)); |
+ ///AutoCFRelease<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(ct)); |
+ //CFShow(desc); |
+ //AutoCFRelease<CTFontDescriptorRef> desc1(CTFontDescriptorCreateCopyWithVariation(desc, (CFNumberRef)keys[0], 1.0)); |
+ //CFShow(desc1); |
+ AutoCFRelease<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct)); |
+ CFShow(ctAxes); |
+ SkTypeface* typeface = NewFromFontRef(ct, NULL, true); |
+ SkFontData* fontData1 = typeface->createFontData(); |
+ delete fontData1; |
+ return typeface; |
+ } |
+ |
SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { |
AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path)); |
if (NULL == pr) { |
@@ -2308,3 +2448,4 @@ protected: |
SkFontMgr* SkFontMgr::Factory() { |
return SkNEW(SkFontMgr_Mac); |
} |
+ |