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

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: Android and tests. 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
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 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported. 420 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported.
421 #if defined(__MAC_10_7) || defined(__IPHONE_4_3) 421 #if defined(__MAC_10_7) || defined(__IPHONE_4_3)
422 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait; 422 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait;
423 #else 423 #else
424 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); 424 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13);
425 #endif 425 #endif
426 426
427 class SkTypeface_Mac : public SkTypeface { 427 class SkTypeface_Mac : public SkTypeface {
428 public: 428 public:
429 SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch, 429 SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch,
430 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream) 430 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream,
431 CGFontRef originatingCGFontRef = NULL)
431 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) 432 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch)
432 , fRequestedName(requestedName) 433 , fRequestedName(requestedName)
433 , fFontRef(fontRef) // caller has already called CFRetain for us 434 , fFontRef(fontRef) // caller has already called CFRetain for us
435 , fOriginatingCGFontRef(originatingCGFontRef)
434 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait)) 436 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait))
435 , fIsLocalStream(isLocalStream) 437 , fIsLocalStream(isLocalStream)
436 { 438 {
437 SkASSERT(fontRef); 439 SkASSERT(fontRef);
438 } 440 }
439 441
440 SkString fRequestedName; 442 SkString fRequestedName;
441 AutoCFRelease<CTFontRef> fFontRef; 443 AutoCFRelease<CTFontRef> fFontRef;
444 AutoCFRelease<CGFontRef> fOriginatingCGFontRef;
442 const bool fHasColorGlyphs; 445 const bool fHasColorGlyphs;
443 446
444 protected: 447 protected:
445 int onGetUPEM() const override; 448 int onGetUPEM() const override;
446 SkStreamAsset* onOpenStream(int* ttcIndex) const override; 449 SkStreamAsset* onOpenStream(int* ttcIndex) const override;
450 SkFontData* onCreateFontData() const override;
447 void onGetFamilyName(SkString* familyName) const override; 451 void onGetFamilyName(SkString* familyName) const override;
448 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; 452 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
449 int onGetTableTags(SkFontTableTag tags[]) const override; 453 int onGetTableTags(SkFontTableTag tags[]) const override;
450 virtual size_t onGetTableData(SkFontTableTag, size_t offset, 454 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
451 size_t length, void* data) const override; 455 size_t length, void* data) const override;
452 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override; 456 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override;
453 void onFilterRec(SkScalerContextRec*) const override; 457 void onFilterRec(SkScalerContextRec*) const override;
454 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; 458 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
455 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 459 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
456 SkAdvancedTypefaceMetrics::PerGlyphInfo, 460 SkAdvancedTypefaceMetrics::PerGlyphInfo,
457 const uint32_t*, uint32_t) const override; 461 const uint32_t*, uint32_t) const override;
458 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], 462 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[],
459 int glyphCount) const override; 463 int glyphCount) const override;
460 int onCountGlyphs() const override; 464 int onCountGlyphs() const override;
461 465
462 private: 466 private:
463 bool fIsLocalStream; 467 bool fIsLocalStream;
464 468
465 typedef SkTypeface INHERITED; 469 typedef SkTypeface INHERITED;
466 }; 470 };
467 471
468 /** Creates a typeface without searching the cache. Takes ownership of the CTFon tRef. */ 472 /** Creates a typeface without searching the cache. Takes ownership of the CTFon tRef. */
469 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream) { 473 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream,
474 CGFontRef originatingCGFontRef = NULL)
475 {
470 SkASSERT(fontRef); 476 SkASSERT(fontRef);
471 bool isFixedPitch; 477 bool isFixedPitch;
472 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); 478 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch));
473 479
474 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream) ; 480 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream,
481 originatingCGFontRef);
475 } 482 }
476 483
477 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont ext) { 484 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont ext) {
478 CTFontRef self = (CTFontRef)context; 485 CTFontRef self = (CTFontRef)context;
479 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; 486 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef;
480 487
481 return CFEqual(self, other); 488 return CFEqual(self, other);
482 } 489 }
483 490
484 /** Creates a typeface from a name, searching the cache. */ 491 /** Creates a typeface from a name, searching the cache. */
(...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); 1751 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
1745 1752
1746 dataPtr += (tableSize + 3) & ~3; 1753 dataPtr += (tableSize + 3) & ~3;
1747 ++entry; 1754 ++entry;
1748 } 1755 }
1749 1756
1750 *ttcIndex = 0; 1757 *ttcIndex = 0;
1751 return stream; 1758 return stream;
1752 } 1759 }
1753 1760
1761 struct NonDefaultAxesContext {
1762 SkFixed* axisValue;
1763 CFArrayRef cgAxes;
1764 };
1765 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
1766 NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
1767
1768 if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumbe rGetTypeID()) {
1769 return;
1770 }
1771
1772 // The key is a CFString which is a string from the 'name' table.
1773 // Search the cgAxes for an axis with this name, and use its index to store the value.
1774 CFIndex keyIndex = -1;
1775 CFStringRef keyString = static_cast<CFStringRef>(key);
1776 for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
1777 CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
1778 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
1779 continue;
1780 }
1781
1782 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
1783 CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariation AxisName);
1784 if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
1785 continue;
1786 }
1787 CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
1788 if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo ) {
1789 keyIndex = i;
1790 break;
1791 }
1792 }
1793 if (keyIndex == -1) {
1794 return;
1795 }
1796
1797 CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
1798 double valueDouble;
1799 if (!CFNumberGetValue(valueNumber, CFNumberType::kCFNumberDoubleType, &value Double) ||
1800 valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMa x) < valueDouble)
1801 {
1802 return;
1803 }
1804 self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
1805 }
1806 static bool get_variations(CTFontRef fFontRef, CFIndex* cgAxisCount,
1807 SkAutoSTMalloc<4, SkFixed>* axisValues)
1808 {
1809 // CTFontCopyVariationAxes and CTFontCopyVariation do not work when applied to fonts which
1810 // started life with CGFontCreateWithDataProvider (they simply always return NULL).
1811 // As a result, we are limited to CGFontCopyVariationAxes and CGFontCopyVari ations.
1812 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
1813
1814 AutoCFRelease<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont));
1815 // If a font has no variations CGFontCopyVariations returns NULL (instead of an empty dict).
1816 if (!cgVariations.get()) {
1817 return false;
1818 }
1819
1820 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont));
1821 *cgAxisCount = CFArrayGetCount(cgAxes);
1822 axisValues->reset(*cgAxisCount);
1823
1824 // Set all of the axes to their default values.
1825 // Fail if any default value cannot be determined.
1826 for (CFIndex i = 0; i < *cgAxisCount; ++i) {
1827 CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i);
1828 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
1829 return false;
1830 }
1831
1832 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
1833 CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
1834 kCGFontVariationAxisDe faultValue);
1835 if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTyp eID()) {
1836 return false;
1837 }
1838 CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaul tValue);
1839 double axisDefaultValueDouble;
1840 if (!CFNumberGetValue(axisDefaultValueNumber, CFNumberType::kCFNumberDou bleType,
1841 &axisDefaultValueDouble))
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, cgAxisCount, axisValues.ge t());
1867 }
1868 return new SkFontData(stream.detach(), index, 0, NULL);
1869 }
1870
1754 /////////////////////////////////////////////////////////////////////////////// 1871 ///////////////////////////////////////////////////////////////////////////////
1755 /////////////////////////////////////////////////////////////////////////////// 1872 ///////////////////////////////////////////////////////////////////////////////
1756 1873
1757 int SkTypeface_Mac::onGetUPEM() const { 1874 int SkTypeface_Mac::onGetUPEM() const {
1758 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); 1875 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
1759 return CGFontGetUnitsPerEm(cgFont); 1876 return CGFontGetUnitsPerEm(cgFont);
1760 } 1877 }
1761 1878
1762 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1879 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
1763 SkTypeface::LocalizedStrings* nameIter = 1880 SkTypeface::LocalizedStrings* nameIter =
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 } 2356 }
2240 2357
2241 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride { 2358 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov erride {
2242 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m)); 2359 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea m));
2243 if (NULL == pr) { 2360 if (NULL == pr) {
2244 return NULL; 2361 return NULL;
2245 } 2362 }
2246 return create_from_dataProvider(pr); 2363 return create_from_dataProvider(pr);
2247 } 2364 }
2248 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* fontData) const override {
2420 SkStreamAsset* stream = fontData->detachStream();
2421 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream (stream));
2422 if (NULL == provider) {
2423 return NULL;
2424 }
2425 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider));
2426 if (NULL == cg) {
2427 return NULL;
2428 }
2429
2430 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData));
2431 // The CGFontRef returned by CGFontCreateCopyWithVariations when the pas sed CGFontRef was
2432 // created from a data provider does not appear to have any ownership of the underlying
2433 // data. The original CGFontRef must be kept alive until the copy will n o longer be used.
2434 AutoCFRelease<CGFontRef> cgVariant;
2435 if (cgVariations) {
2436 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations));
2437 } else {
2438 cgVariant.reset(cg.detach());
2439 }
2440
2441 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, NULL, NULL);
2442 if (!ct) {
2443 return NULL;
2444 }
2445 return NewFromFontRef(ct, NULL, true, cg.detach());
2446 }
2447
2249 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 2448 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
2250 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h)); 2449 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat h));
2251 if (NULL == pr) { 2450 if (NULL == pr) {
2252 return NULL; 2451 return NULL;
2253 } 2452 }
2254 return create_from_dataProvider(pr); 2453 return create_from_dataProvider(pr);
2255 } 2454 }
2256 2455
2257 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2456 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
2258 unsigned styleBits) const overrid e { 2457 unsigned styleBits) const overrid e {
(...skipping 21 matching lines...) Expand all
2280 } 2479 }
2281 return face; 2480 return face;
2282 } 2481 }
2283 }; 2482 };
2284 2483
2285 /////////////////////////////////////////////////////////////////////////////// 2484 ///////////////////////////////////////////////////////////////////////////////
2286 2485
2287 SkFontMgr* SkFontMgr::Factory() { 2486 SkFontMgr* SkFontMgr::Factory() {
2288 return SkNEW(SkFontMgr_Mac); 2487 return SkNEW(SkFontMgr_Mac);
2289 } 2488 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698