Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkTypes.h"  // Keep this before any #ifdef ...
      9 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
     10 
     11 #ifdef SK_BUILD_FOR_MAC
     12 #import <ApplicationServices/ApplicationServices.h>
     13 #endif
     14 
     15 #ifdef SK_BUILD_FOR_IOS
     16 #include <CoreText/CoreText.h>
     17 #include <CoreText/CTFontManager.h>
     18 #include <CoreGraphics/CoreGraphics.h>
     19 #include <CoreFoundation/CoreFoundation.h>
     20 #endif
     21 
     22 #include "SkAdvancedTypefaceMetrics.h"
     23 #include "SkAutoMalloc.h"
     24 #include "SkCGUtils.h"
     25 #include "SkColorPriv.h"
     26 #include "SkDescriptor.h"
     27 #include "SkEndian.h"
     28 #include "SkFloatingPoint.h"
     29 #include "SkFontDescriptor.h"
     30 #include "SkFontMgr.h"
     31 #include "SkGlyph.h"
     32 #include "SkMakeUnique.h"
     33 #include "SkMaskGamma.h"
     34 #include "SkMathPriv.h"
     35 #include "SkMutex.h"
     36 #include "SkOTTable_OS_2.h"
     37 #include "SkOTUtils.h"
     38 #include "SkOnce.h"
     39 #include "SkPaint.h"
     40 #include "SkPath.h"
     41 #include "SkSFNTHeader.h"
     42 #include "SkStream.h"
     43 #include "SkString.h"
     44 #include "SkTemplates.h"
     45 #include "SkTypefaceCache.h"
     46 #include "SkTypeface_mac.h"
     47 #include "SkUtils.h"
     48 
     49 // Experimental code to use a global lock whenever we access CG, to see if this reduces
     50 // crashes in Chrome
     51 #define USE_GLOBAL_MUTEX_FOR_CG_ACCESS
     52 
     53 #ifdef USE_GLOBAL_MUTEX_FOR_CG_ACCESS
     54     SK_DECLARE_STATIC_MUTEX(gCGMutex);
     55     #define AUTO_CG_LOCK()  SkAutoMutexAcquire amc(gCGMutex)
     56 #else
     57     #define AUTO_CG_LOCK()
     58 #endif
     59 
     60 // Set to make glyph bounding boxes visible.
     61 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
     62 
     63 class SkScalerContext_Mac;
     64 
     65 struct CFSafeRelease {
     66     void operator()(CFTypeRef cfTypeRef) {
     67       if (cfTypeRef) {
     68           CFRelease(cfTypeRef);
     69       }
     70     }
     71 };
     72 template <typename CFRef> using UniqueCFRef =
     73         std::unique_ptr<skstd::remove_pointer_t<CFRef>, CFSafeRelease>;
     74 
     75 static UniqueCFRef<CFStringRef> make_CFString(const char str[]) {
     76     return UniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, str, kCFStringEncodingUTF8));
     77 }
     78 
     79 // inline versions of these rect helpers
     80 
     81 static bool CGRectIsEmpty_inline(const CGRect& rect) {
     82     return rect.size.width <= 0 || rect.size.height <= 0;
     83 }
     84 
     85 static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
     86     return rect.origin.x;
     87 }
     88 
     89 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) {
     90     return rect.origin.x + rect.size.width;
     91 }
     92 
     93 static CGFloat CGRectGetMinY_inline(const CGRect& rect) {
     94     return rect.origin.y;
     95 }
     96 
     97 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
     98     return rect.origin.y + rect.size.height;
     99 }
    100 
    101 static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
    102     return rect.size.width;
    103 }
    104 
    105 ///////////////////////////////////////////////////////////////////////////////
    106 
    107 static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
    108                              int width, int height, size_t rowBytes) {
    109     SkASSERT(width);
    110     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
    111 
    112     if (width >= 32) {
    113         while (height) {
    114             sk_memset32(ptr, value, width);
    115             ptr = (uint32_t*)((char*)ptr + rowBytes);
    116             height -= 1;
    117         }
    118         return;
    119     }
    120 
    121     rowBytes -= width * sizeof(uint32_t);
    122 
    123     if (width >= 8) {
    124         while (height) {
    125             int w = width;
    126             do {
    127                 *ptr++ = value; *ptr++ = value;
    128                 *ptr++ = value; *ptr++ = value;
    129                 *ptr++ = value; *ptr++ = value;
    130                 *ptr++ = value; *ptr++ = value;
    131                 w -= 8;
    132             } while (w >= 8);
    133             while (--w >= 0) {
    134                 *ptr++ = value;
    135             }
    136             ptr = (uint32_t*)((char*)ptr + rowBytes);
    137             height -= 1;
    138         }
    139     } else {
    140         while (height) {
    141             int w = width;
    142             do {
    143                 *ptr++ = value;
    144             } while (--w > 0);
    145             ptr = (uint32_t*)((char*)ptr + rowBytes);
    146             height -= 1;
    147         }
    148     }
    149 }
    150 
    151 typedef uint32_t CGRGBPixel;
    152 
    153 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
    154     return pixel & 0xFF;
    155 }
    156 
    157 static CGFloat ScalarToCG(SkScalar scalar) {
    158     if (sizeof(CGFloat) == sizeof(float)) {
    159         return SkScalarToFloat(scalar);
    160     } else {
    161         SkASSERT(sizeof(CGFloat) == sizeof(double));
    162         return (CGFloat) SkScalarToDouble(scalar);
    163     }
    164 }
    165 
    166 static SkScalar CGToScalar(CGFloat cgFloat) {
    167     if (sizeof(CGFloat) == sizeof(float)) {
    168         return SkFloatToScalar(cgFloat);
    169     } else {
    170         SkASSERT(sizeof(CGFloat) == sizeof(double));
    171         return SkDoubleToScalar(cgFloat);
    172     }
    173 }
    174 
    175 static float CGToFloat(CGFloat cgFloat) {
    176     if (sizeof(CGFloat) == sizeof(float)) {
    177         return cgFloat;
    178     } else {
    179         SkASSERT(sizeof(CGFloat) == sizeof(double));
    180         return static_cast<float>(cgFloat);
    181     }
    182 }
    183 
    184 static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix) {
    185     return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX]),
    186                                  -ScalarToCG(matrix[SkMatrix::kMSkewY] ),
    187                                  -ScalarToCG(matrix[SkMatrix::kMSkewX] ),
    188                                   ScalarToCG(matrix[SkMatrix::kMScaleY]),
    189                                   ScalarToCG(matrix[SkMatrix::kMTransX]),
    190                                   ScalarToCG(matrix[SkMatrix::kMTransY]));
    191 }
    192 
    193 ///////////////////////////////////////////////////////////////////////////////
    194 
    195 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
    196 
    197 /**
    198  * There does not appear to be a publicly accessable API for determining if lcd
    199  * font smoothing will be applied if we request it. The main issue is that if
    200  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
    201  */
    202 static bool supports_LCD() {
    203     static int gSupportsLCD = -1;
    204     if (gSupportsLCD >= 0) {
    205         return (bool) gSupportsLCD;
    206     }
    207     uint32_t rgb = 0;
    208     UniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
    209     UniqueCFRef<CGContextRef> cgContext(
    210             CGBitmapContextCreate(&rgb, 1, 1, 8, 4, colorspace.get(), BITMAP_INFO_RGB));
    211     UniqueCFRef<CTFontRef> ctFont(CTFontCreateWithName(CFSTR("Helvetica"), 16, nullptr));
    212     CGContextSetShouldSmoothFonts(cgContext.get(), true);
    213     CGContextSetShouldAntialias(cgContext.get(), true);
    214     CGContextSetTextDrawingMode(cgContext.get(), kCGTextFill);
    215     CGContextSetGrayFillColor(cgContext.get(), 1, 1);
    216     CGPoint point = CGPointMake(-1, 0);
    217     static const UniChar pipeChar = '|';
    218     CGGlyph pipeGlyph;
    219     CTFontGetGlyphsForCharacters(ctFont.get(), &pipeChar, &pipeGlyph, 1);
    220     CTFontDrawGlyphs(ctFont.get(), &pipeGlyph, &point, 1, cgContext.get());
    221 
    222     uint32_t r = (rgb >> 16) & 0xFF;
    223     uint32_t g = (rgb >>  8) & 0xFF;
    224     uint32_t b = (rgb >>  0) & 0xFF;
    225     gSupportsLCD = (r != g || r != b);
    226     return (bool) gSupportsLCD;
    227 }
    228 
    229 class Offscreen {
    230 public:
    231     Offscreen()
    232         : fRGBSpace(nullptr)
    233         , fCG(nullptr)
    234         , fDoAA(false)
    235         , fDoLCD(false)
    236     {
    237         fSize.set(0, 0);
    238     }
    239 
    240     CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    241                       CGGlyph glyphID, size_t* rowBytesPtr, bool generateA8FromLCD);
    242 
    243 private:
    244     enum {
    245         kSize = 32 * 32 * sizeof(CGRGBPixel)
    246     };
    247     SkAutoSMalloc<kSize> fImageStorage;
    248     UniqueCFRef<CGColorSpaceRef> fRGBSpace;
    249 
    250     // cached state
    251     UniqueCFRef<CGContextRef> fCG;
    252     SkISize fSize;
    253     bool fDoAA;
    254     bool fDoLCD;
    255 
    256     static int RoundSize(int dimension) {
    257         return SkNextPow2(dimension);
    258     }
    259 };
    260 
    261 ///////////////////////////////////////////////////////////////////////////////
    262 
    263 static bool find_dict_CGFloat(CFDictionaryRef dict, CFStringRef name, CGFloat* value) {
    264     CFNumberRef num;
    265     return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num)
    266         && CFNumberIsFloatType(num)
    267         && CFNumberGetValue(num, kCFNumberCGFloatType, value);
    268 }
    269 
    270 template <typename S, typename D, typename C> struct LinearInterpolater {
    271     struct Mapping {
    272         S src_val;
    273         D dst_val;
    274     };
    275     constexpr LinearInterpolater(Mapping const mapping[], int mappingCount)
    276         : fMapping(mapping), fMappingCount(mappingCount) {}
    277 
    278     static D map(S value, S src_min, S src_max, D dst_min, D dst_max) {
    279         SkASSERT(src_min < src_max);
    280         SkASSERT(dst_min <= dst_max);
    281         return C()(dst_min + (((value - src_min) * (dst_max - dst_min)) / (src_max - src_min)));
    282     }
    283 
    284     D map(S val) const {
    285         // -Inf to [0]
    286         if (val < fMapping[0].src_val) {
    287             return fMapping[0].dst_val;
    288         }
    289 
    290         // Linear from [i] to [i+1]
    291         for (int i = 0; i < fMappingCount - 1; ++i) {
    292             if (val < fMapping[i+1].src_val) {
    293                 return map(val, fMapping[i].src_val, fMapping[i+1].src_val,
    294                                 fMapping[i].dst_val, fMapping[i+1].dst_val);
    295             }
    296         }
    297 
    298         // From [n] to +Inf
    299         // if (fcweight < Inf)
    300         return fMapping[fMappingCount - 1].dst_val;
    301     }
    302 
    303     Mapping const * fMapping;
    304     int fMappingCount;
    305 };
    306 
    307 struct RoundCGFloatToInt {
    308     int operator()(CGFloat s) { return s + 0.5; }
    309 };
    310 struct CGFloatIdentity {
    311     CGFloat operator()(CGFloat s) { return s; }
    312 };
    313 
    314 /** Convert the [0, 1000] CSS weight to [-1, 1] CTFontDescriptor weight (for system fonts).
    315  *
    316  *  The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
    317  *  CTFont is native or created from a CGDataProvider.
    318  */
    319 static CGFloat fontstyle_to_ct_weight(int fontstyleWeight) {
    320     using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
    321 
    322     // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
    323     // However, on this end we can't tell, so this is ignored.
    324 
    325     /** This mapping for native fonts is determined by running the following in an .mm file
    326      *  #include <AppKit/AppKit>
    327      *  printf("{  100, % #.2f },\n", NSFontWeightUltraLight);
    328      *  printf("{  200, % #.2f },\n", NSFontWeightThin);
    329      *  printf("{  300, % #.2f },\n", NSFontWeightLight);
    330      *  printf("{  400, % #.2f },\n", NSFontWeightRegular);
    331      *  printf("{  500, % #.2f },\n", NSFontWeightMedium);
    332      *  printf("{  600, % #.2f },\n", NSFontWeightSemibold);
    333      *  printf("{  700, % #.2f },\n", NSFontWeightBold);
    334      *  printf("{  800, % #.2f },\n", NSFontWeightHeavy);
    335      *  printf("{  900, % #.2f },\n", NSFontWeightBlack);
    336      */
    337     static constexpr Interpolator::Mapping nativeWeightMappings[] = {
    338         {    0, -1.00 },
    339         {  100, -0.80 },
    340         {  200, -0.60 },
    341         {  300, -0.40 },
    342         {  400,  0.00 },
    343         {  500,  0.23 },
    344         {  600,  0.30 },
    345         {  700,  0.40 },
    346         {  800,  0.56 },
    347         {  900,  0.62 },
    348         { 1000,  1.00 },
    349     };
    350     static constexpr Interpolator nativeInterpolator(
    351             nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
    352 
    353     return nativeInterpolator.map(fontstyleWeight);
    354 }
    355 
    356 
    357 /** Convert the [-1, 1] CTFontDescriptor weight to [0, 1000] CSS weight.
    358  *
    359  *  The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
    360  *  CTFont is native or created from a CGDataProvider.
    361  */
    362 static int ct_weight_to_fontstyle(CGFloat cgWeight, bool fromDataProvider) {
    363     using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
    364 
    365     // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
    366     // However, on this end we can't tell, so this is ignored.
    367 
    368     /** This mapping for CGDataProvider created fonts is determined by creating font data with every
    369      *  weight, creating a CTFont, and asking the CTFont for its weight. See the TypefaceStyle test
    370      *  in tests/TypefaceTest.cpp for the code used to determine these values.
    371      */
    372     static constexpr Interpolator::Mapping dataProviderWeightMappings[] = {
    373         { -1.00,    0 },
    374         { -0.70,  100 },
    375         { -0.50,  200 },
    376         { -0.23,  300 },
    377         {  0.00,  400 },
    378         {  0.20,  500 },
    379         {  0.30,  600 },
    380         {  0.40,  700 },
    381         {  0.60,  800 },
    382         {  0.80,  900 },
    383         {  1.00, 1000 },
    384     };
    385     static constexpr Interpolator dataProviderInterpolator(
    386             dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings));
    387 
    388     /** This mapping for native fonts is determined by running the following in an .mm file
    389      *  #include <AppKit/AppKit>
    390      *  printf("{ % #.2f,  100 },\n", NSFontWeightUltraLight);
    391      *  printf("{ % #.2f,  200 },\n", NSFontWeightThin);
    392      *  printf("{ % #.2f,  300 },\n", NSFontWeightLight);
    393      *  printf("{ % #.2f,  400 },\n", NSFontWeightRegular);
    394      *  printf("{ % #.2f,  500 },\n", NSFontWeightMedium);
    395      *  printf("{ % #.2f,  600 },\n", NSFontWeightSemibold);
    396      *  printf("{ % #.2f,  700 },\n", NSFontWeightBold);
    397      *  printf("{ % #.2f,  800 },\n", NSFontWeightHeavy);
    398      *  printf("{ % #.2f,  900 },\n", NSFontWeightBlack);
    399      */
    400     static constexpr Interpolator::Mapping nativeWeightMappings[] = {
    401         { -1.00,    0 },
    402         { -0.80,  100 },
    403         { -0.60,  200 },
    404         { -0.40,  300 },
    405         {  0.00,  400 },
    406         {  0.23,  500 },
    407         {  0.30,  600 },
    408         {  0.40,  700 },
    409         {  0.56,  800 },
    410         {  0.62,  900 },
    411         {  1.00, 1000 },
    412     };
    413     static constexpr Interpolator nativeInterpolator(
    414             nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
    415 
    416     return fromDataProvider ? dataProviderInterpolator.map(cgWeight)
    417                             : nativeInterpolator.map(cgWeight);
    418 }
    419 
    420 /** Convert the [0, 10] CSS weight to [-1, 1] CTFontDescriptor width. */
    421 static int fontstyle_to_ct_width(int fontstyleWidth) {
    422     using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
    423 
    424     // Values determined by creating font data with every width, creating a CTFont,
    425     // and asking the CTFont for its width. See TypefaceStyle test for basics.
    426     static constexpr Interpolator::Mapping widthMappings[] = {
    427         {  0, -0.5 },
    428         { 10,  0.5 },
    429     };
    430     static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
    431     return interpolator.map(fontstyleWidth);
    432 }
    433 
    434 /** Convert the [-1, 1] CTFontDescriptor width to [0, 10] CSS weight. */
    435 static int ct_width_to_fontstyle(CGFloat cgWidth) {
    436     using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
    437 
    438     // Values determined by creating font data with every width, creating a CTFont,
    439     // and asking the CTFont for its width. See TypefaceStyle test for basics.
    440     static constexpr Interpolator::Mapping widthMappings[] = {
    441         { -0.5,  0 },
    442         {  0.5, 10 },
    443     };
    444     static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
    445     return interpolator.map(cgWidth);
    446 }
    447 
    448 static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc, bool fromDataProvider) {
    449     UniqueCFRef<CFTypeRef> fontTraits(CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute));
    450     if (!fontTraits || CFDictionaryGetTypeID() != CFGetTypeID(fontTraits.get())) {
    451         return SkFontStyle();
    452     }
    453     UniqueCFRef<CFDictionaryRef> fontTraitsDict(static_cast<CFDictionaryRef>(fontTraits.release()));
    454 
    455     CGFloat weight, width, slant;
    456     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWeightTrait, &weight)) {
    457         weight = 0;
    458     }
    459     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWidthTrait, &width)) {
    460         width = 0;
    461     }
    462     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontSlantTrait, &slant)) {
    463         slant = 0;
    464     }
    465 
    466     return SkFontStyle(ct_weight_to_fontstyle(weight, fromDataProvider),
    467                        ct_width_to_fontstyle(width),
    468                        slant ? SkFontStyle::kItalic_Slant
    469                              : SkFontStyle::kUpright_Slant);
    470 }
    471 
    472 class SkTypeface_Mac : public SkTypeface {
    473 public:
    474     SkTypeface_Mac(UniqueCFRef<CTFontRef> fontRef, UniqueCFRef<CFTypeRef> resourceRef,
    475                    const SkFontStyle& fs, bool isFixedPitch,
    476                    bool isLocalStream)
    477         : SkTypeface(fs, isFixedPitch)
    478         , fFontRef(std::move(fontRef))
    479         , fOriginatingCFTypeRef(std::move(resourceRef))
    480         , fHasColorGlyphs(
    481                 SkToBool(CTFontGetSymbolicTraits(fFontRef.get()) & kCTFontColorGlyphsTrait))
    482         , fIsLocalStream(isLocalStream)
    483     {
    484         SkASSERT(fFontRef);
    485     }
    486 
    487     UniqueCFRef<CTFontRef> fFontRef;
    488     UniqueCFRef<CFTypeRef> fOriginatingCFTypeRef;
    489     const bool fHasColorGlyphs;
    490 
    491 protected:
    492     int onGetUPEM() const override;
    493     SkStreamAsset* onOpenStream(int* ttcIndex) const override;
    494     std::unique_ptr<SkFontData> onMakeFontData() const override;
    495     int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
    496                                      int coordinateCount) const override;
    497     void onGetFamilyName(SkString* familyName) const override;
    498     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
    499     int onGetTableTags(SkFontTableTag tags[]) const override;
    500     size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
    501     SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
    502                                            const SkDescriptor*) const override;
    503     void onFilterRec(SkScalerContextRec*) const override;
    504     void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
    505     SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
    506             PerGlyphInfo, const uint32_t* glyphIDs, uint32_t glyphIDsCount) const override;
    507     int onCharsToGlyphs(const void* chars, Encoding,
    508                         uint16_t glyphs[], int glyphCount) const override;
    509     int onCountGlyphs() const override;
    510 
    511 private:
    512     bool fIsLocalStream;
    513 
    514     typedef SkTypeface INHERITED;
    515 };
    516 
    517 static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
    518     CTFontRef self = (CTFontRef)context;
    519     CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef.get();
    520 
    521     return CFEqual(self, other);
    522 }
    523 
    524 /** Creates a typeface, searching the cache if isLocalStream is false. */
    525 static SkTypeface* create_from_CTFontRef(UniqueCFRef<CTFontRef> font,
    526                                          UniqueCFRef<CFTypeRef> resource,
    527                                          bool isLocalStream) {
    528     SkASSERT(font);
    529 
    530     if (!isLocalStream) {
    531         SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)font.get());
    532         if (face) {
    533             return face;
    534         }
    535     }
    536 
    537     UniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get()));
    538     SkFontStyle style = fontstyle_from_descriptor(desc.get(), isLocalStream);
    539     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get());
    540     bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait);
    541 
    542     SkTypeface* face = new SkTypeface_Mac(std::move(font), std::move(resource),
    543                                           style, isFixedPitch, isLocalStream);
    544     if (!isLocalStream) {
    545         SkTypefaceCache::Add(face);
    546     }
    547     return face;
    548 }
    549 
    550 /** Creates a typeface from a descriptor, searching the cache. */
    551 static SkTypeface* create_from_desc(CTFontDescriptorRef desc) {
    552     UniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
    553     if (!ctFont) {
    554         return nullptr;
    555     }
    556 
    557     return create_from_CTFontRef(std::move(ctFont), nullptr, false);
    558 }
    559 
    560 static UniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[],
    561                                                           const SkFontStyle& style) {
    562     UniqueCFRef<CFMutableDictionaryRef> cfAttributes(
    563             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    564                                       &kCFTypeDictionaryKeyCallBacks,
    565                                       &kCFTypeDictionaryValueCallBacks));
    566 
    567     UniqueCFRef<CFMutableDictionaryRef> cfTraits(
    568             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    569                                       &kCFTypeDictionaryKeyCallBacks,
    570                                       &kCFTypeDictionaryValueCallBacks));
    571 
    572     if (!cfAttributes || !cfTraits) {
    573         return nullptr;
    574     }
    575 
    576     // CTFontTraits (symbolic)
    577     CTFontSymbolicTraits ctFontTraits = 0;
    578     if (style.weight() >= SkFontStyle::kBold_Weight) {
    579         ctFontTraits |= kCTFontBoldTrait;
    580     }
    581     if (style.slant() != SkFontStyle::kUpright_Slant) {
    582         ctFontTraits |= kCTFontItalicTrait;
    583     }
    584     UniqueCFRef<CFNumberRef> cfFontTraits(
    585             CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
    586     if (cfFontTraits) {
    587         CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
    588     }
    589     // CTFontTraits (weight)
    590     CGFloat ctWeight = fontstyle_to_ct_weight(style.weight());
    591     UniqueCFRef<CFNumberRef> cfFontWeight(
    592             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
    593     if (cfFontWeight) {
    594         CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
    595     }
    596     // CTFontTraits (width)
    597     CGFloat ctWidth = fontstyle_to_ct_width(style.weight());
    598     UniqueCFRef<CFNumberRef> cfFontWidth(
    599             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
    600     if (cfFontWidth) {
    601         CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
    602     }
    603     // CTFontTraits (slant)
    604     CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1;
    605     UniqueCFRef<CFNumberRef> cfFontSlant(
    606             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
    607     if (cfFontSlant) {
    608         CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
    609     }
    610     // CTFontTraits
    611     CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
    612 
    613     // CTFontFamilyName
    614     if (familyName) {
    615         UniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
    616         if (cfFontName) {
    617             CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
    618         }
    619     }
    620 
    621     return UniqueCFRef<CTFontDescriptorRef>(
    622             CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
    623 }
    624 
    625 /** Creates a typeface from a name, searching the cache. */
    626 static SkTypeface* create_from_name(const char familyName[], const SkFontStyle& style) {
    627     UniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
    628     if (!desc) {
    629         return nullptr;
    630     }
    631     return create_from_desc(desc.get());
    632 }
    633 
    634 ///////////////////////////////////////////////////////////////////////////////
    635 
    636 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face);
    637 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
    638     const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face;
    639     return macface ? macface->fFontRef.get() : nullptr;
    640 }
    641 
    642 /*  This function is visible on the outside. It first searches the cache, and if
    643  *  not found, returns a new entry (after adding it to the cache).
    644  */
    645 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font, CFTypeRef resource) {
    646     CFRetain(font);
    647     if (resource) {
    648         CFRetain(resource);
    649     }
    650     return create_from_CTFontRef(UniqueCFRef<CTFontRef>(font),
    651                                  UniqueCFRef<CFTypeRef>(resource),
    652                                  false);
    653 }
    654 
    655 static const char* map_css_names(const char* name) {
    656     static const struct {
    657         const char* fFrom;  // name the caller specified
    658         const char* fTo;    // "canonical" name we map to
    659     } gPairs[] = {
    660         { "sans-serif", "Helvetica" },
    661         { "serif",      "Times"     },
    662         { "monospace",  "Courier"   }
    663     };
    664 
    665     for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
    666         if (strcmp(name, gPairs[i].fFrom) == 0) {
    667             return gPairs[i].fTo;
    668         }
    669     }
    670     return name;    // no change
    671 }
    672 
    673 ///////////////////////////////////////////////////////////////////////////////
    674 
    675 class SkScalerContext_Mac : public SkScalerContext {
    676 public:
    677     SkScalerContext_Mac(sk_sp<SkTypeface_Mac>, const SkScalerContextEffects&, const SkDescriptor*);
    678 
    679 protected:
    680     unsigned generateGlyphCount(void) override;
    681     uint16_t generateCharToGlyph(SkUnichar uni) override;
    682     void generateAdvance(SkGlyph* glyph) override;
    683     void generateMetrics(SkGlyph* glyph) override;
    684     void generateImage(const SkGlyph& glyph) override;
    685     void generatePath(SkGlyphID glyph, SkPath* path) override;
    686     void generateFontMetrics(SkPaint::FontMetrics*) override;
    687 
    688 private:
    689     static void CTPathElement(void *info, const CGPathElement *element);
    690 
    691     /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */
    692     void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const;
    693 
    694     Offscreen fOffscreen;
    695 
    696     /** Unrotated variant of fCTFont.
    697      *
    698      *  In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the
    699      *  advances, but always sets the height to 0. This font is used to get the advances of the
    700      *  unrotated glyph, and then the rotation is applied separately.
    701      *
    702      *  CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
    703      *  This makes kCTFontOrientationDefault dangerous, because the metrics from
    704      *  kCTFontOrientationHorizontal are in a different space from kCTFontOrientationVertical.
    705      *  With kCTFontOrientationVertical the advances must be unrotated.
    706      *
    707      *  Sometimes, creating a copy of a CTFont with the same size but different trasform will select
    708      *  different underlying font data. As a result, avoid ever creating more than one CTFont per
    709      *  SkScalerContext to ensure that only one CTFont is used.
    710      *
    711      *  As a result of the above (and other constraints) this font contains the size, but not the
    712      *  transform. The transform must always be applied separately.
    713      */
    714     UniqueCFRef<CTFontRef> fCTFont;
    715 
    716     /** The transform without the font size. */
    717     CGAffineTransform fTransform;
    718     CGAffineTransform fInvTransform;
    719 
    720     UniqueCFRef<CGFontRef> fCGFont;
    721     uint16_t fGlyphCount;
    722     const bool fDoSubPosition;
    723     const bool fVertical;
    724 
    725     friend class Offscreen;
    726 
    727     typedef SkScalerContext INHERITED;
    728 };
    729 
    730 // CTFontCreateCopyWithAttributes or CTFontCreateCopyWithSymbolicTraits cannot be used on 10.10
    731 // and later, as they will return different underlying fonts depending on the size requested.
    732 // It is not possible to use descriptors with CTFontCreateWithFontDescriptor, since that does not
    733 // work with non-system fonts. As a result, create the strike specific CTFonts from the underlying
    734 // CGFont.
    735 static UniqueCFRef<CTFontRef> ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize,
    736                                                        const CGAffineTransform* transform)
    737 {
    738     UniqueCFRef<CGFontRef> baseCGFont(CTFontCopyGraphicsFont(baseFont, nullptr));
    739 
    740     // The last parameter (CTFontDescriptorRef attributes) *must* be nullptr.
    741     // If non-nullptr then with fonts with variation axes, the copy will fail in
    742     // CGFontVariationFromDictCallback when it assumes kCGFontVariationAxisName is CFNumberRef
    743     // which it quite obviously is not.
    744 
    745     // Because we cannot setup the CTFont descriptor to match, the same restriction applies here
    746     // as other uses of CTFontCreateWithGraphicsFont which is that such CTFonts should not escape
    747     // the scaler context, since they aren't 'normal'.
    748     return UniqueCFRef<CTFontRef>(
    749             CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, transform, nullptr));
    750 }
    751 
    752 SkScalerContext_Mac::SkScalerContext_Mac(sk_sp<SkTypeface_Mac> typeface,
    753                                          const SkScalerContextEffects& effects,
    754                                          const SkDescriptor* desc)
    755         : INHERITED(std::move(typeface), effects, desc)
    756         , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
    757         , fVertical(SkToBool(fRec.fFlags & kVertical_Flag))
    758 
    759 {
    760     AUTO_CG_LOCK();
    761 
    762     CTFontRef ctFont = static_cast<SkTypeface_Mac*>(this->getTypeface())->fFontRef.get();
    763     CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
    764     SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
    765     fGlyphCount = SkToU16(numGlyphs);
    766 
    767     // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
    768     // As a result, it is necessary to know the actual device size and request that.
    769     SkVector scale;
    770     SkMatrix skTransform;
    771     bool invertible = fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
    772                                            &scale, &skTransform, nullptr, nullptr, nullptr);
    773     fTransform = MatrixToCGAffineTransform(skTransform);
    774     // CGAffineTransformInvert documents that if the transform is non-invertible it will return the
    775     // passed transform unchanged. It does so, but then also prints a message to stdout. Avoid this.
    776     if (invertible) {
    777         fInvTransform = CGAffineTransformInvert(fTransform);
    778     } else {
    779         fInvTransform = fTransform;
    780     }
    781 
    782     // The transform contains everything except the requested text size.
    783     // Some properties, like 'trak', are based on the text size (before applying the matrix).
    784     CGFloat textSize = ScalarToCG(scale.y());
    785     fCTFont = ctfont_create_exact_copy(ctFont, textSize, nullptr);
    786     fCGFont.reset(CTFontCopyGraphicsFont(fCTFont.get(), nullptr));
    787 }
    788 
    789 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    790                              CGGlyph glyphID, size_t* rowBytesPtr,
    791                              bool generateA8FromLCD) {
    792     if (!fRGBSpace) {
    793         //It doesn't appear to matter what color space is specified.
    794         //Regular blends and antialiased text are always (s*a + d*(1-a))
    795         //and smoothed text is always g=2.0.
    796         fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
    797     }
    798 
    799     // default to kBW_Format
    800     bool doAA = false;
    801     bool doLCD = false;
    802 
    803     if (SkMask::kBW_Format != glyph.fMaskFormat) {
    804         doLCD = true;
    805         doAA = true;
    806     }
    807 
    808     // FIXME: lcd smoothed un-hinted rasterization unsupported.
    809     if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) {
    810         doLCD = false;
    811         doAA = true;
    812     }
    813 
    814     // If this font might have color glyphs, disable LCD as there's no way to support it.
    815     // CoreText doesn't tell us which format it ended up using, so we can't detect it.
    816     // A8 will end up black on transparent, but TODO: we can detect gray and set to A8.
    817     if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
    818         doLCD = false;
    819     }
    820 
    821     size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    822     if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) {
    823         if (fSize.fWidth < glyph.fWidth) {
    824             fSize.fWidth = RoundSize(glyph.fWidth);
    825         }
    826         if (fSize.fHeight < glyph.fHeight) {
    827             fSize.fHeight = RoundSize(glyph.fHeight);
    828         }
    829 
    830         rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    831         void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
    832         const CGImageAlphaInfo alpha = (SkMask::kARGB32_Format == glyph.fMaskFormat)
    833                                      ? kCGImageAlphaPremultipliedFirst
    834                                      : kCGImageAlphaNoneSkipFirst;
    835         const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha;
    836         fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
    837                                         rowBytes, fRGBSpace.get(), bitmapInfo));
    838 
    839         // Skia handles quantization and subpixel positioning,
    840         // so disable quantization and enabe subpixel positioning in CG.
    841         CGContextSetAllowsFontSubpixelQuantization(fCG.get(), false);
    842         CGContextSetShouldSubpixelQuantizeFonts(fCG.get(), false);
    843 
    844         // Because CG always draws from the horizontal baseline,
    845         // if there is a non-integral translation from the horizontal origin to the vertical origin,
    846         // then CG cannot draw the glyph in the correct location without subpixel positioning.
    847         CGContextSetAllowsFontSubpixelPositioning(fCG.get(), true);
    848         CGContextSetShouldSubpixelPositionFonts(fCG.get(), true);
    849 
    850         CGContextSetTextDrawingMode(fCG.get(), kCGTextFill);
    851 
    852         // Draw black on white to create mask. (Special path exists to speed this up in CG.)
    853         CGContextSetGrayFillColor(fCG.get(), 0.0f, 1.0f);
    854 
    855         // force our checks below to happen
    856         fDoAA = !doAA;
    857         fDoLCD = !doLCD;
    858 
    859         CGContextSetTextMatrix(fCG.get(), context.fTransform);
    860     }
    861 
    862     if (fDoAA != doAA) {
    863         CGContextSetShouldAntialias(fCG.get(), doAA);
    864         fDoAA = doAA;
    865     }
    866     if (fDoLCD != doLCD) {
    867         CGContextSetShouldSmoothFonts(fCG.get(), doLCD);
    868         fDoLCD = doLCD;
    869     }
    870 
    871     CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
    872     // skip rows based on the glyph's height
    873     image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth;
    874 
    875     // Erase to white (or transparent black if it's a color glyph, to not composite against white).
    876     uint32_t bgColor = (SkMask::kARGB32_Format != glyph.fMaskFormat) ? 0xFFFFFFFF : 0x00000000;
    877     sk_memset_rect32(image, bgColor, glyph.fWidth, glyph.fHeight, rowBytes);
    878 
    879     float subX = 0;
    880     float subY = 0;
    881     if (context.fDoSubPosition) {
    882         subX = SkFixedToFloat(glyph.getSubXFixed());
    883         subY = SkFixedToFloat(glyph.getSubYFixed());
    884     }
    885 
    886     // CoreText and CoreGraphics always draw using the horizontal baseline origin.
    887     if (context.fVertical) {
    888         SkPoint offset;
    889         context.getVerticalOffset(glyphID, &offset);
    890         subX += offset.fX;
    891         subY += offset.fY;
    892     }
    893 
    894     CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY);
    895     // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
    896     // 'positions' which are in text space. The glyph location (in device space) must be
    897     // mapped into text space, so that CG can convert it back into device space.
    898     // In 10.10.1, this is handled directly in CTFontDrawGlyphs.
    899     //
    900     // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
    901     // So always make the font transform identity and place the transform on the context.
    902     point = CGPointApplyAffineTransform(point, context.fInvTransform);
    903 
    904     CTFontDrawGlyphs(context.fCTFont.get(), &glyphID, &point, 1, fCG.get());
    905 
    906     SkASSERT(rowBytesPtr);
    907     *rowBytesPtr = rowBytes;
    908     return image;
    909 }
    910 
    911 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const {
    912     // CTFontGetVerticalTranslationsForGlyphs produces cgVertOffset in CG units (pixels, y up).
    913     CGSize cgVertOffset;
    914     CTFontGetVerticalTranslationsForGlyphs(fCTFont.get(), &glyphID, &cgVertOffset, 1);
    915     cgVertOffset = CGSizeApplyAffineTransform(cgVertOffset, fTransform);
    916     SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
    917     // From CG units (pixels, y up) to SkGlyph units (pixels, y down).
    918     skVertOffset.fY = -skVertOffset.fY;
    919     *offset = skVertOffset;
    920 }
    921 
    922 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
    923     return fGlyphCount;
    924 }
    925 
    926 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) {
    927     AUTO_CG_LOCK();
    928 
    929     CGGlyph cgGlyph[2];
    930     UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit.
    931 
    932     // Get the glyph
    933     size_t numUniChar = SkUTF16_FromUnichar(uni, theChar);
    934     SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t));
    935 
    936     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
    937     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
    938     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
    939     CTFontGetGlyphsForCharacters(fCTFont.get(), theChar, cgGlyph, numUniChar);
    940     return cgGlyph[0];
    941 }
    942 
    943 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
    944     this->generateMetrics(glyph);
    945 }
    946 
    947 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
    948     AUTO_CG_LOCK();
    949 
    950     const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
    951     glyph->zeroMetrics();
    952 
    953     // The following block produces cgAdvance in CG units (pixels, y up).
    954     CGSize cgAdvance;
    955     if (fVertical) {
    956         CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationVertical,
    957                                    &cgGlyph, &cgAdvance, 1);
    958         // Vertical advances are returned as widths instead of heights.
    959         SkTSwap(cgAdvance.height, cgAdvance.width);
    960         cgAdvance.height = -cgAdvance.height;
    961     } else {
    962         CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
    963                                    &cgGlyph, &cgAdvance, 1);
    964     }
    965     cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
    966     glyph->fAdvanceX =  CGToFloat(cgAdvance.width);
    967     glyph->fAdvanceY = -CGToFloat(cgAdvance.height);
    968 
    969     // The following produces skBounds in SkGlyph units (pixels, y down),
    970     // or returns early if skBounds would be empty.
    971     SkRect skBounds;
    972 
    973     // Glyphs are always drawn from the horizontal origin. The caller must manually use the result
    974     // of CTFontGetVerticalTranslationsForGlyphs to calculate where to draw the glyph for vertical
    975     // glyphs. As a result, always get the horizontal bounds of a glyph and translate it if the
    976     // glyph is vertical. This avoids any diagreement between the various means of retrieving
    977     // vertical metrics.
    978     {
    979         // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
    980         CGRect cgBounds;
    981         CTFontGetBoundingRectsForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
    982                                         &cgGlyph, &cgBounds, 1);
    983         cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
    984 
    985         // BUG?
    986         // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
    987         // it should be empty. So, if we see a zero-advance, we check if it has an
    988         // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
    989         // is rare, so we won't incur a big performance cost for this extra check.
    990         if (0 == cgAdvance.width && 0 == cgAdvance.height) {
    991             UniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, nullptr));
    992             if (!path || CGPathIsEmpty(path.get())) {
    993                 return;
    994             }
    995         }
    996 
    997         if (CGRectIsEmpty_inline(cgBounds)) {
    998             return;
    999         }
   1000 
   1001         // Convert cgBounds to SkGlyph units (pixels, y down).
   1002         skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
   1003                                     cgBounds.size.width, cgBounds.size.height);
   1004     }
   1005 
   1006     if (fVertical) {
   1007         // Due to possible vertical bounds bugs and simplicity, skBounds is the horizontal bounds.
   1008         // Convert these horizontal bounds into vertical bounds.
   1009         SkPoint offset;
   1010         this->getVerticalOffset(cgGlyph, &offset);
   1011         skBounds.offset(offset);
   1012     }
   1013 
   1014     // Currently the bounds are based on being rendered at (0,0).
   1015     // The top left must not move, since that is the base from which subpixel positioning is offset.
   1016     if (fDoSubPosition) {
   1017         skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
   1018         skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
   1019     }
   1020 
   1021     SkIRect skIBounds;
   1022     skBounds.roundOut(&skIBounds);
   1023     // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
   1024     // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
   1025     // is not currently known, as CG dilates the outlines by some percentage.
   1026     // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
   1027     skIBounds.outset(1, 1);
   1028     glyph->fLeft = SkToS16(skIBounds.fLeft);
   1029     glyph->fTop = SkToS16(skIBounds.fTop);
   1030     glyph->fWidth = SkToU16(skIBounds.width());
   1031     glyph->fHeight = SkToU16(skIBounds.height());
   1032 }
   1033 
   1034 #include "SkColorPriv.h"
   1035 
   1036 static void build_power_table(uint8_t table[]) {
   1037     for (int i = 0; i < 256; i++) {
   1038         float x = i / 255.f;
   1039         int xx = SkScalarRoundToInt(x * x * 255);
   1040         table[i] = SkToU8(xx);
   1041     }
   1042 }
   1043 
   1044 /**
   1045  *  This will invert the gamma applied by CoreGraphics, so we can get linear
   1046  *  values.
   1047  *
   1048  *  CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
   1049  *  The color space used does not appear to affect this choice.
   1050  */
   1051 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() {
   1052     static bool gInited;
   1053     static uint8_t gTableCoreGraphicsSmoothing[256];
   1054     if (!gInited) {
   1055         build_power_table(gTableCoreGraphicsSmoothing);
   1056         gInited = true;
   1057     }
   1058     return gTableCoreGraphicsSmoothing;
   1059 }
   1060 
   1061 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
   1062     while (count > 0) {
   1063         uint8_t mask = 0;
   1064         for (int i = 7; i >= 0; --i) {
   1065             mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i;
   1066             if (0 == --count) {
   1067                 break;
   1068             }
   1069         }
   1070         *dst++ = mask;
   1071     }
   1072 }
   1073 
   1074 template<bool APPLY_PREBLEND>
   1075 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
   1076     U8CPU r = 0xFF - ((rgb >> 16) & 0xFF);
   1077     U8CPU g = 0xFF - ((rgb >>  8) & 0xFF);
   1078     U8CPU b = 0xFF - ((rgb >>  0) & 0xFF);
   1079     U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1080 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1081     lum = SkTMax(lum, (U8CPU)0x30);
   1082 #endif
   1083     return lum;
   1084 }
   1085 template<bool APPLY_PREBLEND>
   1086 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
   1087                       const SkGlyph& glyph, const uint8_t* table8) {
   1088     const int width = glyph.fWidth;
   1089     size_t dstRB = glyph.rowBytes();
   1090     uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
   1091 
   1092     for (int y = 0; y < glyph.fHeight; y++) {
   1093         for (int i = 0; i < width; ++i) {
   1094             dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
   1095         }
   1096         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
   1097         dst = SkTAddOffset<uint8_t>(dst, dstRB);
   1098     }
   1099 }
   1100 
   1101 template<bool APPLY_PREBLEND>
   1102 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR,
   1103                                                     const uint8_t* tableG,
   1104                                                     const uint8_t* tableB) {
   1105     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
   1106     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  8) & 0xFF), tableG);
   1107     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  0) & 0xFF), tableB);
   1108 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1109     r = SkTMax(r, (U8CPU)0x30);
   1110     g = SkTMax(g, (U8CPU)0x30);
   1111     b = SkTMax(b, (U8CPU)0x30);
   1112 #endif
   1113     return SkPack888ToRGB16(r, g, b);
   1114 }
   1115 template<bool APPLY_PREBLEND>
   1116 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph,
   1117                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1118     const int width = glyph.fWidth;
   1119     size_t dstRB = glyph.rowBytes();
   1120     uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
   1121 
   1122     for (int y = 0; y < glyph.fHeight; y++) {
   1123         for (int i = 0; i < width; i++) {
   1124             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
   1125         }
   1126         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
   1127         dst = SkTAddOffset<uint16_t>(dst, dstRB);
   1128     }
   1129 }
   1130 
   1131 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
   1132     U8CPU a = (rgb >> 24) & 0xFF;
   1133     U8CPU r = (rgb >> 16) & 0xFF;
   1134     U8CPU g = (rgb >>  8) & 0xFF;
   1135     U8CPU b = (rgb >>  0) & 0xFF;
   1136 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1137     a = SkTMax(a, (U8CPU)0x30);
   1138 #endif
   1139     return SkPackARGB32(a, r, g, b);
   1140 }
   1141 
   1142 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
   1143     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
   1144 
   1145     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   1146     bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting;
   1147 
   1148     // Draw the glyph
   1149     size_t cgRowBytes;
   1150     CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD);
   1151     if (cgPixels == nullptr) {
   1152         return;
   1153     }
   1154 
   1155     // Fix the glyph
   1156     if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
   1157         (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD))
   1158     {
   1159         const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing();
   1160 
   1161         //Note that the following cannot really be integrated into the
   1162         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1163         //applying the pre-blend it means that a filter wants linear anyway.
   1164         //Other code may also be applying the pre-blend, so we'd need another
   1165         //one with this and one without.
   1166         CGRGBPixel* addr = cgPixels;
   1167         for (int y = 0; y < glyph.fHeight; ++y) {
   1168             for (int x = 0; x < glyph.fWidth; ++x) {
   1169                 int r = (addr[x] >> 16) & 0xFF;
   1170                 int g = (addr[x] >>  8) & 0xFF;
   1171                 int b = (addr[x] >>  0) & 0xFF;
   1172                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1173             }
   1174             addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
   1175         }
   1176     }
   1177 
   1178     // Convert glyph to mask
   1179     switch (glyph.fMaskFormat) {
   1180         case SkMask::kLCD16_Format: {
   1181             if (fPreBlend.isApplicable()) {
   1182                 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph,
   1183                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1184             } else {
   1185                 rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph,
   1186                                     fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1187             }
   1188         } break;
   1189         case SkMask::kA8_Format: {
   1190             if (fPreBlend.isApplicable()) {
   1191                 rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1192             } else {
   1193                 rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1194             }
   1195         } break;
   1196         case SkMask::kBW_Format: {
   1197             const int width = glyph.fWidth;
   1198             size_t dstRB = glyph.rowBytes();
   1199             uint8_t* dst = (uint8_t*)glyph.fImage;
   1200             for (int y = 0; y < glyph.fHeight; y++) {
   1201                 cgpixels_to_bits(dst, cgPixels, width);
   1202                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
   1203                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
   1204             }
   1205         } break;
   1206         case SkMask::kARGB32_Format: {
   1207             const int width = glyph.fWidth;
   1208             size_t dstRB = glyph.rowBytes();
   1209             SkPMColor* dst = (SkPMColor*)glyph.fImage;
   1210             for (int y = 0; y < glyph.fHeight; y++) {
   1211                 for (int x = 0; x < width; ++x) {
   1212                     dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
   1213                 }
   1214                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
   1215                 dst = SkTAddOffset<SkPMColor>(dst, dstRB);
   1216             }
   1217         } break;
   1218         default:
   1219             SkDEBUGFAIL("unexpected mask format");
   1220             break;
   1221     }
   1222 }
   1223 
   1224 /*
   1225  *  Our subpixel resolution is only 2 bits in each direction, so a scale of 4
   1226  *  seems sufficient, and possibly even correct, to allow the hinted outline
   1227  *  to be subpixel positioned.
   1228  */
   1229 #define kScaleForSubPixelPositionHinting (4.0f)
   1230 
   1231 void SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
   1232     AUTO_CG_LOCK();
   1233 
   1234     SkScalar scaleX = SK_Scalar1;
   1235     SkScalar scaleY = SK_Scalar1;
   1236 
   1237     CGAffineTransform xform = fTransform;
   1238     /*
   1239      *  For subpixel positioning, we want to return an unhinted outline, so it
   1240      *  can be positioned nicely at fractional offsets. However, we special-case
   1241      *  if the baseline of the (horizontal) text is axis-aligned. In those cases
   1242      *  we want to retain hinting in the direction orthogonal to the baseline.
   1243      *  e.g. for horizontal baseline, we want to retain hinting in Y.
   1244      *  The way we remove hinting is to scale the font by some value (4) in that
   1245      *  direction, ask for the path, and then scale the path back down.
   1246      */
   1247     if (fDoSubPosition) {
   1248         // start out by assuming that we want no hining in X and Y
   1249         scaleX = scaleY = kScaleForSubPixelPositionHinting;
   1250         // now see if we need to restore hinting for axis-aligned baselines
   1251         switch (this->computeAxisAlignmentForHText()) {
   1252             case kX_SkAxisAlignment:
   1253                 scaleY = SK_Scalar1; // want hinting in the Y direction
   1254                 break;
   1255             case kY_SkAxisAlignment:
   1256                 scaleX = SK_Scalar1; // want hinting in the X direction
   1257                 break;
   1258             default:
   1259                 break;
   1260         }
   1261 
   1262         CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY)));
   1263         xform = CGAffineTransformConcat(fTransform, scale);
   1264     }
   1265 
   1266     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph);
   1267     UniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
   1268 
   1269     path->reset();
   1270     if (cgPath != nullptr) {
   1271         CGPathApply(cgPath.get(), path, SkScalerContext_Mac::CTPathElement);
   1272     }
   1273 
   1274     if (fDoSubPosition) {
   1275         SkMatrix m;
   1276         m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
   1277         path->transform(m);
   1278     }
   1279     if (fVertical) {
   1280         SkPoint offset;
   1281         getVerticalOffset(cgGlyph, &offset);
   1282         path->offset(offset.fX, offset.fY);
   1283     }
   1284 }
   1285 
   1286 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) {
   1287     if (nullptr == metrics) {
   1288         return;
   1289     }
   1290 
   1291     AUTO_CG_LOCK();
   1292 
   1293     CGRect theBounds = CTFontGetBoundingBox(fCTFont.get());
   1294 
   1295     metrics->fTop          = CGToScalar(-CGRectGetMaxY_inline(theBounds));
   1296     metrics->fAscent       = CGToScalar(-CTFontGetAscent(fCTFont.get()));
   1297     metrics->fDescent      = CGToScalar( CTFontGetDescent(fCTFont.get()));
   1298     metrics->fBottom       = CGToScalar(-CGRectGetMinY_inline(theBounds));
   1299     metrics->fLeading      = CGToScalar( CTFontGetLeading(fCTFont.get()));
   1300     metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
   1301     metrics->fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
   1302     metrics->fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
   1303     metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
   1304     metrics->fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont.get()));
   1305     metrics->fCapHeight    = CGToScalar( CTFontGetCapHeight(fCTFont.get()));
   1306     metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont.get()));
   1307     metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont.get()));
   1308 
   1309     metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag;
   1310     metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1311 
   1312     // See https://bugs.chromium.org/p/skia/issues/detail?id=6203
   1313     // At least on 10.12.3 with memory based fonts the x-height is always 0.6666 of the ascent and
   1314     // the cap-height is always 0.8888 of the ascent. It appears that the values from the 'OS/2'
   1315     // table are read, but then overwritten if the font is not a system font. As a result, if there
   1316     // is a valid 'OS/2' table available use the values from the table if they aren't too strange.
   1317     struct OS2HeightMetrics {
   1318         SK_OT_SHORT sxHeight;
   1319         SK_OT_SHORT sCapHeight;
   1320     } heights;
   1321     size_t bytesRead = this->getTypeface()->getTableData(
   1322             SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2, version.v2.sxHeight),
   1323             sizeof(heights), &heights);
   1324     if (bytesRead == sizeof(heights)) {
   1325         // 'fontSize' is correct because the entire resolved size is set by the constructor.
   1326         CGFloat fontSize = CTFontGetSize(this->fCTFont.get());
   1327         unsigned upem = CTFontGetUnitsPerEm(this->fCTFont.get());
   1328         unsigned maxSaneHeight = upem * 2;
   1329         uint16_t xHeight = SkEndian_SwapBE16(heights.sxHeight);
   1330         if (xHeight && xHeight < maxSaneHeight) {
   1331             metrics->fXHeight = CGToScalar(xHeight * fontSize / upem);
   1332         }
   1333         uint16_t capHeight = SkEndian_SwapBE16(heights.sCapHeight);
   1334         if (capHeight && capHeight < maxSaneHeight) {
   1335             metrics->fCapHeight = CGToScalar(capHeight * fontSize / upem);
   1336         }
   1337     }
   1338 }
   1339 
   1340 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) {
   1341     SkPath* skPath = (SkPath*)info;
   1342 
   1343     // Process the path element
   1344     switch (element->type) {
   1345         case kCGPathElementMoveToPoint:
   1346             skPath->moveTo(element->points[0].x, -element->points[0].y);
   1347             break;
   1348 
   1349         case kCGPathElementAddLineToPoint:
   1350             skPath->lineTo(element->points[0].x, -element->points[0].y);
   1351             break;
   1352 
   1353         case kCGPathElementAddQuadCurveToPoint:
   1354             skPath->quadTo(element->points[0].x, -element->points[0].y,
   1355                            element->points[1].x, -element->points[1].y);
   1356             break;
   1357 
   1358         case kCGPathElementAddCurveToPoint:
   1359             skPath->cubicTo(element->points[0].x, -element->points[0].y,
   1360                             element->points[1].x, -element->points[1].y,
   1361                             element->points[2].x, -element->points[2].y);
   1362             break;
   1363 
   1364         case kCGPathElementCloseSubpath:
   1365             skPath->close();
   1366             break;
   1367 
   1368         default:
   1369             SkDEBUGFAIL("Unknown path element!");
   1370             break;
   1371         }
   1372 }
   1373 
   1374 
   1375 ///////////////////////////////////////////////////////////////////////////////
   1376 
   1377 // Returns nullptr on failure
   1378 // Call must still manage its ownership of provider
   1379 static SkTypeface* create_from_dataProvider(UniqueCFRef<CGDataProviderRef> provider, int ttcIndex) {
   1380     if (ttcIndex != 0) {
   1381         return nullptr;
   1382     }
   1383     UniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
   1384     if (!cg) {
   1385         return nullptr;
   1386     }
   1387     UniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg.get(), 0, nullptr, nullptr));
   1388     if (!ct) {
   1389         return nullptr;
   1390     }
   1391     return create_from_CTFontRef(std::move(ct), nullptr, true);
   1392 }
   1393 
   1394 // Web fonts added to the CTFont registry do not return their character set.
   1395 // Iterate through the font in this case. The existing caller caches the result,
   1396 // so the performance impact isn't too bad.
   1397 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
   1398                                            SkTDArray<SkUnichar>* glyphToUnicode) {
   1399     glyphToUnicode->setCount(SkToInt(glyphCount));
   1400     SkUnichar* out = glyphToUnicode->begin();
   1401     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1402     UniChar unichar = 0;
   1403     while (glyphCount > 0) {
   1404         CGGlyph glyph;
   1405         if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1406             out[glyph] = unichar;
   1407             --glyphCount;
   1408         }
   1409         if (++unichar == 0) {
   1410             break;
   1411         }
   1412     }
   1413 }
   1414 
   1415 // Construct Glyph to Unicode table.
   1416 // Unicode code points that require conjugate pairs in utf16 are not
   1417 // supported.
   1418 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
   1419                                       SkTDArray<SkUnichar>* glyphToUnicode) {
   1420     UniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
   1421     if (!charSet) {
   1422         populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
   1423         return;
   1424     }
   1425 
   1426     UniqueCFRef<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(nullptr, charSet.get()));
   1427     if (!bitmap) {
   1428         return;
   1429     }
   1430     CFIndex length = CFDataGetLength(bitmap.get());
   1431     if (!length) {
   1432         return;
   1433     }
   1434     if (length > 8192) {
   1435         // TODO: Add support for Unicode above 0xFFFF
   1436         // Consider only the BMP portion of the Unicode character points.
   1437         // The bitmap may contain other planes, up to plane 16.
   1438         // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html
   1439         length = 8192;
   1440     }
   1441     const UInt8* bits = CFDataGetBytePtr(bitmap.get());
   1442     glyphToUnicode->setCount(SkToInt(glyphCount));
   1443     SkUnichar* out = glyphToUnicode->begin();
   1444     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1445     for (int i = 0; i < length; i++) {
   1446         int mask = bits[i];
   1447         if (!mask) {
   1448             continue;
   1449         }
   1450         for (int j = 0; j < 8; j++) {
   1451             CGGlyph glyph;
   1452             UniChar unichar = static_cast<UniChar>((i << 3) + j);
   1453             if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1454                 out[glyph] = unichar;
   1455             }
   1456         }
   1457     }
   1458 }
   1459 
   1460 /** Assumes src and dst are not nullptr. */
   1461 static void CFStringToSkString(CFStringRef src, SkString* dst) {
   1462     // Reserve enough room for the worst-case string,
   1463     // plus 1 byte for the trailing null.
   1464     CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
   1465                                                        kCFStringEncodingUTF8) + 1;
   1466     dst->resize(length);
   1467     CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
   1468     // Resize to the actual UTF-8 length used, stripping the null character.
   1469     dst->resize(strlen(dst->c_str()));
   1470 }
   1471 
   1472 SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
   1473         PerGlyphInfo perGlyphInfo,
   1474         const uint32_t* glyphIDs,
   1475         uint32_t glyphIDsCount) const {
   1476 
   1477     AUTO_CG_LOCK();
   1478 
   1479     UniqueCFRef<CTFontRef> ctFont =
   1480             ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr);
   1481 
   1482     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
   1483 
   1484     {
   1485         UniqueCFRef<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont.get()));
   1486         if (fontName.get()) {
   1487             CFStringToSkString(fontName.get(), &info->fFontName);
   1488         }
   1489     }
   1490 
   1491     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
   1492     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
   1493     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
   1494     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
   1495     UniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont.get(), nullptr));
   1496     if (cgFont) {
   1497         UniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
   1498         if (cgAxes && CFArrayGetCount(cgAxes.get()) > 0) {
   1499             info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
   1500         }
   1501     }
   1502 
   1503     CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get());
   1504 
   1505     if (perGlyphInfo & kToUnicode_PerGlyphInfo) {
   1506         populate_glyph_to_unicode(ctFont.get(), glyphCount, &info->fGlyphToUnicode);
   1507     }
   1508 
   1509     // If it's not a truetype font, mark it as 'other'. Assume that TrueType
   1510     // fonts always have both glyf and loca tables. At the least, this is what
   1511     // sfntly needs to subset the font. CTFontCopyAttribute() does not always
   1512     // succeed in determining this directly.
   1513     if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
   1514         return info;
   1515     }
   1516 
   1517     info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1518     CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont.get());
   1519     if (symbolicTraits & kCTFontMonoSpaceTrait) {
   1520         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1521     }
   1522     if (symbolicTraits & kCTFontItalicTrait) {
   1523         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1524     }
   1525     CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
   1526     if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
   1527         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1528     } else if (stylisticClass & kCTFontScriptsClass) {
   1529         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1530     }
   1531     info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont.get());
   1532     info->fAscent = (int16_t) CTFontGetAscent(ctFont.get());
   1533     info->fDescent = (int16_t) CTFontGetDescent(ctFont.get());
   1534     info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont.get());
   1535     CGRect bbox = CTFontGetBoundingBox(ctFont.get());
   1536 
   1537     SkRect r;
   1538     r.set( CGToScalar(CGRectGetMinX_inline(bbox)),   // Left
   1539            CGToScalar(CGRectGetMaxY_inline(bbox)),   // Top
   1540            CGToScalar(CGRectGetMaxX_inline(bbox)),   // Right
   1541            CGToScalar(CGRectGetMinY_inline(bbox)));  // Bottom
   1542 
   1543     r.roundOut(&(info->fBBox));
   1544 
   1545     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1546     // This probably isn't very good with an italic font.
   1547     int16_t min_width = SHRT_MAX;
   1548     info->fStemV = 0;
   1549     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
   1550     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
   1551     CGGlyph glyphs[count];
   1552     CGRect boundingRects[count];
   1553     if (CTFontGetGlyphsForCharacters(ctFont.get(), stem_chars, glyphs, count)) {
   1554         CTFontGetBoundingRectsForGlyphs(ctFont.get(), kCTFontOrientationHorizontal,
   1555                                         glyphs, boundingRects, count);
   1556         for (size_t i = 0; i < count; i++) {
   1557             int16_t width = (int16_t) boundingRects[i].size.width;
   1558             if (width > 0 && width < min_width) {
   1559                 min_width = width;
   1560                 info->fStemV = min_width;
   1561             }
   1562         }
   1563     }
   1564     return info;
   1565 }
   1566 
   1567 ///////////////////////////////////////////////////////////////////////////////
   1568 
   1569 static SK_SFNT_ULONG get_font_type_tag(const SkTypeface_Mac* typeface) {
   1570     CTFontRef ctFont = typeface->fFontRef.get();
   1571     UniqueCFRef<CFNumberRef> fontFormatRef(
   1572             static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
   1573     if (!fontFormatRef) {
   1574         return 0;
   1575     }
   1576 
   1577     SInt32 fontFormatValue;
   1578     if (!CFNumberGetValue(fontFormatRef.get(), kCFNumberSInt32Type, &fontFormatValue)) {
   1579         return 0;
   1580     }
   1581 
   1582     switch (fontFormatValue) {
   1583         case kCTFontFormatOpenTypePostScript:
   1584             return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
   1585         case kCTFontFormatOpenTypeTrueType:
   1586             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1587         case kCTFontFormatTrueType:
   1588             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1589         case kCTFontFormatPostScript:
   1590             return SkSFNTHeader::fontType_PostScript::TAG;
   1591         case kCTFontFormatBitmap:
   1592             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1593         case kCTFontFormatUnrecognized:
   1594         default:
   1595             //CT seems to be unreliable in being able to obtain the type,
   1596             //even if all we want is the first four bytes of the font resource.
   1597             //Just the presence of the FontForge 'FFTM' table seems to throw it off.
   1598             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1599     }
   1600 }
   1601 
   1602 SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
   1603     SK_SFNT_ULONG fontType = get_font_type_tag(this);
   1604     if (0 == fontType) {
   1605         return nullptr;
   1606     }
   1607 
   1608     // get table tags
   1609     int numTables = this->countTables();
   1610     SkTDArray<SkFontTableTag> tableTags;
   1611     tableTags.setCount(numTables);
   1612     this->getTableTags(tableTags.begin());
   1613 
   1614     // calc total size for font, save sizes
   1615     SkTDArray<size_t> tableSizes;
   1616     size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1617     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1618         size_t tableSize = this->getTableSize(tableTags[tableIndex]);
   1619         totalSize += (tableSize + 3) & ~3;
   1620         *tableSizes.append() = tableSize;
   1621     }
   1622 
   1623     // reserve memory for stream, and zero it (tables must be zero padded)
   1624     SkMemoryStream* stream = new SkMemoryStream(totalSize);
   1625     char* dataStart = (char*)stream->getMemoryBase();
   1626     sk_bzero(dataStart, totalSize);
   1627     char* dataPtr = dataStart;
   1628 
   1629     // compute font header entries
   1630     uint16_t entrySelector = 0;
   1631     uint16_t searchRange = 1;
   1632     while (searchRange < numTables >> 1) {
   1633         entrySelector++;
   1634         searchRange <<= 1;
   1635     }
   1636     searchRange <<= 4;
   1637     uint16_t rangeShift = (numTables << 4) - searchRange;
   1638 
   1639     // write font header
   1640     SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
   1641     header->fontType = fontType;
   1642     header->numTables = SkEndian_SwapBE16(numTables);
   1643     header->searchRange = SkEndian_SwapBE16(searchRange);
   1644     header->entrySelector = SkEndian_SwapBE16(entrySelector);
   1645     header->rangeShift = SkEndian_SwapBE16(rangeShift);
   1646     dataPtr += sizeof(SkSFNTHeader);
   1647 
   1648     // write tables
   1649     SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
   1650     dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1651     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1652         size_t tableSize = tableSizes[tableIndex];
   1653         this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
   1654         entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
   1655         entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
   1656                                                                          tableSize));
   1657         entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
   1658         entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
   1659 
   1660         dataPtr += (tableSize + 3) & ~3;
   1661         ++entry;
   1662     }
   1663 
   1664     *ttcIndex = 0;
   1665     return stream;
   1666 }
   1667 
   1668 struct NonDefaultAxesContext {
   1669     SkFixed* axisValue;
   1670     CFArrayRef cgAxes;
   1671 };
   1672 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
   1673     NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
   1674 
   1675     if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) {
   1676         return;
   1677     }
   1678 
   1679     // The key is a CFString which is a string from the 'name' table.
   1680     // Search the cgAxes for an axis with this name, and use its index to store the value.
   1681     CFIndex keyIndex = -1;
   1682     CFStringRef keyString = static_cast<CFStringRef>(key);
   1683     for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
   1684         CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
   1685         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
   1686             continue;
   1687         }
   1688 
   1689         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
   1690         CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
   1691         if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
   1692             continue;
   1693         }
   1694         CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
   1695         if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
   1696             keyIndex = i;
   1697             break;
   1698         }
   1699     }
   1700     if (keyIndex == -1) {
   1701         return;
   1702     }
   1703 
   1704     CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
   1705     double valueDouble;
   1706     if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
   1707         valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble)
   1708     {
   1709         return;
   1710     }
   1711     self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
   1712 }
   1713 static bool get_variations(CTFontRef ctFont, CFIndex* cgAxisCount,
   1714                            SkAutoSTMalloc<4, SkFixed>* axisValues)
   1715 {
   1716     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
   1717     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
   1718     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
   1719     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
   1720     UniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
   1721     if (!cgFont) {
   1722         return false;
   1723     }
   1724 
   1725     UniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
   1726     // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict).
   1727     if (!cgVariations) {
   1728         return false;
   1729     }
   1730 
   1731     UniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
   1732     if (!cgAxes) {
   1733         return false;
   1734     }
   1735     *cgAxisCount = CFArrayGetCount(cgAxes.get());
   1736     axisValues->reset(*cgAxisCount);
   1737 
   1738     // Set all of the axes to their default values.
   1739     // Fail if any default value cannot be determined.
   1740     for (CFIndex i = 0; i < *cgAxisCount; ++i) {
   1741         CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes.get(), i);
   1742         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
   1743             return false;
   1744         }
   1745 
   1746         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
   1747         CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
   1748                                                           kCGFontVariationAxisDefaultValue);
   1749         if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
   1750             return false;
   1751         }
   1752         CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
   1753         double axisDefaultValueDouble;
   1754         if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble))
   1755         {
   1756             return false;
   1757         }
   1758         if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
   1759                                      SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
   1760         {
   1761             return false;
   1762         }
   1763         (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
   1764     }
   1765 
   1766     // Override the default values with the given font's stated axis values.
   1767     NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
   1768     CFDictionaryApplyFunction(cgVariations.get(), set_non_default_axes, &c);
   1769 
   1770     return true;
   1771 }
   1772 std::unique_ptr<SkFontData> SkTypeface_Mac::onMakeFontData() const {
   1773     int index;
   1774     std::unique_ptr<SkStreamAsset> stream(this->onOpenStream(&index));
   1775 
   1776     CFIndex cgAxisCount;
   1777     SkAutoSTMalloc<4, SkFixed> axisValues;
   1778     if (get_variations(fFontRef.get(), &cgAxisCount, &axisValues)) {
   1779         return skstd::make_unique<SkFontData>(std::move(stream), index,
   1780                                               axisValues.get(), cgAxisCount);
   1781     }
   1782     return skstd::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
   1783 }
   1784 
   1785 /** Creates a CT variation dictionary {tag, value} from a CG variation dictionary {name, value}. */
   1786 static UniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
   1787                                                                    CFArrayRef ctAxes) {
   1788 
   1789     UniqueCFRef<CFMutableDictionaryRef> ctVariations(
   1790             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
   1791                                       &kCFTypeDictionaryKeyCallBacks,
   1792                                       &kCFTypeDictionaryValueCallBacks));
   1793 
   1794     CFIndex axisCount = CFArrayGetCount(ctAxes);
   1795     for (CFIndex i = 0; i < axisCount; ++i) {
   1796         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes, i);
   1797         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
   1798             return nullptr;
   1799         }
   1800         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
   1801 
   1802         // The assumption is that values produced by kCTFontVariationAxisNameKey and
   1803         // kCGFontVariationAxisName will always be equal.
   1804         CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
   1805         if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
   1806             return nullptr;
   1807         }
   1808 
   1809         CFTypeRef axisValue = CFDictionaryGetValue(cgVariations, axisName);
   1810         if (!axisValue || CFGetTypeID(axisValue) != CFNumberGetTypeID()) {
   1811             return nullptr;
   1812         }
   1813 
   1814         CFTypeRef axisTag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
   1815         if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
   1816             return nullptr;
   1817         }
   1818 
   1819         CFDictionaryAddValue(ctVariations.get(), axisTag, axisValue);
   1820     }
   1821     return std::move(ctVariations);
   1822 }
   1823 
   1824 int SkTypeface_Mac::onGetVariationDesignPosition(
   1825         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
   1826 {
   1827     // The CGFont variation data does not contain the tag.
   1828 
   1829     // This call always returns nullptr on 10.10 and under for CGFontCreateWithDataProvider fonts.
   1830     // When this happens, there is no API to provide the tag.
   1831     UniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
   1832     if (!ctAxes) {
   1833         return -1;
   1834     }
   1835     CFIndex axisCount = CFArrayGetCount(ctAxes.get());
   1836     if (!coordinates || coordinateCount < axisCount) {
   1837         return axisCount;
   1838     }
   1839 
   1840     // This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
   1841     // When this happens, try converting the CG variation to a CT variation.
   1842     // On 10.12 and later, this only returns non-default variations.
   1843     UniqueCFRef<CFDictionaryRef> ctVariations(CTFontCopyVariation(fFontRef.get()));
   1844     if (!ctVariations) {
   1845         // When 10.11 and earlier are no longer supported, the following code can be replaced with
   1846         // return -1 and ct_variation_from_cg_variation can be removed.
   1847         UniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
   1848         if (!cgFont) {
   1849             return -1;
   1850         }
   1851         UniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
   1852         if (!cgVariations) {
   1853             return -1;
   1854         }
   1855         ctVariations = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
   1856         if (!ctVariations) {
   1857             return -1;
   1858         }
   1859     }
   1860 
   1861     for (int i = 0; i < axisCount; ++i) {
   1862         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
   1863         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
   1864             return -1;
   1865         }
   1866         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
   1867 
   1868         CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
   1869         if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
   1870             return -1;
   1871         }
   1872         CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
   1873         int64_t tagLong;
   1874         if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
   1875             return -1;
   1876         }
   1877         coordinates[i].axis = tagLong;
   1878 
   1879         CGFloat variationCGFloat;
   1880         CFTypeRef variationValue = CFDictionaryGetValue(ctVariations.get(), tagNumber);
   1881         if (variationValue) {
   1882             if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
   1883                 return -1;
   1884             }
   1885             CFNumberRef variationNumber = static_cast<CFNumberRef>(variationValue);
   1886             if (!CFNumberGetValue(variationNumber, kCFNumberCGFloatType, &variationCGFloat)) {
   1887                 return -1;
   1888             }
   1889         } else {
   1890             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
   1891             if (!def || CFGetTypeID(def) != CFNumberGetTypeID()) {
   1892                 return -1;
   1893             }
   1894             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
   1895             if (!CFNumberGetValue(defNumber, kCFNumberCGFloatType, &variationCGFloat)) {
   1896                 return -1;
   1897             }
   1898         }
   1899         coordinates[i].value = CGToScalar(variationCGFloat);
   1900 
   1901     }
   1902     return axisCount;
   1903 }
   1904 
   1905 ///////////////////////////////////////////////////////////////////////////////
   1906 ///////////////////////////////////////////////////////////////////////////////
   1907 
   1908 int SkTypeface_Mac::onGetUPEM() const {
   1909     UniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
   1910     return CGFontGetUnitsPerEm(cgFont.get());
   1911 }
   1912 
   1913 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
   1914     SkTypeface::LocalizedStrings* nameIter =
   1915             SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
   1916     if (nullptr == nameIter) {
   1917         CFStringRef cfLanguageRaw;
   1918         UniqueCFRef<CFStringRef> cfFamilyName(
   1919                 CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
   1920         UniqueCFRef<CFStringRef> cfLanguage(cfLanguageRaw);
   1921 
   1922         SkString skLanguage;
   1923         SkString skFamilyName;
   1924         if (cfLanguage) {
   1925             CFStringToSkString(cfLanguage.get(), &skLanguage);
   1926         } else {
   1927             skLanguage = "und"; //undetermined
   1928         }
   1929         if (cfFamilyName) {
   1930             CFStringToSkString(cfFamilyName.get(), &skFamilyName);
   1931         }
   1932 
   1933         nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage);
   1934     }
   1935     return nameIter;
   1936 }
   1937 
   1938 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
   1939     UniqueCFRef<CFArrayRef> cfArray(
   1940             CTFontCopyAvailableTables(fFontRef.get(), kCTFontTableOptionNoOptions));
   1941     if (!cfArray) {
   1942         return 0;
   1943     }
   1944     int count = SkToInt(CFArrayGetCount(cfArray.get()));
   1945     if (tags) {
   1946         for (int i = 0; i < count; ++i) {
   1947             uintptr_t fontTag = reinterpret_cast<uintptr_t>(
   1948                 CFArrayGetValueAtIndex(cfArray.get(), i));
   1949             tags[i] = static_cast<SkFontTableTag>(fontTag);
   1950         }
   1951     }
   1952     return count;
   1953 }
   1954 
   1955 // If, as is the case with web fonts, the CTFont data isn't available,
   1956 // the CGFont data may work. While the CGFont may always provide the
   1957 // right result, leave the CTFont code path to minimize disruption.
   1958 static UniqueCFRef<CFDataRef> copy_table_from_font(CTFontRef ctFont, SkFontTableTag tag) {
   1959     UniqueCFRef<CFDataRef> data(CTFontCopyTable(ctFont, (CTFontTableTag) tag,
   1960                                                 kCTFontTableOptionNoOptions));
   1961     if (!data) {
   1962         UniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
   1963         data.reset(CGFontCopyTableForTag(cgFont.get(), tag));
   1964     }
   1965     return data;
   1966 }
   1967 
   1968 size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
   1969                                       size_t length, void* dstData) const {
   1970     UniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
   1971     if (!srcData) {
   1972         return 0;
   1973     }
   1974 
   1975     size_t srcSize = CFDataGetLength(srcData.get());
   1976     if (offset >= srcSize) {
   1977         return 0;
   1978     }
   1979     if (length > srcSize - offset) {
   1980         length = srcSize - offset;
   1981     }
   1982     if (dstData) {
   1983         memcpy(dstData, CFDataGetBytePtr(srcData.get()) + offset, length);
   1984     }
   1985     return length;
   1986 }
   1987 
   1988 SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkScalerContextEffects& effects,
   1989                                                        const SkDescriptor* desc) const {
   1990     return new SkScalerContext_Mac(sk_ref_sp(const_cast<SkTypeface_Mac*>(this)), effects, desc);
   1991 }
   1992 
   1993 void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
   1994     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
   1995         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
   1996     {
   1997         rec->fMaskFormat = SkMask::kA8_Format;
   1998         // Render the glyphs as close as possible to what was requested.
   1999         // The above turns off subpixel rendering, but the user requested it.
   2000         // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
   2001         // See comments below for more details.
   2002         rec->setHinting(SkPaint::kNormal_Hinting);
   2003     }
   2004 
   2005     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag  |
   2006                                   SkScalerContext::kForceAutohinting_Flag  |
   2007                                   SkScalerContext::kLCD_BGROrder_Flag |
   2008                                   SkScalerContext::kLCD_Vertical_Flag;
   2009 
   2010     rec->fFlags &= ~flagsWeDontSupport;
   2011 
   2012     bool lcdSupport = supports_LCD();
   2013 
   2014     // Only two levels of hinting are supported.
   2015     // kNo_Hinting means avoid CoreGraphics outline dilation.
   2016     // kNormal_Hinting means CoreGraphics outline dilation is allowed.
   2017     // If there is no lcd support, hinting (dilation) cannot be supported.
   2018     SkPaint::Hinting hinting = rec->getHinting();
   2019     if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) {
   2020         hinting = SkPaint::kNo_Hinting;
   2021     } else if (SkPaint::kFull_Hinting == hinting) {
   2022         hinting = SkPaint::kNormal_Hinting;
   2023     }
   2024     rec->setHinting(hinting);
   2025 
   2026     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   2027     // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
   2028     // There is no current means to honor a request for unhinted lcd,
   2029     // so arbitrarilly ignore the hinting request and honor lcd.
   2030 
   2031     // Hinting and smoothing should be orthogonal, but currently they are not.
   2032     // CoreGraphics has no API to influence hinting. However, its lcd smoothed
   2033     // output is drawn from auto-dilated outlines (the amount of which is
   2034     // determined by AppleFontSmoothing). Its regular anti-aliased output is
   2035     // drawn from un-dilated outlines.
   2036 
   2037     // The behavior of Skia is as follows:
   2038     // [AA][no-hint]: generate AA using CoreGraphic's AA output.
   2039     // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
   2040     // channel. This matches [LCD][yes-hint] in weight.
   2041     // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
   2042     // Currenly side with LCD, effectively ignoring the hinting setting.
   2043     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
   2044 
   2045     if (rec->fMaskFormat == SkMask::kLCD16_Format) {
   2046         if (lcdSupport) {
   2047             //CoreGraphics creates 555 masks for smoothed text anyway.
   2048             rec->fMaskFormat = SkMask::kLCD16_Format;
   2049             rec->setHinting(SkPaint::kNormal_Hinting);
   2050         } else {
   2051             rec->fMaskFormat = SkMask::kA8_Format;
   2052         }
   2053     }
   2054 
   2055     // CoreText provides no information as to whether a glyph will be color or not.
   2056     // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
   2057     // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
   2058     if (fHasColorGlyphs) {
   2059         rec->fMaskFormat = SkMask::kARGB32_Format;
   2060     }
   2061 
   2062     // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
   2063     // All other masks can use regular gamma.
   2064     if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) {
   2065 #ifndef SK_GAMMA_APPLY_TO_A8
   2066         // SRGBTODO: Is this correct? Do we want contrast boost?
   2067         rec->ignorePreBlend();
   2068 #endif
   2069     } else {
   2070         //CoreGraphics dialates smoothed text as needed.
   2071         rec->setContrast(0);
   2072     }
   2073 }
   2074 
   2075 /** Takes ownership of the CFStringRef. */
   2076 static const char* get_str(CFStringRef ref, SkString* str) {
   2077     if (nullptr == ref) {
   2078         return nullptr;
   2079     }
   2080     CFStringToSkString(ref, str);
   2081     CFRelease(ref);
   2082     return str->c_str();
   2083 }
   2084 
   2085 void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
   2086     get_str(CTFontCopyFamilyName(fFontRef.get()), familyName);
   2087 }
   2088 
   2089 void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
   2090                                          bool* isLocalStream) const {
   2091     SkString tmpStr;
   2092 
   2093     desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef.get()), &tmpStr));
   2094     desc->setFullName(get_str(CTFontCopyFullName(fFontRef.get()), &tmpStr));
   2095     desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef.get()), &tmpStr));
   2096     desc->setStyle(this->fontStyle());
   2097     *isLocalStream = fIsLocalStream;
   2098 }
   2099 
   2100 int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding,
   2101                                     uint16_t glyphs[], int glyphCount) const
   2102 {
   2103     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
   2104     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
   2105     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
   2106 
   2107     SkAutoSTMalloc<1024, UniChar> charStorage;
   2108     const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
   2109     int srcCount;
   2110     switch (encoding) {
   2111         case kUTF8_Encoding: {
   2112             const char* utf8 = reinterpret_cast<const char*>(chars);
   2113             UniChar* utf16 = charStorage.reset(2 * glyphCount);
   2114             src = utf16;
   2115             for (int i = 0; i < glyphCount; ++i) {
   2116                 SkUnichar uni = SkUTF8_NextUnichar(&utf8);
   2117                 utf16 += SkUTF16_FromUnichar(uni, utf16);
   2118             }
   2119             srcCount = SkToInt(utf16 - src);
   2120             break;
   2121         }
   2122         case kUTF16_Encoding: {
   2123             src = reinterpret_cast<const UniChar*>(chars);
   2124             int extra = 0;
   2125             for (int i = 0; i < glyphCount; ++i) {
   2126                 if (SkUTF16_IsHighSurrogate(src[i + extra])) {
   2127                     ++extra;
   2128                 }
   2129             }
   2130             srcCount = glyphCount + extra;
   2131             break;
   2132         }
   2133         case kUTF32_Encoding: {
   2134             const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(chars);
   2135             UniChar* utf16 = charStorage.reset(2 * glyphCount);
   2136             src = utf16;
   2137             for (int i = 0; i < glyphCount; ++i) {
   2138                 utf16 += SkUTF16_FromUnichar(utf32[i], utf16);
   2139             }
   2140             srcCount = SkToInt(utf16 - src);
   2141             break;
   2142         }
   2143     }
   2144 
   2145     // If glyphs is nullptr, CT still needs glyph storage for finding the first failure.
   2146     // Also, if there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
   2147     SkAutoSTMalloc<1024, uint16_t> glyphStorage;
   2148     uint16_t* macGlyphs = glyphs;
   2149     if (nullptr == macGlyphs || srcCount > glyphCount) {
   2150         macGlyphs = glyphStorage.reset(srcCount);
   2151     }
   2152 
   2153     bool allEncoded = CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount);
   2154 
   2155     // If there were any non-bmp, then copy and compact.
   2156     // If 'glyphs' is nullptr, then compact glyphStorage in-place.
   2157     // If all are bmp and 'glyphs' is non-nullptr, 'glyphs' already contains the compact glyphs.
   2158     // If some are non-bmp and 'glyphs' is non-nullptr, copy and compact into 'glyphs'.
   2159     uint16_t* compactedGlyphs = glyphs;
   2160     if (nullptr == compactedGlyphs) {
   2161         compactedGlyphs = macGlyphs;
   2162     }
   2163     if (srcCount > glyphCount) {
   2164         int extra = 0;
   2165         for (int i = 0; i < glyphCount; ++i) {
   2166             compactedGlyphs[i] = macGlyphs[i + extra];
   2167             if (SkUTF16_IsHighSurrogate(src[i + extra])) {
   2168                 ++extra;
   2169             }
   2170         }
   2171     }
   2172 
   2173     if (allEncoded) {
   2174         return glyphCount;
   2175     }
   2176 
   2177     // If we got false, then we need to manually look for first failure.
   2178     for (int i = 0; i < glyphCount; ++i) {
   2179         if (0 == compactedGlyphs[i]) {
   2180             return i;
   2181         }
   2182     }
   2183     // Odd to get here, as we expected CT to have returned true up front.
   2184     return glyphCount;
   2185 }
   2186 
   2187 int SkTypeface_Mac::onCountGlyphs() const {
   2188     return SkToInt(CTFontGetGlyphCount(fFontRef.get()));
   2189 }
   2190 
   2191 ///////////////////////////////////////////////////////////////////////////////
   2192 ///////////////////////////////////////////////////////////////////////////////
   2193 
   2194 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
   2195     UniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
   2196     if (!ref) {
   2197         return false;
   2198     }
   2199     CFStringToSkString(ref.get(), value);
   2200     return true;
   2201 }
   2202 
   2203 #include "SkFontMgr.h"
   2204 
   2205 static inline int sqr(int value) {
   2206     SkASSERT(SkAbs32(value) < 0x7FFF);  // check for overflow
   2207     return value * value;
   2208 }
   2209 
   2210 // We normalize each axis (weight, width, italic) to be base-900
   2211 static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
   2212     return sqr(a.weight() - b.weight()) +
   2213            sqr((a.width() - b.width()) * 100) +
   2214            sqr((a.slant() != b.slant()) * 900);
   2215 }
   2216 
   2217 class SkFontStyleSet_Mac : public SkFontStyleSet {
   2218 public:
   2219     SkFontStyleSet_Mac(CTFontDescriptorRef desc)
   2220         : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr))
   2221         , fCount(0)
   2222     {
   2223         if (!fArray) {
   2224             fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
   2225         }
   2226         fCount = SkToInt(CFArrayGetCount(fArray.get()));
   2227     }
   2228 
   2229     int count() override {
   2230         return fCount;
   2231     }
   2232 
   2233     void getStyle(int index, SkFontStyle* style, SkString* name) override {
   2234         SkASSERT((unsigned)index < (unsigned)fCount);
   2235         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
   2236         if (style) {
   2237             *style = fontstyle_from_descriptor(desc, false);
   2238         }
   2239         if (name) {
   2240             if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
   2241                 name->reset();
   2242             }
   2243         }
   2244     }
   2245 
   2246     SkTypeface* createTypeface(int index) override {
   2247         SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
   2248         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
   2249 
   2250         return create_from_desc(desc);
   2251     }
   2252 
   2253     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
   2254         if (0 == fCount) {
   2255             return nullptr;
   2256         }
   2257         return create_from_desc(findMatchingDesc(pattern));
   2258     }
   2259 
   2260 private:
   2261     UniqueCFRef<CFArrayRef> fArray;
   2262     int fCount;
   2263 
   2264     CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
   2265         int bestMetric = SK_MaxS32;
   2266         CTFontDescriptorRef bestDesc = nullptr;
   2267 
   2268         for (int i = 0; i < fCount; ++i) {
   2269             CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
   2270             int metric = compute_metric(pattern, fontstyle_from_descriptor(desc, false));
   2271             if (0 == metric) {
   2272                 return desc;
   2273             }
   2274             if (metric < bestMetric) {
   2275                 bestMetric = metric;
   2276                 bestDesc = desc;
   2277             }
   2278         }
   2279         SkASSERT(bestDesc);
   2280         return bestDesc;
   2281     }
   2282 };
   2283 
   2284 class SkFontMgr_Mac : public SkFontMgr {
   2285     UniqueCFRef<CFArrayRef> fNames;
   2286     int fCount;
   2287 
   2288     CFStringRef getFamilyNameAt(int index) const {
   2289         SkASSERT((unsigned)index < (unsigned)fCount);
   2290         return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
   2291     }
   2292 
   2293     static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
   2294         UniqueCFRef<CFMutableDictionaryRef> cfAttr(
   2295                  CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
   2296                                            &kCFTypeDictionaryKeyCallBacks,
   2297                                            &kCFTypeDictionaryValueCallBacks));
   2298 
   2299         CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
   2300 
   2301         UniqueCFRef<CTFontDescriptorRef> desc(
   2302                 CTFontDescriptorCreateWithAttributes(cfAttr.get()));
   2303         return new SkFontStyleSet_Mac(desc.get());
   2304     }
   2305 
   2306     /** CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
   2307      *  provide a wrapper here that will return an empty array if need be.
   2308      */
   2309     static UniqueCFRef<CFArrayRef> CopyAvailableFontFamilyNames() {
   2310 #ifdef SK_BUILD_FOR_IOS
   2311         return UniqueCFRef<CFArrayRef>(CFArrayCreate(nullptr, nullptr, 0, nullptr));
   2312 #else
   2313         return UniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
   2314 #endif
   2315     }
   2316 
   2317 public:
   2318     SkFontMgr_Mac()
   2319         : fNames(CopyAvailableFontFamilyNames())
   2320         , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0) {}
   2321 
   2322 protected:
   2323     int onCountFamilies() const override {
   2324         return fCount;
   2325     }
   2326 
   2327     void onGetFamilyName(int index, SkString* familyName) const override {
   2328         if ((unsigned)index < (unsigned)fCount) {
   2329             CFStringToSkString(this->getFamilyNameAt(index), familyName);
   2330         } else {
   2331             familyName->reset();
   2332         }
   2333     }
   2334 
   2335     SkFontStyleSet* onCreateStyleSet(int index) const override {
   2336         if ((unsigned)index >= (unsigned)fCount) {
   2337             return nullptr;
   2338         }
   2339         return CreateSet(this->getFamilyNameAt(index));
   2340     }
   2341 
   2342     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
   2343         UniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
   2344         return CreateSet(cfName.get());
   2345     }
   2346 
   2347     SkTypeface* onMatchFamilyStyle(const char familyName[],
   2348                                    const SkFontStyle& fontStyle) const override {
   2349         sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
   2350         return sset->matchStyle(fontStyle);
   2351     }
   2352 
   2353     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
   2354                                             const SkFontStyle& style,
   2355                                             const char* bcp47[], int bcp47Count,
   2356                                             SkUnichar character) const override {
   2357         UniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
   2358         UniqueCFRef<CTFontRef> currentFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
   2359 
   2360         // kCFStringEncodingUTF32 is BE unless there is a BOM.
   2361         // Since there is no machine endian option, explicitly state machine endian.
   2362 #ifdef SK_CPU_LENDIAN
   2363         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
   2364 #else
   2365         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
   2366 #endif
   2367         UniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
   2368                 kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
   2369                 encoding, false));
   2370         CFRange range = CFRangeMake(0, CFStringGetLength(string.get()));  // in UniChar units.
   2371         UniqueCFRef<CTFontRef> fallbackFont(
   2372                 CTFontCreateForString(currentFont.get(), string.get(), range));
   2373         return create_from_CTFontRef(std::move(fallbackFont), nullptr, false);
   2374     }
   2375 
   2376     SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   2377                                  const SkFontStyle&) const override {
   2378         return nullptr;
   2379     }
   2380 
   2381     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
   2382         UniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromData(sk_ref_sp(data)));
   2383         if (!pr) {
   2384             return nullptr;
   2385         }
   2386         return create_from_dataProvider(std::move(pr), ttcIndex);
   2387     }
   2388 
   2389     SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
   2390         std::unique_ptr<SkStreamAsset> stream(bareStream);
   2391         UniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromStream(std::move(stream)));
   2392         if (!pr) {
   2393             return nullptr;
   2394         }
   2395         return create_from_dataProvider(std::move(pr), ttcIndex);
   2396     }
   2397 
   2398     /** Creates a dictionary suitable for setting the axes on a CGFont. */
   2399     static UniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, const SkFontArguments& args) {
   2400         // The CGFont variation data is keyed by name, but lacks the tag.
   2401         // The CTFont variation data is keyed by tag, and also has the name.
   2402         // We would like to work with CTFont variations, but creating a CTFont font with
   2403         // CTFont variation dictionary runs into bugs. So use the CTFont variation data
   2404         // to match names to tags to create the appropriate CGFont.
   2405         UniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr));
   2406         // This call always returns nullptr on 10.10 and under.
   2407         // When this happens, there is no API to provide the tag.
   2408         UniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct.get()));
   2409         if (!ctAxes) {
   2410             return nullptr;
   2411         }
   2412         CFIndex axisCount = CFArrayGetCount(ctAxes.get());
   2413 
   2414         const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
   2415 
   2416         UniqueCFRef<CFMutableDictionaryRef> dict(
   2417                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
   2418                                           &kCFTypeDictionaryKeyCallBacks,
   2419                                           &kCFTypeDictionaryValueCallBacks));
   2420 
   2421         for (int i = 0; i < axisCount; ++i) {
   2422             CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
   2423             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
   2424                 return nullptr;
   2425             }
   2426             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
   2427 
   2428             // The assumption is that values produced by kCTFontVariationAxisNameKey and
   2429             // kCGFontVariationAxisName will always be equal.
   2430             // If they are ever not, seach the project history for "get_tag_for_name".
   2431             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
   2432             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
   2433                 return nullptr;
   2434             }
   2435 
   2436             CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
   2437             if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
   2438                 return nullptr;
   2439             }
   2440             CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
   2441             int64_t tagLong;
   2442             if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
   2443                 return nullptr;
   2444             }
   2445 
   2446             // The variation axes can be set to any value, but cg will effectively pin them.
   2447             // Pin them here to normalize.
   2448             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
   2449             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
   2450             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
   2451             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
   2452                 !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
   2453                 !def || CFGetTypeID(def) != CFNumberGetTypeID())
   2454             {
   2455                 return nullptr;
   2456             }
   2457             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
   2458             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
   2459             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
   2460             double minDouble;
   2461             double maxDouble;
   2462             double defDouble;
   2463             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
   2464                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
   2465                 !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
   2466             {
   2467                 return nullptr;
   2468             }
   2469 
   2470             double value = defDouble;
   2471             for (int j = 0; j < position.coordinateCount; ++j) {
   2472                 if (position.coordinates[j].axis == tagLong) {
   2473                     value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
   2474                                    minDouble, maxDouble);
   2475                     break;
   2476                 }
   2477             }
   2478             UniqueCFRef<CFNumberRef> valueNumber(
   2479                 CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
   2480             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
   2481         }
   2482         return std::move(dict);
   2483     }
   2484     SkTypeface* onCreateFromStream(SkStreamAsset* bs, const SkFontArguments& args) const override {
   2485         std::unique_ptr<SkStreamAsset> s(bs);
   2486         if (args.getCollectionIndex() != 0) {
   2487             return nullptr;
   2488         }
   2489         UniqueCFRef<CGDataProviderRef> provider(SkCreateDataProviderFromStream(std::move(s)));
   2490         if (!provider) {
   2491             return nullptr;
   2492         }
   2493         UniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
   2494         if (!cg) {
   2495             return nullptr;
   2496         }
   2497 
   2498         UniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), args);
   2499         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
   2500         // created from a data provider does not appear to have any ownership of the underlying
   2501         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
   2502         UniqueCFRef<CGFontRef> cgVariant;
   2503         if (cgVariations) {
   2504             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
   2505         } else {
   2506             cgVariant.reset(cg.release());
   2507         }
   2508 
   2509         UniqueCFRef<CTFontRef> ct(
   2510                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
   2511         if (!ct) {
   2512             return nullptr;
   2513         }
   2514         return create_from_CTFontRef(std::move(ct), std::move(cg), true);
   2515     }
   2516 
   2517     /** Creates a dictionary suitable for setting the axes on a CGFont. */
   2518     static UniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, SkFontData* fontData) {
   2519         UniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
   2520         if (!cgAxes) {
   2521             return nullptr;
   2522         }
   2523 
   2524         CFIndex axisCount = CFArrayGetCount(cgAxes.get());
   2525         if (0 == axisCount || axisCount != fontData->getAxisCount()) {
   2526             return nullptr;
   2527         }
   2528 
   2529         UniqueCFRef<CFMutableDictionaryRef> dict(
   2530                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
   2531                                           &kCFTypeDictionaryKeyCallBacks,
   2532                                           &kCFTypeDictionaryValueCallBacks));
   2533 
   2534         for (int i = 0; i < fontData->getAxisCount(); ++i) {
   2535             CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes.get(), i);
   2536             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
   2537                 return nullptr;
   2538             }
   2539             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
   2540 
   2541             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName);
   2542             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
   2543                 return nullptr;
   2544             }
   2545 
   2546             // The variation axes can be set to any value, but cg will effectively pin them.
   2547             // Pin them here to normalize.
   2548             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue);
   2549             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue);
   2550             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
   2551                 !max || CFGetTypeID(max) != CFNumberGetTypeID())
   2552             {
   2553                 return nullptr;
   2554             }
   2555             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
   2556             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
   2557             double minDouble;
   2558             double maxDouble;
   2559             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
   2560                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
   2561             {
   2562                 return nullptr;
   2563             }
   2564             double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
   2565             UniqueCFRef<CFNumberRef> valueNumber(
   2566                     CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
   2567             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
   2568         }
   2569         return std::move(dict);
   2570     }
   2571     SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> fontData) const override {
   2572         if (fontData->getIndex() != 0) {
   2573             return nullptr;
   2574         }
   2575         UniqueCFRef<CGDataProviderRef> provider(
   2576                 SkCreateDataProviderFromStream(fontData->detachStream()));
   2577         if (!provider) {
   2578             return nullptr;
   2579         }
   2580         UniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
   2581         if (!cg) {
   2582             return nullptr;
   2583         }
   2584 
   2585         UniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), fontData.get());
   2586         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
   2587         // created from a data provider does not appear to have any ownership of the underlying
   2588         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
   2589         UniqueCFRef<CGFontRef> cgVariant;
   2590         if (cgVariations) {
   2591             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
   2592         } else {
   2593             cgVariant.reset(cg.release());
   2594         }
   2595 
   2596         UniqueCFRef<CTFontRef> ct(
   2597                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
   2598         if (!ct) {
   2599             return nullptr;
   2600         }
   2601         return create_from_CTFontRef(std::move(ct), std::move(cg), true);
   2602     }
   2603 
   2604     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
   2605         UniqueCFRef<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
   2606         if (!pr) {
   2607             return nullptr;
   2608         }
   2609         return create_from_dataProvider(std::move(pr), ttcIndex);
   2610     }
   2611 
   2612     SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
   2613         if (familyName) {
   2614             familyName = map_css_names(familyName);
   2615         }
   2616 
   2617         SkTypeface* face = create_from_name(familyName, style);
   2618         if (face) {
   2619             return face;
   2620         }
   2621 
   2622         static SkTypeface* gDefaultFace;
   2623         static SkOnce lookupDefault;
   2624         static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
   2625         lookupDefault([]{
   2626             gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle());
   2627         });
   2628         return SkSafeRef(gDefaultFace);
   2629     }
   2630 };
   2631 
   2632 ///////////////////////////////////////////////////////////////////////////////
   2633 
   2634 sk_sp<SkFontMgr> SkFontMgr::Factory() { return sk_make_sp<SkFontMgr_Mac>(); }
   2635 
   2636 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
   2637