blob: c86951e78d24424c976de164926ad25be50ed01d [file] [log] [blame]
Kevin Lubick569a30f2023-09-25 08:26:27 -04001/*
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
15const char kTestDataJsonFilename[] = "raster_test.json";
16const char kTestDataBasePath[] = "third_party/externals/googlefonts_testdata/data/";
17
18std::atomic<const char*> gFontTestDataBasePath{kTestDataBasePath};
19
20namespace skiatest {
21static DEFINE_string(fontTestDataPath,
22 "",
23 "Path to extracted data from googlefonts_testdata CIPD file.");
24
25void 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.
37constexpr size_t kExpectNumFonts = 51;
38#endif
39
40namespace {
41SkString prefixWithTestDataPath(SkString suffix) {
42 return SkOSPath::Join(gFontTestDataBasePath, suffix.c_str());
43}
44
45SkString prefixWithFontsPath(SkString suffix) {
46 SkString fontsPath = prefixWithTestDataPath(SkString("fonts"));
47 return SkOSPath::Join(fontsPath.c_str(), suffix.c_str());
48}
49
50} // namespace
51
John Stiles26bf5222023-10-17 10:29:41 -040052TestFontDataProvider::TestFontDataProvider(const std::string& fontFilterRegexp,
53 const std::string& langFilterRegexp)
Kevin Lubick569a30f2023-09-25 08:26:27 -040054 : 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
73bool 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
94void TestFontDataProvider::rewind() { fFontsIndex = 0; }
95
96std::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}