Bug 1276594 - Don't rely on the fontconfig charmap for user fonts or app-bundled fonts; check the cmap directly instead. r=karlt

This commit is contained in:
Jonathan Kew 2016-06-15 14:35:05 +01:00
Родитель a963e59e11
Коммит 96bb44cd34
2 изменённых файлов: 71 добавлений и 20 удалений

Просмотреть файл

@ -185,9 +185,11 @@ MapFcWidth(int aFcWidth)
}
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
FcPattern* aFontPattern)
FcPattern* aFontPattern,
bool aIgnoreFcCharmap)
: gfxFontEntry(aFaceName), mFontPattern(aFontPattern),
mFTFace(nullptr), mFTFaceInitialized(false),
mIgnoreFcCharmap(aIgnoreFcCharmap),
mAspect(0.0), mFontData(nullptr)
{
// italic
@ -224,6 +226,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
FT_Face aFace)
: gfxFontEntry(aFaceName),
mFTFace(aFace), mFTFaceInitialized(true),
mIgnoreFcCharmap(true),
mAspect(0.0), mFontData(aData)
{
mWeight = aWeight;
@ -269,6 +272,19 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
mStyle = aStyle;
mStretch = aStretch;
mIsLocalUserFont = true;
// The proper setting of mIgnoreFcCharmap is tricky for fonts loaded
// via src:local()...
// If the local font happens to come from the application fontset,
// we want to set it to true so that color/svg fonts will work even
// if the default glyphs are blank; but if the local font is a non-
// sfnt face (e.g. legacy type 1) then we need to set it to false
// because our cmap-reading code will fail and we depend on FT+Fc to
// determine the coverage.
// We set the flag here, but may flip it the first time TestCharacterMap
// is called, at which point we'll look to see whether a 'cmap' is
// actually present in the font.
mIgnoreFcCharmap = true;
}
gfxFontconfigFontEntry::~gfxFontconfigFontEntry()
@ -377,11 +393,23 @@ HasChar(FcPattern *aFont, FcChar32 aCh)
bool
gfxFontconfigFontEntry::TestCharacterMap(uint32_t aCh)
{
// for system fonts, use the charmap in the pattern
if (!mIsDataUserFont) {
return HasChar(mFontPattern, aCh);
// For user fonts, or for fonts bundled with the app (which might include
// color/svg glyphs where the default glyphs may be blank, and thus confuse
// fontconfig/freetype's char map checking), we instead check the cmap
// directly for character coverage.
if (mIgnoreFcCharmap) {
// If it does not actually have a cmap, switch our strategy to use
// fontconfig's charmap after all (except for data fonts, which must
// always have a cmap to have passed OTS validation).
if (!mIsDataUserFont && !HasFontTable(TRUETYPE_TAG('c','m','a','p'))) {
mIgnoreFcCharmap = false;
// ...and continue with HasChar() below.
} else {
return gfxFontEntry::TestCharacterMap(aCh);
}
}
return gfxFontEntry::TestCharacterMap(aCh);
// otherwise (for system fonts), use the charmap in the pattern
return HasChar(mFontPattern, aCh);
}
hb_blob_t*
@ -810,7 +838,7 @@ gfxFontconfigFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
const nsAutoString& faceName = !psname.IsEmpty() ? psname : fullname;
gfxFontconfigFontEntry *fontEntry =
new gfxFontconfigFontEntry(faceName, face);
new gfxFontconfigFontEntry(faceName, face, mContainsAppFonts);
AddFontEntry(fontEntry);
if (fontEntry->IsUpright() &&
@ -927,7 +955,7 @@ gfxFcPlatformFontList::~gfxFcPlatformFontList()
}
void
gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet)
gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts)
{
// This iterates over the fonts in a font set and adds in gfxFontFamily
// objects for each family. The patterns for individual fonts are not
@ -942,7 +970,7 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet)
}
FcChar8* lastFamilyName = (FcChar8*)"";
gfxFontFamily* fontFamily = nullptr;
gfxFontconfigFontFamily* fontFamily = nullptr;
nsAutoString familyName;
for (int f = 0; f < aFontSet->nfont; f++) {
FcPattern* font = aFontSet->fonts[f];
@ -972,11 +1000,18 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet)
nsAutoString keyName(familyName);
ToLowerCase(keyName);
fontFamily = mFontFamilies.GetWeak(keyName);
fontFamily = static_cast<gfxFontconfigFontFamily*>
(mFontFamilies.GetWeak(keyName));
if (!fontFamily) {
fontFamily = new gfxFontconfigFontFamily(familyName);
mFontFamilies.Put(keyName, fontFamily);
}
// Record if the family contains fonts from the app font set
// (in which case we won't rely on fontconfig's charmap, due to
// bug 1276594).
if (aAppFonts) {
fontFamily->SetFamilyContainsAppFonts(true);
}
// Add pointers to other localized family names. Most fonts
// only have a single name, so the first call to GetString
@ -994,9 +1029,7 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet)
}
NS_ASSERTION(fontFamily, "font must belong to a font family");
gfxFontconfigFontFamily* fcFamily =
static_cast<gfxFontconfigFontFamily*>(fontFamily);
fcFamily->AddFontPattern(font);
fontFamily->AddFontPattern(font);
// map the psname, fullname ==> font family for local font lookups
nsAutoString psname, fullname;
@ -1025,13 +1058,13 @@ gfxFcPlatformFontList::InitFontList()
// iterate over available fonts
FcFontSet* systemFonts = FcConfigGetFonts(nullptr, FcSetSystem);
AddFontSetFamilies(systemFonts);
AddFontSetFamilies(systemFonts, /* aAppFonts = */ false);
mAlwaysUseFontconfigGenerics = PrefFontListsUseOnlyGenerics();
#ifdef MOZ_BUNDLED_FONTS
ActivateBundledFonts();
FcFontSet* appFonts = FcConfigGetFonts(nullptr, FcSetApplication);
AddFontSetFamilies(appFonts);
AddFontSetFamilies(appFonts, /* aAppFonts = */ true);
#endif
mOtherFamilyNamesInitialized = true;
@ -1162,8 +1195,7 @@ gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName,
return nullptr;
}
return new gfxFontconfigFontEntry(aFontName,
fontPattern,
return new gfxFontconfigFontEntry(aFontName, fontPattern,
aWeight, aStretch, aStyle);
}

