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