Bug 508725 - Part 7: Optimize restyling when a scoped style sheet changes. r=dbaron

This commit is contained in:
Cameron McCormack 2013-01-08 19:09:23 +11:00
Родитель f83b36df21
Коммит 0cdf2690f0
3 изменённых файлов: 62 добавлений и 9 удалений

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

@ -1424,6 +1424,9 @@ protected:
// re-use old pixels.
RenderFlags mRenderFlags;
// Indicates that the whole document must be restyled. Changes to scoped
// style sheets are recorded in mChangedScopeStyleRoots rather than here
// in mStylesHaveChanged.
bool mStylesHaveChanged : 1;
bool mDidInitialize : 1;
bool mIsDestroying : 1;
@ -1447,6 +1450,15 @@ protected:
bool mSuppressInterruptibleReflows : 1;
bool mScrollPositionClampingScrollPortSizeSet : 1;
// List of subtrees rooted at style scope roots that need to be restyled.
// When a change to a scoped style sheet is made, we add the style scope
// root to this array rather than setting mStylesHaveChanged = true, since
// we know we don't need to restyle the whole document. However, if in the
// same update block we have already had other changes that require
// the whole document to be restyled (i.e., mStylesHaveChanged is already
// true), then we don't bother adding the scope root here.
nsAutoTArray<nsRefPtr<mozilla::dom::Element>,1> mChangedScopeStyleRoots;
static nsIContent* gKeyDownTarget;
// Cached font inflation values. This is done to prevent changing of font

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

@ -33,7 +33,7 @@
#include "mozilla/dom/Element.h"
#include "nsIDocument.h"
#include "nsIDOMXULDocument.h"
#include "nsCSSStyleSheet.h" // XXX for UA sheet loading hack, can this go away please?
#include "nsCSSStyleSheet.h"
#include "nsIDOMCSSStyleSheet.h" // for Pref-related rule management (bugs 22963,20760,31816)
#include "nsAnimationManager.h"
#include "nsINameSpaceManager.h" // for Pref-related rule management (bugs 22963,20760,31816)
@ -2419,7 +2419,7 @@ PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
if (aUpdateType & UPDATE_STYLE) {
mStyleSet->EndUpdate();
if (mStylesHaveChanged)
if (mStylesHaveChanged || !mChangedScopeStyleRoots.IsEmpty())
ReconstructStyleData();
}
@ -4170,6 +4170,15 @@ PresShell::ReconstructFrames(void)
void
nsIPresShell::ReconstructStyleDataInternal()
{
nsAutoTArray<nsRefPtr<mozilla::dom::Element>,1> scopeRoots;
mChangedScopeStyleRoots.SwapElements(scopeRoots);
if (mStylesHaveChanged) {
// If we need to restyle everything, no need to restyle individual
// scoped style roots.
scopeRoots.Clear();
}
mStylesHaveChanged = false;
if (mIsDestroying) {
@ -4193,7 +4202,19 @@ nsIPresShell::ReconstructStyleDataInternal()
return;
}
mFrameConstructor->PostRestyleEvent(root, eRestyle_Subtree, NS_STYLE_HINT_NONE);
if (scopeRoots.IsEmpty()) {
// If scopeRoots is empty, we know that mStylesHaveChanged was true at
// the beginning of this function, and that we need to restyle the whole
// document.
mFrameConstructor->PostRestyleEvent(root, eRestyle_Subtree,
NS_STYLE_HINT_NONE);
} else {
for (uint32_t i = 0; i < scopeRoots.Length(); i++) {
Element* scopeRoot = scopeRoots[i];
mFrameConstructor->PostRestyleEvent(scopeRoot, eRestyle_Subtree,
NS_STYLE_HINT_NONE);
}
}
}
void
@ -4202,6 +4223,24 @@ nsIPresShell::ReconstructStyleDataExternal()
ReconstructStyleDataInternal();
}
void
PresShell::RecordStyleSheetChange(nsIStyleSheet* aStyleSheet)
{
if (mStylesHaveChanged)
return;
nsRefPtr<nsCSSStyleSheet> cssStyleSheet = do_QueryObject(aStyleSheet);
if (cssStyleSheet) {
Element* scopeElement = cssStyleSheet->GetScopeElement();
if (scopeElement) {
mChangedScopeStyleRoots.AppendElement(scopeElement);
return;
}
}
mStylesHaveChanged = true;
}
void
PresShell::StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
@ -4211,7 +4250,7 @@ PresShell::StyleSheetAdded(nsIDocument *aDocument,
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
}
@ -4224,7 +4263,7 @@ PresShell::StyleSheetRemoved(nsIDocument *aDocument,
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
}
@ -4234,7 +4273,7 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument,
bool aApplicable)
{
if (aStyleSheet->HasRules()) {
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
}
@ -4244,7 +4283,7 @@ PresShell::StyleRuleChanged(nsIDocument *aDocument,
nsIStyleRule* aOldStyleRule,
nsIStyleRule* aNewStyleRule)
{
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
void
@ -4252,7 +4291,7 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule)
{
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
void
@ -4260,7 +4299,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule)
{
mStylesHaveChanged = true;
RecordStyleSheetChange(aStyleSheet);
}
nsIFrame*

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

@ -440,6 +440,8 @@ protected:
void ShowEventTargetDebug();
#endif
void RecordStyleSheetChange(nsIStyleSheet* aStyleSheet);
/**
* methods that manage rules that are used to implement the associated preferences
* - initially created for bugs 31816, 20760, 22963