зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1676966 - Don't block layout on global font fallback; load character maps asynchronously, and then reflow when available. r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D98904
This commit is contained in:
Родитель
1833b8b292
Коммит
809ac36608
|
@ -61,6 +61,7 @@ support-files =
|
|||
# remove this after bug 1628486 is landed
|
||||
prefs =
|
||||
network.cookie.cookieBehavior=5
|
||||
gfx.font_rendering.fallback.async=false
|
||||
|
||||
#NB: the following are disabled
|
||||
# browser_464620_a.html
|
||||
|
|
|
@ -53,6 +53,8 @@ support-files =
|
|||
start_historyframe.html
|
||||
url1_historyframe.html
|
||||
url2_historyframe.html
|
||||
prefs =
|
||||
gfx.font_rendering.fallback.async=false
|
||||
|
||||
[test_anchor_scroll_after_document_open.html]
|
||||
[test_bfcache_plus_hash.html]
|
||||
|
|
|
@ -19,7 +19,9 @@ support-files =
|
|||
window_nsITextInputProcessor.xhtml
|
||||
title_window.xhtml
|
||||
window_swapFrameLoaders.xhtml
|
||||
|
||||
prefs =
|
||||
gfx.font_rendering.fallback.async=false
|
||||
|
||||
[test_bug120684.xhtml]
|
||||
[test_bug206691.xhtml]
|
||||
[test_bug289714.xhtml]
|
||||
|
|
|
@ -2408,12 +2408,13 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateDictionaryList(
|
|||
mozilla::ipc::IPCResult ContentChild::RecvUpdateFontList(
|
||||
nsTArray<SystemFontListEntry>&& aFontList) {
|
||||
mFontList = std::move(aFontList);
|
||||
gfxPlatform::GetPlatform()->UpdateFontList();
|
||||
gfxPlatform::GetPlatform()->UpdateFontList(true);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList() {
|
||||
gfxPlatform::GetPlatform()->UpdateFontList();
|
||||
mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
|
||||
const bool& aFullRebuild) {
|
||||
gfxPlatform::GetPlatform()->UpdateFontList(aFullRebuild);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
mozilla::ipc::IPCResult RecvUpdateFontList(
|
||||
nsTArray<SystemFontListEntry>&& aFontList);
|
||||
mozilla::ipc::IPCResult RecvRebuildFontList();
|
||||
mozilla::ipc::IPCResult RecvRebuildFontList(const bool& aFullRebuild);
|
||||
|
||||
mozilla::ipc::IPCResult RecvUpdateAppLocales(
|
||||
nsTArray<nsCString>&& aAppLocales);
|
||||
|
|
|
@ -4851,7 +4851,14 @@ void ContentParent::NotifyUpdatedDictionaries() {
|
|||
}
|
||||
}
|
||||
|
||||
void ContentParent::NotifyUpdatedFonts() {
|
||||
void ContentParent::NotifyUpdatedFonts(bool aFullRebuild) {
|
||||
if (gfxPlatformFontList::PlatformFontList()->SharedFontList()) {
|
||||
for (auto* cp : AllProcesses(eLive)) {
|
||||
Unused << cp->SendRebuildFontList(aFullRebuild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<SystemFontListEntry> fontList;
|
||||
gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList);
|
||||
|
||||
|
@ -4860,12 +4867,6 @@ void ContentParent::NotifyUpdatedFonts() {
|
|||
}
|
||||
}
|
||||
|
||||
void ContentParent::NotifyRebuildFontList() {
|
||||
for (auto* cp : AllProcesses(eLive)) {
|
||||
Unused << cp->SendRebuildFontList();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::docshell::POfflineCacheUpdateParent>
|
||||
ContentParent::AllocPOfflineCacheUpdateParent(
|
||||
nsIURI* aManifestURI, nsIURI* aDocumentURI,
|
||||
|
@ -5440,7 +5441,7 @@ mozilla::ipc::IPCResult ContentParent::RecvGetOutputColorProfileData(
|
|||
mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock(
|
||||
const uint32_t& aGeneration, const uint32_t& aIndex,
|
||||
base::SharedMemoryHandle* aOut) {
|
||||
auto fontList = gfxPlatformFontList::PlatformFontList();
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
fontList->ShareFontListShmBlockToProcess(aGeneration, aIndex, Pid(), aOut);
|
||||
return IPC_OK();
|
||||
|
@ -5449,7 +5450,7 @@ mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock(
|
|||
mozilla::ipc::IPCResult ContentParent::RecvInitializeFamily(
|
||||
const uint32_t& aGeneration, const uint32_t& aFamilyIndex,
|
||||
const bool& aLoadCmaps) {
|
||||
auto fontList = gfxPlatformFontList::PlatformFontList();
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
fontList->InitializeFamily(aGeneration, aFamilyIndex, aLoadCmaps);
|
||||
return IPC_OK();
|
||||
|
@ -5458,7 +5459,7 @@ mozilla::ipc::IPCResult ContentParent::RecvInitializeFamily(
|
|||
mozilla::ipc::IPCResult ContentParent::RecvSetCharacterMap(
|
||||
const uint32_t& aGeneration, const mozilla::fontlist::Pointer& aFacePtr,
|
||||
const gfxSparseBitSet& aMap) {
|
||||
auto fontList = gfxPlatformFontList::PlatformFontList();
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
fontList->SetCharacterMap(aGeneration, aFacePtr, aMap);
|
||||
return IPC_OK();
|
||||
|
@ -5466,7 +5467,7 @@ mozilla::ipc::IPCResult ContentParent::RecvSetCharacterMap(
|
|||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvInitOtherFamilyNames(
|
||||
const uint32_t& aGeneration, const bool& aDefer, bool* aLoaded) {
|
||||
auto fontList = gfxPlatformFontList::PlatformFontList();
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
*aLoaded = fontList->InitOtherFamilyNames(aGeneration, aDefer);
|
||||
return IPC_OK();
|
||||
|
@ -5474,12 +5475,20 @@ mozilla::ipc::IPCResult ContentParent::RecvInitOtherFamilyNames(
|
|||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvSetupFamilyCharMap(
|
||||
const uint32_t& aGeneration, const mozilla::fontlist::Pointer& aFamilyPtr) {
|
||||
auto fontList = gfxPlatformFontList::PlatformFontList();
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
fontList->SetupFamilyCharMap(aGeneration, aFamilyPtr);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvStartCmapLoading(
|
||||
const uint32_t& aGeneration, const uint32_t& aStartIndex) {
|
||||
auto* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
MOZ_RELEASE_ASSERT(fontList, "gfxPlatformFontList not initialized?");
|
||||
fontList->StartCmapLoading(aGeneration, aStartIndex);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvGetHyphDict(
|
||||
nsIURI* aURI, base::SharedMemoryHandle* aOutHandle, uint32_t* aOutSize) {
|
||||
if (!aURI) {
|
||||
|
|
|
@ -312,8 +312,11 @@ class ContentParent final
|
|||
|
||||
static void NotifyUpdatedDictionaries();
|
||||
|
||||
static void NotifyUpdatedFonts();
|
||||
static void NotifyRebuildFontList();
|
||||
// Tell content processes the font list has changed. If aFullRebuild is true,
|
||||
// the shared list has been rebuilt and must be freshly mapped by child
|
||||
// processes; if false, existing mappings are still valid but the data has
|
||||
// been updated and so full reflows are in order.
|
||||
static void NotifyUpdatedFonts(bool aFullRebuild);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
/**
|
||||
|
@ -1202,6 +1205,9 @@ class ContentParent final
|
|||
const uint32_t& aGeneration,
|
||||
const mozilla::fontlist::Pointer& aFamilyPtr);
|
||||
|
||||
mozilla::ipc::IPCResult RecvStartCmapLoading(const uint32_t& aGeneration,
|
||||
const uint32_t& aStartIndex);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetHyphDict(nsIURI* aURIParams,
|
||||
base::SharedMemoryHandle* aOutHandle,
|
||||
uint32_t* aOutSize);
|
||||
|
|
|
@ -605,10 +605,12 @@ child:
|
|||
async UpdateFontList(SystemFontListEntry[] fontList);
|
||||
|
||||
/**
|
||||
* The shared font list has been reinitialized by the parent;
|
||||
* child processes must discard and recreate their mappings to it.
|
||||
* The shared font list has been updated by the parent, so child processes
|
||||
* should globally reflow everything to pick up new character coverage etc.
|
||||
* If aFullRebuild is true, child processes must discard and recreate
|
||||
* their mappings to the shmem blocks, as those are no longer valid.
|
||||
*/
|
||||
async RebuildFontList();
|
||||
async RebuildFontList(bool aFulLRebuild);
|
||||
|
||||
/**
|
||||
* The shared font list has been modified, potentially adding matches
|
||||
|
@ -1432,6 +1434,23 @@ parent:
|
|||
*/
|
||||
sync InitOtherFamilyNames(uint32_t aGeneration, bool aDefer) returns (bool aLoaded);
|
||||
|
||||
/**
|
||||
* Ask the parent to load all font character maps, as we need to do an
|
||||
* exhaustive font-fallback search. This is done asynchronously; when it
|
||||
* finishes, the parent will trigger global reflow so that font selection
|
||||
* is re-done in all content, making use of the newly-loaded cmaps.
|
||||
* Normally this will only happen once per browser session (unless the
|
||||
* font list is rebuilt due to installation/removal of system fonts).
|
||||
*
|
||||
* @param aGeneration
|
||||
* Font-list generation, so requests relating to an obsolete list can be
|
||||
* ignored (see comments for GetFontListShmBlock).
|
||||
* @param aStartIndex
|
||||
* The family index to start from; the sender has determined that cmaps
|
||||
* up to this point are already loaded.
|
||||
*/
|
||||
async StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex);
|
||||
|
||||
/**
|
||||
* Ask the parent for a specific hyphenation resource (identified by URI)
|
||||
* as a shared memory block.
|
||||
|
|
|
@ -290,6 +290,13 @@ struct Family {
|
|||
// It is possible that character maps have not yet been loaded.
|
||||
bool IsInitialized() const { return !mFaces.IsNull(); }
|
||||
|
||||
// IsFullyInitialized indicates that not only faces but also character maps
|
||||
// have been set up, so the family can be searched without the possibility
|
||||
// that IPC messaging will be triggered.
|
||||
bool IsFullyInitialized() const {
|
||||
return IsInitialized() && !mCharacterMap.IsNull();
|
||||
}
|
||||
|
||||
void FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||
nsTArray<Face*>& aFaceList,
|
||||
bool aIgnoreSizeTolerance = false) const;
|
||||
|
|
|
@ -2298,7 +2298,7 @@ void gfxFcPlatformFontList::CheckFontUpdates(nsITimer* aTimer, void* aThis) {
|
|||
pfl->UpdateFontList();
|
||||
pfl->ForceGlobalReflow();
|
||||
|
||||
mozilla::dom::ContentParent::NotifyUpdatedFonts();
|
||||
mozilla::dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -337,6 +337,8 @@ class gfxFontCache final : private gfxFontCacheExpirationTracker {
|
|||
AgeAllGenerations();
|
||||
}
|
||||
|
||||
uint32_t Count() const { return mFonts.Count(); }
|
||||
|
||||
void FlushShapedWordCaches();
|
||||
void NotifyGlyphsChanged();
|
||||
|
||||
|
|
|
@ -1286,7 +1286,7 @@ void gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(
|
|||
// modify a preference that will trigger reflow everywhere
|
||||
fl->ForceGlobalReflow();
|
||||
|
||||
mozilla::dom::ContentParent::NotifyUpdatedFonts();
|
||||
dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
|
||||
gfxFontEntry* gfxMacPlatformFontList::PlatformGlobalFontFallback(const uint32_t aCh,
|
||||
|
|
|
@ -1791,8 +1791,8 @@ nsresult gfxPlatform::GetFontList(nsAtom* aLangGroup,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult gfxPlatform::UpdateFontList() {
|
||||
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
|
||||
nsresult gfxPlatform::UpdateFontList(bool aFullRebuild) {
|
||||
gfxPlatformFontList::PlatformFontList()->UpdateFontList(aFullRebuild);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -356,9 +356,11 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
nsTArray<mozilla::dom::SystemFontListEntry>* aFontList) {}
|
||||
|
||||
/**
|
||||
* Rebuilds the any cached system font lists
|
||||
* Rebuilds the system font lists (if aFullRebuild is true), or just notifies
|
||||
* content that the list has changed but existing memory mappings are still
|
||||
* valid (aFullRebuild is false).
|
||||
*/
|
||||
virtual nsresult UpdateFontList();
|
||||
nsresult UpdateFontList(bool aFullRebuild = true);
|
||||
|
||||
/**
|
||||
* Create the platform font-list object (gfxPlatformFontList concrete
|
||||
|
|
|
@ -302,8 +302,9 @@ gfxPlatformFontList::~gfxPlatformFontList() {
|
|||
void gfxPlatformFontList::FontWhitelistPrefChanged(const char* aPref,
|
||||
void* aClosure) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
|
||||
mozilla::dom::ContentParent::NotifyUpdatedFonts();
|
||||
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
pfl->UpdateFontList(true);
|
||||
dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
|
||||
// number of CSS generic font families
|
||||
|
@ -442,8 +443,8 @@ nsresult gfxPlatformFontList::InitFontList() {
|
|||
// rebuilding fontlist so clear out font/word caches
|
||||
gfxFontCache* fontCache = gfxFontCache::GetCache();
|
||||
if (fontCache) {
|
||||
fontCache->AgeAllGenerations();
|
||||
fontCache->FlushShapedWordCaches();
|
||||
fontCache->Flush();
|
||||
}
|
||||
|
||||
gfxPlatform::PurgeSkiaFontCache();
|
||||
|
@ -458,6 +459,9 @@ nsresult gfxPlatformFontList::InitFontList() {
|
|||
mAliasTable.Clear();
|
||||
mLocalNameTable.Clear();
|
||||
|
||||
CancelLoadCmapsTask();
|
||||
mStartedLoadingCmapsFrom = 0xffffffffu;
|
||||
|
||||
CancelInitOtherFamilyNamesTask();
|
||||
MutexAutoLock lock(mFontFamiliesMutex);
|
||||
mFontFamilies.Clear();
|
||||
|
@ -509,7 +513,7 @@ nsresult gfxPlatformFontList::InitFontList() {
|
|||
if (oldSharedList) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
// notify all children of the change
|
||||
mozilla::dom::ContentParent::NotifyRebuildFontList();
|
||||
dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +544,18 @@ nsresult gfxPlatformFontList::InitFontList() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
void gfxPlatformFontList::SetVisibilityLevel() {
|
||||
FontVisibility newLevel;
|
||||
if (StaticPrefs::privacy_resistFingerprinting()) {
|
||||
|
@ -554,15 +570,7 @@ void gfxPlatformFontList::SetVisibilityLevel() {
|
|||
mVisibilityLevel = newLevel;
|
||||
// (Re-)initialize ranges of characters for which system-wide font search
|
||||
// should be skipped
|
||||
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
|
||||
}
|
||||
InitializeCodepointsWithNoFonts();
|
||||
// Forget any font family we previously chose for U+FFFD.
|
||||
mReplacementCharFallbackFamily = FontFamily();
|
||||
}
|
||||
|
@ -570,6 +578,7 @@ void gfxPlatformFontList::SetVisibilityLevel() {
|
|||
|
||||
void gfxPlatformFontList::FontListChanged() {
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
InitializeCodepointsWithNoFonts();
|
||||
if (SharedFontList()) {
|
||||
// If we're using a shared local face-name list, this may have changed
|
||||
// such that existing font entries held by user font sets are no longer
|
||||
|
@ -799,10 +808,16 @@ void gfxPlatformFontList::LoadBadUnderlineList() {
|
|||
mBadUnderlineFamilyNames.Sort();
|
||||
}
|
||||
|
||||
void gfxPlatformFontList::UpdateFontList() {
|
||||
void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
InitFontList();
|
||||
RebuildLocalFonts();
|
||||
if (aFullRebuild) {
|
||||
InitFontList();
|
||||
RebuildLocalFonts();
|
||||
} else {
|
||||
InitializeCodepointsWithNoFonts();
|
||||
mStartedLoadingCmapsFrom = 0xffffffffu;
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
}
|
||||
}
|
||||
|
||||
bool gfxPlatformFontList::IsVisibleToCSS(const gfxFontFamily& aFamily) const {
|
||||
|
@ -997,6 +1012,8 @@ gfxFont* gfxPlatformFontList::CommonFontFallback(
|
|||
if (!family || !IsVisibleToCSS(*family)) {
|
||||
continue;
|
||||
}
|
||||
// XXX(jfkthame) Should we fire the async cmap-loader here, or let it
|
||||
// always do a potential sync initialization of the family?
|
||||
family->SearchAllFontsForChar(SharedFontList(), &data);
|
||||
if (data.mBestMatch) {
|
||||
aMatchedFamily = FontFamily(family);
|
||||
|
@ -1075,10 +1092,17 @@ gfxFont* gfxPlatformFontList::GlobalFontFallback(
|
|||
if (!IsVisibleToCSS(family)) {
|
||||
continue;
|
||||
}
|
||||
family.SearchAllFontsForChar(SharedFontList(), &data);
|
||||
if (data.mMatchDistance == 0.0) {
|
||||
// no better style match is possible, so stop searching
|
||||
break;
|
||||
if (!family.IsFullyInitialized() &&
|
||||
StaticPrefs::gfx_font_rendering_fallback_async()) {
|
||||
// Start loading all the missing charmaps; but this is async,
|
||||
// so for now we just continue, ignoring this family.
|
||||
StartCmapLoadingFromFamily(i);
|
||||
} else {
|
||||
family.SearchAllFontsForChar(SharedFontList(), &data);
|
||||
if (data.mMatchDistance == 0.0) {
|
||||
// no better style match is possible, so stop searching
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.mBestMatch) {
|
||||
|
@ -1120,6 +1144,150 @@ gfxFont* gfxPlatformFontList::GlobalFontFallback(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
class StartCmapLoadingRunnable : public mozilla::Runnable {
|
||||
public:
|
||||
explicit StartCmapLoadingRunnable(uint32_t aStartIndex)
|
||||
: Runnable("gfxPlatformFontList::StartCmapLoadingRunnable"),
|
||||
mStartIndex(aStartIndex) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
auto* list = pfl->SharedFontList();
|
||||
if (!list) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (mStartIndex >= list->NumFamilies()) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (XRE_IsParentProcess()) {
|
||||
pfl->StartCmapLoading(list->GetGeneration(), mStartIndex);
|
||||
} else {
|
||||
dom::ContentChild::GetSingleton()->SendStartCmapLoading(
|
||||
list->GetGeneration(), mStartIndex);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mStartIndex;
|
||||
};
|
||||
|
||||
void gfxPlatformFontList::StartCmapLoadingFromFamily(uint32_t aStartIndex) {
|
||||
if (aStartIndex > mStartedLoadingCmapsFrom) {
|
||||
// We already initiated cmap-loading from somewhere earlier in the list;
|
||||
// no need to do it again here.
|
||||
return;
|
||||
}
|
||||
mStartedLoadingCmapsFrom = aStartIndex;
|
||||
|
||||
// If we're already on the main thread, don't bother dispatching a runnable
|
||||
// here to kick off the loading process, just do it directly.
|
||||
if (NS_IsMainThread()) {
|
||||
auto* list = SharedFontList();
|
||||
if (XRE_IsParentProcess()) {
|
||||
StartCmapLoading(list->GetGeneration(), aStartIndex);
|
||||
} else {
|
||||
dom::ContentChild::GetSingleton()->SendStartCmapLoading(
|
||||
list->GetGeneration(), aStartIndex);
|
||||
}
|
||||
} else {
|
||||
NS_DispatchToMainThread(new StartCmapLoadingRunnable(aStartIndex));
|
||||
}
|
||||
}
|
||||
|
||||
class LoadCmapsRunnable : public CancelableRunnable {
|
||||
public:
|
||||
explicit LoadCmapsRunnable(uint32_t aGeneration, uint32_t aFamilyIndex)
|
||||
: CancelableRunnable("gfxPlatformFontList::LoadCmapsRunnable"),
|
||||
mGeneration(aGeneration),
|
||||
mStartIndex(aFamilyIndex),
|
||||
mIndex(aFamilyIndex) {}
|
||||
|
||||
// Reset the current family index, if the value passed is earlier than our
|
||||
// original starting position. We don't "reset" if it would move the current
|
||||
// position forward, or back into the already-scanned range.
|
||||
// We could optimize further by remembering the current position reached,
|
||||
// and then skipping ahead from the original start, but it doesn't seem worth
|
||||
// extra complexity for a task that usually only happens once, and already-
|
||||
// processed families will be skipped pretty quickly in Run() anyhow.
|
||||
void MaybeResetIndex(uint32_t aFamilyIndex) {
|
||||
if (aFamilyIndex < mStartIndex) {
|
||||
mStartIndex = aFamilyIndex;
|
||||
mIndex = aFamilyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Cancel() override {
|
||||
mIsCanceled = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
if (mIsCanceled) {
|
||||
return NS_OK;
|
||||
}
|
||||
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
auto* list = pfl->SharedFontList();
|
||||
MOZ_ASSERT(list);
|
||||
if (!list) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (mGeneration != list->GetGeneration()) {
|
||||
return NS_OK;
|
||||
}
|
||||
uint32_t numFamilies = list->NumFamilies();
|
||||
if (mIndex >= numFamilies) {
|
||||
return NS_OK;
|
||||
}
|
||||
auto* families = list->Families();
|
||||
// Skip any families that are already initialized.
|
||||
while (mIndex < numFamilies && families[mIndex].IsFullyInitialized()) {
|
||||
++mIndex;
|
||||
}
|
||||
// Fully process one family, and advance index.
|
||||
if (mIndex < numFamilies) {
|
||||
Unused << pfl->InitializeFamily(&families[mIndex], true);
|
||||
++mIndex;
|
||||
}
|
||||
// If there are more families to initialize, post ourselves back to the
|
||||
// idle queue to handle the next one; otherwise we're finished and we need
|
||||
// to notify content processes to update their rendering.
|
||||
if (mIndex < numFamilies) {
|
||||
RefPtr<CancelableRunnable> task = this;
|
||||
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
|
||||
} else {
|
||||
pfl->CancelLoadCmapsTask();
|
||||
pfl->InitializeCodepointsWithNoFonts();
|
||||
dom::ContentParent::NotifyUpdatedFonts(false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mGeneration;
|
||||
uint32_t mStartIndex;
|
||||
uint32_t mIndex;
|
||||
bool mIsCanceled = false;
|
||||
};
|
||||
|
||||
void gfxPlatformFontList::StartCmapLoading(uint32_t aGeneration,
|
||||
uint32_t aStartIndex) {
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
if (aGeneration != SharedFontList()->GetGeneration()) {
|
||||
return;
|
||||
}
|
||||
if (mLoadCmapsRunnable) {
|
||||
// We already have a runnable; just make sure it covers the full range of
|
||||
// families needed.
|
||||
static_cast<LoadCmapsRunnable*>(mLoadCmapsRunnable.get())
|
||||
->MaybeResetIndex(aStartIndex);
|
||||
return;
|
||||
}
|
||||
mLoadCmapsRunnable = new LoadCmapsRunnable(aGeneration, aStartIndex);
|
||||
RefPtr<CancelableRunnable> task = mLoadCmapsRunnable;
|
||||
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
|
||||
}
|
||||
|
||||
gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) {
|
||||
if (aFamily && !aFamily->HasStyles()) {
|
||||
aFamily->FindStyleVariations();
|
||||
|
|
|
@ -203,7 +203,9 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||
virtual void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts);
|
||||
|
||||
void UpdateFontList();
|
||||
// Pass false to notify content that the shared font list has been modified
|
||||
// but not completely invalidated.
|
||||
void UpdateFontList(bool aFullRebuild = true);
|
||||
|
||||
virtual void ClearLangGroupPrefFonts();
|
||||
|
||||
|
@ -281,6 +283,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||
void SetupFamilyCharMap(uint32_t aGeneration,
|
||||
const mozilla::fontlist::Pointer& aFamilyPtr);
|
||||
|
||||
// Start the async cmap loading process, if not already under way, from the
|
||||
// given family index. (For use in any process that needs font lookups.)
|
||||
void StartCmapLoadingFromFamily(uint32_t aStartIndex);
|
||||
|
||||
// [Parent] Handle request from content process to start cmap loading.
|
||||
void StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex);
|
||||
|
||||
void CancelLoadCmapsTask() {
|
||||
if (mLoadCmapsRunnable) {
|
||||
mLoadCmapsRunnable->Cancel();
|
||||
mLoadCmapsRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate aFamily with face records, and if aLoadCmaps is true, also load
|
||||
// their character maps (rather than leaving this to be done lazily).
|
||||
// Note that even when aFamily->IsInitialized() is true, it can make sense
|
||||
|
@ -480,6 +496,9 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||
// Initialize the current visibility level from user prefs.
|
||||
void SetVisibilityLevel();
|
||||
|
||||
// (Re-)initialize the set of codepoints that we know cannot be rendered.
|
||||
void InitializeCodepointsWithNoFonts();
|
||||
|
||||
// If using the shared font list, returns a generation count that is
|
||||
// incremented if/when the platform list is reinitialized (e.g. because
|
||||
// fonts are installed/removed while the browser is running), such that
|
||||
|
@ -863,6 +882,9 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||
|
||||
RefPtr<gfxFontEntry> mDefaultFontEntry;
|
||||
|
||||
RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
|
||||
uint32_t mStartedLoadingCmapsFrom = 0xffffffffu;
|
||||
|
||||
FontVisibility mVisibilityLevel = FontVisibility::Unknown;
|
||||
|
||||
bool mFontFamilyWhitelistActive;
|
||||
|
|
|
@ -201,11 +201,6 @@ nsresult gfxPlatformGtk::GetFontList(nsAtom* aLangGroup,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult gfxPlatformGtk::UpdateFontList() {
|
||||
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// xxx - this is ubuntu centric, need to go through other distros and flesh
|
||||
// out a more general list
|
||||
static const char kFontDejaVuSans[] = "DejaVu Sans";
|
||||
|
|
|
@ -40,8 +40,6 @@ class gfxPlatformGtk final : public gfxPlatform {
|
|||
nsresult GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts) override;
|
||||
|
||||
nsresult UpdateFontList() override;
|
||||
|
||||
void GetCommonFallbackFonts(uint32_t aCh, Script aRunScript,
|
||||
eFontPresentation aPresentation,
|
||||
nsTArray<const char*>& aFontList) override;
|
||||
|
|
|
@ -2926,8 +2926,17 @@ gfxFont* gfxFontGroup::FindFallbackFaceForChar(
|
|||
gfxFont* gfxFontGroup::FindFallbackFaceForChar(
|
||||
fontlist::Family* aFamily, uint32_t aCh, uint32_t aNextCh,
|
||||
eFontPresentation aPresentation) {
|
||||
fontlist::FontList* list =
|
||||
gfxPlatformFontList::PlatformFontList()->SharedFontList();
|
||||
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
auto* list = pfl->SharedFontList();
|
||||
|
||||
// If async fallback is enabled, and the family isn't fully initialized yet,
|
||||
// just start the async cmap loading and return.
|
||||
if (!aFamily->IsFullyInitialized() &&
|
||||
StaticPrefs::gfx_font_rendering_fallback_async()) {
|
||||
pfl->StartCmapLoadingFromFamily(aFamily - list->Families());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GlobalFontMatch data(aCh, aNextCh, mStyle, aPresentation);
|
||||
aFamily->SearchAllFontsForChar(list, &data);
|
||||
gfxFontEntry* fe = data.mBestMatch;
|
||||
|
|
|
@ -3,6 +3,8 @@ support-files =
|
|||
bug287446_subframe.html
|
||||
bug477700_subframe.html
|
||||
bug564115_window.html
|
||||
prefs =
|
||||
gfx.font_rendering.fallback.async=false
|
||||
|
||||
[test_bug231389.html]
|
||||
[test_bug287446.html]
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# Font-matching reftests may fail intermittently/transiently due to asynch fallback,
|
||||
# so we disable the async mechanism for this directory.
|
||||
defaults pref(gfx.font_rendering.fallback.async,false)
|
||||
|
||||
== CSS21-t1502-no-inherited-font-family.xhtml CSS21-t1502-no-inherited-font-family-ref.xhtml
|
||||
|
||||
# tests for bug 1394311 (case-insensitive lang tag processing)
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == currency-1.html currency-1-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == currency-2.html currency-2-ref.html # Bug 1392106
|
||||
== datetime-1.html datetime-1-ref.html
|
||||
== emoji-1.html emoji-1-ref.html
|
||||
== emoji-2.html emoji-2-ref.html
|
||||
pref(gfx.font_rendering.fallback.async,false) == emoji-1.html emoji-1-ref.html
|
||||
pref(gfx.font_rendering.fallback.async,false) == emoji-2.html emoji-2-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == hyphens-1.html hyphens-1-ref.html # Bug 1392106
|
||||
== hyphens-2.html hyphens-2-ref.html
|
||||
# The following three tests may fail if rendering with Core Text (see bug 389074)
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
# and layout/reftests/w3c-css/submitted/multicol3/
|
||||
# Pagination tests
|
||||
# asserts(3) == abspos-breaking-000.xhtml abspos-breaking-000.ref.xhtml # bug 1067755, 1135556
|
||||
asserts(3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-001.xhtml abspos-breaking-000.ref.xhtml # Bug 1655630, Bug 1392106
|
||||
asserts(3-6) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-001.xhtml abspos-breaking-000.ref.xhtml # Bug 1655630, Bug 1392106
|
||||
asserts(3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-002.xhtml abspos-breaking-000.ref.xhtml # Bug 1655630, Bug 1392106
|
||||
asserts(2) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-003.html abspos-breaking-003-ref.html # Bug 1655630, Bug 1392106
|
||||
asserts(2-3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-003.html abspos-breaking-003-ref.html # Bug 1655630, Bug 1392106
|
||||
asserts(4) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-004.html abspos-breaking-004-ref.html # Bug 1655630, Bug 1392106
|
||||
asserts(4) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-005.html abspos-breaking-005-ref.html # Bug 1655630, Bug 1392106
|
||||
asserts(4) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == abspos-breaking-006.html abspos-breaking-006-ref.html # Bug 1655630, Bug 1392106
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# Font-dependent reftests may fail intermittently/transiently due to asynch fallback,
|
||||
# so we disable the async mechanism for this directory.
|
||||
defaults pref(gfx.font_rendering.fallback.async,false)
|
||||
|
||||
fails-if(Android) == fallback-01.xhtml fallback-01-ref.xhtml
|
||||
== font-selection-by-lang-01.html font-selection-by-lang-01-ref.html
|
||||
== font-selection-fallback-1.html font-selection-fallback-1-ref.html
|
||||
|
@ -371,3 +375,6 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == segment-break-transforma
|
|||
|
||||
# sub and sup elements should be influenced by their container's line-height - bug 1524897
|
||||
== sub-sup-and-line-height.html sub-sup-and-line-height-ref.html
|
||||
|
||||
# Reset default prefs.
|
||||
defaults
|
||||
|
|
|
@ -4334,6 +4334,11 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
- name: gfx.font_rendering.fallback.async
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether to enable LayerScope tool and default listening port.
|
||||
- name: gfx.layerscope.enabled
|
||||
type: RelaxedAtomicBool
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[bidi-flag-emoji.html]
|
||||
prefs: [gfx.font_rendering.fallback.async:false]
|
|
@ -0,0 +1 @@
|
|||
prefs: [gfx.font_rendering.fallback.async:false]
|
|
@ -0,0 +1 @@
|
|||
prefs: [gfx.font_rendering.fallback.async:false]
|
|
@ -0,0 +1,2 @@
|
|||
[disclosure-styles.html]
|
||||
prefs: [gfx.font_rendering.fallback.async:false]
|
|
@ -1,3 +1,4 @@
|
|||
[symbols-function.html]
|
||||
prefs: [gfx.font_rendering.fallback.async:false]
|
||||
expected:
|
||||
if (processor == "x86") and not debug: ["PASS", "TIMEOUT"]
|
||||
|
|
|
@ -53,6 +53,8 @@ support-files =
|
|||
rtlchrome/rtl.css
|
||||
rtlchrome/rtl.dtd
|
||||
rtlchrome/rtl.manifest
|
||||
prefs =
|
||||
gfx.font_rendering.fallback.async=false
|
||||
|
||||
[test_about_networking.html]
|
||||
[test_arrowpanel.xhtml]
|
||||
|
|
Загрузка…
Ссылка в новой задаче