Bug 1715501 - patch 1 - Track codepoints with no available fonts and replacement-char family separately for each font-visibility level. r=emilio

This does not change existing behavior, but will be required once font visibility
is no longer simply a global setting. The data cached in these members depends on
the font visibility level, so currently we just flush it if the visibility pref is
modified. But in future we may be using multiple levels at the same time (in
separate contexts), so we want to maintain separate per-level caches here.

Differential Revision: https://phabricator.services.mozilla.com/D124194
This commit is contained in:
Jonathan Kew 2021-09-08 09:35:16 +00:00
Родитель fa511566f2
Коммит ffc9bc9fe0
2 изменённых файлов: 35 добавлений и 42 удалений

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

@ -519,9 +519,6 @@ bool gfxPlatformFontList::InitFontList() {
CancelLoader();
gfxFontUtils::GetPrefsFontList(kFontSystemWhitelistPref, mEnabledFontsList);
// Ensure SetVisibilityLevel will clear the mCodepointsWithNoFonts set.
mVisibilityLevel = FontVisibility::Unknown;
}
SetVisibilityLevel();
@ -594,14 +591,16 @@ bool gfxPlatformFontList::InitFontList() {
}
void gfxPlatformFontList::InitializeCodepointsWithNoFonts() {
mCodepointsWithNoFonts.reset();
mCodepointsWithNoFonts.SetRange(0, 0x1f); // C0 controls
mCodepointsWithNoFonts.SetRange(0x7f, 0x9f); // C1 controls
mCodepointsWithNoFonts.SetRange(0xE000, 0xF8FF); // PUA
mCodepointsWithNoFonts.SetRange(0xF0000, 0x10FFFD); // Supplementary PUA
mCodepointsWithNoFonts.SetRange(0xfdd0, 0xfdef); // noncharacters
for (unsigned i = 0; i <= 0x100000; i += 0x10000) {
mCodepointsWithNoFonts.SetRange(i + 0xfffe, i + 0xffff); // noncharacters
for (auto& bitset : mCodepointsWithNoFonts) {
bitset.reset();
bitset.SetRange(0, 0x1f); // C0 controls
bitset.SetRange(0x7f, 0x9f); // C1 controls
bitset.SetRange(0xE000, 0xF8FF); // PUA
bitset.SetRange(0xF0000, 0x10FFFD); // Supplementary PUA
bitset.SetRange(0xfdd0, 0xfdef); // noncharacters
for (unsigned i = 0; i <= 0x100000; i += 0x10000) {
bitset.SetRange(i + 0xfffe, i + 0xffff); // noncharacters
}
}
}
@ -615,14 +614,7 @@ void gfxPlatformFontList::SetVisibilityLevel() {
std::max(int32_t(FontVisibility::Base),
StaticPrefs::layout_css_font_visibility_level())));
}
if (newLevel != mVisibilityLevel) {
mVisibilityLevel = newLevel;
// (Re-)initialize ranges of characters for which system-wide font search
// should be skipped
InitializeCodepointsWithNoFonts();
// Forget any font family we previously chose for U+FFFD.
mReplacementCharFallbackFamily = FontFamily();
}
mVisibilityLevel = newLevel;
}
void gfxPlatformFontList::FontListChanged() {
@ -921,7 +913,7 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar(
uint32_t aCh, uint32_t aNextCh, Script aRunScript,
eFontPresentation aPresentation, const gfxFontStyle* aStyle,
FontVisibility* aVisibility) {
MOZ_ASSERT(!mCodepointsWithNoFonts.test(aCh),
MOZ_ASSERT(!mCodepointsWithNoFonts[mVisibilityLevel].test(aCh),
"don't call for codepoints already known to be unsupported");
// Try to short-circuit font fallback for U+FFFD, used to represent
@ -930,25 +922,21 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar(
// etc.
if (aCh == 0xFFFD) {
gfxFontEntry* fontEntry = nullptr;
if (mReplacementCharFallbackFamily.mIsShared &&
mReplacementCharFallbackFamily.mShared) {
auto& fallbackFamily = mReplacementCharFallbackFamily[mVisibilityLevel];
if (fallbackFamily.mIsShared && fallbackFamily.mShared) {
fontlist::Face* face =
mReplacementCharFallbackFamily.mShared->FindFaceForStyle(
SharedFontList(), *aStyle);
fallbackFamily.mShared->FindFaceForStyle(SharedFontList(), *aStyle);
if (face) {
fontEntry =
GetOrCreateFontEntry(face, mReplacementCharFallbackFamily.mShared);
*aVisibility = mReplacementCharFallbackFamily.mShared->Visibility();
fontEntry = GetOrCreateFontEntry(face, fallbackFamily.mShared);
*aVisibility = fallbackFamily.mShared->Visibility();
}
} else if (!mReplacementCharFallbackFamily.mIsShared &&
mReplacementCharFallbackFamily.mUnshared) {
fontEntry =
mReplacementCharFallbackFamily.mUnshared->FindFontForStyle(*aStyle);
*aVisibility = mReplacementCharFallbackFamily.mUnshared->Visibility();
} else if (!fallbackFamily.mIsShared && fallbackFamily.mUnshared) {
fontEntry = fallbackFamily.mUnshared->FindFontForStyle(*aStyle);
*aVisibility = fallbackFamily.mUnshared->Visibility();
}
// this should never fail, as we must have found U+FFFD in order to set
// mReplacementCharFallbackFamily at all, but better play it safe
// mReplacementCharFallbackFamily[...] at all, but better play it safe
if (fontEntry && fontEntry->HasCharacter(aCh)) {
return fontEntry->FindOrMakeFont(aStyle);
}
@ -1009,13 +997,13 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar(
// no match? add to set of non-matching codepoints
if (!font) {
mCodepointsWithNoFonts.set(aCh);
mCodepointsWithNoFonts[mVisibilityLevel].set(aCh);
} else {
*aVisibility = fallbackFamily.mIsShared
? fallbackFamily.mShared->Visibility()
: fallbackFamily.mUnshared->Visibility();
if (aCh == 0xFFFD) {
mReplacementCharFallbackFamily = fallbackFamily;
mReplacementCharFallbackFamily[mVisibilityLevel] = fallbackFamily;
}
}
@ -2593,8 +2581,9 @@ void gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
}
}
aSizes->mFontListSize +=
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
for (const auto& bitset : mCodepointsWithNoFonts) {
aSizes->mFontListSize += bitset.SizeOfExcludingThis(aMallocSizeOf);
}
aSizes->mFontListSize +=
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);

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

@ -21,6 +21,7 @@
#include "nsIMemoryReporter.h"
#include "mozilla/Attributes.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
@ -509,7 +510,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
mozilla::StyleGenericFontFamily aGenericType);
bool SkipFontFallbackForChar(uint32_t aCh) const {
return mCodepointsWithNoFonts.test(aCh);
return mCodepointsWithNoFonts[mVisibilityLevel].test(aCh);
}
// Return whether the given font-family record should be visible to CSS,
@ -869,13 +870,16 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
mLangGroupPrefFonts;
mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
// when system-wide font lookup fails for a character, cache it to skip future
// searches
gfxSparseBitSet mCodepointsWithNoFonts;
// When system-wide font lookup fails for a character, cache it to skip future
// searches. This is an array of bitsets, one for each FontVisibility level.
mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count,
gfxSparseBitSet>
mCodepointsWithNoFonts;
// the family to use for U+FFFD fallback, to avoid expensive search every time
// on pages with lots of problems
FontFamily mReplacementCharFallbackFamily;
mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count, FontFamily>
mReplacementCharFallbackFamily;
// Sorted array of lowercased family names; use ContainsSorted to test
nsTArray<nsCString> mBadUnderlineFamilyNames;