mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1523181 - Don't implicitly flush the user font set.
Summary: Flushing it at a bad time can cancel loads whose timer / completion handler is in progress, which makes no sense. Reviewers: jfkthame, jwatt, heycam Tags: #secure-revision Bug #: 1523181 Differential Revision: https://phabricator.services.mozilla.com/D17856
This commit is contained in:
parent
38a8cb51e1
commit
0ebf739646
@ -1246,7 +1246,6 @@ Document::Document(const char* aContentType)
|
||||
mDidDocumentOpen(false),
|
||||
mHasDisplayDocument(false),
|
||||
mFontFaceSetDirty(true),
|
||||
mGetUserFontSetCalled(false),
|
||||
mDidFireDOMContentLoaded(true),
|
||||
mHasScrollLinkedEffect(false),
|
||||
mFrameRequestCallbacksScheduled(false),
|
||||
@ -11601,33 +11600,7 @@ nsAutoSyncOperation::~nsAutoSyncOperation() {
|
||||
}
|
||||
}
|
||||
|
||||
gfxUserFontSet* Document::GetUserFontSet(bool aFlushUserFontSet) {
|
||||
// We want to initialize the user font set lazily the first time the
|
||||
// user asks for it, rather than building it too early and forcing
|
||||
// rule cascade creation. Thus we try to enforce the invariant that
|
||||
// we *never* build the user font set until the first call to
|
||||
// GetUserFontSet. However, once it's been requested, we can't wait
|
||||
// for somebody to call GetUserFontSet in order to rebuild it (see
|
||||
// comments below in MarkUserFontSetDirty for why).
|
||||
#ifdef DEBUG
|
||||
bool userFontSetGottenBefore = mGetUserFontSetCalled;
|
||||
#endif
|
||||
// Set mGetUserFontSetCalled up front, so that FlushUserFontSet will actually
|
||||
// flush.
|
||||
mGetUserFontSetCalled = true;
|
||||
if (mFontFaceSetDirty && aFlushUserFontSet) {
|
||||
// If this assertion fails, and there have actually been changes to
|
||||
// @font-face rules, then we will call StyleChangeReflow in
|
||||
// FlushUserFontSet. If we're in the middle of reflow,
|
||||
// that's a bad thing to do, and the caller was responsible for
|
||||
// flushing first. If we're not (e.g., in frame construction), it's
|
||||
// ok.
|
||||
NS_ASSERTION(!userFontSetGottenBefore || !GetShell() ||
|
||||
!GetShell()->IsReflowLocked(),
|
||||
"FlushUserFontSet should have been called first");
|
||||
FlushUserFontSet();
|
||||
}
|
||||
|
||||
gfxUserFontSet* Document::GetUserFontSet() {
|
||||
if (!mFontFaceSet) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -11636,12 +11609,6 @@ gfxUserFontSet* Document::GetUserFontSet(bool aFlushUserFontSet) {
|
||||
}
|
||||
|
||||
void Document::FlushUserFontSet() {
|
||||
if (!mGetUserFontSetCalled) {
|
||||
return; // No one cares about this font set yet, but we want to be careful
|
||||
// to not unset our mFontFaceSetDirty bit, so when someone really
|
||||
// does we'll create it.
|
||||
}
|
||||
|
||||
if (!mFontFaceSetDirty) {
|
||||
return;
|
||||
}
|
||||
@ -11678,22 +11645,20 @@ void Document::FlushUserFontSet() {
|
||||
}
|
||||
|
||||
void Document::MarkUserFontSetDirty() {
|
||||
if (!mGetUserFontSetCalled) {
|
||||
// We want to lazily build the user font set the first time it's
|
||||
// requested (so we don't force creation of rule cascades too
|
||||
// early), so don't do anything now.
|
||||
if (mFontFaceSetDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFontFaceSetDirty = true;
|
||||
if (nsIPresShell* shell = GetShell()) {
|
||||
shell->EnsureStyleFlush();
|
||||
}
|
||||
}
|
||||
|
||||
FontFaceSet* Document::Fonts() {
|
||||
if (!mFontFaceSet) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
|
||||
mFontFaceSet = new FontFaceSet(window, this);
|
||||
GetUserFontSet(); // this will cause the user font set to be
|
||||
// created/updated
|
||||
FlushUserFontSet();
|
||||
}
|
||||
return mFontFaceSet;
|
||||
}
|
||||
|
@ -3339,7 +3339,7 @@ class Document : public nsINode,
|
||||
}
|
||||
}
|
||||
|
||||
gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
void FlushUserFontSet();
|
||||
void MarkUserFontSetDirty();
|
||||
mozilla::dom::FontFaceSet* GetFonts() { return mFontFaceSet; }
|
||||
@ -4065,9 +4065,6 @@ class Document : public nsINode,
|
||||
// Is the current mFontFaceSet valid?
|
||||
bool mFontFaceSetDirty : 1;
|
||||
|
||||
// Has GetUserFontSet() been called?
|
||||
bool mGetUserFontSetCalled : 1;
|
||||
|
||||
// True if we have fired the DOMContentLoaded event, or don't plan to fire one
|
||||
// (e.g. we're not being parsed at all).
|
||||
bool mDidFireDOMContentLoaded : 1;
|
||||
|
@ -3486,6 +3486,8 @@ bool CanvasRenderingContext2D::SetFontInternal(const nsAString& aFont,
|
||||
resizedFont.size =
|
||||
(fontStyle->mSize * c->AppUnitsPerDevPixel()) / AppUnitsPerCSSPixel();
|
||||
|
||||
c->Document()->FlushUserFontSet();
|
||||
|
||||
nsFontMetrics::Params params;
|
||||
params.language = fontStyle->mLanguage;
|
||||
params.explicitLanguage = fontStyle->mExplicitLanguage;
|
||||
@ -4026,6 +4028,7 @@ nsresult CanvasRenderingContext2D::DrawOrMeasureText(
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
|
||||
// ensure user font set is up to date
|
||||
presContext->Document()->FlushUserFontSet();
|
||||
currentFontStyle->SetUserFontSet(presContext->GetUserFontSet());
|
||||
|
||||
if (currentFontStyle->GetStyle()->size == 0.0F) {
|
||||
|
@ -1157,9 +1157,7 @@ void PresShell::Destroy() {
|
||||
}
|
||||
}
|
||||
if (mPresContext) {
|
||||
const bool mayFlushUserFontSet = false;
|
||||
gfxUserFontSet* fs = mPresContext->GetUserFontSet(mayFlushUserFontSet);
|
||||
if (fs) {
|
||||
if (gfxUserFontSet* fs = mPresContext->GetUserFontSet()) {
|
||||
uint32_t fontCount;
|
||||
uint64_t fontSize;
|
||||
fs->GetLoadStatistics(fontCount, fontSize);
|
||||
|
@ -9583,8 +9583,7 @@ static nsRect ComputeHTMLReferenceRect(nsIFrame* aFrame,
|
||||
/* static */
|
||||
already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
|
||||
nsPresContext* aPresContext, bool aIsVertical,
|
||||
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet,
|
||||
FlushUserFontSet aFlushUserFontSet) {
|
||||
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet) {
|
||||
nsFont font = aStyleFont->mFont;
|
||||
font.size = aFontSize;
|
||||
gfxFont::Orientation orientation =
|
||||
@ -9593,10 +9592,8 @@ already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
|
||||
params.language = aStyleFont->mLanguage;
|
||||
params.explicitLanguage = aStyleFont->mExplicitLanguage;
|
||||
params.orientation = orientation;
|
||||
params.userFontSet = aUseUserFontSet
|
||||
? aPresContext->GetUserFontSet(aFlushUserFontSet ==
|
||||
FlushUserFontSet::Yes)
|
||||
: nullptr;
|
||||
params.userFontSet =
|
||||
aUseUserFontSet ? aPresContext->GetUserFontSet() : nullptr;
|
||||
params.textPerf = aPresContext->GetTextPerfMetrics();
|
||||
return aPresContext->DeviceContext()->GetMetricsFor(font, params);
|
||||
}
|
||||
|
@ -2945,15 +2945,11 @@ class nsLayoutUtils {
|
||||
// from preferences.
|
||||
static uint8_t ControlCharVisibilityDefault();
|
||||
|
||||
enum class FlushUserFontSet {
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
|
||||
// Callers are responsible to ensure the user-font-set is up-to-date if
|
||||
// aUseUserFontSet is true.
|
||||
static already_AddRefed<nsFontMetrics> GetMetricsFor(
|
||||
nsPresContext* aPresContext, bool aIsVertical,
|
||||
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet,
|
||||
FlushUserFontSet aFlushUserFontSet);
|
||||
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet);
|
||||
|
||||
/**
|
||||
* Appropriately add the correct font if we are using DocumentFonts or
|
||||
|
@ -1864,8 +1864,8 @@ bool nsPresContext::HasAuthorSpecifiedRules(const nsIFrame* aFrame,
|
||||
aRuleTypeMask, UseDocumentColors());
|
||||
}
|
||||
|
||||
gfxUserFontSet* nsPresContext::GetUserFontSet(bool aFlushUserFontSet) {
|
||||
return mDocument->GetUserFontSet(aFlushUserFontSet);
|
||||
gfxUserFontSet* nsPresContext::GetUserFontSet() {
|
||||
return mDocument->GetUserFontSet();
|
||||
}
|
||||
|
||||
void nsPresContext::UserFontSetUpdated(gfxUserFontEntry* aUpdatedFont) {
|
||||
|
@ -901,7 +901,7 @@ class nsPresContext : public nsISupports,
|
||||
|
||||
bool SuppressingResizeReflow() const { return mSuppressResizeReflow; }
|
||||
|
||||
gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
|
||||
// Should be called whenever the set of fonts available in the user
|
||||
// font set changes (e.g., because a new font loads, or because the
|
||||
|
@ -2048,8 +2048,7 @@ GeckoFontMetrics Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext,
|
||||
nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
|
||||
presContext->SetUsesExChUnits(true);
|
||||
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor(
|
||||
presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet,
|
||||
nsLayoutUtils::FlushUserFontSet::No);
|
||||
presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet);
|
||||
|
||||
ret.mXSize = fm->XHeight();
|
||||
gfxFloat zeroWidth = fm->GetThebesFontGroup()
|
||||
|
@ -351,9 +351,7 @@ void ServoStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled) {
|
||||
already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleFor(
|
||||
Element* aElement, LazyComputeBehavior aMayCompute) {
|
||||
if (aMayCompute == LazyComputeBehavior::Allow) {
|
||||
PreTraverseSync();
|
||||
return ResolveStyleLazilyInternal(aElement,
|
||||
CSSPseudoElementType::NotPseudo);
|
||||
return ResolveStyleLazily(aElement, CSSPseudoElementType::NotPseudo);
|
||||
}
|
||||
|
||||
return ResolveServoStyle(*aElement);
|
||||
@ -378,6 +376,12 @@ void ServoStyleSet::PreTraverseSync() {
|
||||
// is necessary to avoid a data race when updating the cache.
|
||||
mozilla::Unused << mDocument->GetRootElement();
|
||||
|
||||
// FIXME(emilio): This shouldn't be needed in theory, the call to the same
|
||||
// function in PresShell should do the work, but as it turns out we
|
||||
// ProcessPendingRestyles() twice, and runnables from frames just constructed
|
||||
// can end up doing editing stuff, which adds stylesheets etc...
|
||||
mDocument->FlushUserFontSet();
|
||||
|
||||
ResolveMappedAttrDeclarationBlocks();
|
||||
|
||||
nsMediaFeatures::InitSystemMetrics();
|
||||
@ -536,7 +540,6 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazily(
|
||||
Element* aElement, CSSPseudoElementType aPseudoType,
|
||||
StyleRuleInclusion aRuleInclusion) {
|
||||
PreTraverseSync();
|
||||
|
||||
return ResolveStyleLazilyInternal(aElement, aPseudoType, aRuleInclusion);
|
||||
}
|
||||
|
||||
|
@ -640,8 +640,8 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout) {
|
||||
// since the reflow is what starts font loads.
|
||||
mozilla::FlushType flushType = mozilla::FlushType::Style;
|
||||
// Be safe in case this presshell is in teardown now
|
||||
nsPresContext* presContext = doc->GetPresContext();
|
||||
if (presContext && presContext->GetUserFontSet()) {
|
||||
doc->FlushUserFontSet();
|
||||
if (doc->GetUserFontSet()) {
|
||||
flushType = mozilla::FlushType::Layout;
|
||||
}
|
||||
mDontFlushLayout = mIsFlushingLayout = true;
|
||||
|
Loading…
Reference in New Issue
Block a user