xref: /aosp_15_r20/external/skia/src/utils/mac/SkCTFont.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
11*c8dee2aaSAndroid Build Coastguard Worker 
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkOnce.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sfnt/SkOTTable_OS_2.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sfnt/SkSFNTHeader.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/mac/SkCTFont.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/mac/SkUniqueCFRef.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_MAC
21*c8dee2aaSAndroid Build Coastguard Worker #import <ApplicationServices/ApplicationServices.h>
22*c8dee2aaSAndroid Build Coastguard Worker #endif
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_IOS
25*c8dee2aaSAndroid Build Coastguard Worker #include <CoreText/CoreText.h>
26*c8dee2aaSAndroid Build Coastguard Worker #include <CoreText/CTFontManager.h>
27*c8dee2aaSAndroid Build Coastguard Worker #include <CoreGraphics/CoreGraphics.h>
28*c8dee2aaSAndroid Build Coastguard Worker #include <CoreFoundation/CoreFoundation.h>
29*c8dee2aaSAndroid Build Coastguard Worker #endif
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker #include <dlfcn.h>
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker static constexpr CGBitmapInfo kBitmapInfoRGB = ((CGBitmapInfo)kCGImageAlphaNoneSkipFirst |
34*c8dee2aaSAndroid Build Coastguard Worker                                                 kCGBitmapByteOrder32Host);
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker /** Drawn in FontForge, reduced with fonttools ttx, converted by xxd -i,
37*c8dee2aaSAndroid Build Coastguard Worker  *  this TrueType font contains a glyph of the spider.
38*c8dee2aaSAndroid Build Coastguard Worker  *
39*c8dee2aaSAndroid Build Coastguard Worker  *  To re-forge the original bytes of the TrueType font file,
40*c8dee2aaSAndroid Build Coastguard Worker  *  remove all ',|( +0x)' from this definition,
41*c8dee2aaSAndroid Build Coastguard Worker  *  copy the data to the clipboard,
42*c8dee2aaSAndroid Build Coastguard Worker  *  run 'pbpaste | xxd -p -r - spider.ttf'.
43*c8dee2aaSAndroid Build Coastguard Worker  */
44*c8dee2aaSAndroid Build Coastguard Worker static constexpr const uint8_t kSpiderSymbol_ttf[] = {
45*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x80, 0x00, 0x03, 0x00, 0x40,
46*c8dee2aaSAndroid Build Coastguard Worker     0x47, 0x44, 0x45, 0x46, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x07, 0xa8,
47*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x18, 0x4f, 0x53, 0x2f, 0x32, 0x8a, 0xf4, 0xfb, 0xdb,
48*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
49*c8dee2aaSAndroid Build Coastguard Worker     0xe0, 0x7f, 0x10, 0x7e, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x54,
50*c8dee2aaSAndroid Build Coastguard Worker     0x67, 0x61, 0x73, 0x70, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x07, 0xa0,
51*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x97, 0x0b, 0x6a, 0xf6,
52*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x40, 0x68, 0x65, 0x61, 0x64,
53*c8dee2aaSAndroid Build Coastguard Worker     0x0f, 0xa2, 0x24, 0x1a, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x36,
54*c8dee2aaSAndroid Build Coastguard Worker     0x68, 0x68, 0x65, 0x61, 0x0e, 0xd3, 0x07, 0x3f, 0x00, 0x00, 0x01, 0x04,
55*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0x10, 0x03, 0x00, 0x44,
56*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x0e, 0x6c, 0x6f, 0x63, 0x61,
57*c8dee2aaSAndroid Build Coastguard Worker     0x01, 0xb4, 0x00, 0x28, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x0a,
58*c8dee2aaSAndroid Build Coastguard Worker     0x6d, 0x61, 0x78, 0x70, 0x00, 0x4a, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x28,
59*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xc3, 0xe5, 0x39, 0xd4,
60*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x05, 0x58, 0x00, 0x00, 0x02, 0x28, 0x70, 0x6f, 0x73, 0x74,
61*c8dee2aaSAndroid Build Coastguard Worker     0xff, 0x03, 0x00, 0x67, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x20,
62*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0f, 0x08, 0x1d,
63*c8dee2aaSAndroid Build Coastguard Worker     0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
64*c8dee2aaSAndroid Build Coastguard Worker     0xd1, 0x97, 0xa8, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xe8, 0x32, 0x33,
65*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x08,
66*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
67*c8dee2aaSAndroid Build Coastguard Worker     0x05, 0x55, 0xff, 0x3b, 0x01, 0x79, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
68*c8dee2aaSAndroid Build Coastguard Worker     0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
70*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x04, 0x01, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
71*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x2e,
72*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x01, 0x90, 0x00, 0x05,
73*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x01, 0x1e, 0x05, 0x33,
74*c8dee2aaSAndroid Build Coastguard Worker     0x05, 0x99, 0x00, 0x00, 0x03, 0xd7, 0x00, 0x66, 0x02, 0x12, 0x00, 0x00,
75*c8dee2aaSAndroid Build Coastguard Worker     0x05, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x73, 0x6b, 0x69, 0x61, 0x00, 0xc0, 0x00, 0x00, 0xf0, 0x21,
78*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x66, 0xfe, 0x66, 0x01, 0x79, 0x05, 0x55, 0x00, 0xc5, 0x80, 0x00,
79*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x20, 0x00, 0x01, 0x08, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
81*c8dee2aaSAndroid Build Coastguard Worker     0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
82*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x48,
83*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00,
84*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x09, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21, 0xf0, 0x21, 0xff, 0xff,
85*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21,
86*c8dee2aaSAndroid Build Coastguard Worker     0xf0, 0x21, 0xff, 0xff, 0x00, 0x01, 0xff, 0xf9, 0xff, 0xf5, 0xff, 0xe4,
87*c8dee2aaSAndroid Build Coastguard Worker     0xff, 0xe2, 0x0f, 0xe2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
89*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x14, 0x00, 0x14, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44,
90*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x02, 0x64, 0x05, 0x55, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00,
91*c8dee2aaSAndroid Build Coastguard Worker     0x33, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x44, 0x02, 0x20, 0xfe,
92*c8dee2aaSAndroid Build Coastguard Worker     0x24, 0x01, 0x98, 0xfe, 0x68, 0x05, 0x55, 0xfa, 0xab, 0x44, 0x04, 0xcd,
93*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x04, 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x4c, 0x00, 0x15,
94*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x1d, 0x00, 0x25, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36,
95*c8dee2aaSAndroid Build Coastguard Worker     0x27, 0x26, 0x07, 0x06, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07,
96*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x32, 0x35, 0x34, 0x23, 0x22,
97*c8dee2aaSAndroid Build Coastguard Worker     0x15, 0x14, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0x03, 0x32,
98*c8dee2aaSAndroid Build Coastguard Worker     0x17, 0x30, 0x17, 0x31, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33,
99*c8dee2aaSAndroid Build Coastguard Worker     0x32, 0x33, 0x16, 0x33, 0x32, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27,
100*c8dee2aaSAndroid Build Coastguard Worker     0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
101*c8dee2aaSAndroid Build Coastguard Worker     0x1f, 0x02, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x17, 0x16, 0x33,
102*c8dee2aaSAndroid Build Coastguard Worker     0x16, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27, 0x27, 0x26, 0x23, 0x22,
103*c8dee2aaSAndroid Build Coastguard Worker     0x07, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x33, 0x32,
104*c8dee2aaSAndroid Build Coastguard Worker     0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x02, 0x16, 0x17, 0x16, 0x15,
105*c8dee2aaSAndroid Build Coastguard Worker     0x14, 0x23, 0x22, 0x27, 0x27, 0x26, 0x27, 0x27, 0x26, 0x27, 0x26, 0x07,
106*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07,
107*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x23, 0x22, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17,
108*c8dee2aaSAndroid Build Coastguard Worker     0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27,
109*c8dee2aaSAndroid Build Coastguard Worker     0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x07,
110*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x07, 0x06, 0x0f, 0x02, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34,
111*c8dee2aaSAndroid Build Coastguard Worker     0x37, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27,
112*c8dee2aaSAndroid Build Coastguard Worker     0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x07, 0x06, 0x23, 0x22,
113*c8dee2aaSAndroid Build Coastguard Worker     0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x37, 0x36, 0x37, 0x37, 0x36,
114*c8dee2aaSAndroid Build Coastguard Worker     0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26,
115*c8dee2aaSAndroid Build Coastguard Worker     0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x26,
116*c8dee2aaSAndroid Build Coastguard Worker     0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32,
117*c8dee2aaSAndroid Build Coastguard Worker     0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36,
118*c8dee2aaSAndroid Build Coastguard Worker     0x33, 0x04, 0xf5, 0x23, 0x13, 0x11, 0x14, 0x16, 0x1d, 0x1b, 0x4c, 0x1f,
119*c8dee2aaSAndroid Build Coastguard Worker     0x0e, 0x2d, 0x23, 0x14, 0x2c, 0x13, 0x18, 0x25, 0x2c, 0x10, 0x3c, 0x71,
120*c8dee2aaSAndroid Build Coastguard Worker     0x1d, 0x5c, 0x5c, 0x3f, 0xae, 0x5c, 0x5c, 0x3f, 0x6a, 0x27, 0x31, 0x5b,
121*c8dee2aaSAndroid Build Coastguard Worker     0x09, 0x27, 0x36, 0x03, 0x0a, 0x26, 0x35, 0x2e, 0x09, 0x08, 0xc6, 0x13,
122*c8dee2aaSAndroid Build Coastguard Worker     0x81, 0x17, 0x20, 0x18, 0x21, 0x1e, 0x04, 0x04, 0x15, 0x5c, 0x22, 0x26,
123*c8dee2aaSAndroid Build Coastguard Worker     0x48, 0x56, 0x3b, 0x10, 0x21, 0x01, 0x0c, 0x06, 0x06, 0x0f, 0x31, 0x44,
124*c8dee2aaSAndroid Build Coastguard Worker     0x3c, 0x52, 0x4a, 0x1d, 0x11, 0x3f, 0xb4, 0x71, 0x01, 0x26, 0x06, 0x0d,
125*c8dee2aaSAndroid Build Coastguard Worker     0x15, 0x1a, 0x2a, 0x13, 0x53, 0xaa, 0x42, 0x1d, 0x0a, 0x33, 0x20, 0x21,
126*c8dee2aaSAndroid Build Coastguard Worker     0x2b, 0x01, 0x02, 0x3e, 0x21, 0x09, 0x02, 0x02, 0x0f, 0x2d, 0x4b, 0x0a,
127*c8dee2aaSAndroid Build Coastguard Worker     0x22, 0x15, 0x20, 0x1f, 0x72, 0x8b, 0x2d, 0x2f, 0x1d, 0x1f, 0x0e, 0x25,
128*c8dee2aaSAndroid Build Coastguard Worker     0x3f, 0x4d, 0x1b, 0x63, 0x2a, 0x2c, 0x14, 0x22, 0x18, 0x1c, 0x0f, 0x08,
129*c8dee2aaSAndroid Build Coastguard Worker     0x2a, 0x08, 0x08, 0x0d, 0x3b, 0x4c, 0x52, 0x74, 0x27, 0x71, 0x2e, 0x01,
130*c8dee2aaSAndroid Build Coastguard Worker     0x0c, 0x10, 0x15, 0x0d, 0x06, 0x0d, 0x05, 0x01, 0x06, 0x2c, 0x28, 0x14,
131*c8dee2aaSAndroid Build Coastguard Worker     0x1b, 0x05, 0x04, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x16, 0x27, 0x03, 0x0d,
132*c8dee2aaSAndroid Build Coastguard Worker     0x30, 0x4c, 0x4c, 0x4b, 0x1f, 0x0b, 0x22, 0x26, 0x0d, 0x15, 0x0d, 0x2d,
133*c8dee2aaSAndroid Build Coastguard Worker     0x68, 0x34, 0x14, 0x3c, 0x25, 0x12, 0x04, 0x10, 0x18, 0x0b, 0x09, 0x30,
134*c8dee2aaSAndroid Build Coastguard Worker     0x2b, 0x44, 0x66, 0x14, 0x47, 0x47, 0x59, 0x73, 0x25, 0x05, 0x03, 0x1f,
135*c8dee2aaSAndroid Build Coastguard Worker     0x01, 0x08, 0x3f, 0x48, 0x4b, 0x4b, 0x76, 0x2f, 0x49, 0x2d, 0x22, 0x24,
136*c8dee2aaSAndroid Build Coastguard Worker     0x0c, 0x15, 0x08, 0x0e, 0x33, 0x03, 0x44, 0x4c, 0x10, 0x46, 0x13, 0x1f,
137*c8dee2aaSAndroid Build Coastguard Worker     0x27, 0x1b, 0x1d, 0x13, 0x02, 0x24, 0x08, 0x02, 0x42, 0x0e, 0x4d, 0x3c,
138*c8dee2aaSAndroid Build Coastguard Worker     0x19, 0x1b, 0x40, 0x2b, 0x2b, 0x1e, 0x16, 0x11, 0x04, 0x1f, 0x11, 0x04,
139*c8dee2aaSAndroid Build Coastguard Worker     0x18, 0x11, 0x35, 0x01, 0xa3, 0x13, 0x24, 0x1f, 0x0b, 0x0c, 0x19, 0x19,
140*c8dee2aaSAndroid Build Coastguard Worker     0x18, 0x13, 0x0f, 0x0c, 0x1a, 0x18, 0x1f, 0x19, 0x1e, 0x07, 0x1a, 0xc3,
141*c8dee2aaSAndroid Build Coastguard Worker     0x54, 0x51, 0x54, 0x51, 0x04, 0x53, 0x51, 0x54, 0x50, 0x02, 0x48, 0x1a,
142*c8dee2aaSAndroid Build Coastguard Worker     0x31, 0x18, 0x55, 0x74, 0x04, 0x0e, 0x09, 0x0d, 0x06, 0x10, 0x16, 0x1b,
143*c8dee2aaSAndroid Build Coastguard Worker     0x24, 0x01, 0x04, 0x0b, 0x04, 0x10, 0x3f, 0x0a, 0x41, 0x02, 0x41, 0x20,
144*c8dee2aaSAndroid Build Coastguard Worker     0x06, 0x12, 0x16, 0x21, 0x17, 0x2a, 0x1e, 0x15, 0x40, 0x27, 0x11, 0x0e,
145*c8dee2aaSAndroid Build Coastguard Worker     0x1e, 0x11, 0x15, 0x1f, 0x43, 0x13, 0x1a, 0x10, 0x15, 0x1b, 0x04, 0x09,
146*c8dee2aaSAndroid Build Coastguard Worker     0x4d, 0x2a, 0x0f, 0x19, 0x0a, 0x0a, 0x03, 0x05, 0x15, 0x3c, 0x64, 0x21,
147*c8dee2aaSAndroid Build Coastguard Worker     0x4b, 0x2e, 0x21, 0x28, 0x13, 0x47, 0x44, 0x19, 0x3f, 0x11, 0x18, 0x0b,
148*c8dee2aaSAndroid Build Coastguard Worker     0x0a, 0x07, 0x18, 0x0d, 0x07, 0x24, 0x2c, 0x2b, 0x21, 0x32, 0x10, 0x48,
149*c8dee2aaSAndroid Build Coastguard Worker     0x2a, 0x2d, 0x1e, 0x1a, 0x01, 0x0c, 0x43, 0x59, 0x28, 0x4e, 0x1c, 0x0d,
150*c8dee2aaSAndroid Build Coastguard Worker     0x5d, 0x24, 0x14, 0x0a, 0x05, 0x1f, 0x24, 0x32, 0x46, 0x3e, 0x5f, 0x3e,
151*c8dee2aaSAndroid Build Coastguard Worker     0x44, 0x1a, 0x30, 0x15, 0x0d, 0x07, 0x18, 0x2b, 0x03, 0x0d, 0x1a, 0x28,
152*c8dee2aaSAndroid Build Coastguard Worker     0x28, 0x57, 0xb2, 0x29, 0x27, 0x40, 0x2c, 0x23, 0x16, 0x63, 0x58, 0x1a,
153*c8dee2aaSAndroid Build Coastguard Worker     0x0a, 0x18, 0x11, 0x23, 0x08, 0x1b, 0x29, 0x05, 0x04, 0x0b, 0x15, 0x0d,
154*c8dee2aaSAndroid Build Coastguard Worker     0x14, 0x0b, 0x2a, 0x29, 0x5a, 0x62, 0x01, 0x19, 0x1e, 0x05, 0x05, 0x26,
155*c8dee2aaSAndroid Build Coastguard Worker     0x42, 0x42, 0x2a, 0x2a, 0x3f, 0x0d, 0x0f, 0x09, 0x05, 0x07, 0x01, 0x0b,
156*c8dee2aaSAndroid Build Coastguard Worker     0x25, 0x3e, 0x0d, 0x17, 0x11, 0x01, 0x03, 0x0d, 0x13, 0x20, 0x19, 0x11,
157*c8dee2aaSAndroid Build Coastguard Worker     0x03, 0x02, 0x01, 0x04, 0x11, 0x04, 0x05, 0x1b, 0x3d, 0x10, 0x29, 0x20,
158*c8dee2aaSAndroid Build Coastguard Worker     0x04, 0x04, 0x0a, 0x07, 0x04, 0x1f, 0x15, 0x20, 0x3e, 0x0f, 0x2a, 0x1e,
159*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x1b, 0x01, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
160*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
161*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x01, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
162*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x02, 0x00, 0x07, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
163*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
164*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x04, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
165*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x05, 0x00, 0x02, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
166*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x06, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
167*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
168*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0e, 0x00, 0x1a, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
169*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
170*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
171*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
172*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
173*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
174*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
175*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
176*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
177*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
178*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
179*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
180*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
181*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
182*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
183*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
184*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
185*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
186*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
187*c8dee2aaSAndroid Build Coastguard Worker     0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35,
188*c8dee2aaSAndroid Build Coastguard Worker     0x2c, 0x20, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x53, 0x70, 0x69,
189*c8dee2aaSAndroid Build Coastguard Worker     0x64, 0x65, 0x72, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x52, 0x65, 0x67,
190*c8dee2aaSAndroid Build Coastguard Worker     0x75, 0x6c, 0x61, 0x72, 0x56, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
191*c8dee2aaSAndroid Build Coastguard Worker     0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x2e, 0x73, 0x69, 0x6c,
192*c8dee2aaSAndroid Build Coastguard Worker     0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x4f, 0x46, 0x4c, 0x00, 0x43, 0x00, 0x6f,
193*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68,
194*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20,
195*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x20,
196*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65,
197*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x2e, 0x00, 0x53, 0x00, 0x70, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65,
198*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x72, 0x00, 0x53, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f,
199*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x6c, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c,
200*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x31, 0x00, 0x68, 0x00, 0x74,
201*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x73,
202*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x73,
203*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x2e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6f,
204*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x72, 0x00, 0x67, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x4c,
205*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x66,
206*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
208*c8dee2aaSAndroid Build Coastguard Worker     0xff, 0xff, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
210*c8dee2aaSAndroid Build Coastguard Worker     0x00, 0x02, 0x00, 0x00
211*c8dee2aaSAndroid Build Coastguard Worker };
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker /**
214*c8dee2aaSAndroid Build Coastguard Worker  * There does not appear to be a publicly accessible API for determining if lcd
215*c8dee2aaSAndroid Build Coastguard Worker  * font smoothing will be applied if we request it. The main issue is that if
216*c8dee2aaSAndroid Build Coastguard Worker  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
217*c8dee2aaSAndroid Build Coastguard Worker  */
SkCTFontGetSmoothBehavior()218*c8dee2aaSAndroid Build Coastguard Worker SkCTFontSmoothBehavior SkCTFontGetSmoothBehavior() {
219*c8dee2aaSAndroid Build Coastguard Worker     static SkCTFontSmoothBehavior gSmoothBehavior = []{
220*c8dee2aaSAndroid Build Coastguard Worker         uint32_t noSmoothBitmap[16][16] = {};
221*c8dee2aaSAndroid Build Coastguard Worker         uint32_t smoothBitmap[16][16] = {};
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
224*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CGContextRef> noSmoothContext(
225*c8dee2aaSAndroid Build Coastguard Worker                 CGBitmapContextCreate(&noSmoothBitmap, 16, 16, 8, 16*4,
226*c8dee2aaSAndroid Build Coastguard Worker                                       colorspace.get(), kBitmapInfoRGB));
227*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CGContextRef> smoothContext(
228*c8dee2aaSAndroid Build Coastguard Worker                 CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
229*c8dee2aaSAndroid Build Coastguard Worker                                       colorspace.get(), kBitmapInfoRGB));
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CFDataRef> data(CFDataCreateWithBytesNoCopy(
232*c8dee2aaSAndroid Build Coastguard Worker                 kCFAllocatorDefault, kSpiderSymbol_ttf, std::size(kSpiderSymbol_ttf),
233*c8dee2aaSAndroid Build Coastguard Worker                 kCFAllocatorNull));
234*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CTFontDescriptorRef> desc(
235*c8dee2aaSAndroid Build Coastguard Worker                 CTFontManagerCreateFontDescriptorFromData(data.get()));
236*c8dee2aaSAndroid Build Coastguard Worker         SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc.get(), 16, nullptr));
237*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(ctFont);
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
240*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetShouldAntialias(noSmoothContext.get(), true);
241*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetTextDrawingMode(noSmoothContext.get(), kCGTextFill);
242*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetGrayFillColor(noSmoothContext.get(), 1, 1);
243*c8dee2aaSAndroid Build Coastguard Worker 
244*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetShouldSmoothFonts(smoothContext.get(), true);
245*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetShouldAntialias(smoothContext.get(), true);
246*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetTextDrawingMode(smoothContext.get(), kCGTextFill);
247*c8dee2aaSAndroid Build Coastguard Worker         CGContextSetGrayFillColor(smoothContext.get(), 1, 1);
248*c8dee2aaSAndroid Build Coastguard Worker 
249*c8dee2aaSAndroid Build Coastguard Worker         CGPoint point = CGPointMake(0, 3);
250*c8dee2aaSAndroid Build Coastguard Worker         CGGlyph spiderGlyph = 3;
251*c8dee2aaSAndroid Build Coastguard Worker         CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, noSmoothContext.get());
252*c8dee2aaSAndroid Build Coastguard Worker         CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, smoothContext.get());
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker         // For debugging.
255*c8dee2aaSAndroid Build Coastguard Worker         //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(noSmoothContext()));
256*c8dee2aaSAndroid Build Coastguard Worker         //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(smoothContext()));
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker         SkCTFontSmoothBehavior smoothBehavior = SkCTFontSmoothBehavior::none;
259*c8dee2aaSAndroid Build Coastguard Worker         for (int x = 0; x < 16; ++x) {
260*c8dee2aaSAndroid Build Coastguard Worker             for (int y = 0; y < 16; ++y) {
261*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t smoothPixel = smoothBitmap[x][y];
262*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t r = (smoothPixel >> 16) & 0xFF;
263*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t g = (smoothPixel >>  8) & 0xFF;
264*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t b = (smoothPixel >>  0) & 0xFF;
265*c8dee2aaSAndroid Build Coastguard Worker                 if (r != g || r != b) {
266*c8dee2aaSAndroid Build Coastguard Worker                     return SkCTFontSmoothBehavior::subpixel;
267*c8dee2aaSAndroid Build Coastguard Worker                 }
268*c8dee2aaSAndroid Build Coastguard Worker                 if (noSmoothBitmap[x][y] != smoothPixel) {
269*c8dee2aaSAndroid Build Coastguard Worker                     smoothBehavior = SkCTFontSmoothBehavior::some;
270*c8dee2aaSAndroid Build Coastguard Worker                 }
271*c8dee2aaSAndroid Build Coastguard Worker             }
272*c8dee2aaSAndroid Build Coastguard Worker         }
273*c8dee2aaSAndroid Build Coastguard Worker         return smoothBehavior;
274*c8dee2aaSAndroid Build Coastguard Worker     }();
275*c8dee2aaSAndroid Build Coastguard Worker     return gSmoothBehavior;
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker 
SkCTFontGetNSFontWeightMapping()278*c8dee2aaSAndroid Build Coastguard Worker SkCTFontWeightMapping& SkCTFontGetNSFontWeightMapping() {
279*c8dee2aaSAndroid Build Coastguard Worker     // In the event something goes wrong finding the real values, use this mapping.
280*c8dee2aaSAndroid Build Coastguard Worker     static constexpr CGFloat defaultNSFontWeights[] =
281*c8dee2aaSAndroid Build Coastguard Worker         { -1.00, -0.80, -0.60, -0.40, 0.00, 0.23, 0.30, 0.40, 0.56, 0.62, 1.00 };
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker     // Declarations in <AppKit/AppKit.h> on macOS, <UIKit/UIKit.h> on iOS
284*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_MAC
285*c8dee2aaSAndroid Build Coastguard Worker #  define SK_KIT_FONT_WEIGHT_PREFIX "NS"
286*c8dee2aaSAndroid Build Coastguard Worker #endif
287*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_IOS
288*c8dee2aaSAndroid Build Coastguard Worker #  define SK_KIT_FONT_WEIGHT_PREFIX "UI"
289*c8dee2aaSAndroid Build Coastguard Worker #endif
290*c8dee2aaSAndroid Build Coastguard Worker     static constexpr const char* nsFontWeightNames[] = {
291*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightUltraLight",
292*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightThin",
293*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightLight",
294*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightRegular",
295*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightMedium",
296*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightSemibold",
297*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBold",
298*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightHeavy",
299*c8dee2aaSAndroid Build Coastguard Worker         SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBlack",
300*c8dee2aaSAndroid Build Coastguard Worker     };
301*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(nsFontWeightNames) == 9, "");
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker     static CGFloat nsFontWeights[11];
304*c8dee2aaSAndroid Build Coastguard Worker     static const CGFloat (*selectedNSFontWeights)[11] = &defaultNSFontWeights;
305*c8dee2aaSAndroid Build Coastguard Worker     static SkOnce once;
306*c8dee2aaSAndroid Build Coastguard Worker     once([&] {
307*c8dee2aaSAndroid Build Coastguard Worker         size_t i = 0;
308*c8dee2aaSAndroid Build Coastguard Worker         nsFontWeights[i++] = -1.00;
309*c8dee2aaSAndroid Build Coastguard Worker         for (const char* nsFontWeightName : nsFontWeightNames) {
310*c8dee2aaSAndroid Build Coastguard Worker             void* nsFontWeightValuePtr = dlsym(RTLD_DEFAULT, nsFontWeightName);
311*c8dee2aaSAndroid Build Coastguard Worker             if (nsFontWeightValuePtr) {
312*c8dee2aaSAndroid Build Coastguard Worker                 nsFontWeights[i++] = *(static_cast<CGFloat*>(nsFontWeightValuePtr));
313*c8dee2aaSAndroid Build Coastguard Worker             } else {
314*c8dee2aaSAndroid Build Coastguard Worker                 return;
315*c8dee2aaSAndroid Build Coastguard Worker             }
316*c8dee2aaSAndroid Build Coastguard Worker         }
317*c8dee2aaSAndroid Build Coastguard Worker         nsFontWeights[i++] = 1.00;
318*c8dee2aaSAndroid Build Coastguard Worker         selectedNSFontWeights = &nsFontWeights;
319*c8dee2aaSAndroid Build Coastguard Worker     });
320*c8dee2aaSAndroid Build Coastguard Worker     return *selectedNSFontWeights;
321*c8dee2aaSAndroid Build Coastguard Worker }
322*c8dee2aaSAndroid Build Coastguard Worker 
SkCTFontGetDataFontWeightMapping()323*c8dee2aaSAndroid Build Coastguard Worker SkCTFontWeightMapping& SkCTFontGetDataFontWeightMapping() {
324*c8dee2aaSAndroid Build Coastguard Worker     // In the event something goes wrong finding the real values, use this mapping.
325*c8dee2aaSAndroid Build Coastguard Worker     // These were the values from macOS 10.13 to 10.15.
326*c8dee2aaSAndroid Build Coastguard Worker     static constexpr CGFloat defaultDataFontWeights[] =
327*c8dee2aaSAndroid Build Coastguard Worker         { -1.00, -0.70, -0.50, -0.23, 0.00, 0.20, 0.30, 0.40, 0.60, 0.80, 1.00 };
328*c8dee2aaSAndroid Build Coastguard Worker 
329*c8dee2aaSAndroid Build Coastguard Worker     static const CGFloat (*selectedDataFontWeights)[11] = &defaultDataFontWeights;
330*c8dee2aaSAndroid Build Coastguard Worker     static CGFloat dataFontWeights[11];
331*c8dee2aaSAndroid Build Coastguard Worker     static SkOnce once;
332*c8dee2aaSAndroid Build Coastguard Worker     once([&] {
333*c8dee2aaSAndroid Build Coastguard Worker         constexpr size_t dataSize = std::size(kSpiderSymbol_ttf);
334*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkData> data = SkData::MakeWithCopy(kSpiderSymbol_ttf, dataSize);
335*c8dee2aaSAndroid Build Coastguard Worker         const SkSFNTHeader* sfntHeader = reinterpret_cast<const SkSFNTHeader*>(data->data());
336*c8dee2aaSAndroid Build Coastguard Worker         const SkSFNTHeader::TableDirectoryEntry* tableEntry =
337*c8dee2aaSAndroid Build Coastguard Worker             SkTAfter<const SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
338*c8dee2aaSAndroid Build Coastguard Worker         const SkSFNTHeader::TableDirectoryEntry* os2TableEntry = nullptr;
339*c8dee2aaSAndroid Build Coastguard Worker         int numTables = SkEndian_SwapBE16(sfntHeader->numTables);
340*c8dee2aaSAndroid Build Coastguard Worker         for (int tableEntryIndex = 0; tableEntryIndex < numTables; ++tableEntryIndex) {
341*c8dee2aaSAndroid Build Coastguard Worker             if (SkOTTableOS2::TAG == tableEntry[tableEntryIndex].tag) {
342*c8dee2aaSAndroid Build Coastguard Worker                 os2TableEntry = tableEntry + tableEntryIndex;
343*c8dee2aaSAndroid Build Coastguard Worker                 break;
344*c8dee2aaSAndroid Build Coastguard Worker             }
345*c8dee2aaSAndroid Build Coastguard Worker         }
346*c8dee2aaSAndroid Build Coastguard Worker         if (!os2TableEntry) {
347*c8dee2aaSAndroid Build Coastguard Worker             return;
348*c8dee2aaSAndroid Build Coastguard Worker         }
349*c8dee2aaSAndroid Build Coastguard Worker         size_t os2TableOffset = SkEndian_SwapBE32(os2TableEntry->offset);
350*c8dee2aaSAndroid Build Coastguard Worker         SkOTTableOS2_V0* os2Table = SkTAddOffset<SkOTTableOS2_V0>(data->writable_data(),
351*c8dee2aaSAndroid Build Coastguard Worker                                                                   os2TableOffset);
352*c8dee2aaSAndroid Build Coastguard Worker 
353*c8dee2aaSAndroid Build Coastguard Worker         CGFloat previousWeight = -CGFLOAT_MAX;
354*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < 11; ++i) {
355*c8dee2aaSAndroid Build Coastguard Worker             os2Table->usWeightClass.value = SkEndian_SwapBE16(i * 100);
356*c8dee2aaSAndroid Build Coastguard Worker 
357*c8dee2aaSAndroid Build Coastguard Worker             // On macOS 10.14 and earlier it appears that the CFDataGetBytePtr is used somehow in
358*c8dee2aaSAndroid Build Coastguard Worker             // font caching. Creating a slightly modified font with data at the same address seems
359*c8dee2aaSAndroid Build Coastguard Worker             // to in some ways act like a font previously created at that address. As a result,
360*c8dee2aaSAndroid Build Coastguard Worker             // always make a copy of the data.
361*c8dee2aaSAndroid Build Coastguard Worker             SkUniqueCFRef<CFDataRef> cfData(
362*c8dee2aaSAndroid Build Coastguard Worker                     CFDataCreate(kCFAllocatorDefault, (const UInt8 *)data->data(), data->size()));
363*c8dee2aaSAndroid Build Coastguard Worker             if (!cfData) {
364*c8dee2aaSAndroid Build Coastguard Worker                 return;
365*c8dee2aaSAndroid Build Coastguard Worker             }
366*c8dee2aaSAndroid Build Coastguard Worker             SkUniqueCFRef<CTFontDescriptorRef> desc(
367*c8dee2aaSAndroid Build Coastguard Worker                     CTFontManagerCreateFontDescriptorFromData(cfData.get()));
368*c8dee2aaSAndroid Build Coastguard Worker             if (!desc) {
369*c8dee2aaSAndroid Build Coastguard Worker                 return;
370*c8dee2aaSAndroid Build Coastguard Worker             }
371*c8dee2aaSAndroid Build Coastguard Worker 
372*c8dee2aaSAndroid Build Coastguard Worker             // On macOS 10.14 and earlier, the CTFontDescriptorRef returned from
373*c8dee2aaSAndroid Build Coastguard Worker             // CTFontManagerCreateFontDescriptorFromData is incomplete and does not have the
374*c8dee2aaSAndroid Build Coastguard Worker             // correct traits. It is necessary to create the CTFont and then get the descriptor
375*c8dee2aaSAndroid Build Coastguard Worker             // off of it.
376*c8dee2aaSAndroid Build Coastguard Worker             SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc.get(), 9, nullptr));
377*c8dee2aaSAndroid Build Coastguard Worker             if (!ctFont) {
378*c8dee2aaSAndroid Build Coastguard Worker                 return;
379*c8dee2aaSAndroid Build Coastguard Worker             }
380*c8dee2aaSAndroid Build Coastguard Worker             SkUniqueCFRef<CTFontDescriptorRef> desc2(CTFontCopyFontDescriptor(ctFont.get()));
381*c8dee2aaSAndroid Build Coastguard Worker             if (!desc2) {
382*c8dee2aaSAndroid Build Coastguard Worker                 return;
383*c8dee2aaSAndroid Build Coastguard Worker             }
384*c8dee2aaSAndroid Build Coastguard Worker 
385*c8dee2aaSAndroid Build Coastguard Worker             SkUniqueCFRef<CFTypeRef> traitsRef(
386*c8dee2aaSAndroid Build Coastguard Worker                     CTFontDescriptorCopyAttribute(desc2.get(), kCTFontTraitsAttribute));
387*c8dee2aaSAndroid Build Coastguard Worker             if (!traitsRef || CFGetTypeID(traitsRef.get()) != CFDictionaryGetTypeID()) {
388*c8dee2aaSAndroid Build Coastguard Worker                 return;
389*c8dee2aaSAndroid Build Coastguard Worker             }
390*c8dee2aaSAndroid Build Coastguard Worker             CFDictionaryRef fontTraitsDict = static_cast<CFDictionaryRef>(traitsRef.get());
391*c8dee2aaSAndroid Build Coastguard Worker 
392*c8dee2aaSAndroid Build Coastguard Worker             CFTypeRef weightRef;
393*c8dee2aaSAndroid Build Coastguard Worker             if (!CFDictionaryGetValueIfPresent(fontTraitsDict, kCTFontWeightTrait, &weightRef) ||
394*c8dee2aaSAndroid Build Coastguard Worker                 !weightRef)
395*c8dee2aaSAndroid Build Coastguard Worker             {
396*c8dee2aaSAndroid Build Coastguard Worker                 return;
397*c8dee2aaSAndroid Build Coastguard Worker             }
398*c8dee2aaSAndroid Build Coastguard Worker 
399*c8dee2aaSAndroid Build Coastguard Worker             // It is possible there is a kCTFontWeightTrait entry, but it is not a CFNumberRef.
400*c8dee2aaSAndroid Build Coastguard Worker             // This is usually due to a bug with the handling of 0, so set the default to 0.
401*c8dee2aaSAndroid Build Coastguard Worker             // See https://crbug.com/1372420
402*c8dee2aaSAndroid Build Coastguard Worker             CGFloat weight = 0;
403*c8dee2aaSAndroid Build Coastguard Worker             if (CFGetTypeID(weightRef) == CFNumberGetTypeID()) {
404*c8dee2aaSAndroid Build Coastguard Worker                 CFNumberRef weightNumber = static_cast<CFNumberRef>(weightRef);
405*c8dee2aaSAndroid Build Coastguard Worker                 if (!CFNumberIsFloatType(weightNumber) ||
406*c8dee2aaSAndroid Build Coastguard Worker                     !CFNumberGetValue(weightNumber, kCFNumberCGFloatType, &weight))
407*c8dee2aaSAndroid Build Coastguard Worker                 {
408*c8dee2aaSAndroid Build Coastguard Worker                     // CFNumberGetValue may modify `weight` even when returning `false`.
409*c8dee2aaSAndroid Build Coastguard Worker                     weight = 0;
410*c8dee2aaSAndroid Build Coastguard Worker                 }
411*c8dee2aaSAndroid Build Coastguard Worker             }
412*c8dee2aaSAndroid Build Coastguard Worker 
413*c8dee2aaSAndroid Build Coastguard Worker             // It is expected that the weights will be strictly monotonically increasing.
414*c8dee2aaSAndroid Build Coastguard Worker             if (weight <= previousWeight) {
415*c8dee2aaSAndroid Build Coastguard Worker                 return;
416*c8dee2aaSAndroid Build Coastguard Worker             }
417*c8dee2aaSAndroid Build Coastguard Worker             previousWeight = weight;
418*c8dee2aaSAndroid Build Coastguard Worker             dataFontWeights[i] = weight;
419*c8dee2aaSAndroid Build Coastguard Worker         }
420*c8dee2aaSAndroid Build Coastguard Worker         selectedDataFontWeights = &dataFontWeights;
421*c8dee2aaSAndroid Build Coastguard Worker     });
422*c8dee2aaSAndroid Build Coastguard Worker     return *selectedDataFontWeights;
423*c8dee2aaSAndroid Build Coastguard Worker }
424*c8dee2aaSAndroid Build Coastguard Worker 
425*c8dee2aaSAndroid Build Coastguard Worker #endif
426