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