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

Side by Side Diff: src/ports/SkFontHost_mac.cpp

Issue 1027373002: Font variations. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase Created 5 years, 7 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 unified diff | Download patch
« no previous file with comments | « src/ports/SkFontHost_linux.cpp ('k') | src/ports/SkFontMgr_android.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkTypes.h" // Keep this before any #ifdef ... 9 #include "SkTypes.h" // Keep this before any #ifdef ...
10 10
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported. 421 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported.
422 #if defined(__MAC_10_7) || defined(__IPHONE_4_3) 422 #if defined(__MAC_10_7) || defined(__IPHONE_4_3)
423 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait; 423 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait;
424 #else 424 #else
425 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); 425 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13);
426 #endif 426 #endif
427 427
428 class SkTypeface_Mac : public SkTypeface { 428 class SkTypeface_Mac : public SkTypeface {
429 public: 429 public:
430 SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch, 430 SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch,
431 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream) 431 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream,
432 CGFontRef originatingCGFontRef = NULL)
432 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) 433 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch)
433 , fRequestedName(requestedName) 434 , fRequestedName(requestedName)
434 , fFontRef(fontRef) // caller has already called CFRetain for us 435 , fFontRef(fontRef) // caller has already called CFRetain for us
436 , fOriginatingCGFontRef(originatingCGFontRef)
435 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait)) 437 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait))
436 , fIsLocalStream(isLocalStream) 438 , fIsLocalStream(isLocalStream)
437 { 439 {
438 SkASSERT(fontRef); 440 SkASSERT(fontRef);
439 } 441 }
440 442
441 SkString fRequestedName; 443 SkString fRequestedName;
442 AutoCFRelease<CTFontRef> fFontRef; 444 AutoCFRelease<CTFontRef> fFontRef;
445 AutoCFRelease<CGFontRef> fOriginatingCGFontRef;
443 const bool fHasColorGlyphs; 446 const bool fHasColorGlyphs;
444 447
445 protected: 448 protected:
446 int onGetUPEM() const override; 449 int onGetUPEM() const override;
447 SkStreamAsset* onOpenStream(int* ttcIndex) const override; 450 SkStreamAsset* onOpenStream(int* ttcIndex) const override;
451 SkFontData* onCreateFontData() const override;
448 void onGetFamilyName(SkString* familyName) const override; 452 void onGetFamilyName(SkString* familyName) const override;
449 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; 453 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
450 int onGetTableTags(SkFontTableTag tags[]) const override; 454 int onGetTableTags(SkFontTableTag tags[]) const override;
451 virtual size_t onGetTableData(SkFontTableTag, size_t offset, 455 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
452 size_t length, void* data) const override; 456 size_t length, void* data) const override;
453 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override; 457 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override;
454 void onFilterRec(SkScalerContextRec*) const override; 458 void onFilterRec(SkScalerContextRec*) const override;
455 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; 459 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
456 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 460 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
457 PerGlyphInfo, 461 PerGlyphInfo,
458 const uint32_t*, uint32_t) const override; 462 const uint32_t*, uint32_t) const override;
459 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], 463 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[],
460 int glyphCount) const override; 464 int glyphCount) const override;
461 int onCountGlyphs() const override; 465 int onCountGlyphs() const override;
462 466
463 private: 467 private:
464 bool fIsLocalStream; 468 bool fIsLocalStream;
465 469
466 typedef SkTypeface INHERITED; 470 typedef SkTypeface INHERITED;
467 }; 471 };
468 472
469 /** Creates a typeface without searching the cache. Takes ownership of the CTFon tRef. */ 473 /** Creates a typeface without searching the cache. Takes ownership of the CTFon tRef. */
470 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream) { 474 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream,
475 CGFontRef originatingCGFontRef = NULL)
476 {
471 SkASSERT(fontRef); 477 SkASSERT(fontRef);
472 bool isFixedPitch; 478 bool isFixedPitch;
473 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); 479 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch));
474 480
475 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream) ; 481 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream,
482 originatingCGFontRef);
476 } 483 }
477 484
478 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont ext) { 485 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont ext) {
479 CTFontRef self = (CTFontRef)context; 486 CTFontRef self = (CTFontRef)context;
480 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; 487 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef;
481 488
482 return CFEqual(self, other); 489 return CFEqual(self, other);
483 } 490 }
484 491
485 /** Creates a typeface from a name, searching the cache. */ 492 /** Creates a typeface from a name, searching the cache. */
(...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1745 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); 1752 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
1746 1753
1747 dataPtr += (tableSize + 3) & ~3; 1754 dataPtr += (tableSize + 3) & ~3;
1748 ++entry; 1755 ++entry;
1749 } 1756 }
1750 1757
1751 *ttcIndex = 0; 1758 *ttcIndex = 0;
1752 return stream; 1759 return stream;
1753 } 1760 }
1754 1761
1762 struct NonDefaultAxesContext {
1763 SkFixed* axisValue;
1764 CFArrayRef cgAxes;
1765 };
1766 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
1767 NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
1768
1769 if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumbe rGetTypeID()) {
1770 return;
1771 }
1772
1773 // The key is a CFString which is a string from the 'name' table.
1774 // Search the cgAxes for an axis with this name, and use its index to store the value.
1775 CFIndex keyIndex = -1;
1776 CFStringRef keyString = static_cast<CFStringRef>(key);
1777 for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
1778 CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
1779 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
1780 continue;
1781 }
1782
1783 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
1784 CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariation AxisName);
1785 if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
1786 continue;
1787 }
1788 CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
1789 if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo ) {
1790 keyIndex = i;
1791 break;
1792 }
1793 }
1794 if (keyIndex == -1) {
1795 return;
1796 }
1797
1798 CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
1799 double valueDouble;
1800 if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
1801 valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMa x) < valueDouble)
1802 {
1803 return;
1804 }
1805 self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
1806 }
1807 static bool get_variations(CTFontRef fFontRef, CFIndex* cgAxisCount,
1808 SkAutoSTMalloc<4, SkFixed>* axisValues)
1809 {
1810 // CTFontCopyVariationAxes and CTFontCopyVariation do not work when applied to fonts which
1811 // started life with CGFontCreateWithDataProvider (they simply always return NULL).
1812 // As a result, we are limited to CGFontCopyVariationAxes and CGFontCopyVari ations.
1813 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
1814
1815 AutoCFRelease<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont));
1816 // If a font has no variations CGFontCopyVariations returns NULL (instead of an empty dict).
1817 if (!cgVariations.get()) {
1818 return false;
1819 }
1820
1821 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont));
1822 *cgAxisCount = CFArrayGetCount(cgAxes);
1823 axisValues->reset(*cgAxisCount);
1824
1825 // Set all of the axes to their default values.
1826 // Fail if any default value cannot be determined.
1827 for (CFIndex i = 0; i < *cgAxisCount; ++i) {
1828 CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i);
1829 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
1830 return false;
1831 }
1832
1833 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
1834 CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
1835 kCGFontVariationAxisDe faultValue);
1836 if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTyp eID()) {
1837 return false;
1838 }
1839 CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaul tValue);
1840 double axisDefaultValueDouble;
1841 if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axis DefaultValueDouble))
1842 {
1843 return false;
1844 }
1845 if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
1846 SkFixedToDouble(SK_FixedMax) < axisDefaultV alueDouble)
1847 {
1848 return false;
1849 }
1850 (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
1851 }
1852
1853 // Override the default values with the given font's stated axis values.
1854 NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
1855 CFDictionaryApplyFunction(cgVariations, set_non_default_axes, &c);
1856
1857 return true;
1858 }
1859 SkFontData* SkTypeface_Mac::onCreateFontData() const {
1860 int index;
1861 SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index));
1862
1863 CFIndex cgAxisCount;
1864 SkAutoSTMalloc<4, SkFixed> axisValues;
1865 if (get_variations(fFontRef, &cgAxisCount, &axisValues)) {
1866 return new SkFontData(stream.detach(), index, axisValues.get(), cgAxisCo unt);
1867 }
1868 return new SkFontData(stream.detach(), index, NULL, 0);
1869 }
1870
1755 /////////////////////////////////////////////////////////////////////////////// 1871 ///////////////////////////////////////////////////////////////////////////////
1756 /////////////////////////////////////////////////////////////////////////////// 1872 ///////////////////////////////////////////////////////////////////////////////
1757 1873
1758 int SkTypeface_Mac::onGetUPEM() const { 1874 int SkTypeface_Mac::onGetUPEM() const {
1759 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); 1875 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
1760 return CGFontGetUnitsPerEm(cgFont); 1876 return CGFontGetUnitsPerEm(cgFont);
1761 } 1877 }
1762 1878
1763 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1879 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
1764 SkTypeface::LocalizedStrings* nameIter = 1880 SkTypeface::LocalizedStrings* nameIter =
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 } 2356 }
2241 2357
2242 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride { 2358 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride {
2243 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m)); 2359 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m));
2244 if (NULL == pr) { 2360 if (NULL == pr) {
2245 return NULL; 2361 return NULL;
2246 } 2362 }
2247 return create_from_dataProvider(pr); 2363 return create_from_dataProvider(pr);
2248 } 2364 }
2249 2365
2366 static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) {
2367 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
2368 if (!cgAxes) {
2369 return NULL;
2370 }
2371
2372 CFIndex axisCount = CFArrayGetCount(cgAxes);
2373 if (0 == axisCount || axisCount != fontData->getAxisCount()) {
2374 return NULL;
2375 }
2376
2377 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefa ult, axisCount,
2378 &kCFTypeDictiona ryKeyCallBacks,
2379 &kCFTypeDictiona ryValueCallBacks);
2380 for (int i = 0; i < fontData->getAxisCount(); ++i) {
2381 CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i);
2382 if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2383 return NULL;
2384 }
2385 CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo );
2386
2387 CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVaria tionAxisName);
2388 if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2389 return NULL;
2390 }
2391
2392 // The variation axes can be set to any value, but cg will effective ly pin them.
2393 // Pin them here to normalize.
2394 CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA xisMinValue);
2395 CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA xisMaxValue);
2396 if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2397 !max || CFGetTypeID(max) != CFNumberGetTypeID())
2398 {
2399 return NULL;
2400 }
2401 CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2402 CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2403 double minDouble;
2404 double maxDouble;
2405 if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2406 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
2407 {
2408 return NULL;
2409 }
2410 double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDo uble, maxDouble);
2411 CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNum berDoubleType,
2412 &value);
2413
2414 CFDictionaryAddValue(dict, axisName, valueNumber);
2415 CFRelease(valueNumber);
2416 }
2417 return dict;
2418 }
2419 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
2420 SkAutoTDelete<SkFontData> fontData(data);
2421 SkStreamAsset* stream = fontData->detachStream();
2422 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream (stream));
2423 if (NULL == provider) {
2424 return NULL;
2425 }
2426 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider));
2427 if (NULL == cg) {
2428 return NULL;
2429 }
2430
2431 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData));
2432 // The CGFontRef returned by CGFontCreateCopyWithVariations when the pas sed CGFontRef was
2433 // created from a data provider does not appear to have any ownership of the underlying
2434 // data. The original CGFontRef must be kept alive until the copy will n o longer be used.
2435 AutoCFRelease<CGFontRef> cgVariant;
2436 if (cgVariations) {
2437 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations));
2438 } else {
2439 cgVariant.reset(cg.detach());
2440 }
2441
2442 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, NULL, NULL);
2443 if (!ct) {
2444 return NULL;
2445 }
2446 return NewFromFontRef(ct, NULL, true, cg.detach());
2447 }
2448
2250 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 2449 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
2251 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h)); 2450 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h));
2252 if (NULL == pr) { 2451 if (NULL == pr) {
2253 return NULL; 2452 return NULL;
2254 } 2453 }
2255 return create_from_dataProvider(pr); 2454 return create_from_dataProvider(pr);
2256 } 2455 }
2257 2456
2258 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2457 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
2259 unsigned styleBits) const overrid e { 2458 unsigned styleBits) const overrid e {
(...skipping 21 matching lines...) Expand all
2281 } 2480 }
2282 return face; 2481 return face;
2283 } 2482 }
2284 }; 2483 };
2285 2484
2286 /////////////////////////////////////////////////////////////////////////////// 2485 ///////////////////////////////////////////////////////////////////////////////
2287 2486
2288 SkFontMgr* SkFontMgr::Factory() { 2487 SkFontMgr* SkFontMgr::Factory() {
2289 return SkNEW(SkFontMgr_Mac); 2488 return SkNEW(SkFontMgr_Mac);
2290 } 2489 }
OLDNEW
« no previous file with comments | « src/ports/SkFontHost_linux.cpp ('k') | src/ports/SkFontMgr_android.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698