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