Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(906)

Unified Diff: src/ports/SkFontHost_mac.cpp

Issue 1027373002: Font variations. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Some clean up. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/ports/SkFontHost_mac.cpp
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 5eaf7df6036b281fe08560d07baeef9e418fa7fe..4b8316afd3f9139940255e55dcd4e3765c2bf63f 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,111 @@ SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
return stream;
}
+struct NonDefaultAxesContext {
+ SkFixed* axisValue;
+ CFArrayRef cgAxes;
+};
+static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
+ NonDefaultAxesContext* c = static_cast<NonDefaultAxesContext*>(context);
+
+ // The key is a CFString which is a string from the 'name' table.
+ // Search the cgAxes for an axis with this name, and use its index to store the value.
+ CFIndex keyIndex = -1;
+ if (CFGetTypeID(key) == CFStringGetTypeID()) {
+ CFStringRef keyString = static_cast<CFStringRef>(key);
+ for (CFIndex i = 0; i < CFArrayGetCount(c->cgAxes); ++i) {
+ CFTypeRef cgAxis = CFArrayGetValueAtIndex(c->cgAxes, i);
+ if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
+ continue;
+ }
+
+ CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
+ CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
+ if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
+ continue;
+ }
+ CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
+ if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
+ keyIndex = i;
+ break;
+ }
+ }
+ }
+ if (keyIndex == -1) {
+ return;
+ }
+
+ 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?
+ {
+ c->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
+ }
+ }
+}
+static bool get_variations(CTFontRef fFontRef, CFIndex* cgAxisCount, SkAutoSTMalloc<4, SkFixed>* axisValues) {
+ // CTFontCopyVariationAxes and CTFontCopyVariation do not work when applied to fonts which
+ // started life with CGFontCreateWithDataProvider (they simply always return NULL).
+ // As a result, we are limited to CGFontCopyVariationAxes and CGFontCopyVariations.
+ AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
+
+ AutoCFRelease<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont));
+ // If a font has no variations CGFontCopyVariations returns NULL (instead of an empty dict).
+ if (!cgVariations.get()) {
+ return false;
+ }
+
+ AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont));
+ *cgAxisCount = CFArrayGetCount(cgAxes);
+ axisValues->reset(*cgAxisCount);
+
+ // Set all of the axes to their default values.
+ // Fail if any default value cannot be determined.
+ for (CFIndex i = 0; i < *cgAxisCount; ++i) {
+ CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i);
+ if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
+ return false;
+ }
+
+ CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
+ CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisDefaultValue);
+ if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
+ return false;
+ }
+ CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
+ double axisDefaultValueDouble;
+ if (!CFNumberGetValue(axisDefaultValueNumber, CFNumberType::kCFNumberDoubleType, &axisDefaultValueDouble)) {
+ return false;
+ }
+ if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
+ SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
+ {
+ return false;
+ }
+ (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
+ }
+
+ // Override the default values with the given font's stated axis values.
+ NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
+ CFDictionaryApplyFunction(cgVariations, set_non_default_axes, &c);
+
+ return true;
+}
+SkFontData* SkTypeface_Mac::onCreateFontData() const {
+ int index;
+ SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index));
+
+ CFIndex cgAxisCount;
+ SkAutoSTMalloc<4, SkFixed> axisValues;
+ if (get_variations(fFontRef, &cgAxisCount, &axisValues)) {
+ //axisValues[0] = 4 * SK_Fixed1; // TODO:remove, for testing out of bound values
+ return new SkFontData(stream.detach(), index, cgAxisCount, axisValues.get());
+ }
+ return new SkFontData(stream.detach(), index, 0, NULL);
+}
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -2267,6 +2373,67 @@ protected:
return create_from_dataProvider(pr);
}
+ static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) {
+ AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
+ if (!cgAxes) {
+ return NULL;
+ }
+
+ CFIndex axisCount = CFArrayGetCount(cgAxes);
+ if (axisCount != fontData->getAxisCount()) {
+ return NULL;
+ }
+
+ SkAutoSTMalloc<4, CFTypeRef> keys(fontData->getAxisCount());
+ SkAutoSTMalloc<4, CFTypeRef> values(fontData->getAxisCount());
+ for (int i = 0; i < fontData->getAxisCount(); ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return NULL;
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName);
+ if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
+ return NULL;
+ }
+ keys[i] = axisName;
+
+ //CFNumberRef min = static_cast<CFNumberRef>(CFDictionaryGetValue(axisInfo, kCGFontVariationAxisMinValue));
+ //CFNumberRef max = static_cast<CFNumberRef>(CFDictionaryGetValue(axisInfo, kCGFontVariationAxisMaxValue));
+ //TODO: should the value be pinned?
+ double value = SkFixedToDouble(fontData->getAxis()[i]);
+ values[i] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value);
+ }
+
+ return CFDictionaryCreate(kCFAllocatorDefault, keys.get(), values.get(), fontData->getAxisCount(),
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ }
+ 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;
+ }
+
+ AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData));
+ AutoCFRelease<CGFontRef> cgVariant(cgVariations ? CGFontCreateCopyWithVariations(cg, cgVariations) : cg);
+
+ CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, NULL, NULL);
+ if (!ct) {
+ return NULL;
+ }
+ //SkTypeface* typeface = NewFromFontRef(ct, NULL, true);
+ //SkFontData* fontData1 = typeface->createFontData();
+ //delete fontData1;
+ //return typeface;
+ return NewFromFontRef(ct, NULL, true);
+ }
+
SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
if (NULL == pr) {

Powered by Google App Engine
This is Rietveld 408576698