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;
__anon4eda7c130602null586     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         // force our checks below to happen
1180         fDoAA = !doAA;
1181         fDoLCD = !doLCD;
1182 
1183         CGContextSetTextMatrix(fCG.get(), context.fTransform);
1184     }
1185 
1186     if (glyph.isColor()) {
1187         // Set the current color for layers with palette index 0xffff, or non-colored
1188         // glyphs that may be present in a color font.
1189         //
1190         // Per comment in the Windows code at https://searchfox.org/mozilla-central/source/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp#1069-1074:
1191         // > "getLuminanceColor() is kinda sorta what is wanted here, but not really,
1192         // > it will often be the wrong value because it wan't designed for this.
1193         //
1194         // Empirically, in simple testcases it looks like a decent approximation of what
1195         // we need.
1196         SkColor4f color = SkColor4f::FromColor(context.getRec().getLuminanceColor());
1197         CGContextSetRGBFillColor(fCG.get(), color.fR, color.fG, color.fB, 1.0f);
1198     } else {
1199         // Draw black on white to create mask. (Special path exists to speed this up in CG.)
1200         // If light-on-dark is requested, draw white on black.
1201         CGContextSetGrayFillColor(fCG.get(), lightOnDark ? 1.0f : 0.0f, 1.0f);
1202     }
1203 
1204     if (fDoAA != doAA) {
1205         CGContextSetShouldAntialias(fCG.get(), doAA);
1206         fDoAA = doAA;
1207     }
1208     if (fDoLCD != doLCD) {
1209         CGContextSetShouldSmoothFonts(fCG.get(), doLCD);
1210         fDoLCD = doLCD;
1211     }
1212 
1213     CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
1214     // skip rows based on the glyph's height
1215     image += (fSize.fHeight - glyph.height()) * fSize.fWidth;
1216 
1217     // Erase to white (or transparent black if it's a color glyph, to not composite against white).
1218     // For light-on-dark, instead erase to black.
1219     uint32_t bgColor = (!glyph.isColor()) ? (lightOnDark ? 0xFF000000 : 0xFFFFFFFF) : 0x00000000;
1220     sk_memset_rect32(image, bgColor, glyph.width(), glyph.height(), rowBytes);
1221 
1222     float subX = 0;
1223     float subY = 0;
1224     if (context.fDoSubPosition) {
1225         subX = SkFixedToFloat(glyph.getSubXFixed());
1226         subY = SkFixedToFloat(glyph.getSubYFixed());
1227     }
1228 
1229     CGPoint point = CGPointMake(-glyph.left() + subX, glyph.top() + glyph.height() - subY);
1230     // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
1231     // 'positions' which are in text space. The glyph location (in device space) must be
1232     // mapped into text space, so that CG can convert it back into device space.
1233     // In 10.10.1, this is handled directly in CTFontDrawGlyphs.
1234     //
1235     // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
1236     // So always make the font transform identity and place the transform on the context.
1237     point = CGPointApplyAffineTransform(point, context.fInvTransform);
1238 
1239     CTFontDrawGlyphs(context.fCTFont.get(), &glyphID, &point, 1, fCG.get());
1240 
1241     SkASSERT(rowBytesPtr);
1242     *rowBytesPtr = rowBytes;
1243     return image;
1244 }
1245 
generateGlyphCount(void)1246 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
1247     return fGlyphCount;
1248 }
1249 
generateAdvance(SkGlyph * glyph)1250 bool SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
1251     return false;
1252 }
1253 
generateMetrics(SkGlyph * glyph)1254 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
1255     glyph->fMaskFormat = fRec.fMaskFormat;
1256 
1257     const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
1258     glyph->zeroMetrics();
1259 
1260     // The following block produces cgAdvance in CG units (pixels, y up).
1261     CGSize cgAdvance;
1262     CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
1263                                &cgGlyph, &cgAdvance, 1);
1264     cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
1265     glyph->fAdvanceX =  CGToFloat(cgAdvance.width);
1266     glyph->fAdvanceY = -CGToFloat(cgAdvance.height);
1267 
1268     // The following produces skBounds in SkGlyph units (pixels, y down),
1269     // or returns early if skBounds would be empty.
1270     SkRect skBounds;
1271 
1272     // Glyphs are always drawn from the horizontal origin. The caller must manually use the result
1273     // of CTFontGetVerticalTranslationsForGlyphs to calculate where to draw the glyph for vertical
1274     // glyphs. As a result, always get the horizontal bounds of a glyph and translate it if the
1275     // glyph is vertical. This avoids any diagreement between the various means of retrieving
1276     // vertical metrics.
1277     {
1278         // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
1279         CGRect cgBounds;
1280         CTFontGetBoundingRectsForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
1281                                         &cgGlyph, &cgBounds, 1);
1282         cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
1283 
1284         // BUG?
1285         // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
1286         // it should be empty. So, if we see a zero-advance, we check if it has an
1287         // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
1288         // is rare, so we won't incur a big performance cost for this extra check.
1289         // Avoid trying to create a path from a color font due to crashing on 10.9.
1290         if (0 == cgAdvance.width && 0 == cgAdvance.height &&
1291             SkMask::kARGB32_Format != glyph->fMaskFormat) {
1292             SkUniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph,nullptr));
1293             if (!path || CGPathIsEmpty(path.get())) {
1294                 return;
1295             }
1296         }
1297 
1298         if (CGRectIsEmpty_inline(cgBounds)) {
1299             return;
1300         }
1301 
1302         // Convert cgBounds to SkGlyph units (pixels, y down).
1303         skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
1304                                     cgBounds.size.width, cgBounds.size.height);
1305     }
1306 
1307     // Currently the bounds are based on being rendered at (0,0).
1308     // The top left must not move, since that is the base from which subpixel positioning is offset.
1309     if (fDoSubPosition) {
1310         skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
1311         skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
1312     }
1313 
1314     // We're trying to pack left and top into int16_t,
1315     // and width and height into uint16_t, after outsetting by 1.
1316     if (!SkRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(skBounds)) {
1317         return;
1318     }
1319 
1320     SkIRect skIBounds;
1321     skBounds.roundOut(&skIBounds);
1322     // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
1323     // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
1324     // is not currently known, as CG dilates the outlines by some percentage.
1325     // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
1326     skIBounds.outset(1, 1);
1327     glyph->fLeft = SkToS16(skIBounds.fLeft);
1328     glyph->fTop = SkToS16(skIBounds.fTop);
1329     glyph->fWidth = SkToU16(skIBounds.width());
1330     glyph->fHeight = SkToU16(skIBounds.height());
1331 }
1332 
1333 #include "include/private/SkColorData.h"
1334 
sk_pow2_table(size_t i)1335 static constexpr uint8_t sk_pow2_table(size_t i) {
1336     return SkToU8(((i * i + 128) / 255));
1337 }
1338 
1339 /**
1340  *  This will invert the gamma applied by CoreGraphics, so we can get linear
1341  *  values.
1342  *
1343  *  CoreGraphics obscurely defaults to 2.0 as the subpixel coverage gamma value.
1344  *  The color space used does not appear to affect this choice.
1345  */
1346 static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
1347 
cgpixels_to_bits(uint8_t dst[],const CGRGBPixel src[],int count)1348 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
1349     while (count > 0) {
1350         uint8_t mask = 0;
1351         for (int i = 7; i >= 0; --i) {
1352             mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i;
1353             if (0 == --count) {
1354                 break;
1355             }
1356         }
1357         *dst++ = mask;
1358     }
1359 }
1360 
1361 template<bool APPLY_PREBLEND>
rgb_to_a8(CGRGBPixel rgb,const uint8_t * table8)1362 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
1363     U8CPU r = 0xFF - ((rgb >> 16) & 0xFF);
1364     U8CPU g = 0xFF - ((rgb >>  8) & 0xFF);
1365     U8CPU b = 0xFF - ((rgb >>  0) & 0xFF);
1366     U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
1367 #if SK_SHOW_TEXT_BLIT_COVERAGE
1368     lum = SkTMax(lum, (U8CPU)0x30);
1369 #endif
1370     return lum;
1371 }
1372 
1373 template<bool APPLY_PREBLEND>
RGBToA8(const CGRGBPixel * SK_RESTRICT cgPixels,size_t cgRowBytes,const SkGlyph & glyph,const uint8_t * table8)1374 void SkScalerContext_Mac::RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
1375                                   const SkGlyph& glyph, const uint8_t* table8) {
1376     const int width = glyph.fWidth;
1377     size_t dstRB = glyph.rowBytes();
1378     uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
1379 
1380     for (int y = 0; y < glyph.fHeight; y++) {
1381         for (int i = 0; i < width; ++i) {
1382             dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
1383         }
1384         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
1385         dst = SkTAddOffset<uint8_t>(dst, dstRB);
1386     }
1387 }
1388 
1389 template<bool APPLY_PREBLEND>
RGBToLcd16(CGRGBPixel rgb,const uint8_t * tableR,const uint8_t * tableG,const uint8_t * tableB)1390 uint16_t SkScalerContext_Mac::RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
1391                                          const uint8_t* tableG,
1392                                          const uint8_t* tableB) {
1393     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
1394     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  8) & 0xFF), tableG);
1395     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  0) & 0xFF), tableB);
1396 #if SK_SHOW_TEXT_BLIT_COVERAGE
1397     r = SkTMax(r, (U8CPU)0x30);
1398     g = SkTMax(g, (U8CPU)0x30);
1399     b = SkTMax(b, (U8CPU)0x30);
1400 #endif
1401     return SkPack888ToRGB16(r, g, b);
1402 }
1403 
1404 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)1405 void SkScalerContext_Mac::RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels,
1406                                      size_t cgRowBytes,
1407                                      const SkGlyph& glyph,
1408                                      const uint8_t* tableR,
1409                                      const uint8_t* tableG,
1410                                      const uint8_t* tableB) {
1411     const int width = glyph.fWidth;
1412     size_t dstRB = glyph.rowBytes();
1413     uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
1414 
1415     for (int y = 0; y < glyph.fHeight; y++) {
1416         for (int i = 0; i < width; i++) {
1417             dst[i] = RGBToLcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
1418         }
1419         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
1420         dst = SkTAddOffset<uint16_t>(dst, dstRB);
1421     }
1422 }
1423 
cgpixels_to_pmcolor(CGRGBPixel rgb)1424 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
1425     U8CPU a = (rgb >> 24) & 0xFF;
1426     U8CPU r = (rgb >> 16) & 0xFF;
1427     U8CPU g = (rgb >>  8) & 0xFF;
1428     U8CPU b = (rgb >>  0) & 0xFF;
1429 #if SK_SHOW_TEXT_BLIT_COVERAGE
1430     a = SkTMax(a, (U8CPU)0x30);
1431 #endif
1432     return SkPackARGB32(a, r, g, b);
1433 }
1434 
generateImage(const SkGlyph & glyph)1435 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
1436     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
1437 
1438     // FIXME: lcd smoothed un-hinted rasterization unsupported.
1439     bool requestSmooth = fRec.getHinting() != SkFontHinting::kNone;
1440     bool lightOnDark = (fRec.fFlags & SkScalerContext::kLightOnDark_Flag) != 0;
1441 
1442     // Draw the glyph
1443     size_t cgRowBytes;
1444     CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, requestSmooth, lightOnDark);
1445     if (cgPixels == nullptr) {
1446         return;
1447     }
1448 
1449     // Fix the glyph
1450     if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
1451         (glyph.fMaskFormat == SkMask::kA8_Format
1452          && requestSmooth
1453          && smooth_behavior() != SmoothBehavior::none))
1454     {
1455         const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
1456 
1457         //Note that the following cannot really be integrated into the
1458         //pre-blend, since we may not be applying the pre-blend; when we aren't
1459         //applying the pre-blend it means that a filter wants linear anyway.
1460         //Other code may also be applying the pre-blend, so we'd need another
1461         //one with this and one without.
1462         CGRGBPixel* addr = cgPixels;
1463         for (int y = 0; y < glyph.fHeight; ++y) {
1464             for (int x = 0; x < glyph.fWidth; ++x) {
1465                 int r = linear[(addr[x] >> 16) & 0xFF];
1466                 int g = linear[(addr[x] >>  8) & 0xFF];
1467                 int b = linear[(addr[x] >>  0) & 0xFF];
1468                 // If light-on-dark was requested, the mask is drawn inverted.
1469                 if (lightOnDark) {
1470                     r = 255 - r;
1471                     g = 255 - g;
1472                     b = 255 - b;
1473                 }
1474                 addr[x] = (r << 16) | (g << 8) | b;
1475             }
1476             addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
1477         }
1478     }
1479 
1480     // Convert glyph to mask
1481     switch (glyph.fMaskFormat) {
1482         case SkMask::kLCD16_Format: {
1483             if (fPreBlend.isApplicable()) {
1484                 RGBToLcd16<true>(cgPixels, cgRowBytes, glyph,
1485                                  fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1486             } else {
1487                 RGBToLcd16<false>(cgPixels, cgRowBytes, glyph,
1488                                   fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1489             }
1490         } break;
1491         case SkMask::kA8_Format: {
1492             if (fPreBlend.isApplicable()) {
1493                 RGBToA8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
1494             } else {
1495                 RGBToA8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
1496             }
1497         } break;
1498         case SkMask::kBW_Format: {
1499             const int width = glyph.fWidth;
1500             size_t dstRB = glyph.rowBytes();
1501             uint8_t* dst = (uint8_t*)glyph.fImage;
1502             for (int y = 0; y < glyph.fHeight; y++) {
1503                 cgpixels_to_bits(dst, cgPixels, width);
1504                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
1505                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
1506             }
1507         } break;
1508         case SkMask::kARGB32_Format: {
1509             const int width = glyph.fWidth;
1510             size_t dstRB = glyph.rowBytes();
1511             SkPMColor* dst = (SkPMColor*)glyph.fImage;
1512             for (int y = 0; y < glyph.fHeight; y++) {
1513                 for (int x = 0; x < width; ++x) {
1514                     dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
1515                 }
1516                 cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
1517                 dst = SkTAddOffset<SkPMColor>(dst, dstRB);
1518             }
1519         } break;
1520         default:
1521             SkDEBUGFAIL("unexpected mask format");
1522             break;
1523     }
1524 }
1525 
1526 /*
1527  *  Our subpixel resolution is only 2 bits in each direction, so a scale of 4
1528  *  seems sufficient, and possibly even correct, to allow the hinted outline
1529  *  to be subpixel positioned.
1530  */
1531 #define kScaleForSubPixelPositionHinting (4.0f)
1532 
generatePath(SkGlyphID glyph,SkPath * path)1533 bool SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
1534     SkScalar scaleX = SK_Scalar1;
1535     SkScalar scaleY = SK_Scalar1;
1536 
1537     CGAffineTransform xform = fTransform;
1538     /*
1539      *  For subpixel positioning, we want to return an unhinted outline, so it
1540      *  can be positioned nicely at fractional offsets. However, we special-case
1541      *  if the baseline of the (horizontal) text is axis-aligned. In those cases
1542      *  we want to retain hinting in the direction orthogonal to the baseline.
1543      *  e.g. for horizontal baseline, we want to retain hinting in Y.
1544      *  The way we remove hinting is to scale the font by some value (4) in that
1545      *  direction, ask for the path, and then scale the path back down.
1546      */
1547     if (fDoSubPosition) {
1548         // start out by assuming that we want no hining in X and Y
1549         scaleX = scaleY = kScaleForSubPixelPositionHinting;
1550         // now see if we need to restore hinting for axis-aligned baselines
1551         switch (this->computeAxisAlignmentForHText()) {
1552             case kX_SkAxisAlignment:
1553                 scaleY = SK_Scalar1; // want hinting in the Y direction
1554                 break;
1555             case kY_SkAxisAlignment:
1556                 scaleX = SK_Scalar1; // want hinting in the X direction
1557                 break;
1558             default:
1559                 break;
1560         }
1561 
1562         CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY)));
1563         xform = CGAffineTransformConcat(fTransform, scale);
1564     }
1565 
1566     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph);
1567     SkUniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
1568 
1569     path->reset();
1570     if (!cgPath) {
1571         return false;
1572     }
1573 
1574     CGPathApply(cgPath.get(), path, SkScalerContext_Mac::CTPathElement);
1575     if (fDoSubPosition) {
1576         SkMatrix m;
1577         m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
1578         path->transform(m);
1579     }
1580     return true;
1581 }
1582 
generateFontMetrics(SkFontMetrics * metrics)1583 void SkScalerContext_Mac::generateFontMetrics(SkFontMetrics* metrics) {
1584     if (nullptr == metrics) {
1585         return;
1586     }
1587 
1588     CGRect theBounds = CTFontGetBoundingBox(fCTFont.get());
1589 
1590     metrics->fTop          = CGToScalar(-CGRectGetMaxY_inline(theBounds));
1591     metrics->fAscent       = CGToScalar(-CTFontGetAscent(fCTFont.get()));
1592     metrics->fDescent      = CGToScalar( CTFontGetDescent(fCTFont.get()));
1593     metrics->fBottom       = CGToScalar(-CGRectGetMinY_inline(theBounds));
1594     metrics->fLeading      = CGToScalar( CTFontGetLeading(fCTFont.get()));
1595     metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
1596     metrics->fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
1597     metrics->fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
1598     metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
1599     metrics->fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont.get()));
1600     metrics->fCapHeight    = CGToScalar( CTFontGetCapHeight(fCTFont.get()));
1601     metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont.get()));
1602     metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont.get()));
1603 
1604     metrics->fFlags = 0;
1605     metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
1606     metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
1607 
1608     // See https://bugs.chromium.org/p/skia/issues/detail?id=6203
1609     // At least on 10.12.3 with memory based fonts the x-height is always 0.6666 of the ascent and
1610     // the cap-height is always 0.8888 of the ascent. It appears that the values from the 'OS/2'
1611     // table are read, but then overwritten if the font is not a system font. As a result, if there
1612     // is a valid 'OS/2' table available use the values from the table if they aren't too strange.
1613     struct OS2HeightMetrics {
1614         SK_OT_SHORT sxHeight;
1615         SK_OT_SHORT sCapHeight;
1616     } heights;
1617     size_t bytesRead = this->getTypeface()->getTableData(
1618             SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2, version.v2.sxHeight),
1619             sizeof(heights), &heights);
1620     if (bytesRead == sizeof(heights)) {
1621         // 'fontSize' is correct because the entire resolved size is set by the constructor.
1622         CGFloat fontSize = CTFontGetSize(this->fCTFont.get());
1623         unsigned upem = CTFontGetUnitsPerEm(this->fCTFont.get());
1624         unsigned maxSaneHeight = upem * 2;
1625         uint16_t xHeight = SkEndian_SwapBE16(heights.sxHeight);
1626         if (xHeight && xHeight < maxSaneHeight) {
1627             metrics->fXHeight = CGToScalar(xHeight * fontSize / upem);
1628         }
1629         uint16_t capHeight = SkEndian_SwapBE16(heights.sCapHeight);
1630         if (capHeight && capHeight < maxSaneHeight) {
1631             metrics->fCapHeight = CGToScalar(capHeight * fontSize / upem);
1632         }
1633     }
1634 }
1635 
CTPathElement(void * info,const CGPathElement * element)1636 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) {
1637     SkPath* skPath = (SkPath*)info;
1638 
1639     // Process the path element
1640     switch (element->type) {
1641         case kCGPathElementMoveToPoint:
1642             skPath->moveTo(element->points[0].x, -element->points[0].y);
1643             break;
1644 
1645         case kCGPathElementAddLineToPoint:
1646             skPath->lineTo(element->points[0].x, -element->points[0].y);
1647             break;
1648 
1649         case kCGPathElementAddQuadCurveToPoint:
1650             skPath->quadTo(element->points[0].x, -element->points[0].y,
1651                            element->points[1].x, -element->points[1].y);
1652             break;
1653 
1654         case kCGPathElementAddCurveToPoint:
1655             skPath->cubicTo(element->points[0].x, -element->points[0].y,
1656                             element->points[1].x, -element->points[1].y,
1657                             element->points[2].x, -element->points[2].y);
1658             break;
1659 
1660         case kCGPathElementCloseSubpath:
1661             skPath->close();
1662             break;
1663 
1664         default:
1665             SkDEBUGFAIL("Unknown path element!");
1666             break;
1667         }
1668 }
1669 
1670 
1671 ///////////////////////////////////////////////////////////////////////////////
1672 
1673 // Returns nullptr on failure
1674 // Call must still manage its ownership of provider
create_from_dataProvider(SkUniqueCFRef<CGDataProviderRef> provider,std::unique_ptr<SkStreamAsset> providedData,int ttcIndex)1675 static sk_sp<SkTypeface> create_from_dataProvider(SkUniqueCFRef<CGDataProviderRef> provider,
1676                                                   std::unique_ptr<SkStreamAsset> providedData,
1677                                                   int ttcIndex) {
1678     if (ttcIndex != 0) {
1679         return nullptr;
1680     }
1681     SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
1682     if (!cg) {
1683         return nullptr;
1684     }
1685     SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg.get(), 0, nullptr, nullptr));
1686     if (!ct) {
1687         return nullptr;
1688     }
1689     return create_from_CTFontRef(std::move(ct), nullptr, std::move(providedData));
1690 }
1691 
1692 // Web fonts added to the CTFont registry do not return their character set.
1693 // Iterate through the font in this case. The existing caller caches the result,
1694 // so the performance impact isn't too bad.
populate_glyph_to_unicode_slow(CTFontRef ctFont,CFIndex glyphCount,SkUnichar * out)1695 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
1696                                            SkUnichar* out) {
1697     sk_bzero(out, glyphCount * sizeof(SkUnichar));
1698     UniChar unichar = 0;
1699     while (glyphCount > 0) {
1700         CGGlyph glyph;
1701         if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
1702             if (out[glyph] == 0) {
1703                 out[glyph] = unichar;
1704                 --glyphCount;
1705             }
1706         }
1707         if (++unichar == 0) {
1708             break;
1709         }
1710     }
1711 }
1712 
1713 static constexpr uint16_t kPlaneSize = 1 << 13;
1714 
get_plane_glyph_map(const uint8_t * bits,CTFontRef ctFont,CFIndex glyphCount,SkUnichar * glyphToUnicode,uint8_t planeIndex)1715 static void get_plane_glyph_map(const uint8_t* bits,
1716                                 CTFontRef ctFont,
1717                                 CFIndex glyphCount,
1718                                 SkUnichar* glyphToUnicode,
1719                                 uint8_t planeIndex) {
1720     SkUnichar planeOrigin = (SkUnichar)planeIndex << 16; // top half of codepoint.
1721     for (uint16_t i = 0; i < kPlaneSize; i++) {
1722         uint8_t mask = bits[i];
1723         if (!mask) {
1724             continue;
1725         }
1726         for (uint8_t j = 0; j < 8; j++) {
1727             if (0 == (mask & ((uint8_t)1 << j))) {
1728                 continue;
1729             }
1730             uint16_t planeOffset = (i << 3) | j;
1731             SkUnichar codepoint = planeOrigin | (SkUnichar)planeOffset;
1732             uint16_t utf16[2] = {planeOffset, 0};
1733             size_t count = 1;
1734             if (planeOrigin != 0) {
1735                 count = SkUTF::ToUTF16(codepoint, utf16);
1736             }
1737             CGGlyph glyphs[2] = {0, 0};
1738             if (CTFontGetGlyphsForCharacters(ctFont, utf16, glyphs, count)) {
1739                 SkASSERT(glyphs[1] == 0);
1740                 SkASSERT(glyphs[0] < glyphCount);
1741                 // CTFontCopyCharacterSet and CTFontGetGlyphsForCharacters seem to add 'support'
1742                 // for characters 0x9, 0xA, and 0xD mapping them to the glyph for character 0x20?
1743                 // Prefer mappings to codepoints at or above 0x20.
1744                 if (glyphToUnicode[glyphs[0]] < 0x20) {
1745                     glyphToUnicode[glyphs[0]] = codepoint;
1746                 }
1747             }
1748         }
1749     }
1750 }
1751 // Construct Glyph to Unicode table.
populate_glyph_to_unicode(CTFontRef ctFont,CFIndex glyphCount,SkUnichar * glyphToUnicode)1752 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
1753                                       SkUnichar* glyphToUnicode) {
1754     sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount);
1755     SkUniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
1756     if (!charSet) {
1757         populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
1758         return;
1759     }
1760 
1761     SkUniqueCFRef<CFDataRef> bitmap(
1762             CFCharacterSetCreateBitmapRepresentation(nullptr, charSet.get()));
1763     if (!bitmap) {
1764         return;
1765     }
1766     CFIndex dataLength = CFDataGetLength(bitmap.get());
1767     if (!dataLength) {
1768         return;
1769     }
1770     SkASSERT(dataLength >= kPlaneSize);
1771     const UInt8* bits = CFDataGetBytePtr(bitmap.get());
1772 
1773     get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, 0);
1774     /*
1775     A CFData object that specifies the bitmap representation of the Unicode
1776     character points the for the new character set. The bitmap representation could
1777     contain all the Unicode character range starting from BMP to Plane 16. The
1778     first 8KiB (8192 bytes) of the data represent the BMP range. The BMP range 8KiB
1779     can be followed by zero to sixteen 8KiB bitmaps, each prepended with the plane
1780     index byte. For example, the bitmap representing the BMP and Plane 2 has the
1781     size of 16385 bytes (8KiB for BMP, 1 byte index, and a 8KiB bitmap for Plane
1782     2). The plane index byte, in this case, contains the integer value two.
1783     */
1784 
1785     if (dataLength <= kPlaneSize) {
1786         return;
1787     }
1788     int extraPlaneCount = (dataLength - kPlaneSize) / (1 + kPlaneSize);
1789     SkASSERT(dataLength == kPlaneSize + extraPlaneCount * (1 + kPlaneSize));
1790     while (extraPlaneCount-- > 0) {
1791         bits += kPlaneSize;
1792         uint8_t planeIndex = *bits++;
1793         SkASSERT(planeIndex >= 1);
1794         SkASSERT(planeIndex <= 16);
1795         get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, planeIndex);
1796     }
1797 }
1798 
1799 /** Assumes src and dst are not nullptr. */
CFStringToSkString(CFStringRef src,SkString * dst)1800 static void CFStringToSkString(CFStringRef src, SkString* dst) {
1801     // Reserve enough room for the worst-case string,
1802     // plus 1 byte for the trailing null.
1803     CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
1804                                                        kCFStringEncodingUTF8) + 1;
1805     dst->resize(length);
1806     CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
1807     // Resize to the actual UTF-8 length used, stripping the null character.
1808     dst->resize(strlen(dst->c_str()));
1809 }
1810 
getGlyphToUnicodeMap(SkUnichar * dstArray) const1811 void SkTypeface_Mac::getGlyphToUnicodeMap(SkUnichar* dstArray) const {
1812     SkUniqueCFRef<CTFontRef> ctFont =
1813             ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr);
1814     CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get());
1815     populate_glyph_to_unicode(ctFont.get(), glyphCount, dstArray);
1816 }
1817 
onGetAdvancedMetrics() const1818 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics() const {
1819 
1820     SkUniqueCFRef<CTFontRef> ctFont =
1821             ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr);
1822 
1823     std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
1824 
1825     {
1826         SkUniqueCFRef<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont.get()));
1827         if (fontName.get()) {
1828             CFStringToSkString(fontName.get(), &info->fPostScriptName);
1829             info->fFontName = info->fPostScriptName;
1830         }
1831     }
1832 
1833     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
1834     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
1835     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
1836     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
1837     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont.get(), nullptr));
1838     if (cgFont) {
1839         SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
1840         if (cgAxes && CFArrayGetCount(cgAxes.get()) > 0) {
1841             info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
1842         }
1843     }
1844 
1845     SkOTTableOS2_V4::Type fsType;
1846     if (sizeof(fsType) == this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG),
1847                                              offsetof(SkOTTableOS2_V4, fsType),
1848                                              sizeof(fsType),
1849                                              &fsType)) {
1850         SkOTUtils::SetAdvancedTypefaceFlags(fsType, info.get());
1851     }
1852 
1853     // If it's not a truetype font, mark it as 'other'. Assume that TrueType
1854     // fonts always have both glyf and loca tables. At the least, this is what
1855     // sfntly needs to subset the font. CTFontCopyAttribute() does not always
1856     // succeed in determining this directly.
1857     if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
1858         return info;
1859     }
1860 
1861     info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1862     CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont.get());
1863     if (symbolicTraits & kCTFontMonoSpaceTrait) {
1864         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1865     }
1866     if (symbolicTraits & kCTFontItalicTrait) {
1867         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1868     }
1869     CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
1870     if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
1871         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1872     } else if (stylisticClass & kCTFontScriptsClass) {
1873         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1874     }
1875     info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont.get());
1876     info->fAscent = (int16_t) CTFontGetAscent(ctFont.get());
1877     info->fDescent = (int16_t) CTFontGetDescent(ctFont.get());
1878     info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont.get());
1879     CGRect bbox = CTFontGetBoundingBox(ctFont.get());
1880 
1881     SkRect r;
1882     r.setLTRB(CGToScalar(CGRectGetMinX_inline(bbox)),   // Left
1883               CGToScalar(CGRectGetMaxY_inline(bbox)),   // Top
1884               CGToScalar(CGRectGetMaxX_inline(bbox)),   // Right
1885               CGToScalar(CGRectGetMinY_inline(bbox)));  // Bottom
1886 
1887     r.roundOut(&(info->fBBox));
1888 
1889     // Figure out a good guess for StemV - Min width of i, I, !, 1.
1890     // This probably isn't very good with an italic font.
1891     int16_t min_width = SHRT_MAX;
1892     info->fStemV = 0;
1893     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
1894     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
1895     CGGlyph glyphs[count];
1896     CGRect boundingRects[count];
1897     if (CTFontGetGlyphsForCharacters(ctFont.get(), stem_chars, glyphs, count)) {
1898         CTFontGetBoundingRectsForGlyphs(ctFont.get(), kCTFontOrientationHorizontal,
1899                                         glyphs, boundingRects, count);
1900         for (size_t i = 0; i < count; i++) {
1901             int16_t width = (int16_t) boundingRects[i].size.width;
1902             if (width > 0 && width < min_width) {
1903                 min_width = width;
1904                 info->fStemV = min_width;
1905             }
1906         }
1907     }
1908     return info;
1909 }
1910 
1911 ///////////////////////////////////////////////////////////////////////////////
1912 
get_font_type_tag(CTFontRef ctFont)1913 static SK_SFNT_ULONG get_font_type_tag(CTFontRef ctFont) {
1914     SkUniqueCFRef<CFNumberRef> fontFormatRef(
1915             static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
1916     if (!fontFormatRef) {
1917         return 0;
1918     }
1919 
1920     SInt32 fontFormatValue;
1921     if (!CFNumberGetValue(fontFormatRef.get(), kCFNumberSInt32Type, &fontFormatValue)) {
1922         return 0;
1923     }
1924 
1925     switch (fontFormatValue) {
1926         case kCTFontFormatOpenTypePostScript:
1927             return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1928         case kCTFontFormatOpenTypeTrueType:
1929             return SkSFNTHeader::fontType_WindowsTrueType::TAG;
1930         case kCTFontFormatTrueType:
1931             return SkSFNTHeader::fontType_MacTrueType::TAG;
1932         case kCTFontFormatPostScript:
1933             return SkSFNTHeader::fontType_PostScript::TAG;
1934         case kCTFontFormatBitmap:
1935             return SkSFNTHeader::fontType_MacTrueType::TAG;
1936         case kCTFontFormatUnrecognized:
1937         default:
1938             return 0;
1939     }
1940 }
1941 
onOpenStream(int * ttcIndex) const1942 std::unique_ptr<SkStreamAsset> SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
1943     *ttcIndex = 0;
1944 
1945     fInitStream([this]{
1946     if (fStream) {
1947         return;
1948     }
1949 
1950     SK_SFNT_ULONG fontType = get_font_type_tag(fFontRef.get());
1951 
1952     // get table tags
1953     int numTables = this->countTables();
1954     SkTDArray<SkFontTableTag> tableTags;
1955     tableTags.setCount(numTables);
1956     this->getTableTags(tableTags.begin());
1957 
1958     // CT seems to be unreliable in being able to obtain the type,
1959     // even if all we want is the first four bytes of the font resource.
1960     // Just the presence of the FontForge 'FFTM' table seems to throw it off.
1961     if (fontType == 0) {
1962         fontType = SkSFNTHeader::fontType_WindowsTrueType::TAG;
1963 
1964         // see https://skbug.com/7630#c7
1965         bool couldBeCFF = false;
1966         constexpr SkFontTableTag CFFTag = SkSetFourByteTag('C', 'F', 'F', ' ');
1967         constexpr SkFontTableTag CFF2Tag = SkSetFourByteTag('C', 'F', 'F', '2');
1968         for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
1969             if (CFFTag == tableTags[tableIndex] || CFF2Tag == tableTags[tableIndex]) {
1970                 couldBeCFF = true;
1971             }
1972         }
1973         if (couldBeCFF) {
1974             fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1975         }
1976     }
1977 
1978     // Sometimes CoreGraphics incorrectly thinks a font is kCTFontFormatPostScript.
1979     // It is exceedingly unlikely that this is the case, so double check
1980     // (see https://crbug.com/809763 ).
1981     if (fontType == SkSFNTHeader::fontType_PostScript::TAG) {
1982         // see if there are any required 'typ1' tables (see Adobe Technical Note #5180)
1983         bool couldBeTyp1 = false;
1984         constexpr SkFontTableTag TYPE1Tag = SkSetFourByteTag('T', 'Y', 'P', '1');
1985         constexpr SkFontTableTag CIDTag = SkSetFourByteTag('C', 'I', 'D', ' ');
1986         for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
1987             if (TYPE1Tag == tableTags[tableIndex] || CIDTag == tableTags[tableIndex]) {
1988                 couldBeTyp1 = true;
1989             }
1990         }
1991         if (!couldBeTyp1) {
1992             fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
1993         }
1994     }
1995 
1996     // get the table sizes and accumulate the total size of the font
1997     SkTDArray<size_t> tableSizes;
1998     size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
1999     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
2000         size_t tableSize = this->getTableSize(tableTags[tableIndex]);
2001         totalSize += (tableSize + 3) & ~3;
2002         *tableSizes.append() = tableSize;
2003     }
2004 
2005     // reserve memory for stream, and zero it (tables must be zero padded)
2006     fStream.reset(new SkMemoryStream(totalSize));
2007     char* dataStart = (char*)fStream->getMemoryBase();
2008     sk_bzero(dataStart, totalSize);
2009     char* dataPtr = dataStart;
2010 
2011     // compute font header entries
2012     uint16_t entrySelector = 0;
2013     uint16_t searchRange = 1;
2014     while (searchRange < numTables >> 1) {
2015         entrySelector++;
2016         searchRange <<= 1;
2017     }
2018     searchRange <<= 4;
2019     uint16_t rangeShift = (numTables << 4) - searchRange;
2020 
2021     // write font header
2022     SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
2023     header->fontType = fontType;
2024     header->numTables = SkEndian_SwapBE16(numTables);
2025     header->searchRange = SkEndian_SwapBE16(searchRange);
2026     header->entrySelector = SkEndian_SwapBE16(entrySelector);
2027     header->rangeShift = SkEndian_SwapBE16(rangeShift);
2028     dataPtr += sizeof(SkSFNTHeader);
2029 
2030     // write tables
2031     SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
2032     dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
2033     for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
2034         size_t tableSize = tableSizes[tableIndex];
2035         this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
2036         entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
2037         entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
2038                                                                          tableSize));
2039         entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
2040         entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
2041 
2042         dataPtr += (tableSize + 3) & ~3;
2043         ++entry;
2044     }
2045     });
2046     return fStream->duplicate();
2047 }
2048 
2049 struct NonDefaultAxesContext {
2050     SkFixed* axisValue;
2051     CFArrayRef cgAxes;
2052 };
set_non_default_axes(CFTypeRef key,CFTypeRef value,void * context)2053 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
2054     NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
2055 
2056     if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) {
2057         return;
2058     }
2059 
2060     // The key is a CFString which is a string from the 'name' table.
2061     // Search the cgAxes for an axis with this name, and use its index to store the value.
2062     CFIndex keyIndex = -1;
2063     CFStringRef keyString = static_cast<CFStringRef>(key);
2064     for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
2065         CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
2066         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
2067             continue;
2068         }
2069 
2070         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
2071         CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
2072         if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
2073             continue;
2074         }
2075         CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
2076         if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
2077             keyIndex = i;
2078             break;
2079         }
2080     }
2081     if (keyIndex == -1) {
2082         return;
2083     }
2084 
2085     CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
2086     double valueDouble;
2087     if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
2088         valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble)
2089     {
2090         return;
2091     }
2092     self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
2093 }
get_variations(CTFontRef ctFont,CFIndex * cgAxisCount,SkAutoSTMalloc<4,SkFixed> * axisValues)2094 static bool get_variations(CTFontRef ctFont, CFIndex* cgAxisCount,
2095                            SkAutoSTMalloc<4, SkFixed>* axisValues)
2096 {
2097     // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
2098     // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
2099     // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
2100     // CGFontCopyVariations here until support for 10.10 and earlier is removed.
2101     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
2102     if (!cgFont) {
2103         return false;
2104     }
2105 
2106     SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
2107     // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict).
2108     if (!cgVariations) {
2109         return false;
2110     }
2111 
2112     SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
2113     if (!cgAxes) {
2114         return false;
2115     }
2116     *cgAxisCount = CFArrayGetCount(cgAxes.get());
2117     axisValues->reset(*cgAxisCount);
2118 
2119     // Set all of the axes to their default values.
2120     // Fail if any default value cannot be determined.
2121     for (CFIndex i = 0; i < *cgAxisCount; ++i) {
2122         CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes.get(), i);
2123         if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
2124             return false;
2125         }
2126 
2127         CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
2128         CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
2129                                                           kCGFontVariationAxisDefaultValue);
2130         if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
2131             return false;
2132         }
2133         CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
2134         double axisDefaultValueDouble;
2135         if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble))
2136         {
2137             return false;
2138         }
2139         if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
2140                                      SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
2141         {
2142             return false;
2143         }
2144         (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
2145     }
2146 
2147     // Override the default values with the given font's stated axis values.
2148     NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
2149     CFDictionaryApplyFunction(cgVariations.get(), set_non_default_axes, &c);
2150 
2151     return true;
2152 }
onMakeFontData() const2153 std::unique_ptr<SkFontData> SkTypeface_Mac::onMakeFontData() const {
2154     int index;
2155     std::unique_ptr<SkStreamAsset> stream(this->onOpenStream(&index));
2156 
2157     CFIndex cgAxisCount;
2158     SkAutoSTMalloc<4, SkFixed> axisValues;
2159     if (get_variations(fFontRef.get(), &cgAxisCount, &axisValues)) {
2160         return skstd::make_unique<SkFontData>(std::move(stream), index,
2161                                               axisValues.get(), cgAxisCount);
2162     }
2163     return skstd::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
2164 }
2165 
2166 /** Creates a CT variation dictionary {tag, value} from a CG variation dictionary {name, value}. */
ct_variation_from_cg_variation(CFDictionaryRef cgVariations,CFArrayRef ctAxes)2167 static SkUniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
2168                                                                      CFArrayRef ctAxes) {
2169 
2170     SkUniqueCFRef<CFMutableDictionaryRef> ctVariations(
2171             CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2172                                       &kCFTypeDictionaryKeyCallBacks,
2173                                       &kCFTypeDictionaryValueCallBacks));
2174 
2175     CFIndex axisCount = CFArrayGetCount(ctAxes);
2176     for (CFIndex i = 0; i < axisCount; ++i) {
2177         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes, i);
2178         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2179             return nullptr;
2180         }
2181         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2182 
2183         // The assumption is that values produced by kCTFontVariationAxisNameKey and
2184         // kCGFontVariationAxisName will always be equal.
2185         CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
2186         if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2187             return nullptr;
2188         }
2189 
2190         CFTypeRef axisValue = CFDictionaryGetValue(cgVariations, axisName);
2191         if (!axisValue || CFGetTypeID(axisValue) != CFNumberGetTypeID()) {
2192             return nullptr;
2193         }
2194 
2195         CFTypeRef axisTag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2196         if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
2197             return nullptr;
2198         }
2199 
2200         CFDictionaryAddValue(ctVariations.get(), axisTag, axisValue);
2201     }
2202     return ctVariations;
2203 }
2204 
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const2205 int SkTypeface_Mac::onGetVariationDesignPosition(
2206         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
2207 {
2208     // The CGFont variation data does not contain the tag.
2209 
2210     // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
2211     // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
2212     SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
2213     if (!ctAxes) {
2214         return -1;
2215     }
2216     CFIndex axisCount = CFArrayGetCount(ctAxes.get());
2217     if (!coordinates || coordinateCount < axisCount) {
2218         return axisCount;
2219     }
2220 
2221     // This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
2222     // When this happens, try converting the CG variation to a CT variation.
2223     // On 10.12 and later, this only returns non-default variations.
2224     SkUniqueCFRef<CFDictionaryRef> ctVariations(CTFontCopyVariation(fFontRef.get()));
2225     if (!ctVariations) {
2226         // When 10.11 and earlier are no longer supported, the following code can be replaced with
2227         // return -1 and ct_variation_from_cg_variation can be removed.
2228         SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
2229         if (!cgFont) {
2230             return -1;
2231         }
2232         SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
2233         if (!cgVariations) {
2234             return -1;
2235         }
2236         ctVariations = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
2237         if (!ctVariations) {
2238             return -1;
2239         }
2240     }
2241 
2242     for (int i = 0; i < axisCount; ++i) {
2243         CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
2244         if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2245             return -1;
2246         }
2247         CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2248 
2249         CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2250         if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
2251             return -1;
2252         }
2253         CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
2254         int64_t tagLong;
2255         if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
2256             return -1;
2257         }
2258         coordinates[i].axis = tagLong;
2259 
2260         CGFloat variationCGFloat;
2261         CFTypeRef variationValue = CFDictionaryGetValue(ctVariations.get(), tagNumber);
2262         if (variationValue) {
2263             if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
2264                 return -1;
2265             }
2266             CFNumberRef variationNumber = static_cast<CFNumberRef>(variationValue);
2267             if (!CFNumberGetValue(variationNumber, kCFNumberCGFloatType, &variationCGFloat)) {
2268                 return -1;
2269             }
2270         } else {
2271             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
2272             if (!def || CFGetTypeID(def) != CFNumberGetTypeID()) {
2273                 return -1;
2274             }
2275             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
2276             if (!CFNumberGetValue(defNumber, kCFNumberCGFloatType, &variationCGFloat)) {
2277                 return -1;
2278             }
2279         }
2280         coordinates[i].value = CGToScalar(variationCGFloat);
2281 
2282     }
2283     return axisCount;
2284 }
2285 
2286 ///////////////////////////////////////////////////////////////////////////////
2287 ///////////////////////////////////////////////////////////////////////////////
2288 
onGetUPEM() const2289 int SkTypeface_Mac::onGetUPEM() const {
2290     SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
2291     return CGFontGetUnitsPerEm(cgFont.get());
2292 }
2293 
onCreateFamilyNameIterator() const2294 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
2295     sk_sp<SkTypeface::LocalizedStrings> nameIter =
2296             SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
2297     if (!nameIter) {
2298         CFStringRef cfLanguageRaw;
2299         SkUniqueCFRef<CFStringRef> cfFamilyName(
2300                 CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
2301         SkUniqueCFRef<CFStringRef> cfLanguage(cfLanguageRaw);
2302 
2303         SkString skLanguage;
2304         SkString skFamilyName;
2305         if (cfLanguage) {
2306             CFStringToSkString(cfLanguage.get(), &skLanguage);
2307         } else {
2308             skLanguage = "und"; //undetermined
2309         }
2310         if (cfFamilyName) {
2311             CFStringToSkString(cfFamilyName.get(), &skFamilyName);
2312         }
2313 
2314         nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(skFamilyName, skLanguage);
2315     }
2316     return nameIter.release();
2317 }
2318 
onGetTableTags(SkFontTableTag tags[]) const2319 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
2320     SkUniqueCFRef<CFArrayRef> cfArray(
2321             CTFontCopyAvailableTables(fFontRef.get(), kCTFontTableOptionNoOptions));
2322     if (!cfArray) {
2323         return 0;
2324     }
2325     int count = SkToInt(CFArrayGetCount(cfArray.get()));
2326     if (tags) {
2327         for (int i = 0; i < count; ++i) {
2328             uintptr_t fontTag = reinterpret_cast<uintptr_t>(
2329                 CFArrayGetValueAtIndex(cfArray.get(), i));
2330             tags[i] = static_cast<SkFontTableTag>(fontTag);
2331         }
2332     }
2333     return count;
2334 }
2335 
2336 // If, as is the case with web fonts, the CTFont data isn't available,
2337 // the CGFont data may work. While the CGFont may always provide the
2338 // right result, leave the CTFont code path to minimize disruption.
copy_table_from_font(CTFontRef ctFont,SkFontTableTag tag)2339 static SkUniqueCFRef<CFDataRef> copy_table_from_font(CTFontRef ctFont, SkFontTableTag tag) {
2340     SkUniqueCFRef<CFDataRef> data(CTFontCopyTable(ctFont, (CTFontTableTag) tag,
2341                                                   kCTFontTableOptionNoOptions));
2342     if (!data) {
2343         SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
2344         data.reset(CGFontCopyTableForTag(cgFont.get(), tag));
2345     }
2346     return data;
2347 }
2348 
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * dstData) const2349 size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
2350                                       size_t length, void* dstData) const {
2351     SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
2352     if (!srcData) {
2353         return 0;
2354     }
2355 
2356     size_t srcSize = CFDataGetLength(srcData.get());
2357     if (offset >= srcSize) {
2358         return 0;
2359     }
2360     if (length > srcSize - offset) {
2361         length = srcSize - offset;
2362     }
2363     if (dstData) {
2364         memcpy(dstData, CFDataGetBytePtr(srcData.get()) + offset, length);
2365     }
2366     return length;
2367 }
2368 
onCopyTableData(SkFontTableTag tag) const2369 sk_sp<SkData> SkTypeface_Mac::onCopyTableData(SkFontTableTag tag) const {
2370     SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
2371     if (!srcData) {
2372         return nullptr;
2373     }
2374     const UInt8* data = CFDataGetBytePtr(srcData.get());
2375     CFIndex length = CFDataGetLength(srcData.get());
2376     return SkData::MakeWithProc(data, length,
2377                                 [](const void*, void* ctx) {
2378                                     CFRelease((CFDataRef)ctx);
2379                                 }, (void*)srcData.release());
2380 }
2381 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const2382 SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkScalerContextEffects& effects,
2383                                                        const SkDescriptor* desc) const {
2384     return new SkScalerContext_Mac(sk_ref_sp(const_cast<SkTypeface_Mac*>(this)), effects, desc);
2385 }
2386 
onFilterRec(SkScalerContextRec * rec) const2387 void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
2388     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
2389         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
2390     {
2391         rec->fMaskFormat = SkMask::kA8_Format;
2392         // Render the glyphs as close as possible to what was requested.
2393         // The above turns off subpixel rendering, but the user requested it.
2394         // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
2395         // See comments below for more details.
2396         rec->setHinting(SkFontHinting::kNormal);
2397     }
2398 
2399     unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag  |
2400                                   SkScalerContext::kLCD_BGROrder_Flag |
2401                                   SkScalerContext::kLCD_Vertical_Flag;
2402 
2403     rec->fFlags &= ~flagsWeDontSupport;
2404 
2405     const SmoothBehavior smoothBehavior = smooth_behavior();
2406 
2407     // Only two levels of hinting are supported.
2408     // kNo_Hinting means avoid CoreGraphics outline dilation (smoothing).
2409     // kNormal_Hinting means CoreGraphics outline dilation (smoothing) is allowed.
2410     if (rec->getHinting() != SkFontHinting::kNone) {
2411         rec->setHinting(SkFontHinting::kNormal);
2412     }
2413     // If smoothing has no effect, don't request it.
2414     if (smoothBehavior == SmoothBehavior::none) {
2415         rec->setHinting(SkFontHinting::kNone);
2416     }
2417 
2418     // FIXME: lcd smoothed un-hinted rasterization unsupported.
2419     // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
2420     // There is no current means to honor a request for unhinted lcd,
2421     // so arbitrarilly ignore the hinting request and honor lcd.
2422 
2423     // Hinting and smoothing should be orthogonal, but currently they are not.
2424     // CoreGraphics has no API to influence hinting. However, its lcd smoothed
2425     // output is drawn from auto-dilated outlines (the amount of which is
2426     // determined by AppleFontSmoothing). Its regular anti-aliased output is
2427     // drawn from un-dilated outlines.
2428 
2429     // The behavior of Skia is as follows:
2430     // [AA][no-hint]: generate AA using CoreGraphic's AA output.
2431     // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
2432     // channel. This matches [LCD][yes-hint] in weight.
2433     // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
2434     // Currenly side with LCD, effectively ignoring the hinting setting.
2435     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
2436     if (rec->fMaskFormat == SkMask::kLCD16_Format) {
2437         if (smoothBehavior == SmoothBehavior::subpixel) {
2438             //CoreGraphics creates 555 masks for smoothed text anyway.
2439             rec->fMaskFormat = SkMask::kLCD16_Format;
2440             rec->setHinting(SkFontHinting::kNormal);
2441         } else {
2442             rec->fMaskFormat = SkMask::kA8_Format;
2443             if (smoothBehavior != SmoothBehavior::none) {
2444                 rec->setHinting(SkFontHinting::kNormal);
2445             }
2446         }
2447     }
2448 
2449     // CoreText provides no information as to whether a glyph will be color or not.
2450     // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
2451     // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
2452     if (fHasColorGlyphs) {
2453         rec->fMaskFormat = SkMask::kARGB32_Format;
2454     }
2455 
2456     // Smoothing will be used if the format is either LCD or if there is hinting.
2457     // In those cases, we need to choose the proper dilation mask based on the color.
2458     if (rec->fMaskFormat == SkMask::kLCD16_Format ||
2459         (rec->fMaskFormat == SkMask::kA8_Format && rec->getHinting() != SkFontHinting::kNone)) {
2460         SkColor color = rec->getLuminanceColor();
2461         int r = SkColorGetR(color);
2462         int g = SkColorGetG(color);
2463         int b = SkColorGetB(color);
2464         // Choose whether to draw using a light-on-dark mask based on observed
2465         // color/luminance thresholds that CoreText uses.
2466         if (r >= 85 && g >= 85 && b >= 85 && r + g + b >= 2 * 255) {
2467             rec->fFlags |= SkScalerContext::kLightOnDark_Flag;
2468         }
2469     }
2470 
2471     // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
2472     // All other masks can use regular gamma.
2473     if (SkMask::kA8_Format == rec->fMaskFormat && SkFontHinting::kNone == rec->getHinting()) {
2474 #ifndef SK_GAMMA_APPLY_TO_A8
2475         // SRGBTODO: Is this correct? Do we want contrast boost?
2476         rec->ignorePreBlend();
2477 #endif
2478     } else {
2479 #ifndef SK_IGNORE_MAC_BLENDING_MATCH_FIX
2480         SkColor color = rec->getLuminanceColor();
2481         if (smoothBehavior == SmoothBehavior::some) {
2482             // CoreGraphics smoothed text without subpixel coverage blitting goes from a gamma of
2483             // 2.0 for black foreground to a gamma of 1.0 for white foreground. Emulate this
2484             // through the mask gamma by reducing the color values to 1/2.
2485             color = SkColorSetRGB(SkColorGetR(color) * 1/2,
2486                                   SkColorGetG(color) * 1/2,
2487                                   SkColorGetB(color) * 1/2);
2488         } else if (smoothBehavior == SmoothBehavior::subpixel) {
2489             // CoreGraphics smoothed text with subpixel coverage blitting goes from a gamma of
2490             // 2.0 for black foreground to a gamma of ~1.4? for white foreground. Emulate this
2491             // through the mask gamma by reducing the color values to 3/4.
2492             color = SkColorSetRGB(SkColorGetR(color) * 3/4,
2493                                   SkColorGetG(color) * 3/4,
2494                                   SkColorGetB(color) * 3/4);
2495         }
2496         rec->setLuminanceColor(color);
2497 #endif
2498         // CoreGraphics dialates smoothed text to provide contrast.
2499         rec->setContrast(0);
2500     }
2501 }
2502 
2503 /** Takes ownership of the CFStringRef. */
get_str(CFStringRef ref,SkString * str)2504 static const char* get_str(CFStringRef ref, SkString* str) {
2505     if (nullptr == ref) {
2506         return nullptr;
2507     }
2508     CFStringToSkString(ref, str);
2509     CFRelease(ref);
2510     return str->c_str();
2511 }
2512 
onGetFamilyName(SkString * familyName) const2513 void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
2514     get_str(CTFontCopyFamilyName(fFontRef.get()), familyName);
2515 }
2516 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocalStream) const2517 void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
2518                                          bool* isLocalStream) const {
2519     SkString tmpStr;
2520 
2521     desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef.get()), &tmpStr));
2522     desc->setFullName(get_str(CTFontCopyFullName(fFontRef.get()), &tmpStr));
2523     desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef.get()), &tmpStr));
2524     desc->setStyle(this->fontStyle());
2525     *isLocalStream = fIsFromStream;
2526 }
2527 
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const2528 void SkTypeface_Mac::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
2529     // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
2530     // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
2531     // It is documented that if a mapping is unavailable, the glyph will be set to 0.
2532 
2533     SkAutoSTMalloc<1024, UniChar> charStorage;
2534     const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
2535     int srcCount;
2536     const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(uni);
2537     UniChar* utf16 = charStorage.reset(2 * count);
2538     src = utf16;
2539     for (int i = 0; i < count; ++i) {
2540         utf16 += SkUTF::ToUTF16(utf32[i], utf16);
2541     }
2542     srcCount = SkToInt(utf16 - src);
2543 
2544     // If there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
2545     SkAutoSTMalloc<1024, uint16_t> glyphStorage;
2546     uint16_t* macGlyphs = glyphs;
2547     if (srcCount > count) {
2548         macGlyphs = glyphStorage.reset(srcCount);
2549     }
2550 
2551     CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount);
2552 
2553     // If there were any non-bmp, then copy and compact.
2554     // If all are bmp, 'glyphs' already contains the compact glyphs.
2555     // If some are non-bmp, copy and compact into 'glyphs'.
2556     if (srcCount > count) {
2557         SkASSERT(glyphs != macGlyphs);
2558         int extra = 0;
2559         for (int i = 0; i < count; ++i) {
2560             glyphs[i] = macGlyphs[i + extra];
2561             if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
2562                 ++extra;
2563             }
2564         }
2565     } else {
2566         SkASSERT(glyphs == macGlyphs);
2567     }
2568 }
2569 
onCountGlyphs() const2570 int SkTypeface_Mac::onCountGlyphs() const {
2571     return SkToInt(CTFontGetGlyphCount(fFontRef.get()));
2572 }
2573 
2574 ///////////////////////////////////////////////////////////////////////////////
2575 ///////////////////////////////////////////////////////////////////////////////
2576 
find_desc_str(CTFontDescriptorRef desc,CFStringRef name,SkString * value)2577 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
2578     SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
2579     if (!ref) {
2580         return false;
2581     }
2582     CFStringToSkString(ref.get(), value);
2583     return true;
2584 }
2585 
2586 #include "include/core/SkFontMgr.h"
2587 
sqr(int value)2588 static inline int sqr(int value) {
2589     SkASSERT(SkAbs32(value) < 0x7FFF);  // check for overflow
2590     return value * value;
2591 }
2592 
2593 // We normalize each axis (weight, width, italic) to be base-900
compute_metric(const SkFontStyle & a,const SkFontStyle & b)2594 static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
2595     return sqr(a.weight() - b.weight()) +
2596            sqr((a.width() - b.width()) * 100) +
2597            sqr((a.slant() != b.slant()) * 900);
2598 }
2599 
2600 class SkFontStyleSet_Mac : public SkFontStyleSet {
2601 public:
SkFontStyleSet_Mac(CTFontDescriptorRef desc)2602     SkFontStyleSet_Mac(CTFontDescriptorRef desc)
2603         : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr))
2604         , fCount(0)
2605     {
2606         if (!fArray) {
2607             fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
2608         }
2609         fCount = SkToInt(CFArrayGetCount(fArray.get()));
2610     }
2611 
count()2612     int count() override {
2613         return fCount;
2614     }
2615 
getStyle(int index,SkFontStyle * style,SkString * name)2616     void getStyle(int index, SkFontStyle* style, SkString* name) override {
2617         SkASSERT((unsigned)index < (unsigned)fCount);
2618         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
2619         if (style) {
2620             *style = fontstyle_from_descriptor(desc, false);
2621         }
2622         if (name) {
2623             if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
2624                 name->reset();
2625             }
2626         }
2627     }
2628 
createTypeface(int index)2629     SkTypeface* createTypeface(int index) override {
2630         SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
2631         CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
2632 
2633         return create_from_desc(desc).release();
2634     }
2635 
matchStyle(const SkFontStyle & pattern)2636     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
2637         if (0 == fCount) {
2638             return nullptr;
2639         }
2640         return create_from_desc(findMatchingDesc(pattern)).release();
2641     }
2642 
2643 private:
2644     SkUniqueCFRef<CFArrayRef> fArray;
2645     int fCount;
2646 
findMatchingDesc(const SkFontStyle & pattern) const2647     CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
2648         int bestMetric = SK_MaxS32;
2649         CTFontDescriptorRef bestDesc = nullptr;
2650 
2651         for (int i = 0; i < fCount; ++i) {
2652             CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
2653             int metric = compute_metric(pattern, fontstyle_from_descriptor(desc, false));
2654             if (0 == metric) {
2655                 return desc;
2656             }
2657             if (metric < bestMetric) {
2658                 bestMetric = metric;
2659                 bestDesc = desc;
2660             }
2661         }
2662         SkASSERT(bestDesc);
2663         return bestDesc;
2664     }
2665 };
2666 
2667 class SkFontMgr_Mac : public SkFontMgr {
2668     SkUniqueCFRef<CFArrayRef> fNames;
2669     int fCount;
2670 
getFamilyNameAt(int index) const2671     CFStringRef getFamilyNameAt(int index) const {
2672         SkASSERT((unsigned)index < (unsigned)fCount);
2673         return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
2674     }
2675 
CreateSet(CFStringRef cfFamilyName)2676     static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
2677         SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
2678                  CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2679                                            &kCFTypeDictionaryKeyCallBacks,
2680                                            &kCFTypeDictionaryValueCallBacks));
2681 
2682         CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
2683 
2684         SkUniqueCFRef<CTFontDescriptorRef> desc(
2685                 CTFontDescriptorCreateWithAttributes(cfAttr.get()));
2686         return new SkFontStyleSet_Mac(desc.get());
2687     }
2688 
2689     /** CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
2690      *  provide a wrapper here that will return an empty array if need be.
2691      */
CopyAvailableFontFamilyNames()2692     static SkUniqueCFRef<CFArrayRef> CopyAvailableFontFamilyNames() {
2693 #ifdef SK_BUILD_FOR_IOS
2694         return SkUniqueCFRef<CFArrayRef>(CFArrayCreate(nullptr, nullptr, 0, nullptr));
2695 #else
2696         return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
2697 #endif
2698     }
2699 
2700 public:
SkFontMgr_Mac()2701     SkFontMgr_Mac()
2702         : fNames(CopyAvailableFontFamilyNames())
2703         , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0) {}
2704 
2705 protected:
onCountFamilies() const2706     int onCountFamilies() const override {
2707         return fCount;
2708     }
2709 
onGetFamilyName(int index,SkString * familyName) const2710     void onGetFamilyName(int index, SkString* familyName) const override {
2711         if ((unsigned)index < (unsigned)fCount) {
2712             CFStringToSkString(this->getFamilyNameAt(index), familyName);
2713         } else {
2714             familyName->reset();
2715         }
2716     }
2717 
onCreateStyleSet(int index) const2718     SkFontStyleSet* onCreateStyleSet(int index) const override {
2719         if ((unsigned)index >= (unsigned)fCount) {
2720             return nullptr;
2721         }
2722         return CreateSet(this->getFamilyNameAt(index));
2723     }
2724 
onMatchFamily(const char familyName[]) const2725     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
2726         if (!familyName) {
2727             return nullptr;
2728         }
2729         SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
2730         return CreateSet(cfName.get());
2731     }
2732 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const2733     SkTypeface* onMatchFamilyStyle(const char familyName[],
2734                                    const SkFontStyle& style) const override {
2735         SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
2736         return create_from_desc(desc.get()).release();
2737     }
2738 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const2739     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
2740                                             const SkFontStyle& style,
2741                                             const char* bcp47[], int bcp47Count,
2742                                             SkUnichar character) const override {
2743         SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
2744         SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
2745 
2746         // kCFStringEncodingUTF32 is BE unless there is a BOM.
2747         // Since there is no machine endian option, explicitly state machine endian.
2748 #ifdef SK_CPU_LENDIAN
2749         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
2750 #else
2751         constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
2752 #endif
2753         SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
2754                 kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
2755                 encoding, false));
2756         CFRange range = CFRangeMake(0, CFStringGetLength(string.get()));  // in UniChar units.
2757         SkUniqueCFRef<CTFontRef> fallbackFont(
2758                 CTFontCreateForString(familyFont.get(), string.get(), range));
2759         return create_from_CTFontRef(std::move(fallbackFont), nullptr, nullptr).release();
2760     }
2761 
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle &) const2762     SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
2763                                  const SkFontStyle&) const override {
2764         return nullptr;
2765     }
2766 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const2767     sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
2768         SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromData(data));
2769         if (!pr) {
2770             return nullptr;
2771         }
2772         return create_from_dataProvider(std::move(pr), SkMemoryStream::Make(std::move(data)),
2773                                         ttcIndex);
2774     }
2775 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const2776     sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
2777                                             int ttcIndex) const override {
2778         SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream->duplicate()));
2779         if (!pr) {
2780             return nullptr;
2781         }
2782         return create_from_dataProvider(std::move(pr), std::move(stream), ttcIndex);
2783     }
2784 
2785     /** Creates a dictionary suitable for setting the axes on a CGFont. */
copy_axes(CGFontRef cg,const SkFontArguments & args)2786     static SkUniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, const SkFontArguments& args) {
2787         // The CGFont variation data is keyed by name, but lacks the tag.
2788         // The CTFont variation data is keyed by tag, and also has the name.
2789         // We would like to work with CTFont variations, but creating a CTFont font with
2790         // CTFont variation dictionary runs into bugs. So use the CTFont variation data
2791         // to match names to tags to create the appropriate CGFont.
2792         SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr));
2793         // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
2794         // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
2795         SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct.get()));
2796         if (!ctAxes) {
2797             return nullptr;
2798         }
2799         CFIndex axisCount = CFArrayGetCount(ctAxes.get());
2800 
2801         const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
2802 
2803         SkUniqueCFRef<CFMutableDictionaryRef> dict(
2804                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
2805                                           &kCFTypeDictionaryKeyCallBacks,
2806                                           &kCFTypeDictionaryValueCallBacks));
2807 
2808         for (int i = 0; i < axisCount; ++i) {
2809             CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
2810             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2811                 return nullptr;
2812             }
2813             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2814 
2815             // The assumption is that values produced by kCTFontVariationAxisNameKey and
2816             // kCGFontVariationAxisName will always be equal.
2817             // If they are ever not, seach the project history for "get_tag_for_name".
2818             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
2819             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2820                 return nullptr;
2821             }
2822 
2823             CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
2824             if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
2825                 return nullptr;
2826             }
2827             CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
2828             int64_t tagLong;
2829             if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
2830                 return nullptr;
2831             }
2832 
2833             // The variation axes can be set to any value, but cg will effectively pin them.
2834             // Pin them here to normalize.
2835             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
2836             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
2837             CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
2838             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2839                 !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
2840                 !def || CFGetTypeID(def) != CFNumberGetTypeID())
2841             {
2842                 return nullptr;
2843             }
2844             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2845             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2846             CFNumberRef defNumber = static_cast<CFNumberRef>(def);
2847             double minDouble;
2848             double maxDouble;
2849             double defDouble;
2850             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2851                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
2852                 !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
2853             {
2854                 return nullptr;
2855             }
2856 
2857             double value = defDouble;
2858             // The position may be over specified. If there are multiple values for a given axis,
2859             // use the last one since that's what css-fonts-4 requires.
2860             for (int j = position.coordinateCount; j --> 0;) {
2861                 if (position.coordinates[j].axis == tagLong) {
2862                     value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
2863                                    minDouble, maxDouble);
2864                     break;
2865                 }
2866             }
2867             SkUniqueCFRef<CFNumberRef> valueNumber(
2868                 CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
2869             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
2870         }
2871         return dict;
2872     }
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> s,const SkFontArguments & args) const2873     sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> s,
2874                                            const SkFontArguments& args) const override {
2875         if (args.getCollectionIndex() != 0) {
2876             return nullptr;
2877         }
2878         SkUniqueCFRef<CGDataProviderRef> provider(SkCreateDataProviderFromStream(s->duplicate()));
2879         if (!provider) {
2880             return nullptr;
2881         }
2882         SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
2883         if (!cg) {
2884             return nullptr;
2885         }
2886 
2887         SkUniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), args);
2888         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
2889         // created from a data provider does not appear to have any ownership of the underlying
2890         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
2891         SkUniqueCFRef<CGFontRef> cgVariant;
2892         if (cgVariations) {
2893             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
2894         } else {
2895             cgVariant.reset(cg.release());
2896         }
2897 
2898         SkUniqueCFRef<CTFontRef> ct(
2899                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
2900         if (!ct) {
2901             return nullptr;
2902         }
2903         return create_from_CTFontRef(std::move(ct), std::move(cg), std::move(s));
2904     }
2905 
2906     /** Creates a dictionary suitable for setting the axes on a CGFont. */
copy_axes(CGFontRef cg,SkFontData * fontData)2907     static SkUniqueCFRef<CFDictionaryRef> copy_axes(CGFontRef cg, SkFontData* fontData) {
2908         SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
2909         if (!cgAxes) {
2910             return nullptr;
2911         }
2912 
2913         CFIndex axisCount = CFArrayGetCount(cgAxes.get());
2914         if (0 == axisCount || axisCount != fontData->getAxisCount()) {
2915             return nullptr;
2916         }
2917 
2918         SkUniqueCFRef<CFMutableDictionaryRef> dict(
2919                 CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
2920                                           &kCFTypeDictionaryKeyCallBacks,
2921                                           &kCFTypeDictionaryValueCallBacks));
2922 
2923         for (int i = 0; i < fontData->getAxisCount(); ++i) {
2924             CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes.get(), i);
2925             if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
2926                 return nullptr;
2927             }
2928             CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
2929 
2930             CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName);
2931             if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
2932                 return nullptr;
2933             }
2934 
2935             // The variation axes can be set to any value, but cg will effectively pin them.
2936             // Pin them here to normalize.
2937             CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue);
2938             CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue);
2939             if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
2940                 !max || CFGetTypeID(max) != CFNumberGetTypeID())
2941             {
2942                 return nullptr;
2943             }
2944             CFNumberRef minNumber = static_cast<CFNumberRef>(min);
2945             CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
2946             double minDouble;
2947             double maxDouble;
2948             if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
2949                 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
2950             {
2951                 return nullptr;
2952             }
2953             double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
2954             SkUniqueCFRef<CFNumberRef> valueNumber(
2955                     CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
2956             CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
2957         }
2958         return dict;
2959     }
onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const2960     sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
2961         if (fontData->getIndex() != 0) {
2962             return nullptr;
2963         }
2964         SkUniqueCFRef<CGDataProviderRef> provider(
2965                 SkCreateDataProviderFromStream(fontData->getStream()->duplicate()));
2966         if (!provider) {
2967             return nullptr;
2968         }
2969         SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
2970         if (!cg) {
2971             return nullptr;
2972         }
2973 
2974         SkUniqueCFRef<CFDictionaryRef> cgVariations = copy_axes(cg.get(), fontData.get());
2975         // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
2976         // created from a data provider does not appear to have any ownership of the underlying
2977         // data. The original CGFontRef must be kept alive until the copy will no longer be used.
2978         SkUniqueCFRef<CGFontRef> cgVariant;
2979         if (cgVariations) {
2980             cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.get()));
2981         } else {
2982             cgVariant.reset(cg.release());
2983         }
2984 
2985         SkUniqueCFRef<CTFontRef> ct(
2986                 CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, nullptr));
2987         if (!ct) {
2988             return nullptr;
2989         }
2990         return create_from_CTFontRef(std::move(ct), std::move(cg), fontData->detachStream());
2991     }
2992 
onMakeFromFile(const char path[],int ttcIndex) const2993     sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
2994         SkUniqueCFRef<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
2995         if (!pr) {
2996             return nullptr;
2997         }
2998         return create_from_dataProvider(std::move(pr), SkFILEStream::Make(path), ttcIndex);
2999     }
3000 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const3001     sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
3002         if (familyName) {
3003             familyName = map_css_names(familyName);
3004         }
3005 
3006         sk_sp<SkTypeface> face = create_from_name(familyName, style);
3007         if (face) {
3008             return face;
3009         }
3010 
3011         static SkTypeface* gDefaultFace;
3012         static SkOnce lookupDefault;
3013         static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
3014         lookupDefault([]{
3015             gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release();
3016         });
3017         return sk_ref_sp(gDefaultFace);
3018     }
3019 };
3020 
3021 ///////////////////////////////////////////////////////////////////////////////
3022 
Factory()3023 sk_sp<SkFontMgr> SkFontMgr::Factory() { return sk_make_sp<SkFontMgr_Mac>(); }
3024 
3025 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
3026