Commit 2ff93446 authored by derat's avatar derat Committed by Commit bot

linux/chromeos: Improve queries for Fontconfig defaults.

r302898 made FontRenderParams avoid calling FcFontMatch()
for empty queries, instead just sticking to the default
pattern. Many users don't have sane default patterns,
though, so instead call FcConfigSubstituteWithPat() to load
settings that aren't tied to particular font families.

Also use scoped_ptr to simplify FcPattern management and add
myself as an owner for font_render_params*.

BUG=442443,435277,423056

Review URL: https://codereview.chromium.org/811123002

Cr-Commit-Position: refs/heads/master@{#309560}
parent 1fac4392
...@@ -11,6 +11,9 @@ msw@chromium.org ...@@ -11,6 +11,9 @@ msw@chromium.org
per-file display*=oshima@chromium.org per-file display*=oshima@chromium.org
per-file screen*=oshima@chromium.org per-file screen*=oshima@chromium.org
# Font-rendering configuration.
per-file font_render_params*=derat@chromium.org
# Transform, interpolated transform and transform util. # Transform, interpolated transform and transform util.
per-file transform*=vollick@chromium.org per-file transform*=vollick@chromium.org
per-file interpolated_transform*=vollick@chromium.org per-file interpolated_transform*=vollick@chromium.org
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
...@@ -96,84 +97,97 @@ FontRenderParams::SubpixelRendering ConvertFontconfigRgba(int rgba) { ...@@ -96,84 +97,97 @@ FontRenderParams::SubpixelRendering ConvertFontconfigRgba(int rgba) {
bool QueryFontconfig(const FontRenderParamsQuery& query, bool QueryFontconfig(const FontRenderParamsQuery& query,
FontRenderParams* params_out, FontRenderParams* params_out,
std::string* family_out) { std::string* family_out) {
FcPattern* query_pattern = FcPatternCreate(); struct FcPatternDeleter {
void operator()(FcPattern* ptr) const { FcPatternDestroy(ptr); }
};
typedef scoped_ptr<FcPattern, FcPatternDeleter> ScopedFcPattern;
ScopedFcPattern query_pattern(FcPatternCreate());
CHECK(query_pattern); CHECK(query_pattern);
FcPatternAddBool(query_pattern, FC_SCALABLE, FcTrue); FcPatternAddBool(query_pattern.get(), FC_SCALABLE, FcTrue);
for (std::vector<std::string>::const_iterator it = query.families.begin(); for (std::vector<std::string>::const_iterator it = query.families.begin();
it != query.families.end(); ++it) { it != query.families.end(); ++it) {
FcPatternAddString(query_pattern, FcPatternAddString(query_pattern.get(),
FC_FAMILY, reinterpret_cast<const FcChar8*>(it->c_str())); FC_FAMILY, reinterpret_cast<const FcChar8*>(it->c_str()));
} }
if (query.pixel_size > 0) if (query.pixel_size > 0)
FcPatternAddDouble(query_pattern, FC_PIXEL_SIZE, query.pixel_size); FcPatternAddDouble(query_pattern.get(), FC_PIXEL_SIZE, query.pixel_size);
if (query.point_size > 0) if (query.point_size > 0)
FcPatternAddInteger(query_pattern, FC_SIZE, query.point_size); FcPatternAddInteger(query_pattern.get(), FC_SIZE, query.point_size);
if (query.style >= 0) { if (query.style >= 0) {
FcPatternAddInteger(query_pattern, FC_SLANT, FcPatternAddInteger(query_pattern.get(), FC_SLANT,
(query.style & Font::ITALIC) ? FC_SLANT_ITALIC : FC_SLANT_ROMAN); (query.style & Font::ITALIC) ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
FcPatternAddInteger(query_pattern, FC_WEIGHT, FcPatternAddInteger(query_pattern.get(), FC_WEIGHT,
(query.style & Font::BOLD) ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL); (query.style & Font::BOLD) ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL);
} }
FcConfigSubstitute(NULL, query_pattern, FcMatchPattern); FcConfigSubstitute(NULL, query_pattern.get(), FcMatchPattern);
FcDefaultSubstitute(query_pattern); FcDefaultSubstitute(query_pattern.get());
// If the query was non-empty, match a specific font and destroy the query ScopedFcPattern result_pattern;
// pattern. Otherwise, just use the query pattern. if (query.is_empty()) {
FcPattern* result_pattern = query_pattern; // If the query was empty, call FcConfigSubstituteWithPat() to get
if (!query.is_empty()) { // non-family-specific configuration so it can be used as the default.
result_pattern.reset(FcPatternDuplicate(query_pattern.get()));
if (!result_pattern)
return false;
FcPatternDel(result_pattern.get(), FC_FAMILY);
FcConfigSubstituteWithPat(NULL, result_pattern.get(), query_pattern.get(),
FcMatchFont);
} else {
FcResult result; FcResult result;
result_pattern = FcFontMatch(NULL, query_pattern, &result); result_pattern.reset(FcFontMatch(NULL, query_pattern.get(), &result));
FcPatternDestroy(query_pattern);
query_pattern = NULL;
if (!result_pattern) if (!result_pattern)
return false; return false;
} }
DCHECK(result_pattern);
if (family_out) { if (family_out) {
FcChar8* family = NULL; FcChar8* family = NULL;
FcPatternGetString(result_pattern, FC_FAMILY, 0, &family); FcPatternGetString(result_pattern.get(), FC_FAMILY, 0, &family);
if (family) if (family)
family_out->assign(reinterpret_cast<const char*>(family)); family_out->assign(reinterpret_cast<const char*>(family));
} }
if (params_out) { if (params_out) {
FcBool fc_antialias = 0; FcBool fc_antialias = 0;
if (FcPatternGetBool(result_pattern, FC_ANTIALIAS, 0, &fc_antialias) == if (FcPatternGetBool(result_pattern.get(), FC_ANTIALIAS, 0,
FcResultMatch) { &fc_antialias) == FcResultMatch) {
params_out->antialiasing = fc_antialias; params_out->antialiasing = fc_antialias;
} }
FcBool fc_autohint = 0; FcBool fc_autohint = 0;
if (FcPatternGetBool(result_pattern, FC_AUTOHINT, 0, &fc_autohint) == if (FcPatternGetBool(result_pattern.get(), FC_AUTOHINT, 0, &fc_autohint) ==
FcResultMatch) { FcResultMatch) {
params_out->autohinter = fc_autohint; params_out->autohinter = fc_autohint;
} }
FcBool fc_bitmap = 0; FcBool fc_bitmap = 0;
if (FcPatternGetBool(result_pattern, FC_EMBEDDED_BITMAP, 0, &fc_bitmap) == if (FcPatternGetBool(result_pattern.get(), FC_EMBEDDED_BITMAP, 0,
&fc_bitmap) ==
FcResultMatch) { FcResultMatch) {
params_out->use_bitmaps = fc_bitmap; params_out->use_bitmaps = fc_bitmap;
} }
FcBool fc_hinting = 0; FcBool fc_hinting = 0;
if (FcPatternGetBool(result_pattern, FC_HINTING, 0, &fc_hinting) == if (FcPatternGetBool(result_pattern.get(), FC_HINTING, 0, &fc_hinting) ==
FcResultMatch) { FcResultMatch) {
int fc_hint_style = FC_HINT_NONE; int fc_hint_style = FC_HINT_NONE;
if (fc_hinting) if (fc_hinting) {
FcPatternGetInteger(result_pattern, FC_HINT_STYLE, 0, &fc_hint_style); FcPatternGetInteger(
result_pattern.get(), FC_HINT_STYLE, 0, &fc_hint_style);
}
params_out->hinting = ConvertFontconfigHintStyle(fc_hint_style); params_out->hinting = ConvertFontconfigHintStyle(fc_hint_style);
} }
int fc_rgba = FC_RGBA_NONE; int fc_rgba = FC_RGBA_NONE;
if (FcPatternGetInteger(result_pattern, FC_RGBA, 0, &fc_rgba) == if (FcPatternGetInteger(result_pattern.get(), FC_RGBA, 0, &fc_rgba) ==
FcResultMatch) FcResultMatch)
params_out->subpixel_rendering = ConvertFontconfigRgba(fc_rgba); params_out->subpixel_rendering = ConvertFontconfigRgba(fc_rgba);
} }
FcPatternDestroy(result_pattern);
return true; return true;
} }
......
...@@ -47,7 +47,8 @@ class TestFontDelegate : public LinuxFontDelegate { ...@@ -47,7 +47,8 @@ class TestFontDelegate : public LinuxFontDelegate {
}; };
// Loads the first system font defined by fontconfig_util_linux.h with a base // Loads the first system font defined by fontconfig_util_linux.h with a base
// filename of |basename|. Case is ignored. // filename of |basename|. Case is ignored. FcFontMatch() requires there to be
// at least one font present.
bool LoadSystemFont(const std::string& basename) { bool LoadSystemFont(const std::string& basename) {
for (size_t i = 0; i < kNumSystemFontsForFontconfig; ++i) { for (size_t i = 0; i < kNumSystemFontsForFontconfig; ++i) {
base::FilePath path(gfx::kSystemFontsForFontconfig[i]); base::FilePath path(gfx::kSystemFontsForFontconfig[i]);
...@@ -89,21 +90,24 @@ TEST_F(FontRenderParamsTest, Default) { ...@@ -89,21 +90,24 @@ TEST_F(FontRenderParamsTest, Default) {
ASSERT_TRUE(LoadSystemFont("arial.ttf")); ASSERT_TRUE(LoadSystemFont("arial.ttf"));
ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_.path(), ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_.path(),
std::string(kFontconfigFileHeader) + std::string(kFontconfigFileHeader) +
kFontconfigMatchPatternHeader + // Specify the desired defaults via a font match rather than a pattern
// match (since this is the style generally used in /etc/fonts/conf.d).
kFontconfigMatchFontHeader +
CreateFontconfigEditStanza("antialias", "bool", "true") + CreateFontconfigEditStanza("antialias", "bool", "true") +
CreateFontconfigEditStanza("autohint", "bool", "true") + CreateFontconfigEditStanza("autohint", "bool", "true") +
CreateFontconfigEditStanza("hinting", "bool", "true") + CreateFontconfigEditStanza("hinting", "bool", "true") +
CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
CreateFontconfigEditStanza("rgba", "const", "rgb") + CreateFontconfigEditStanza("rgba", "const", "rgb") +
kFontconfigMatchFooter + kFontconfigMatchFooter +
// Add a font match for Arial; it shouldn't be used when querying for // Add a font match for Arial. Since it specifies a family, it shouldn't
// default settings: http://crbug.com/421247 // take effect when querying default settings.
kFontconfigMatchFontHeader + kFontconfigMatchFontHeader +
CreateFontconfigTestStanza("family", "eq", "string", "Arial") + CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
CreateFontconfigEditStanza("antialias", "bool", "true") + CreateFontconfigEditStanza("antialias", "bool", "true") +
CreateFontconfigEditStanza("autohint", "bool", "false") + CreateFontconfigEditStanza("autohint", "bool", "false") +
CreateFontconfigEditStanza("hinting", "bool", "true") + CreateFontconfigEditStanza("hinting", "bool", "true") +
CreateFontconfigEditStanza("hintstyle", "const", "hintfull") + CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
CreateFontconfigEditStanza("rgba", "const", "none") +
kFontconfigMatchFooter + kFontconfigMatchFooter +
kFontconfigFileFooter)); kFontconfigFileFooter));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment