1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/gfx/test/fontconfig_util_linux.h" 6 7 #include <fontconfig/fontconfig.h> 8 9 #include "base/files/file_util.h" 10 #include "base/logging.h" 11 #include "base/strings/stringprintf.h" 12 13 namespace gfx { 14 15 const char* const kSystemFontsForFontconfig[] = { 16 "/usr/share/fonts/truetype/kochi/kochi-gothic.ttf", 17 "/usr/share/fonts/truetype/kochi/kochi-mincho.ttf", 18 "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 19 "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf", 20 "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold_Italic.ttf", 21 "/usr/share/fonts/truetype/msttcorefonts/Arial_Italic.ttf", 22 "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf", 23 "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS_Bold.ttf", 24 "/usr/share/fonts/truetype/msttcorefonts/Courier_New.ttf", 25 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf", 26 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold_Italic.ttf", 27 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Italic.ttf", 28 "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf", 29 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold.ttf", 30 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold_Italic.ttf", 31 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Italic.ttf", 32 "/usr/share/fonts/truetype/msttcorefonts/Impact.ttf", 33 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS.ttf", 34 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold.ttf", 35 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold_Italic.ttf", 36 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Italic.ttf", 37 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf", 38 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold.ttf", 39 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold_Italic.ttf", 40 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Italic.ttf", 41 "/usr/share/fonts/truetype/msttcorefonts/Verdana.ttf", 42 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold.ttf", 43 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold_Italic.ttf", 44 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Italic.ttf", 45 // The DejaVuSans font is used by the css2.1 tests. 46 "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", 47 "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_hi.ttf", 48 "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_ta.ttf", 49 "/usr/share/fonts/truetype/ttf-indic-fonts-core/MuktiNarrow.ttf", 50 }; 51 52 const size_t kNumSystemFontsForFontconfig = 53 arraysize(kSystemFontsForFontconfig); 54 55 const char kFontconfigFileHeader[] = 56 "<?xml version=\"1.0\"?>\n" 57 "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n" 58 "<fontconfig>\n"; 59 const char kFontconfigFileFooter[] = "</fontconfig>"; 60 const char kFontconfigMatchHeader[] = " <match>\n"; 61 const char kFontconfigMatchFooter[] = " </match>\n"; 62 63 void SetUpFontconfig() { 64 FcInit(); 65 66 // A primer on undocumented FcConfig reference-counting: 67 // 68 // - FcConfigCreate() creates a config with a refcount of 1. 69 // - FcConfigReference() increments a config's refcount. 70 // - FcConfigDestroy() decrements a config's refcount, deallocating the 71 // config when the count reaches 0. 72 // - FcConfigSetCurrent() calls FcConfigDestroy() on the old config, but 73 // interestingly does not call FcConfigReference() on the new config. 74 CHECK(FcConfigSetCurrent(FcConfigCreate())); 75 } 76 77 void TearDownFontconfig() { 78 FcFini(); 79 } 80 81 bool LoadFontIntoFontconfig(const base::FilePath& path) { 82 if (!base::PathExists(path)) { 83 LOG(ERROR) << "You are missing " << path.value() << ". Try re-running " 84 << "build/install-build-deps.sh. Also see " 85 << "http://code.google.com/p/chromium/wiki/LayoutTestsLinux"; 86 return false; 87 } 88 89 if (!FcConfigAppFontAddFile( 90 NULL, reinterpret_cast<const FcChar8*>(path.value().c_str()))) { 91 LOG(ERROR) << "Failed to load font " << path.value(); 92 return false; 93 } 94 95 return true; 96 } 97 98 bool LoadConfigFileIntoFontconfig(const base::FilePath& path) { 99 // Unlike other FcConfig functions, FcConfigParseAndLoad() doesn't default to 100 // the current config when passed NULL. So that's cool. 101 if (!FcConfigParseAndLoad(FcConfigGetCurrent(), 102 reinterpret_cast<const FcChar8*>(path.value().c_str()), FcTrue)) { 103 LOG(ERROR) << "Fontconfig failed to load " << path.value(); 104 return false; 105 } 106 return true; 107 } 108 109 bool LoadConfigDataIntoFontconfig(const base::FilePath& temp_dir, 110 const std::string& data) { 111 base::FilePath path; 112 if (!CreateTemporaryFileInDir(temp_dir, &path)) { 113 PLOG(ERROR) << "Unable to create temporary file in " << temp_dir.value(); 114 return false; 115 } 116 if (base::WriteFile(path, data.data(), data.size()) != 117 static_cast<int>(data.size())) { 118 PLOG(ERROR) << "Unable to write config data to " << path.value(); 119 return false; 120 } 121 return LoadConfigFileIntoFontconfig(path); 122 } 123 124 std::string CreateFontconfigEditStanza(const std::string& name, 125 const std::string& type, 126 const std::string& value) { 127 return base::StringPrintf( 128 " <edit name=\"%s\" mode=\"assign\">\n" 129 " <%s>%s</%s>\n" 130 " </edit>\n", 131 name.c_str(), type.c_str(), value.c_str(), type.c_str()); 132 } 133 134 std::string CreateFontconfigTestStanza(const std::string& name, 135 const std::string& op, 136 const std::string& type, 137 const std::string& value) { 138 return base::StringPrintf( 139 " <test name=\"%s\" compare=\"%s\" qual=\"any\">\n" 140 " <%s>%s</%s>\n" 141 " </test>\n", 142 name.c_str(), op.c_str(), type.c_str(), value.c_str(), type.c_str()); 143 } 144 145 std::string CreateFontconfigAliasStanza(const std::string& original_family, 146 const std::string& preferred_family) { 147 return base::StringPrintf( 148 " <alias>\n" 149 " <family>%s</family>\n" 150 " <prefer><family>%s</family></prefer>\n" 151 " </alias>\n", 152 original_family.c_str(), preferred_family.c_str()); 153 } 154 155 } // namespace gfx 156