Flutter Engine
The Flutter Engine
FontationsTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2013 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
11#include "tests/Test.h"
12#include "tools/Resources.h"
13
14#include <memory>
15
16namespace {
17const char kFontResource[] = "fonts/ahem.ttf";
18const char kTtcResource[] = "fonts/test.ttc";
19const char kVariableResource[] = "fonts/test_glyphs-glyf_colr_1_variable.ttf";
20constexpr size_t kNumVariableAxes = 44;
21
22struct AxisExpectation {
23 SkFourByteTag tag;
24 float minValue;
25 float defValue;
26 float maxValue;
27} axisExpectations[] = {
28 {SkSetFourByteTag('S', 'W', 'P', 'S'), -90.0, 0.0, 90.0},
29 {SkSetFourByteTag('S', 'W', 'P', 'E'), -90.0, 0.0, 90.0},
30 {SkSetFourByteTag('S', 'W', 'C', '1'), -2.0, 0.0, 2.0},
31 {SkSetFourByteTag('S', 'W', 'C', '2'), -2.0, 0.0, 2.0},
32 {SkSetFourByteTag('S', 'W', 'C', '3'), -2.0, 0.0, 2.0},
33 {SkSetFourByteTag('S', 'W', 'C', '4'), -2.0, 0.0, 2.0},
34 {SkSetFourByteTag('S', 'C', 'O', 'X'), -200., 0.0, 200.},
35 {SkSetFourByteTag('S', 'C', 'O', 'Y'), -200., 0.0, 200.},
36 {SkSetFourByteTag('S', 'C', 'S', 'X'), -2.0, 0.0, 1.9999389648437},
37 {SkSetFourByteTag('S', 'C', 'S', 'Y'), -2.0, 0.0, 1.9999389648437},
38 {SkSetFourByteTag('G', 'R', 'X', '0'), -1000, 0.0, 1000},
39 {SkSetFourByteTag('G', 'R', 'Y', '0'), -1000, 0.0, 1000},
40 {SkSetFourByteTag('G', 'R', 'X', '1'), -1000, 0.0, 1000},
41 {SkSetFourByteTag('G', 'R', 'Y', '1'), -1000, 0.0, 1000},
42 {SkSetFourByteTag('G', 'R', 'X', '2'), -1000, 0.0, 1000},
43 {SkSetFourByteTag('G', 'R', 'Y', '2'), -1000, 0.0, 1000},
44 {SkSetFourByteTag('G', 'R', 'R', '0'), -1000, 0.0, 1000},
45 {SkSetFourByteTag('G', 'R', 'R', '1'), -1000, 0.0, 1000},
46 {SkSetFourByteTag('C', 'O', 'L', '1'), -2.0, 0.0, 2.0},
47 {SkSetFourByteTag('C', 'O', 'L', '2'), -2.0, 0.0, 2.0},
48 {SkSetFourByteTag('C', 'O', 'L', '3'), -2.0, 0.0, 2.0},
49 {SkSetFourByteTag('R', 'O', 'T', 'A'), 0.0, 0.0, 539.989013671875},
50 {SkSetFourByteTag('R', 'O', 'T', 'X'), -500.0, 0.0, 500.0},
51 {SkSetFourByteTag('R', 'O', 'T', 'Y'), -500.0, 0.0, 500.0},
52 {SkSetFourByteTag('S', 'K', 'X', 'A'), -90.0, 0.0, 90.0},
53 {SkSetFourByteTag('S', 'K', 'Y', 'A'), -90.0, 0.0, 90.0},
54 {SkSetFourByteTag('S', 'K', 'C', 'X'), -500.0, 0.0, 500.0},
55 {SkSetFourByteTag('S', 'K', 'C', 'Y'), -500.0, 0.0, 500.0},
56 {SkSetFourByteTag('T', 'R', 'X', 'X'), -2.0, 0.0, 2.0},
57 {SkSetFourByteTag('T', 'R', 'Y', 'X'), -2.0, 0.0, 2.0},
58 {SkSetFourByteTag('T', 'R', 'X', 'Y'), -2.0, 0.0, 2.0},
59 {SkSetFourByteTag('T', 'R', 'Y', 'Y'), -2.0, 0.0, 2.0},
60 {SkSetFourByteTag('T', 'R', 'D', 'X'), -500.0, 0.0, 500.0},
61 {SkSetFourByteTag('T', 'R', 'D', 'Y'), -500.0, 0.0, 500.0},
62 {SkSetFourByteTag('T', 'L', 'D', 'X'), -500.0, 0.0, 500.0},
63 {SkSetFourByteTag('T', 'L', 'D', 'Y'), -500.0, 0.0, 500.0},
64 {SkSetFourByteTag('C', 'L', 'X', 'I'), -500.0, 0.0, 500.0},
65 {SkSetFourByteTag('C', 'L', 'Y', 'I'), -500.0, 0.0, 500.0},
66 {SkSetFourByteTag('C', 'L', 'X', 'A'), -500.0, 0.0, 500.0},
67 {SkSetFourByteTag('C', 'L', 'Y', 'A'), -500.0, 0.0, 500.0},
68 {SkSetFourByteTag('C', 'L', 'I', 'O'), -500.0, 0.0, 500.0},
69 {SkSetFourByteTag('A', 'P', 'H', '1'), -1.0, 0.0, 0.0},
70 {SkSetFourByteTag('A', 'P', 'H', '2'), -1.0, 0.0, 0.0},
71 {SkSetFourByteTag('A', 'P', 'H', '3'), -1.0, 0.0, 0.0},
72};
73} // namespace
74
75DEF_TEST(Fontations_DoNotMakeFromNull, reporter) {
76 std::unique_ptr<SkStreamAsset> nullStream = SkMemoryStream::MakeDirect(nullptr, 0);
77 sk_sp<SkTypeface> probeTypeface(
78 SkTypeface_Make_Fontations(std::move(nullStream), SkFontArguments()));
79 REPORTER_ASSERT(reporter, !probeTypeface);
80}
81
82DEF_TEST(Fontations_DoNotMakeFromNonSfnt, reporter) {
83 char notAnSfnt[] = "I_AM_NOT_AN_SFNT";
84 std::unique_ptr<SkStreamAsset> notSfntStream =
85 SkMemoryStream::MakeDirect(notAnSfnt, std::size(notAnSfnt));
86 sk_sp<SkTypeface> probeTypeface(
87 SkTypeface_Make_Fontations(std::move(notSfntStream), SkFontArguments()));
88 REPORTER_ASSERT(reporter, !probeTypeface);
89}
90
91DEF_TEST(Fontations_MakeFromFont, reporter) {
92 sk_sp<SkTypeface> probeTypeface(
94 REPORTER_ASSERT(reporter, probeTypeface);
95}
96
97DEF_TEST(Fontations_MakeFromCollection, reporter) {
98 sk_sp<SkTypeface> probeTypeface(
100 REPORTER_ASSERT(reporter, probeTypeface);
101}
102
103DEF_TEST(Fontations_MakeFromCollectionNonNullIndex, reporter) {
105 args.setCollectionIndex(1);
106 sk_sp<SkTypeface> probeTypeface(
108 REPORTER_ASSERT(reporter, probeTypeface);
109}
110
111DEF_TEST(Fontations_DoNotMakeFromCollection_Invalid_Index, reporter) {
113 args.setCollectionIndex(1000);
114 sk_sp<SkTypeface> probeTypeface(
116 REPORTER_ASSERT(reporter, !probeTypeface);
117}
118
119DEF_TEST(Fontations_TableData, reporter) {
120 constexpr size_t kNameTableSize = 11310;
121 constexpr size_t kTestOffset = 1310;
122 constexpr size_t kTestLength = 500;
123 char destBuffer[kNameTableSize] = {0};
124 sk_sp<SkTypeface> testTypeface(
126 SkFourByteTag nameTableTag = SkSetFourByteTag('n', 'a', 'm', 'e');
127 SkFourByteTag nonExistantTag = SkSetFourByteTag('0', 'X', '0', 'X');
128
129 // Getting size without buffer.
131 testTypeface->getTableData(nameTableTag, 0, kNameTableSize, nullptr) ==
132 kNameTableSize);
133 // Reading full table.
135 testTypeface->getTableData(nameTableTag, 0, kNameTableSize, destBuffer) ==
136 kNameTableSize);
137 // Reading restricted length.
139 reporter,
140 testTypeface->getTableData(nameTableTag, 0, kTestLength, destBuffer) == kTestLength);
142 testTypeface->getTableData(
143 nameTableTag, kTestOffset, kTestLength, destBuffer) == kTestLength);
144 // Reading at an offset.
146 reporter,
147 testTypeface->getTableData(nameTableTag, kTestOffset, kNameTableSize, destBuffer) ==
148 kNameTableSize - kTestOffset);
149
150 // Reading from offset past table.
152 testTypeface->getTableData(
153 nameTableTag, kNameTableSize, kNameTableSize, destBuffer) == 0);
155 testTypeface->getTableData(nameTableTag, kNameTableSize, 0, nullptr) == 0);
156 // Reading one byte before end of table.
158 testTypeface->getTableData(
159 nameTableTag, kNameTableSize - 1, kNameTableSize, destBuffer) == 1);
160 // Trying to start reading at an offset past table start.
162 testTypeface->getTableData(nameTableTag, 0, kNameTableSize + 10, destBuffer) ==
163 kNameTableSize);
164 // Restricting length without target buffer.
166 testTypeface->getTableData(nameTableTag, 0, kTestLength, nullptr) ==
167 kTestLength);
168
169 // Trying to access non-existant table.
171 testTypeface->getTableData(nonExistantTag, 0, kNameTableSize, destBuffer) ==
172 0);
174 testTypeface->getTableData(nonExistantTag, 0, 0, nullptr) ==
175 0);
177 testTypeface->getTableData(nonExistantTag, kTestOffset, 0, nullptr) == 0);
178}
179
180DEF_TEST(Fontations_TableTags, reporter) {
181 constexpr size_t kNumTags = 11;
182 SkFourByteTag tagsBuffer[kNumTags] = {0};
183 sk_sp<SkTypeface> testTypeface(
185 SkFourByteTag firstTag = SkSetFourByteTag('O', 'S', '/', '2');
186 SkFourByteTag lastTag = SkSetFourByteTag('p', 'o', 's', 't');
187
188 REPORTER_ASSERT(reporter, testTypeface->getTableTags(nullptr) == kNumTags);
189
190 REPORTER_ASSERT(reporter, testTypeface->getTableTags(tagsBuffer) == kNumTags);
191 REPORTER_ASSERT(reporter, tagsBuffer[0] == firstTag);
192 REPORTER_ASSERT(reporter, tagsBuffer[kNumTags - 1] == lastTag);
193}
194
195DEF_TEST(Fontations_VariationPosition, reporter) {
196 sk_sp<SkTypeface> variableTypeface(
198 // Everything at default.
199 const int numAxes = variableTypeface->getVariationDesignPosition(nullptr, 0);
200 REPORTER_ASSERT(reporter, numAxes == kNumVariableAxes, "numAxes: %d", numAxes);
201
202 SkFontArguments::VariationPosition::Coordinate kSwpsCoordinateFirst = {SkSetFourByteTag('S', 'W', 'P', 'S'), 25};
203 SkFontArguments::VariationPosition::Coordinate kSwpsCoordinateSecond = {SkSetFourByteTag('S', 'W', 'P', 'S'), 55};
204 SkFontArguments::VariationPosition::Coordinate kSwpeCoordinate = {SkSetFourByteTag('S', 'W', 'P', 'E'), 45};
205 SkFontArguments::VariationPosition::Coordinate kInvalidCoordinate = {SkSetFourByteTag('_', '_', '_', '_'), 0};
206
207 // 'SWPS' and 'SWPE' exist. Second 'SWPS' should override first, invalid tag should be stripped.
209 kSwpsCoordinateFirst, kSwpsCoordinateSecond, kSwpeCoordinate, kInvalidCoordinate};
210
212 clonePosition.coordinates = cloneCoordinates;
213 clonePosition.coordinateCount = 4;
214
215 sk_sp<SkTypeface> cloneTypeface = variableTypeface->makeClone(
216 SkFontArguments().setVariationDesignPosition(clonePosition));
217 const int cloneNumAxes = cloneTypeface->getVariationDesignPosition(nullptr, 0);
218 REPORTER_ASSERT(reporter, cloneNumAxes == kNumVariableAxes, "clonedNumAxes: %d", cloneNumAxes);
219
220 SkFontArguments::VariationPosition::Coordinate retrieveCoordinates[kNumVariableAxes] = {};
221
222 // Error when providing too little space.
223 const int badClonedNumAxes = cloneTypeface->getVariationDesignPosition(retrieveCoordinates, 1);
224 REPORTER_ASSERT(reporter, badClonedNumAxes == -1, "badClonedNumAxes: %d", badClonedNumAxes);
225
226 const int retrievedClonedNumAxes =
227 cloneTypeface->getVariationDesignPosition(retrieveCoordinates, kNumVariableAxes);
228 REPORTER_ASSERT(reporter, retrievedClonedNumAxes == kNumVariableAxes,
229 "retrievedClonedNumAxes: %d", retrievedClonedNumAxes);
231 retrieveCoordinates[0].axis == kSwpsCoordinateSecond.axis &&
232 retrieveCoordinates[0].value == kSwpsCoordinateSecond.value);
234 retrieveCoordinates[1].axis == kSwpeCoordinate.axis &&
235 retrieveCoordinates[1].value == kSwpeCoordinate.value);
236}
237
238DEF_TEST(Fontations_VariationParameters, reporter) {
239 sk_sp<SkTypeface> variableTypeface(
242 variableTypeface->getVariationDesignParameters(nullptr, 0) == kNumVariableAxes);
243
244 SkFontParameters::Variation::Axis axes[kNumVariableAxes] = {};
246 variableTypeface->getVariationDesignParameters(axes, kNumVariableAxes) ==
247 kNumVariableAxes);
248
249 for (size_t i = 0; i < kNumVariableAxes; ++i) {
250 REPORTER_ASSERT(reporter, axes[i].tag == axisExpectations[i].tag);
251 REPORTER_ASSERT(reporter, axes[i].min == axisExpectations[i].minValue);
252 REPORTER_ASSERT(reporter, axes[i].def == axisExpectations[i].defValue);
253 REPORTER_ASSERT(reporter, axes[i].max == axisExpectations[i].maxValue);
254 }
255}
256
257DEF_TEST(Fontations_VariationParameters_BufferTooSmall, reporter) {
258 sk_sp<SkTypeface> variableTypeface(
261 variableTypeface->getVariationDesignParameters(nullptr, 0) == kNumVariableAxes);
262
263 constexpr size_t kArrayTooSmall = 3;
264 SkFontParameters::Variation::Axis axes[kArrayTooSmall] = {};
266 variableTypeface->getVariationDesignParameters(axes, kArrayTooSmall) == -1);
267}
reporter
Definition: FontMgrTest.cpp:39
DEF_TEST(Fontations_DoNotMakeFromNull, reporter)
std::unique_ptr< SkStreamAsset > GetResourceAsStream(const char *resource, bool useFileStream)
Definition: Resources.cpp:31
SK_API sk_sp< SkTypeface > SkTypeface_Make_Fontations(std::unique_ptr< SkStreamAsset > fontData, const SkFontArguments &args)
uint32_t SkFourByteTag
Definition: SkTypes.h:166
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition: SkTypes.h:167
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static std::unique_ptr< SkMemoryStream > MakeDirect(const void *data, size_t length)
Definition: SkStream.cpp:310
int getVariationDesignParameters(SkFontParameters::Variation::Axis parameters[], int parameterCount) const
Definition: SkTypeface.cpp:295
int getTableTags(SkFontTableTag tags[]) const
Definition: SkTypeface.cpp:305
int getVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
Definition: SkTypeface.cpp:289
size_t getTableData(SkFontTableTag tag, size_t offset, size_t length, void *data) const
Definition: SkTypeface.cpp:313
sk_sp< SkTypeface > makeClone(const SkFontArguments &) const
Definition: SkTypeface.cpp:190
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259