зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1722487 - Avoid some work for font list updates. r=jfkthame
Differential Revision: https://phabricator.services.mozilla.com/D123363
This commit is contained in:
Родитель
3e1dc3d1eb
Коммит
cfca657d9c
|
@ -2392,6 +2392,14 @@ mozilla::ipc::IPCResult ContentChild::RecvFontListChanged() {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow(
|
||||
bool aNeedsReframe) {
|
||||
gfxPlatform::ForceGlobalReflow(aNeedsReframe ? gfxPlatform::NeedsReframe::Yes
|
||||
: gfxPlatform::NeedsReframe::No);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvGeolocationUpdate(
|
||||
nsIDOMGeoPosition* aPosition) {
|
||||
RefPtr<nsGeolocationService> gs =
|
||||
|
|
|
@ -339,6 +339,7 @@ class ContentChild final : public PContentChild,
|
|||
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
|
||||
|
||||
mozilla::ipc::IPCResult RecvFontListChanged();
|
||||
mozilla::ipc::IPCResult RecvForceGlobalReflow(bool aNeedsReframe);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition);
|
||||
|
||||
|
|
|
@ -645,7 +645,7 @@ child:
|
|||
* This message has raised priority so that it will take precedence over
|
||||
* vsync messages to the child.
|
||||
*/
|
||||
[Priority=mediumhigh] async RebuildFontList(bool aFulLRebuild);
|
||||
[Priority=mediumhigh] async RebuildFontList(bool aFullRebuild);
|
||||
|
||||
/**
|
||||
* The shared font list has been modified, potentially adding matches
|
||||
|
@ -654,6 +654,12 @@ child:
|
|||
*/
|
||||
async FontListChanged();
|
||||
|
||||
/**
|
||||
* The font list or prefs have been updated in such a way that we might need
|
||||
* to do a reflow and maybe reframe.
|
||||
*/
|
||||
async ForceGlobalReflow(bool aNeedsReframe);
|
||||
|
||||
/**
|
||||
* A new shmem block has been added to the font list; the child process
|
||||
* should map the new block and add to its index.
|
||||
|
|
|
@ -132,7 +132,7 @@ void gfxDWriteFont::SystemTextQualityChanged() {
|
|||
// flush cached stuff that depended on the old setting, and force
|
||||
// reflow everywhere to ensure we are using correct glyph metrics.
|
||||
gfxPlatform::FlushFontAndWordCaches();
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
||||
}
|
||||
|
||||
mozilla::Atomic<bool> gfxDWriteFont::sForceGDIClassicEnabled{true};
|
||||
|
|
|
@ -2429,8 +2429,8 @@ void gfxFcPlatformFontList::CheckFontUpdates(nsITimer* aTimer, void* aThis) {
|
|||
FcConfig* current = FcConfigGetCurrent();
|
||||
if (current != pfl->GetLastConfig()) {
|
||||
pfl->UpdateFontList();
|
||||
pfl->ForceGlobalReflow();
|
||||
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
|
||||
mozilla::dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1313,9 +1313,7 @@ void gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(
|
|||
// xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch
|
||||
fl->UpdateFontList();
|
||||
|
||||
// modify a preference that will trigger reflow everywhere
|
||||
fl->ForceGlobalReflow();
|
||||
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
|
||||
dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ static const uint32_t kDefaultGlyphCacheSize = -1;
|
|||
#include "SoftwareVsyncSource.h"
|
||||
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "gfxVR.h"
|
||||
#include "VRManager.h"
|
||||
|
@ -2260,20 +2261,20 @@ void gfxPlatform::FlushFontAndWordCaches() {
|
|||
}
|
||||
|
||||
/* static */
|
||||
void gfxPlatform::ForceGlobalReflow() {
|
||||
void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
const bool reframe = aNeedsReframe == NeedsReframe::Yes;
|
||||
// Send a notification that will be observed by PresShells in this process
|
||||
// only.
|
||||
if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
|
||||
char16_t needsReframe[] = {char16_t(reframe), 0};
|
||||
obs->NotifyObservers(nullptr, "font-info-updated", needsReframe);
|
||||
}
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Modify a preference that will trigger reflow everywhere (in all
|
||||
// content processes, as well as the parent).
|
||||
static const char kPrefName[] = "font.internaluseonly.changed";
|
||||
bool fontInternalChange = Preferences::GetBool(kPrefName, false);
|
||||
Preferences::SetBool(kPrefName, !fontInternalChange);
|
||||
} else {
|
||||
// Send a notification that will be observed by PresShells in this
|
||||
// process only.
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nullptr, "font-info-updated", nullptr);
|
||||
// Propagate the change to child processes.
|
||||
for (auto* process :
|
||||
dom::ContentParent::AllProcesses(dom::ContentParent::eLive)) {
|
||||
Unused << process->SendForceGlobalReflow(reframe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -626,7 +626,8 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
* something about platform settings changes that might have an effect
|
||||
* on layout, such as font rendering settings that influence metrics.
|
||||
*/
|
||||
static void ForceGlobalReflow();
|
||||
enum class NeedsReframe : bool { No, Yes };
|
||||
static void ForceGlobalReflow(NeedsReframe);
|
||||
|
||||
static void FlushFontAndWordCaches();
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ static void FontListPrefChanged(const char* aPref, void* aData = nullptr) {
|
|||
!strcmp(aPref, "privacy.resistFingerprinting"))) {
|
||||
gfxPlatformFontList::PlatformFontList()->SetVisibilityLevel();
|
||||
if (XRE_IsParentProcess()) {
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ gfxFontListPrefObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
FontListPrefChanged(nullptr);
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -336,9 +336,6 @@ void gfxPlatformFontList::FontWhitelistPrefChanged(const char* aPref,
|
|||
dom::ContentParent::NotifyUpdatedFonts(true);
|
||||
}
|
||||
|
||||
// number of CSS generic font families
|
||||
const uint32_t kNumGenerics = 5;
|
||||
|
||||
void gfxPlatformFontList::ApplyWhitelist() {
|
||||
uint32_t numFonts = mEnabledFontsList.Length();
|
||||
mFontFamilyWhitelistActive = (numFonts > 0);
|
||||
|
@ -637,7 +634,7 @@ void gfxPlatformFontList::FontListChanged() {
|
|||
// safe to use: ensure they all get flushed.
|
||||
RebuildLocalFonts(/*aForgetLocalFaces*/ true);
|
||||
}
|
||||
ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
|
||||
}
|
||||
|
||||
void gfxPlatformFontList::GenerateFontListKey(const nsACString& aKeyName,
|
||||
|
@ -857,7 +854,7 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
|
|||
if (mStartedLoadingCmapsFrom != 0xffffffffu) {
|
||||
InitializeCodepointsWithNoFonts();
|
||||
mStartedLoadingCmapsFrom = 0xffffffffu;
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2491,7 +2488,7 @@ void gfxPlatformFontList::CleanupLoader() {
|
|||
FindFamiliesFlags::eNoAddToNamesMissedWhenSearching));
|
||||
});
|
||||
if (forceReflow) {
|
||||
ForceGlobalReflow();
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
||||
}
|
||||
|
||||
mOtherNamesMissed = nullptr;
|
||||
|
@ -2523,10 +2520,6 @@ void gfxPlatformFontList::GetPrefsAndStartLoader() {
|
|||
}
|
||||
}
|
||||
|
||||
void gfxPlatformFontList::ForceGlobalReflow() {
|
||||
gfxPlatform::ForceGlobalReflow();
|
||||
}
|
||||
|
||||
void gfxPlatformFontList::RebuildLocalFonts(bool aForgetLocalFaces) {
|
||||
for (auto* fontset : mUserFontSetList) {
|
||||
if (aForgetLocalFaces) {
|
||||
|
|
|
@ -760,9 +760,6 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||
// read the loader initialization prefs, and start it
|
||||
void GetPrefsAndStartLoader();
|
||||
|
||||
// for font list changes that affect all documents
|
||||
void ForceGlobalReflow();
|
||||
|
||||
// If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
|
||||
// be discarded (not potentially reused to satisfy the rebuilt rules),
|
||||
// because they may no longer be valid.
|
||||
|
|
|
@ -9932,7 +9932,9 @@ PresShell::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, "font-info-updated")) {
|
||||
mPresContext->ForceReflowForFontInfoUpdate();
|
||||
// See how gfxPlatform::ForceGlobalReflow encodes this.
|
||||
bool needsReframe = aData && !!aData[0];
|
||||
mPresContext->ForceReflowForFontInfoUpdate(needsReframe);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,11 +138,42 @@ bool nsPresContext::IsDOMPaintEventPending() {
|
|||
return false;
|
||||
}
|
||||
|
||||
void nsPresContext::ForceReflowForFontInfoUpdate() {
|
||||
// We can trigger reflow by pretending a font.* preference has changed;
|
||||
// this is the same mechanism as gfxPlatform::ForceGlobalReflow() uses
|
||||
// if new fonts are installed during the session, for example.
|
||||
PreferenceChanged("font.internaluseonly.changed");
|
||||
void nsPresContext::ForceReflowForFontInfoUpdate(bool aNeedsReframe) {
|
||||
// In the case of a static-clone document used for printing or print-preview,
|
||||
// this is undesirable because the nsPrintJob is holding weak refs to frames
|
||||
// that will get blown away unexpectedly by this reconstruction. So the
|
||||
// prescontext for a print/preview doc ignores the font-list update.
|
||||
//
|
||||
// This means the print document may still be using cached fonts that are no
|
||||
// longer present in the font list, but that should be safe given that all the
|
||||
// required font instances have already been created, so it won't be depending
|
||||
// on access to the font-list entries.
|
||||
//
|
||||
// XXX Actually, I think it's probably a bad idea to do *any* restyling of
|
||||
// print documents in response to pref changes. We could be in the middle
|
||||
// of printing the document, and reflowing all the frames might cause some
|
||||
// kind of unwanted mid-document discontinuity.
|
||||
if (IsPrintingOrPrintPreview()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's a user font set, discard any src:local() faces it may have
|
||||
// loaded because their font entries may no longer be valid.
|
||||
if (auto* fonts = Document()->GetFonts()) {
|
||||
fonts->GetUserFontSet()->ForgetLocalFaces();
|
||||
}
|
||||
|
||||
FlushFontCache();
|
||||
|
||||
nsChangeHint changeHint =
|
||||
aNeedsReframe ? nsChangeHint_ReconstructFrame : NS_STYLE_HINT_REFLOW;
|
||||
|
||||
// We also need to trigger restyling for ex/ch units changes to take effect,
|
||||
// if needed.
|
||||
auto restyleHint =
|
||||
UsesExChUnits() ? RestyleHint::RecascadeSubtree() : RestyleHint{0};
|
||||
|
||||
RebuildAllStyleData(changeHint, restyleHint);
|
||||
}
|
||||
|
||||
static bool IsVisualCharset(NotNull<const Encoding*> aCharset) {
|
||||
|
@ -567,46 +598,16 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
|
|||
mMissingFonts = nullptr;
|
||||
}
|
||||
}
|
||||
if (prefName.EqualsLiteral("font.internaluseonly.changed") &&
|
||||
!IsPrintingOrPrintPreview()) {
|
||||
// If there's a user font set, discard any src:local() faces it may have
|
||||
// loaded because their font entries may no longer be valid.
|
||||
if (auto* fonts = Document()->GetFonts()) {
|
||||
fonts->GetUserFontSet()->ForgetLocalFaces();
|
||||
}
|
||||
|
||||
// If there's a change to the font list, we generally need to reconstruct
|
||||
// frames, as the existing frames may be referring to fonts that are no
|
||||
// longer available. But in the case of a static-clone document used for
|
||||
// printing or print-preview, this is undesirable because the nsPrintJob
|
||||
// is holding weak refs to frames that will get blown away unexpectedly by
|
||||
// this reconstruction. So the prescontext for a print/preview doc ignores
|
||||
// the font-list update.
|
||||
//
|
||||
// This means the print document may still be using cached fonts that are
|
||||
// no longer present in the font list, but that should be safe given that
|
||||
// all the required font instances have already been created, so it won't
|
||||
// be depending on access to the font-list entries.
|
||||
//
|
||||
// XXX Actually, I think it's probably a bad idea to do *any* restyling of
|
||||
// print documents in response to pref changes. We could be in the middle
|
||||
// of printing the document, and reflowing all the frames might cause some
|
||||
// kind of unwanted mid-document discontinuity.
|
||||
changeHint |= nsChangeHint_ReconstructFrame;
|
||||
// We also need to trigger restyling for ex/ch units changes to take effect,
|
||||
// if needed.
|
||||
if (UsesExChUnits()) {
|
||||
restyleHint |= RestyleHint::RecascadeSubtree();
|
||||
}
|
||||
} else if (StringBeginsWith(prefName, "font."_ns) ||
|
||||
// Changes to font family preferences don't change anything in the
|
||||
// computed style data, so the style system won't generate a reflow
|
||||
// hint for us. We need to do that manually.
|
||||
prefName.EqualsLiteral("intl.accept_languages") ||
|
||||
// Changes to bidi prefs need to trigger a reflow (see bug 443629)
|
||||
StringBeginsWith(prefName, "bidi."_ns) ||
|
||||
// Changes to font_rendering prefs need to trigger a reflow
|
||||
StringBeginsWith(prefName, "gfx.font_rendering."_ns)) {
|
||||
if (StringBeginsWith(prefName, "font."_ns) ||
|
||||
// Changes to font family preferences don't change anything in the
|
||||
// computed style data, so the style system won't generate a reflow hint
|
||||
// for us. We need to do that manually.
|
||||
prefName.EqualsLiteral("intl.accept_languages") ||
|
||||
// Changes to bidi prefs need to trigger a reflow (see bug 443629)
|
||||
StringBeginsWith(prefName, "bidi."_ns) ||
|
||||
// Changes to font_rendering prefs need to trigger a reflow
|
||||
StringBeginsWith(prefName, "gfx.font_rendering."_ns)) {
|
||||
changeHint |= NS_STYLE_HINT_REFLOW;
|
||||
if (UsesExChUnits()) {
|
||||
restyleHint |= RestyleHint::RecascadeSubtree();
|
||||
|
|
|
@ -1114,7 +1114,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
public:
|
||||
// Used by the PresShell to force a reflow when some aspect of font info
|
||||
// has been updated, potentially affecting font selection and layout.
|
||||
void ForceReflowForFontInfoUpdate();
|
||||
void ForceReflowForFontInfoUpdate(bool aNeedsReframe);
|
||||
|
||||
/**
|
||||
* Checks for MozAfterPaint listeners on the document
|
||||
|
|
|
@ -50,7 +50,7 @@ void PostTraversalTask::Run() {
|
|||
nsPresContext* pc =
|
||||
static_cast<ServoStyleSet*>(mTarget)->GetPresContext();
|
||||
if (pc) {
|
||||
pc->ForceReflowForFontInfoUpdate();
|
||||
pc->ForceReflowForFontInfoUpdate(/* aNeedsReframe = */ false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -97,22 +97,16 @@ add_task(async function() {
|
|||
}
|
||||
}
|
||||
|
||||
// Pref "font.internaluseonly.changed" is updated when system
|
||||
// fonts change. We use it to wait for changes to be detected
|
||||
// in the browser.
|
||||
let prefBranch = Services.prefs.getBranch("font.internaluseonly.");
|
||||
|
||||
// Returns a promise that resolves when the pref is changed
|
||||
// Returns a promise that resolves when font info is changed.
|
||||
let getFontNotificationPromise = () =>
|
||||
new Promise(resolve => {
|
||||
let prefObserver = {
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
|
||||
observe() {
|
||||
prefBranch.removeObserver("changed", prefObserver);
|
||||
resolve();
|
||||
},
|
||||
};
|
||||
prefBranch.addObserver("changed", prefObserver);
|
||||
const kTopic = "font-info-updated";
|
||||
function observe() {
|
||||
Services.obs.removeObserver(observe, kTopic);
|
||||
resolve();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observe, kTopic);
|
||||
});
|
||||
|
||||
let homeDir = Services.dirsvc.get("Home", Ci.nsIFile);
|
||||
|
|
|
@ -5048,17 +5048,6 @@ const char16_t* GetQuitType() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static void ForceFontUpdate() {
|
||||
// update device context font cache
|
||||
// Dirty but easiest way:
|
||||
// Changing nsIPrefBranch entry which triggers callbacks
|
||||
// and flows into calling mDeviceContext->FlushFontCache()
|
||||
// to update the font cache in all the instance of Browsers
|
||||
static const char kPrefName[] = "font.internaluseonly.changed";
|
||||
bool fontInternalChange = Preferences::GetBool(kPrefName, false);
|
||||
Preferences::SetBool(kPrefName, !fontInternalChange);
|
||||
}
|
||||
|
||||
bool nsWindow::ExternalHandlerProcessMessage(UINT aMessage, WPARAM& aWParam,
|
||||
LPARAM& aLParam,
|
||||
MSGResult& aResult) {
|
||||
|
@ -5231,7 +5220,9 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
fontEnum->UpdateFontList(&didChange);
|
||||
ForceFontUpdate();
|
||||
if (didChange) {
|
||||
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
|
||||
}
|
||||
} // if (NS_SUCCEEDED(rv))
|
||||
} break;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче