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