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