Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FontationsFtCompTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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
10#include "include/core/SkPath.h"
17#include "tests/Test.h"
19
20#include <memory>
21
22namespace {
23
24bool textBlobsAllPathsEqual(sk_sp<const SkTextBlob> blobA,
26 SkString fontName) {
27 SkTextBlob::Iter iterA(*blobA);
28 SkTextBlob::Iter iterB(*blobB);
31 SkPath pathA, pathB;
32 while (iterA.experimentalNext(&runAInfo)) {
33 pathA.reset();
34 pathB.reset();
35 SkASSERT(iterB.experimentalNext(&runBInfo));
36 for (int i = 0; i < runAInfo.count; ++i) {
37 runAInfo.font.getPath(runAInfo.glyphs[i], &pathA);
38 runBInfo.font.getPath(runBInfo.glyphs[i], &pathB);
39 SkDynamicMemoryWStream streamA, streamB;
40 // Re-use the logic in Path::dump() to canonicalize the output and account for
41 // differences between FreeType (inserting a lineTo() to original moveTo() coordinate)
42 // or Fontations (which saves the extra lineTo() before close()).
43 pathA.dump(&streamA, false);
44 pathB.dump(&streamB, false);
45 sk_sp<SkData> dataA = streamA.detachAsData();
46 sk_sp<SkData> dataB = streamB.detachAsData();
47 if (dataA->size() != dataB->size() ||
48 memcmp(dataA->data(), dataB->data(), dataA->size() - 1)) {
50 "Different path in font %s for glyph index: %d glyph id: %d, data sizes "
51 "%ld "
52 "vs %ld\n",
53 fontName.c_str(),
54 i,
55 runAInfo.glyphs[i],
56 dataA->size(),
57 dataB->size());
58 std::string fontationsPath(reinterpret_cast<const char*>(dataA->bytes()),
59 dataA->size());
60 std::string freetypePath(reinterpret_cast<const char*>(dataB->bytes()),
61 dataB->size());
62 SkDebugf("Path A (Fontations): \n%s\n", fontationsPath.c_str());
63 SkDebugf("Path B (FreeType): \n%s\n", freetypePath.c_str());
64 return false;
65 }
66 }
67 }
68 return true;
69}
70
71class FontationsFtComparison {
72public:
73 FontationsFtComparison(std::string fontMatch, std::string langMatch)
74 : fTestDataIterator(fontMatch, langMatch) {}
75
76 void assertAllPathsEqual(skiatest::Reporter* reporter) {
78 size_t numTestsExecuted = 0;
79 while (fTestDataIterator.next(&testSet)) {
81 SkStream::MakeFromFile(testSet.fontFilename.c_str()), SkFontArguments());
83 SkStream::MakeFromFile(testSet.fontFilename.c_str()), SkFontArguments());
84
85 SkASSERT_RELEASE(fontationsTypeface);
86 SkASSERT_RELEASE(freetypeTypeface);
87
88 int upem = fontationsTypeface->getUnitsPerEm();
89 SkFont fontationsFont(fontationsTypeface);
90 SkFont freetypeFont(freetypeTypeface);
91
92 auto configureFont = [upem](SkFont& font) {
93 font.setSize(upem);
95 font.setSubpixel(true);
96 font.setHinting(SkFontHinting::kNone);
97 };
98
99 configureFont(fontationsFont);
100 configureFont(freetypeFont);
101
102 for (const auto& sampleLang : testSet.langSamples) {
103 sk_sp<const SkTextBlob> fontationsTextBlob =
104 makeTextBlobWithFontAndText(fontationsFont, sampleLang.sampleLong);
105 sk_sp<const SkTextBlob> freetypeTextBlob =
106 makeTextBlobWithFontAndText(freetypeFont, sampleLang.sampleLong);
107
109 textBlobsAllPathsEqual(
110 fontationsTextBlob, freetypeTextBlob, testSet.fontName),
111 "paths not equal for %s",
112 testSet.fontName.c_str());
113 }
114 numTestsExecuted++;
115 }
117 numTestsExecuted > 0,
118 "Error: FontationsFtComparison did not run any tests, missing third-party "
119 "googlefonts_testdata resource? See bin/fetch-fonts-testdata.");
120 }
121
122private:
123 sk_sp<const SkTextBlob> makeTextBlobWithFontAndText(const SkFont& font,
124 const SkString& testPhrase) {
125 std::unique_ptr<SkShaper> shaper = SkShaper::Make();
126 SkTextBlobBuilderRunHandler textBlobBuilder(testPhrase.c_str(), {0, 0});
127 SkString fam;
128 font.getTypeface()->getFamilyName(&fam);
129 SkASSERT_RELEASE(testPhrase.size());
130 // Reserve enough space for the test phrase to fit into one line.
131 SkScalar shapeWidth = font.getTypeface()->getUnitsPerEm() * testPhrase.size() * 1.10f;
132 shaper->shape(
133 testPhrase.c_str(), testPhrase.size(), font, true, shapeWidth, &textBlobBuilder);
134 return textBlobBuilder.makeBlob();
135 }
136
137 TestFontDataProvider fTestDataIterator;
138};
139
140} // namespace
141
142DEF_TEST(Fontations_NotoSans, reporter) {
143 FontationsFtComparison("Noto Sans",
144 "en_Latn|es_Latn|pt_Latn|id_Latn|ru_Cyrl|fr_Latn|tr_Latn|vi_Latn|de_"
145 "Latn|it_Latn|pl_Latn|nl_Latn|uk_Cyrl|gl_Latn|ro_Latn|cs_Latn|hu_Latn|"
146 "el_Grek|se_Latn|da_Latn|bg_Latn|sk_Latn|fi_Latn|bs_Latn|ca_Latn|no_"
147 "Latn|sr_Latn|sr_Cyrl|lt_Latn|hr_Latn|sl_Latn|uz_Latn|uz_Cyrl|lv_Latn|"
148 "et_Latn|az_Latn|az_Cyrl|la_Latn|tg_Latn|tg_Cyrl|sw_Latn|mn_Cyrl|kk_"
149 "Latn|kk_Cyrl|sq_Latn|af_Latn|ha_Latn|ky_Cyrl")
150 .assertAllPathsEqual(reporter);
151}
152
153DEF_TEST(Fontations_NotoSans_Deva, reporter) {
154 FontationsFtComparison("Noto Sans Devanagari", "hi_Deva|mr_Deva").assertAllPathsEqual(reporter);
155}
156
157DEF_TEST(Fontations_NotoSans_ar_Arab, reporter) {
158 FontationsFtComparison("Noto Sans Arabic", "ar_Arab|uz_Arab|kk_Arab|ky_Arab")
159 .assertAllPathsEqual(reporter);
160}
161
162DEF_TEST(Fontations_NotoSans_Beng, reporter) {
163 FontationsFtComparison("Noto Sans Bengali", "bn_Beng").assertAllPathsEqual(reporter);
164}
165
166DEF_TEST(Fontations_NotoSans_Jpan, reporter) {
167 FontationsFtComparison("Noto Sans JP", "ja_Jpan").assertAllPathsEqual(reporter);
168}
169
170DEF_TEST(Fontations_NotoSans_Thai, reporter) {
171 FontationsFtComparison("Noto Sans Thai", "th_Thai").assertAllPathsEqual(reporter);
172}
173
174DEF_TEST(Fontations_NotoSans_Hans, reporter) {
175 FontationsFtComparison("Noto Sans SC", "zh_Hans").assertAllPathsEqual(reporter);
176}
177
178DEF_TEST(Fontations_NotoSans_Hant, reporter) {
179 FontationsFtComparison("Noto Sans TC", "zh_Hant").assertAllPathsEqual(reporter);
180}
181
182DEF_TEST(Fontations_NotoSans_Kore, reporter) {
183 FontationsFtComparison("Noto Sans KR", "ko_Kore").assertAllPathsEqual(reporter);
184}
185
186DEF_TEST(Fontations_NotoSans_Taml, reporter) {
187 FontationsFtComparison("Noto Sans Tamil", "ta_Taml").assertAllPathsEqual(reporter);
188}
189
190DEF_TEST(Fontations_NotoSans_Newa, reporter) {
191 FontationsFtComparison("Noto Sans Newa", "new_Newa").assertAllPathsEqual(reporter);
192}
193
194DEF_TEST(Fontations_NotoSans_Knda, reporter) {
195 FontationsFtComparison("Noto Sans Kannada", "kn_Knda").assertAllPathsEqual(reporter);
196}
197
198DEF_TEST(Fontations_NotoSans_Tglg, reporter) {
199 FontationsFtComparison("Noto Sans Tagalog", "fil_Tglg").assertAllPathsEqual(reporter);
200}
201
202DEF_TEST(Fontations_NotoSans_Telu, reporter) {
203 FontationsFtComparison("Noto Sans Telugu", "te_Telu").assertAllPathsEqual(reporter);
204}
205
206DEF_TEST(Fontations_NotoSans_Gujr, reporter) {
207 FontationsFtComparison("Noto Sans Gujarati", "gu_Gujr").assertAllPathsEqual(reporter);
208}
209
210DEF_TEST(Fontations_NotoSans_Geor, reporter) {
211 FontationsFtComparison("Noto Sans Georgian", "ka_Geor").assertAllPathsEqual(reporter);
212}
213
214DEF_TEST(Fontations_NotoSans_Mlym, reporter) {
215 FontationsFtComparison("Noto Sans Malayalam", "ml_Mlym").assertAllPathsEqual(reporter);
216}
217
218DEF_TEST(Fontations_NotoSans_Khmr, reporter) {
219 FontationsFtComparison("Noto Sans Khmer", "km_Khmr").assertAllPathsEqual(reporter);
220}
221
222DEF_TEST(Fontations_NotoSans_Sinh, reporter) {
223 FontationsFtComparison("Noto Sans Sinhala", "si_Sinh").assertAllPathsEqual(reporter);
224}
225
226DEF_TEST(Fontations_NotoSans_Mymr, reporter) {
227 FontationsFtComparison("Noto Sans Myanmar", "my_Mymr").assertAllPathsEqual(reporter);
228}
229
230DEF_TEST(Fontations_NotoSans_Java, reporter) {
231 FontationsFtComparison("Noto Sans Javanese", "jv_Java").assertAllPathsEqual(reporter);
232}
233
234DEF_TEST(Fontations_NotoSans_Mong, reporter) {
235 FontationsFtComparison("Noto Sans Mongolian", "mn_Mong").assertAllPathsEqual(reporter);
236}
237
238DEF_TEST(Fontations_NotoSans_Armn, reporter) {
239 FontationsFtComparison("Noto Sans Armenian", "hy_Armn").assertAllPathsEqual(reporter);
240}
241
242DEF_TEST(Fontations_NotoSans_Elba, reporter) {
243 FontationsFtComparison("Noto Sans Elbasan", "sq_Elba").assertAllPathsEqual(reporter);
244}
245
246DEF_TEST(Fontations_NotoSans_Vith, reporter) {
247 FontationsFtComparison("Noto Sans Vithkuqi", "sq_Vith").assertAllPathsEqual(reporter);
248}
249
250DEF_TEST(Fontations_NotoSans_Guru, reporter) {
251 FontationsFtComparison("Noto Sans Gurmukhi", "pa_Guru").assertAllPathsEqual(reporter);
252}
reporter
static const ConicPts testSet[]
#define SkASSERT_RELEASE(cond)
Definition SkAssert.h:100
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
@ kNone
glyph outlines unchanged
SK_API sk_sp< SkTypeface > SkTypeface_Make_Fontations(std::unique_ptr< SkStreamAsset > fontData, const SkFontArguments &args)
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
sk_sp< SkData > detachAsData()
Definition SkStream.cpp:707
bool getPath(SkGlyphID glyphID, SkPath *path) const
Definition SkFont.cpp:300
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
SkPath & reset()
Definition SkPath.cpp:360
void dump(SkWStream *stream, bool dumpAsHex) const
Definition SkPath.cpp:1976
static std::unique_ptr< SkShaper > Make(sk_sp< SkFontMgr > fallback=nullptr)
Definition SkShaper.cpp:36
static std::unique_ptr< SkStreamAsset > MakeFromFile(const char path[])
Definition SkStream.cpp:922
size_t size() const
Definition SkString.h:131
const char * c_str() const
Definition SkString.h:133
static sk_sp< SkTypeface > MakeFromStream(std::unique_ptr< SkStreamAsset >, const SkFontArguments &)
float SkScalar
Definition extension.cpp:12
font
Font Metadata and Metrics.