mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1160506 - support intra-family font fallback. r=heycam
Fontconfig allows for fonts to be arbitrarily mapped into another font family. Under some versions of Debian and Fedora, families like Droid Sans Japanese were mapped into the Droid Sans family. To match these font families properly, it's necessary to test multiple fonts within a single given family. Since this is a relatively time consuming procedure, only do this when there are multiple regular faces for a given family.
This commit is contained in:
parent
2732ddf842
commit
8204f43ef5
@ -847,6 +847,7 @@ gfxFontconfigFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
// add font entries for each of the faces
|
||||
uint32_t numFonts = mFontPatterns.Length();
|
||||
NS_ASSERTION(numFonts, "font family containing no faces!!");
|
||||
uint32_t numRegularFaces = 0;
|
||||
for (uint32_t i = 0; i < numFonts; i++) {
|
||||
FcPattern* face = mFontPatterns[i];
|
||||
|
||||
@ -859,6 +860,12 @@ gfxFontconfigFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
new gfxFontconfigFontEntry(faceName, face);
|
||||
AddFontEntry(fontEntry);
|
||||
|
||||
if (fontEntry->IsUpright() &&
|
||||
fontEntry->Weight() == NS_FONT_WEIGHT_NORMAL &&
|
||||
fontEntry->Stretch() == NS_FONT_STRETCH_NORMAL) {
|
||||
numRegularFaces++;
|
||||
}
|
||||
|
||||
if (LOG_FONTLIST_ENABLED()) {
|
||||
LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
|
||||
" with style: %s weight: %d stretch: %d"
|
||||
@ -872,6 +879,12 @@ gfxFontconfigFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
NS_ConvertUTF16toUTF8(fullname).get()));
|
||||
}
|
||||
}
|
||||
|
||||
// somewhat arbitrary, but define a family with two or more regular
|
||||
// faces as a family for which intra-family fallback should be used
|
||||
if (numRegularFaces > 1) {
|
||||
mCheckForFallbackFaces = true;
|
||||
}
|
||||
mFaceNamesInitialized = true;
|
||||
mFontPatterns.Clear();
|
||||
SetHasStyles(true);
|
||||
|
@ -663,7 +663,8 @@ public:
|
||||
mIsSimpleFamily(false),
|
||||
mIsBadUnderlineFamily(false),
|
||||
mFamilyCharacterMapInitialized(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false)
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mCheckForFallbackFaces(false)
|
||||
{ }
|
||||
|
||||
const nsString& Name() { return mName; }
|
||||
@ -767,6 +768,7 @@ public:
|
||||
}
|
||||
|
||||
bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
|
||||
bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
|
||||
|
||||
// sort available fonts to put preferred (standard) faces towards the end
|
||||
void SortAvailableFonts();
|
||||
@ -822,6 +824,7 @@ protected:
|
||||
bool mIsBadUnderlineFamily : 1;
|
||||
bool mFamilyCharacterMapInitialized : 1;
|
||||
bool mSkipDefaultFeatureSpaceCheck : 1;
|
||||
bool mCheckForFallbackFaces : 1; // check other faces for character
|
||||
|
||||
enum {
|
||||
// for "simple" families, the faces are stored in mAvailableFonts
|
||||
|
@ -1648,6 +1648,12 @@ gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily)
|
||||
mFonts.AppendElement(ff);
|
||||
}
|
||||
}
|
||||
// for a family marked as "check fallback faces", only mark the last
|
||||
// entry so that fallbacks for a family are only checked once
|
||||
if (aFamily->CheckForFallbackFaces() &&
|
||||
!fontEntryList.IsEmpty() && !mFonts.IsEmpty()) {
|
||||
mFonts.LastElement().SetCheckForFallbackFaces();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2555,6 +2561,23 @@ gfxFontGroup::FindNonItalicFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
|
||||
int32_t aRunScript)
|
||||
{
|
||||
GlobalFontMatch data(aCh, aRunScript, &mStyle);
|
||||
aFamily->SearchAllFontsForChar(&data);
|
||||
gfxFontEntry* fe = data.mBestMatch;
|
||||
if (!fe) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool needsBold = mStyle.weight >= 600 && !fe->IsBold() &&
|
||||
mStyle.allowSyntheticWeight;
|
||||
RefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, needsBold);
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
gfxFloat
|
||||
gfxFontGroup::GetUnderlineOffset()
|
||||
{
|
||||
@ -2619,10 +2642,17 @@ gfxFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh, uint32_t aNextCh,
|
||||
return firstFont.forget();
|
||||
}
|
||||
|
||||
// If italic, test the regular face to see if it supports character.
|
||||
// Only do this for platform fonts, not userfonts.
|
||||
if (mStyle.style != NS_FONT_STYLE_NORMAL &&
|
||||
!firstFont->GetFontEntry()->IsUserFont()) {
|
||||
if (mFonts[0].CheckForFallbackFaces()) {
|
||||
RefPtr<gfxFont> font =
|
||||
FindFallbackFaceForChar(mFonts[0].Family(), aCh, aRunScript);
|
||||
if (font) {
|
||||
*aMatchType = gfxTextRange::kFontGroup;
|
||||
return font.forget();
|
||||
}
|
||||
} else if (mStyle.style != NS_FONT_STYLE_NORMAL &&
|
||||
!firstFont->GetFontEntry()->IsUserFont()) {
|
||||
// If italic, test the regular face to see if it supports
|
||||
// character. Only do this for platform fonts, not userfonts.
|
||||
RefPtr<gfxFont> font =
|
||||
FindNonItalicFaceForChar(mFonts[0].Family(), aCh);
|
||||
if (font) {
|
||||
@ -2722,17 +2752,30 @@ gfxFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh, uint32_t aNextCh,
|
||||
}
|
||||
}
|
||||
|
||||
// If italic, test the regular face to see if it supports the character.
|
||||
// Only do this for platform fonts, not userfonts.
|
||||
fe = ff.FontEntry();
|
||||
if (mStyle.style != NS_FONT_STYLE_NORMAL &&
|
||||
!fe->mIsUserFontContainer &&
|
||||
!fe->IsUserFont()) {
|
||||
font = FindNonItalicFaceForChar(ff.Family(), aCh);
|
||||
// check other family faces if needed
|
||||
if (ff.CheckForFallbackFaces()) {
|
||||
NS_ASSERTION(i == 0 ? true :
|
||||
!mFonts[i-1].CheckForFallbackFaces() ||
|
||||
!mFonts[i-1].Family()->Name().Equals(ff.Family()->Name()),
|
||||
"should only do fallback once per font family");
|
||||
font = FindFallbackFaceForChar(ff.Family(), aCh, aRunScript);
|
||||
if (font) {
|
||||
*aMatchType = gfxTextRange::kFontGroup;
|
||||
return font.forget();
|
||||
}
|
||||
} else {
|
||||
// If italic, test the regular face to see if it supports the
|
||||
// character. Only do this for platform fonts, not userfonts.
|
||||
fe = ff.FontEntry();
|
||||
if (mStyle.style != NS_FONT_STYLE_NORMAL &&
|
||||
!fe->mIsUserFontContainer &&
|
||||
!fe->IsUserFont()) {
|
||||
font = FindNonItalicFaceForChar(ff.Family(), aCh);
|
||||
if (font) {
|
||||
*aMatchType = gfxTextRange::kFontGroup;
|
||||
return font.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -882,12 +882,13 @@ protected:
|
||||
public:
|
||||
FamilyFace() : mFamily(nullptr), mFontEntry(nullptr),
|
||||
mNeedsBold(false), mFontCreated(false),
|
||||
mLoading(false), mInvalid(false)
|
||||
mLoading(false), mInvalid(false),
|
||||
mCheckForFallbackFaces(false)
|
||||
{ }
|
||||
|
||||
FamilyFace(gfxFontFamily* aFamily, gfxFont* aFont)
|
||||
: mFamily(aFamily), mNeedsBold(false), mFontCreated(true),
|
||||
mLoading(false), mInvalid(false)
|
||||
mLoading(false), mInvalid(false), mCheckForFallbackFaces(false)
|
||||
{
|
||||
NS_ASSERTION(aFont, "font pointer must not be null");
|
||||
NS_ASSERTION(!aFamily ||
|
||||
@ -900,7 +901,7 @@ protected:
|
||||
FamilyFace(gfxFontFamily* aFamily, gfxFontEntry* aFontEntry,
|
||||
bool aNeedsBold)
|
||||
: mFamily(aFamily), mNeedsBold(aNeedsBold), mFontCreated(false),
|
||||
mLoading(false), mInvalid(false)
|
||||
mLoading(false), mInvalid(false), mCheckForFallbackFaces(false)
|
||||
{
|
||||
NS_ASSERTION(aFontEntry, "font entry pointer must not be null");
|
||||
NS_ASSERTION(!aFamily ||
|
||||
@ -915,7 +916,8 @@ protected:
|
||||
mNeedsBold(aOtherFamilyFace.mNeedsBold),
|
||||
mFontCreated(aOtherFamilyFace.mFontCreated),
|
||||
mLoading(aOtherFamilyFace.mLoading),
|
||||
mInvalid(aOtherFamilyFace.mInvalid)
|
||||
mInvalid(aOtherFamilyFace.mInvalid),
|
||||
mCheckForFallbackFaces(aOtherFamilyFace.mCheckForFallbackFaces)
|
||||
{
|
||||
if (mFontCreated) {
|
||||
mFont = aOtherFamilyFace.mFont;
|
||||
@ -978,6 +980,8 @@ protected:
|
||||
void CheckState(bool& aSkipDrawing);
|
||||
void SetLoading(bool aIsLoading) { mLoading = aIsLoading; }
|
||||
void SetInvalid() { mInvalid = true; }
|
||||
bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
|
||||
void SetCheckForFallbackFaces() { mCheckForFallbackFaces = true; }
|
||||
|
||||
void SetFont(gfxFont* aFont)
|
||||
{
|
||||
@ -1006,6 +1010,7 @@ protected:
|
||||
bool mFontCreated : 1;
|
||||
bool mLoading : 1;
|
||||
bool mInvalid : 1;
|
||||
bool mCheckForFallbackFaces : 1;
|
||||
};
|
||||
|
||||
// List of font families, either named or generic.
|
||||
@ -1102,7 +1107,13 @@ protected:
|
||||
already_AddRefed<gfxFont>
|
||||
FindNonItalicFaceForChar(gfxFontFamily* aFamily, uint32_t aCh);
|
||||
|
||||
// helper methods for looking up fonts
|
||||
// search all faces in a family for a fallback in cases where it's unclear
|
||||
// whether the family might have a font for a given character
|
||||
already_AddRefed<gfxFont>
|
||||
FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
|
||||
int32_t aRunScript);
|
||||
|
||||
// helper methods for looking up fonts
|
||||
|
||||
// lookup and add a font with a given name (i.e. *not* a generic!)
|
||||
void AddPlatformFont(const nsAString& aName,
|
||||
|
Loading…
Reference in New Issue
Block a user