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

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, CFNumberType::kCFNumberDoubleType, &value Double) ||
bungeman-skia 2015/05/13 23:04:44 This should have just been just kCFNumberDoubleTyp
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, CFNumberType::kCFNumberDou bleType,
bungeman-skia 2015/05/13 23:04:44 Same here.
1842 &axisDefaultValueDouble))
1843 {
1844 return false;
1845 }
1846 if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
1847 SkFixedToDouble(SK_FixedMax) < axisDefaultV alueDouble)
1848 {
1849 return false;
1850 }
1851 (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
1852 }
1853
1854 // Override the default values with the given font's stated axis values.
1855 NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
1856 CFDictionaryApplyFunction(cgVariations, set_non_default_axes, &c);
1857
1858 return true;
1859 }
1860 SkFontData* SkTypeface_Mac::onCreateFontData() const {
1861 int index;
1862 SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index));
1863
1864 CFIndex cgAxisCount;
1865 SkAutoSTMalloc<4, SkFixed> axisValues;
1866 if (get_variations(fFontRef, &cgAxisCount, &axisValues)) {
1867 return new SkFontData(stream.detach(), index, axisValues.get(), cgAxisCo unt);
1868 }
1869 return new SkFontData(stream.detach(), index, NULL, 0);
1870 }
1871
1755 /////////////////////////////////////////////////////////////////////////////// 1872 ///////////////////////////////////////////////////////////////////////////////
1756 /////////////////////////////////////////////////////////////////////////////// 1873 ///////////////////////////////////////////////////////////////////////////////
1757 1874
1758 int SkTypeface_Mac::onGetUPEM() const { 1875 int SkTypeface_Mac::onGetUPEM() const {
1759 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); 1876 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
1760 return CGFontGetUnitsPerEm(cgFont); 1877 return CGFontGetUnitsPerEm(cgFont);
1761 } 1878 }
1762 1879
1763 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1880 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
1764 SkTypeface::LocalizedStrings* nameIter = 1881 SkTypeface::LocalizedStrings* nameIter =
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 } 2357 }
2241 2358
2242 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride { 2359 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride {
2243 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m)); 2360 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m));
2244 if (NULL == pr) { 2361 if (NULL == pr) {
2245 return NULL; 2362 return NULL;
2246 } 2363 }
2247 return create_from_dataProvider(pr); 2364 return create_from_dataProvider(pr);
2248 } 2365 }
2249 2366
2367 static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) {
2368 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
2369 if (!cgAxes) {
2370 return NULL;
2371 }
2372
2373 CFIndex axisCount = CFArrayGetCount(cgAxes);
2374 if (0 == axisCount || axisCount != fontData->getAxisCount()) {
2375 return NULL;
2376 }
2377
2378 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefa ult, axisCount,
2379 &kCFTypeDictiona ryKeyCallBacks,
2380 &kCFTypeDictiona ryValueCallBacks);
2381 for (int i = 0; i < fontData->getAxisCount(); ++i) {
2382 CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i);
2383 if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2384 return NULL;
2385 }
2386 CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo );
2387
2388 CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVaria tionAxisName);
2389 if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2390 return NULL;
2391 }
2392
2393 // The variation axes can be set to any value, but cg will effective ly pin them.
2394 // Pin them here to normalize.
2395 CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA xisMinValue);
2396 CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA xisMaxValue);
2397 if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2398 !max || CFGetTypeID(max) != CFNumberGetTypeID())
2399 {
2400 return NULL;
2401 }
2402 CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2403 CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2404 double minDouble;
2405 double maxDouble;
2406 if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2407 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
2408 {
2409 return NULL;
2410 }
2411 double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDo uble, maxDouble);
2412 CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNum berDoubleType,
2413 &value);
2414
2415 CFDictionaryAddValue(dict, axisName, valueNumber);
2416 CFRelease(valueNumber);
2417 }
2418 return dict;
2419 }
2420 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
2421 SkAutoTDelete<SkFontData> fontData(data);
2422 SkStreamAsset* stream = fontData->detachStream();
2423 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream (stream));
2424 if (NULL == provider) {
2425 return NULL;
2426 }
2427 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider));
2428 if (NULL == cg) {
2429 return NULL;
2430 }
2431
2432 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData));
2433 // The CGFontRef returned by CGFontCreateCopyWithVariations when the pas sed CGFontRef was
2434 // created from a data provider does not appear to have any ownership of the underlying
2435 // data. The original CGFontRef must be kept alive until the copy will n o longer be used.
2436 AutoCFRelease<CGFontRef> cgVariant;
2437 if (cgVariations) {
2438 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations));
2439 } else {
2440 cgVariant.reset(cg.detach());
2441 }
2442
2443 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, NULL, NULL);
2444 if (!ct) {
2445 return NULL;
2446 }
2447 return NewFromFontRef(ct, NULL, true, cg.detach());
2448 }
2449
2250 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 2450 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
2251 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h)); 2451 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h));
2252 if (NULL == pr) { 2452 if (NULL == pr) {
2253 return NULL; 2453 return NULL;
2254 } 2454 }
2255 return create_from_dataProvider(pr); 2455 return create_from_dataProvider(pr);
2256 } 2456 }
2257 2457
2258 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2458 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
2259 unsigned styleBits) const overrid e { 2459 unsigned styleBits) const overrid e {
(...skipping 21 matching lines...) Expand all
2281 } 2481 }
2282 return face; 2482 return face;
2283 } 2483 }
2284 }; 2484 };
2285 2485
2286 /////////////////////////////////////////////////////////////////////////////// 2486 ///////////////////////////////////////////////////////////////////////////////
2287 2487
2288 SkFontMgr* SkFontMgr::Factory() { 2488 SkFontMgr* SkFontMgr::Factory() {
2289 return SkNEW(SkFontMgr_Mac); 2489 return SkNEW(SkFontMgr_Mac);
2290 } 2490 }
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