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