Commit 47f54c53 authored by Etienne Bergeron's avatar Etienne Bergeron Committed by Commit Bot

Lift font-config FcPattern accessors

This CL is lifting out the FcPattern accessors to the fontconfig_util
file. It is also adding the unittests related to that code.

The goal of this refactoring is to share the accessors with the new
fallback font caching algorithm.
R=robliao@chromium.org

Bug: 1008531
Change-Id: Ib8d0ec9ef2ec93b91247595f7b03613d640ade80
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1830059
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701317}
parent b0443c65
......@@ -24,46 +24,22 @@ namespace {
const char kFontFormatTrueType[] = "TrueType";
const char kFontFormatCFF[] = "CFF";
std::string GetFilenameFromFcPattern(FcPattern* pattern) {
const char* c_filename = nullptr;
if (FcPatternGetString(pattern, FC_FILE, 0,
reinterpret_cast<FcChar8**>(const_cast<char**>(
&c_filename))) != FcResultMatch) {
return std::string();
}
const char* sysroot =
reinterpret_cast<const char*>(FcConfigGetSysRoot(nullptr));
return std::string(sysroot ? sysroot : "") + c_filename;
}
bool IsValidFontFromPattern(FcPattern* pattern) {
// Ignore any bitmap fonts users may still have installed from last
// century.
FcBool is_scalable;
if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) !=
FcResultMatch ||
!is_scalable) {
return false;
}
// Ignore any fonts FontConfig knows about, but that we don't have
// permission to read.
std::string filename = GetFilenameFromFcPattern(pattern);
if (access(filename.c_str(), R_OK))
if (!IsFontScalable(pattern))
return false;
// Take only supported font formats on board.
FcChar8* font_format;
if (FcPatternGetString(pattern, FC_FONTFORMAT, 0, &font_format) !=
FcResultMatch) {
std::string format = GetFontFormat(pattern);
if (format != kFontFormatTrueType && format != kFontFormatCFF)
return false;
}
if (font_format &&
strcmp(reinterpret_cast<char*>(font_format), kFontFormatTrueType) != 0 &&
strcmp(reinterpret_cast<char*>(font_format), kFontFormatCFF) != 0) {
// Ignore any fonts FontConfig knows about, but that we don't have
// permission to read.
base::FilePath font_path = GetFontPath(pattern);
if (font_path.empty() || access(font_path.AsUTF8Unsafe().c_str(), R_OK))
return false;
}
return true;
}
......@@ -202,7 +178,7 @@ class CachedFont {
DCHECK(pattern);
DCHECK(char_set);
fallback_font_.name = GetFontName(pattern);
fallback_font_.filename = GetFilenameFromFcPattern(pattern);
fallback_font_.filename = GetFontPath(pattern).AsUTF8Unsafe();
fallback_font_.ttc_index = GetFontTtcIndex(pattern);
fallback_font_.is_bold = IsFontBold(pattern);
fallback_font_.is_italic = IsFontItalic(pattern);
......@@ -215,35 +191,6 @@ class CachedFont {
}
private:
static std::string GetFontName(FcPattern* pattern) {
FcChar8* familyName = nullptr;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &familyName) != FcResultMatch)
return std::string();
return std::string(reinterpret_cast<const char*>(familyName));
}
static int GetFontTtcIndex(FcPattern* pattern) {
int ttcIndex = -1;
if (FcPatternGetInteger(pattern, FC_INDEX, 0, &ttcIndex) != FcResultMatch ||
ttcIndex < 0)
return 0;
return ttcIndex;
}
static bool IsFontBold(FcPattern* pattern) {
int weight = 0;
if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch)
return false;
return weight >= FC_WEIGHT_BOLD;
}
static bool IsFontItalic(FcPattern* pattern) {
int slant = 0;
if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch)
return false;
return slant != FC_SLANT_ROMAN;
}
FallbackFontData fallback_font_;
// supported_characters_ is owned by the parent
// FcFontSet and should never be freed.
......
......@@ -33,6 +33,8 @@ GFX_EXPORT FallbackFontsCache* GetFallbackFontsCacheInstance();
// Previously blink::WebFontInfo::fallbackFontForChar.
struct FallbackFontData {
std::string name;
// TODO(etienneb): This field should be a base::FilePath and renamed
// |filepath|.
std::string filename;
int ttc_index = 0;
bool is_bold = false;
......
......@@ -42,8 +42,87 @@ FontRenderParams::SubpixelRendering ConvertFontconfigRgba(int rgba) {
}
}
// Extracts a string property from a font-config pattern (e.g. FcPattern).
std::string GetFontConfigPropertyAsString(FcPattern* pattern,
const char* property) {
FcChar8* text = nullptr;
if (FcPatternGetString(pattern, property, 0, &text) != FcResultMatch ||
text == nullptr) {
return std::string();
}
return std::string(reinterpret_cast<const char*>(text));
}
// Extracts an integer property from a font-config pattern (e.g. FcPattern).
int GetFontConfigPropertyAsInt(FcPattern* pattern,
const char* property,
int default_value) {
int value = -1;
if (FcPatternGetInteger(pattern, property, 0, &value) != FcResultMatch)
return default_value;
return value;
}
// Extracts an boolean property from a font-config pattern (e.g. FcPattern).
bool GetFontConfigPropertyAsBool(FcPattern* pattern, const char* property) {
FcBool value = FcFalse;
if (FcPatternGetBool(pattern, property, 0, &value) != FcResultMatch)
return false;
return value != FcFalse;
}
} // namespace
std::string GetFontName(FcPattern* pattern) {
return GetFontConfigPropertyAsString(pattern, FC_FAMILY);
}
std::string GetFilename(FcPattern* pattern) {
return GetFontConfigPropertyAsString(pattern, FC_FILE);
}
base::FilePath GetFontPath(FcPattern* pattern) {
std::string filename = GetFilename(pattern);
// Paths may be specified with a heading slash (e.g.
// /test_fonts/DejaVuSans.ttf).
if (!filename.empty() && base::FilePath::IsSeparator(filename[0]))
filename = filename.substr(1);
if (filename.empty())
return base::FilePath();
// Obtains the system root directory in 'config' if available. All files
// (including file properties in patterns) obtained from this 'config' are
// relative to this system root directory.
const char* sysroot =
reinterpret_cast<const char*>(FcConfigGetSysRoot(nullptr));
if (!sysroot)
return base::FilePath(filename);
return base::FilePath(sysroot).Append(filename);
}
int GetFontTtcIndex(FcPattern* pattern) {
return GetFontConfigPropertyAsInt(pattern, FC_INDEX, 0);
}
bool IsFontBold(FcPattern* pattern) {
int weight = GetFontConfigPropertyAsInt(pattern, FC_WEIGHT, FC_WEIGHT_NORMAL);
return weight >= FC_WEIGHT_BOLD;
}
bool IsFontItalic(FcPattern* pattern) {
int slant = GetFontConfigPropertyAsInt(pattern, FC_SLANT, FC_SLANT_ROMAN);
return slant != FC_SLANT_ROMAN;
}
bool IsFontScalable(FcPattern* pattern) {
return GetFontConfigPropertyAsBool(pattern, FC_SCALABLE);
}
std::string GetFontFormat(FcPattern* pattern) {
return GetFontConfigPropertyAsString(pattern, FC_FONTFORMAT);
}
void GetFontRenderParamsFromFcPattern(FcPattern* pattern,
FontRenderParams* param_out) {
FcBool fc_antialias = 0;
......
......@@ -7,6 +7,7 @@
#include <fontconfig/fontconfig.h>
#include "base/files/file_path.h"
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/gfx_export.h"
......@@ -17,6 +18,19 @@ struct FcPatternDeleter {
};
using ScopedFcPattern = std::unique_ptr<FcPattern, FcPatternDeleter>;
// FcPattern accessor wrappers.
GFX_EXPORT std::string GetFontName(FcPattern* pattern);
GFX_EXPORT std::string GetFilename(FcPattern* pattern);
GFX_EXPORT int GetFontTtcIndex(FcPattern* pattern);
GFX_EXPORT bool IsFontBold(FcPattern* pattern);
GFX_EXPORT bool IsFontItalic(FcPattern* pattern);
GFX_EXPORT bool IsFontScalable(FcPattern* pattern);
GFX_EXPORT std::string GetFontFormat(FcPattern* pattern);
// Return the path of the font. Relative to the sysroot config specified in the
// font config (see: FcConfigGetSysRoot(...)).
GFX_EXPORT base::FilePath GetFontPath(FcPattern* pattern);
// Returns the appropriate parameters for rendering the font represented by the
// font config pattern.
GFX_EXPORT void GetFontRenderParamsFromFcPattern(FcPattern* pattern,
......
......@@ -10,6 +10,61 @@
namespace gfx {
TEST(FontConfigUtilTest, FcPatternAccessors) {
ScopedFcPattern pattern(FcPatternCreate());
const char kFamilyName[] = "sans";
FcPatternAddString(pattern.get(), FC_FAMILY,
reinterpret_cast<const FcChar8*>(kFamilyName));
const char kFileName[] = "/usr/share/fonts/arial.ttf";
FcPatternAddString(pattern.get(), FC_FILE,
reinterpret_cast<const FcChar8*>(kFileName));
const int kIndex = 42;
FcPatternAddInteger(pattern.get(), FC_INDEX, kIndex);
FcPatternAddInteger(pattern.get(), FC_WEIGHT, FC_WEIGHT_BOLD);
FcPatternAddInteger(pattern.get(), FC_SLANT, FC_SLANT_ROMAN);
FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
const char kFontFormat[] = "TrueType";
FcPatternAddString(pattern.get(), FC_FONTFORMAT,
reinterpret_cast<const FcChar8*>(kFontFormat));
EXPECT_EQ(kFamilyName, GetFontName(pattern.get()));
EXPECT_EQ(kFileName, GetFilename(pattern.get()));
EXPECT_EQ(kIndex, GetFontTtcIndex(pattern.get()));
EXPECT_TRUE(IsFontBold(pattern.get()));
EXPECT_FALSE(IsFontItalic(pattern.get()));
EXPECT_TRUE(IsFontScalable(pattern.get()));
EXPECT_EQ(kFontFormat, GetFontFormat(pattern.get()));
}
TEST(FontConfigUtilTest, GetFontPathWithSysRoot) {
ScopedFcPattern pattern(FcPatternCreate());
// Save the old sysroot, if specified.
std::string old_sysroot;
const FcChar8* old_sysroot_ptr = FcConfigGetSysRoot(nullptr);
if (old_sysroot_ptr)
old_sysroot = reinterpret_cast<const char*>(old_sysroot_ptr);
// Override the sysroot.
base::FilePath sysroot("/var/opt/fonts");
FcConfigSetSysRoot(nullptr, reinterpret_cast<const FcChar8*>(
sysroot.AsUTF8Unsafe().c_str()));
// Validate that path are relative to sysroot.
const char kFileName[] = "fonts/arial.ttf";
FcPatternAddString(pattern.get(), FC_FILE,
reinterpret_cast<const FcChar8*>(kFileName));
const char kExpectedFileName[] = "/var/opt/fonts/fonts/arial.ttf";
EXPECT_EQ(base::FilePath(kExpectedFileName), GetFontPath(pattern.get()));
// Restore the old sysroot, if specified.
if (old_sysroot_ptr) {
FcConfigSetSysRoot(nullptr,
reinterpret_cast<const FcChar8*>(old_sysroot.c_str()));
}
}
TEST(FontConfigUtilTest, GetFontRenderParamsFromFcPatternWithEmptyPattern) {
ScopedFcPattern pattern(FcPatternCreate());
......
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