Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkTypes.h"  // Keep this before any #ifdef ...
     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 "SkCGUtils.h"
     24 #include "SkColorPriv.h"
     25 #include "SkDescriptor.h"
     26 #include "SkEndian.h"
     27 #include "SkFontDescriptor.h"
     28 #include "SkFloatingPoint.h"
     29 #include "SkGlyph.h"
     30 #include "SkLazyFnPtr.h"
     31 #include "SkMaskGamma.h"
     32 #include "SkSFNTHeader.h"
     33 #include "SkOTTable_glyf.h"
     34 #include "SkOTTable_head.h"
     35 #include "SkOTTable_hhea.h"
     36 #include "SkOTTable_loca.h"
     37 #include "SkOTUtils.h"
     38 #include "SkPaint.h"
     39 #include "SkPath.h"
     40 #include "SkString.h"
     41 #include "SkStream.h"
     42 #include "SkThread.h"
     43 #include "SkTypeface_mac.h"
     44 #include "SkUtils.h"
     45 #include "SkTypefaceCache.h"
     46 #include "SkFontMgr.h"
     47 #include "SkUtils.h"
     48 
     49 #include <dlfcn.h>
     50 
     51 // Set to make glyph bounding boxes visible.
     52 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
     53 
     54 class SkScalerContext_Mac;
     55 
     56 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
     57 // provide a wrapper here that will return an empty array if need be.
     58 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() {
     59 #ifdef SK_BUILD_FOR_IOS
     60     return CFArrayCreate(NULL, NULL, 0, NULL);
     61 #else
     62     return CTFontManagerCopyAvailableFontFamilyNames();
     63 #endif
     64 }
     65 
     66 
     67 // Being templated and taking const T* prevents calling
     68 // CFSafeRelease(autoCFRelease) through implicit conversion.
     69 template <typename T> static void CFSafeRelease(/*CFTypeRef*/const T* cfTypeRef) {
     70     if (cfTypeRef) {
     71         CFRelease(cfTypeRef);
     72     }
     73 }
     74 
     75 // Being templated and taking const T* prevents calling
     76 // CFSafeRetain(autoCFRelease) through implicit conversion.
     77 template <typename T> static void CFSafeRetain(/*CFTypeRef*/const T* cfTypeRef) {
     78     if (cfTypeRef) {
     79         CFRetain(cfTypeRef);
     80     }
     81 }
     82 
     83 /** Acts like a CFRef, but calls CFSafeRelease when it goes out of scope. */
     84 template<typename CFRef> class AutoCFRelease : private SkNoncopyable {
     85 public:
     86     explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { }
     87     ~AutoCFRelease() { CFSafeRelease(fCFRef); }
     88 
     89     void reset(CFRef that = NULL) {
     90         if (that != fCFRef) {
     91             CFSafeRelease(fCFRef);
     92             fCFRef = that;
     93         }
     94     }
     95 
     96     CFRef detach() {
     97         CFRef self = fCFRef;
     98         fCFRef = NULL;
     99         return self;
    100     }
    101 
    102     operator CFRef() const { return fCFRef; }
    103     CFRef get() const { return fCFRef; }
    104 
    105     CFRef* operator&() { SkASSERT(fCFRef == NULL); return &fCFRef; }
    106 private:
    107     CFRef fCFRef;
    108 };
    109 
    110 static CFStringRef make_CFString(const char str[]) {
    111     return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
    112 }
    113 
    114 template<typename T> class AutoCGTable : SkNoncopyable {
    115 public:
    116     AutoCGTable(CGFontRef font)
    117     //Undocumented: the tag parameter in this call is expected in machine order and not BE order.
    118     : fCFData(CGFontCopyTableForTag(font, SkSetFourByteTag(T::TAG0, T::TAG1, T::TAG2, T::TAG3)))
    119     , fData(fCFData ? reinterpret_cast<const T*>(CFDataGetBytePtr(fCFData)) : NULL)
    120     { }
    121 
    122     const T* operator->() const { return fData; }
    123 
    124 private:
    125     AutoCFRelease<CFDataRef> fCFData;
    126 public:
    127     const T* fData;
    128 };
    129 
    130 // inline versions of these rect helpers
    131 
    132 static bool CGRectIsEmpty_inline(const CGRect& rect) {
    133     return rect.size.width <= 0 || rect.size.height <= 0;
    134 }
    135 
    136 static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
    137     return rect.origin.x;
    138 }
    139 
    140 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) {
    141     return rect.origin.x + rect.size.width;
    142 }
    143 
    144 static CGFloat CGRectGetMinY_inline(const CGRect& rect) {
    145     return rect.origin.y;
    146 }
    147 
    148 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
    149     return rect.origin.y + rect.size.height;
    150 }
    151 
    152 static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
    153     return rect.size.width;
    154 }
    155 
    156 ///////////////////////////////////////////////////////////////////////////////
    157 
    158 static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
    159                              int width, int height, size_t rowBytes) {
    160     SkASSERT(width);
    161     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
    162 
    163     if (width >= 32) {
    164         while (height) {
    165             sk_memset32(ptr, value, width);
    166             ptr = (uint32_t*)((char*)ptr + rowBytes);
    167             height -= 1;
    168         }
    169         return;
    170     }
    171 
    172     rowBytes -= width * sizeof(uint32_t);
    173 
    174     if (width >= 8) {
    175         while (height) {
    176             int w = width;
    177             do {
    178                 *ptr++ = value; *ptr++ = value;
    179                 *ptr++ = value; *ptr++ = value;
    180                 *ptr++ = value; *ptr++ = value;
    181                 *ptr++ = value; *ptr++ = value;
    182                 w -= 8;
    183             } while (w >= 8);
    184             while (--w >= 0) {
    185                 *ptr++ = value;
    186             }
    187             ptr = (uint32_t*)((char*)ptr + rowBytes);
    188             height -= 1;
    189         }
    190     } else {
    191         while (height) {
    192             int w = width;
    193             do {
    194                 *ptr++ = value;
    195             } while (--w > 0);
    196             ptr = (uint32_t*)((char*)ptr + rowBytes);
    197             height -= 1;
    198         }
    199     }
    200 }
    201 
    202 #include <sys/utsname.h>
    203 
    204 typedef uint32_t CGRGBPixel;
    205 
    206 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
    207     return pixel & 0xFF;
    208 }
    209 
    210 static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
    211 
    212 // See Source/WebKit/chromium/base/mac/mac_util.mm DarwinMajorVersionInternal for original source.
    213 static int readVersion() {
    214     struct utsname info;
    215     if (uname(&info) != 0) {
    216         SkDebugf("uname failed\n");
    217         return 0;
    218     }
    219     if (strcmp(info.sysname, "Darwin") != 0) {
    220         SkDebugf("unexpected uname sysname %s\n", info.sysname);
    221         return 0;
    222     }
    223     char* dot = strchr(info.release, '.');
    224     if (!dot) {
    225         SkDebugf("expected dot in uname release %s\n", info.release);
    226         return 0;
    227     }
    228     int version = atoi(info.release);
    229     if (version == 0) {
    230         SkDebugf("could not parse uname release %s\n", info.release);
    231     }
    232     return version;
    233 }
    234 
    235 static int darwinVersion() {
    236     static int darwin_version = readVersion();
    237     return darwin_version;
    238 }
    239 
    240 static bool isSnowLeopard() {
    241     return darwinVersion() == 10;
    242 }
    243 
    244 static bool isLion() {
    245     return darwinVersion() == 11;
    246 }
    247 
    248 static bool isMountainLion() {
    249     return darwinVersion() == 12;
    250 }
    251 
    252 static bool isLCDFormat(unsigned format) {
    253     return SkMask::kLCD16_Format == format;
    254 }
    255 
    256 static CGFloat ScalarToCG(SkScalar scalar) {
    257     if (sizeof(CGFloat) == sizeof(float)) {
    258         return SkScalarToFloat(scalar);
    259     } else {
    260         SkASSERT(sizeof(CGFloat) == sizeof(double));
    261         return (CGFloat) SkScalarToDouble(scalar);
    262     }
    263 }
    264 
    265 static SkScalar CGToScalar(CGFloat cgFloat) {
    266     if (sizeof(CGFloat) == sizeof(float)) {
    267         return cgFloat;
    268     } else {
    269         SkASSERT(sizeof(CGFloat) == sizeof(double));
    270         return SkDoubleToScalar(cgFloat);
    271     }
    272 }
    273 
    274 static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix,
    275                                                    SkScalar sx = SK_Scalar1,
    276                                                    SkScalar sy = SK_Scalar1) {
    277     return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx),
    278                                  -ScalarToCG(matrix[SkMatrix::kMSkewY]  * sy),
    279                                  -ScalarToCG(matrix[SkMatrix::kMSkewX]  * sx),
    280                                   ScalarToCG(matrix[SkMatrix::kMScaleY] * sy),
    281                                   ScalarToCG(matrix[SkMatrix::kMTransX] * sx),
    282                                   ScalarToCG(matrix[SkMatrix::kMTransY] * sy));
    283 }
    284 
    285 ///////////////////////////////////////////////////////////////////////////////
    286 
    287 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
    288 
    289 /**
    290  * There does not appear to be a publicly accessable API for determining if lcd
    291  * font smoothing will be applied if we request it. The main issue is that if
    292  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
    293  */
    294 static bool supports_LCD() {
    295     static int gSupportsLCD = -1;
    296     if (gSupportsLCD >= 0) {
    297         return (bool) gSupportsLCD;
    298     }
    299     uint32_t rgb = 0;
    300     AutoCFRelease<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
    301     AutoCFRelease<CGContextRef> cgContext(CGBitmapContextCreate(&rgb, 1, 1, 8, 4,
    302                                                                 colorspace, BITMAP_INFO_RGB));
    303     CGContextSelectFont(cgContext, "Helvetica", 16, kCGEncodingMacRoman);
    304     CGContextSetShouldSmoothFonts(cgContext, true);
    305     CGContextSetShouldAntialias(cgContext, true);
    306     CGContextSetTextDrawingMode(cgContext, kCGTextFill);
    307     CGContextSetGrayFillColor(cgContext, 1, 1);
    308     CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1);
    309     uint32_t r = (rgb >> 16) & 0xFF;
    310     uint32_t g = (rgb >>  8) & 0xFF;
    311     uint32_t b = (rgb >>  0) & 0xFF;
    312     gSupportsLCD = (r != g || r != b);
    313     return (bool) gSupportsLCD;
    314 }
    315 
    316 class Offscreen {
    317 public:
    318     Offscreen()
    319         : fRGBSpace(NULL)
    320         , fCG(NULL)
    321         , fDoAA(false)
    322         , fDoLCD(false)
    323     {
    324         fSize.set(0, 0);
    325     }
    326 
    327     CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    328                       CGGlyph glyphID, size_t* rowBytesPtr,
    329                       bool generateA8FromLCD);
    330 
    331 private:
    332     enum {
    333         kSize = 32 * 32 * sizeof(CGRGBPixel)
    334     };
    335     SkAutoSMalloc<kSize> fImageStorage;
    336     AutoCFRelease<CGColorSpaceRef> fRGBSpace;
    337 
    338     // cached state
    339     AutoCFRelease<CGContextRef> fCG;
    340     SkISize fSize;
    341     bool fDoAA;
    342     bool fDoLCD;
    343 
    344     static int RoundSize(int dimension) {
    345         return SkNextPow2(dimension);
    346     }
    347 };
    348 
    349 ///////////////////////////////////////////////////////////////////////////////
    350 
    351 static bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value) {
    352     CFNumberRef num;
    353     return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num)
    354     && CFNumberIsFloatType(num)
    355     && CFNumberGetValue(num, kCFNumberFloatType, value);
    356 }
    357 
    358 static int unit_weight_to_fontstyle(float unit) {
    359     float value;
    360     if (unit < 0) {
    361         value = 100 + (1 + unit) * 300;
    362     } else {
    363         value = 400 + unit * 500;
    364     }
    365     return sk_float_round2int(value);
    366 }
    367 
    368 static int unit_width_to_fontstyle(float unit) {
    369     float value;
    370     if (unit < 0) {
    371         value = 1 + (1 + unit) * 4;
    372     } else {
    373         value = 5 + unit * 4;
    374     }
    375     return sk_float_round2int(value);
    376 }
    377 
    378 static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc) {
    379     AutoCFRelease<CFDictionaryRef> dict(
    380             (CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute));
    381     if (NULL == dict.get()) {
    382         return SkFontStyle();
    383     }
    384 
    385     float weight, width, slant;
    386     if (!find_dict_float(dict, kCTFontWeightTrait, &weight)) {
    387         weight = 0;
    388     }
    389     if (!find_dict_float(dict, kCTFontWidthTrait, &width)) {
    390         width = 0;
    391     }
    392     if (!find_dict_float(dict, kCTFontSlantTrait, &slant)) {
    393         slant = 0;
    394     }
    395 
    396     return SkFontStyle(unit_weight_to_fontstyle(weight),
    397                        unit_width_to_fontstyle(width),
    398                        slant ? SkFontStyle::kItalic_Slant
    399                        : SkFontStyle::kUpright_Slant);
    400 }
    401 
    402 static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isFixedPitch) {
    403     unsigned style = SkTypeface::kNormal;
    404     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font);
    405 
    406     if (traits & kCTFontBoldTrait) {
    407         style |= SkTypeface::kBold;
    408     }
    409     if (traits & kCTFontItalicTrait) {
    410         style |= SkTypeface::kItalic;
    411     }
    412     if (isFixedPitch) {
    413         *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0;
    414     }
    415     return (SkTypeface::Style)style;
    416 }
    417 
    418 #define WEIGHT_THRESHOLD    ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_Weight)/2)
    419 
    420 // kCTFontColorGlyphsTrait was added in the Mac 10.7 and iPhone 4.3 SDKs.
    421 // Being an enum value it is not guarded by version macros, but old SDKs must still be supported.
    422 #if defined(__MAC_10_7) || defined(__IPHONE_4_3)
    423 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait;
    424 #else
    425 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13);
    426 #endif
    427 
    428 class SkTypeface_Mac : public SkTypeface {
    429 public:
    430     SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch,
    431                    CTFontRef fontRef, const char requestedName[], bool isLocalStream)
    432         : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch)
    433         , fRequestedName(requestedName)
    434         , fFontRef(fontRef) // caller has already called CFRetain for us
    435         , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontColorGlyphsTrait))
    436         , fIsLocalStream(isLocalStream)
    437     {
    438         SkASSERT(fontRef);
    439     }
    440 
    441     SkString fRequestedName;
    442     AutoCFRelease<CTFontRef> fFontRef;
    443     const bool fHasColorGlyphs;
    444 
    445 protected:
    446     int onGetUPEM() const override;
    447     SkStreamAsset* onOpenStream(int* ttcIndex) const override;
    448     void onGetFamilyName(SkString* familyName) const override;
    449     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
    450     int onGetTableTags(SkFontTableTag tags[]) const override;
    451     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
    452                                   size_t length, void* data) const override;
    453     SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override;
    454     void onFilterRec(SkScalerContextRec*) const override;
    455     void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
    456     virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
    457                                 PerGlyphInfo,
    458                                 const uint32_t*, uint32_t) const override;
    459     virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[],
    460                                 int glyphCount) const override;
    461     int onCountGlyphs() const override;
    462 
    463 private:
    464     bool fIsLocalStream;
    465 
    466     typedef SkTypeface INHERITED;
    467 };
    468 
    469 /** Creates a typeface without searching the cache. Takes ownership of the CTFontRef. */
    470 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isLocalStream) {
    471     SkASSERT(fontRef);
    472     bool isFixedPitch;
    473     SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch));
    474 
    475     return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream);
    476 }
    477 
    478 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* context) {
    479     CTFontRef self = (CTFontRef)context;
    480     CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef;
    481 
    482     return CFEqual(self, other);
    483 }
    484 
    485 /** Creates a typeface from a name, searching the cache. */
    486 static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theStyle) {
    487     CTFontSymbolicTraits ctFontTraits = 0;
    488     if (theStyle.weight() >= SkFontStyle::kBold_Weight) {
    489         ctFontTraits |= kCTFontBoldTrait;
    490     }
    491     if (theStyle.slant() != SkFontStyle::kUpright_Slant) {
    492         ctFontTraits |= kCTFontItalicTrait;
    493     }
    494 
    495     //TODO: add weight width slant
    496 
    497     // Create the font info
    498     AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName));
    499 
    500     AutoCFRelease<CFNumberRef> cfFontTraits(
    501             CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
    502 
    503     AutoCFRelease<CFMutableDictionaryRef> cfAttributes(
    504             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    505                                       &kCFTypeDictionaryKeyCallBacks,
    506                                       &kCFTypeDictionaryValueCallBacks));
    507 
    508     AutoCFRelease<CFMutableDictionaryRef> cfTraits(
    509             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    510                                       &kCFTypeDictionaryKeyCallBacks,
    511                                       &kCFTypeDictionaryValueCallBacks));
    512 
    513     if (!cfFontName || !cfFontTraits || !cfAttributes || !cfTraits) {
    514         return NULL;
    515     }
    516 
    517     CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
    518 
    519     CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
    520     CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
    521 
    522     AutoCFRelease<CTFontDescriptorRef> ctFontDesc(
    523             CTFontDescriptorCreateWithAttributes(cfAttributes));
    524     if (!ctFontDesc) {
    525         return NULL;
    526     }
    527 
    528     AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL));
    529     if (!ctFont) {
    530         return NULL;
    531     }
    532 
    533     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)ctFont.get());
    534     if (!face) {
    535         face = NewFromFontRef(ctFont.detach(), NULL, false);
    536         SkTypefaceCache::Add(face, face->fontStyle());
    537     }
    538     return face;
    539 }
    540 
    541 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex);
    542 static SkTypeface* GetDefaultFace() {
    543     SkAutoMutexAcquire ma(gGetDefaultFaceMutex);
    544 
    545     static SkTypeface* gDefaultFace;
    546 
    547     if (NULL == gDefaultFace) {
    548         gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle());
    549         SkTypefaceCache::Add(gDefaultFace, SkFontStyle());
    550     }
    551     return gDefaultFace;
    552 }
    553 
    554 ///////////////////////////////////////////////////////////////////////////////
    555 
    556 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face);
    557 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
    558     const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face;
    559     return macface ? macface->fFontRef.get() : NULL;
    560 }
    561 
    562 /*  This function is visible on the outside. It first searches the cache, and if
    563  *  not found, returns a new entry (after adding it to the cache).
    564  */
    565 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) {
    566     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)fontRef);
    567     if (!face) {
    568         CFRetain(fontRef);
    569         face = NewFromFontRef(fontRef, NULL, false);
    570         SkTypefaceCache::Add(face, face->fontStyle());
    571     }
    572     return face;
    573 }
    574 
    575 struct NameStyle {
    576     const char* fName;
    577     SkFontStyle fStyle;
    578 };
    579 
    580 static bool find_by_NameStyle(SkTypeface* cachedFace, const SkFontStyle& cachedStyle, void* ctx) {
    581     const SkTypeface_Mac* cachedMacFace = static_cast<SkTypeface_Mac*>(cachedFace);
    582     const NameStyle* requested = static_cast<const NameStyle*>(ctx);
    583 
    584     return cachedStyle == requested->fStyle
    585         && cachedMacFace->fRequestedName.equals(requested->fName);
    586 }
    587 
    588 static const char* map_css_names(const char* name) {
    589     static const struct {
    590         const char* fFrom;  // name the caller specified
    591         const char* fTo;    // "canonical" name we map to
    592     } gPairs[] = {
    593         { "sans-serif", "Helvetica" },
    594         { "serif",      "Times"     },
    595         { "monospace",  "Courier"   }
    596     };
    597 
    598     for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
    599         if (strcmp(name, gPairs[i].fFrom) == 0) {
    600             return gPairs[i].fTo;
    601         }
    602     }
    603     return name;    // no change
    604 }
    605 
    606 ///////////////////////////////////////////////////////////////////////////////
    607 
    608 /** GlyphRect is in FUnits (em space, y up). */
    609 struct GlyphRect {
    610     int16_t fMinX;
    611     int16_t fMinY;
    612     int16_t fMaxX;
    613     int16_t fMaxY;
    614 };
    615 
    616 class SkScalerContext_Mac : public SkScalerContext {
    617 public:
    618     SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*);
    619 
    620 protected:
    621     unsigned generateGlyphCount(void) override;
    622     uint16_t generateCharToGlyph(SkUnichar uni) override;
    623     void generateAdvance(SkGlyph* glyph) override;
    624     void generateMetrics(SkGlyph* glyph) override;
    625     void generateImage(const SkGlyph& glyph) override;
    626     void generatePath(const SkGlyph& glyph, SkPath* path) override;
    627     void generateFontMetrics(SkPaint::FontMetrics*) override;
    628 
    629 private:
    630     static void CTPathElement(void *info, const CGPathElement *element);
    631 
    632     /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */
    633     void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const;
    634 
    635     /** Initializes and returns the value of fFBoundingBoxesGlyphOffset.
    636      *
    637      *  For use with (and must be called before) generateBBoxes.
    638      */
    639     uint16_t getFBoundingBoxesGlyphOffset();
    640 
    641     /** Initializes fFBoundingBoxes and returns true on success.
    642      *
    643      *  On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to
    644      *  return a bad value in bounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is
    645      *  less than its maxp::numGlyphs. When this is the case we try to read the bounds from the
    646      *  font directly.
    647      *
    648      *  This routine initializes fFBoundingBoxes to an array of
    649      *  fGlyphCount - fFBoundingBoxesGlyphOffset GlyphRects which contain the bounds in FUnits
    650      *  (em space, y up) of glyphs with ids in the range [fFBoundingBoxesGlyphOffset, fGlyphCount).
    651      *
    652      *  Returns true if fFBoundingBoxes is properly initialized. The table can only be properly
    653      *  initialized for a TrueType font with 'head', 'loca', and 'glyf' tables.
    654      *
    655      *  TODO: A future optimization will compute fFBoundingBoxes once per fCTFont.
    656      */
    657     bool generateBBoxes();
    658 
    659     /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down).
    660      *
    661      *  Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs.
    662      *  Used on Lion to correct CTFontGetBoundingRectsForGlyphs.
    663      */
    664     SkMatrix fFUnitMatrix;
    665 
    666     Offscreen fOffscreen;
    667     AutoCFRelease<CTFontRef> fCTFont;
    668     CGAffineTransform fTransform;
    669     CGAffineTransform fInvTransform;
    670 
    671     /** Unrotated variant of fCTFont.
    672      *
    673      *  In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the
    674      *  advances, but always sets the height to 0. This font is used to get the advances of the
    675      *  unrotated glyph, and then the rotation is applied separately.
    676      *
    677      *  CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
    678      *  This makes kCTFontDefaultOrientation dangerous, because the metrics from
    679      *  kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation.
    680      *  With kCTFontVerticalOrientation the advances must be unrotated.
    681      */
    682     AutoCFRelease<CTFontRef> fCTUnrotatedFont;
    683 
    684     AutoCFRelease<CGFontRef> fCGFont;
    685     SkAutoTMalloc<GlyphRect> fFBoundingBoxes;
    686     uint16_t fFBoundingBoxesGlyphOffset;
    687     uint16_t fGlyphCount;
    688     bool fGeneratedFBoundingBoxes;
    689     const bool fDoSubPosition;
    690     const bool fVertical;
    691 
    692     friend class Offscreen;
    693 
    694     typedef SkScalerContext INHERITED;
    695 };
    696 
    697 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
    698                                          const SkDescriptor* desc)
    699         : INHERITED(typeface, desc)
    700         , fFBoundingBoxes()
    701         , fFBoundingBoxesGlyphOffset(0)
    702         , fGeneratedFBoundingBoxes(false)
    703         , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
    704         , fVertical(SkToBool(fRec.fFlags & kVertical_Flag))
    705 
    706 {
    707     CTFontRef ctFont = typeface->fFontRef.get();
    708     CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
    709     SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
    710     fGlyphCount = SkToU16(numGlyphs);
    711 
    712     // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
    713     // As a result, it is necessary to know the actual device size and request that.
    714     SkVector scale;
    715     SkMatrix skTransform;
    716     fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &skTransform,
    717                          NULL, NULL, &fFUnitMatrix);
    718     fTransform = MatrixToCGAffineTransform(skTransform);
    719     fInvTransform = CGAffineTransformInvert(fTransform);
    720 
    721     AutoCFRelease<CTFontDescriptorRef> ctFontDesc;
    722     if (fVertical) {
    723         // Setting the vertical orientation here is required for vertical metrics on some versions.
    724         AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMutable(
    725                 kCFAllocatorDefault, 0,
    726                 &kCFTypeDictionaryKeyCallBacks,
    727                 &kCFTypeDictionaryValueCallBacks));
    728         if (cfAttributes) {
    729             CTFontOrientation ctOrientation = kCTFontVerticalOrientation;
    730             AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate(
    731                     kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation));
    732             CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVertical);
    733             ctFontDesc.reset(CTFontDescriptorCreateWithAttributes(cfAttributes));
    734         }
    735     }
    736 
    737     // The transform contains everything except the requested text size.
    738     // Some properties, like 'trak', are based on the text size (before applying the matrix).
    739     CGFloat textSize = ScalarToCG(scale.y());
    740 
    741     fCTFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &fTransform, ctFontDesc));
    742     fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, NULL));
    743     fCTUnrotatedFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize,
    744                                                           &CGAffineTransformIdentity, NULL));
    745 
    746     // The fUnitMatrix includes the text size (and em) as it is used to scale the raw font data.
    747     SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont)));
    748     fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit);
    749 }
    750 
    751 extern "C" {
    752 
    753 /** CTFontDrawGlyphs was introduced in 10.7. */
    754 typedef void (*CTFontDrawGlyphsProc)(CTFontRef, const CGGlyph[], const CGPoint[],
    755                                      size_t, CGContextRef);
    756 
    757 /** This is an implementation of CTFontDrawGlyphs for 10.6. */
    758 static void sk_legacy_CTFontDrawGlyphs(CTFontRef, const CGGlyph glyphs[], const CGPoint points[],
    759                                        size_t count, CGContextRef cg)
    760 {
    761     CGContextShowGlyphsAtPositions(cg, glyphs, points, count);
    762 }
    763 
    764 }
    765 
    766 CTFontDrawGlyphsProc SkChooseCTFontDrawGlyphs() {
    767     CTFontDrawGlyphsProc realCTFontDrawGlyphs;
    768     *reinterpret_cast<void**>(&realCTFontDrawGlyphs) = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
    769     return realCTFontDrawGlyphs ? realCTFontDrawGlyphs : sk_legacy_CTFontDrawGlyphs;
    770 };
    771 
    772 SK_DECLARE_STATIC_LAZY_FN_PTR(CTFontDrawGlyphsProc, gCTFontDrawGlyphs, SkChooseCTFontDrawGlyphs);
    773 
    774 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    775                              CGGlyph glyphID, size_t* rowBytesPtr,
    776                              bool generateA8FromLCD)
    777 {
    778     CTFontDrawGlyphsProc ctFontDrawGlyphs = gCTFontDrawGlyphs.get();
    779 
    780     if (!fRGBSpace) {
    781         //It doesn't appear to matter what color space is specified.
    782         //Regular blends and antialiased text are always (s*a + d*(1-a))
    783         //and smoothed text is always g=2.0.
    784         fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
    785     }
    786 
    787     // default to kBW_Format
    788     bool doAA = false;
    789     bool doLCD = false;
    790 
    791     if (SkMask::kBW_Format != glyph.fMaskFormat) {
    792         doLCD = true;
    793         doAA = true;
    794     }
    795 
    796     // FIXME: lcd smoothed un-hinted rasterization unsupported.
    797     if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) {
    798         doLCD = false;
    799         doAA = true;
    800     }
    801 
    802     // If this font might have color glyphs, disable LCD as there's no way to support it.
    803     // CoreText doesn't tell us which format it ended up using, so we can't detect it.
    804     // A8 will be ugly too (white on transparent), but TODO: we can detect gray and set to A8.
    805     if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
    806         doLCD = false;
    807     }
    808 
    809     size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    810     if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) {
    811         if (fSize.fWidth < glyph.fWidth) {
    812             fSize.fWidth = RoundSize(glyph.fWidth);
    813         }
    814         if (fSize.fHeight < glyph.fHeight) {
    815             fSize.fHeight = RoundSize(glyph.fHeight);
    816         }
    817 
    818         rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    819         void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
    820         const CGImageAlphaInfo alpha = (SkMask::kARGB32_Format == glyph.fMaskFormat)
    821                                      ? kCGImageAlphaPremultipliedFirst
    822                                      : kCGImageAlphaNoneSkipFirst;
    823         const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha;
    824         fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
    825                                         rowBytes, fRGBSpace, bitmapInfo));
    826 
    827         // Skia handles quantization and subpixel positioning,
    828         // so disable quantization and enabe subpixel positioning in CG.
    829         CGContextSetAllowsFontSubpixelQuantization(fCG, false);
    830         CGContextSetShouldSubpixelQuantizeFonts(fCG, false);
    831 
    832         // Because CG always draws from the horizontal baseline,
    833         // if there is a non-integral translation from the horizontal origin to the vertical origin,
    834         // then CG cannot draw the glyph in the correct location without subpixel positioning.
    835         CGContextSetAllowsFontSubpixelPositioning(fCG, true);
    836         CGContextSetShouldSubpixelPositionFonts(fCG, true);
    837 
    838         CGContextSetTextDrawingMode(fCG, kCGTextFill);
    839 
    840         // Draw white on black to create mask.
    841         // TODO: Draw black on white and invert, CG has a special case codepath.
    842         CGContextSetGrayFillColor(fCG, 1.0f, 1.0f);
    843 
    844         // force our checks below to happen
    845         fDoAA = !doAA;
    846         fDoLCD = !doLCD;
    847 
    848         if (sk_legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) {
    849             // CTFontDrawGlyphs will apply the font, font size, and font matrix to the CGContext.
    850             // Our 'fake' one does not, so set up the CGContext here.
    851             CGContextSetFont(fCG, context.fCGFont);
    852             CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont));
    853         }
    854         CGContextSetTextMatrix(fCG, context.fTransform);
    855     }
    856 
    857     if (fDoAA != doAA) {
    858         CGContextSetShouldAntialias(fCG, doAA);
    859         fDoAA = doAA;
    860     }
    861     if (fDoLCD != doLCD) {
    862         CGContextSetShouldSmoothFonts(fCG, doLCD);
    863         fDoLCD = doLCD;
    864     }
    865 
    866     CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
    867     // skip rows based on the glyph's height
    868     image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth;
    869 
    870     // erase to black
    871     sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes);
    872 
    873     float subX = 0;
    874     float subY = 0;
    875     if (context.fDoSubPosition) {
    876         subX = SkFixedToFloat(glyph.getSubXFixed());
    877         subY = SkFixedToFloat(glyph.getSubYFixed());
    878     }
    879 
    880     // CoreText and CoreGraphics always draw using the horizontal baseline origin.
    881     if (context.fVertical) {
    882         SkPoint offset;
    883         context.getVerticalOffset(glyphID, &offset);
    884         subX += offset.fX;
    885         subY += offset.fY;
    886     }
    887 
    888     CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY);
    889     // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
    890     // 'positions' which are in text space. The glyph location (in device space) must be
    891     // mapped into text space, so that CG can convert it back into device space.
    892     // In 10.10.1, this is handled directly inCTFontDrawGlyphs.
    893 
    894     // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
    895     // So always make the font transform identity and place the transform on the context.
    896     point = CGPointApplyAffineTransform(point, context.fInvTransform);
    897 
    898     // Attempt to keep on the stack a hard reference to the font tables.
    899     // This is an experiment to see if this affects crbug.com/413332 .
    900     // When 10.6 headers are no longer supported, 'sbix' can be replaced with kCTFontTableSbix.
    901     AutoCFRelease<CFDataRef> sbix;
    902     if (static_cast<SkTypeface_Mac*>(context.getTypeface())->fHasColorGlyphs) {
    903         sbix.reset(CGFontCopyTableForTag(context.fCGFont, 'sbix'));
    904         // Attempt to read from the sbix table data to determine if the returned data is valid.
    905         const UInt8* sbixData = CFDataGetBytePtr(sbix);
    906         CFIndex sbixLength = CFDataGetLength(sbix);
    907         if (sbixLength > 0 && *sbixData > 0x80) {
    908             // We need to actually do something to avoid this being optimized away.
    909             CFRetain(sbix);
    910             CFRelease(sbix);
    911         }
    912     }
    913     ctFontDrawGlyphs(context.fCTUnrotatedFont, &glyphID, &point, 1, fCG);
    914 
    915     SkASSERT(rowBytesPtr);
    916     *rowBytesPtr = rowBytes;
    917     return image;
    918 }
    919 
    920 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const {
    921     // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em space, y up).
    922     // Lion and Leopard return cgVertOffset in CG units (pixels, y up).
    923     CGSize cgVertOffset;
    924     CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1);
    925 
    926     SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
    927     if (isSnowLeopard()) {
    928         // From FUnits (em space, y up) to SkGlyph units (pixels, y down).
    929         fFUnitMatrix.mapPoints(&skVertOffset, 1);
    930     } else {
    931         // From CG units (pixels, y up) to SkGlyph units (pixels, y down).
    932         skVertOffset.fY = -skVertOffset.fY;
    933     }
    934 
    935     *offset = skVertOffset;
    936 }
    937 
    938 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() {
    939     if (fFBoundingBoxesGlyphOffset) {
    940         return fFBoundingBoxesGlyphOffset;
    941     }
    942     fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts
    943     AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont);
    944     if (hheaTable.fData) {
    945         fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetrics);
    946     }
    947     return fFBoundingBoxesGlyphOffset;
    948 }
    949 
    950 bool SkScalerContext_Mac::generateBBoxes() {
    951     if (fGeneratedFBoundingBoxes) {
    952         return SkToBool(fFBoundingBoxes.get());
    953     }
    954     fGeneratedFBoundingBoxes = true;
    955 
    956     AutoCGTable<SkOTTableHead> headTable(fCGFont);
    957     if (!headTable.fData) {
    958         return false;
    959     }
    960 
    961     AutoCGTable<SkOTTableIndexToLocation> locaTable(fCGFont);
    962     if (!locaTable.fData) {
    963         return false;
    964     }
    965 
    966     AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont);
    967     if (!glyfTable.fData) {
    968         return false;
    969     }
    970 
    971     uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset;
    972     fFBoundingBoxes.reset(entries);
    973 
    974     SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat;
    975     SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat);
    976     glyphDataIter.advance(fFBoundingBoxesGlyphOffset);
    977     for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundingBoxesIndex) {
    978         const SkOTTableGlyphData* glyphData = glyphDataIter.next();
    979         GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex];
    980         rect.fMinX = SkEndian_SwapBE16(glyphData->xMin);
    981         rect.fMinY = SkEndian_SwapBE16(glyphData->yMin);
    982         rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax);
    983         rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax);
    984     }
    985 
    986     return true;
    987 }
    988 
    989 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
    990     return fGlyphCount;
    991 }
    992 
    993 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) {
    994     CGGlyph cgGlyph[2];
    995     UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit.
    996 
    997     // Get the glyph
    998     size_t numUniChar = SkUTF16_FromUnichar(uni, theChar);
    999     SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t));
   1000 
   1001     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
   1002     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
   1003     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
   1004     CTFontGetGlyphsForCharacters(fCTFont, theChar, cgGlyph, numUniChar);
   1005     return cgGlyph[0];
   1006 }
   1007 
   1008 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
   1009     this->generateMetrics(glyph);
   1010 }
   1011 
   1012 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
   1013     const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
   1014     glyph->zeroMetrics();
   1015 
   1016     // The following block produces cgAdvance in CG units (pixels, y up).
   1017     CGSize cgAdvance;
   1018     if (fVertical) {
   1019         CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontVerticalOrientation,
   1020                                    &cgGlyph, &cgAdvance, 1);
   1021         // Vertical advances are returned as widths instead of heights.
   1022         SkTSwap(cgAdvance.height, cgAdvance.width);
   1023         cgAdvance.height = -cgAdvance.height;
   1024     } else {
   1025         CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontHorizontalOrientation,
   1026                                    &cgGlyph, &cgAdvance, 1);
   1027     }
   1028     cgAdvance = CGSizeApplyAffineTransform(cgAdvance, CTFontGetMatrix(fCTFont));
   1029     glyph->fAdvanceX =  SkFloatToFixed_Check(cgAdvance.width);
   1030     glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height);
   1031 
   1032     // The following produces skBounds in SkGlyph units (pixels, y down),
   1033     // or returns early if skBounds would be empty.
   1034     SkRect skBounds;
   1035 
   1036     // On Mountain Lion, CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation and
   1037     // CTFontGetVerticalTranslationsForGlyphs do not agree when using OTF CFF fonts.
   1038     // For TTF fonts these two do agree and we can use CTFontGetBoundingRectsForGlyphs to get
   1039     // the bounding box and CTFontGetVerticalTranslationsForGlyphs to then draw the glyph
   1040     // inside that bounding box. However, with OTF CFF fonts this does not work. It appears that
   1041     // CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation on OTF CFF fonts tries
   1042     // to center the glyph along the vertical baseline and also perform some mysterious shift
   1043     // along the baseline. CTFontGetVerticalTranslationsForGlyphs does not appear to perform
   1044     // these steps.
   1045     //
   1046     // It is not known which is correct (or if either is correct). However, we must always draw
   1047     // from the horizontal origin and must use CTFontGetVerticalTranslationsForGlyphs to draw.
   1048     // As a result, we do not call CTFontGetBoundingRectsForGlyphs for vertical glyphs.
   1049 
   1050     // On Snow Leopard, CTFontGetBoundingRectsForGlyphs ignores kCTFontVerticalOrientation and
   1051     // returns horizontal bounds.
   1052 
   1053     // On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to
   1054     // return a bad value in cgBounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is
   1055     // less than its maxp::numGlyphs. When this is the case we try to read the bounds from the
   1056     // font directly.
   1057     if ((isLion() || isMountainLion()) &&
   1058         (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes()))
   1059     {
   1060         const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset];
   1061         if (gRect.fMinX >= gRect.fMaxX || gRect.fMinY >= gRect.fMaxY) {
   1062             return;
   1063         }
   1064         skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY);
   1065         // From FUnits (em space, y up) to SkGlyph units (pixels, y down).
   1066         fFUnitMatrix.mapRect(&skBounds);
   1067 
   1068     } else {
   1069         // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
   1070         CGRect cgBounds;
   1071         CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation,
   1072                                         &cgGlyph, &cgBounds, 1);
   1073 
   1074         // BUG?
   1075         // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
   1076         // it should be empty. So, if we see a zero-advance, we check if it has an
   1077         // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
   1078         // is rare, so we won't incur a big performance cost for this extra check.
   1079         if (0 == cgAdvance.width && 0 == cgAdvance.height) {
   1080             AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL));
   1081             if (NULL == path || CGPathIsEmpty(path)) {
   1082                 return;
   1083             }
   1084         }
   1085 
   1086         if (CGRectIsEmpty_inline(cgBounds)) {
   1087             return;
   1088         }
   1089 
   1090         // Convert cgBounds to SkGlyph units (pixels, y down).
   1091         skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
   1092                                     cgBounds.size.width, cgBounds.size.height);
   1093     }
   1094 
   1095     if (fVertical) {
   1096         // Due to all of the vertical bounds bugs, skBounds is always the horizontal bounds.
   1097         // Convert these horizontal bounds into vertical bounds.
   1098         SkPoint offset;
   1099         getVerticalOffset(cgGlyph, &offset);
   1100         skBounds.offset(offset);
   1101     }
   1102 
   1103     // Currently the bounds are based on being rendered at (0,0).
   1104     // The top left must not move, since that is the base from which subpixel positioning is offset.
   1105     if (fDoSubPosition) {
   1106         skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
   1107         skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
   1108     }
   1109 
   1110     SkIRect skIBounds;
   1111     skBounds.roundOut(&skIBounds);
   1112     // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
   1113     // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
   1114     // is not currently known, as CG dilates the outlines by some percentage.
   1115     // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
   1116     skIBounds.outset(1, 1);
   1117     glyph->fLeft = SkToS16(skIBounds.fLeft);
   1118     glyph->fTop = SkToS16(skIBounds.fTop);
   1119     glyph->fWidth = SkToU16(skIBounds.width());
   1120     glyph->fHeight = SkToU16(skIBounds.height());
   1121 }
   1122 
   1123 #include "SkColorPriv.h"
   1124 
   1125 static void build_power_table(uint8_t table[], float ee) {
   1126     for (int i = 0; i < 256; i++) {
   1127         float x = i / 255.f;
   1128         x = sk_float_pow(x, ee);
   1129         int xx = SkScalarRoundToInt(x * 255);
   1130         table[i] = SkToU8(xx);
   1131     }
   1132 }
   1133 
   1134 /**
   1135  *  This will invert the gamma applied by CoreGraphics, so we can get linear
   1136  *  values.
   1137  *
   1138  *  CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
   1139  *  The color space used does not appear to affect this choice.
   1140  */
   1141 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() {
   1142     static bool gInited;
   1143     static uint8_t gTableCoreGraphicsSmoothing[256];
   1144     if (!gInited) {
   1145         build_power_table(gTableCoreGraphicsSmoothing, 2.0f);
   1146         gInited = true;
   1147     }
   1148     return gTableCoreGraphicsSmoothing;
   1149 }
   1150 
   1151 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
   1152     while (count > 0) {
   1153         uint8_t mask = 0;
   1154         for (int i = 7; i >= 0; --i) {
   1155             mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i;
   1156             if (0 == --count) {
   1157                 break;
   1158             }
   1159         }
   1160         *dst++ = mask;
   1161     }
   1162 }
   1163 
   1164 template<bool APPLY_PREBLEND>
   1165 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
   1166     U8CPU r = (rgb >> 16) & 0xFF;
   1167     U8CPU g = (rgb >>  8) & 0xFF;
   1168     U8CPU b = (rgb >>  0) & 0xFF;
   1169     U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1170 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1171     lum = SkTMax(lum, (U8CPU)0x30);
   1172 #endif
   1173     return lum;
   1174 }
   1175 template<bool APPLY_PREBLEND>
   1176 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
   1177                       const SkGlyph& glyph, const uint8_t* table8) {
   1178     const int width = glyph.fWidth;
   1179     size_t dstRB = glyph.rowBytes();
   1180     uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
   1181 
   1182     for (int y = 0; y < glyph.fHeight; y++) {
   1183         for (int i = 0; i < width; ++i) {
   1184             dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
   1185         }
   1186         cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1187         dst += dstRB;
   1188     }
   1189 }
   1190 
   1191 template<bool APPLY_PREBLEND>
   1192 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR,
   1193                                                     const uint8_t* tableG,
   1194                                                     const uint8_t* tableB) {
   1195     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1196     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1197     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1198 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1199     r = SkTMax(r, (U8CPU)0x30);
   1200     g = SkTMax(g, (U8CPU)0x30);
   1201     b = SkTMax(b, (U8CPU)0x30);
   1202 #endif
   1203     return SkPack888ToRGB16(r, g, b);
   1204 }
   1205 template<bool APPLY_PREBLEND>
   1206 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph,
   1207                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1208     const int width = glyph.fWidth;
   1209     size_t dstRB = glyph.rowBytes();
   1210     uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
   1211 
   1212     for (int y = 0; y < glyph.fHeight; y++) {
   1213         for (int i = 0; i < width; i++) {
   1214             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
   1215         }
   1216         cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1217         dst = (uint16_t*)((char*)dst + dstRB);
   1218     }
   1219 }
   1220 
   1221 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
   1222     U8CPU a = (rgb >> 24) & 0xFF;
   1223     U8CPU r = (rgb >> 16) & 0xFF;
   1224     U8CPU g = (rgb >>  8) & 0xFF;
   1225     U8CPU b = (rgb >>  0) & 0xFF;
   1226 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1227     a = SkTMax(a, (U8CPU)0x30);
   1228 #endif
   1229     return SkPackARGB32(a, r, g, b);
   1230 }
   1231 
   1232 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
   1233     return (T*)((char*)ptr + byteOffset);
   1234 }
   1235 
   1236 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
   1237     CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID();
   1238 
   1239     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   1240     bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting;
   1241 
   1242     // Draw the glyph
   1243     size_t cgRowBytes;
   1244     CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD);
   1245     if (cgPixels == NULL) {
   1246         return;
   1247     }
   1248 
   1249     //TODO: see if drawing black on white and inverting is faster (at least in
   1250     //lcd case) as core graphics appears to have special case code for drawing
   1251     //black text.
   1252 
   1253     // Fix the glyph
   1254     const bool isLCD = isLCDFormat(glyph.fMaskFormat);
   1255     if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) {
   1256         const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing();
   1257 
   1258         //Note that the following cannot really be integrated into the
   1259         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1260         //applying the pre-blend it means that a filter wants linear anyway.
   1261         //Other code may also be applying the pre-blend, so we'd need another
   1262         //one with this and one without.
   1263         CGRGBPixel* addr = cgPixels;
   1264         for (int y = 0; y < glyph.fHeight; ++y) {
   1265             for (int x = 0; x < glyph.fWidth; ++x) {
   1266                 int r = (addr[x] >> 16) & 0xFF;
   1267                 int g = (addr[x] >>  8) & 0xFF;
   1268                 int b = (addr[x] >>  0) & 0xFF;
   1269                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1270             }
   1271             addr = SkTAddByteOffset(addr, cgRowBytes);
   1272         }
   1273     }
   1274 
   1275     // Convert glyph to mask
   1276     switch (glyph.fMaskFormat) {
   1277         case SkMask::kLCD16_Format: {
   1278             if (fPreBlend.isApplicable()) {
   1279                 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph,
   1280                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1281             } else {
   1282                 rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph,
   1283                                     fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1284             }
   1285         } break;
   1286         case SkMask::kA8_Format: {
   1287             if (fPreBlend.isApplicable()) {
   1288                 rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1289             } else {
   1290                 rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1291             }
   1292         } break;
   1293         case SkMask::kBW_Format: {
   1294             const int width = glyph.fWidth;
   1295             size_t dstRB = glyph.rowBytes();
   1296             uint8_t* dst = (uint8_t*)glyph.fImage;
   1297             for (int y = 0; y < glyph.fHeight; y++) {
   1298                 cgpixels_to_bits(dst, cgPixels, width);
   1299                 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1300                 dst += dstRB;
   1301             }
   1302         } break;
   1303         case SkMask::kARGB32_Format: {
   1304             const int width = glyph.fWidth;
   1305             size_t dstRB = glyph.rowBytes();
   1306             SkPMColor* dst = (SkPMColor*)glyph.fImage;
   1307             for (int y = 0; y < glyph.fHeight; y++) {
   1308                 for (int x = 0; x < width; ++x) {
   1309                     dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
   1310                 }
   1311                 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1312                 dst = (SkPMColor*)((char*)dst + dstRB);
   1313             }
   1314         } break;
   1315         default:
   1316             SkDEBUGFAIL("unexpected mask format");
   1317             break;
   1318     }
   1319 }
   1320 
   1321 /*
   1322  *  Our subpixel resolution is only 2 bits in each direction, so a scale of 4
   1323  *  seems sufficient, and possibly even correct, to allow the hinted outline
   1324  *  to be subpixel positioned.
   1325  */
   1326 #define kScaleForSubPixelPositionHinting (4.0f)
   1327 
   1328 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) {
   1329     CTFontRef font = fCTFont;
   1330     SkScalar scaleX = SK_Scalar1;
   1331     SkScalar scaleY = SK_Scalar1;
   1332 
   1333     /*
   1334      *  For subpixel positioning, we want to return an unhinted outline, so it
   1335      *  can be positioned nicely at fractional offsets. However, we special-case
   1336      *  if the baseline of the (horizontal) text is axis-aligned. In those cases
   1337      *  we want to retain hinting in the direction orthogonal to the baseline.
   1338      *  e.g. for horizontal baseline, we want to retain hinting in Y.
   1339      *  The way we remove hinting is to scale the font by some value (4) in that
   1340      *  direction, ask for the path, and then scale the path back down.
   1341      */
   1342     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
   1343         SkMatrix m;
   1344         fRec.getSingleMatrix(&m);
   1345 
   1346         // start out by assuming that we want no hining in X and Y
   1347         scaleX = scaleY = kScaleForSubPixelPositionHinting;
   1348         // now see if we need to restore hinting for axis-aligned baselines
   1349         switch (SkComputeAxisAlignmentForHText(m)) {
   1350             case kX_SkAxisAlignment:
   1351                 scaleY = SK_Scalar1; // want hinting in the Y direction
   1352                 break;
   1353             case kY_SkAxisAlignment:
   1354                 scaleX = SK_Scalar1; // want hinting in the X direction
   1355                 break;
   1356             default:
   1357                 break;
   1358         }
   1359 
   1360         CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY);
   1361         // need to release font when we're done
   1362         font = CTFontCreateCopyWithAttributes(fCTFont, 1, &xform, NULL);
   1363     }
   1364 
   1365     CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID();
   1366     AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL));
   1367 
   1368     path->reset();
   1369     if (cgPath != NULL) {
   1370         CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement);
   1371     }
   1372 
   1373     if (fDoSubPosition) {
   1374         SkMatrix m;
   1375         m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
   1376         path->transform(m);
   1377         // balance the call to CTFontCreateCopyWithAttributes
   1378         CFSafeRelease(font);
   1379     }
   1380     if (fVertical) {
   1381         SkPoint offset;
   1382         getVerticalOffset(cgGlyph, &offset);
   1383         path->offset(offset.fX, offset.fY);
   1384     }
   1385 }
   1386 
   1387 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) {
   1388     if (NULL == metrics) {
   1389         return;
   1390     }
   1391 
   1392     CGRect theBounds = CTFontGetBoundingBox(fCTFont);
   1393 
   1394     metrics->fTop          = CGToScalar(-CGRectGetMaxY_inline(theBounds));
   1395     metrics->fAscent       = CGToScalar(-CTFontGetAscent(fCTFont));
   1396     metrics->fDescent      = CGToScalar( CTFontGetDescent(fCTFont));
   1397     metrics->fBottom       = CGToScalar(-CGRectGetMinY_inline(theBounds));
   1398     metrics->fLeading      = CGToScalar( CTFontGetLeading(fCTFont));
   1399     metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
   1400     metrics->fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
   1401     metrics->fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
   1402     metrics->fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont));
   1403     metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont));
   1404     metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont));
   1405 
   1406     metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1407     metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1408 }
   1409 
   1410 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) {
   1411     SkPath* skPath = (SkPath*)info;
   1412 
   1413     // Process the path element
   1414     switch (element->type) {
   1415         case kCGPathElementMoveToPoint:
   1416             skPath->moveTo(element->points[0].x, -element->points[0].y);
   1417             break;
   1418 
   1419         case kCGPathElementAddLineToPoint:
   1420             skPath->lineTo(element->points[0].x, -element->points[0].y);
   1421             break;
   1422 
   1423         case kCGPathElementAddQuadCurveToPoint:
   1424             skPath->quadTo(element->points[0].x, -element->points[0].y,
   1425                            element->points[1].x, -element->points[1].y);
   1426             break;
   1427 
   1428         case kCGPathElementAddCurveToPoint:
   1429             skPath->cubicTo(element->points[0].x, -element->points[0].y,
   1430                             element->points[1].x, -element->points[1].y,
   1431                             element->points[2].x, -element->points[2].y);
   1432             break;
   1433 
   1434         case kCGPathElementCloseSubpath:
   1435             skPath->close();
   1436             break;
   1437 
   1438         default:
   1439             SkDEBUGFAIL("Unknown path element!");
   1440             break;
   1441         }
   1442 }
   1443 
   1444 
   1445 ///////////////////////////////////////////////////////////////////////////////
   1446 
   1447 // Returns NULL on failure
   1448 // Call must still manage its ownership of provider
   1449 static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) {
   1450     AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider));
   1451     if (NULL == cg) {
   1452         return NULL;
   1453     }
   1454     CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, NULL);
   1455     return ct ? NewFromFontRef(ct, NULL, true) : NULL;
   1456 }
   1457 
   1458 // Web fonts added to the the CTFont registry do not return their character set.
   1459 // Iterate through the font in this case. The existing caller caches the result,
   1460 // so the performance impact isn't too bad.
   1461 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
   1462                                            SkTDArray<SkUnichar>* glyphToUnicode) {
   1463     glyphToUnicode->setCount(SkToInt(glyphCount));
   1464     SkUnichar* out = glyphToUnicode->begin();
   1465     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1466     UniChar unichar = 0;
   1467     while (glyphCount > 0) {
   1468         CGGlyph glyph;
   1469         if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1470             out[glyph] = unichar;
   1471             --glyphCount;
   1472         }
   1473         if (++unichar == 0) {
   1474             break;
   1475         }
   1476     }
   1477 }
   1478 
   1479 // Construct Glyph to Unicode table.
   1480 // Unicode code points that require conjugate pairs in utf16 are not
   1481 // supported.
   1482 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
   1483                                       SkTDArray<SkUnichar>* glyphToUnicode) {
   1484     AutoCFRelease<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
   1485     if (!charSet) {
   1486         populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
   1487         return;
   1488     }
   1489 
   1490     AutoCFRelease<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault,
   1491                                                                              charSet));
   1492     if (!bitmap) {
   1493         return;
   1494     }
   1495     CFIndex length = CFDataGetLength(bitmap);
   1496     if (!length) {
   1497         return;
   1498     }
   1499     if (length > 8192) {
   1500         // TODO: Add support for Unicode above 0xFFFF
   1501         // Consider only the BMP portion of the Unicode character points.
   1502         // The bitmap may contain other planes, up to plane 16.
   1503         // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html
   1504         length = 8192;
   1505     }
   1506     const UInt8* bits = CFDataGetBytePtr(bitmap);
   1507     glyphToUnicode->setCount(SkToInt(glyphCount));
   1508     SkUnichar* out = glyphToUnicode->begin();
   1509     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1510     for (int i = 0; i < length; i++) {
   1511         int mask = bits[i];
   1512         if (!mask) {
   1513             continue;
   1514         }
   1515         for (int j = 0; j < 8; j++) {
   1516             CGGlyph glyph;
   1517             UniChar unichar = static_cast<UniChar>((i << 3) + j);
   1518             if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1519                 out[glyph] = unichar;
   1520             }
   1521         }
   1522     }
   1523 }
   1524 
   1525 static bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) {
   1526     CGSize advance;
   1527     advance.width = 0;
   1528     CGGlyph glyph = gId;
   1529     CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &glyph, &advance, 1);
   1530     *data = sk_float_round2int(advance.width);
   1531     return true;
   1532 }
   1533 
   1534 /** Assumes src and dst are not NULL. */
   1535 static void CFStringToSkString(CFStringRef src, SkString* dst) {
   1536     // Reserve enough room for the worst-case string,
   1537     // plus 1 byte for the trailing null.
   1538     CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
   1539                                                        kCFStringEncodingUTF8) + 1;
   1540     dst->resize(length);
   1541     CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
   1542     // Resize to the actual UTF-8 length used, stripping the null character.
   1543     dst->resize(strlen(dst->c_str()));
   1544 }
   1545 
   1546 SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
   1547         PerGlyphInfo perGlyphInfo,
   1548         const uint32_t* glyphIDs,
   1549         uint32_t glyphIDsCount) const {
   1550 
   1551     CTFontRef originalCTFont = fFontRef.get();
   1552     AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes(
   1553             originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL));
   1554     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
   1555 
   1556     {
   1557         AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont));
   1558         if (fontName.get()) {
   1559             CFStringToSkString(fontName, &info->fFontName);
   1560         }
   1561     }
   1562 
   1563     CFIndex glyphCount = CTFontGetGlyphCount(ctFont);
   1564     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1565     info->fEmSize = CTFontGetUnitsPerEm(ctFont);
   1566     info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
   1567     info->fStyle = 0;
   1568 
   1569     if (perGlyphInfo & kToUnicode_PerGlyphInfo) {
   1570         populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode);
   1571     }
   1572 
   1573     // If it's not a truetype font, mark it as 'other'. Assume that TrueType
   1574     // fonts always have both glyf and loca tables. At the least, this is what
   1575     // sfntly needs to subset the font. CTFontCopyAttribute() does not always
   1576     // succeed in determining this directly.
   1577     if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
   1578         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1579         info->fItalicAngle = 0;
   1580         info->fAscent = 0;
   1581         info->fDescent = 0;
   1582         info->fStemV = 0;
   1583         info->fCapHeight = 0;
   1584         info->fBBox = SkIRect::MakeEmpty();
   1585         return info;
   1586     }
   1587 
   1588     info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1589     CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont);
   1590     if (symbolicTraits & kCTFontMonoSpaceTrait) {
   1591         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1592     }
   1593     if (symbolicTraits & kCTFontItalicTrait) {
   1594         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1595     }
   1596     CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
   1597     if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
   1598         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1599     } else if (stylisticClass & kCTFontScriptsClass) {
   1600         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1601     }
   1602     info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont);
   1603     info->fAscent = (int16_t) CTFontGetAscent(ctFont);
   1604     info->fDescent = (int16_t) CTFontGetDescent(ctFont);
   1605     info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont);
   1606     CGRect bbox = CTFontGetBoundingBox(ctFont);
   1607 
   1608     SkRect r;
   1609     r.set( CGToScalar(CGRectGetMinX_inline(bbox)),   // Left
   1610            CGToScalar(CGRectGetMaxY_inline(bbox)),   // Top
   1611            CGToScalar(CGRectGetMaxX_inline(bbox)),   // Right
   1612            CGToScalar(CGRectGetMinY_inline(bbox)));  // Bottom
   1613 
   1614     r.roundOut(&(info->fBBox));
   1615 
   1616     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1617     // This probably isn't very good with an italic font.
   1618     int16_t min_width = SHRT_MAX;
   1619     info->fStemV = 0;
   1620     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
   1621     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
   1622     CGGlyph glyphs[count];
   1623     CGRect boundingRects[count];
   1624     if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) {
   1625         CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation,
   1626                                         glyphs, boundingRects, count);
   1627         for (size_t i = 0; i < count; i++) {
   1628             int16_t width = (int16_t) boundingRects[i].size.width;
   1629             if (width > 0 && width < min_width) {
   1630                 min_width = width;
   1631                 info->fStemV = min_width;
   1632             }
   1633         }
   1634     }
   1635 
   1636     if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
   1637         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1638             skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0);
   1639             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1640             skia_advanced_typeface_metrics_utils::finishRange(info->fGlyphWidths.get(), 0,
   1641                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1642         } else {
   1643             info->fGlyphWidths.reset(
   1644                 skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(),
   1645                                SkToInt(glyphCount),
   1646                                glyphIDs,
   1647                                glyphIDsCount,
   1648                                &getWidthAdvance));
   1649         }
   1650     }
   1651     return info;
   1652 }
   1653 
   1654 ///////////////////////////////////////////////////////////////////////////////
   1655 
   1656 static SK_SFNT_ULONG get_font_type_tag(const SkTypeface_Mac* typeface) {
   1657     CTFontRef ctFont = typeface->fFontRef.get();
   1658     AutoCFRelease<CFNumberRef> fontFormatRef(
   1659             static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
   1660     if (!fontFormatRef) {
   1661         return 0;
   1662     }
   1663 
   1664     SInt32 fontFormatValue;
   1665     if (!CFNumberGetValue(fontFormatRef, kCFNumberSInt32Type, &fontFormatValue)) {
   1666         return 0;
   1667     }
   1668 
   1669     switch (fontFormatValue) {
   1670         case kCTFontFormatOpenTypePostScript:
   1671             return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
   1672         case kCTFontFormatOpenTypeTrueType:
   1673             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1674         case kCTFontFormatTrueType:
   1675             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1676         case kCTFontFormatPostScript:
   1677             return SkSFNTHeader::fontType_PostScript::TAG;
   1678         case kCTFontFormatBitmap:
   1679             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1680         case kCTFontFormatUnrecognized:
   1681         default:
   1682             //CT seems to be unreliable in being able to obtain the type,
   1683             //even if all we want is the first four bytes of the font resource.
   1684             //Just the presence of the FontForge 'FFTM' table seems to throw it off.
   1685             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1686     }
   1687 }
   1688 
   1689 SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
   1690     SK_SFNT_ULONG fontType = get_font_type_tag(this);
   1691     if (0 == fontType) {
   1692         return NULL;
   1693     }
   1694 
   1695     // get table tags
   1696     int numTables = this->countTables();
   1697     SkTDArray<SkFontTableTag> tableTags;
   1698     tableTags.setCount(numTables);
   1699     this->getTableTags(tableTags.begin());
   1700 
   1701     // calc total size for font, save sizes
   1702     SkTDArray<size_t> tableSizes;
   1703     size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1704     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1705         size_t tableSize = this->getTableSize(tableTags[tableIndex]);
   1706         totalSize += (tableSize + 3) & ~3;
   1707         *tableSizes.append() = tableSize;
   1708     }
   1709 
   1710     // reserve memory for stream, and zero it (tables must be zero padded)
   1711     SkMemoryStream* stream = new SkMemoryStream(totalSize);
   1712     char* dataStart = (char*)stream->getMemoryBase();
   1713     sk_bzero(dataStart, totalSize);
   1714     char* dataPtr = dataStart;
   1715 
   1716     // compute font header entries
   1717     uint16_t entrySelector = 0;
   1718     uint16_t searchRange = 1;
   1719     while (searchRange < numTables >> 1) {
   1720         entrySelector++;
   1721         searchRange <<= 1;
   1722     }
   1723     searchRange <<= 4;
   1724     uint16_t rangeShift = (numTables << 4) - searchRange;
   1725 
   1726     // write font header
   1727     SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
   1728     header->fontType = fontType;
   1729     header->numTables = SkEndian_SwapBE16(numTables);
   1730     header->searchRange = SkEndian_SwapBE16(searchRange);
   1731     header->entrySelector = SkEndian_SwapBE16(entrySelector);
   1732     header->rangeShift = SkEndian_SwapBE16(rangeShift);
   1733     dataPtr += sizeof(SkSFNTHeader);
   1734 
   1735     // write tables
   1736     SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
   1737     dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1738     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1739         size_t tableSize = tableSizes[tableIndex];
   1740         this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
   1741         entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
   1742         entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
   1743                                                                          tableSize));
   1744         entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
   1745         entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
   1746 
   1747         dataPtr += (tableSize + 3) & ~3;
   1748         ++entry;
   1749     }
   1750 
   1751     *ttcIndex = 0;
   1752     return stream;
   1753 }
   1754 
   1755 ///////////////////////////////////////////////////////////////////////////////
   1756 ///////////////////////////////////////////////////////////////////////////////
   1757 
   1758 int SkTypeface_Mac::onGetUPEM() const {
   1759     AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL));
   1760     return CGFontGetUnitsPerEm(cgFont);
   1761 }
   1762 
   1763 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
   1764     SkTypeface::LocalizedStrings* nameIter =
   1765         SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
   1766     if (NULL == nameIter) {
   1767         AutoCFRelease<CFStringRef> cfLanguage;
   1768         AutoCFRelease<CFStringRef> cfFamilyName(
   1769             CTFontCopyLocalizedName(fFontRef, kCTFontFamilyNameKey, &cfLanguage));
   1770 
   1771         SkString skLanguage;
   1772         SkString skFamilyName;
   1773         if (cfLanguage.get()) {
   1774             CFStringToSkString(cfLanguage.get(), &skLanguage);
   1775         } else {
   1776             skLanguage = "und"; //undetermined
   1777         }
   1778         if (cfFamilyName.get()) {
   1779             CFStringToSkString(cfFamilyName.get(), &skFamilyName);
   1780         }
   1781 
   1782         nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage);
   1783     }
   1784     return nameIter;
   1785 }
   1786 
   1787 // If, as is the case with web fonts, the CTFont data isn't available,
   1788 // the CGFont data may work. While the CGFont may always provide the
   1789 // right result, leave the CTFont code path to minimize disruption.
   1790 static CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) {
   1791     CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag,
   1792                                      kCTFontTableOptionNoOptions);
   1793     if (NULL == data) {
   1794         AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, NULL));
   1795         data = CGFontCopyTableForTag(cgFont, tag);
   1796     }
   1797     return data;
   1798 }
   1799 
   1800 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
   1801     AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(fFontRef,
   1802                                                 kCTFontTableOptionNoOptions));
   1803     if (NULL == cfArray) {
   1804         return 0;
   1805     }
   1806     int count = SkToInt(CFArrayGetCount(cfArray));
   1807     if (tags) {
   1808         for (int i = 0; i < count; ++i) {
   1809             uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i));
   1810             tags[i] = static_cast<SkFontTableTag>(fontTag);
   1811         }
   1812     }
   1813     return count;
   1814 }
   1815 
   1816 size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
   1817                                       size_t length, void* dstData) const {
   1818     AutoCFRelease<CFDataRef> srcData(copyTableFromFont(fFontRef, tag));
   1819     if (NULL == srcData) {
   1820         return 0;
   1821     }
   1822 
   1823     size_t srcSize = CFDataGetLength(srcData);
   1824     if (offset >= srcSize) {
   1825         return 0;
   1826     }
   1827     if (length > srcSize - offset) {
   1828         length = srcSize - offset;
   1829     }
   1830     if (dstData) {
   1831         memcpy(dstData, CFDataGetBytePtr(srcData) + offset, length);
   1832     }
   1833     return length;
   1834 }
   1835 
   1836 SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkDescriptor* desc) const {
   1837     return new SkScalerContext_Mac(const_cast<SkTypeface_Mac*>(this), desc);
   1838 }
   1839 
   1840 void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
   1841     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
   1842         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
   1843     {
   1844         rec->fMaskFormat = SkMask::kA8_Format;
   1845         // Render the glyphs as close as possible to what was requested.
   1846         // The above turns off subpixel rendering, but the user requested it.
   1847         // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
   1848         // See comments below for more details.
   1849         rec->setHinting(SkPaint::kNormal_Hinting);
   1850     }
   1851 
   1852     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag  |
   1853                                   SkScalerContext::kForceAutohinting_Flag  |
   1854                                   SkScalerContext::kLCD_BGROrder_Flag |
   1855                                   SkScalerContext::kLCD_Vertical_Flag;
   1856 
   1857     rec->fFlags &= ~flagsWeDontSupport;
   1858 
   1859     bool lcdSupport = supports_LCD();
   1860 
   1861     // Only two levels of hinting are supported.
   1862     // kNo_Hinting means avoid CoreGraphics outline dilation.
   1863     // kNormal_Hinting means CoreGraphics outline dilation is allowed.
   1864     // If there is no lcd support, hinting (dilation) cannot be supported.
   1865     SkPaint::Hinting hinting = rec->getHinting();
   1866     if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) {
   1867         hinting = SkPaint::kNo_Hinting;
   1868     } else if (SkPaint::kFull_Hinting == hinting) {
   1869         hinting = SkPaint::kNormal_Hinting;
   1870     }
   1871     rec->setHinting(hinting);
   1872 
   1873     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   1874     // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
   1875     // There is no current means to honor a request for unhinted lcd,
   1876     // so arbitrarilly ignore the hinting request and honor lcd.
   1877 
   1878     // Hinting and smoothing should be orthogonal, but currently they are not.
   1879     // CoreGraphics has no API to influence hinting. However, its lcd smoothed
   1880     // output is drawn from auto-dilated outlines (the amount of which is
   1881     // determined by AppleFontSmoothing). Its regular anti-aliased output is
   1882     // drawn from un-dilated outlines.
   1883 
   1884     // The behavior of Skia is as follows:
   1885     // [AA][no-hint]: generate AA using CoreGraphic's AA output.
   1886     // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
   1887     // channel. This matches [LCD][yes-hint] in weight.
   1888     // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
   1889     // Currenly side with LCD, effectively ignoring the hinting setting.
   1890     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
   1891 
   1892     if (isLCDFormat(rec->fMaskFormat)) {
   1893         if (lcdSupport) {
   1894             //CoreGraphics creates 555 masks for smoothed text anyway.
   1895             rec->fMaskFormat = SkMask::kLCD16_Format;
   1896             rec->setHinting(SkPaint::kNormal_Hinting);
   1897         } else {
   1898             rec->fMaskFormat = SkMask::kA8_Format;
   1899         }
   1900     }
   1901 
   1902     // CoreText provides no information as to whether a glyph will be color or not.
   1903     // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
   1904     // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
   1905     if (fHasColorGlyphs) {
   1906         rec->fMaskFormat = SkMask::kARGB32_Format;
   1907     }
   1908 
   1909     // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
   1910     // All other masks can use regular gamma.
   1911     if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) {
   1912 #ifndef SK_GAMMA_APPLY_TO_A8
   1913         rec->ignorePreBlend();
   1914 #endif
   1915     } else {
   1916         //CoreGraphics dialates smoothed text as needed.
   1917         rec->setContrast(0);
   1918     }
   1919 }
   1920 
   1921 // we take ownership of the ref
   1922 static const char* get_str(CFStringRef ref, SkString* str) {
   1923     if (NULL == ref) {
   1924         return NULL;
   1925     }
   1926     CFStringToSkString(ref, str);
   1927     CFSafeRelease(ref);
   1928     return str->c_str();
   1929 }
   1930 
   1931 void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
   1932     get_str(CTFontCopyFamilyName(fFontRef), familyName);
   1933 }
   1934 
   1935 void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
   1936                                          bool* isLocalStream) const {
   1937     SkString tmpStr;
   1938 
   1939     desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef), &tmpStr));
   1940     desc->setFullName(get_str(CTFontCopyFullName(fFontRef), &tmpStr));
   1941     desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef), &tmpStr));
   1942     *isLocalStream = fIsLocalStream;
   1943 }
   1944 
   1945 int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding,
   1946                                     uint16_t glyphs[], int glyphCount) const
   1947 {
   1948     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
   1949     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
   1950     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
   1951 
   1952     SkAutoSTMalloc<1024, UniChar> charStorage;
   1953     const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
   1954     int srcCount;
   1955     switch (encoding) {
   1956         case kUTF8_Encoding: {
   1957             const char* utf8 = reinterpret_cast<const char*>(chars);
   1958             UniChar* utf16 = charStorage.reset(2 * glyphCount);
   1959             src = utf16;
   1960             for (int i = 0; i < glyphCount; ++i) {
   1961                 SkUnichar uni = SkUTF8_NextUnichar(&utf8);
   1962                 utf16 += SkUTF16_FromUnichar(uni, utf16);
   1963             }
   1964             srcCount = SkToInt(utf16 - src);
   1965             break;
   1966         }
   1967         case kUTF16_Encoding: {
   1968             src = reinterpret_cast<const UniChar*>(chars);
   1969             int extra = 0;
   1970             for (int i = 0; i < glyphCount; ++i) {
   1971                 if (SkUTF16_IsHighSurrogate(src[i + extra])) {
   1972                     ++extra;
   1973                 }
   1974             }
   1975             srcCount = glyphCount + extra;
   1976             break;
   1977         }
   1978         case kUTF32_Encoding: {
   1979             const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(chars);
   1980             UniChar* utf16 = charStorage.reset(2 * glyphCount);
   1981             src = utf16;
   1982             for (int i = 0; i < glyphCount; ++i) {
   1983                 utf16 += SkUTF16_FromUnichar(utf32[i], utf16);
   1984             }
   1985             srcCount = SkToInt(utf16 - src);
   1986             break;
   1987         }
   1988     }
   1989 
   1990     // If glyphs is NULL, CT still needs glyph storage for finding the first failure.
   1991     // Also, if there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
   1992     SkAutoSTMalloc<1024, uint16_t> glyphStorage;
   1993     uint16_t* macGlyphs = glyphs;
   1994     if (NULL == macGlyphs || srcCount > glyphCount) {
   1995         macGlyphs = glyphStorage.reset(srcCount);
   1996     }
   1997 
   1998     bool allEncoded = CTFontGetGlyphsForCharacters(fFontRef, src, macGlyphs, srcCount);
   1999 
   2000     // If there were any non-bmp, then copy and compact.
   2001     // If 'glyphs' is NULL, then compact glyphStorage in-place.
   2002     // If all are bmp and 'glyphs' is non-NULL, 'glyphs' already contains the compact glyphs.
   2003     // If some are non-bmp and 'glyphs' is non-NULL, copy and compact into 'glyphs'.
   2004     uint16_t* compactedGlyphs = glyphs;
   2005     if (NULL == compactedGlyphs) {
   2006         compactedGlyphs = macGlyphs;
   2007     }
   2008     if (srcCount > glyphCount) {
   2009         int extra = 0;
   2010         for (int i = 0; i < glyphCount; ++i) {
   2011             compactedGlyphs[i] = macGlyphs[i + extra];
   2012             if (SkUTF16_IsHighSurrogate(src[i + extra])) {
   2013                 ++extra;
   2014             }
   2015         }
   2016     }
   2017 
   2018     if (allEncoded) {
   2019         return glyphCount;
   2020     }
   2021 
   2022     // If we got false, then we need to manually look for first failure.
   2023     for (int i = 0; i < glyphCount; ++i) {
   2024         if (0 == compactedGlyphs[i]) {
   2025             return i;
   2026         }
   2027     }
   2028     // Odd to get here, as we expected CT to have returned true up front.
   2029     return glyphCount;
   2030 }
   2031 
   2032 int SkTypeface_Mac::onCountGlyphs() const {
   2033     return SkToInt(CTFontGetGlyphCount(fFontRef));
   2034 }
   2035 
   2036 ///////////////////////////////////////////////////////////////////////////////
   2037 ///////////////////////////////////////////////////////////////////////////////
   2038 
   2039 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
   2040     AutoCFRelease<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
   2041     if (NULL == ref.get()) {
   2042         return false;
   2043     }
   2044     CFStringToSkString(ref, value);
   2045     return true;
   2046 }
   2047 
   2048 #include "SkFontMgr.h"
   2049 
   2050 static inline int sqr(int value) {
   2051     SkASSERT(SkAbs32(value) < 0x7FFF);  // check for overflow
   2052     return value * value;
   2053 }
   2054 
   2055 // We normalize each axis (weight, width, italic) to be base-900
   2056 static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
   2057     return sqr(a.weight() - b.weight()) +
   2058            sqr((a.width() - b.width()) * 100) +
   2059            sqr((a.isItalic() != b.isItalic()) * 900);
   2060 }
   2061 
   2062 static SkTypeface* createFromDesc(CFStringRef cfFamilyName, CTFontDescriptorRef desc) {
   2063     NameStyle cacheRequest;
   2064     SkString skFamilyName;
   2065     CFStringToSkString(cfFamilyName, &skFamilyName);
   2066     cacheRequest.fName = skFamilyName.c_str();
   2067     cacheRequest.fStyle = fontstyle_from_descriptor(desc);
   2068 
   2069     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cacheRequest);
   2070     if (face) {
   2071         return face;
   2072     }
   2073 
   2074     AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, NULL));
   2075     if (!ctFont) {
   2076         return NULL;
   2077     }
   2078 
   2079     bool isFixedPitch;
   2080     (void)computeStyleBits(ctFont, &isFixedPitch);
   2081 
   2082     face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, isFixedPitch,
   2083                                        ctFont.detach(), skFamilyName.c_str(), false));
   2084     SkTypefaceCache::Add(face, face->fontStyle());
   2085     return face;
   2086 }
   2087 
   2088 class SkFontStyleSet_Mac : public SkFontStyleSet {
   2089 public:
   2090     SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc)
   2091         : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL))
   2092         , fFamilyName(familyName)
   2093         , fCount(0) {
   2094         CFRetain(familyName);
   2095         if (NULL == fArray) {
   2096             fArray = CFArrayCreate(NULL, NULL, 0, NULL);
   2097         }
   2098         fCount = SkToInt(CFArrayGetCount(fArray));
   2099     }
   2100 
   2101     virtual ~SkFontStyleSet_Mac() {
   2102         CFRelease(fArray);
   2103         CFRelease(fFamilyName);
   2104     }
   2105 
   2106     int count() override {
   2107         return fCount;
   2108     }
   2109 
   2110     void getStyle(int index, SkFontStyle* style, SkString* name) override {
   2111         SkASSERT((unsigned)index < (unsigned)fCount);
   2112         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index);
   2113         if (style) {
   2114             *style = fontstyle_from_descriptor(desc);
   2115         }
   2116         if (name) {
   2117             if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
   2118                 name->reset();
   2119             }
   2120         }
   2121     }
   2122 
   2123     SkTypeface* createTypeface(int index) override {
   2124         SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray));
   2125         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index);
   2126 
   2127         return createFromDesc(fFamilyName, desc);
   2128     }
   2129 
   2130     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
   2131         if (0 == fCount) {
   2132             return NULL;
   2133         }
   2134         return createFromDesc(fFamilyName, findMatchingDesc(pattern));
   2135     }
   2136 
   2137 private:
   2138     CFArrayRef  fArray;
   2139     CFStringRef fFamilyName;
   2140     int         fCount;
   2141 
   2142     CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
   2143         int bestMetric = SK_MaxS32;
   2144         CTFontDescriptorRef bestDesc = NULL;
   2145 
   2146         for (int i = 0; i < fCount; ++i) {
   2147             CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, i);
   2148             int metric = compute_metric(pattern, fontstyle_from_descriptor(desc));
   2149             if (0 == metric) {
   2150                 return desc;
   2151             }
   2152             if (metric < bestMetric) {
   2153                 bestMetric = metric;
   2154                 bestDesc = desc;
   2155             }
   2156         }
   2157         SkASSERT(bestDesc);
   2158         return bestDesc;
   2159     }
   2160 };
   2161 
   2162 class SkFontMgr_Mac : public SkFontMgr {
   2163     CFArrayRef  fNames;
   2164     int         fCount;
   2165 
   2166     CFStringRef stringAt(int index) const {
   2167         SkASSERT((unsigned)index < (unsigned)fCount);
   2168         return (CFStringRef)CFArrayGetValueAtIndex(fNames, index);
   2169     }
   2170 
   2171     static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
   2172         AutoCFRelease<CFMutableDictionaryRef> cfAttr(
   2173                  CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
   2174                                            &kCFTypeDictionaryKeyCallBacks,
   2175                                            &kCFTypeDictionaryValueCallBacks));
   2176 
   2177         CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute, cfFamilyName);
   2178 
   2179         AutoCFRelease<CTFontDescriptorRef> desc(
   2180                                 CTFontDescriptorCreateWithAttributes(cfAttr));
   2181         return SkNEW_ARGS(SkFontStyleSet_Mac, (cfFamilyName, desc));
   2182     }
   2183 
   2184 public:
   2185     SkFontMgr_Mac()
   2186         : fNames(SkCTFontManagerCopyAvailableFontFamilyNames())
   2187         , fCount(fNames ? SkToInt(CFArrayGetCount(fNames)) : 0) {}
   2188 
   2189     virtual ~SkFontMgr_Mac() {
   2190         CFSafeRelease(fNames);
   2191     }
   2192 
   2193 protected:
   2194     int onCountFamilies() const override {
   2195         return fCount;
   2196     }
   2197 
   2198     void onGetFamilyName(int index, SkString* familyName) const override {
   2199         if ((unsigned)index < (unsigned)fCount) {
   2200             CFStringToSkString(this->stringAt(index), familyName);
   2201         } else {
   2202             familyName->reset();
   2203         }
   2204     }
   2205 
   2206     SkFontStyleSet* onCreateStyleSet(int index) const override {
   2207         if ((unsigned)index >= (unsigned)fCount) {
   2208             return NULL;
   2209         }
   2210         return CreateSet(this->stringAt(index));
   2211     }
   2212 
   2213     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
   2214         AutoCFRelease<CFStringRef> cfName(make_CFString(familyName));
   2215         return CreateSet(cfName);
   2216     }
   2217 
   2218     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   2219                                            const SkFontStyle&) const override {
   2220         return NULL;
   2221     }
   2222 
   2223     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
   2224                                                     const char* bcp47[], int bcp47Count,
   2225                                                     SkUnichar character) const override {
   2226         return NULL;
   2227     }
   2228 
   2229     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   2230                                          const SkFontStyle&) const override {
   2231         return NULL;
   2232     }
   2233 
   2234     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
   2235         AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromData(data));
   2236         if (NULL == pr) {
   2237             return NULL;
   2238         }
   2239         return create_from_dataProvider(pr);
   2240     }
   2241 
   2242     SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const override {
   2243         AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream));
   2244         if (NULL == pr) {
   2245             return NULL;
   2246         }
   2247         return create_from_dataProvider(pr);
   2248     }
   2249 
   2250     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
   2251         AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
   2252         if (NULL == pr) {
   2253             return NULL;
   2254         }
   2255         return create_from_dataProvider(pr);
   2256     }
   2257 
   2258     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   2259                                                unsigned styleBits) const override {
   2260 
   2261         SkFontStyle style = SkFontStyle((SkTypeface::Style)styleBits);
   2262         if (familyName) {
   2263             familyName = map_css_names(familyName);
   2264         }
   2265 
   2266         if (!familyName || !*familyName) {
   2267             familyName = FONT_DEFAULT_NAME;
   2268         }
   2269 
   2270         NameStyle cacheRequest = { familyName, style };
   2271         SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cacheRequest);
   2272 
   2273         if (NULL == face) {
   2274             face = NewFromName(familyName, style);
   2275             if (face) {
   2276                 SkTypefaceCache::Add(face, style);
   2277             } else {
   2278                 face = GetDefaultFace();
   2279                 face->ref();
   2280             }
   2281         }
   2282         return face;
   2283     }
   2284 };
   2285 
   2286 ///////////////////////////////////////////////////////////////////////////////
   2287 
   2288 SkFontMgr* SkFontMgr::Factory() {
   2289     return SkNEW(SkFontMgr_Mac);
   2290 }
   2291