• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google Inc.
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 #include "include/core/SkFontScanner.h"
8 #include "src/base/SkAutoMalloc.h"
9 #include "src/core/SkTHash.h"
10 #include "src/core/SkWriteBuffer.h"
11 
12 #include "tests/FontScanner.h"
13 #include "tests/Test.h"
14 #include "tools/Resources.h"
15 #include "tools/fonts/FontToolUtils.h"
16 
FontScanner_VariableFont(skiatest::Reporter * reporter,SkFontScanner * scanner)17 void FontScanner_VariableFont(skiatest::Reporter* reporter,
18                                      SkFontScanner* scanner) {
19     SkString name = GetResourcePath("fonts/Variable.ttf");
20 
21     std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(name.c_str());
22     if (!stream) {
23          REPORTER_ASSERT(reporter, false, "Cannot open the font file %s\n", name.c_str());
24     }
25 
26     int numFaces;
27     if (!scanner->scanFile(stream.get(), &numFaces)) {
28          REPORTER_ASSERT(reporter, false, "Cannot scanFile\n");
29     }
30     REPORTER_ASSERT(reporter, numFaces == 1);
31 
32     skia_private::THashSet<SkFontStyle> uniqueStyles;
33     for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
34         int numInstances;
35         if (!scanner->scanFace(stream.get(), faceIndex, &numInstances)) {
36             REPORTER_ASSERT(reporter, false, "Cannot scanFace\n");
37             continue;
38         }
39 
40         REPORTER_ASSERT(reporter, numInstances == 5);
41         // Not including the default instance
42         for (int instanceIndex = 1; instanceIndex <= numInstances; ++instanceIndex) {
43             bool isFixedPitch;
44             SkString realName;
45             SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
46             if (!scanner->scanInstance(stream.get(), faceIndex, instanceIndex,
47                                        &realName, &style, &isFixedPitch,
48                                        nullptr, nullptr)) {
49                 REPORTER_ASSERT(reporter,
50                                 false,
51                                 "Cannot scanInstance %s %d\n",
52                                 name.c_str(),
53                                 faceIndex);
54                 continue;
55             } else {
56                 if (instanceIndex == 0) {
57                     // Do not add it to the set
58                 } else if (uniqueStyles.find(style) == nullptr) {
59                     uniqueStyles.add(style);
60                 } else {
61                     REPORTER_ASSERT(
62                         reporter,
63                         false,
64                         "Font: %s (%d %d %d)\n",
65                             realName.c_str(), style.weight(), style.width(), style.slant());
66                 }
67             }
68         }
69         REPORTER_ASSERT(reporter, uniqueStyles.count() == numInstances);
70     }
71 }
72 
FontScanner_NamedInstances1(skiatest::Reporter * reporter,SkFontScanner * scanner)73 void FontScanner_NamedInstances1(skiatest::Reporter* reporter, SkFontScanner* scanner) {
74     SkString name = GetResourcePath("fonts/Variable.ttf");
75 
76     std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(name.c_str());
77     if (!stream) {
78         REPORTER_ASSERT(reporter, false, "Cannot open the font file %s\n", name.c_str());
79     }
80 
81     int numFaces;
82     if (!scanner->scanFile(stream.get(), &numFaces)) {
83         REPORTER_ASSERT(reporter, false, "Cannot scanFile\n");
84     }
85     REPORTER_ASSERT(reporter, numFaces == 1);
86 
87     skia_private::THashSet<SkFontStyle> uniqueStyles;
88     for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
89         int numInstances;
90         if (!scanner->scanFace(stream.get(), faceIndex, &numInstances)) {
91             REPORTER_ASSERT(reporter, false, "Cannot scanFace\n");
92             continue;
93         }
94         REPORTER_ASSERT(reporter, numInstances == 5);
95         // Not including the default instance (most time it will be listed anyway)
96         for (int instanceIndex = 1; instanceIndex <= numInstances; ++instanceIndex) {
97             bool isFixedPitch;
98             SkString realName;
99             SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
100             SkFontScanner::AxisDefinitions axes;
101             if (!scanner->scanInstance(stream.get(), faceIndex, instanceIndex,
102                                        &realName, &style, &isFixedPitch,
103                                        &axes, nullptr)) {
104                 REPORTER_ASSERT(reporter,
105                                 false,
106                                 "Cannot scanInstance %s %d\n",
107                                 name.c_str(),
108                                 faceIndex);
109                 continue;
110             } else {
111                 if (uniqueStyles.find(style) == nullptr) {
112                     uniqueStyles.add(style);
113                     REPORTER_ASSERT(reporter, axes.size() == 2);
114                     if (instanceIndex == 5) {
115                         SkFourByteTag weight = SkSetFourByteTag('w', 'g', 'h', 't');
116                         SkFourByteTag width = SkSetFourByteTag('w', 'd', 't', 'h');
117                         REPORTER_ASSERT(reporter, axes[0].tag == weight);
118                         REPORTER_ASSERT(reporter, axes[0].def == 400.0f);
119                         REPORTER_ASSERT(reporter, axes[0].min == 100.0f);
120                         REPORTER_ASSERT(reporter, axes[0].max == 900.0f);
121                         REPORTER_ASSERT(reporter, axes[1].tag == width);
122                         REPORTER_ASSERT(reporter, axes[1].def == 100.0f);
123                         REPORTER_ASSERT(reporter, axes[1].min == 050.0f);
124                         REPORTER_ASSERT(reporter, axes[1].max == 200.0f);
125                     }
126                 } else {
127                     REPORTER_ASSERT(reporter,
128                                     false,
129                                     "Font #%d: %s (%d %d %d)\n",
130                                     instanceIndex,
131                                     realName.c_str(),
132                                     style.weight(),
133                                     style.width(),
134                                     style.slant());
135                 }
136             }
137         }
138     }
139 }
140 
FontScanner_NamedInstances2(skiatest::Reporter * reporter,SkFontScanner * scanner)141 void FontScanner_NamedInstances2(skiatest::Reporter* reporter, SkFontScanner* scanner) {
142     SkString name = GetResourcePath("fonts/VaryAlongQuads.ttf");
143 
144     std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(name.c_str());
145     if (!stream) {
146         REPORTER_ASSERT(reporter, false, "Cannot open the font file %s\n", name.c_str());
147     }
148 
149     int numFaces;
150     if (!scanner->scanFile(stream.get(), &numFaces)) {
151         REPORTER_ASSERT(reporter, false, "Cannot scanFile\n");
152     }
153     REPORTER_ASSERT(reporter, numFaces == 1);
154 
155     for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
156         int numInstances;
157         if (!scanner->scanFace(stream.get(), faceIndex, &numInstances)) {
158             REPORTER_ASSERT(reporter, false, "Cannot scanFace\n");
159             continue;
160         }
161         REPORTER_ASSERT(reporter, numInstances == 3);
162         // Not including the default instance (most time it will be listed anyway)
163         for (int instanceIndex = 1; instanceIndex <= numInstances; ++instanceIndex) {
164             bool isFixedPitch;
165             SkString realName;
166             SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
167             SkFontScanner::AxisDefinitions axes;
168             if (!scanner->scanInstance(stream.get(), faceIndex, instanceIndex,
169                                        &realName, &style, &isFixedPitch,
170                                        &axes, nullptr)) {
171                 REPORTER_ASSERT(reporter,
172                                 false,
173                                 "Cannot scanInstance %s %d\n",
174                                 name.c_str(),
175                                 faceIndex);
176                 continue;
177             }
178             REPORTER_ASSERT(reporter, axes.size() == 2);
179             SkFourByteTag weight = SkSetFourByteTag('w', 'g', 'h', 't');
180             for (auto i = 0; i < axes.size(); ++i) {
181                 const auto& axis = axes[i];
182                 REPORTER_ASSERT(reporter, (instanceIndex != 1) || (style.weight() == 100.0f));
183                 REPORTER_ASSERT(reporter, (instanceIndex != 2) || (style.weight() == 400.0f));
184                 REPORTER_ASSERT(reporter, (instanceIndex != 3) || (style.weight() == 900.0f));
185                 REPORTER_ASSERT(reporter, axis.tag == weight);
186                 REPORTER_ASSERT(reporter, axis.def == 400.0f);
187                 REPORTER_ASSERT(reporter, axis.min == 100.0f);
188                 REPORTER_ASSERT(reporter, axis.max == 900.0f);
189             }
190         }
191     }
192 }
193 
FontScanner_FontCollection(skiatest::Reporter * reporter,SkFontScanner * scanner)194 void FontScanner_FontCollection(skiatest::Reporter* reporter, SkFontScanner* scanner) {
195     SkString name = SkString("fonts/test.ttc");
196     std::unique_ptr<SkStreamAsset> stream = GetResourceAsStream(name.c_str());
197     if (!stream) {
198         REPORTER_ASSERT(reporter, false, "Cannot open the font file %s\n", name.c_str());
199     }
200 
201     int numFaces;
202     if (!scanner->scanFile(stream.get(), &numFaces)) {
203         REPORTER_ASSERT(reporter, false, "Cannot scanFile\n");
204     }
205     REPORTER_ASSERT(reporter, numFaces == 2);
206 
207     for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
208         int numInstances;
209         if (!scanner->scanFace(stream.get(), faceIndex, &numInstances)) {
210             REPORTER_ASSERT(reporter, false, "Cannot scanFace\n");
211             continue;
212         }
213         REPORTER_ASSERT(reporter, numInstances == 0);
214         const auto defaultInstance = 0;
215         bool isFixedPitch;
216         SkString realName;
217         SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
218         SkFontScanner::AxisDefinitions axes;
219         if (!scanner->scanInstance(stream.get(), faceIndex, defaultInstance,
220                                    &realName, &style, &isFixedPitch,
221                                    &axes, nullptr)) {
222             REPORTER_ASSERT(reporter,
223                             false,
224                             "Cannot scanInstance %s %d\n",
225                             name.c_str(),
226                             faceIndex);
227             continue;
228         }
229         REPORTER_ASSERT(reporter, axes.size() == 0);
230         REPORTER_ASSERT(reporter, (faceIndex != 0) || (style.weight() == 400.0f));
231         REPORTER_ASSERT(reporter, (faceIndex != 1) || (style.weight() == 700.0f));
232     }
233 }
234