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