| OLD | NEW |
| 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 Loading... |
| 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) | |
| 433 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) | 432 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) |
| 434 , fRequestedName(requestedName) | 433 , fRequestedName(requestedName) |
| 435 , fFontRef(fontRef) // caller has already called CFRetain for us | 434 , fFontRef(fontRef) // caller has already called CFRetain for us |
| 436 , fOriginatingCGFontRef(originatingCGFontRef) | |
| 437 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC
olorGlyphsTrait)) | 435 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC
olorGlyphsTrait)) |
| 438 , fIsLocalStream(isLocalStream) | 436 , fIsLocalStream(isLocalStream) |
| 439 { | 437 { |
| 440 SkASSERT(fontRef); | 438 SkASSERT(fontRef); |
| 441 } | 439 } |
| 442 | 440 |
| 443 SkString fRequestedName; | 441 SkString fRequestedName; |
| 444 AutoCFRelease<CTFontRef> fFontRef; | 442 AutoCFRelease<CTFontRef> fFontRef; |
| 445 AutoCFRelease<CGFontRef> fOriginatingCGFontRef; | |
| 446 const bool fHasColorGlyphs; | 443 const bool fHasColorGlyphs; |
| 447 | 444 |
| 448 protected: | 445 protected: |
| 449 int onGetUPEM() const override; | 446 int onGetUPEM() const override; |
| 450 SkStreamAsset* onOpenStream(int* ttcIndex) const override; | 447 SkStreamAsset* onOpenStream(int* ttcIndex) const override; |
| 451 SkFontData* onCreateFontData() const override; | |
| 452 void onGetFamilyName(SkString* familyName) const override; | 448 void onGetFamilyName(SkString* familyName) const override; |
| 453 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; | 449 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; |
| 454 int onGetTableTags(SkFontTableTag tags[]) const override; | 450 int onGetTableTags(SkFontTableTag tags[]) const override; |
| 455 virtual size_t onGetTableData(SkFontTableTag, size_t offset, | 451 virtual size_t onGetTableData(SkFontTableTag, size_t offset, |
| 456 size_t length, void* data) const override; | 452 size_t length, void* data) const override; |
| 457 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override; | 453 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override; |
| 458 void onFilterRec(SkScalerContextRec*) const override; | 454 void onFilterRec(SkScalerContextRec*) const override; |
| 459 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; | 455 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; |
| 460 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | 456 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
| 461 PerGlyphInfo, | 457 PerGlyphInfo, |
| 462 const uint32_t*, uint32_t) const override; | 458 const uint32_t*, uint32_t) const override; |
| 463 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], | 459 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], |
| 464 int glyphCount) const override; | 460 int glyphCount) const override; |
| 465 int onCountGlyphs() const override; | 461 int onCountGlyphs() const override; |
| 466 | 462 |
| 467 private: | 463 private: |
| 468 bool fIsLocalStream; | 464 bool fIsLocalStream; |
| 469 | 465 |
| 470 typedef SkTypeface INHERITED; | 466 typedef SkTypeface INHERITED; |
| 471 }; | 467 }; |
| 472 | 468 |
| 473 /** Creates a typeface without searching the cache. Takes ownership of the CTFon
tRef. */ | 469 /** Creates a typeface without searching the cache. Takes ownership of the CTFon
tRef. */ |
| 474 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL
ocalStream, | 470 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL
ocalStream) { |
| 475 CGFontRef originatingCGFontRef = NULL) | |
| 476 { | |
| 477 SkASSERT(fontRef); | 471 SkASSERT(fontRef); |
| 478 bool isFixedPitch; | 472 bool isFixedPitch; |
| 479 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); | 473 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); |
| 480 | 474 |
| 481 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream, | 475 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream)
; |
| 482 originatingCGFontRef); | |
| 483 } | 476 } |
| 484 | 477 |
| 485 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont
ext) { | 478 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont
ext) { |
| 486 CTFontRef self = (CTFontRef)context; | 479 CTFontRef self = (CTFontRef)context; |
| 487 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; | 480 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; |
| 488 | 481 |
| 489 return CFEqual(self, other); | 482 return CFEqual(self, other); |
| 490 } | 483 } |
| 491 | 484 |
| 492 /** Creates a typeface from a name, searching the cache. */ | 485 /** Creates a typeface from a name, searching the cache. */ |
| (...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1752 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); | 1745 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); |
| 1753 | 1746 |
| 1754 dataPtr += (tableSize + 3) & ~3; | 1747 dataPtr += (tableSize + 3) & ~3; |
| 1755 ++entry; | 1748 ++entry; |
| 1756 } | 1749 } |
| 1757 | 1750 |
| 1758 *ttcIndex = 0; | 1751 *ttcIndex = 0; |
| 1759 return stream; | 1752 return stream; |
| 1760 } | 1753 } |
| 1761 | 1754 |
| 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 | |
| 1871 /////////////////////////////////////////////////////////////////////////////// | 1755 /////////////////////////////////////////////////////////////////////////////// |
| 1872 /////////////////////////////////////////////////////////////////////////////// | 1756 /////////////////////////////////////////////////////////////////////////////// |
| 1873 | 1757 |
| 1874 int SkTypeface_Mac::onGetUPEM() const { | 1758 int SkTypeface_Mac::onGetUPEM() const { |
| 1875 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); | 1759 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); |
| 1876 return CGFontGetUnitsPerEm(cgFont); | 1760 return CGFontGetUnitsPerEm(cgFont); |
| 1877 } | 1761 } |
| 1878 | 1762 |
| 1879 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const
{ | 1763 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const
{ |
| 1880 SkTypeface::LocalizedStrings* nameIter = | 1764 SkTypeface::LocalizedStrings* nameIter = |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2356 } | 2240 } |
| 2357 | 2241 |
| 2358 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov
erride { | 2242 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov
erride { |
| 2359 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea
m)); | 2243 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea
m)); |
| 2360 if (NULL == pr) { | 2244 if (NULL == pr) { |
| 2361 return NULL; | 2245 return NULL; |
| 2362 } | 2246 } |
| 2363 return create_from_dataProvider(pr); | 2247 return create_from_dataProvider(pr); |
| 2364 } | 2248 } |
| 2365 | 2249 |
| 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 | |
| 2449 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override
{ | 2250 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override
{ |
| 2450 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat
h)); | 2251 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(pat
h)); |
| 2451 if (NULL == pr) { | 2252 if (NULL == pr) { |
| 2452 return NULL; | 2253 return NULL; |
| 2453 } | 2254 } |
| 2454 return create_from_dataProvider(pr); | 2255 return create_from_dataProvider(pr); |
| 2455 } | 2256 } |
| 2456 | 2257 |
| 2457 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], | 2258 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
| 2458 unsigned styleBits) const overrid
e { | 2259 unsigned styleBits) const overrid
e { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2480 } | 2281 } |
| 2481 return face; | 2282 return face; |
| 2482 } | 2283 } |
| 2483 }; | 2284 }; |
| 2484 | 2285 |
| 2485 /////////////////////////////////////////////////////////////////////////////// | 2286 /////////////////////////////////////////////////////////////////////////////// |
| 2486 | 2287 |
| 2487 SkFontMgr* SkFontMgr::Factory() { | 2288 SkFontMgr* SkFontMgr::Factory() { |
| 2488 return SkNEW(SkFontMgr_Mac); | 2289 return SkNEW(SkFontMgr_Mac); |
| 2489 } | 2290 } |
| OLD | NEW |