| // Copyright 2014 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "base/test/fontconfig_util_linux.h" | |
| #include <fontconfig/fontconfig.h> | |
| #include "base/base_paths.h" | |
| #include "base/environment.h" | |
| #include "base/files/file_path.h" | |
| #include "base/files/file_util.h" | |
| #include "base/logging.h" | |
| #include "base/macros.h" | |
| #include "base/path_service.h" | |
| #include "base/strings/string_util.h" | |
| #include "starboard/types.h" | |
| namespace base { | |
| namespace { | |
| const char kFontsConfTemplate[] = R"(<?xml version="1.0"?> | |
| <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> | |
| <fontconfig> | |
| <!-- Cache location. --> | |
| <cachedir>$1</cachedir> | |
| <!-- GCS-synced fonts. --> | |
| <dir>$2</dir> | |
| <!-- Default properties. --> | |
| <match target="font"> | |
| <edit name="embeddedbitmap" mode="append_last"> | |
| <bool>false</bool> | |
| </edit> | |
| </match> | |
| <!-- TODO(thomasanderson): Figure out why this is necessary. --> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>Tinos</string> | |
| </test> | |
| <test name="prgname" compare="eq"> | |
| <string>chromevox_tests</string> | |
| </test> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintslight</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Times</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>sans</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>DejaVu Sans</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>sans serif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| </match> | |
| <!-- Some layout tests specify Helvetica as a family and we need to make sure | |
| that we don't fallback to Tinos for them --> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Helvetica</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>sans-serif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>serif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>mono</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Cousine</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>monospace</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Cousine</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Courier</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Cousine</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>cursive</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Comic Sans MS</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>fantasy</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Impact</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Monaco</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Arial</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Courier New</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Cousine</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Georgia</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Gelasio</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Times New Roman</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test qual="any" name="family"> | |
| <string>Verdana</string> | |
| </test> | |
| <!-- NOT metrically compatible! --> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| </match> | |
| <!-- TODO(thomasanderson): Move these configs to be test-specific. --> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>NonAntiAliasedSans</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="antialias" mode="assign"> | |
| <bool>false</bool> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>SlightHintedGeorgia</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Gelasio</string> | |
| </edit> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintslight</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>NonHintedSans</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <!-- These deliberately contradict each other. The 'hinting' preference | |
| should take priority --> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintfull</const> | |
| </edit> | |
| <edit name="hinting" mode="assign"> | |
| <bool>false</bool> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>AutohintedSerif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="autohint" mode="assign"> | |
| <bool>true</bool> | |
| </edit> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintmedium</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>HintedSerif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="autohint" mode="assign"> | |
| <bool>false</bool> | |
| </edit> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintmedium</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>FullAndAutoHintedSerif</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="autohint" mode="assign"> | |
| <bool>true</bool> | |
| </edit> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintfull</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>SubpixelEnabledArial</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="rgba" mode="assign"> | |
| <const>rgb</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>SubpixelDisabledArial</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Arimo</string> | |
| </edit> | |
| <edit name="rgba" mode="assign"> | |
| <const>none</const> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <!-- FontConfig doesn't currently provide a well-defined way to turn on | |
| subpixel positioning. This is just an arbitrary pattern to use after | |
| turning subpixel positioning on globally to ensure that we don't have | |
| issues with our style getting cached for other tests. --> | |
| <test name="family" compare="eq"> | |
| <string>SubpixelPositioning</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <!-- See comments above --> | |
| <test name="family" compare="eq"> | |
| <string>SubpixelPositioningAhem</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>ahem</string> | |
| </edit> | |
| </match> | |
| <match target="pattern"> | |
| <test name="family" compare="eq"> | |
| <string>SlightHintedTimesNewRoman</string> | |
| </test> | |
| <edit name="family" mode="assign"> | |
| <string>Tinos</string> | |
| </edit> | |
| <edit name="hintstyle" mode="assign"> | |
| <const>hintslight</const> | |
| </edit> | |
| </match> | |
| <!-- When we encounter a character that the current font doesn't | |
| support, gfx::GetFallbackFontForChar() returns the first font | |
| that does have a glyph for the character. The list of fonts is | |
| sorted by a pattern that includes the current locale, but doesn't | |
| include a font family (which means that the fallback font depends | |
| on the locale but not on the current font). | |
| DejaVu Sans is commonly the only font that supports some | |
| characters, such as "⇧", and even when other candidates are | |
| available, DejaVu Sans is commonly first among them, because of | |
| the way Fontconfig is ordinarily configured. For example, the | |
| configuration in the Fonconfig source lists DejaVu Sans under the | |
| sans-serif generic family, and appends sans-serif to patterns | |
| that don't already include a generic family (such as the pattern | |
| in gfx::GetFallbackFontForChar()). | |
| To get the same fallback font in the layout tests, we could | |
| duplicate this configuration here, or more directly, simply | |
| append DejaVu Sans to all patterns. --> | |
| <match target="pattern"> | |
| <edit name="family" mode="append_last"> | |
| <string>DejaVu Sans</string> | |
| </edit> | |
| </match> | |
| </fontconfig> | |
| )"; | |
| } // namespace | |
| void SetUpFontconfig() { | |
| // TODO(thomasanderson): Use FONTCONFIG_SYSROOT to avoid having to write | |
| // a new fonts.conf with updated paths. | |
| std::unique_ptr<Environment> env = Environment::Create(); | |
| if (!env->HasVar("FONTCONFIG_FILE")) { | |
| // fonts.conf must be generated on-the-fly since it contains absolute paths | |
| // which may be different if | |
| // 1. The user moves/renames their build directory (or any parent dirs). | |
| // 2. The build directory is mapped on a swarming bot at a location | |
| // different from the one the buildbot used. | |
| FilePath dir_module; | |
| PathService::Get(DIR_MODULE, &dir_module); | |
| FilePath font_cache = dir_module.Append("fontconfig_caches"); | |
| FilePath test_fonts = dir_module.Append("test_fonts"); | |
| std::string fonts_conf = ReplaceStringPlaceholders( | |
| kFontsConfTemplate, {font_cache.value(), test_fonts.value()}, nullptr); | |
| // Write the data to a different file and then atomically rename it to | |
| // fonts.conf. This avoids the file being in a bad state when different | |
| // parallel tests call this function at the same time. | |
| FilePath fonts_conf_file_temp; | |
| if(!CreateTemporaryFileInDir(dir_module, &fonts_conf_file_temp)) | |
| CHECK(CreateTemporaryFile(&fonts_conf_file_temp)); | |
| CHECK( | |
| WriteFile(fonts_conf_file_temp, fonts_conf.c_str(), fonts_conf.size())); | |
| FilePath fonts_conf_file = dir_module.Append("fonts.conf"); | |
| if (ReplaceFile(fonts_conf_file_temp, fonts_conf_file, nullptr)) | |
| env->SetVar("FONTCONFIG_FILE", fonts_conf_file.value()); | |
| else | |
| env->SetVar("FONTCONFIG_FILE", fonts_conf_file_temp.value()); | |
| } | |
| CHECK(FcInit()); | |
| } | |
| void TearDownFontconfig() { | |
| FcFini(); | |
| } | |
| } // namespace base |