Просмотреть файл

@ -93,7 +93,8 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
public:
// used for system fonts with explicit patterns
explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
FcPattern* aFontPattern);
FcPattern* aFontPattern,
bool aIgnoreFcCharmap);
// used for data fonts where the fontentry takes ownership
// of the font data and the FT_Face
@ -154,6 +155,14 @@ protected:
// FTFace - initialized when needed
FT_Face mFTFace;
bool mFTFaceInitialized;
// Whether TestCharacterMap should check the actual cmap rather than asking
// fontconfig about character coverage.
// We do this for app-bundled (rather than system) fonts, as they may
// include color glyphs that fontconfig would overlook, and for fonts
// loaded via @font-face.
bool mIgnoreFcCharmap;
double mAspect;
// data font
@ -163,7 +172,9 @@ protected:
class gfxFontconfigFontFamily : public gfxFontFamily {
public:
explicit gfxFontconfigFontFamily(const nsAString& aName) :
gfxFontFamily(aName) { }
gfxFontFamily(aName),
mContainsAppFonts(false)
{ }
void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) override;
@ -171,10 +182,17 @@ public:
// When necessary, these are enumerated within FindStyleVariations.
void AddFontPattern(FcPattern* aFontPattern);
void SetFamilyContainsAppFonts(bool aContainsAppFonts)
{
mContainsAppFonts = aContainsAppFonts;
}
protected:
virtual ~gfxFontconfigFontFamily() { }
nsTArray<nsCountedRef<FcPattern> > mFontPatterns;
bool mContainsAppFonts;
};
class gfxFontconfigFont : public gfxFT2FontBase {
@ -258,8 +276,9 @@ public:
protected:
virtual ~gfxFcPlatformFontList();
// add all the font families found in a font set
void AddFontSetFamilies(FcFontSet* aFontSet);
// Add all the font families found in a font set.
// aAppFonts indicates whether this is the system or application fontset.
void AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts);
// figure out which families fontconfig maps a generic to
// (aGeneric assumed already lowercase)