xref: /aosp_15_r20/frameworks/minikin/tests/util/FontTestUtils.cpp (revision 834a2baab5fdfc28e9a428ee87c7ea8f6a06a53d)
1*834a2baaSAndroid Build Coastguard Worker /*
2*834a2baaSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*834a2baaSAndroid Build Coastguard Worker  *
4*834a2baaSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*834a2baaSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*834a2baaSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*834a2baaSAndroid Build Coastguard Worker  *
8*834a2baaSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*834a2baaSAndroid Build Coastguard Worker  *
10*834a2baaSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*834a2baaSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*834a2baaSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*834a2baaSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*834a2baaSAndroid Build Coastguard Worker  * limitations under the License.
15*834a2baaSAndroid Build Coastguard Worker  */
16*834a2baaSAndroid Build Coastguard Worker 
17*834a2baaSAndroid Build Coastguard Worker #include "FontTestUtils.h"
18*834a2baaSAndroid Build Coastguard Worker 
19*834a2baaSAndroid Build Coastguard Worker #include <libxml/parser.h>
20*834a2baaSAndroid Build Coastguard Worker #include <log/log.h>
21*834a2baaSAndroid Build Coastguard Worker #include <unistd.h>
22*834a2baaSAndroid Build Coastguard Worker 
23*834a2baaSAndroid Build Coastguard Worker #include "FreeTypeMinikinFontForTest.h"
24*834a2baaSAndroid Build Coastguard Worker #include "LocaleListCache.h"
25*834a2baaSAndroid Build Coastguard Worker #include "MinikinInternal.h"
26*834a2baaSAndroid Build Coastguard Worker #include "minikin/FontCollection.h"
27*834a2baaSAndroid Build Coastguard Worker #include "minikin/FontFamily.h"
28*834a2baaSAndroid Build Coastguard Worker #include "minikin/LocaleList.h"
29*834a2baaSAndroid Build Coastguard Worker 
30*834a2baaSAndroid Build Coastguard Worker namespace minikin {
31*834a2baaSAndroid Build Coastguard Worker 
32*834a2baaSAndroid Build Coastguard Worker namespace {
xmlTrim(const std::string & in)33*834a2baaSAndroid Build Coastguard Worker std::string xmlTrim(const std::string& in) {
34*834a2baaSAndroid Build Coastguard Worker     if (in.empty()) {
35*834a2baaSAndroid Build Coastguard Worker         return in;
36*834a2baaSAndroid Build Coastguard Worker     }
37*834a2baaSAndroid Build Coastguard Worker     const char XML_SPACES[] = "\u0020\u000D\u000A\u0009";
38*834a2baaSAndroid Build Coastguard Worker     const size_t start = in.find_first_not_of(XML_SPACES);  // inclusive
39*834a2baaSAndroid Build Coastguard Worker     const size_t end = in.find_last_not_of(XML_SPACES);     // inclusive
40*834a2baaSAndroid Build Coastguard Worker     MINIKIN_ASSERT(start != std::string::npos, "Not a valid file name \"%s\"", in.c_str());
41*834a2baaSAndroid Build Coastguard Worker     MINIKIN_ASSERT(end != std::string::npos, "Not a valid file name \"%s\"", in.c_str());
42*834a2baaSAndroid Build Coastguard Worker     return in.substr(start, end - start + 1 /* +1 since end is inclusive */);
43*834a2baaSAndroid Build Coastguard Worker }
44*834a2baaSAndroid Build Coastguard Worker 
45*834a2baaSAndroid Build Coastguard Worker }  // namespace
46*834a2baaSAndroid Build Coastguard Worker 
getFontFamilies(const std::string & fontDir,const std::string & xmlPath)47*834a2baaSAndroid Build Coastguard Worker std::vector<std::shared_ptr<FontFamily>> getFontFamilies(const std::string& fontDir,
48*834a2baaSAndroid Build Coastguard Worker                                                          const std::string& xmlPath) {
49*834a2baaSAndroid Build Coastguard Worker     xmlDoc* doc = xmlReadFile(xmlPath.c_str(), NULL, 0);
50*834a2baaSAndroid Build Coastguard Worker     xmlNode* familySet = xmlDocGetRootElement(doc);
51*834a2baaSAndroid Build Coastguard Worker 
52*834a2baaSAndroid Build Coastguard Worker     std::vector<std::shared_ptr<FontFamily>> families;
53*834a2baaSAndroid Build Coastguard Worker     for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) {
54*834a2baaSAndroid Build Coastguard Worker         if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) {
55*834a2baaSAndroid Build Coastguard Worker             continue;
56*834a2baaSAndroid Build Coastguard Worker         }
57*834a2baaSAndroid Build Coastguard Worker 
58*834a2baaSAndroid Build Coastguard Worker         xmlChar* variantXmlch = xmlGetProp(familyNode, (const xmlChar*)"variant");
59*834a2baaSAndroid Build Coastguard Worker         FamilyVariant variant = FamilyVariant::DEFAULT;
60*834a2baaSAndroid Build Coastguard Worker         if (variantXmlch) {
61*834a2baaSAndroid Build Coastguard Worker             if (xmlStrcmp(variantXmlch, (const xmlChar*)"elegant") == 0) {
62*834a2baaSAndroid Build Coastguard Worker                 variant = FamilyVariant::ELEGANT;
63*834a2baaSAndroid Build Coastguard Worker             } else if (xmlStrcmp(variantXmlch, (const xmlChar*)"compact") == 0) {
64*834a2baaSAndroid Build Coastguard Worker                 variant = FamilyVariant::COMPACT;
65*834a2baaSAndroid Build Coastguard Worker             }
66*834a2baaSAndroid Build Coastguard Worker         }
67*834a2baaSAndroid Build Coastguard Worker 
68*834a2baaSAndroid Build Coastguard Worker         std::vector<std::shared_ptr<Font>> fonts;
69*834a2baaSAndroid Build Coastguard Worker         for (xmlNode* fontNode = familyNode->children; fontNode; fontNode = fontNode->next) {
70*834a2baaSAndroid Build Coastguard Worker             if (xmlStrcmp(fontNode->name, (const xmlChar*)"font") != 0) {
71*834a2baaSAndroid Build Coastguard Worker                 continue;
72*834a2baaSAndroid Build Coastguard Worker             }
73*834a2baaSAndroid Build Coastguard Worker 
74*834a2baaSAndroid Build Coastguard Worker             uint16_t weight = atoi((const char*)(xmlGetProp(fontNode, (const xmlChar*)"weight")));
75*834a2baaSAndroid Build Coastguard Worker             FontStyle::Slant italic = static_cast<FontStyle::Slant>(
76*834a2baaSAndroid Build Coastguard Worker                     xmlStrcmp(xmlGetProp(fontNode, (const xmlChar*)"style"),
77*834a2baaSAndroid Build Coastguard Worker                               (const xmlChar*)"italic") == 0);
78*834a2baaSAndroid Build Coastguard Worker             xmlChar* index = xmlGetProp(familyNode, (const xmlChar*)"index");
79*834a2baaSAndroid Build Coastguard Worker 
80*834a2baaSAndroid Build Coastguard Worker             xmlChar* fontFileName = xmlNodeListGetString(doc, fontNode->xmlChildrenNode, 1);
81*834a2baaSAndroid Build Coastguard Worker             const std::string fontPath = xmlTrim(fontDir + std::string((const char*)fontFileName));
82*834a2baaSAndroid Build Coastguard Worker             xmlFree(fontFileName);
83*834a2baaSAndroid Build Coastguard Worker 
84*834a2baaSAndroid Build Coastguard Worker             // TODO: Support font variation axis.
85*834a2baaSAndroid Build Coastguard Worker 
86*834a2baaSAndroid Build Coastguard Worker             if (access(fontPath.c_str(), R_OK) != 0) {
87*834a2baaSAndroid Build Coastguard Worker                 ALOGW("%s is not found.", fontPath.c_str());
88*834a2baaSAndroid Build Coastguard Worker                 continue;
89*834a2baaSAndroid Build Coastguard Worker             }
90*834a2baaSAndroid Build Coastguard Worker 
91*834a2baaSAndroid Build Coastguard Worker             FontStyle style(weight, italic);
92*834a2baaSAndroid Build Coastguard Worker             if (index == nullptr) {
93*834a2baaSAndroid Build Coastguard Worker                 std::shared_ptr<MinikinFont> minikinFont =
94*834a2baaSAndroid Build Coastguard Worker                         std::make_shared<FreeTypeMinikinFontForTest>(fontPath);
95*834a2baaSAndroid Build Coastguard Worker                 fonts.push_back(Font::Builder(minikinFont).setStyle(style).build());
96*834a2baaSAndroid Build Coastguard Worker             } else {
97*834a2baaSAndroid Build Coastguard Worker                 std::shared_ptr<MinikinFont> minikinFont =
98*834a2baaSAndroid Build Coastguard Worker                         std::make_shared<FreeTypeMinikinFontForTest>(fontPath,
99*834a2baaSAndroid Build Coastguard Worker                                                                      atoi((const char*)index));
100*834a2baaSAndroid Build Coastguard Worker                 fonts.push_back(Font::Builder(minikinFont).setStyle(style).build());
101*834a2baaSAndroid Build Coastguard Worker             }
102*834a2baaSAndroid Build Coastguard Worker         }
103*834a2baaSAndroid Build Coastguard Worker 
104*834a2baaSAndroid Build Coastguard Worker         xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang");
105*834a2baaSAndroid Build Coastguard Worker         std::shared_ptr<FontFamily> family;
106*834a2baaSAndroid Build Coastguard Worker         if (lang == nullptr) {
107*834a2baaSAndroid Build Coastguard Worker             family = FontFamily::create(variant, std::move(fonts));
108*834a2baaSAndroid Build Coastguard Worker         } else {
109*834a2baaSAndroid Build Coastguard Worker             uint32_t langId = registerLocaleList(std::string((const char*)lang, xmlStrlen(lang)));
110*834a2baaSAndroid Build Coastguard Worker             family = FontFamily::create(langId, variant, std::move(fonts),
111*834a2baaSAndroid Build Coastguard Worker                                         false /* isCustomFallback */, false /* isdefaultFallback */,
112*834a2baaSAndroid Build Coastguard Worker                                         VariationFamilyType::None);
113*834a2baaSAndroid Build Coastguard Worker         }
114*834a2baaSAndroid Build Coastguard Worker         families.push_back(family);
115*834a2baaSAndroid Build Coastguard Worker     }
116*834a2baaSAndroid Build Coastguard Worker     xmlFreeDoc(doc);
117*834a2baaSAndroid Build Coastguard Worker     return families;
118*834a2baaSAndroid Build Coastguard Worker }
119*834a2baaSAndroid Build Coastguard Worker 
buildFontCollection(const std::string & filePath)120*834a2baaSAndroid Build Coastguard Worker std::shared_ptr<FontCollection> buildFontCollection(const std::string& filePath) {
121*834a2baaSAndroid Build Coastguard Worker     return FontCollection::create(buildFontFamily(filePath));
122*834a2baaSAndroid Build Coastguard Worker }
123*834a2baaSAndroid Build Coastguard Worker 
buildFontFamily(const std::string & filePath)124*834a2baaSAndroid Build Coastguard Worker std::shared_ptr<FontFamily> buildFontFamily(const std::string& filePath) {
125*834a2baaSAndroid Build Coastguard Worker     auto font = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(filePath));
126*834a2baaSAndroid Build Coastguard Worker     std::vector<std::shared_ptr<Font>> fonts;
127*834a2baaSAndroid Build Coastguard Worker     fonts.push_back(Font::Builder(font).build());
128*834a2baaSAndroid Build Coastguard Worker     return FontFamily::create(std::move(fonts));
129*834a2baaSAndroid Build Coastguard Worker }
130*834a2baaSAndroid Build Coastguard Worker 
buildFontFamily(const std::string & filePath,const std::string & lang,bool isCustomFallback)131*834a2baaSAndroid Build Coastguard Worker std::shared_ptr<FontFamily> buildFontFamily(const std::string& filePath, const std::string& lang,
132*834a2baaSAndroid Build Coastguard Worker                                             bool isCustomFallback) {
133*834a2baaSAndroid Build Coastguard Worker     auto font = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(filePath));
134*834a2baaSAndroid Build Coastguard Worker     std::vector<std::shared_ptr<Font>> fonts;
135*834a2baaSAndroid Build Coastguard Worker     fonts.push_back(Font::Builder(font).build());
136*834a2baaSAndroid Build Coastguard Worker     return FontFamily::create(LocaleListCache::getId(lang), FamilyVariant::DEFAULT,
137*834a2baaSAndroid Build Coastguard Worker                               std::move(fonts), isCustomFallback, false /* isDefaultFallback */,
138*834a2baaSAndroid Build Coastguard Worker                               VariationFamilyType::None);
139*834a2baaSAndroid Build Coastguard Worker }
140*834a2baaSAndroid Build Coastguard Worker 
141*834a2baaSAndroid Build Coastguard Worker }  // namespace minikin
142