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 "include/core/SkTypes.h"
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 "include/core/SkFontMetrics.h"
23 #include "include/core/SkFontMgr.h"
24 #include "include/core/SkPaint.h"
25 #include "include/core/SkPath.h"
26 #include "include/core/SkStream.h"
27 #include "include/core/SkString.h"
28 #include "include/ports/SkTypeface_mac.h"
29 #include "include/private/SkColorData.h"
30 #include "include/private/SkFloatingPoint.h"
31 #include "include/private/SkMutex.h"
32 #include "include/private/SkOnce.h"
33 #include "include/private/SkTemplates.h"
34 #include "include/private/SkTo.h"
35 #include "include/utils/mac/SkCGUtils.h"
36 #include "src/core/SkAdvancedTypefaceMetrics.h"
37 #include "src/core/SkAutoMalloc.h"
38 #include "src/core/SkDescriptor.h"
39 #include "src/core/SkEndian.h"
40 #include "src/core/SkFontDescriptor.h"
41 #include "src/core/SkGlyph.h"
42 #include "src/core/SkMakeUnique.h"
43 #include "src/core/SkMaskGamma.h"
44 #include "src/core/SkMathPriv.h"
45 #include "src/core/SkTypefaceCache.h"
46 #include "src/core/SkUtils.h"
47 #include "src/sfnt/SkOTTable_OS_2.h"
48 #include "src/sfnt/SkOTUtils.h"
49 #include "src/sfnt/SkSFNTHeader.h"
50 #include "src/utils/SkUTF.h"
51 #include "src/utils/mac/SkUniqueCFRef.h"
52 
53 #include <dlfcn.h>
54 
55 #include <utility>
56 
57 // Set to make glyph bounding boxes visible.
58 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
59 
SkTypeface_GetCTFontRef(const SkTypeface * face)60 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
61     return face ? (CTFontRef)face->internal_private_getCTFontRef() : nullptr;
62 }
63 
64 class SkScalerContext_Mac;
65 
make_CFString(const char s[])66 static SkUniqueCFRef<CFStringRef> make_CFString(const char s[]) {
67     return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8));
68 }
69 
70 // inline versions of these rect helpers
71 
CGRectIsEmpty_inline(const CGRect & rect)72 static bool CGRectIsEmpty_inline(const CGRect& rect) {
73     return rect.size.width <= 0 || rect.size.height <= 0;
74 }
75 
CGRectGetMinX_inline(const CGRect & rect)76 static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
77     return rect.origin.x;
78 }
79 
CGRectGetMaxX_inline(const CGRect & rect)80 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) {
81     return rect.origin.x + rect.size.width;
82 }
83 
CGRectGetMinY_inline(const CGRect & rect)84 static CGFloat CGRectGetMinY_inline(const CGRect& rect) {
85     return rect.origin.y;
86 }
87 
CGRectGetMaxY_inline(const CGRect & rect)88 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
89     return rect.origin.y + rect.size.height;
90 }
91 
CGRectGetWidth_inline(const CGRect & rect)92 static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
93     return rect.size.width;
94 }
95 
96 ///////////////////////////////////////////////////////////////////////////////
97 
sk_memset_rect32(uint32_t * ptr,uint32_t value,int width,int height,size_t rowBytes)98 static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
99                              int width, int height, size_t rowBytes) {
100     SkASSERT(width);
101     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
102 
103     if (width >= 32) {
104         while (height) {
105             sk_memset32(ptr, value, width);
106             ptr = (uint32_t*)((char*)ptr + rowBytes);
107             height -= 1;
108         }
109         return;
110     }
111 
112     rowBytes -= width * sizeof(uint32_t);
113 
114     if (width >= 8) {
115         while (height) {
116             int w = width;
117             do {
118                 *ptr++ = value; *ptr++ = value;
119                 *ptr++ = value; *ptr++ = value;
120                 *ptr++ = value; *ptr++ = value;
121                 *ptr++ = value; *ptr++ = value;
122                 w -= 8;
123             } while (w >= 8);
124             while (--w >= 0) {
125                 *ptr++ = value;
126             }
127             ptr = (uint32_t*)((char*)ptr + rowBytes);
128             height -= 1;
129         }
130     } else {
131         while (height) {
132             int w = width;
133             do {
134                 *ptr++ = value;
135             } while (--w > 0);
136             ptr = (uint32_t*)((char*)ptr + rowBytes);
137             height -= 1;
138         }
139     }
140 }
141 
142 typedef uint32_t CGRGBPixel;
143 
CGRGBPixel_getAlpha(CGRGBPixel pixel)144 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
145     return pixel & 0xFF;
146 }
147 
ScalarToCG(SkScalar scalar)148 static CGFloat ScalarToCG(SkScalar scalar) {
149     if (sizeof(CGFloat) == sizeof(float)) {
150         return SkScalarToFloat(scalar);
151     } else {
152         SkASSERT(sizeof(CGFloat) == sizeof(double));
153         return (CGFloat) SkScalarToDouble(scalar);
154     }
155 }
156 
CGToScalar(CGFloat cgFloat)157 static SkScalar CGToScalar(CGFloat cgFloat) {
158     if (sizeof(CGFloat) == sizeof(float)) {
159         return SkFloatToScalar(cgFloat);
160     } else {
161         SkASSERT(sizeof(CGFloat) == sizeof(double));
162         return SkDoubleToScalar(cgFloat);
163     }
164 }
165 
CGToFloat(CGFloat cgFloat)166 static float CGToFloat(CGFloat cgFloat) {
167     if (sizeof(CGFloat) == sizeof(float)) {
168         return cgFloat;
169     } else {
170         SkASSERT(sizeof(CGFloat) == sizeof(double));
171         return static_cast<float>(cgFloat);
172     }
173 }
174 
MatrixToCGAffineTransform(const SkMatrix & matrix)175 static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix) {
176     return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX]),
177                                  -ScalarToCG(matrix[SkMatrix::kMSkewY] ),
178                                  -ScalarToCG(matrix[SkMatrix::kMSkewX] ),
179                                   ScalarToCG(matrix[SkMatrix::kMScaleY]),
180                                   ScalarToCG(matrix[SkMatrix::kMTransX]),
181                                   ScalarToCG(matrix[SkMatrix::kMTransY]));
182 }
183 
184 ///////////////////////////////////////////////////////////////////////////////
185 
186 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
187 
188 /** Drawn in FontForge, reduced with fonttools ttx, converted by xxd -i,
189  *  this TrueType font contains a glyph of the spider.
190  *
191  *  To re-forge the original bytes of the TrueType font file,
192  *  remove all ',|( +0x)' from this definition,
193  *  copy the data to the clipboard,
194  *  run 'pbpaste | xxd -p -r - spider.ttf'.
195  */
196 static constexpr const uint8_t kSpiderSymbol_ttf[] = {
197     0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x80, 0x00, 0x03, 0x00, 0x40,
198     0x47, 0x44, 0x45, 0x46, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x07, 0xa8,
199     0x00, 0x00, 0x00, 0x18, 0x4f, 0x53, 0x2f, 0x32, 0x8a, 0xf4, 0xfb, 0xdb,
200     0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
201     0xe0, 0x7f, 0x10, 0x7e, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x54,
202     0x67, 0x61, 0x73, 0x70, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x07, 0xa0,
203     0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x97, 0x0b, 0x6a, 0xf6,
204     0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x40, 0x68, 0x65, 0x61, 0x64,
205     0x0f, 0xa2, 0x24, 0x1a, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x36,
206     0x68, 0x68, 0x65, 0x61, 0x0e, 0xd3, 0x07, 0x3f, 0x00, 0x00, 0x01, 0x04,
207     0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0x10, 0x03, 0x00, 0x44,
208     0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x0e, 0x6c, 0x6f, 0x63, 0x61,
209     0x01, 0xb4, 0x00, 0x28, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x0a,
210     0x6d, 0x61, 0x78, 0x70, 0x00, 0x4a, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x28,
211     0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xc3, 0xe5, 0x39, 0xd4,
212     0x00, 0x00, 0x05, 0x58, 0x00, 0x00, 0x02, 0x28, 0x70, 0x6f, 0x73, 0x74,
213     0xff, 0x03, 0x00, 0x67, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x20,
214     0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0f, 0x08, 0x1d,
215     0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
216     0xd1, 0x97, 0xa8, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xe8, 0x32, 0x33,
217     0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x08,
218     0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
219     0x05, 0x55, 0xff, 0x3b, 0x01, 0x79, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
220     0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
222     0x00, 0x04, 0x01, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
223     0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x2e,
224     0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x01, 0x90, 0x00, 0x05,
225     0x00, 0x00, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x01, 0x1e, 0x05, 0x33,
226     0x05, 0x99, 0x00, 0x00, 0x03, 0xd7, 0x00, 0x66, 0x02, 0x12, 0x00, 0x00,
227     0x05, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229     0x00, 0x00, 0x73, 0x6b, 0x69, 0x61, 0x00, 0xc0, 0x00, 0x00, 0xf0, 0x21,
230     0x06, 0x66, 0xfe, 0x66, 0x01, 0x79, 0x05, 0x55, 0x00, 0xc5, 0x80, 0x00,
231     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232     0x00, 0x20, 0x00, 0x01, 0x08, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
233     0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
234     0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x48,
235     0x00, 0x00, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00,
236     0x00, 0x09, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21, 0xf0, 0x21, 0xff, 0xff,
237     0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21,
238     0xf0, 0x21, 0xff, 0xff, 0x00, 0x01, 0xff, 0xf9, 0xff, 0xf5, 0xff, 0xe4,
239     0xff, 0xe2, 0x0f, 0xe2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
241     0x00, 0x14, 0x00, 0x14, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44,
242     0x00, 0x00, 0x02, 0x64, 0x05, 0x55, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00,
243     0x33, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x44, 0x02, 0x20, 0xfe,
244     0x24, 0x01, 0x98, 0xfe, 0x68, 0x05, 0x55, 0xfa, 0xab, 0x44, 0x04, 0xcd,
245     0x00, 0x04, 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x4c, 0x00, 0x15,
246     0x00, 0x1d, 0x00, 0x25, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36,
247     0x27, 0x26, 0x07, 0x06, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07,
248     0x06, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x32, 0x35, 0x34, 0x23, 0x22,
249     0x15, 0x14, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0x03, 0x32,
250     0x17, 0x30, 0x17, 0x31, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33,
251     0x32, 0x33, 0x16, 0x33, 0x32, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27,
252     0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
253     0x1f, 0x02, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x17, 0x16, 0x33,
254     0x16, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27, 0x27, 0x26, 0x23, 0x22,
255     0x07, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x33, 0x32,
256     0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x02, 0x16, 0x17, 0x16, 0x15,
257     0x14, 0x23, 0x22, 0x27, 0x27, 0x26, 0x27, 0x27, 0x26, 0x27, 0x26, 0x07,
258     0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07,
259     0x06, 0x23, 0x22, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17,
260     0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27,
261     0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x07,
262     0x06, 0x07, 0x06, 0x0f, 0x02, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34,
263     0x37, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27,
264     0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x07, 0x06, 0x23, 0x22,
265     0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x37, 0x36, 0x37, 0x37, 0x36,
266     0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26,
267     0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x26,
268     0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32,
269     0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36,
270     0x33, 0x04, 0xf5, 0x23, 0x13, 0x11, 0x14, 0x16, 0x1d, 0x1b, 0x4c, 0x1f,
271     0x0e, 0x2d, 0x23, 0x14, 0x2c, 0x13, 0x18, 0x25, 0x2c, 0x10, 0x3c, 0x71,
272     0x1d, 0x5c, 0x5c, 0x3f, 0xae, 0x5c, 0x5c, 0x3f, 0x6a, 0x27, 0x31, 0x5b,
273     0x09, 0x27, 0x36, 0x03, 0x0a, 0x26, 0x35, 0x2e, 0x09, 0x08, 0xc6, 0x13,
274     0x81, 0x17, 0x20, 0x18, 0x21, 0x1e, 0x04, 0x04, 0x15, 0x5c, 0x22, 0x26,
275     0x48, 0x56, 0x3b, 0x10, 0x21, 0x01, 0x0c, 0x06, 0x06, 0x0f, 0x31, 0x44,
276     0x3c, 0x52, 0x4a, 0x1d, 0x11, 0x3f, 0xb4, 0x71, 0x01, 0x26, 0x06, 0x0d,
277     0x15, 0x1a, 0x2a, 0x13, 0x53, 0xaa, 0x42, 0x1d, 0x0a, 0x33, 0x20, 0x21,
278     0x2b, 0x01, 0x02, 0x3e, 0x21, 0x09, 0x02, 0x02, 0x0f, 0x2d, 0x4b, 0x0a,
279     0x22, 0x15, 0x20, 0x1f, 0x72, 0x8b, 0x2d, 0x2f, 0x1d, 0x1f, 0x0e, 0x25,
280     0x3f, 0x4d, 0x1b, 0x63, 0x2a, 0x2c, 0x14, 0x22, 0x18, 0x1c, 0x0f, 0x08,
281     0x2a, 0x08, 0x08, 0x0d, 0x3b, 0x4c, 0x52, 0x74, 0x27, 0x71, 0x2e, 0x01,
282     0x0c, 0x10, 0x15, 0x0d, 0x06, 0x0d, 0x05, 0x01, 0x06, 0x2c, 0x28, 0x14,
283     0x1b, 0x05, 0x04, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x16, 0x27, 0x03, 0x0d,
284     0x30, 0x4c, 0x4c, 0x4b, 0x1f, 0x0b, 0x22, 0x26, 0x0d, 0x15, 0x0d, 0x2d,
285     0x68, 0x34, 0x14, 0x3c, 0x25, 0x12, 0x04, 0x10, 0x18, 0x0b, 0x09, 0x30,
286     0x2b, 0x44, 0x66, 0x14, 0x47, 0x47, 0x59, 0x73, 0x25, 0x05, 0x03, 0x1f,
287     0x01, 0x08, 0x3f, 0x48, 0x4b, 0x4b, 0x76, 0x2f, 0x49, 0x2d, 0x22, 0x24,
288     0x0c, 0x15, 0x08, 0x0e, 0x33, 0x03, 0x44, 0x4c, 0x10, 0x46, 0x13, 0x1f,
289     0x27, 0x1b, 0x1d, 0x13, 0x02, 0x24, 0x08, 0x02, 0x42, 0x0e, 0x4d, 0x3c,
290     0x19, 0x1b, 0x40, 0x2b, 0x2b, 0x1e, 0x16, 0x11, 0x04, 0x1f, 0x11, 0x04,
291     0x18, 0x11, 0x35, 0x01, 0xa3, 0x13, 0x24, 0x1f, 0x0b, 0x0c, 0x19, 0x19,
292     0x18, 0x13, 0x0f, 0x0c, 0x1a, 0x18, 0x1f, 0x19, 0x1e, 0x07, 0x1a, 0xc3,
293     0x54, 0x51, 0x54, 0x51, 0x04, 0x53, 0x51, 0x54, 0x50, 0x02, 0x48, 0x1a,
294     0x31, 0x18, 0x55, 0x74, 0x04, 0x0e, 0x09, 0x0d, 0x06, 0x10, 0x16, 0x1b,
295     0x24, 0x01, 0x04, 0x0b, 0x04, 0x10, 0x3f, 0x0a, 0x41, 0x02, 0x41, 0x20,
296     0x06, 0x12, 0x16, 0x21, 0x17, 0x2a, 0x1e, 0x15, 0x40, 0x27, 0x11, 0x0e,
297     0x1e, 0x11, 0x15, 0x1f, 0x43, 0x13, 0x1a, 0x10, 0x15, 0x1b, 0x04, 0x09,
298     0x4d, 0x2a, 0x0f, 0x19, 0x0a, 0x0a, 0x03, 0x05, 0x15, 0x3c, 0x64, 0x21,
299     0x4b, 0x2e, 0x21, 0x28, 0x13, 0x47, 0x44, 0x19, 0x3f, 0x11, 0x18, 0x0b,
300     0x0a, 0x07, 0x18, 0x0d, 0x07, 0x24, 0x2c, 0x2b, 0x21, 0x32, 0x10, 0x48,
301     0x2a, 0x2d, 0x1e, 0x1a, 0x01, 0x0c, 0x43, 0x59, 0x28, 0x4e, 0x1c, 0x0d,
302     0x5d, 0x24, 0x14, 0x0a, 0x05, 0x1f, 0x24, 0x32, 0x46, 0x3e, 0x5f, 0x3e,
303     0x44, 0x1a, 0x30, 0x15, 0x0d, 0x07, 0x18, 0x2b, 0x03, 0x0d, 0x1a, 0x28,
304     0x28, 0x57, 0xb2, 0x29, 0x27, 0x40, 0x2c, 0x23, 0x16, 0x63, 0x58, 0x1a,
305     0x0a, 0x18, 0x11, 0x23, 0x08, 0x1b, 0x29, 0x05, 0x04, 0x0b, 0x15, 0x0d,
306     0x14, 0x0b, 0x2a, 0x29, 0x5a, 0x62, 0x01, 0x19, 0x1e, 0x05, 0x05, 0x26,
307     0x42, 0x42, 0x2a, 0x2a, 0x3f, 0x0d, 0x0f, 0x09, 0x05, 0x07, 0x01, 0x0b,
308     0x25, 0x3e, 0x0d, 0x17, 0x11, 0x01, 0x03, 0x0d, 0x13, 0x20, 0x19, 0x11,
309     0x03, 0x02, 0x01, 0x04, 0x11, 0x04, 0x05, 0x1b, 0x3d, 0x10, 0x29, 0x20,
310     0x04, 0x04, 0x0a, 0x07, 0x04, 0x1f, 0x15, 0x20, 0x3e, 0x0f, 0x2a, 0x1e,
311     0x00, 0x00, 0x00, 0x1b, 0x01, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
312     0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
313     0x00, 0x01, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
314     0x00, 0x02, 0x00, 0x07, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
315     0x00, 0x03, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
316     0x00, 0x04, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
317     0x00, 0x05, 0x00, 0x02, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
318     0x00, 0x06, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
319     0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
320     0x00, 0x0e, 0x00, 0x1a, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
321     0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
322     0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
323     0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
324     0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
325     0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
326     0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
327     0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
328     0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
329     0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
330     0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
331     0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
332     0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
333     0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
334     0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
335     0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
336     0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
337     0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
338     0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
339     0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35,
340     0x2c, 0x20, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x53, 0x70, 0x69,
341     0x64, 0x65, 0x72, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x52, 0x65, 0x67,
342     0x75, 0x6c, 0x61, 0x72, 0x56, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
343     0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x2e, 0x73, 0x69, 0x6c,
344     0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x4f, 0x46, 0x4c, 0x00, 0x43, 0x00, 0x6f,
345     0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68,
346     0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20,
347     0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x20,
348     0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65,
349     0x00, 0x2e, 0x00, 0x53, 0x00, 0x70, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65,
350     0x00, 0x72, 0x00, 0x53, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f,
351     0x00, 0x6c, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c,
352     0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x31, 0x00, 0x68, 0x00, 0x74,
353     0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x73,
354     0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x73,
355     0x00, 0x2e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6f,
356     0x00, 0x72, 0x00, 0x67, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x4c,
357     0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x66,
358     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
360     0xff, 0xff, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361     0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
362     0x00, 0x02, 0x00, 0x00
363 };
364 
365 enum class SmoothBehavior {
366     none, // SmoothFonts produces no effect.
367     some, // SmoothFonts produces some effect, but not subpixel coverage.
368     subpixel, // SmoothFonts produces some effect and provides subpixel coverage.
369 };
370 
371 /**
372  * There does not appear to be a publicly accessable API for determining if lcd
373  * font smoothing will be applied if we request it. The main issue is that if
374  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
375  */
smooth_behavior()376 static SmoothBehavior smooth_behavior() {
377     static SmoothBehavior gSmoothBehavior = []{
378         uint32_t noSmoothBitmap[16][16] = {};
379         uint32_t smoothBitmap[16][16] = {};
380 
381         SkUniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
382         SkUniqueCFRef<CGContextRef> noSmoothContext(
383                 CGBitmapContextCreate(&noSmoothBitmap, 16, 16, 8, 16*4,
384                                       colorspace.get(), BITMAP_INFO_RGB));
385         SkUniqueCFRef<CGContextRef> smoothContext(
386                 CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
387                                       colorspace.get(), BITMAP_INFO_RGB));
388 
389         SkUniqueCFRef<CGDataProviderRef> data(
390                 CGDataProviderCreateWithData(nullptr, kSpiderSymbol_ttf,
391                                              SK_ARRAY_COUNT(kSpiderSymbol_ttf), nullptr));
392         SkUniqueCFRef<CGFontRef> cgFont(CGFontCreateWithDataProvider(data.get()));
393         SkASSERT(cgFont);
394         SkUniqueCFRef<CTFontRef> ctFont(
395                 CTFontCreateWithGraphicsFont(cgFont.get(), 16, nullptr, nullptr));
396         SkASSERT(ctFont);
397 
398         CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
399         CGContextSetShouldAntialias(noSmoothContext.get(), true);
400         CGContextSetTextDrawingMode(noSmoothContext.get(), kCGTextFill);
401         CGContextSetGrayFillColor(noSmoothContext.get(), 1, 1);
402 
403         CGContextSetShouldSmoothFonts(smoothContext.get(), true);
404         CGContextSetShouldAntialias(smoothContext.get(), true);
405         CGContextSetTextDrawingMode(smoothContext.get(), kCGTextFill);
406         CGContextSetGrayFillColor(smoothContext.get(), 1, 1);
407 
408         CGPoint point = CGPointMake(0, 3);
409         CGGlyph spiderGlyph = 3;
410         CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, noSmoothContext.get());
411         CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, smoothContext.get());
412 
413         // For debugging.
414         //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(noSmoothContext()));
415         //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(smoothContext()));
416 
417         SmoothBehavior smoothBehavior = SmoothBehavior::none;
418         for (int x = 0; x < 16; ++x) {
419             for (int y = 0; y < 16; ++y) {
420                 uint32_t smoothPixel = smoothBitmap[x][y];
421                 uint32_t r = (smoothPixel >> 16) & 0xFF;
422                 uint32_t g = (smoothPixel >>  8) & 0xFF;
423                 uint32_t b = (smoothPixel >>  0) & 0xFF;
424                 if (r != g || r != b) {
425                     return SmoothBehavior::subpixel;
426                 }
427                 if (noSmoothBitmap[x][y] != smoothPixel) {
428                     smoothBehavior = SmoothBehavior::some;
429                 }
430             }
431         }
432         return smoothBehavior;
433     }();
434     return gSmoothBehavior;
435 }
436 
437 class Offscreen {
438 public:
Offscreen()439     Offscreen()
440         : fRGBSpace(nullptr)
441         , fCG(nullptr)
442         , fDoAA(false)
443         , fDoLCD(false)
444     {
445         fSize.set(0, 0);
446     }
447 
448     CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
449                       CGGlyph glyphID, size_t* rowBytesPtr, bool generateA8FromLCD,
450                       bool lightOnDark);
451 
452 private:
453     enum {
454         kSize = 32 * 32 * sizeof(CGRGBPixel)
455     };
456     SkAutoSMalloc<kSize> fImageStorage;
457     SkUniqueCFRef<CGColorSpaceRef> fRGBSpace;
458 
459     // cached state
460     SkUniqueCFRef<CGContextRef> fCG;
461     SkISize fSize;
462     bool fDoAA;
463     bool fDoLCD;
464 
RoundSize(int dimension)465     static int RoundSize(int dimension) {
466         return SkNextPow2(dimension);
467     }
468 };
469 
470 ///////////////////////////////////////////////////////////////////////////////
471 
find_dict_CGFloat(CFDictionaryRef dict,CFStringRef name,CGFloat * value)472 static bool find_dict_CGFloat(CFDictionaryRef dict, CFStringRef name, CGFloat* value) {
473     CFNumberRef num;
474     return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num)
475         && CFNumberIsFloatType(num)
476         && CFNumberGetValue(num, kCFNumberCGFloatType, value);
477 }
478 
479 template <typename S, typename D, typename C> struct LinearInterpolater {
480     struct Mapping {
481         S src_val;
482         D dst_val;
483     };
LinearInterpolaterLinearInterpolater484     constexpr LinearInterpolater(Mapping const mapping[], int mappingCount)
485         : fMapping(mapping), fMappingCount(mappingCount) {}
486 
mapLinearInterpolater487     static D map(S value, S src_min, S src_max, D dst_min, D dst_max) {
488         SkASSERT(src_min < src_max);
489         SkASSERT(dst_min <= dst_max);
490         return C()(dst_min + (((value - src_min) * (dst_max - dst_min)) / (src_max - src_min)));
491     }
492 
mapLinearInterpolater493     D map(S val) const {
494         // -Inf to [0]
495         if (val < fMapping[0].src_val) {
496             return fMapping[0].dst_val;
497         }
498 
499         // Linear from [i] to [i+1]
500         for (int i = 0; i < fMappingCount - 1; ++i) {
501             if (val < fMapping[i+1].src_val) {
502                 return map(val, fMapping[i].src_val, fMapping[i+1].src_val,
503                                 fMapping[i].dst_val, fMapping[i+1].dst_val);
504             }
505         }
506 
507         // From [n] to +Inf
508         // if (fcweight < Inf)
509         return fMapping[fMappingCount - 1].dst_val;
510     }
511 
512     Mapping const * fMapping;
513     int fMappingCount;
514 };
515 
516 struct RoundCGFloatToInt {
operator ()RoundCGFloatToInt517     int operator()(CGFloat s) { return s + 0.5; }
518 };
519 struct CGFloatIdentity {
operator ()CGFloatIdentity520     CGFloat operator()(CGFloat s) { return s; }
521 };
522 
523 /** Returns the [-1, 1] CTFontDescriptor weights for the
524  *  <0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000> CSS weights.
525  *
526  *  It is assumed that the values will be interpolated linearly between these points.
527  *  NSFontWeightXXX were added in 10.11, appear in 10.10, but do not appear in 10.9.
528  *  The actual values appear to be stable, but they may change in the future without notice.
529  */
get_NSFontWeight_mapping()530 static CGFloat(&get_NSFontWeight_mapping())[11] {
531 
532     // Declarations in <AppKit/AppKit.h> on macOS, <UIKit/UIKit.h> on iOS
533 #ifdef SK_BUILD_FOR_MAC
534 #  define SK_KIT_FONT_WEIGHT_PREFIX "NS"
535 #endif
536 #ifdef SK_BUILD_FOR_IOS
537 #  define SK_KIT_FONT_WEIGHT_PREFIX "UI"
538 #endif
539     static constexpr struct {
540         CGFloat defaultValue;
541         const char* name;
542     } nsFontWeightLoaderInfos[] = {
543         { -0.80f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightUltraLight" },
544         { -0.60f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightThin" },
545         { -0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightLight" },
546         {  0.00f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightRegular" },
547         {  0.23f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightMedium" },
548         {  0.30f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightSemibold" },
549         {  0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBold" },
550         {  0.56f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightHeavy" },
551         {  0.62f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBlack" },
552     };
553 
554     static_assert(SK_ARRAY_COUNT(nsFontWeightLoaderInfos) == 9, "");
555     static CGFloat nsFontWeights[11];
556     static SkOnce once;
557     once([&] {
558         size_t i = 0;
559         nsFontWeights[i++] = -1.00;
560         for (const auto& nsFontWeightLoaderInfo : nsFontWeightLoaderInfos) {
561             void* nsFontWeightValuePtr = dlsym(RTLD_DEFAULT, nsFontWeightLoaderInfo.name);
562             if (nsFontWeightValuePtr) {
563                 nsFontWeights[i++] = *(static_cast<CGFloat*>(nsFontWeightValuePtr));
564             } else {
565                 nsFontWeights[i++] = nsFontWeightLoaderInfo.defaultValue;
566             }
567         }
568         nsFontWeights[i++] = 1.00;
569     });
570     return nsFontWeights;
571 }
572 
573 /** Convert the [0, 1000] CSS weight to [-1, 1] CTFontDescriptor weight (for system fonts).
574  *
575  *  The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
576  *  CTFont is native or created from a CGDataProvider.
577  */
578 static CGFloat fontstyle_to_ct_weight(int fontstyleWeight) {
579     using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
580 
581     // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
582     // However, on this end we can't tell, so this is ignored.
583 
584     static Interpolator::Mapping nativeWeightMappings[11];
585     static SkOnce once;
__anon65e1c2df0602null586     once([&] {
587         CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
588         for (int i = 0; i < 11; ++i) {
589             nativeWeightMappings[i].src_val = i * 100;
590             nativeWeightMappings[i].dst_val = nsFontWeights[i];
591         }
592     });
593     static constexpr Interpolator nativeInterpolator(
594             nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
595 
596     return nativeInterpolator.map(fontstyleWeight);
597 }
598 
599 
600 /** Convert the [-1, 1] CTFontDescriptor weight to [0, 1000] CSS weight.
601  *
602  *  The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
603  *  CTFont is native or created from a CGDataProvider.
604  */
ct_weight_to_fontstyle(CGFloat cgWeight,bool fromDataProvider)605 static int ct_weight_to_fontstyle(CGFloat cgWeight, bool fromDataProvider) {
606     using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
607 
608     // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
609     // However, on this end we can't tell, so this is ignored.
610 
611     /** This mapping for CGDataProvider created fonts is determined by creating font data with every
612      *  weight, creating a CTFont, and asking the CTFont for its weight. See the TypefaceStyle test
613      *  in tests/TypefaceTest.cpp for the code used to determine these values.
614      */
615     static constexpr Interpolator::Mapping dataProviderWeightMappings[] = {
616         { -1.00,    0 },
617         { -0.70,  100 },
618         { -0.50,  200 },
619         { -0.23,  300 },
620         {  0.00,  400 },
621         {  0.20,  500 },
622         {  0.30,  600 },
623         {  0.40,  700 },
624         {  0.60,  800 },
625         {  0.80,  900 },
626         {  1.00, 1000 },
627     };
628     static constexpr Interpolator dataProviderInterpolator(
629             dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings));
630 
631     static Interpolator::Mapping nativeWeightMappings[11];
632     static SkOnce once;
633     once([&] {
634         CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
635         for (int i = 0; i < 11; ++i) {
636             nativeWeightMappings[i].src_val = nsFontWeights[i];
637             nativeWeightMappings[i].dst_val = i * 100;
638         }
639     });
640     static constexpr Interpolator nativeInterpolator(
641             nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
642 
643     return fromDataProvider ? dataProviderInterpolator.map(cgWeight)
644                             : nativeInterpolator.map(cgWeight);
645 }
646 
647 /** Convert the [0, 10] CSS weight to [-1, 1] CTFontDescriptor width. */
fontstyle_to_ct_width(int fontstyleWidth)648 static int fontstyle_to_ct_width(int fontstyleWidth) {
649     using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
650 
651     // Values determined by creating font data with every width, creating a CTFont,
652     // and asking the CTFont for its width. See TypefaceStyle test for basics.
653     static constexpr Interpolator::Mapping widthMappings[] = {
654         {  0, -0.5 },
655         { 10,  0.5 },
656     };
657     static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
658     return interpolator.map(fontstyleWidth);
659 }
660 
661 /** Convert the [-1, 1] CTFontDescriptor width to [0, 10] CSS weight. */
ct_width_to_fontstyle(CGFloat cgWidth)662 static int ct_width_to_fontstyle(CGFloat cgWidth) {
663     using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
664 
665     // Values determined by creating font data with every width, creating a CTFont,
666     // and asking the CTFont for its width. See TypefaceStyle test for basics.
667     static constexpr Interpolator::Mapping widthMappings[] = {
668         { -0.5,  0 },
669         {  0.5, 10 },
670     };
671     static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
672     return interpolator.map(cgWidth);
673 }
674 
fontstyle_from_descriptor(CTFontDescriptorRef desc,bool fromDataProvider)675 static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc, bool fromDataProvider) {
676     SkUniqueCFRef<CFTypeRef> traits(CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute));
677     if (!traits || CFDictionaryGetTypeID() != CFGetTypeID(traits.get())) {
678         return SkFontStyle();
679     }
680     SkUniqueCFRef<CFDictionaryRef> fontTraitsDict(static_cast<CFDictionaryRef>(traits.release()));
681 
682     CGFloat weight, width, slant;
683     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWeightTrait, &weight)) {
684         weight = 0;
685     }
686     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWidthTrait, &width)) {
687         width = 0;
688     }
689     if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontSlantTrait, &slant)) {
690         slant = 0;
691     }
692 
693     return SkFontStyle(ct_weight_to_fontstyle(weight, fromDataProvider),
694                        ct_width_to_fontstyle(width),
695                        slant ? SkFontStyle::kItalic_Slant
696                              : SkFontStyle::kUpright_Slant);
697 }
698 
699 class SkTypeface_Mac : public SkTypeface {
700 public:
SkTypeface_Mac(SkUniqueCFRef<CTFontRef> fontRef,SkUniqueCFRef<CFTypeRef> resourceRef,const SkFontStyle & fs,bool isFixedPitch,std::unique_ptr<SkStreamAsset> providedData)701     SkTypeface_Mac(SkUniqueCFRef<CTFontRef> fontRef, SkUniqueCFRef<CFTypeRef> resourceRef,
702                    const SkFontStyle& fs, bool isFixedPitch,
703                    std::unique_ptr<SkStreamAsset> providedData)
704         : SkTypeface(fs, isFixedPitch)
705         , fFontRef(std::move(fontRef))
706         , fOriginatingCFTypeRef(std::move(resourceRef))
707         , fHasColorGlyphs(
708                 SkToBool(CTFontGetSymbolicTraits(fFontRef.get()) & kCTFontColorGlyphsTrait))
709         , fStream(std::move(providedData))
710         , fIsFromStream(fStream)
711     {
712         SkASSERT(fFontRef);
713     }
714 
715     SkUniqueCFRef<CTFontRef> fFontRef;
716     SkUniqueCFRef<CFTypeRef> fOriginatingCFTypeRef;
717     const bool fHasColorGlyphs;
hasColorGlyphs() const718     bool hasColorGlyphs() const override { return fHasColorGlyphs; }
719 
720 protected:
721     int onGetUPEM() const override;
722     std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
723     std::unique_ptr<SkFontData> onMakeFontData() const override;
724     int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
725                                      int coordinateCount) const override;
726     void onGetFamilyName(SkString* familyName) const override;
727     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
728     int onGetTableTags(SkFontTableTag tags[]) const override;
729     size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
730     sk_sp<SkData> onCopyTableData(SkFontTableTag) const override;
731     SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
732                                            const SkDescriptor*) const override;
733     void onFilterRec(SkScalerContextRec*) const override;
734     void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
735     void getGlyphToUnicodeMap(SkUnichar*) const override;
736     std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
737     void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
738     int onCountGlyphs() const override;
getPostScriptGlyphNames(SkString *) const739     void getPostScriptGlyphNames(SkString*) const override {}
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const740     int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
741                                        int parameterCount) const override
742     {
743         return -1;
744     }
onMakeClone(const SkFontArguments &) const745     sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const override {
746         return nullptr;
747     }
748 
onGetCTFontRef() const749     void* onGetCTFontRef() const override { return (void*)fFontRef.get(); }
750 
751 private:
752     mutable std::unique_ptr<SkStreamAsset> fStream;
753     bool fIsFromStream;
754     mutable SkOnce fInitStream;
755 
756     typedef SkTypeface INHERITED;
757 };
758 
find_by_CTFontRef(SkTypeface * cached,void * context)759 static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
760     CTFontRef self = (CTFontRef)context;
761     CTFontRef other = (CTFontRef)cached->internal_private_getCTFontRef();
762 
763     return CFEqual(self, other);
764 }
765 
766 /** Creates a typeface, searching the cache if isLocalStream is false. */
create_from_CTFontRef(SkUniqueCFRef<CTFontRef> font,SkUniqueCFRef<CFTypeRef> resource,std::unique_ptr<SkStreamAsset> providedData)767 static sk_sp<SkTypeface> create_from_CTFontRef(SkUniqueCFRef<CTFontRef> font,
768                                                SkUniqueCFRef<CFTypeRef> resource,
769                                                std::unique_ptr<SkStreamAsset> providedData) {
770     SkASSERT(font);
771     const bool isFromStream(providedData);
772 
773     if (!isFromStream) {
774         sk_sp<SkTypeface> face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef,
775                                                                    (void*)font.get());
776         if (face) {
777             return face;
778         }
779     }
780 
781     SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get()));
782     SkFontStyle style = fontstyle_from_descriptor(desc.get(), isFromStream);
783     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get());
784     bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait);
785 
786     sk_sp<SkTypeface> face(new SkTypeface_Mac(std::move(font), std::move(resource),
787                                               style, isFixedPitch, std::move(providedData)));
788     if (!isFromStream) {
789         SkTypefaceCache::Add(face);
790     }
791     return face;
792 }
793 
794 /** Creates a typeface from a descriptor, searching the cache. */
create_from_desc(CTFontDescriptorRef desc)795 static sk_sp<SkTypeface> create_from_desc(CTFontDescriptorRef desc) {
796     SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
797     if (!ctFont) {
798         return nullptr;
799     }
800 
801     return create_from_CTFontRef(std::move(ctFont), nullptr, nullptr);
802 }
803 
create_descriptor(const char familyName[],const SkFontStyle & style)804 static SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[],
805                                                             const SkFontStyle& style) {
806     SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes(
807             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
808                                       &kCFTypeDictionaryKeyCallBacks,
809                                       &kCFTypeDictionaryValueCallBacks));
810 
811     SkUniqueCFRef<CFMutableDictionaryRef> cfTraits(
812             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
813                                       &kCFTypeDictionaryKeyCallBacks,
814                                       &kCFTypeDictionaryValueCallBacks));
815 
816     if (!cfAttributes || !cfTraits) {
817         return nullptr;
818     }
819 
820     // CTFontTraits (symbolic)
821     // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set.
822 
823     // CTFontTraits (weight)
824     CGFloat ctWeight = fontstyle_to_ct_weight(style.weight());
825     SkUniqueCFRef<CFNumberRef> cfFontWeight(
826             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
827     if (cfFontWeight) {
828         CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
829     }
830     // CTFontTraits (width)
831     CGFloat ctWidth = fontstyle_to_ct_width(style.width());
832     SkUniqueCFRef<CFNumberRef> cfFontWidth(
833             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
834     if (cfFontWidth) {
835         CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
836     }
837     // CTFontTraits (slant)
838     CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1;
839     SkUniqueCFRef<CFNumberRef> cfFontSlant(
840             CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
841     if (cfFontSlant) {
842         CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
843     }
844     // CTFontTraits
845     CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
846 
847     // CTFontFamilyName
848     if (familyName) {
849         SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
850         if (cfFontName) {
851             CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
852         }
853     }
854 
855     return SkUniqueCFRef<CTFontDescriptorRef>(
856             CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
857 }
858 
859 // Same as the above function except style is included so we can
860 // compare whether the created font conforms to the style. If not, we need
861 // to recreate the font with symbolic traits. This is needed due to MacOS 10.11
862 // font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447.
create_from_desc_and_style(CTFontDescriptorRef desc,const SkFontStyle & style)863 static sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc,
864                                                     const SkFontStyle& style) {
865     SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
866     if (!ctFont) {
867         return nullptr;
868     }
869 
870     const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get());
871     CTFontSymbolicTraits expected_traits = traits;
872     if (style.slant() != SkFontStyle::kUpright_Slant) {
873         expected_traits |= kCTFontItalicTrait;
874     }
875     if (style.weight() >= SkFontStyle::kBold_Weight) {
876         expected_traits |= kCTFontBoldTrait;
877     }
878 
879     if (expected_traits != traits) {
880         SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits(ctFont.get(), 0,                                       nullptr, expected_traits, expected_traits));
881         if (ctNewFont) {
882             ctFont = std::move(ctNewFont);
883         }
884     }
885 
886     return create_from_CTFontRef(std::move(ctFont), nullptr, nullptr);
887 }
888 
889 /** Creates a typeface from a name, searching the cache. */
create_from_name(const char familyName[],const SkFontStyle & style)890 static sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontStyle& style) {
891     SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
892     if (!desc) {
893         return nullptr;
894     }
895     return create_from_desc_and_style(desc.get(), style);
896 }
897 
898 ///////////////////////////////////////////////////////////////////////////////
899 
900 /*  This function is visible on the outside. It first searches the cache, and if
901  *  not found, returns a new entry (after adding it to the cache).
902  */
SkCreateTypefaceFromCTFont(CTFontRef font,CFTypeRef resource)903 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font, CFTypeRef resource) {
904     CFRetain(font);
905     if (resource) {
906         CFRetain(resource);
907     }
908     return create_from_CTFontRef(SkUniqueCFRef<CTFontRef>(font),
909                                  SkUniqueCFRef<CFTypeRef>(resource),
910                                  nullptr).release();
911 }
912 
map_css_names(const char * name)913 static const char* map_css_names(const char* name) {
914     static const struct {
915         const char* fFrom;  // name the caller specified
916         const char* fTo;    // "canonical" name we map to
917     } gPairs[] = {
918         { "sans-serif", "Helvetica" },
919         { "serif",      "Times"     },
920         { "monospace",  "Courier"   }
921     };
922 
923     for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
924         if (strcmp(name, gPairs[i].fFrom) == 0) {
925             return gPairs[i].fTo;
926         }
927     }
928     return name;    // no change
929 }
930 
931 ///////////////////////////////////////////////////////////////////////////////
932 
933 class SkScalerContext_Mac : public SkScalerContext {
934 public:
935     SkScalerContext_Mac(sk_sp<SkTypeface_Mac>, const SkScalerContextEffects&, const SkDescriptor*);
936 
937 protected:
938     unsigned generateGlyphCount(void) override;
939     bool generateAdvance(SkGlyph* glyph) override;
940     void generateMetrics(SkGlyph* glyph) override;
941     void generateImage(const SkGlyph& glyph) override;
942     bool generatePath(SkGlyphID glyph, SkPath* path) override;
943     void generateFontMetrics(SkFontMetrics*) override;
944 
945 private:
946     static void CTPathElement(void *info, const CGPathElement *element);
947     template<bool APPLY_PREBLEND>
948     static void RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
949                         const SkGlyph& glyph, const uint8_t* table8);
950     template<bool APPLY_PREBLEND>
951     static uint16_t RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
952                                const uint8_t* tableG,
953                                const uint8_t* tableB);
954     template<bool APPLY_PREBLEND>
955     static void RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels,
956                            size_t cgRowBytes,
957                            const SkGlyph& glyph,
958                            const uint8_t* tableR,
959                            const uint8_t* tableG,
960                            const uint8_t* tableB);
961 
962     Offscreen fOffscreen;
963 
964     /** Unrotated variant of fCTFont.
965      *
966      *  In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the
967      *  advances, but always sets the height to 0. This font is used to get the advances of the
968      *  unrotated glyph, and then the rotation is applied separately.
969      *
970      *  CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
971      *  This makes kCTFontOrientationDefault dangerous, because the metrics from
972      *  kCTFontOrientationHorizontal are in a different space from kCTFontOrientationVertical.
973      *  With kCTFontOrientationVertical the advances must be unrotated.
974      *
975      *  Sometimes, creating a copy of a CTFont with the same size but different trasform will select
976      *  different underlying font data. As a result, avoid ever creating more than one CTFont per
977      *  SkScalerContext to ensure that only one CTFont is used.
978      *
979      *  As a result of the above (and other constraints) this font contains the size, but not the
980      *  transform. The transform must always be applied separately.
981      */
982     SkUniqueCFRef<CTFontRef> fCTFont;
983 
984     /** The transform without the font size. */
985     CGAffineTransform fTransform;
986     CGAffineTransform fInvTransform;
987 
988     SkUniqueCFRef<CGFontRef> fCGFont;
989     uint16_t fGlyphCount;
990     const bool fDoSubPosition;
991 
992     friend class Offscreen;
993 
994     typedef SkScalerContext INHERITED;
995 };
996 
997 // CTFontCreateCopyWithAttributes or CTFontCreateCopyWithSymbolicTraits cannot be used on 10.10
998 // and later, as they will return different underlying fonts depending on the size requested.
ctfont_create_exact_copy(CTFontRef baseFont,CGFloat textSize,const CGAffineTransform * transform)999 static SkUniqueCFRef<CTFontRef> ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize,
1000                                                          const CGAffineTransform* transform)
1001 {
1002     // To figure out if a font is installed locally or used from a @font-face
1003     // resource, we check whether its descriptor can provide a URL. This will
1004     // be present for installed fonts, but not for those activated from an
1005     // in-memory resource.
1006     auto IsInstalledFont = [](CTFontRef aFont) {
1007         CTFontDescriptorRef desc = CTFontCopyFontDescriptor(aFont);
1008         CFTypeRef attr = CTFontDescriptorCopyAttribute(desc, kCTFontURLAttribute);
1009         CFRelease(desc);
1010         bool result = false;
1011         if (attr) {
1012             result = true;
1013             CFRelease(attr);
1014         }
1015         return result;
1016     };
1017 
1018     // If we have a system font we need to use the CGFont APIs to avoid having the
1019     // underlying font change for us when using CTFontCreateCopyWithAttributes.
1020     if (IsInstalledFont(baseFont)) {
1021         SkUniqueCFRef<CGFontRef> baseCGFont(CTFontCopyGraphicsFont(baseFont, nullptr));
1022 
1023         // The last parameter (CTFontDescriptorRef attributes) *must* be nullptr.
1024         // If non-nullptr then with fonts with variation axes, the copy will fail in
1025         // CGFontVariationFromDictCallback when it assumes kCGFontVariationAxisName is CFNumberRef
1026         // which it quite obviously is not.
1027 
1028         // Because we cannot setup the CTFont descriptor to match, the same restriction applies here
1029         // as other uses of CTFontCreateWithGraphicsFont which is that such CTFonts should not escape
1030         // the scaler context, since they aren't 'normal'.
1031 
1032         // Avoid calling potentially buggy variation APIs on pre-Sierra macOS
1033         // versions (see bug 1331683).
1034         //
1035         // And on HighSierra, CTFontCreateWithGraphicsFont properly carries over
1036         // variation settings from the CGFont to CTFont, so we don't need to do
1037         // the extra work here -- and this seems to avoid Core Text crashiness
1038         // seen in bug 1454094.
1039         //
1040         // However, for installed fonts it seems we DO need to copy the variations
1041         // explicitly even on 10.13, otherwise fonts fail to render (as in bug
1042         // 1455494) when non-default values are used. Fortunately, the crash
1043         // mentioned above occurs with data fonts, not (AFAICT) with system-
1044         // installed fonts.
1045         //
1046         // So we only need to do this "the hard way" on Sierra, and for installed
1047         // fonts on HighSierra+; otherwise, just let the standard CTFont function
1048         // do its thing.
1049         //
1050         // NOTE in case this ever needs further adjustment: there is similar logic
1051         // in four places in the tree (sadly):
1052         //    CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
1053         //    CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
1054         //    CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
1055         //    ctfont_create_exact_copy in SkFontHost_mac.cpp
1056 
1057         // Not UniqueCFRef<> because CGFontCopyVariations can return null!
1058         CFDictionaryRef variations = CGFontCopyVariations(baseCGFont.get());
1059         if (variations) {
1060             SkUniqueCFRef<CFDictionaryRef>
1061             varAttr(CFDictionaryCreate(nullptr,
1062                                          (const void**)&kCTFontVariationAttribute,
1063                                          (const void**)&variations,
1064                                          1,
1065                                          &kCFTypeDictionaryKeyCallBacks,
1066                                          &kCFTypeDictionaryValueCallBacks));
1067             CFRelease(variations);
1068 
1069             SkUniqueCFRef<CTFontDescriptorRef>
1070               varDesc(CTFontDescriptorCreateWithAttributes(varAttr.get()));
1071 
1072             return SkUniqueCFRef<CTFontRef>(
1073                                             CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, transform, varDesc.get()));
1074         }
1075         return SkUniqueCFRef<CTFontRef>(
1076                                       CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, transform, nullptr));
1077     } else {
1078         return SkUniqueCFRef<CTFontRef>(CTFontCreateCopyWithAttributes(baseFont, textSize, transform, nullptr));
1079     }
1080 }
1081 
SkScalerContext_Mac(sk_sp<SkTypeface_Mac> typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc)1082 SkScalerContext_Mac::SkScalerContext_Mac(sk_sp<SkTypeface_Mac> typeface,
1083                                          const SkScalerContextEffects& effects,
1084                                          const SkDescriptor* desc)
1085         : INHERITED(std::move(typeface), effects, desc)
1086         , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
1087 
1088 {
1089     CTFontRef ctFont = (CTFontRef)this->getTypeface()->internal_private_getCTFontRef();
1090     CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
1091     SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
1092     fGlyphCount = SkToU16(numGlyphs);
1093 
1094     // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
1095     // As a result, it is necessary to know the actual device size and request that.
1096     SkVector scale;
1097     SkMatrix skTransform;
1098     bool invertible = fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
1099                                            &scale, &skTransform, nullptr, nullptr, nullptr);
1100     fTransform = MatrixToCGAffineTransform(skTransform);
1101     // CGAffineTransformInvert documents that if the transform is non-invertible it will return the
1102     // passed transform unchanged. It does so, but then also prints a message to stdout. Avoid this.
1103     if (invertible) {
1104         fInvTransform = CGAffineTransformInvert(fTransform);
1105     } else {
1106         fInvTransform = fTransform;
1107     }
1108 
1109     // The transform contains everything except the requested text size.
1110     // Some properties, like 'trak', are based on the text size (before applying the matrix).
1111     CGFloat textSize = ScalarToCG(scale.y());
1112     fCTFont = ctfont_create_exact_copy(ctFont, textSize, nullptr);
1113     fCGFont.reset(CTFontCopyGraphicsFont(fCTFont.get(), nullptr));
1114 }
1115 
getCG(const SkScalerContext_Mac & context,const SkGlyph & glyph,CGGlyph glyphID,size_t * rowBytesPtr,bool generateA8FromLCD,bool lightOnDark)1116 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
1117                              CGGlyph glyphID, size_t* rowBytesPtr,
1118                              bool generateA8FromLCD, bool lightOnDark) {
1119     if (!fRGBSpace) {
1120         //It doesn't appear to matter what color space is specified.
1121         //Regular blends and antialiased text are always (s*a + d*(1-a))
1122         //and subpixel antialiased text is always g=2.0.
1123         fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
1124     }
1125 
1126     // default to kBW_Format
1127     bool doAA = false;
1128     bool doLCD = false;
1129 
1130     if (SkMask::kBW_Format != glyph.maskFormat()) {
1131         doLCD = true;
1132         doAA = true;
1133     }
1134 
1135     // FIXME: lcd smoothed un-hinted rasterization unsupported.
1136     if (!generateA8FromLCD && SkMask::kA8_Format == glyph.maskFormat()) {
1137         doLCD = false;
1138         doAA = true;
1139     }
1140 
1141     // If this font might have color glyphs, disable LCD as there's no way to support it.
1142     // CoreText doesn't tell us which format it ended up using, so we can't detect it.
1143     // A8 will end up black on transparent, but TODO: we can detect gray and set to A8.
1144     if (SkMask::kARGB32_Format == glyph.maskFormat()) {
1145         doLCD = false;
1146     }
1147 
1148     size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
1149     if (!fCG || fSize.fWidth < glyph.width() || fSize.fHeight < glyph.height()) {
1150         if (fSize.fWidth < glyph.width()) {
1151             fSize.fWidth = RoundSize(glyph.width());
1152         }
1153         if (fSize.fHeight < glyph.height()) {
1154             fSize.fHeight = RoundSize(glyph.height());
1155         }
1156 
1157         rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
1158         void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
1159         const CGImageAlphaInfo alpha = (glyph.isColor())
1160                                      ? kCGImageAlphaPremultipliedFirst
1161                                      : kCGImageAlphaNoneSkipFirst;
1162         const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha;
1163         fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
1164                                         rowBytes, fRGBSpace.get(), bitmapInfo));
1165 
1166         // Skia handles quantization and subpixel positioning,
1167         // so disable quantization and enabe subpixel positioning in CG.
1168         CGContextSetAllowsFontSubpixelQuantization(fCG.get(), false);
1169         CGContextSetShouldSubpixelQuantizeFonts(fCG.get(), false);
1170 
1171         // Because CG always draws from the horizontal baseline,
1172         // if there is a non-integral translation from the horizontal origin to the vertical origin,
1173         // then CG cannot draw the glyph in the correct location without subpixel positioning.
1174         CGContextSetAllowsFontSubpixelPositioning(fCG.get(), true);
1175         CGContextSetShouldSubpixelPositionFonts(fCG.get(), true);
1176 
1177         CGContextSetTextDrawingMode(fCG.get(), kCGTextFill);
1178 
1179         // Draw black on white to create mask. (Special path exists to speed this up in CG.)
1180         // If light-on-dark is requested, draw white on black.
1181         CGContextSetGrayFillColor(fCG.get(), lightOnDark ? 1.0f : 0.0f, 1.0f);
1182 
1183         // force our checks below to happen
1184         fDoAA = !doAA;
1185         fDoLCD = !doLCD;
1186 
1187         CGContextSetTextMatrix(fCG.get(), context.fTransform);
1188     }
1189 
1190     if (fDoAA != doAA) {
1191         CGContextSetShouldAntialias(fCG.get(), doAA);
1192         fDoAA = doAA;
1193     }
1194     if (fDoLCD != doLCD) {
1195         CGContextSetShouldSmoothFonts(fCG.get(), doLCD);
1196         fDoLCD = doLCD;
1197     }
1198 
1199     CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
1200     // skip rows based on the glyph's height
1201     image += (fSize.fHeight - glyph.height()) * fSize.fWidth;
1202 
1203     // Erase to white (or transparent black if it's a color glyph, to not composite against white).
1204     // For light-on-dark, instead erase to black.
1205     uint32_t bgColor = (!glyph.isColor()) ? (lightOnDark ? 0xFF000000 : 0xFFFFFFFF) : 0x00000000;
1206     sk_memset_rect32(image, bgColor, glyph.width(), glyph.height(), rowBytes);
1207 
1208     float subX = 0;
1209     float subY = 0;
1210     if (context.fDoSubPosition) {
1211         subX = SkFixedToFloat(glyph.getSubXFixed());
1212         subY = SkFixedToFloat(glyph.getSubYFixed());
1213     }
1214 
1215     CGPoint point = CGPointMake(-glyph.left() + subX, glyph.top() + glyph.height() - subY);
1216     // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
1217     // 'positions' which are in text space. The glyph location (in device space) must be
1218     // mapped into text space, so that CG can convert it back into device space.
1219     // In 10.10.1, this is handled directly in CTFontDrawGlyphs.
1220     //
1221     // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
1222     // So always make the font transform identity and place the transform on the context.
1223     point = CGPointApplyAffineTransform(point, context.fInvTransform);
1224 
1225     CTFontDrawGlyphs(context.fCTFont.get(), &glyphID, &point, 1, fCG.get());
1226 
1227     SkASSERT(rowBytesPtr);
1228     *rowBytesPtr = rowBytes;
1229     return image;
1230 }
1231 
generateGlyphCount(void)1232 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
1233     return fGlyphCount;
1234 }
1235 
generateAdvance(SkGlyph * glyph)1236 bool SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
1237     return false;
1238 }
1239 
generateMetrics(SkGlyph * glyph)1240 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
1241     glyph->fMaskFormat = fRec.fMaskFormat;
1242 
1243     const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
1244     glyph->zeroMetrics();
1245 
1246     // The following block produces cgAdvance in CG units (pixels, y up).
1247     CGSize cgAdvance;
1248     CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
1249                                &cgGlyph, &cgAdvance, 1);
1250     cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
1251     glyph->fAdvanceX =  CGToFloat(cgAdvance.width);
1252     glyph->fAdvanceY = -CGToFloat(cgAdvance.height);
1253 
1254     // The following produces skBounds in SkGlyph units (pixels, y down),
1255     // or returns early if skBounds would be empty.
1256     SkRect skBounds;
1257 
1258     // Glyphs are always drawn from the horizontal origin. The caller must manually use the result
1259     // of CTFontGetVerticalTranslationsForGlyphs to calculate where to draw the glyph for vertical
1260     // glyphs. As a result, always get the horizontal bounds of a glyph and translate it if the
1261     // glyph is vertical. This avoids any diagreement between the various means of retrieving
1262     // vertical metrics.
1263     {
1264         // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
1265         CGRect cgBounds;
1266         CTFontGetBoundingRectsForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
1267                                         &cgGlyph, &cgBounds, 1);
1268         cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
1269 
1270         // BUG?
1271         // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
1272         // it should be empty. So, if we see a zero-advance, we check if it has an
1273         // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
1274         // is rare, so we won't incur a big performance cost for this extra check.
1275         // Avoid trying to create a path from a color font due to crashing on 10.9.
1276         if (0 == cgAdvance.width && 0 == cgAdvance.height &&
1277             SkMask::kARGB32_Format != glyph->fMaskFormat) {
1278             SkUniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph,nullptr));
1279             if (!path || CGPathIsEmpty(path.get())) {
1280                 return;
1281             }
1282         }
1283 
1284         if (CGRectIsEmpty_inline(cgBounds)) {
1285             return;
1286         }
1287 
1288         // Convert cgBounds to SkGlyph units (pixels, y down).
1289         skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
1290                                     cgBounds.size.width, cgBounds.size.height);
1291     }
1292 
1293     // Currently the bounds are based on being rendered at (0,0).
1294     // The top left must not move, since that is the base from which subpixel positioning is offset.
1295     if (fDoSubPosition) {
1296         skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
1297         skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
1298     }
1299 
1300     // We're trying to pack left and top into int16_t,
1301     // and width and height into uint16_t, after outsetting by 1.
1302     if (!SkRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(skBounds)) {
1303         return;
1304     }
1305 
1306     SkIRect skIBounds;
1307     skBounds.roundOut(&skIBounds);
1308     // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
1309     // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
1310     // is not currently known, as CG dilates the outlines by some percentage.
1311     // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
1312     skIBounds.outset(1, 1);
1313     glyph->fLeft = SkToS16(skIBounds.fLeft);
1314     glyph->fTop = SkToS16(skIBounds.fTop);
1315     glyph->fWidth = SkToU16(skIBounds.width());
1316     glyph->fHeight = SkToU16(skIBounds.height());
1317 }
1318 
1319 #include "include/private/SkColorData.h"
1320 
sk_pow2_table(size_t i)1321 static constexpr uint8_t sk_pow2_table(size_t i) {
1322     return SkToU8(((i * i + 128) / 255));
1323 }
1324 
1325 /**
1326  *  This will invert the gamma applied by CoreGraphics, so we can get linear
1327  *  values.
1328  *
1329  *  CoreGraphics obscurely defaults to 2.0 as the subpixel coverage gamma value.
1330  *  The color space used does not appear to affect this choice.
1331  */
1332 static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
1333 
cgpixels_to_bits(uint8_t dst[],const CGRGBPixel src[],int count)1334 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
1335     while (count > 0) {
1336         uint8_t mask = 0;
1337         for (int i = 7; i >= 0; --i) {
1338             mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i;
1339             if (0 == --count) {
1340                 break;
1341             }
1342         }
1343         *dst++ = mask;
1344     }
1345 }
1346 
1347 template<bool APPLY_PREBLEND>
rgb_to_a8(CGRGBPixel rgb,const uint8_t * table8)1348 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
1349     U8CPU r = 0xFF - ((rgb >> 16) & 0xFF);
1350     U8CPU g = 0xFF - ((rgb >>  8) & 0xFF);
1351     U8CPU b = 0xFF - ((rgb >>  0) & 0xFF);
1352     U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
1353 #if SK_SHOW_TEXT_BLIT_COVERAGE
1354     lum = SkTMax(lum, (U8CPU)0x30);
1355 #endif
1356     return lum;
1357 }
1358 
1359 template<bool APPLY_PREBLEND>
RGBToA8(const CGRGBPixel * SK_RESTRICT cgPixels,size_t cgRowBytes,const SkGlyph & glyph,const uint8_t * table8)1360 void SkScalerContext_Mac::RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
1361                                   const SkGlyph& glyph, const uint8_t* table8) {
1362     const int width = glyph.fWidth;
1363     size_t dstRB = glyph.rowBytes();
1364     uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
1365 
1366     for (int y = 0; y < glyph.fHeight; y++) {
1367         for (int i = 0; i < width; ++i) {
1368             dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
1369         }
1370         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
1371         dst = SkTAddOffset<uint8_t>(dst, dstRB);
1372     }
1373 }
1374 
1375 template<bool APPLY_PREBLEND>
RGBToLcd16(CGRGBPixel rgb,const uint8_t * tableR,const uint8_t * tableG,const uint8_t * tableB)1376 uint16_t SkScalerContext_Mac::RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
1377                                          const uint8_t* tableG,
1378                                          const uint8_t* tableB) {
1379     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
1380     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  8) & 0xFF), tableG);
1381     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  0) & 0xFF), tableB);
1382 #if SK_SHOW_TEXT_BLIT_COVERAGE
1383     r = SkTMax(r, (U8CPU)0x30);
1384     g = SkTMax(g, (U8CPU)0x30);
1385     b = SkTMax(b, (U8CPU)0x30);
1386 #endif
1387     return SkPack888ToRGB16(r, g, b);
1388 }
1389 
1390 template<bool APPLY_PREBLEND>
RGBToLcd16(const CGRGBPixel * SK_RESTRICT cgPixels,size_t cgRowBytes,const SkGlyph & glyph,const uint8_t * tableR,const uint8_t * tableG,const uint8_t * tableB)1391 void SkScalerContext_Mac::RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels,
1392                                      size_t cgRowBytes,
1393                                      const SkGlyph& glyph,
1394                                      const uint8_t* tableR,
1395                                      const uint8_t* tableG,
1396                                      const uint8_t* tableB) {
1397     const int width = glyph.fWidth;
1398     size_t dstRB = glyph.rowBytes();
1399     uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
1400 
1401     for (int y = 0; y < glyph.fHeight; y++) {
1402         for (int i = 0; i < width; i++) {
1403             dst[i] = RGBToLcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
1404         }
1405         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
1406         dst = SkTAddOffset<uint16_t>(dst, dstRB);
1407     }
1408 }
1409 
cgpixels_to_pmcolor(CGRGBPixel rgb)1410 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
1411     U8CPU a = (rgb >> 24) & 0xFF;
1412     U8CPU r = (rgb >> 16) & 0xFF;
1413     U8CPU g = (rgb >>  8) & 0xFF;
1414     U8CPU b = (rgb >>  0) & 0xFF;
1415 #if SK_SHOW_TEXT_BLIT_COVERAGE
1416     a = SkTMax(a, (U8CPU)0x30);
1417 #endif
1418     return SkPackARGB32(a, r, g, b);
1419 }
1420 
generateImage(const SkGlyph & glyph)1421 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
1422     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
1423 
1424     // FIXME: lcd smoothed un-hinted rasterization unsupported.
1425     bool requestSmooth = fRec.getHinting() != SkFontHinting::kNone;
1426     bool lightOnDark = (fRec.fFlags & SkScalerContext::kLightOnDark_Flag) != 0;
1427 
1428     // Draw the glyph
1429     size_t cgRowBytes;
1430     CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, requestSmooth, lightOnDark);
1431     if (cgPixels == nullptr) {
1432         return;
1433     }
1434 
1435     // Fix the glyph
1436     if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
1437         (glyph.fMaskFormat == SkMask::kA8_Format
1438          && requestSmooth
1439          && smooth_behavior() != SmoothBehavior::none))
1440     {
1441         const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
1442 
1443         //Note that the following cannot really be integrated into the
1444         //pre-blend, since we may not be applying the pre-blend; when we aren't
1445         //applying the pre-blend it means that a filter wants linear anyway.
1446         //Other code may also be applying the pre-blend, so we'd need another
1447         //one with this and one without.
1448         CGRGBPixel* addr = cgPixels;
1449         for (int y = 0; y < glyph.fHeight; ++y) {
1450             for (int x = 0; x < glyph.fWidth; ++x) {
1451                 int r = linear[(addr[x] >> 16) & 0xFF];
1452                 int g = linear[(addr[x] >>  8) & 0xFF];
1453                 int b = linear[(addr[x] >>  0) & 0xFF];
1454                 // If light-on-dark was requested, the mask is drawn inverted.
1455                 if (lightOnDark) {
1456                     r = 255 - r;
1457                     g = 255 - g;
1458                     b = 255 - b;
1459                 }
1460                 addr[x] = (r << 16) | (g << 8) | b;
1461             }
1462             addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
1463         }
1464     }
1465 
1466     // Convert glyph to mask
1467     switch (glyph.fMaskFormat) {
1468         case SkMask::kLCD16_Format: {
1469             if (fPreBlend.isApplicable()) {
1470                 RGBToLcd16<true>(cgPixels, cgRowBytes, glyph,
1471                                  fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1472             } else {
1473                 RGBToLcd16<false>(cgPixels, cgRowBytes, glyph,
1474                                   fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1475             }
1476         } break;
1477         case SkMask::kA8_Format: {
1478             if (fPreBlend.isApplicable()) {
1479                 RGBToA8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
1480             } else {
1481                 RGBToA8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
1482             }
1483         } break;
1484         case SkMask::kBW_Format: {
1485             const int width = glyph.fWidth;
1486             size_t dstRB = glyph.rowBytes();
1487             uint8_t* dst = (uint8_t*)glyph.fImage;
1488             for (int y = 0; y < glyph.fHeight; y++) {
1489                 cgpixels_to_bits(dst, cgPixels, width);
1490                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
1491                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
1492             }
1493         } break;
1494         case SkMask::kARGB32_Format: {
1495             const int width = glyph.fWidth;
1496             size_t dstRB = glyph.rowBytes();
1497             SkPMColor* dst = (SkPMColor*)glyph.fImage;
1498             for (int y = 0; y < glyph.fHeight; y++) {
1499                 for (int x = 0; x < width; ++x) {
1500                     dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
1501                 }
1502                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
1503                 dst = SkTAddOffset<SkPMColor>(dst, dstRB);
1504             }
1505         } break;
1506         default:
1507             SkDEBUGFAIL("unexpected mask format");
1508             break;
1509     }
1510 }
1511 
1512 /*
1513  *  Our subpixel resolution is only 2 bits in each direction, so a scale of 4
1514  *  seems sufficient, and possibly even correct, to allow the hinted outline
1515  *  to be subpixel positioned.
1516  */
1517 #define kScaleForSubPixelPositionHinting (4.0f)
1518 
generatePath(SkGlyphID glyph,SkPath * path)1519 bool SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
1520     SkScalar scaleX = SK_Scalar1;
1521     SkScalar scaleY = SK_Scalar1;
1522 
1523     CGAffineTransform xform = fTransform;
1524     /*
1525      *  For subpixel positioning, we want to return an unhinted outline, so it
1526      *  can be positioned nicely at fractional offsets. However, we special-case
1527      *  if the baseline of the (horizontal) text is axis-aligned. In those cases
1528      *  we want to retain hinting in the direction orthogonal to the baseline.
1529      *  e.g. for horizontal baseline, we want to retain hinting in Y.
1530      *  The way we remove hinting is to scale the font by some value (4) in that
1531      *  direction, ask for the path, and then scale the path back down.
1532      */
1533     if (fDoSubPosition) {
1534         // start out by assuming that we want no hining in X and Y
1535         scaleX = scaleY = kScaleForSubPixelPositionHinting;
1536         // now see if we need to restore hinting for axis-aligned baselines
1537         switch (this->computeAxisAlignmentForHText()) {
1538             case kX_SkAxisAlignment:
1539                 scaleY = SK_Scalar1; // want hinting in the Y direction
1540                 break;
1541             case kY_SkAxisAlignment:
1542                 scaleX = SK_Scalar1; // want hinting in the X direction
1543                 break;
1544             default:
1545                 break;
1546         }
1547 
1548         CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY)));
1549         xform = CGAffineTransformConcat(fTransform, scale);
1550     }
1551 
1552     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph);
1553     SkUniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
1554 
1555     path->reset();
1556     if (!cgPath) {
1557         return false;
1558     }
1559 
1560     CGPathApply(cgPath.get(), path, SkScalerContext_Mac::CTPathElement);
1561     if (fDoSubPosition) {
1562         SkMatrix m;
1563         m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
1564         path->transform(m);
1565     }
1566     return true;
1567 }
1568 
generateFontMetrics(SkFontMetrics * metrics)1569 void SkScalerContext_Mac::generateFontMetrics(SkFontMetrics* metrics) {
1570     if (nullptr == metrics) {
1571         return;
1572     }
1573 
1574     CGRect theBounds = CTFontGetBoundingBox(fCTFont.get());
1575 
1576     metrics->fTop          = CGToScalar(-CGRectGetMaxY_inline(theBounds));
1577     metrics->fAscent       = CGToScalar(-CTFontGetAscent(fCTFont.get()));
1578     metrics->fDescent      = CGToScalar( CTFontGetDescent(fCTFont.get()));
1579     metrics->fBottom       = CGToScalar(-CGRectGetMinY_inline(theBounds));
1580     metrics->fLeading      = CGToScalar( CTFontGetLeading(fCTFont.get()));
1581     metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
1582     metrics->fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
1583     metrics->fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
1584     metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
1585     metrics->fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont.get()));
1586     metrics->fCapHeight    = CGToScalar( CTFontGetCapHeight(fCTFont.get()));
1587     metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont.get()));
1588     metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont.get()));
1589 
1590     metrics->fFlags = 0;
1591     metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
1592     metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
1593 
1594     // See https://bugs.chromium.org/p/skia/issues/detail?id=6203
1595     // At least on 10.12.3 with memory based fonts the x-height is always 0.6666 of the ascent and
1596     // the cap-height is always 0.8888 of the ascent. It appears that the values from the 'OS/2'
1597     // table are read, but then overwritten if the font is not a system font. As a result, if there
1598     // is a valid 'OS/2' table available use the values from the table if they aren't too strange.
1599     struct OS2HeightMetrics {
1600         SK_OT_SHORT sxHeight;
1601         SK_OT_SHORT sCapHeight;
1602     } heights;
1603     size_t bytesRead = this->getTypeface()->getTableData(
1604             SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2, version.v2.sxHeight),
1605             sizeof(heights), &heights);
1606     if (bytesRead == sizeof(heights)) {
1607         // 'fontSize' is correct because the entire resolved size is set by the constructor.
1608         CGFloat fontSize = CTFontGetSize(this->fCTFont.get());
1609         unsigned upem = CTFontGetUnitsPerEm(this->fCTFont.get());
1610         unsigned maxSaneHeight = upem * 2;
1611         uint16_t xHeight = SkEndian_SwapBE16(heights.sxHeight);
1612         if (xHeight && xHeight < maxSaneHeight) {
1613             metrics->fXHeight = CGToScalar(xHeight * fontSize / upem);
1614         }
1615         uint16_t capHeight = SkEndian_SwapBE16(heights.sCapHeight);
1616         if (capHeight && capHeight < maxSaneHeight) {
1617             metrics->fCapHeight = CGToScalar(capHeight * fontSize / upem);
1618         }
1619     }
1620 }
1621 
CTPathElement(void * info,const CGPathElement * element)1622 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) {
1623     SkPath* skPath = (SkPath*)info;
1624 
1625     // Process the path element
1626     switch (element->type) {
1627         case kCGPathElementMoveToPoint:
1628             skPath->moveTo(element->points[0].x, -element->points[0].y);
1629             break;
1630 
1631         case kCGPathElementAddLineToPoint:
1632             skPath->lineTo(element->points[0].x, -element->points[0].y);
1633             break;
1634 
1635         case kCGPathElementAddQuadCurveToPoint:
1636             skPath->quadTo(element->points[0].x, -element->points[0].y,
1637                            element->points[1].x, -element->points[1].y);
1638             break;
1639 
1640         case kCGPathElementAddCurveToPoint:
1641             skPath->cubicTo(element->points[0].x, -element->points[0].y,
1642                             element->points[1].x, -element->points[1].y,
1643                             element->points[2].x, -element->points[2].y);
1644             break;
1645 
1646         case kCGPathElementCloseSubpath:
1647             skPath->close();
1648             break;
1649 
1650         default:
1651             SkDEBUGFAIL("Unknown path element!");
1652             break;
1653         }
1654 }
1655 
1656 
1657 ///////////////////////////////////////////////////////////////////////////////
1658 
1659 // Returns nullptr on failure
1660 // Call must still manage its ownership of provider
create_from_dataProvider(SkUniqueCFRef<CGDataProviderRef> provider,std::unique_ptr<SkStreamAsset> providedData,int ttcIndex)1661 static sk_sp<SkTypeface> create_from_dataProvider(SkUniqueCFRef<CGDataProviderRef> provider,
1662                                                   std::unique_ptr<SkStreamAsset> providedData,
1663                                                   int ttcIndex) {
1664     if (ttcIndex != 0) {
1665         return nullptr;
1666     }
1667     SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
1668     if (!cg) {
1669         return nullptr;
1670     }
1671     SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg.get(), 0, nullptr, nullptr));
1672     if (!ct) {
1673         return nullptr;
1674     }
1675     return create_from_CTFontRef(std::move(ct), nullptr, std::move(providedData));
1676 }
1677 
1678 // Web fonts added to the CTFont registry do not return their character set.
1679 // Iterate through the font in this case. The existing caller caches the result,
1680 // so the performance impact isn't too bad.
populate_glyph_to_unicode_slow(CTFontRef ctFont,CFIndex glyphCount,SkUnichar * out)1681 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
1682                                            SkUnichar* out) {
1683     sk_bzero(out, glyphCount * sizeof(SkUnichar));
1684     UniChar unichar = 0;
1685     while (glyphCount > 0) {
1686         CGGlyph glyph;
1687         if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
1688             if (out[glyph] == 0) {
1689                 out[glyph] = unichar;
1690                 --glyphCount;
1691             }
1692         }
1693         if (++unichar == 0) {
1694             break;
1695         }
1696     }
1697 }
1698 
1699 static constexpr uint16_t kPlaneSize = 1 << 13;
1700 
get_plane_glyph_map(const uint8_t * bits,CTFontRef ctFont,CFIndex glyphCount,SkUnichar * glyphToUnicode,uint8_t planeIndex)1701 static void get_plane_glyph_map(const uint8_t* bits,
1702                                 CTFontRef ctFont,
1703                                 CFIndex glyphCount,
1704                                 SkUnichar* glyphToUnicode,
1705                                 uint8_t planeIndex) {
1706     SkUnichar planeOrigin = (SkUnichar)planeIndex << 16; // top half of codepoint.
1707     for (uint16_t i = 0; i < kPlaneSize; i++) {
1708         uint8_t mask = bits[i];
1709         if (!mask) {
1710             continue;
1711         }
1712         for (uint8_t j = 0; j < 8; j++) {
1713             if (0 == (mask & ((uint8_t)1 << j))) {
1714                 continue;
1715             }
1716             uint16_t planeOffset = (i << 3) | j;
1717             SkUnichar codepoint = planeOrigin | (SkUnichar)planeOffset;
1718             uint16_t utf16[2] = {planeOffset, 0};
1719             size_t count = 1;
1720             if (planeOrigin != 0) {
1721                 count = SkUTF::ToUTF16(codepoint, utf16);
1722             }
1723             CGGlyph glyphs[2] = {0, 0};
1724             if (CTFontGetGlyphsForCharacters(ctFont, utf16, glyphs, count)) {
1725                 SkASSERT(glyphs[1] == 0);
1726                 SkASSERT(glyphs[0] < glyphCount);
1727                 // CTFontCopyCharacterSet and CTFontGetGlyphsForCharacters seem to add 'support'
1728                 // for characters 0x9, 0xA, and 0xD mapping them to the glyph for character 0x20?
1729                 // Prefer mappings to codepoints at or above 0x20.
1730                 if (glyphToUnicode[glyphs[0]] < 0x20) {
1731                     glyphToUnicode[glyphs[0]] = codepoint;
1732                 }
1733             }
1734         }
1735     }
1736 }
1737 // Construct Glyph to Unicode table.
populate_glyph_to_unicode(CTFontRef ctFont,CFIndex glyphCount,SkUnichar * glyphToUnicode)1738 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
1739                                       SkUnichar* glyphToUnicode) {
1740     sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount);
1741     SkUniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
1742     if (!charSet) {
1743         populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
1744         return;
1745     }
1746 
1747     SkUniqueCFRef<CFDataRef> bitmap(
1748             CFCharacterSetCreateBitmapRepresentation(nullptr, charSet.get()));
1749     if (!bitmap) {
1750         return;
1751     }
1752     CFIndex dataLength = CFDataGetLength(bitmap.get());
1753     if (!dataLength) {
1754         return;
1755     }
1756     SkASSERT(dataLength >= kPlaneSize);
1757     const UInt8* bits = CFDataGetBytePtr(bitmap.get());
1758 
1759     get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, 0);
1760     /*
1761     A CFData object that specifies the bitmap representation of the Unicode
1762     character points the for the new character set. The bitmap representation could
1763     contain all the Unicode character range starting from BMP to Plane 16. The
1764     first 8KiB (8192 bytes) of the data represent the BMP range. The BMP range 8KiB
1765     can be followed by zero to sixteen 8KiB bitmaps, each prepended with the plane
1766     index byte. For example, the bitmap representing the BMP and Plane 2 has the
1767     size of 16385 bytes (8KiB for BMP, 1 byte index, and a 8KiB bitmap for Plane
1768     2). The plane index byte, in this case, contains the integer value two.
1769     */
1770 
1771     if (dataLength <= kPlaneSize) {
1772         return;
1773     }
1774     int extraPlaneCount = (dataLength - kPlaneSize) / (1 + kPlaneSize);
1775     SkASSERT(dataLength == kPlaneSize + extraPlaneCount * (1 + kPlaneSize));
1776     while (extraPlaneCount-- > 0) {
1777         bits += kPlaneSize;
1778         uint8_t planeIndex = *bits++;
1779         SkASSERT(planeIndex >= 1);
1780         SkASSERT(planeIndex <= 16);
1781         get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, planeIndex);
1782     }
1783 }
1784 
1785 /** Assumes src and dst are not nullptr. */
CFStringToSkString(CFStringRef src,SkString * dst)1786 static void CFStringToSkString(CFStringRef src, SkString* dst) {
1787     // Reserve enough room for the worst-case string,
1788     // plus 1 byte for the trailing null.
1789     CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
1790                                                        kCFStringEncodingUTF8) + 1;
1791     dst->resize(length);
1792     CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
1793     // Resize to the actual UTF-8 length used, stripping the null character.
1794     dst->resize(strlen(dst->c_str()));
1795 }
1796 
getGlyphToUnicodeMap(SkUnichar * dstArray) const1797 void SkTypeface_Mac::getGlyphToUnicodeMap(SkUnichar* dstArray) const {
1798     SkUniqueCFRef<CTFontRef> ctFont =
1799             ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr);
1800     CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get());
1801     populate_glyph_to_unicode(ctFont.get(), glyphCount, dstArray);
1802 }
1803 
onGetAdvancedMetrics() const1804 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics() const {
1805 
1806     SkUniqueCFRef<CTFontRef> ctFont =
1807             ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr);
1808 
1809     std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
1810 
1811     {
1812         SkUniqueCFRef<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont.get()));
1813         if (fontName.get()) {
1814             CFStringToSkString(fontName.get(), &info->fPostScriptName);
1815             info->fFontName = info->fPostScriptName;
1816         }
1817     }
1818 
1819     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
1820     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
1821     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
1822     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
1823     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont.get(), nullptr));
1824     if (cgFont) {
1825         SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
1826         if (cgAxes && CFArrayGetCount(cgAxes.get()) > 0) {
1827             info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
1828         }
1829     }
1830 
1831     SkOTTableOS2_V4::Type fsType;
1832     if (sizeof(fsType) == this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG),
1833                                              offsetof(SkOTTableOS2_V4, fsType),
1834                                              sizeof(fsType),
1835                                              &fsType)) {
1836         SkOTUtils::SetAdvancedTypefaceFlags(fsType, info.get());
1837     }
1838 
1839     // If it's not a truetype font, mark it as 'other'. Assume that TrueType
1840     // fonts always have both glyf and loca tables. At the least, this is what
1841     // sfntly needs to subset the font. CTFontCopyAttribute() does not always
1842     // succeed in determining this directly.
1843     if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
1844         return info;
1845     }
1846 
1847     info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1848     CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont.get());
1849     if (symbolicTraits & kCTFontMonoSpaceTrait) {
1850         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1851     }
1852     if (symbolicTraits & kCTFontItalicTrait) {
1853         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1854     }
1855     CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
1856     if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
1857         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1858     } else if (stylisticClass & kCTFontScriptsClass) {
1859         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1860     }
1861     info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont.get());
1862     info->fAscent = (int16_t) CTFontGetAscent(ctFont.get());
1863     info->fDescent = (int16_t) CTFontGetDescent(ctFont.get());
1864     info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont.get());
1865     CGRect bbox = CTFontGetBoundingBox(ctFont.get());
1866 
1867     SkRect r;
1868     r.setLTRB(CGToScalar(CGRectGetMinX_inline(bbox)),   // Left
1869               CGToScalar(CGRectGetMaxY_inline(bbox)),   // Top
1870               CGToScalar(CGRectGetMaxX_inline(bbox)),   // Right
1871               CGToScalar(CGRectGetMinY_inline(bbox)));  // Bottom
1872 
1873     r.roundOut(&(info->fBBox));
1874 
1875     // Figure out a good guess for StemV - Min width of i, I, !, 1.
1876     // This probably isn't very good with an italic font.
1877     int16_t min_width = SHRT_MAX;
1878     info->fStemV = 0;
1879     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
1880     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
1881     CGGlyph glyphs[count];
1882     CGRect boundingRects[count];
1883     if (CTFontGetGlyphsForCharacters(ctFont.get(), stem_chars, glyphs, count)) {
1884         CTFontGetBoundingRectsForGlyphs(ctFont.get(), kCTFontOrientationHorizontal,
1885                                         glyphs, boundingRects, count);
1886         for (size_t i = 0; i < count; i++) {
1887             int16_t width = (int16_t) boundingRects[i].size.width;
1888             if (width > 0 && width < min_width) {
1889                 min_width = width;
1890                 info->fStemV = min_width;
1891             }
1892         }
1893     }
1894     return info;
1895 }
1896 
1897 ///////////////////////////////////////////////////////////////////////////////
1898 
get_font_type_tag(CTFontRef ctFont)1899 static SK_SFNT_ULONG get_font_type_tag(CTFontRef ctFont) {
1900     SkUniqueCFRef<CFNumberRef> fontFormatRef(
1901             static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
1902     if (!fontFormatRef) {
1903         return 0;
1904     }
1905 
1906     SInt32 fontFormatValue;
1907     if (!CFNumberGetValue(fontFormatRef.get(), kCFNumberSInt32Type, &fontFormatValue)) {
1908         return 0;
1909     }
1910 
1911     switch (fontFormatValue) {
1912         case kCTFontFormatOpenTypePostScript:
1913             return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1914         case kCTFontFormatOpenTypeTrueType:
1915             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
1916         case kCTFontFormatTrueType:
1917             return SkSFNTHeader::fontType_MacTrueType::TAG;
1918         case kCTFontFormatPostScript:
1919             return SkSFNTHeader::fontType_PostScript::TAG;
1920         case kCTFontFormatBitmap:
1921             return SkSFNTHeader::fontType_MacTrueType::TAG;
1922         case kCTFontFormatUnrecognized:
1923         default:
1924             return 0;
1925     }
1926 }
1927 
onOpenStream(int * ttcIndex) const1928 std::unique_ptr<SkStreamAsset> SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
1929     *ttcIndex = 0;
1930 
1931     fInitStream([this]{
1932     if (fStream) {
1933         return;
1934     }
1935 
1936     SK_SFNT_ULONG fontType = get_font_type_tag(fFontRef.get());
1937 
1938     // get table tags
1939     int numTables = this->countTables();
1940     SkTDArray<SkFontTableTag> tableTags;
1941     tableTags.setCount(numTables);
1942     this->getTableTags(tableTags.begin());
1943 
1944     // CT seems to be unreliable in being able to obtain the type,
1945     // even if all we want is the first four bytes of the font resource.
1946     // Just the presence of the FontForge 'FFTM' table seems to throw it off.
1947     if (fontType == 0) {
1948         fontType = SkSFNTHeader::fontType_WindowsTrueType::TAG;
1949 
1950         // see https://skbug.com/7630#c7
1951         bool couldBeCFF = false;
1952         constexpr SkFontTableTag CFFTag = SkSetFourByteTag('C', 'F', 'F', ' ');
1953         constexpr SkFontTableTag CFF2Tag = SkSetFourByteTag('C', 'F', 'F', '2');
1954         for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
1955             if (CFFTag == tableTags[tableIndex] || CFF2Tag == tableTags[tableIndex]) {
1956                 couldBeCFF = true;
1957             }
1958         }
1959         if (couldBeCFF) {
1960             fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1961         }
1962     }
1963 
1964     // Sometimes CoreGraphics incorrectly thinks a font is kCTFontFormatPostScript.
1965     // It is exceedingly unlikely that this is the case, so double check
1966     // (see https://crbug.com/809763 ).
1967     if (fontType == SkSFNTHeader::fontType_PostScript::TAG) {
1968         // see if there are any required 'typ1' tables (see Adobe Technical Note #5180)
1969         bool couldBeTyp1 = false;
1970         constexpr SkFontTableTag TYPE1Tag = SkSetFourByteTag('T', 'Y', 'P', '1');
1971         constexpr SkFontTableTag CIDTag = SkSetFourByteTag('C', 'I', 'D', ' ');
1972         for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
1973             if (TYPE1Tag == tableTags[tableIndex] || CIDTag == tableTags[tableIndex]) {
1974                 couldBeTyp1 = true;
1975             }
1976         }
1977         if (!couldBeTyp1) {
1978             fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1979         }
1980     }
1981 
1982     // get the table sizes and accumulate the total size of the font
1983     SkTDArray<size_t> tableSizes;
1984     size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
1985     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
1986         size_t tableSize = this->getTableSize(tableTags[tableIndex]);
1987         totalSize += (tableSize + 3) & ~3;
1988         *tableSizes.append() = tableSize;
1989     }
1990 
1991     // reserve memory for stream, and zero it (tables must be zero padded)
1992     fStream.reset(new SkMemoryStream(totalSize));
1993     char* dataStart = (char*)fStream->getMemoryBase();
1994     sk_bzero(dataStart, totalSize);
1995     char* dataPtr = dataStart;
1996 
1997     // compute font header entries
1998     uint16_t entrySelector = 0;
1999     uint16_t searchRange = 1;
2000     while (searchRange < numTables >> 1) {
2001         entrySelector++;
2002         searchRange <<= 1;
2003     }
2004     searchRange <<= 4;
2005     uint16_t rangeShift = (numTables << 4) - searchRange;
2006 
2007     // write font header
2008     SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
2009     header->fontType = fontType;
2010     header->numTables = SkEndian_SwapBE16(numTables);
2011     header->searchRange = SkEndian_SwapBE16(searchRange);
2012     header->entrySelector = SkEndian_SwapBE16(entrySelector);
2013     header->rangeShift = SkEndian_SwapBE16(rangeShift);
2014     dataPtr += sizeof(SkSFNTHeader);
2015 
2016     // write tables
2017     SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
2018     dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
2019     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
2020         size_t tableSize = tableSizes[tableIndex];
2021         this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
2022         entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
2023         entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
2024                                                                          tableSize));
2025         entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
2026         entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
2027 
2028         dataPtr += (tableSize + 3) & ~3;
2029         ++entry;
2030     }
2031     });
2032     return fStream->duplicate();
2033 }
2034 
2035 struct NonDefaultAxesContext {
2036     SkFixed* axisValue;
2037     CFArrayRef cgAxes;
2038 };
set_non_default_axes(CFTypeRef key,CFTypeRef value,void * context)2039 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
2040     NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
2041 
2042     if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) {
2043         return;
2044     }
2045 
2046     // The key is a CFString which is a string from the 'name' table.
2047     // Search the cgAxes for an axis with this name, and use its index to store the value.
2048     CFIndex keyIndex = -1;
2049     CFStringRef keyString = static_cast<CFStringRef>(key);
2050     for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
2051         CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
2052         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
2053             continue;
2054         }
2055 
2056         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
2057         CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
2058         if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
2059             continue;
2060         }
2061         CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
2062         if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
2063             keyIndex = i;
2064             break;
2065         }
2066     }
2067     if (keyIndex == -1) {
2068         return;
2069     }
2070 
2071     CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
2072     double valueDouble;
2073     if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
2074         valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble)
2075     {
2076         return;
2077     }
2078     self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
2079 }
get_variations(CTFontRef ctFont,CFIndex * cgAxisCount,SkAutoSTMalloc<4,SkFixed> * axisValues)2080 static bool get_variations(CTFontRef ctFont, CFIndex* cgAxisCount,
2081                            SkAutoSTMalloc<4, SkFixed>* axisValues)
2082 {
2083     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
2084     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
2085     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
2086     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
2087     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
2088     if (!cgFont) {
2089         return false;
2090     }
2091 
2092     SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
2093     // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict).
2094     if (!cgVariations) {
2095         return false;
2096     }
2097 
2098     SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
2099     if (!cgAxes) {
2100         return false;
2101     }
2102     *cgAxisCount = CFArrayGetCount(cgAxes.get());
2103     axisValues->reset(*cgAxisCount);
2104 
2105     // Set all of the axes to their default values.
2106     // Fail if any default value cannot be determined.
2107     for (CFIndex i = 0; i < *cgAxisCount; ++i) {
2108         CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes.get(), i);
2109         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
2110             return false;
2111         }
2112 
2113         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
2114         CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
2115                                                           kCGFontVariationAxisDefaultValue);
2116         if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
2117             return false;
2118         }
2119         CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
2120         double axisDefaultValueDouble;
2121         if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble))
2122         {
2123             return false;
2124         }
2125         if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
2126                                      SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
2127         {
2128             return false;
2129         }
2130         (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
2131     }
2132 
2133     // Override the default values with the given font's stated axis values.
2134     NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
2135     CFDictionaryApplyFunction(cgVariations.get(), set_non_default_axes, &c);
2136 
2137     return true;
2138 }
onMakeFontData() const2139 std::unique_ptr<SkFontData> SkTypeface_Mac::onMakeFontData() const {
2140     int index;
2141     std::unique_ptr<SkStreamAsset> stream(this->onOpenStream(&index));
2142 
2143     CFIndex cgAxisCount;
2144     SkAutoSTMalloc<4, SkFixed> axisValues;
2145     if (get_variations(fFontRef.get(), &cgAxisCount, &axisValues)) {
2146         return skstd::make_unique<SkFontData>(std::move(stream), index,
2147                                               axisValues.get(), cgAxisCount);
2148     }
2149     return skstd::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
2150 }
2151 
2152 /** Creates a CT variation dictionary {tag, value} from a CG variation dictionary {name, value}. */
ct_variation_from_cg_variation(CFDictionaryRef cgVariations,CFArrayRef ctAxes)2153 static SkUniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
2154                                                                      CFArrayRef ctAxes) {
2155 
2156     SkUniqueCFRef<CFMutableDictionaryRef> ctVariations(
2157             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2158                                       &kCFTypeDictionaryKeyCallBacks,
2159                                       &kCFTypeDictionaryValueCallBacks));
2160 
2161     CFIndex axisCount = CFArrayGetCount(ctAxes);
2162     for (CFIndex i = 0; i < axisCount; ++i) {
2163         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes, i);
2164         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2165             return nullptr;
2166         }
2167         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2168 
2169         // The assumption is that values produced by kCTFontVariationAxisNameKey and
2170         // kCGFontVariationAxisName will always be equal.
2171         CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
2172         if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2173             return nullptr;
2174         }
2175 
2176         CFTypeRef axisValue = CFDictionaryGetValue(cgVariations, axisName);
2177         if (!axisValue || CFGetTypeID(axisValue) != CFNumberGetTypeID()) {
2178             return nullptr;
2179         }
2180 
2181         CFTypeRef axisTag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2182         if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
2183             return nullptr;
2184         }
2185 
2186         CFDictionaryAddValue(ctVariations.get(), axisTag, axisValue);
2187     }
2188     return ctVariations;
2189 }
2190 
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const2191 int SkTypeface_Mac::onGetVariationDesignPosition(
2192         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
2193 {
2194     // The CGFont variation data does not contain the tag.
2195 
2196     // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
2197     // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
2198     SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
2199     if (!ctAxes) {
2200         return -1;
2201     }
2202     CFIndex axisCount = CFArrayGetCount(ctAxes.get());
2203     if (!coordinates || coordinateCount < axisCount) {
2204         return axisCount;
2205     }
2206 
2207     // This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
2208     // When this happens, try converting the CG variation to a CT variation.
2209     // On 10.12 and later, this only returns non-default variations.
2210     SkUniqueCFRef<CFDictionaryRef> ctVariations(CTFontCopyVariation(fFontRef.get()));
2211     if (!ctVariations) {
2212         // When 10.11 and earlier are no longer supported, the following code can be replaced with
2213         // return -1 and ct_variation_from_cg_variation can be removed.
2214         SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
2215         if (!cgFont) {
2216             return -1;
2217         }
2218         SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
2219         if (!cgVariations) {
2220             return -1;
2221         }
2222         ctVariations = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
2223         if (!ctVariations) {
2224             return -1;
2225         }
2226     }
2227 
2228     for (int i = 0; i < axisCount; ++i) {
2229         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
2230         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2231             return -1;
2232         }
2233         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2234 
2235         CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2236         if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
2237             return -1;
2238         }
2239         CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
2240         int64_t tagLong;
2241         if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
2242             return -1;
2243         }
2244         coordinates[i].axis = tagLong;
2245 
2246         CGFloat variationCGFloat;
2247         CFTypeRef variationValue = CFDictionaryGetValue(ctVariations.get(), tagNumber);
2248         if (variationValue) {
2249             if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
2250                 return -1;
2251             }
2252             CFNumberRef variationNumber = static_cast<CFNumberRef>(variationValue);
2253             if (!CFNumberGetValue(variationNumber, kCFNumberCGFloatType, &variationCGFloat)) {
2254                 return -1;
2255             }
2256         } else {
2257             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
2258             if (!def || CFGetTypeID(def) != CFNumberGetTypeID()) {
2259                 return -1;
2260             }
2261             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
2262             if (!CFNumberGetValue(defNumber, kCFNumberCGFloatType, &variationCGFloat)) {
2263                 return -1;
2264             }
2265         }
2266         coordinates[i].value = CGToScalar(variationCGFloat);
2267 
2268     }
2269     return axisCount;
2270 }
2271 
2272 ///////////////////////////////////////////////////////////////////////////////
2273 ///////////////////////////////////////////////////////////////////////////////
2274 
onGetUPEM() const2275 int SkTypeface_Mac::onGetUPEM() const {
2276     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
2277     return CGFontGetUnitsPerEm(cgFont.get());
2278 }
2279 
onCreateFamilyNameIterator() const2280 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
2281     sk_sp<SkTypeface::LocalizedStrings> nameIter =
2282             SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
2283     if (!nameIter) {
2284         CFStringRef cfLanguageRaw;
2285         SkUniqueCFRef<CFStringRef> cfFamilyName(
2286                 CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
2287         SkUniqueCFRef<CFStringRef> cfLanguage(cfLanguageRaw);
2288 
2289         SkString skLanguage;
2290         SkString skFamilyName;
2291         if (cfLanguage) {
2292             CFStringToSkString(cfLanguage.get(), &skLanguage);
2293         } else {
2294             skLanguage = "und"; //undetermined
2295         }
2296         if (cfFamilyName) {
2297             CFStringToSkString(cfFamilyName.get(), &skFamilyName);
2298         }
2299 
2300         nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(skFamilyName, skLanguage);
2301     }
2302     return nameIter.release();
2303 }
2304 
onGetTableTags(SkFontTableTag tags[]) const2305 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
2306     SkUniqueCFRef<CFArrayRef> cfArray(
2307             CTFontCopyAvailableTables(fFontRef.get(), kCTFontTableOptionNoOptions));
2308     if (!cfArray) {
2309         return 0;
2310     }
2311     int count = SkToInt(CFArrayGetCount(cfArray.get()));
2312     if (tags) {
2313         for (int i = 0; i < count; ++i) {
2314             uintptr_t fontTag = reinterpret_cast<uintptr_t>(
2315                 CFArrayGetValueAtIndex(cfArray.get(), i));
2316             tags[i] = static_cast<SkFontTableTag>(fontTag);
2317         }
2318     }
2319     return count;
2320 }
2321 
2322 // If, as is the case with web fonts, the CTFont data isn't available,
2323 // the CGFont data may work. While the CGFont may always provide the
2324 // right result, leave the CTFont code path to minimize disruption.
copy_table_from_font(CTFontRef ctFont,SkFontTableTag tag)2325 static SkUniqueCFRef<CFDataRef> copy_table_from_font(CTFontRef ctFont, SkFontTableTag tag) {
2326     SkUniqueCFRef<CFDataRef> data(CTFontCopyTable(ctFont, (CTFontTableTag) tag,
2327                                                   kCTFontTableOptionNoOptions));
2328     if (!data) {
2329         SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
2330         data.reset(CGFontCopyTableForTag(cgFont.get(), tag));
2331     }
2332     return data;
2333 }
2334 
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * dstData) const2335 size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
2336                                       size_t length, void* dstData) const {
2337     SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
2338     if (!srcData) {
2339         return 0;
2340     }
2341 
2342     size_t srcSize = CFDataGetLength(srcData.get());
2343     if (offset >= srcSize) {
2344         return 0;
2345     }
2346     if (length > srcSize - offset) {
2347         length = srcSize - offset;
2348     }
2349     if (dstData) {
2350         memcpy(dstData, CFDataGetBytePtr(srcData.get()) + offset, length);
2351     }
2352     return length;
2353 }
2354 
onCopyTableData(SkFontTableTag tag) const2355 sk_sp<SkData> SkTypeface_Mac::onCopyTableData(SkFontTableTag tag) const {
2356     SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
2357     if (!srcData) {
2358         return nullptr;
2359     }
2360     const UInt8* data = CFDataGetBytePtr(srcData.get());
2361     CFIndex length = CFDataGetLength(srcData.get());
2362     return SkData::MakeWithProc(data, length,
2363                                 [](const void*, void* ctx) {
2364                                     CFRelease((CFDataRef)ctx);
2365                                 }, (void*)srcData.release());
2366 }
2367 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const2368 SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkScalerContextEffects& effects,
2369                                                        const SkDescriptor* desc) const {
2370     return new SkScalerContext_Mac(sk_ref_sp(const_cast<SkTypeface_Mac*>(this)), effects, desc);
2371 }
2372 
onFilterRec(SkScalerContextRec * rec) const2373 void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
2374     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
2375         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
2376     {
2377         rec->fMaskFormat = SkMask::kA8_Format;
2378         // Render the glyphs as close as possible to what was requested.
2379         // The above turns off subpixel rendering, but the user requested it.
2380         // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
2381         // See comments below for more details.
2382         rec->setHinting(SkFontHinting::kNormal);
2383     }
2384 
2385     unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag  |
2386                                   SkScalerContext::kLCD_BGROrder_Flag |
2387                                   SkScalerContext::kLCD_Vertical_Flag;
2388 
2389     rec->fFlags &= ~flagsWeDontSupport;
2390 
2391     const SmoothBehavior smoothBehavior = smooth_behavior();
2392 
2393     // Only two levels of hinting are supported.
2394     // kNo_Hinting means avoid CoreGraphics outline dilation (smoothing).
2395     // kNormal_Hinting means CoreGraphics outline dilation (smoothing) is allowed.
2396     if (rec->getHinting() != SkFontHinting::kNone) {
2397         rec->setHinting(SkFontHinting::kNormal);
2398     }
2399     // If smoothing has no effect, don't request it.
2400     if (smoothBehavior == SmoothBehavior::none) {
2401         rec->setHinting(SkFontHinting::kNone);
2402     }
2403 
2404     // FIXME: lcd smoothed un-hinted rasterization unsupported.
2405     // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
2406     // There is no current means to honor a request for unhinted lcd,
2407     // so arbitrarilly ignore the hinting request and honor lcd.
2408 
2409     // Hinting and smoothing should be orthogonal, but currently they are not.
2410     // CoreGraphics has no API to influence hinting. However, its lcd smoothed
2411     // output is drawn from auto-dilated outlines (the amount of which is
2412     // determined by AppleFontSmoothing). Its regular anti-aliased output is
2413     // drawn from un-dilated outlines.
2414 
2415     // The behavior of Skia is as follows:
2416     // [AA][no-hint]: generate AA using CoreGraphic's AA output.
2417     // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
2418     // channel. This matches [LCD][yes-hint] in weight.
2419     // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
2420     // Currenly side with LCD, effectively ignoring the hinting setting.
2421     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
2422     if (rec->fMaskFormat == SkMask::kLCD16_Format) {
2423         if (smoothBehavior == SmoothBehavior::subpixel) {
2424             //CoreGraphics creates 555 masks for smoothed text anyway.
2425             rec->fMaskFormat = SkMask::kLCD16_Format;
2426             rec->setHinting(SkFontHinting::kNormal);
2427         } else {
2428             rec->fMaskFormat = SkMask::kA8_Format;
2429             if (smoothBehavior != SmoothBehavior::none) {
2430                 rec->setHinting(SkFontHinting::kNormal);
2431             }
2432         }
2433     }
2434 
2435     // CoreText provides no information as to whether a glyph will be color or not.
2436     // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
2437     // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
2438     if (fHasColorGlyphs) {
2439         rec->fMaskFormat = SkMask::kARGB32_Format;
2440     }
2441 
2442     // Smoothing will be used if the format is either LCD or if there is hinting.
2443     // In those cases, we need to choose the proper dilation mask based on the color.
2444     if (rec->fMaskFormat == SkMask::kLCD16_Format ||
2445         (rec->fMaskFormat == SkMask::kA8_Format && rec->getHinting() != SkFontHinting::kNone)) {
2446         SkColor color = rec->getLuminanceColor();
2447         int r = SkColorGetR(color);
2448         int g = SkColorGetG(color);
2449         int b = SkColorGetB(color);
2450         // Choose whether to draw using a light-on-dark mask based on observed
2451         // color/luminance thresholds that CoreText uses.
2452         if (r >= 85 && g >= 85 && b >= 85 && r + g + b >= 2 * 255) {
2453             rec->fFlags |= SkScalerContext::kLightOnDark_Flag;
2454         }
2455     }
2456 
2457     // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
2458     // All other masks can use regular gamma.
2459     if (SkMask::kA8_Format == rec->fMaskFormat && SkFontHinting::kNone == rec->getHinting()) {
2460 #ifndef SK_GAMMA_APPLY_TO_A8
2461         // SRGBTODO: Is this correct? Do we want contrast boost?
2462         rec->ignorePreBlend();
2463 #endif
2464     } else {
2465 #ifndef SK_IGNORE_MAC_BLENDING_MATCH_FIX
2466         SkColor color = rec->getLuminanceColor();
2467         if (smoothBehavior == SmoothBehavior::some) {
2468             // CoreGraphics smoothed text without subpixel coverage blitting goes from a gamma of
2469             // 2.0 for black foreground to a gamma of 1.0 for white foreground. Emulate this
2470             // through the mask gamma by reducing the color values to 1/2.
2471             color = SkColorSetRGB(SkColorGetR(color) * 1/2,
2472                                   SkColorGetG(color) * 1/2,
2473                                   SkColorGetB(color) * 1/2);
2474         } else if (smoothBehavior == SmoothBehavior::subpixel) {
2475             // CoreGraphics smoothed text with subpixel coverage blitting goes from a gamma of
2476             // 2.0 for black foreground to a gamma of ~1.4? for white foreground. Emulate this
2477             // through the mask gamma by reducing the color values to 3/4.
2478             color = SkColorSetRGB(SkColorGetR(color) * 3/4,
2479                                   SkColorGetG(color) * 3/4,
2480                                   SkColorGetB(color) * 3/4);
2481         }
2482         rec->setLuminanceColor(color);
2483 #endif
2484         // CoreGraphics dialates smoothed text to provide contrast.
2485         rec->setContrast(0);
2486     }
2487 }
2488 
2489 /** Takes ownership of the CFStringRef. */
get_str(CFStringRef ref,SkString * str)2490 static const char* get_str(CFStringRef ref, SkString* str) {
2491     if (nullptr == ref) {
2492         return nullptr;
2493     }
2494     CFStringToSkString(ref, str);
2495     CFRelease(ref);
2496     return str->c_str();
2497 }
2498 
onGetFamilyName(SkString * familyName) const2499 void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
2500     get_str(CTFontCopyFamilyName(fFontRef.get()), familyName);
2501 }
2502 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocalStream) const2503 void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
2504                                          bool* isLocalStream) const {
2505     SkString tmpStr;
2506 
2507     desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef.get()), &tmpStr));
2508     desc->setFullName(get_str(CTFontCopyFullName(fFontRef.get()), &tmpStr));
2509     desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef.get()), &tmpStr));
2510     desc->setStyle(this->fontStyle());
2511     *isLocalStream = fIsFromStream;
2512 }
2513 
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const2514 void SkTypeface_Mac::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
2515     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
2516     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
2517     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
2518 
2519     SkAutoSTMalloc<1024, UniChar> charStorage;
2520     const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
2521     int srcCount;
2522     const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(uni);
2523     UniChar* utf16 = charStorage.reset(2 * count);
2524     src = utf16;
2525     for (int i = 0; i < count; ++i) {
2526         utf16 += SkUTF::ToUTF16(utf32[i], utf16);
2527     }
2528     srcCount = SkToInt(utf16 - src);
2529 
2530     // If there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
2531     SkAutoSTMalloc<1024, uint16_t> glyphStorage;
2532     uint16_t* macGlyphs = glyphs;
2533     if (srcCount > count) {
2534         macGlyphs = glyphStorage.reset(srcCount);
2535     }
2536 
2537     CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount);
2538 
2539     // If there were any non-bmp, then copy and compact.
2540     // If all are bmp, 'glyphs' already contains the compact glyphs.
2541     // If some are non-bmp, copy and compact into 'glyphs'.
2542     if (srcCount > count) {
2543         SkASSERT(glyphs != macGlyphs);
2544         int extra = 0;
2545         for (int i = 0; i < count; ++i) {
2546             glyphs[i] = macGlyphs[i + extra];
2547             if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
2548                 ++extra;
2549             }
2550         }
2551     } else {
2552         SkASSERT(glyphs == macGlyphs);
2553     }
2554 }
2555 
onCountGlyphs() const2556 int SkTypeface_Mac::onCountGlyphs() const {
2557     return SkToInt(CTFontGetGlyphCount(fFontRef.get()));
2558 }
2559 
2560 ///////////////////////////////////////////////////////////////////////////////
2561 ///////////////////////////////////////////////////////////////////////////////
2562 
find_desc_str(CTFontDescriptorRef desc,CFStringRef name,SkString * value)2563 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
2564     SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
2565     if (!ref) {
2566         return false;
2567     }
2568     CFStringToSkString(ref.get(), value);
2569     return true;
2570 }
2571 
2572 #include "include/core/SkFontMgr.h"
2573 
sqr(int value)2574 static inline int sqr(int value) {
2575     SkASSERT(SkAbs32(value) < 0x7FFF);  // check for overflow
2576     return value * value;
2577 }
2578 
2579 // We normalize each axis (weight, width, italic) to be base-900
compute_metric(const SkFontStyle & a,const SkFontStyle & b)2580 static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
2581     return sqr(a.weight() - b.weight()) +
2582            sqr((a.width() - b.width()) * 100) +
2583            sqr((a.slant() != b.slant()) * 900);
2584 }
2585 
2586 class SkFontStyleSet_Mac : public SkFontStyleSet {
2587 public:
SkFontStyleSet_Mac(CTFontDescriptorRef desc)2588     SkFontStyleSet_Mac(CTFontDescriptorRef desc)
2589         : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr))
2590         , fCount(0)
2591     {
2592         if (!fArray) {
2593             fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
2594         }
2595         fCount = SkToInt(CFArrayGetCount(fArray.get()));
2596     }
2597 
count()2598     int count() override {
2599         return fCount;
2600     }
2601 
getStyle(int index,SkFontStyle * style,SkString * name)2602     void getStyle(int index, SkFontStyle* style, SkString* name) override {
2603         SkASSERT((unsigned)index < (unsigned)fCount);
2604         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
2605         if (style) {
2606             *style = fontstyle_from_descriptor(desc, false);
2607         }
2608         if (name) {
2609             if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
2610                 name->reset();
2611             }
2612         }
2613     }
2614 
createTypeface(int index)2615     SkTypeface* createTypeface(int index) override {
2616         SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
2617         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
2618 
2619         return create_from_desc(desc).release();
2620     }
2621 
matchStyle(const SkFontStyle & pattern)2622     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
2623         if (0 == fCount) {
2624             return nullptr;
2625         }
2626         return create_from_desc(findMatchingDesc(pattern)).release();
2627     }
2628 
2629 private:
2630     SkUniqueCFRef<CFArrayRef> fArray;
2631     int fCount;
2632 
findMatchingDesc(const SkFontStyle & pattern) const2633     CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
2634         int bestMetric = SK_MaxS32;
2635         CTFontDescriptorRef bestDesc = nullptr;
2636 
2637         for (int i = 0; i < fCount; ++i) {
2638             CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
2639             int metric = compute_metric(pattern, fontstyle_from_descriptor(desc, false));
2640             if (0 == metric) {
2641                 return desc;
2642             }
2643             if (metric < bestMetric) {
2644                 bestMetric = metric;
2645                 bestDesc = desc;
2646             }
2647         }
2648         SkASSERT(bestDesc);
2649         return bestDesc;
2650     }
2651 };
2652 
2653 class SkFontMgr_Mac : public SkFontMgr {
2654     SkUniqueCFRef<CFArrayRef> fNames;
2655     int fCount;
2656 
getFamilyNameAt(int index) const2657     CFStringRef getFamilyNameAt(int index) const {
2658         SkASSERT((unsigned)index < (unsigned)fCount);
2659         return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
2660     }
2661 
CreateSet(CFStringRef cfFamilyName)2662     static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
2663         SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
2664                  CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2665                                            &kCFTypeDictionaryKeyCallBacks,
2666                                            &kCFTypeDictionaryValueCallBacks));
2667 
2668         CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
2669 
2670         SkUniqueCFRef<CTFontDescriptorRef> desc(
2671                 CTFontDescriptorCreateWithAttributes(cfAttr.get()));
2672         return new SkFontStyleSet_Mac(desc.get());
2673     }
2674 
2675     /** CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
2676      *  provide a wrapper here that will return an empty array if need be.
2677      */
CopyAvailableFontFamilyNames()2678     static SkUniqueCFRef<CFArrayRef> CopyAvailableFontFamilyNames() {
2679 #ifdef SK_BUILD_FOR_IOS
2680         return SkUniqueCFRef<CFArrayRef>(CFArrayCreate(nullptr, nullptr, 0, nullptr));
2681 #else
2682         return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
2683 #endif
2684     }
2685 
2686 public:
SkFontMgr_Mac()2687     SkFontMgr_Mac()
2688         : fNames(CopyAvailableFontFamilyNames())
2689         , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0) {}
2690 
2691 protected:
onCountFamilies() const2692     int onCountFamilies() const override {
2693         return fCount;
2694     }
2695 
onGetFamilyName(int index,SkString * familyName) const2696     void onGetFamilyName(int index, SkString* familyName) const override {
2697         if ((unsigned)index < (unsigned)fCount) {
2698             CFStringToSkString(this->getFamilyNameAt(index), familyName);
2699         } else {
2700             familyName->reset();
2701         }
2702     }
2703 
onCreateStyleSet(int index) const2704     SkFontStyleSet* onCreateStyleSet(int index) const override {
2705         if ((unsigned)index >= (unsigned)fCount) {
2706             return nullptr;
2707         }
2708         return CreateSet(this->getFamilyNameAt(index));
2709     }
2710 
onMatchFamily(const char familyName[]) const2711     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
2712         if (!familyName) {
2713             return nullptr;
2714         }
2715         SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
2716         return CreateSet(cfName.get());
2717     }
2718 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const2719     SkTypeface* onMatchFamilyStyle(const char familyName[],
2720                                    const SkFontStyle& style) const override {
2721         SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
2722         return create_from_desc(desc.get()).release();
2723     }
2724 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const2725     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
2726                                             const SkFontStyle& style,
2727                                             const char* bcp47[], int bcp47Count,
2728                                             SkUnichar character) const override {
2729         SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
2730         SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
2731 
2732         // kCFStringEncodingUTF32 is BE unless there is a BOM.
2733         // Since there is no machine endian option, explicitly state machine endian.
2734 #ifdef SK_CPU_LENDIAN
2735         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
2736 #else
2737         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
2738 #endif
2739         SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
2740                 kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
2741                 encoding, false));
2742         CFRange range = CFRangeMake(0, CFStringGetLength(string.get()));  // in UniChar units.
2743         SkUniqueCFRef<CTFontRef> fallbackFont(
2744                 CTFontCreateForString(familyFont.get(), string.get(), range));
2745         return create_from_CTFontRef(std::move(fallbackFont), nullptr, nullptr).release();
2746     }
2747 
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle &) const2748     SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
2749                                  const SkFontStyle&) const override {
2750         return nullptr;
2751     }
2752 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const2753     sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
2754         SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromData(data));
2755         if (!pr) {
2756             return nullptr;
2757         }
2758         return create_from_dataProvider(std::move(pr), SkMemoryStream::Make(std::move(data)),
2759                                         ttcIndex);
2760     }
2761 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const2762     sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
2763                                             int ttcIndex) const override {
2764         SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream->duplicate()));
2765         if (!pr) {
2766             return nullptr;
2767         }
2768         return create_from_dataProvider(std::move(pr), std::move(stream), ttcIndex);
2769     }
2770 
2771     /** Creates a dictionary suitable for setting the axes on a CGFont. */
copy_axes(CGFontRef cg,const SkFontArguments & args)2772     static SkUniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, const SkFontArguments& args) {
2773         // The CGFont variation data is keyed by name, but lacks the tag.
2774         // The CTFont variation data is keyed by tag, and also has the name.
2775         // We would like to work with CTFont variations, but creating a CTFont font with
2776         // CTFont variation dictionary runs into bugs. So use the CTFont variation data
2777         // to match names to tags to create the appropriate CGFont.
2778         SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr));
2779         // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
2780         // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
2781         SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct.get()));
2782         if (!ctAxes) {
2783             return nullptr;
2784         }
2785         CFIndex axisCount = CFArrayGetCount(ctAxes.get());
2786 
2787         const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
2788 
2789         SkUniqueCFRef<CFMutableDictionaryRef> dict(
2790                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
2791                                           &kCFTypeDictionaryKeyCallBacks,
2792                                           &kCFTypeDictionaryValueCallBacks));
2793 
2794         for (int i = 0; i < axisCount; ++i) {
2795             CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
2796             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2797                 return nullptr;
2798             }
2799             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2800 
2801             // The assumption is that values produced by kCTFontVariationAxisNameKey and
2802             // kCGFontVariationAxisName will always be equal.
2803             // If they are ever not, seach the project history for "get_tag_for_name".
2804             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
2805             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2806                 return nullptr;
2807             }
2808 
2809             CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2810             if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
2811                 return nullptr;
2812             }
2813             CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
2814             int64_t tagLong;
2815             if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
2816                 return nullptr;
2817             }
2818 
2819             // The variation axes can be set to any value, but cg will effectively pin them.
2820             // Pin them here to normalize.
2821             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
2822             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
2823             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
2824             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2825                 !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
2826                 !def || CFGetTypeID(def) != CFNumberGetTypeID())
2827             {
2828                 return nullptr;
2829             }
2830             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2831             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2832             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
2833             double minDouble;
2834             double maxDouble;
2835             double defDouble;
2836             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2837                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
2838                 !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
2839             {
2840                 return nullptr;
2841             }
2842 
2843             double value = defDouble;
2844             // The position may be over specified. If there are multiple values for a given axis,
2845             // use the last one since that's what css-fonts-4 requires.
2846             for (int j = position.coordinateCount; j --> 0;) {
2847                 if (position.coordinates[j].axis == tagLong) {
2848                     value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
2849                                    minDouble, maxDouble);
2850                     break;
2851                 }
2852             }
2853             SkUniqueCFRef<CFNumberRef> valueNumber(
2854                 CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
2855             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
2856         }
2857         return dict;
2858     }
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> s,const SkFontArguments & args) const2859     sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> s,
2860                                            const SkFontArguments& args) const override {
2861         if (args.getCollectionIndex() != 0) {
2862             return nullptr;
2863         }
2864         SkUniqueCFRef<CGDataProviderRef> provider(SkCreateDataProviderFromStream(s->duplicate()));
2865         if (!provider) {
2866             return nullptr;
2867         }
2868         SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
2869         if (!cg) {
2870             return nullptr;
2871         }
2872 
2873         SkUniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), args);
2874         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
2875         // created from a data provider does not appear to have any ownership of the underlying
2876         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
2877         SkUniqueCFRef<CGFontRef> cgVariant;
2878         if (cgVariations) {
2879             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
2880         } else {
2881             cgVariant.reset(cg.release());
2882         }
2883 
2884         SkUniqueCFRef<CTFontRef> ct(
2885                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
2886         if (!ct) {
2887             return nullptr;
2888         }
2889         return create_from_CTFontRef(std::move(ct), std::move(cg), std::move(s));
2890     }
2891 
2892     /** Creates a dictionary suitable for setting the axes on a CGFont. */
copy_axes(CGFontRef cg,SkFontData * fontData)2893     static SkUniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, SkFontData* fontData) {
2894         SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
2895         if (!cgAxes) {
2896             return nullptr;
2897         }
2898 
2899         CFIndex axisCount = CFArrayGetCount(cgAxes.get());
2900         if (0 == axisCount || axisCount != fontData->getAxisCount()) {
2901             return nullptr;
2902         }
2903 
2904         SkUniqueCFRef<CFMutableDictionaryRef> dict(
2905                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
2906                                           &kCFTypeDictionaryKeyCallBacks,
2907                                           &kCFTypeDictionaryValueCallBacks));
2908 
2909         for (int i = 0; i < fontData->getAxisCount(); ++i) {
2910             CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes.get(), i);
2911             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2912                 return nullptr;
2913             }
2914             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2915 
2916             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName);
2917             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2918                 return nullptr;
2919             }
2920 
2921             // The variation axes can be set to any value, but cg will effectively pin them.
2922             // Pin them here to normalize.
2923             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue);
2924             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue);
2925             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2926                 !max || CFGetTypeID(max) != CFNumberGetTypeID())
2927             {
2928                 return nullptr;
2929             }
2930             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2931             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2932             double minDouble;
2933             double maxDouble;
2934             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2935                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
2936             {
2937                 return nullptr;
2938             }
2939             double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
2940             SkUniqueCFRef<CFNumberRef> valueNumber(
2941                     CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
2942             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
2943         }
2944         return dict;
2945     }
onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const2946     sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
2947         if (fontData->getIndex() != 0) {
2948             return nullptr;
2949         }
2950         SkUniqueCFRef<CGDataProviderRef> provider(
2951                 SkCreateDataProviderFromStream(fontData->getStream()->duplicate()));
2952         if (!provider) {
2953             return nullptr;
2954         }
2955         SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
2956         if (!cg) {
2957             return nullptr;
2958         }
2959 
2960         SkUniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), fontData.get());
2961         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
2962         // created from a data provider does not appear to have any ownership of the underlying
2963         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
2964         SkUniqueCFRef<CGFontRef> cgVariant;
2965         if (cgVariations) {
2966             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
2967         } else {
2968             cgVariant.reset(cg.release());
2969         }
2970 
2971         SkUniqueCFRef<CTFontRef> ct(
2972                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
2973         if (!ct) {
2974             return nullptr;
2975         }
2976         return create_from_CTFontRef(std::move(ct), std::move(cg), fontData->detachStream());
2977     }
2978 
onMakeFromFile(const char path[],int ttcIndex) const2979     sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
2980         SkUniqueCFRef<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
2981         if (!pr) {
2982             return nullptr;
2983         }
2984         return create_from_dataProvider(std::move(pr), SkFILEStream::Make(path), ttcIndex);
2985     }
2986 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const2987     sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
2988         if (familyName) {
2989             familyName = map_css_names(familyName);
2990         }
2991 
2992         sk_sp<SkTypeface> face = create_from_name(familyName, style);
2993         if (face) {
2994             return face;
2995         }
2996 
2997         static SkTypeface* gDefaultFace;
2998         static SkOnce lookupDefault;
2999         static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
3000         lookupDefault([]{
3001             gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release();
3002         });
3003         return sk_ref_sp(gDefaultFace);
3004     }
3005 };
3006 
3007 ///////////////////////////////////////////////////////////////////////////////
3008 
Factory()3009 sk_sp<SkFontMgr> SkFontMgr::Factory() { return sk_make_sp<SkFontMgr_Mac>(); }
3010 
3011 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
3012