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 <CoreGraphics/CoreGraphics.h>
     17 #include <CoreFoundation/CoreFoundation.h>
     18 #endif
     19 
     20 #include "SkFontHost.h"
     21 #include "SkCGUtils.h"
     22 #include "SkColorPriv.h"
     23 #include "SkDescriptor.h"
     24 #include "SkEndian.h"
     25 #include "SkFontDescriptor.h"
     26 #include "SkFloatingPoint.h"
     27 #include "SkGlyph.h"
     28 #include "SkMaskGamma.h"
     29 #include "SkSFNTHeader.h"
     30 #include "SkOTTable_glyf.h"
     31 #include "SkOTTable_head.h"
     32 #include "SkOTTable_hhea.h"
     33 #include "SkOTTable_loca.h"
     34 #include "SkOTUtils.h"
     35 #include "SkPaint.h"
     36 #include "SkPath.h"
     37 #include "SkString.h"
     38 #include "SkStream.h"
     39 #include "SkThread.h"
     40 #include "SkTypeface_mac.h"
     41 #include "SkUtils.h"
     42 #include "SkTypefaceCache.h"
     43 
     44 class SkScalerContext_Mac;
     45 
     46 // Being templated and taking const T* prevents calling
     47 // CFSafeRelease(autoCFRelease) through implicit conversion.
     48 template <typename T> static void CFSafeRelease(/*CFTypeRef*/const T* cfTypeRef) {
     49     if (cfTypeRef) {
     50         CFRelease(cfTypeRef);
     51     }
     52 }
     53 
     54 // Being templated and taking const T* prevents calling
     55 // CFSafeRetain(autoCFRelease) through implicit conversion.
     56 template <typename T> static void CFSafeRetain(/*CFTypeRef*/const T* cfTypeRef) {
     57     if (cfTypeRef) {
     58         CFRetain(cfTypeRef);
     59     }
     60 }
     61 
     62 /** Acts like a CFRef, but calls CFSafeRelease when it goes out of scope. */
     63 template<typename CFRef> class AutoCFRelease : private SkNoncopyable {
     64 public:
     65     explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { }
     66     ~AutoCFRelease() { CFSafeRelease(fCFRef); }
     67 
     68     void reset(CFRef that = NULL) {
     69         CFSafeRetain(that);
     70         CFSafeRelease(fCFRef);
     71         fCFRef = that;
     72     }
     73 
     74     AutoCFRelease& operator =(CFRef that) {
     75         reset(that);
     76         return *this;
     77     }
     78 
     79     operator CFRef() const { return fCFRef; }
     80     CFRef get() const { return fCFRef; }
     81 
     82 private:
     83     CFRef fCFRef;
     84 };
     85 
     86 template<typename T> class AutoCGTable : SkNoncopyable {
     87 public:
     88     AutoCGTable(CGFontRef font)
     89     //Undocumented: the tag parameter in this call is expected in machine order and not BE order.
     90     : fCFData(CGFontCopyTableForTag(font, SkSetFourByteTag(T::TAG0, T::TAG1, T::TAG2, T::TAG3)))
     91     , fData(fCFData ? reinterpret_cast<const T*>(CFDataGetBytePtr(fCFData)) : NULL)
     92     { }
     93 
     94     const T* operator->() const { return fData; }
     95 
     96 private:
     97     AutoCFRelease<CFDataRef> fCFData;
     98 public:
     99     const T* fData;
    100 };
    101 
    102 // inline versions of these rect helpers
    103 
    104 static bool CGRectIsEmpty_inline(const CGRect& rect) {
    105     return rect.size.width <= 0 || rect.size.height <= 0;
    106 }
    107 
    108 static void CGRectInset_inline(CGRect* rect, CGFloat dx, CGFloat dy) {
    109     rect->origin.x += dx;
    110     rect->origin.y += dy;
    111     rect->size.width -= dx * 2;
    112     rect->size.height -= dy * 2;
    113 }
    114 
    115 static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
    116     return rect.origin.x;
    117 }
    118 
    119 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) {
    120     return rect.origin.x + rect.size.width;
    121 }
    122 
    123 static CGFloat CGRectGetMinY_inline(const CGRect& rect) {
    124     return rect.origin.y;
    125 }
    126 
    127 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
    128     return rect.origin.y + rect.size.height;
    129 }
    130 
    131 static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
    132     return rect.size.width;
    133 }
    134 
    135 ///////////////////////////////////////////////////////////////////////////////
    136 
    137 static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
    138                              size_t width, size_t height, size_t rowBytes) {
    139     SkASSERT(width);
    140     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
    141 
    142     if (width >= 32) {
    143         while (height) {
    144             sk_memset32(ptr, value, width);
    145             ptr = (uint32_t*)((char*)ptr + rowBytes);
    146             height -= 1;
    147         }
    148         return;
    149     }
    150 
    151     rowBytes -= width * sizeof(uint32_t);
    152 
    153     if (width >= 8) {
    154         while (height) {
    155             int w = width;
    156             do {
    157                 *ptr++ = value; *ptr++ = value;
    158                 *ptr++ = value; *ptr++ = value;
    159                 *ptr++ = value; *ptr++ = value;
    160                 *ptr++ = value; *ptr++ = value;
    161                 w -= 8;
    162             } while (w >= 8);
    163             while (--w >= 0) {
    164                 *ptr++ = value;
    165             }
    166             ptr = (uint32_t*)((char*)ptr + rowBytes);
    167             height -= 1;
    168         }
    169     } else {
    170         while (height) {
    171             int w = width;
    172             do {
    173                 *ptr++ = value;
    174             } while (--w > 0);
    175             ptr = (uint32_t*)((char*)ptr + rowBytes);
    176             height -= 1;
    177         }
    178     }
    179 }
    180 
    181 #include <sys/utsname.h>
    182 
    183 typedef uint32_t CGRGBPixel;
    184 
    185 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
    186     return pixel & 0xFF;
    187 }
    188 
    189 // The calls to support subpixel are present in 10.5, but are not included in
    190 // the 10.5 SDK. The needed calls have been extracted from the 10.6 SDK and are
    191 // included below. To verify that CGContextSetShouldSubpixelQuantizeFonts, for
    192 // instance, is present in the 10.5 CoreGraphics libary, use:
    193 //   cd /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/
    194 //   cd ApplicationServices.framework/Frameworks/CoreGraphics.framework/
    195 //   nm CoreGraphics | grep CGContextSetShouldSubpixelQuantizeFonts
    196 
    197 #if !defined(MAC_OS_X_VERSION_10_6) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6)
    198 CG_EXTERN void CGContextSetAllowsFontSmoothing(CGContextRef context, bool value);
    199 CG_EXTERN void CGContextSetAllowsFontSubpixelPositioning(CGContextRef context, bool value);
    200 CG_EXTERN void CGContextSetShouldSubpixelPositionFonts(CGContextRef context, bool value);
    201 CG_EXTERN void CGContextSetAllowsFontSubpixelQuantization(CGContextRef context, bool value);
    202 CG_EXTERN void CGContextSetShouldSubpixelQuantizeFonts(CGContextRef context, bool value);
    203 #endif
    204 
    205 static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
    206 
    207 // See Source/WebKit/chromium/base/mac/mac_util.mm DarwinMajorVersionInternal for original source.
    208 static int readVersion() {
    209     struct utsname info;
    210     if (uname(&info) != 0) {
    211         SkDebugf("uname failed\n");
    212         return 0;
    213     }
    214     if (strcmp(info.sysname, "Darwin") != 0) {
    215         SkDebugf("unexpected uname sysname %s\n", info.sysname);
    216         return 0;
    217     }
    218     char* dot = strchr(info.release, '.');
    219     if (!dot) {
    220         SkDebugf("expected dot in uname release %s\n", info.release);
    221         return 0;
    222     }
    223     int version = atoi(info.release);
    224     if (version == 0) {
    225         SkDebugf("could not parse uname release %s\n", info.release);
    226     }
    227     return version;
    228 }
    229 
    230 static int darwinVersion() {
    231     static int darwin_version = readVersion();
    232     return darwin_version;
    233 }
    234 
    235 static bool isLeopard() {
    236     return darwinVersion() == 9;
    237 }
    238 
    239 static bool isSnowLeopard() {
    240     return darwinVersion() == 10;
    241 }
    242 
    243 static bool isLion() {
    244     return darwinVersion() == 11;
    245 }
    246 
    247 static bool isMountainLion() {
    248     return darwinVersion() == 12;
    249 }
    250 
    251 static bool isLCDFormat(unsigned format) {
    252     return SkMask::kLCD16_Format == format || SkMask::kLCD32_Format == format;
    253 }
    254 
    255 static CGFloat ScalarToCG(SkScalar scalar) {
    256     if (sizeof(CGFloat) == sizeof(float)) {
    257         return SkScalarToFloat(scalar);
    258     } else {
    259         SkASSERT(sizeof(CGFloat) == sizeof(double));
    260         return (CGFloat) SkScalarToDouble(scalar);
    261     }
    262 }
    263 
    264 static SkScalar CGToScalar(CGFloat cgFloat) {
    265     if (sizeof(CGFloat) == sizeof(float)) {
    266         return SkFloatToScalar(cgFloat);
    267     } else {
    268         SkASSERT(sizeof(CGFloat) == sizeof(double));
    269         return SkDoubleToScalar(cgFloat);
    270     }
    271 }
    272 
    273 static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix,
    274                                                    SkScalar sx = SK_Scalar1,
    275                                                    SkScalar sy = SK_Scalar1) {
    276     return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx),
    277                                  -ScalarToCG(matrix[SkMatrix::kMSkewY]  * sy),
    278                                  -ScalarToCG(matrix[SkMatrix::kMSkewX]  * sx),
    279                                   ScalarToCG(matrix[SkMatrix::kMScaleY] * sy),
    280                                   ScalarToCG(matrix[SkMatrix::kMTransX] * sx),
    281                                   ScalarToCG(matrix[SkMatrix::kMTransY] * sy));
    282 }
    283 
    284 static SkScalar getFontScale(CGFontRef cgFont) {
    285     int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
    286     return SkScalarInvert(SkIntToScalar(unitsPerEm));
    287 }
    288 
    289 ///////////////////////////////////////////////////////////////////////////////
    290 
    291 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
    292 #define BITMAP_INFO_GRAY (kCGImageAlphaNone)
    293 
    294 /**
    295  * There does not appear to be a publicly accessable API for determining if lcd
    296  * font smoothing will be applied if we request it. The main issue is that if
    297  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
    298  */
    299 static bool supports_LCD() {
    300     static int gSupportsLCD = -1;
    301     if (gSupportsLCD >= 0) {
    302         return (bool) gSupportsLCD;
    303     }
    304     uint32_t rgb = 0;
    305     AutoCFRelease<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
    306     AutoCFRelease<CGContextRef> cgContext(CGBitmapContextCreate(&rgb, 1, 1, 8, 4,
    307                                                                 colorspace, BITMAP_INFO_RGB));
    308     CGContextSelectFont(cgContext, "Helvetica", 16, kCGEncodingMacRoman);
    309     CGContextSetShouldSmoothFonts(cgContext, true);
    310     CGContextSetShouldAntialias(cgContext, true);
    311     CGContextSetTextDrawingMode(cgContext, kCGTextFill);
    312     CGContextSetGrayFillColor(cgContext, 1, 1);
    313     CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1);
    314     uint32_t r = (rgb >> 16) & 0xFF;
    315     uint32_t g = (rgb >>  8) & 0xFF;
    316     uint32_t b = (rgb >>  0) & 0xFF;
    317     gSupportsLCD = (r != g || r != b);
    318     return (bool) gSupportsLCD;
    319 }
    320 
    321 class Offscreen {
    322 public:
    323     Offscreen();
    324 
    325     CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    326                       CGGlyph glyphID, size_t* rowBytesPtr,
    327                       bool generateA8FromLCD);
    328 
    329 private:
    330     enum {
    331         kSize = 32 * 32 * sizeof(CGRGBPixel)
    332     };
    333     SkAutoSMalloc<kSize> fImageStorage;
    334     AutoCFRelease<CGColorSpaceRef> fRGBSpace;
    335 
    336     // cached state
    337     AutoCFRelease<CGContextRef> fCG;
    338     SkISize fSize;
    339     bool fDoAA;
    340     bool fDoLCD;
    341 
    342     static int RoundSize(int dimension) {
    343         return SkNextPow2(dimension);
    344     }
    345 };
    346 
    347 Offscreen::Offscreen() : fRGBSpace(NULL), fCG(NULL) {
    348     fSize.set(0, 0);
    349 }
    350 
    351 ///////////////////////////////////////////////////////////////////////////////
    352 
    353 static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isMonospace) {
    354     unsigned style = SkTypeface::kNormal;
    355     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font);
    356 
    357     if (traits & kCTFontBoldTrait) {
    358         style |= SkTypeface::kBold;
    359     }
    360     if (traits & kCTFontItalicTrait) {
    361         style |= SkTypeface::kItalic;
    362     }
    363     if (isMonospace) {
    364         *isMonospace = (traits & kCTFontMonoSpaceTrait) != 0;
    365     }
    366     return (SkTypeface::Style)style;
    367 }
    368 
    369 static SkFontID CTFontRef_to_SkFontID(CTFontRef fontRef) {
    370     SkFontID id = 0;
    371 // CTFontGetPlatformFont and ATSFontRef are not supported on iOS, so we have to
    372 // bracket this to be Mac only.
    373 #ifdef SK_BUILD_FOR_MAC
    374     ATSFontRef ats = CTFontGetPlatformFont(fontRef, NULL);
    375     id = (SkFontID)ats;
    376     if (id != 0) {
    377         id &= 0x3FFFFFFF; // make top two bits 00
    378         return id;
    379     }
    380 #endif
    381     // CTFontGetPlatformFont returns NULL if the font is local
    382     // (e.g., was created by a CSS3 @font-face rule).
    383     AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fontRef, NULL));
    384     AutoCGTable<SkOTTableHead> headTable(cgFont);
    385     if (headTable.fData) {
    386         id = (SkFontID) headTable->checksumAdjustment;
    387         id = (id & 0x3FFFFFFF) | 0x40000000; // make top two bits 01
    388     }
    389     // well-formed fonts have checksums, but as a last resort, use the pointer.
    390     if (id == 0) {
    391         id = (SkFontID) (uintptr_t) fontRef;
    392         id = (id & 0x3FFFFFFF) | 0x80000000; // make top two bits 10
    393     }
    394     return id;
    395 }
    396 
    397 class SkTypeface_Mac : public SkTypeface {
    398 public:
    399     SkTypeface_Mac(SkTypeface::Style style, SkFontID fontID, bool isMonospace,
    400                    CTFontRef fontRef, const char name[])
    401     : SkTypeface(style, fontID, isMonospace)
    402     , fName(name)
    403     , fFontRef(fontRef) // caller has already called CFRetain for us
    404     {
    405         SkASSERT(fontRef);
    406     }
    407 
    408     SkString fName;
    409     AutoCFRelease<CTFontRef> fFontRef;
    410 };
    411 
    412 static CTFontRef typeface_to_fontref(const SkTypeface* face) {
    413     const SkTypeface_Mac* macface = reinterpret_cast<const SkTypeface_Mac*>(face);
    414     return macface->fFontRef;
    415 }
    416 
    417 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[]) {
    418     SkASSERT(fontRef);
    419     bool isMonospace;
    420     SkTypeface::Style style = computeStyleBits(fontRef, &isMonospace);
    421     SkFontID fontID = CTFontRef_to_SkFontID(fontRef);
    422 
    423     return new SkTypeface_Mac(style, fontID, isMonospace, fontRef, name);
    424 }
    425 
    426 static SkTypeface* NewFromName(const char familyName[], SkTypeface::Style theStyle) {
    427     CTFontRef ctFont = NULL;
    428 
    429     CTFontSymbolicTraits ctFontTraits = 0;
    430     if (theStyle & SkTypeface::kBold) {
    431         ctFontTraits |= kCTFontBoldTrait;
    432     }
    433     if (theStyle & SkTypeface::kItalic) {
    434         ctFontTraits |= kCTFontItalicTrait;
    435     }
    436 
    437     // Create the font info
    438     AutoCFRelease<CFStringRef> cfFontName(
    439             CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8));
    440 
    441     AutoCFRelease<CFNumberRef> cfFontTraits(
    442             CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
    443 
    444     AutoCFRelease<CFMutableDictionaryRef> cfAttributes(
    445             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    446                                       &kCFTypeDictionaryKeyCallBacks,
    447                                       &kCFTypeDictionaryValueCallBacks));
    448 
    449     AutoCFRelease<CFMutableDictionaryRef> cfTraits(
    450             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
    451                                       &kCFTypeDictionaryKeyCallBacks,
    452                                       &kCFTypeDictionaryValueCallBacks));
    453 
    454     // Create the font
    455     if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) {
    456         CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
    457 
    458         CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
    459         CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
    460 
    461         AutoCFRelease<CTFontDescriptorRef> ctFontDesc(
    462                 CTFontDescriptorCreateWithAttributes(cfAttributes));
    463 
    464         if (ctFontDesc != NULL) {
    465             if (isLeopard()) {
    466                 // CTFontCreateWithFontDescriptor on Leopard ignores the name
    467                 AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithName(cfFontName, 1, NULL));
    468                 ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, ctFontDesc);
    469             } else {
    470                 ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
    471             }
    472         }
    473     }
    474 
    475     return ctFont ? NewFromFontRef(ctFont, familyName) : NULL;
    476 }
    477 
    478 static CTFontRef GetFontRefFromFontID(SkFontID fontID) {
    479     SkTypeface_Mac* face = reinterpret_cast<SkTypeface_Mac*>(SkTypefaceCache::FindByID(fontID));
    480     return face ? face->fFontRef.get() : NULL;
    481 }
    482 
    483 static SkTypeface* GetDefaultFace() {
    484     SK_DECLARE_STATIC_MUTEX(gMutex);
    485     SkAutoMutexAcquire ma(gMutex);
    486 
    487     static SkTypeface* gDefaultFace;
    488 
    489     if (NULL == gDefaultFace) {
    490         gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkTypeface::kNormal);
    491         SkTypefaceCache::Add(gDefaultFace, SkTypeface::kNormal);
    492     }
    493     return gDefaultFace;
    494 }
    495 
    496 ///////////////////////////////////////////////////////////////////////////////
    497 
    498 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face);
    499 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
    500     const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face;
    501     return macface ? macface->fFontRef.get() : NULL;
    502 }
    503 
    504 /*  This function is visible on the outside. It first searches the cache, and if
    505  *  not found, returns a new entry (after adding it to the cache).
    506  */
    507 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) {
    508     SkFontID fontID = CTFontRef_to_SkFontID(fontRef);
    509     SkTypeface* face = SkTypefaceCache::FindByID(fontID);
    510     if (face) {
    511         face->ref();
    512     } else {
    513         face = NewFromFontRef(fontRef, NULL);
    514         SkTypefaceCache::Add(face, face->style());
    515         // NewFromFontRef doesn't retain the parameter, but the typeface it
    516         // creates does release it in its destructor, so we balance that with
    517         // a retain call here.
    518         CFRetain(fontRef);
    519     }
    520     SkASSERT(face->getRefCnt() > 1);
    521     return face;
    522 }
    523 
    524 struct NameStyleRec {
    525     const char*         fName;
    526     SkTypeface::Style   fStyle;
    527 };
    528 
    529 static bool FindByNameStyle(SkTypeface* face, SkTypeface::Style style,
    530                             void* ctx) {
    531     const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face);
    532     const NameStyleRec* rec = reinterpret_cast<const NameStyleRec*>(ctx);
    533 
    534     return rec->fStyle == style && mface->fName.equals(rec->fName);
    535 }
    536 
    537 static const char* map_css_names(const char* name) {
    538     static const struct {
    539         const char* fFrom;  // name the caller specified
    540         const char* fTo;    // "canonical" name we map to
    541     } gPairs[] = {
    542         { "sans-serif", "Helvetica" },
    543         { "serif",      "Times"     },
    544         { "monospace",  "Courier"   }
    545     };
    546 
    547     for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
    548         if (strcmp(name, gPairs[i].fFrom) == 0) {
    549             return gPairs[i].fTo;
    550         }
    551     }
    552     return name;    // no change
    553 }
    554 
    555 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
    556                                        const char familyName[],
    557                                        SkTypeface::Style style) {
    558     if (familyName) {
    559         familyName = map_css_names(familyName);
    560     }
    561 
    562     // Clone an existing typeface
    563     // TODO: only clone if style matches the familyFace's style...
    564     if (familyName == NULL && familyFace != NULL) {
    565         familyFace->ref();
    566         return const_cast<SkTypeface*>(familyFace);
    567     }
    568 
    569     if (!familyName || !*familyName) {
    570         familyName = FONT_DEFAULT_NAME;
    571     }
    572 
    573     NameStyleRec rec = { familyName, style };
    574     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByNameStyle, &rec);
    575 
    576     if (NULL == face) {
    577         face = NewFromName(familyName, style);
    578         if (face) {
    579             SkTypefaceCache::Add(face, style);
    580         } else {
    581             face = GetDefaultFace();
    582             face->ref();
    583         }
    584     }
    585     return face;
    586 }
    587 
    588 static void flip(SkMatrix* matrix) {
    589     matrix->setSkewX(-matrix->getSkewX());
    590     matrix->setSkewY(-matrix->getSkewY());
    591 }
    592 
    593 ///////////////////////////////////////////////////////////////////////////////
    594 
    595 struct GlyphRect {
    596     int16_t fMinX;
    597     int16_t fMinY;
    598     int16_t fMaxX;
    599     int16_t fMaxY;
    600 };
    601 
    602 class SkScalerContext_Mac : public SkScalerContext {
    603 public:
    604     SkScalerContext_Mac(const SkDescriptor* desc);
    605     virtual ~SkScalerContext_Mac(void);
    606 
    607 
    608 protected:
    609     unsigned generateGlyphCount(void) SK_OVERRIDE;
    610     uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
    611     void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
    612     void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
    613     void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
    614     void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
    615     void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY) SK_OVERRIDE;
    616 
    617 private:
    618     static void CTPathElement(void *info, const CGPathElement *element);
    619     uint16_t getFBoundingBoxesGlyphOffset();
    620     void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const;
    621     bool generateBBoxes();
    622 
    623     CGAffineTransform fTransform;
    624     SkMatrix fUnitMatrix; // without font size
    625     SkMatrix fVerticalMatrix; // unit rotated
    626     SkMatrix fMatrix; // with font size
    627     SkMatrix fFBoundingBoxesMatrix; // lion-specific fix
    628     Offscreen fOffscreen;
    629     AutoCFRelease<CTFontRef> fCTFont;
    630     AutoCFRelease<CTFontRef> fCTVerticalFont; // for vertical advance
    631     AutoCFRelease<CGFontRef> fCGFont;
    632     GlyphRect* fFBoundingBoxes;
    633     uint16_t fFBoundingBoxesGlyphOffset;
    634     uint16_t fGlyphCount;
    635     bool fGeneratedFBoundingBoxes;
    636     bool fDoSubPosition;
    637     bool fVertical;
    638 
    639     friend class Offscreen;
    640 };
    641 
    642 SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
    643         : SkScalerContext(desc)
    644         , fFBoundingBoxes(NULL)
    645         , fFBoundingBoxesGlyphOffset(0)
    646         , fGeneratedFBoundingBoxes(false)
    647 {
    648     CTFontRef ctFont = GetFontRefFromFontID(fRec.fFontID);
    649     CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
    650 
    651     // Get the state we need
    652     fRec.getSingleMatrix(&fMatrix);
    653     fUnitMatrix = fMatrix;
    654 
    655     // extract the font size out of the matrix, but leave the skewing for italic
    656     SkScalar reciprocal = SkScalarInvert(fRec.fTextSize);
    657     fUnitMatrix.preScale(reciprocal, reciprocal);
    658 
    659     SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
    660 
    661     fTransform = MatrixToCGAffineTransform(fMatrix);
    662 
    663     CGAffineTransform transform;
    664     CGFloat unitFontSize;
    665     if (isLeopard()) {
    666         // passing 1 for pointSize to Leopard sets the font size to 1 pt.
    667         // pass the CoreText size explicitly
    668         transform = MatrixToCGAffineTransform(fUnitMatrix);
    669         unitFontSize = SkScalarToFloat(fRec.fTextSize);
    670     } else {
    671         // since our matrix includes everything, we pass 1 for pointSize
    672         transform = fTransform;
    673         unitFontSize = 1;
    674     }
    675     flip(&fUnitMatrix); // flip to fix up bounds later
    676     fVertical = SkToBool(fRec.fFlags & kVertical_Flag);
    677     AutoCFRelease<CTFontDescriptorRef> ctFontDesc;
    678     if (fVertical) {
    679         AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMutable(
    680                 kCFAllocatorDefault, 0,
    681                 &kCFTypeDictionaryKeyCallBacks,
    682                 &kCFTypeDictionaryValueCallBacks));
    683         if (cfAttributes) {
    684             CTFontOrientation ctOrientation = kCTFontVerticalOrientation;
    685             AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate(
    686                     kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation));
    687             CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVertical);
    688             ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
    689         }
    690     }
    691     fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, ctFontDesc);
    692     fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL);
    693     if (fVertical) {
    694         CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
    695         transform = CGAffineTransformConcat(rotateLeft, transform);
    696         fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, NULL);
    697         fVerticalMatrix = fUnitMatrix;
    698         if (isSnowLeopard()) {
    699             SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont));
    700             fVerticalMatrix.preScale(scale, scale);
    701         } else {
    702             fVerticalMatrix.preRotate(SkIntToScalar(90));
    703         }
    704         fVerticalMatrix.postScale(SK_Scalar1, -SK_Scalar1);
    705     }
    706     fGlyphCount = SkToU16(numGlyphs);
    707     fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
    708 }
    709 
    710 SkScalerContext_Mac::~SkScalerContext_Mac() {
    711     delete[] fFBoundingBoxes;
    712 }
    713 
    714 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
    715                              CGGlyph glyphID, size_t* rowBytesPtr,
    716                              bool generateA8FromLCD) {
    717     if (!fRGBSpace) {
    718         //It doesn't appear to matter what color space is specified.
    719         //Regular blends and antialiased text are always (s*a + d*(1-a))
    720         //and smoothed text is always g=2.0.
    721         fRGBSpace = CGColorSpaceCreateDeviceRGB();
    722     }
    723 
    724     // default to kBW_Format
    725     bool doAA = false;
    726     bool doLCD = false;
    727 
    728     if (SkMask::kBW_Format != glyph.fMaskFormat) {
    729         doLCD = true;
    730         doAA = true;
    731     }
    732 
    733     // FIXME: lcd smoothed un-hinted rasterization unsupported.
    734     if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) {
    735         doLCD = false;
    736         doAA = true;
    737     }
    738 
    739     size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    740     if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) {
    741         if (fSize.fWidth < glyph.fWidth) {
    742             fSize.fWidth = RoundSize(glyph.fWidth);
    743         }
    744         if (fSize.fHeight < glyph.fHeight) {
    745             fSize.fHeight = RoundSize(glyph.fHeight);
    746         }
    747 
    748         rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
    749         void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
    750         fCG = CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
    751                                     rowBytes, fRGBSpace, BITMAP_INFO_RGB);
    752 
    753         // skia handles quantization itself, so we disable this for cg to get
    754         // full fractional data from them.
    755         CGContextSetAllowsFontSubpixelQuantization(fCG, false);
    756         CGContextSetShouldSubpixelQuantizeFonts(fCG, false);
    757 
    758         CGContextSetTextDrawingMode(fCG, kCGTextFill);
    759         CGContextSetFont(fCG, context.fCGFont);
    760         CGContextSetFontSize(fCG, 1);
    761         CGContextSetTextMatrix(fCG, context.fTransform);
    762 
    763         CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition);
    764         CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition);
    765 
    766         // Draw white on black to create mask.
    767         // TODO: Draw black on white and invert, CG has a special case codepath.
    768         CGContextSetGrayFillColor(fCG, 1.0f, 1.0f);
    769 
    770         // force our checks below to happen
    771         fDoAA = !doAA;
    772         fDoLCD = !doLCD;
    773     }
    774 
    775     if (fDoAA != doAA) {
    776         CGContextSetShouldAntialias(fCG, doAA);
    777         fDoAA = doAA;
    778     }
    779     if (fDoLCD != doLCD) {
    780         CGContextSetShouldSmoothFonts(fCG, doLCD);
    781         fDoLCD = doLCD;
    782     }
    783 
    784     CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
    785     // skip rows based on the glyph's height
    786     image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth;
    787 
    788     // erase to black
    789     sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes);
    790 
    791     float subX = 0;
    792     float subY = 0;
    793     if (context.fDoSubPosition) {
    794         subX = SkFixedToFloat(glyph.getSubXFixed());
    795         subY = SkFixedToFloat(glyph.getSubYFixed());
    796     }
    797     if (context.fVertical) {
    798         SkIPoint offset;
    799         context.getVerticalOffset(glyphID, &offset);
    800         subX += offset.fX;
    801         subY += offset.fY;
    802     }
    803     CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX,
    804                                glyph.fTop + glyph.fHeight - subY,
    805                                &glyphID, 1);
    806 
    807     SkASSERT(rowBytesPtr);
    808     *rowBytesPtr = rowBytes;
    809     return image;
    810 }
    811 
    812 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const {
    813     CGSize vertOffset;
    814     CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffset, 1);
    815     const SkPoint trans = {CGToScalar(vertOffset.width),
    816                            CGToScalar(vertOffset.height)};
    817     SkPoint floatOffset;
    818     fVerticalMatrix.mapPoints(&floatOffset, &trans, 1);
    819     if (!isSnowLeopard()) {
    820     // SnowLeopard fails to apply the font's matrix to the vertical metrics,
    821     // but Lion and Leopard do. The unit matrix describes the font's matrix at
    822     // point size 1. There may be some way to avoid mapping here by setting up
    823     // fVerticalMatrix differently, but this works for now.
    824         fUnitMatrix.mapPoints(&floatOffset, 1);
    825     }
    826     offset->fX = SkScalarRound(floatOffset.fX);
    827     offset->fY = SkScalarRound(floatOffset.fY);
    828 }
    829 
    830 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() {
    831     if (fFBoundingBoxesGlyphOffset) {
    832         return fFBoundingBoxesGlyphOffset;
    833     }
    834     fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts
    835     AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont);
    836     if (hheaTable.fData) {
    837         fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetrics);
    838     }
    839     return fFBoundingBoxesGlyphOffset;
    840 }
    841 
    842 /*
    843  * Lion has a bug in CTFontGetBoundingRectsForGlyphs which returns a bad value
    844  * in theBounds.origin.x for fonts whose numOfLogHorMetrics is less than its
    845  * glyph count. This workaround reads the glyph bounds from the font directly.
    846  *
    847  * The table is computed only if the font is a TrueType font, if the glyph
    848  * value is >= fFBoundingBoxesGlyphOffset. (called only if fFBoundingBoxesGlyphOffset < fGlyphCount).
    849  *
    850  * TODO: A future optimization will compute fFBoundingBoxes once per CGFont, and
    851  * compute fFBoundingBoxesMatrix once per font context.
    852  */
    853 bool SkScalerContext_Mac::generateBBoxes() {
    854     if (fGeneratedFBoundingBoxes) {
    855         return NULL != fFBoundingBoxes;
    856     }
    857     fGeneratedFBoundingBoxes = true;
    858 
    859     AutoCGTable<SkOTTableHead> headTable(fCGFont);
    860     if (!headTable.fData) {
    861         return false;
    862     }
    863 
    864     AutoCGTable<SkOTTableIndexToLocation> locaTable(fCGFont);
    865     if (!locaTable.fData) {
    866         return false;
    867     }
    868 
    869     AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont);
    870     if (!glyfTable.fData) {
    871         return false;
    872     }
    873 
    874     uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset;
    875     fFBoundingBoxes = new GlyphRect[entries];
    876 
    877     SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat;
    878     SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat);
    879     glyphDataIter.advance(fFBoundingBoxesGlyphOffset);
    880     for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundingBoxesIndex) {
    881         const SkOTTableGlyphData* glyphData = glyphDataIter.next();
    882         GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex];
    883         rect.fMinX = SkEndian_SwapBE16(glyphData->xMin);
    884         rect.fMinY = SkEndian_SwapBE16(glyphData->yMin);
    885         rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax);
    886         rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax);
    887     }
    888     fFBoundingBoxesMatrix = fMatrix;
    889     flip(&fFBoundingBoxesMatrix);
    890     SkScalar fontScale = getFontScale(fCGFont);
    891     fFBoundingBoxesMatrix.preScale(fontScale, fontScale);
    892     return true;
    893 }
    894 
    895 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
    896     return fGlyphCount;
    897 }
    898 
    899 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) {
    900     CGGlyph     cgGlyph;
    901     UniChar     theChar;
    902 
    903     // Validate our parameters and state
    904     SkASSERT(uni <= 0x0000FFFF);
    905     SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t));
    906 
    907     // Get the glyph
    908     theChar = (UniChar) uni;
    909 
    910     if (!CTFontGetGlyphsForCharacters(fCTFont, &theChar, &cgGlyph, 1)) {
    911         cgGlyph = 0;
    912     }
    913 
    914     return cgGlyph;
    915 }
    916 
    917 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
    918     this->generateMetrics(glyph);
    919 }
    920 
    921 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
    922     CGSize advance;
    923     CGRect bounds;
    924     CGGlyph cgGlyph;
    925 
    926     // Get the state we need
    927     cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount);
    928 
    929     if (fVertical) {
    930         if (!isSnowLeopard()) {
    931             // Lion and Leopard respect the vertical font metrics.
    932             CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation,
    933                                             &cgGlyph, &bounds, 1);
    934         } else {
    935             // Snow Leopard and earlier respect the vertical font metrics for
    936             // advances, but not bounds, so use the default box and adjust it below.
    937             CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation,
    938                                             &cgGlyph, &bounds, 1);
    939         }
    940         CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation,
    941                                    &cgGlyph, &advance, 1);
    942     } else {
    943         CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation,
    944                                         &cgGlyph, &bounds, 1);
    945         CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation,
    946                                    &cgGlyph, &advance, 1);
    947     }
    948 
    949     // BUG?
    950     // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
    951     // it should be empty. So, if we see a zero-advance, we check if it has an
    952     // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
    953     // is rare, so we won't incur a big performance cost for this extra check.
    954     if (0 == advance.width && 0 == advance.height) {
    955         AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL));
    956         if (NULL == path || CGPathIsEmpty(path)) {
    957             bounds = CGRectMake(0, 0, 0, 0);
    958         }
    959     }
    960 
    961     glyph->zeroMetrics();
    962     glyph->fAdvanceX =  SkFloatToFixed_Check(advance.width);
    963     glyph->fAdvanceY = -SkFloatToFixed_Check(advance.height);
    964 
    965     if (CGRectIsEmpty_inline(bounds)) {
    966         return;
    967     }
    968 
    969     if (isLeopard() && !fVertical) {
    970         // Leopard does not consider the matrix skew in its bounds.
    971         // Run the bounding rectangle through the skew matrix to determine
    972         // the true bounds. However, this doesn't work if the font is vertical.
    973         // FIXME (Leopard): If the font has synthetic italic (e.g., matrix skew)
    974         // and the font is vertical, the bounds need to be recomputed.
    975         SkRect glyphBounds = SkRect::MakeXYWH(
    976                 bounds.origin.x, bounds.origin.y,
    977                 bounds.size.width, bounds.size.height);
    978         fUnitMatrix.mapRect(&glyphBounds);
    979         bounds.origin.x = glyphBounds.fLeft;
    980         bounds.origin.y = glyphBounds.fTop;
    981         bounds.size.width = glyphBounds.width();
    982         bounds.size.height = glyphBounds.height();
    983     }
    984     // Adjust the bounds
    985     //
    986     // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need
    987     // to transform the bounding box ourselves.
    988     //
    989     // The bounds are also expanded by 1 pixel, to give CG room for anti-aliasing.
    990     CGRectInset_inline(&bounds, -1, -1);
    991 
    992     // Get the metrics
    993     bool lionAdjustedMetrics = false;
    994     if (isLion() || isMountainLion()) {
    995         if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes()){
    996             lionAdjustedMetrics = true;
    997             SkRect adjust;
    998             const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset];
    999             adjust.set(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY);
   1000             fFBoundingBoxesMatrix.mapRect(&adjust);
   1001             bounds.origin.x = SkScalarToFloat(adjust.fLeft) - 1;
   1002             bounds.origin.y = SkScalarToFloat(adjust.fTop) - 1;
   1003         }
   1004         // Lion returns fractions in the bounds
   1005         glyph->fWidth = SkToU16(sk_float_ceil2int(bounds.size.width));
   1006         glyph->fHeight = SkToU16(sk_float_ceil2int(bounds.size.height));
   1007     } else {
   1008         glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width));
   1009         glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height));
   1010     }
   1011     glyph->fTop = SkToS16(-sk_float_round2int(CGRectGetMaxY_inline(bounds)));
   1012     glyph->fLeft = SkToS16(sk_float_round2int(CGRectGetMinX_inline(bounds)));
   1013     SkIPoint offset;
   1014     if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) {
   1015         // SnowLeopard doesn't respect vertical metrics, so compute them manually.
   1016         // Also compute them for Lion when the metrics were computed by hand.
   1017         getVerticalOffset(cgGlyph, &offset);
   1018         glyph->fLeft += offset.fX;
   1019         glyph->fTop += offset.fY;
   1020     }
   1021 }
   1022 
   1023 #include "SkColorPriv.h"
   1024 
   1025 static void build_power_table(uint8_t table[], float ee) {
   1026     for (int i = 0; i < 256; i++) {
   1027         float x = i / 255.f;
   1028         x = sk_float_pow(x, ee);
   1029         int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255));
   1030         table[i] = SkToU8(xx);
   1031     }
   1032 }
   1033 
   1034 /**
   1035  *  This will invert the gamma applied by CoreGraphics, so we can get linear
   1036  *  values.
   1037  *
   1038  *  CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
   1039  *  The color space used does not appear to affect this choice.
   1040  */
   1041 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() {
   1042     static bool gInited;
   1043     static uint8_t gTableCoreGraphicsSmoothing[256];
   1044     if (!gInited) {
   1045         build_power_table(gTableCoreGraphicsSmoothing, 2.0f);
   1046         gInited = true;
   1047     }
   1048     return gTableCoreGraphicsSmoothing;
   1049 }
   1050 
   1051 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
   1052     while (count > 0) {
   1053         uint8_t mask = 0;
   1054         for (int i = 7; i >= 0; --i) {
   1055             mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i;
   1056             if (0 == --count) {
   1057                 break;
   1058             }
   1059         }
   1060         *dst++ = mask;
   1061     }
   1062 }
   1063 
   1064 template<bool APPLY_PREBLEND>
   1065 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
   1066     U8CPU r = (rgb >> 16) & 0xFF;
   1067     U8CPU g = (rgb >>  8) & 0xFF;
   1068     U8CPU b = (rgb >>  0) & 0xFF;
   1069     return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1070 }
   1071 template<bool APPLY_PREBLEND>
   1072 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
   1073                       const SkGlyph& glyph, const uint8_t* table8) {
   1074     const int width = glyph.fWidth;
   1075     size_t dstRB = glyph.rowBytes();
   1076     uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
   1077 
   1078     for (int y = 0; y < glyph.fHeight; y++) {
   1079         for (int i = 0; i < width; ++i) {
   1080             dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
   1081         }
   1082         cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1083         dst += dstRB;
   1084     }
   1085 }
   1086 
   1087 template<bool APPLY_PREBLEND>
   1088 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR,
   1089                                                     const uint8_t* tableG,
   1090                                                     const uint8_t* tableB) {
   1091     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1092     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1093     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1094     return SkPack888ToRGB16(r, g, b);
   1095 }
   1096 template<bool APPLY_PREBLEND>
   1097 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph,
   1098                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1099     const int width = glyph.fWidth;
   1100     size_t dstRB = glyph.rowBytes();
   1101     uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
   1102 
   1103     for (int y = 0; y < glyph.fHeight; y++) {
   1104         for (int i = 0; i < width; i++) {
   1105             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
   1106         }
   1107         cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1108         dst = (uint16_t*)((char*)dst + dstRB);
   1109     }
   1110 }
   1111 
   1112 template<bool APPLY_PREBLEND>
   1113 static inline uint32_t rgb_to_lcd32(CGRGBPixel rgb, const uint8_t* tableR,
   1114                                                     const uint8_t* tableG,
   1115                                                     const uint8_t* tableB) {
   1116     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1117     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1118     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1119     return SkPackARGB32(0xFF, r, g, b);
   1120 }
   1121 template<bool APPLY_PREBLEND>
   1122 static void rgb_to_lcd32(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph,
   1123                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1124     const int width = glyph.fWidth;
   1125     size_t dstRB = glyph.rowBytes();
   1126     uint32_t* SK_RESTRICT dst = (uint32_t*)glyph.fImage;
   1127     for (int y = 0; y < glyph.fHeight; y++) {
   1128         for (int i = 0; i < width; i++) {
   1129             dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
   1130         }
   1131         cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1132         dst = (uint32_t*)((char*)dst + dstRB);
   1133     }
   1134 }
   1135 
   1136 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
   1137     return (T*)((char*)ptr + byteOffset);
   1138 }
   1139 
   1140 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
   1141     CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
   1142 
   1143     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   1144     bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting;
   1145 
   1146     // Draw the glyph
   1147     size_t cgRowBytes;
   1148     CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD);
   1149     if (cgPixels == NULL) {
   1150         return;
   1151     }
   1152 
   1153     //TODO: see if drawing black on white and inverting is faster (at least in
   1154     //lcd case) as core graphics appears to have special case code for drawing
   1155     //black text.
   1156 
   1157     // Fix the glyph
   1158     const bool isLCD = isLCDFormat(glyph.fMaskFormat);
   1159     if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) {
   1160         const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing();
   1161 
   1162         //Note that the following cannot really be integrated into the
   1163         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1164         //applying the pre-blend it means that a filter wants linear anyway.
   1165         //Other code may also be applying the pre-blend, so we'd need another
   1166         //one with this and one without.
   1167         CGRGBPixel* addr = cgPixels;
   1168         for (int y = 0; y < glyph.fHeight; ++y) {
   1169             for (int x = 0; x < glyph.fWidth; ++x) {
   1170                 int r = (addr[x] >> 16) & 0xFF;
   1171                 int g = (addr[x] >>  8) & 0xFF;
   1172                 int b = (addr[x] >>  0) & 0xFF;
   1173                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1174             }
   1175             addr = SkTAddByteOffset(addr, cgRowBytes);
   1176         }
   1177     }
   1178 
   1179     // Convert glyph to mask
   1180     switch (glyph.fMaskFormat) {
   1181         case SkMask::kLCD32_Format: {
   1182             if (fPreBlend.isApplicable()) {
   1183                 rgb_to_lcd32<true>(cgPixels, cgRowBytes, glyph,
   1184                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1185             } else {
   1186                 rgb_to_lcd32<false>(cgPixels, cgRowBytes, glyph,
   1187                                     fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1188             }
   1189         } break;
   1190         case SkMask::kLCD16_Format: {
   1191             if (fPreBlend.isApplicable()) {
   1192                 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph,
   1193                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1194             } else {
   1195                 rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph,
   1196                                     fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1197             }
   1198         } break;
   1199         case SkMask::kA8_Format: {
   1200             if (fPreBlend.isApplicable()) {
   1201                 rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1202             } else {
   1203                 rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
   1204             }
   1205         } break;
   1206         case SkMask::kBW_Format: {
   1207             const int width = glyph.fWidth;
   1208             size_t dstRB = glyph.rowBytes();
   1209             uint8_t* dst = (uint8_t*)glyph.fImage;
   1210             for (int y = 0; y < glyph.fHeight; y++) {
   1211                 cgpixels_to_bits(dst, cgPixels, width);
   1212                 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
   1213                 dst += dstRB;
   1214             }
   1215         } break;
   1216         default:
   1217             SkDEBUGFAIL("unexpected mask format");
   1218             break;
   1219     }
   1220 }
   1221 
   1222 /*
   1223  *  Our subpixel resolution is only 2 bits in each direction, so a scale of 4
   1224  *  seems sufficient, and possibly even correct, to allow the hinted outline
   1225  *  to be subpixel positioned.
   1226  */
   1227 #define kScaleForSubPixelPositionHinting (4.0f)
   1228 
   1229 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) {
   1230     CTFontRef font = fCTFont;
   1231     SkScalar scaleX = SK_Scalar1;
   1232     SkScalar scaleY = SK_Scalar1;
   1233 
   1234     /*
   1235      *  For subpixel positioning, we want to return an unhinted outline, so it
   1236      *  can be positioned nicely at fractional offsets. However, we special-case
   1237      *  if the baseline of the (horizontal) text is axis-aligned. In those cases
   1238      *  we want to retain hinting in the direction orthogonal to the baseline.
   1239      *  e.g. for horizontal baseline, we want to retain hinting in Y.
   1240      *  The way we remove hinting is to scale the font by some value (4) in that
   1241      *  direction, ask for the path, and then scale the path back down.
   1242      */
   1243     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
   1244         SkMatrix m;
   1245         fRec.getSingleMatrix(&m);
   1246 
   1247         // start out by assuming that we want no hining in X and Y
   1248         scaleX = scaleY = SkFloatToScalar(kScaleForSubPixelPositionHinting);
   1249         // now see if we need to restore hinting for axis-aligned baselines
   1250         switch (SkComputeAxisAlignmentForHText(m)) {
   1251             case kX_SkAxisAlignment:
   1252                 scaleY = SK_Scalar1; // want hinting in the Y direction
   1253                 break;
   1254             case kY_SkAxisAlignment:
   1255                 scaleX = SK_Scalar1; // want hinting in the X direction
   1256                 break;
   1257             default:
   1258                 break;
   1259         }
   1260 
   1261         CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY);
   1262         // need to release font when we're done
   1263         font = CTFontCreateCopyWithAttributes(fCTFont, 1, &xform, NULL);
   1264     }
   1265 
   1266     CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(fBaseGlyphCount);
   1267     AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL));
   1268 
   1269     path->reset();
   1270     if (cgPath != NULL) {
   1271         CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement);
   1272     }
   1273 
   1274     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
   1275         SkMatrix m;
   1276         m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
   1277         path->transform(m);
   1278         // balance the call to CTFontCreateCopyWithAttributes
   1279         CFSafeRelease(font);
   1280     }
   1281     if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
   1282         SkIPoint offset;
   1283         getVerticalOffset(cgGlyph, &offset);
   1284         path->offset(SkIntToScalar(offset.fX), SkIntToScalar(offset.fY));
   1285     }
   1286 }
   1287 
   1288 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx,
   1289                                               SkPaint::FontMetrics* my) {
   1290     CGRect theBounds = CTFontGetBoundingBox(fCTFont);
   1291 
   1292     SkPaint::FontMetrics theMetrics;
   1293     theMetrics.fTop          = CGToScalar(-CGRectGetMaxY_inline(theBounds));
   1294     theMetrics.fAscent       = CGToScalar(-CTFontGetAscent(fCTFont));
   1295     theMetrics.fDescent      = CGToScalar( CTFontGetDescent(fCTFont));
   1296     theMetrics.fBottom       = CGToScalar(-CGRectGetMinY_inline(theBounds));
   1297     theMetrics.fLeading      = CGToScalar( CTFontGetLeading(fCTFont));
   1298     theMetrics.fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
   1299     theMetrics.fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
   1300     theMetrics.fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
   1301     theMetrics.fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont));
   1302 
   1303     if (mx != NULL) {
   1304         *mx = theMetrics;
   1305     }
   1306     if (my != NULL) {
   1307         *my = theMetrics;
   1308     }
   1309 }
   1310 
   1311 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) {
   1312     SkPath* skPath = (SkPath*)info;
   1313 
   1314     // Process the path element
   1315     switch (element->type) {
   1316         case kCGPathElementMoveToPoint:
   1317             skPath->moveTo(element->points[0].x, -element->points[0].y);
   1318             break;
   1319 
   1320         case kCGPathElementAddLineToPoint:
   1321             skPath->lineTo(element->points[0].x, -element->points[0].y);
   1322             break;
   1323 
   1324         case kCGPathElementAddQuadCurveToPoint:
   1325             skPath->quadTo(element->points[0].x, -element->points[0].y,
   1326                            element->points[1].x, -element->points[1].y);
   1327             break;
   1328 
   1329         case kCGPathElementAddCurveToPoint:
   1330             skPath->cubicTo(element->points[0].x, -element->points[0].y,
   1331                             element->points[1].x, -element->points[1].y,
   1332                             element->points[2].x, -element->points[2].y);
   1333             break;
   1334 
   1335         case kCGPathElementCloseSubpath:
   1336             skPath->close();
   1337             break;
   1338 
   1339         default:
   1340             SkDEBUGFAIL("Unknown path element!");
   1341             break;
   1342         }
   1343 }
   1344 
   1345 
   1346 ///////////////////////////////////////////////////////////////////////////////
   1347 
   1348 // Returns NULL on failure
   1349 // Call must still manage its ownership of provider
   1350 static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) {
   1351     AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider));
   1352     if (NULL == cg) {
   1353         return NULL;
   1354     }
   1355     CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, NULL);
   1356     return cg ? SkCreateTypefaceFromCTFont(ct) : NULL;
   1357 }
   1358 
   1359 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
   1360     AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(stream));
   1361     if (NULL == provider) {
   1362         return NULL;
   1363     }
   1364     return create_from_dataProvider(provider);
   1365 }
   1366 
   1367 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
   1368     AutoCFRelease<CGDataProviderRef> provider(CGDataProviderCreateWithFilename(path));
   1369     if (NULL == provider) {
   1370         return NULL;
   1371     }
   1372     return create_from_dataProvider(provider);
   1373 }
   1374 
   1375 // Web fonts added to the the CTFont registry do not return their character set.
   1376 // Iterate through the font in this case. The existing caller caches the result,
   1377 // so the performance impact isn't too bad.
   1378 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
   1379                                            SkTDArray<SkUnichar>* glyphToUnicode) {
   1380     glyphToUnicode->setCount(glyphCount);
   1381     SkUnichar* out = glyphToUnicode->begin();
   1382     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1383     UniChar unichar = 0;
   1384     while (glyphCount > 0) {
   1385         CGGlyph glyph;
   1386         if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1387             out[glyph] = unichar;
   1388             --glyphCount;
   1389         }
   1390         if (++unichar == 0) {
   1391             break;
   1392         }
   1393     }
   1394 }
   1395 
   1396 // Construct Glyph to Unicode table.
   1397 // Unicode code points that require conjugate pairs in utf16 are not
   1398 // supported.
   1399 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
   1400                                       SkTDArray<SkUnichar>* glyphToUnicode) {
   1401     AutoCFRelease<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
   1402     if (!charSet) {
   1403         populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
   1404         return;
   1405     }
   1406 
   1407     AutoCFRelease<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault,
   1408                                                                              charSet));
   1409     if (!bitmap) {
   1410         return;
   1411     }
   1412     CFIndex length = CFDataGetLength(bitmap);
   1413     if (!length) {
   1414         return;
   1415     }
   1416     if (length > 8192) {
   1417         // TODO: Add support for Unicode above 0xFFFF
   1418         // Consider only the BMP portion of the Unicode character points.
   1419         // The bitmap may contain other planes, up to plane 16.
   1420         // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html
   1421         length = 8192;
   1422     }
   1423     const UInt8* bits = CFDataGetBytePtr(bitmap);
   1424     glyphToUnicode->setCount(glyphCount);
   1425     SkUnichar* out = glyphToUnicode->begin();
   1426     sk_bzero(out, glyphCount * sizeof(SkUnichar));
   1427     for (int i = 0; i < length; i++) {
   1428         int mask = bits[i];
   1429         if (!mask) {
   1430             continue;
   1431         }
   1432         for (int j = 0; j < 8; j++) {
   1433             CGGlyph glyph;
   1434             UniChar unichar = static_cast<UniChar>((i << 3) + j);
   1435             if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
   1436                 out[glyph] = unichar;
   1437             }
   1438         }
   1439     }
   1440 }
   1441 
   1442 static bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) {
   1443     CGSize advance;
   1444     advance.width = 0;
   1445     CGGlyph glyph = gId;
   1446     CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &glyph, &advance, 1);
   1447     *data = sk_float_round2int(advance.width);
   1448     return true;
   1449 }
   1450 
   1451 // we might move this into our CGUtils...
   1452 static void CFStringToSkString(CFStringRef src, SkString* dst) {
   1453     // Reserve enough room for the worst-case string,
   1454     // plus 1 byte for the trailing null.
   1455     CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
   1456                                                        kCFStringEncodingUTF8) + 1;
   1457     dst->resize(length);
   1458     CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
   1459     // Resize to the actual UTF-8 length used, stripping the null character.
   1460     dst->resize(strlen(dst->c_str()));
   1461 }
   1462 
   1463 // static
   1464 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
   1465         uint32_t fontID,
   1466         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
   1467         const uint32_t* glyphIDs,
   1468         uint32_t glyphIDsCount) {
   1469     CTFontRef originalCTFont = GetFontRefFromFontID(fontID);
   1470     AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes(
   1471             originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL));
   1472     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
   1473 
   1474     {
   1475         AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont));
   1476         CFStringToSkString(fontName, &info->fFontName);
   1477     }
   1478 
   1479     info->fMultiMaster = false;
   1480     CFIndex glyphCount = CTFontGetGlyphCount(ctFont);
   1481     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1482     info->fEmSize = CTFontGetUnitsPerEm(ctFont);
   1483 
   1484     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
   1485         populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode);
   1486     }
   1487 
   1488     info->fStyle = 0;
   1489 
   1490     // If it's not a truetype font, mark it as 'other'. Assume that TrueType
   1491     // fonts always have both glyf and loca tables. At the least, this is what
   1492     // sfntly needs to subset the font. CTFontCopyAttribute() does not always
   1493     // succeed in determining this directly.
   1494     if (!GetTableSize(fontID, 'glyf') || !GetTableSize(fontID, 'loca')) {
   1495         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1496         info->fItalicAngle = 0;
   1497         info->fAscent = 0;
   1498         info->fDescent = 0;
   1499         info->fStemV = 0;
   1500         info->fCapHeight = 0;
   1501         info->fBBox = SkIRect::MakeEmpty();
   1502         return info;
   1503     }
   1504 
   1505     info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1506     CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont);
   1507     if (symbolicTraits & kCTFontMonoSpaceTrait) {
   1508         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1509     }
   1510     if (symbolicTraits & kCTFontItalicTrait) {
   1511         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1512     }
   1513     CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
   1514     if (stylisticClass & kCTFontSymbolicClass) {
   1515         info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
   1516     }
   1517     if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
   1518         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1519     } else if (stylisticClass & kCTFontScriptsClass) {
   1520         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1521     }
   1522     info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont);
   1523     info->fAscent = (int16_t) CTFontGetAscent(ctFont);
   1524     info->fDescent = (int16_t) CTFontGetDescent(ctFont);
   1525     info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont);
   1526     CGRect bbox = CTFontGetBoundingBox(ctFont);
   1527 
   1528     SkRect r;
   1529     r.set( CGToScalar(CGRectGetMinX_inline(bbox)),   // Left
   1530            CGToScalar(CGRectGetMaxY_inline(bbox)),   // Top
   1531            CGToScalar(CGRectGetMaxX_inline(bbox)),   // Right
   1532            CGToScalar(CGRectGetMinY_inline(bbox)));  // Bottom
   1533 
   1534     r.roundOut(&(info->fBBox));
   1535 
   1536     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1537     // This probably isn't very good with an italic font.
   1538     int16_t min_width = SHRT_MAX;
   1539     info->fStemV = 0;
   1540     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
   1541     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
   1542     CGGlyph glyphs[count];
   1543     CGRect boundingRects[count];
   1544     if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) {
   1545         CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation,
   1546                                         glyphs, boundingRects, count);
   1547         for (size_t i = 0; i < count; i++) {
   1548             int16_t width = (int16_t) boundingRects[i].size.width;
   1549             if (width > 0 && width < min_width) {
   1550                 min_width = width;
   1551                 info->fStemV = min_width;
   1552             }
   1553         }
   1554     }
   1555 
   1556     if (false) { // TODO: haven't figured out how to know if font is embeddable
   1557         // (information is in the OS/2 table)
   1558         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
   1559     } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
   1560         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1561             skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0);
   1562             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1563             skia_advanced_typeface_metrics_utils::finishRange(info->fGlyphWidths.get(), 0,
   1564                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1565         } else {
   1566             info->fGlyphWidths.reset(
   1567                 skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(),
   1568                                glyphCount,
   1569                                glyphIDs,
   1570                                glyphIDsCount,
   1571                                &getWidthAdvance));
   1572         }
   1573     }
   1574     return info;
   1575 }
   1576 
   1577 ///////////////////////////////////////////////////////////////////////////////
   1578 
   1579 static SK_SFNT_ULONG get_font_type_tag(SkFontID uniqueID) {
   1580     CTFontRef ctFont = GetFontRefFromFontID(uniqueID);
   1581     AutoCFRelease<CFNumberRef> fontFormatRef(
   1582             static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
   1583     if (!fontFormatRef) {
   1584         return 0;
   1585     }
   1586 
   1587     SInt32 fontFormatValue;
   1588     if (!CFNumberGetValue(fontFormatRef, kCFNumberSInt32Type, &fontFormatValue)) {
   1589         return 0;
   1590     }
   1591 
   1592     switch (fontFormatValue) {
   1593         case kCTFontFormatOpenTypePostScript:
   1594             return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
   1595         case kCTFontFormatOpenTypeTrueType:
   1596             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1597         case kCTFontFormatTrueType:
   1598             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1599         case kCTFontFormatPostScript:
   1600             return SkSFNTHeader::fontType_PostScript::TAG;
   1601         case kCTFontFormatBitmap:
   1602             return SkSFNTHeader::fontType_MacTrueType::TAG;
   1603         case kCTFontFormatUnrecognized:
   1604         default:
   1605             //CT seems to be unreliable in being able to obtain the type,
   1606             //even if all we want is the first four bytes of the font resource.
   1607             //Just the presence of the FontForge 'FFTM' table seems to throw it off.
   1608             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
   1609     }
   1610 }
   1611 
   1612 SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
   1613     SK_SFNT_ULONG fontType = get_font_type_tag(uniqueID);
   1614     if (0 == fontType) {
   1615         return NULL;
   1616     }
   1617 
   1618     // get table tags
   1619     int numTables = CountTables(uniqueID);
   1620     SkTDArray<SkFontTableTag> tableTags;
   1621     tableTags.setCount(numTables);
   1622     GetTableTags(uniqueID, tableTags.begin());
   1623 
   1624     // calc total size for font, save sizes
   1625     SkTDArray<size_t> tableSizes;
   1626     size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1627     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1628         size_t tableSize = GetTableSize(uniqueID, tableTags[tableIndex]);
   1629         totalSize += (tableSize + 3) & ~3;
   1630         *tableSizes.append() = tableSize;
   1631     }
   1632 
   1633     // reserve memory for stream, and zero it (tables must be zero padded)
   1634     SkMemoryStream* stream = new SkMemoryStream(totalSize);
   1635     char* dataStart = (char*)stream->getMemoryBase();
   1636     sk_bzero(dataStart, totalSize);
   1637     char* dataPtr = dataStart;
   1638 
   1639     // compute font header entries
   1640     uint16_t entrySelector = 0;
   1641     uint16_t searchRange = 1;
   1642     while (searchRange < numTables >> 1) {
   1643         entrySelector++;
   1644         searchRange <<= 1;
   1645     }
   1646     searchRange <<= 4;
   1647     uint16_t rangeShift = (numTables << 4) - searchRange;
   1648 
   1649     // write font header
   1650     SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
   1651     header->fontType = fontType;
   1652     header->numTables = SkEndian_SwapBE16(numTables);
   1653     header->searchRange = SkEndian_SwapBE16(searchRange);
   1654     header->entrySelector = SkEndian_SwapBE16(entrySelector);
   1655     header->rangeShift = SkEndian_SwapBE16(rangeShift);
   1656     dataPtr += sizeof(SkSFNTHeader);
   1657 
   1658     // write tables
   1659     SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
   1660     dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
   1661     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
   1662         size_t tableSize = tableSizes[tableIndex];
   1663         GetTableData(uniqueID, tableTags[tableIndex], 0, tableSize, dataPtr);
   1664         entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
   1665         entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
   1666                                                                          tableSize));
   1667         entry->offset = SkEndian_SwapBE32(dataPtr - dataStart);
   1668         entry->logicalLength = SkEndian_SwapBE32(tableSize);
   1669 
   1670         dataPtr += (tableSize + 3) & ~3;
   1671         ++entry;
   1672     }
   1673 
   1674     return stream;
   1675 }
   1676 
   1677 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, int32_t* index) {
   1678     SkDEBUGFAIL("SkFontHost::GetFileName unimplemented");
   1679     return 0;
   1680 }
   1681 
   1682 ///////////////////////////////////////////////////////////////////////////////
   1683 
   1684 #include "SkStream.h"
   1685 
   1686 // we take ownership of the ref
   1687 static const char* get_str(CFStringRef ref, SkString* str) {
   1688     CFStringToSkString(ref, str);
   1689     CFSafeRelease(ref);
   1690     return str->c_str();
   1691 }
   1692 
   1693 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
   1694     CTFontRef ctFont = typeface_to_fontref(face);
   1695     SkFontDescriptor desc(face->style());
   1696     SkString tmpStr;
   1697 
   1698     desc.setFamilyName(get_str(CTFontCopyFamilyName(ctFont), &tmpStr));
   1699     desc.setFullName(get_str(CTFontCopyFullName(ctFont), &tmpStr));
   1700     desc.setPostscriptName(get_str(CTFontCopyPostScriptName(ctFont), &tmpStr));
   1701 
   1702     desc.serialize(stream);
   1703 
   1704     // by convention, we also write out the actual sfnt data, preceeded by
   1705     // a packed-length. For now we skip that, so we just write the zero.
   1706     stream->writePackedUInt(0);
   1707 }
   1708 
   1709 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
   1710     SkFontDescriptor desc(stream);
   1711 
   1712     // by convention, Serialize will have also written the actual sfnt data.
   1713     // for now, we just want to skip it.
   1714     size_t size = stream->readPackedUInt();
   1715     stream->skip(size);
   1716 
   1717     return SkFontHost::CreateTypeface(NULL, desc.getFamilyName(), desc.getStyle());
   1718 }
   1719 
   1720 ///////////////////////////////////////////////////////////////////////////////
   1721 
   1722 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
   1723     return new SkScalerContext_Mac(desc);
   1724 }
   1725 
   1726 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
   1727     SkFontID nextFontID = 0;
   1728     SkTypeface* face = GetDefaultFace();
   1729     if (face->uniqueID() != currFontID) {
   1730         nextFontID = face->uniqueID();
   1731     }
   1732     return nextFontID;
   1733 }
   1734 
   1735 void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) {
   1736     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
   1737                                   SkScalerContext::kAutohinting_Flag;
   1738 
   1739     rec->fFlags &= ~flagsWeDontSupport;
   1740 
   1741     bool lcdSupport = supports_LCD();
   1742 
   1743     // Only two levels of hinting are supported.
   1744     // kNo_Hinting means avoid CoreGraphics outline dilation.
   1745     // kNormal_Hinting means CoreGraphics outline dilation is allowed.
   1746     // If there is no lcd support, hinting (dilation) cannot be supported.
   1747     SkPaint::Hinting hinting = rec->getHinting();
   1748     if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) {
   1749         hinting = SkPaint::kNo_Hinting;
   1750     } else if (SkPaint::kFull_Hinting == hinting) {
   1751         hinting = SkPaint::kNormal_Hinting;
   1752     }
   1753     rec->setHinting(hinting);
   1754 
   1755     // FIXME: lcd smoothed un-hinted rasterization unsupported.
   1756     // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
   1757     // There is no current means to honor a request for unhinted lcd,
   1758     // so arbitrarilly ignore the hinting request and honor lcd.
   1759 
   1760     // Hinting and smoothing should be orthogonal, but currently they are not.
   1761     // CoreGraphics has no API to influence hinting. However, its lcd smoothed
   1762     // output is drawn from auto-dilated outlines (the amount of which is
   1763     // determined by AppleFontSmoothing). Its regular anti-aliased output is
   1764     // drawn from un-dilated outlines.
   1765 
   1766     // The behavior of Skia is as follows:
   1767     // [AA][no-hint]: generate AA using CoreGraphic's AA output.
   1768     // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
   1769     // channel. This matches [LCD][yes-hint] in weight.
   1770     // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
   1771     // Currenly side with LCD, effectively ignoring the hinting setting.
   1772     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
   1773 
   1774     if (isLCDFormat(rec->fMaskFormat)) {
   1775         if (lcdSupport) {
   1776             //CoreGraphics creates 555 masks for smoothed text anyway.
   1777             rec->fMaskFormat = SkMask::kLCD16_Format;
   1778             rec->setHinting(SkPaint::kNormal_Hinting);
   1779         } else {
   1780             rec->fMaskFormat = SkMask::kA8_Format;
   1781         }
   1782     }
   1783 
   1784     // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
   1785     // All other masks can use regular gamma.
   1786     if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) {
   1787 #ifndef SK_GAMMA_APPLY_TO_A8
   1788         rec->ignorePreBlend();
   1789 #endif
   1790     } else {
   1791         //CoreGraphics dialates smoothed text as needed.
   1792         rec->setContrast(0);
   1793     }
   1794 }
   1795 
   1796 ///////////////////////////////////////////////////////////////////////////
   1797 
   1798 int SkFontHost::CountTables(SkFontID fontID) {
   1799     CTFontRef ctFont = GetFontRefFromFontID(fontID);
   1800     AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(ctFont,
   1801                                                                 kCTFontTableOptionNoOptions));
   1802     if (NULL == cfArray) {
   1803         return 0;
   1804     }
   1805     return CFArrayGetCount(cfArray);
   1806 }
   1807 
   1808 int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
   1809     CTFontRef ctFont = GetFontRefFromFontID(fontID);
   1810     AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(ctFont,
   1811                                                                 kCTFontTableOptionNoOptions));
   1812     if (NULL == cfArray) {
   1813         return 0;
   1814     }
   1815 
   1816     int count = CFArrayGetCount(cfArray);
   1817     if (tags) {
   1818         for (int i = 0; i < count; ++i) {
   1819             uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i));
   1820             tags[i] = static_cast<SkFontTableTag>(fontTag);
   1821         }
   1822     }
   1823     return count;
   1824 }
   1825 
   1826 // If, as is the case with web fonts, the CTFont data isn't available,
   1827 // the CGFont data may work. While the CGFont may always provide the
   1828 // right result, leave the CTFont code path to minimize disruption.
   1829 static CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) {
   1830     CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, kCTFontTableOptionNoOptions);
   1831     if (NULL == data) {
   1832         AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, NULL));
   1833         data = CGFontCopyTableForTag(cgFont, tag);
   1834     }
   1835     return data;
   1836 }
   1837 
   1838 size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
   1839     CTFontRef ctFont = GetFontRefFromFontID(fontID);
   1840     AutoCFRelease<CFDataRef> srcData(copyTableFromFont(ctFont, tag));
   1841     if (NULL == srcData) {
   1842         return 0;
   1843     }
   1844     return CFDataGetLength(srcData);
   1845 }
   1846 
   1847 size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
   1848                                 size_t offset, size_t length, void* dst) {
   1849     CTFontRef ctFont = GetFontRefFromFontID(fontID);
   1850     AutoCFRelease<CFDataRef> srcData(copyTableFromFont(ctFont, tag));
   1851     if (NULL == srcData) {
   1852         return 0;
   1853     }
   1854 
   1855     size_t srcSize = CFDataGetLength(srcData);
   1856     if (offset >= srcSize) {
   1857         return 0;
   1858     }
   1859 
   1860     if ((offset + length) > srcSize) {
   1861         length = srcSize - offset;
   1862     }
   1863 
   1864     if (dst) {
   1865         memcpy(dst, CFDataGetBytePtr(srcData) + offset, length);
   1866     }
   1867     return length;
   1868 }
   1869