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