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