Chromium Code Reviews| 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); |
| } |
| + |