xref: /aosp_15_r20/external/skia/tools/TestFontDataProvider.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
8 #include "tools/TestFontDataProvider.h"
9 
10 #include "include/core/SkData.h"
11 #include "include/private/base/SkDebug.h"
12 #include "src/utils/SkOSPath.h"
13 #include "tools/flags/CommandLineFlags.h"
14 
15 const char kTestDataJsonFilename[] = "raster_test.json";
16 const char kTestDataBasePath[] = "third_party/externals/googlefonts_testdata/data/";
17 
18 std::atomic<const char*> gFontTestDataBasePath{kTestDataBasePath};
19 
20 namespace skiatest {
21 static DEFINE_string(fontTestDataPath,
22                      "",
23                      "Path to extracted data from googlefonts_testdata CIPD file.");
24 
SetFontTestDataDirectory()25 void SetFontTestDataDirectory() {
26     if (FLAGS_fontTestDataPath.isEmpty()) {
27         return;
28     }
29     if (strlen(FLAGS_fontTestDataPath[0])) {
30         gFontTestDataBasePath = FLAGS_fontTestDataPath[0];
31     }
32 }
33 }  // namespace skiatest
34 
35 #if defined(SK_DEBUG)
36 // Change size when rolling / changing googlefonts_testdata CIPD, see bin/fetch-fonts-testdata.
37 constexpr size_t kExpectNumFonts = 51;
38 #endif
39 
40 namespace {
prefixWithTestDataPath(SkString suffix)41 SkString prefixWithTestDataPath(SkString suffix) {
42     return SkOSPath::Join(gFontTestDataBasePath, suffix.c_str());
43 }
44 
prefixWithFontsPath(SkString suffix)45 SkString prefixWithFontsPath(SkString suffix) {
46     SkString fontsPath = prefixWithTestDataPath(SkString("fonts"));
47     return SkOSPath::Join(fontsPath.c_str(), suffix.c_str());
48 }
49 
50 }  // namespace
51 
TestFontDataProvider(const std::string & fontFilterRegexp,const std::string & langFilterRegexp)52 TestFontDataProvider::TestFontDataProvider(const std::string& fontFilterRegexp,
53                                            const std::string& langFilterRegexp)
54         : fFontFilter(fontFilterRegexp), fLangFilter(langFilterRegexp) {
55     SkString testDataLocation = prefixWithTestDataPath(SkString(kTestDataJsonFilename));
56     sk_sp<SkData> jsonTestData = SkData::MakeFromFileName(testDataLocation.c_str());
57     SkASSERTF(jsonTestData && jsonTestData->size(),
58               "Unable to access font test metadata at location %s, check bin/fetch-fonts-testdata.",
59               testDataLocation.c_str());
60     fJsonDom = std::make_unique<skjson::DOM>(reinterpret_cast<const char*>(jsonTestData->bytes()),
61                                              jsonTestData->size());
62     const skjson::ObjectValue& root = fJsonDom->root().as<skjson::ObjectValue>();
63     fFonts = root["fonts"];
64     SkASSERT(fFonts);
65     SkASSERTF(fFonts->size() == kExpectNumFonts,
66               "Unable to access all %zu test fonts (only got %zu), check bin/fetch-fonts-testdata.",
67               kExpectNumFonts,
68               fFonts->size());
69     fSamples = root["samples"];
70     SkASSERT(fSamples);
71 }
72 
next(TestSet * testSet)73 bool TestFontDataProvider::next(TestSet* testSet) {
74     while (testSet && fFontsIndex < fFonts->size()) {
75         const skjson::ObjectValue* fontsEntry = (*fFonts)[fFontsIndex++];
76         SkASSERT(fontsEntry);
77         const skjson::StringValue* fontName = (*fontsEntry)["name"];
78         SkASSERT(fontName);
79         std::smatch match;
80         std::string fontNameStr(fontName->str());
81         if (std::regex_match(fontNameStr, match, fFontFilter)) {
82             testSet->fontName = SkString(fontNameStr);
83             const skjson::StringValue* fontFilename = (*fontsEntry)["path"];
84             testSet->fontFilename = prefixWithFontsPath(
85                     SkString(fontFilename->str().data(), fontFilename->str().size()));
86             testSet->langSamples =
87                     getLanguageSamples((*fontsEntry)["languages"].as<skjson::ArrayValue>());
88             return true;
89         }
90     }
91     return false;
92 }
93 
rewind()94 void TestFontDataProvider::rewind() { fFontsIndex = 0; }
95 
getLanguageSamples(const skjson::ArrayValue * languages)96 std::vector<TestFontDataProvider::LangSample> TestFontDataProvider::getLanguageSamples(
97         const skjson::ArrayValue* languages) {
98     std::vector<LangSample> samples;
99     for (size_t i = 0; i < languages->size(); ++i) {
100         const skjson::StringValue* langTag = (*languages)[i];
101         std::string langTagStr(langTag->str());
102         std::smatch match;
103         if (std::regex_match(langTagStr, match, fLangFilter)) {
104             const skjson::ObjectValue* sample = (*fSamples)[langTagStr.c_str()];
105             const skjson::StringValue* shortSample = (*sample)["short_sample"];
106             const skjson::StringValue* longSample = (*sample)["long_sample"];
107             SkString sampleShort(shortSample->str().data(), shortSample->str().size());
108             SkString sampleLong(longSample->str().data(), longSample->str().size());
109             samples.push_back({SkString(langTagStr), sampleShort, sampleLong});
110         }
111     }
112     SkASSERT_RELEASE(samples.size());
113     return samples;
114 }
115