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