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