11c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka/* 21c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * Copyright (C) 2015 The Android Open Source Project 31c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * 41c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License"); 51c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * you may not use this file except in compliance with the License. 61c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * You may obtain a copy of the License at 71c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * 81c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * http://www.apache.org/licenses/LICENSE-2.0 91c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * 101c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * Unless required by applicable law or agreed to in writing, software 111c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS, 121c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * See the License for the specific language governing permissions and 141c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka * limitations under the License. 151c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka */ 161c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 17555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#define LOG_TAG "Minikin" 181c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 19555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <libxml/tree.h> 2039ab40115fae6d0c948e435233b3dd997ee7d8e5Mark Salyzyn#include <log/log.h> 211d461589869ee5b7102f96271b0ef0a776ab513cSeigo Nonaka#include <unistd.h> 22198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka 231d461589869ee5b7102f96271b0ef0a776ab513cSeigo Nonaka#include "minikin/FontCollection.h" 241d461589869ee5b7102f96271b0ef0a776ab513cSeigo Nonaka#include "minikin/FontFamily.h" 25b47e9b21077d2a0847a64fa713aa9892196b5d2aSeigo Nonaka#include "minikin/LocaleList.h" 266c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka 27e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka#include "FontTestUtils.h" 289dffc23bd79a82e75181e33974af05da62dc6306Seigo Nonaka#include "FreeTypeMinikinFontForTest.h" 297fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka#include "LocaleListCache.h" 30b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka#include "MinikinInternal.h" 311c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 3214e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin { 3314e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka 34b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonakanamespace { 35b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonakastd::string xmlTrim(const std::string& in) { 36b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka if (in.empty()) { 37b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka return in; 38b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka } 39b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka const char XML_SPACES[] = "\u0020\u000D\u000A\u0009"; 40b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka const size_t start = in.find_first_not_of(XML_SPACES); // inclusive 41b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka const size_t end = in.find_last_not_of(XML_SPACES); // inclusive 42b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka MINIKIN_ASSERT(start != std::string::npos, "Not a valid file name \"%s\"", in.c_str()); 43b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka MINIKIN_ASSERT(end != std::string::npos, "Not a valid file name \"%s\"", in.c_str()); 44b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka return in.substr(start, end - start + 1 /* +1 since end is inclusive */); 45b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka} 46b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka 47b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka} // namespace 48b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka 4954e248ac7fa00d430092a8e993c83fccd4f72df5Seigo Nonakastd::vector<std::shared_ptr<FontFamily>> getFontFamilies(const std::string& fontDir, 5054e248ac7fa00d430092a8e993c83fccd4f72df5Seigo Nonaka const std::string& xmlPath) { 5154e248ac7fa00d430092a8e993c83fccd4f72df5Seigo Nonaka xmlDoc* doc = xmlReadFile(xmlPath.c_str(), NULL, 0); 521c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka xmlNode* familySet = xmlDocGetRootElement(doc); 531c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 54dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka std::vector<std::shared_ptr<FontFamily>> families; 551c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) { 561c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) { 571c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka continue; 581c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 591c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 601c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka xmlChar* variantXmlch = xmlGetProp(familyNode, (const xmlChar*)"variant"); 61538122d159ef845767ea430a5541248e85e43717Seigo Nonaka FontFamily::Variant variant = FontFamily::Variant::DEFAULT; 621c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka if (variantXmlch) { 631c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka if (xmlStrcmp(variantXmlch, (const xmlChar*)"elegant") == 0) { 64538122d159ef845767ea430a5541248e85e43717Seigo Nonaka variant = FontFamily::Variant::ELEGANT; 651c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } else if (xmlStrcmp(variantXmlch, (const xmlChar*)"compact") == 0) { 66538122d159ef845767ea430a5541248e85e43717Seigo Nonaka variant = FontFamily::Variant::COMPACT; 671c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 681c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 691c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 7041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka std::vector<Font> fonts; 711c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka for (xmlNode* fontNode = familyNode->children; fontNode; fontNode = fontNode->next) { 721c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka if (xmlStrcmp(fontNode->name, (const xmlChar*)"font") != 0) { 731c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka continue; 741c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 751c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 76538122d159ef845767ea430a5541248e85e43717Seigo Nonaka uint16_t weight = atoi((const char*)(xmlGetProp(fontNode, (const xmlChar*)"weight"))); 776c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka FontStyle::Slant italic = static_cast<FontStyle::Slant>( 786c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka xmlStrcmp(xmlGetProp(fontNode, (const xmlChar*)"style"), 796c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka (const xmlChar*)"italic") == 0); 805e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka xmlChar* index = xmlGetProp(familyNode, (const xmlChar*)"index"); 811c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 821c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka xmlChar* fontFileName = xmlNodeListGetString(doc, fontNode->xmlChildrenNode, 1); 83b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka const std::string fontPath = xmlTrim(fontDir + std::string((const char*)fontFileName)); 841c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka xmlFree(fontFileName); 851c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka 86b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka // TODO: Support font variation axis. 87b02135558f85d94772183b08e6e0c454bca00d22Seigo Nonaka 885e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka if (access(fontPath.c_str(), R_OK) != 0) { 895e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka ALOGW("%s is not found.", fontPath.c_str()); 905e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka continue; 915e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka } 9281c79d6e1e49562c9bc33c14826017dd5e33ebecSeigo Nonaka 93a22996e31226e3dcbfb0c57d03ca9ac54028fc28Seigo Nonaka FontStyle style(weight, italic); 945e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka if (index == nullptr) { 9580a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka std::shared_ptr<MinikinFont> minikinFont = 96e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka std::make_shared<FreeTypeMinikinFontForTest>(fontPath); 97a22996e31226e3dcbfb0c57d03ca9ac54028fc28Seigo Nonaka fonts.push_back(Font::Builder(minikinFont).setStyle(style).build()); 985e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka } else { 9980a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka std::shared_ptr<MinikinFont> minikinFont = 100e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka std::make_shared<FreeTypeMinikinFontForTest>(fontPath, 101e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka atoi((const char*)index)); 102a22996e31226e3dcbfb0c57d03ca9ac54028fc28Seigo Nonaka fonts.push_back(Font::Builder(minikinFont).setStyle(style).build()); 1035e6bc85d69a97d8db6c068e56614aaac02da347aSeigo Nonaka } 1041c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 10541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka 10641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang"); 107dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka std::shared_ptr<FontFamily> family; 10841718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka if (lang == nullptr) { 10980a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka family = std::make_shared<FontFamily>(variant, std::move(fonts)); 11041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka } else { 111b47e9b21077d2a0847a64fa713aa9892196b5d2aSeigo Nonaka uint32_t langId = registerLocaleList(std::string((const char*)lang, xmlStrlen(lang))); 11280a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka family = std::make_shared<FontFamily>(langId, variant, std::move(fonts)); 11341718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka } 1141c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka families.push_back(family); 1151c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka } 1161c2bd209d11e59ea3a31d49ec4e97725fd711beaSeigo Nonaka xmlFreeDoc(doc); 11780a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka return families; 11880a9239d6943878f28a898537e060f821b9aa603Seigo Nonaka} 1199dffc23bd79a82e75181e33974af05da62dc6306Seigo Nonaka 1209dffc23bd79a82e75181e33974af05da62dc6306Seigo Nonakastd::shared_ptr<FontCollection> buildFontCollection(const std::string& filePath) { 121e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka return std::make_shared<FontCollection>(buildFontFamily(filePath)); 122e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka} 123e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka 124e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonakastd::shared_ptr<FontFamily> buildFontFamily(const std::string& filePath) { 12554e248ac7fa00d430092a8e993c83fccd4f72df5Seigo Nonaka auto font = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(filePath)); 126e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka std::vector<Font> fonts; 127a22996e31226e3dcbfb0c57d03ca9ac54028fc28Seigo Nonaka fonts.push_back(Font::Builder(font).build()); 128e1cfa7d7a17f9e24a27132032ec2f77a63e99913Seigo Nonaka return std::make_shared<FontFamily>(std::move(fonts)); 1299dffc23bd79a82e75181e33974af05da62dc6306Seigo Nonaka} 1309dffc23bd79a82e75181e33974af05da62dc6306Seigo Nonaka 1317fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonakastd::shared_ptr<FontFamily> buildFontFamily(const std::string& filePath, const std::string& lang) { 1323998e6fc7fb9cdd27e056253fa2af6de221da926Seigo Nonaka auto font = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(filePath)); 1337fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka std::vector<Font> fonts; 1347fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka fonts.push_back(Font::Builder(font).build()); 1357fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka return std::make_shared<FontFamily>(LocaleListCache::getId(lang), FontFamily::Variant::DEFAULT, 1367fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka std::move(fonts)); 1377fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka} 1387fbdd83e92a76c955c67a1c761088b36daf7158cSeigo Nonaka 13914e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka} // namespace minikin 140