зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1727399 - When style updates font information, make sure to invalidate style asynchronously. r=jfkthame
Some style system APIs (like StyleNewSubtree) don't deal with nested restyles really well (it'd be weird if StyleNewSubtree would end up styling not only that subtree but the whole document). To prevent breaking style system invariants, make sure to invalidate the style asynchronously using an early runner. This should ensure at most one frame of wrong metrics, but usually zero. Differential Revision: https://phabricator.services.mozilla.com/D126076
This commit is contained in:
Родитель
889ce29976
Коммит
9b0fa46c68
|
@ -136,6 +136,52 @@ bool nsPresContext::IsDOMPaintEventPending() {
|
|||
return false;
|
||||
}
|
||||
|
||||
struct WeakRunnableMethod : Runnable {
|
||||
using Method = void (nsPresContext::*)();
|
||||
|
||||
WeakRunnableMethod(const char* aName, nsPresContext* aPc, Method aMethod)
|
||||
: Runnable(aName), mPresContext(aPc), mMethod(aMethod) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
if (nsPresContext* pc = mPresContext.get()) {
|
||||
(pc->*mMethod)();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
WeakPtr<nsPresContext> mPresContext;
|
||||
Method mMethod;
|
||||
};
|
||||
|
||||
// When forcing a font-info-update reflow from style, we don't need to reframe,
|
||||
// but we'll need to restyle to pick up updated font metrics. In order to avoid
|
||||
// synchronously having to deal with multiple restyles, we use an early refresh
|
||||
// driver runner, which should prevent flashing for users.
|
||||
//
|
||||
// We might do a bit of extra work if the page flushes layout between the
|
||||
// restyle and when this happens, which is a bit unfortunate, but not worse than
|
||||
// what we used to do...
|
||||
//
|
||||
// A better solution would be to be able to synchronously initialize font
|
||||
// information from style worker threads, perhaps...
|
||||
void nsPresContext::ForceReflowForFontInfoUpdateFromStyle() {
|
||||
if (mPendingFontInfoUpdateReflowFromStyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPendingFontInfoUpdateReflowFromStyle = true;
|
||||
nsCOMPtr<nsIRunnable> ev = new WeakRunnableMethod(
|
||||
"nsPresContext::DoForceReflowForFontInfoUpdateFromStyle", this,
|
||||
&nsPresContext::DoForceReflowForFontInfoUpdateFromStyle);
|
||||
RefreshDriver()->AddEarlyRunner(ev);
|
||||
}
|
||||
|
||||
void nsPresContext::DoForceReflowForFontInfoUpdateFromStyle() {
|
||||
mPendingFontInfoUpdateReflowFromStyle = false;
|
||||
ForceReflowForFontInfoUpdate(false);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -223,6 +269,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
|
|||
mPendingThemeChanged(false),
|
||||
mPendingThemeChangeKind(0),
|
||||
mPendingUIResolutionChanged(false),
|
||||
mPendingFontInfoUpdateReflowFromStyle(false),
|
||||
mIsGlyph(false),
|
||||
mUsesExChUnits(false),
|
||||
mCounterStylesDirty(true),
|
||||
|
@ -654,24 +701,6 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
|
|||
InvalidatePaintedLayers();
|
||||
}
|
||||
|
||||
struct WeakRunnableMethod : Runnable {
|
||||
using Method = void (nsPresContext::*)();
|
||||
|
||||
WeakRunnableMethod(const char* aName, nsPresContext* aPc, Method aMethod)
|
||||
: Runnable(aName), mPresContext(aPc), mMethod(aMethod) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
if (nsPresContext* pc = mPresContext.get()) {
|
||||
(pc->*mMethod)();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
WeakPtr<nsPresContext> mPresContext;
|
||||
Method mMethod;
|
||||
};
|
||||
|
||||
nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) {
|
||||
NS_ASSERTION(!mInitialized, "attempt to reinit pres context");
|
||||
NS_ENSURE_ARG(aDeviceContext);
|
||||
|
|
|
@ -1103,10 +1103,12 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
|
||||
void UpdateCharSet(NotNull<const Encoding*> aCharSet);
|
||||
|
||||
void DoForceReflowForFontInfoUpdateFromStyle();
|
||||
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(bool aNeedsReframe);
|
||||
void ForceReflowForFontInfoUpdateFromStyle();
|
||||
|
||||
/**
|
||||
* Checks for MozAfterPaint listeners on the document
|
||||
|
@ -1311,6 +1313,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
// widget::ThemeChangeKind
|
||||
unsigned mPendingThemeChangeKind : kThemeChangeKindBits;
|
||||
unsigned mPendingUIResolutionChanged : 1;
|
||||
unsigned mPendingFontInfoUpdateReflowFromStyle : 1;
|
||||
|
||||
// Are we currently drawing an SVG glyph?
|
||||
unsigned mIsGlyph : 1;
|
||||
|
|
|
@ -47,10 +47,8 @@ void PostTraversalTask::Run() {
|
|||
break;
|
||||
|
||||
case Type::FontInfoUpdate:
|
||||
nsPresContext* pc =
|
||||
static_cast<ServoStyleSet*>(mTarget)->GetPresContext();
|
||||
if (pc) {
|
||||
pc->ForceReflowForFontInfoUpdate(/* aNeedsReframe = */ false);
|
||||
if (auto* pc = static_cast<ServoStyleSet*>(mTarget)->GetPresContext()) {
|
||||
pc->ForceReflowForFontInfoUpdateFromStyle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче