Bug 1180120 - Part 7: Add eRestyleResult_StopWithStyleChange. r=dbaron

This commit is contained in:
Cameron McCormack 2015-08-29 06:13:48 +10:00
parent f7742cef5d
commit d32a93dce9
4 changed files with 384 additions and 61 deletions

View File

@ -2876,6 +2876,114 @@ ElementRestyler::MustCheckUndisplayedContent(nsIContent*& aUndisplayedParent)
return !!aUndisplayedParent;
}
/**
* Helper for MoveStyleContextsForChildren, below. Appends the style
* contexts to be moved to mFrame's current (new) style context to
* aContextsToMove.
*/
bool
ElementRestyler::MoveStyleContextsForContentChildren(
nsIFrame* aParent,
nsStyleContext* aOldContext,
nsTArray<nsStyleContext*>& aContextsToMove)
{
nsIFrame::ChildListIterator lists(aParent);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
// Bail out if we have out-of-flow frames.
// FIXME: It might be safe to just continue here instead of bailing out.
if (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
return false;
}
if (GetPrevContinuationWithSameStyle(child)) {
continue;
}
// Bail out if we have placeholder frames.
// FIXME: It is probably safe to just continue here instead of bailing out.
if (nsGkAtoms::placeholderFrame == child->GetType()) {
return false;
}
nsStyleContext* sc = child->StyleContext();
if (sc->GetParent() != aOldContext) {
return false;
}
nsIAtom* type = child->GetType();
if (type == nsGkAtoms::letterFrame ||
type == nsGkAtoms::lineFrame) {
return false;
}
if (sc->HasChildThatUsesGrandancestorStyle()) {
// XXX Not sure if we need this?
return false;
}
nsIAtom* pseudoTag = sc->GetPseudo();
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement) {
return false;
}
aContextsToMove.AppendElement(sc);
}
}
return true;
}
/**
* Traverses to child elements (through the current frame's same style
* continuations, just like RestyleChildren does) and moves any style context
* for those children to be parented under mFrame's current (new) style
* context.
*
* False is returned if it encounters any conditions on the child elements'
* frames and style contexts that means it is impossible to move a
* style context. If false is returned, no style contexts will have been
* moved.
*/
bool
ElementRestyler::MoveStyleContextsForChildren(nsStyleContext* aOldContext)
{
// Bail out if there are undisplayed or display:contents children.
// FIXME: We could get this to work if we need to.
nsIContent* undisplayedParent;
if (MustCheckUndisplayedContent(undisplayedParent)) {
nsCSSFrameConstructor* fc = mPresContext->FrameConstructor();
if (fc->GetAllUndisplayedContentIn(undisplayedParent) ||
fc->GetAllDisplayContentsIn(undisplayedParent)) {
return false;
}
}
nsTArray<nsStyleContext*> contextsToMove;
MOZ_ASSERT(!MustReframeForBeforePseudo(),
"shouldn't need to reframe ::before as we would have had "
"eRestyle_Subtree and wouldn't get in here");
DebugOnly<nsIFrame*> lastContinuation;
for (nsIFrame* f = mFrame; f;
f = GetNextContinuationWithSameStyle(f, f->StyleContext())) {
lastContinuation = f;
if (!MoveStyleContextsForContentChildren(f, aOldContext, contextsToMove)) {
return false;
}
}
MOZ_ASSERT(!MustReframeForAfterPseudo(lastContinuation),
"shouldn't need to reframe ::after as we would have had "
"eRestyle_Subtree and wouldn't get in here");
nsStyleContext* newParent = mFrame->StyleContext();
for (nsStyleContext* child : contextsToMove) {
// We can have duplicate entries in contextsToMove, so only move
// each style context once.
if (child->GetParent() != newParent) {
child->MoveTo(newParent);
}
}
return true;
}
/**
* Recompute style for mFrame (which should not have a prev continuation
* with the same style), all of its next continuations with the same
@ -2962,6 +3070,8 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
nsRefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
nsTArray<SwapInstruction> swaps;
// TEMPORARY (until bug 918064): Call RestyleSelf for each
// continuation or block-in-inline sibling.
@ -2976,7 +3086,8 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
bool haveMoreContinuations = false;
for (nsIFrame* f = mFrame; f; ) {
RestyleResult thisResult = RestyleSelf(f, thisRestyleHint, &swappedStructs);
RestyleResult thisResult =
RestyleSelf(f, thisRestyleHint, &swappedStructs, swaps);
if (thisResult != eRestyleResult_Stop) {
// Calls to RestyleSelf for later same-style continuations must not
@ -2985,8 +3096,9 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
if (result == eRestyleResult_Stop) {
// We received eRestyleResult_Stop for earlier same-style
// continuations, and eRestyleResult_Continue(AndForceDescendants) for
// this one; go back and force-restyle the earlier continuations.
// continuations, and eRestyleResult_StopWithStyleChange or
// eRestyleResult_Continue(AndForceDescendants) for this one; go
// back and force-restyle the earlier continuations.
result = thisResult;
f = mFrame;
continue;
@ -3066,6 +3178,50 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
return;
}
if (result == eRestyleResult_StopWithStyleChange &&
!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
MOZ_ASSERT(mFrame->StyleContext() != oldContext,
"eRestyleResult_StopWithStyleChange should only be returned "
"if we got a new style context or we will reconstruct");
MOZ_ASSERT(swappedStructs == 0,
"should have ensured we didn't swap structs when "
"returning eRestyleResult_StopWithStyleChange");
// We need to ensure that all of the frames that inherit their style
// from oldContext are able to be moved across to newContext.
// MoveStyleContextsForChildren will check for certain conditions
// to ensure it is safe to move all of the relevant child style
// contexts to newContext. If these conditions fail, it will
// return false, and we'll have to continue restyling.
const bool canStop = MoveStyleContextsForChildren(oldContext);
if (canStop) {
// Send the accessibility notifications that RestyleChildren otherwise
// would have sent.
if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
InitializeAccessibilityNotifications(mFrame->StyleContext());
SendAccessibilityNotifications();
}
mRestyleTracker.AddRestyleRootsIfAwaitingRestyle(descendants);
if (aRestyleHint & eRestyle_SomeDescendants) {
AddPendingRestylesForDescendantsMatchingSelectors(mContent);
}
return;
}
// Turns out we couldn't stop restyling here. Process the struct
// swaps that RestyleSelf would've done had we not returned
// eRestyleResult_StopWithStyleChange.
for (SwapInstruction& swap : swaps) {
LOG_RESTYLE("swapping style structs between %p and %p",
swap.mOldContext.get(), swap.mNewContext.get());
swap.mOldContext->SwapStyleData(swap.mNewContext, swap.mStructsToSwap);
swappedStructs |= swap.mStructsToSwap;
}
swaps.Clear();
}
if (!swappedStructs) {
// If we swapped any structs from the old context, then we need to keep
// it alive until after the RestyleChildren call so that we can fix up
@ -3122,8 +3278,10 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
* conditions that would preclude stopping restyling, and
* eRestyleResult_Continue if it does.
*/
ElementRestyler::RestyleResult
ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
void
ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf,
RestyleResult& aRestyleResult,
bool& aCanStopWithStyleChange)
{
// We can't handle situations where the primary style context of a frame
// has not had any style data changes, but its additional style contexts
@ -3131,7 +3289,9 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
// style contexts.
if (aSelf->GetAdditionalStyleContext(0)) {
LOG_RESTYLE_CONTINUE("there are additional style contexts");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
// Style changes might have moved children between the two nsLetterFrames
@ -3143,12 +3303,16 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
if (type == nsGkAtoms::letterFrame) {
LOG_RESTYLE_CONTINUE("frame is a letter frame");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
if (type == nsGkAtoms::lineFrame) {
LOG_RESTYLE_CONTINUE("frame is a line frame");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
// Some style computations depend not on the parent's style, but a grandparent
@ -3161,19 +3325,25 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
nsStyleContext* oldContext = aSelf->StyleContext();
if (oldContext->HasChildThatUsesGrandancestorStyle()) {
LOG_RESTYLE_CONTINUE("the old context uses grandancestor style");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
// We ignore all situations that involve :visited style.
if (oldContext->GetStyleIfVisited()) {
LOG_RESTYLE_CONTINUE("the old style context has StyleIfVisited");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
nsStyleContext* parentContext = oldContext->GetParent();
if (parentContext && parentContext->GetStyleIfVisited()) {
LOG_RESTYLE_CONTINUE("the old style context's parent has StyleIfVisited");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
// We also ignore frames for pseudos, as their style contexts have
@ -3184,7 +3354,9 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
nsIAtom* pseudoTag = oldContext->GetPseudo();
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement) {
LOG_RESTYLE_CONTINUE("the old style context is for a pseudo");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
nsIFrame* parent = mFrame->GetParent();
@ -3196,23 +3368,37 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf)
nsIAtom* parentPseudoTag = parent->StyleContext()->GetPseudo();
if (parentPseudoTag && parentPseudoTag != nsCSSAnonBoxes::mozNonElement) {
LOG_RESTYLE_CONTINUE("the old style context's parent is for a pseudo");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
// Parent style context pseudo-ness doesn't affect whether we can
// return eRestyleResult_StopWithStyleChange.
//
// If we had later conditions to check in this function, we would
// continue to check them, in case we set aCanStopWithStyleChange to
// false.
}
}
return eRestyleResult_Stop;
}
ElementRestyler::RestyleResult
void
ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
nsStyleContext* aNewContext)
nsStyleContext* aNewContext,
RestyleResult& aRestyleResult,
bool& aCanStopWithStyleChange)
{
// If we've already determined that we must continue styling, we don't
// need to check anything.
if (aRestyleResult == eRestyleResult_Continue && !aCanStopWithStyleChange) {
return;
}
// Keep restyling if the new style context has any style-if-visted style, so
// that we can avoid the style context tree surgery having to deal to deal
// with visited styles.
if (aNewContext->GetStyleIfVisited()) {
LOG_RESTYLE_CONTINUE("the new style context has StyleIfVisited");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
// If link-related information has changed, or the pseudo for the frame has
@ -3222,11 +3408,23 @@ ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
if (oldContext->IsLinkContext() != aNewContext->IsLinkContext() ||
oldContext->RelevantLinkVisited() != aNewContext->RelevantLinkVisited() ||
oldContext->GetPseudo() != aNewContext->GetPseudo() ||
oldContext->GetPseudoType() != aNewContext->GetPseudoType() ||
oldContext->RuleNode() != aNewContext->RuleNode()) {
oldContext->GetPseudoType() != aNewContext->GetPseudoType()) {
LOG_RESTYLE_CONTINUE("the old and new style contexts have different link/"
"visited/pseudo/rulenodes");
return eRestyleResult_Continue;
"visited/pseudo");
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
if (oldContext->RuleNode() != aNewContext->RuleNode()) {
LOG_RESTYLE_CONTINUE("the old and new style contexts have different "
"rulenodes");
aRestyleResult = eRestyleResult_Continue;
// Continue to check other conditions if aCanStopWithStyleChange might
// still need to be set to false.
if (!aCanStopWithStyleChange) {
return;
}
}
// If the old and new style contexts differ in their
@ -3237,31 +3435,37 @@ ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
aNewContext->HasTextDecorationLines()) {
LOG_RESTYLE_CONTINUE("NS_STYLE_HAS_TEXT_DECORATION_LINES differs between old"
" and new style contexts");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
if (oldContext->HasPseudoElementData() !=
aNewContext->HasPseudoElementData()) {
LOG_RESTYLE_CONTINUE("NS_STYLE_HAS_PSEUDO_ELEMENT_DATA differs between old"
" and new style contexts");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
if (oldContext->ShouldSuppressLineBreak() !=
aNewContext->ShouldSuppressLineBreak()) {
LOG_RESTYLE_CONTINUE("NS_STYLE_SUPPRESS_LINEBREAK differs"
"between old and new style contexts");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
if (oldContext->IsInDisplayNoneSubtree() !=
aNewContext->IsInDisplayNoneSubtree()) {
LOG_RESTYLE_CONTINUE("NS_STYLE_IN_DISPLAY_NONE_SUBTREE differs between old"
" and new style contexts");
return eRestyleResult_Continue;
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
return;
}
return eRestyleResult_Stop;
}
bool
@ -3305,7 +3509,8 @@ ElementRestyler::CanReparentStyleContext(nsRestyleHint aRestyleHint)
ElementRestyler::RestyleResult
ElementRestyler::RestyleSelf(nsIFrame* aSelf,
nsRestyleHint aRestyleHint,
uint32_t* aSwappedStructs)
uint32_t* aSwappedStructs,
nsTArray<SwapInstruction>& aSwaps)
{
MOZ_ASSERT(!(aRestyleHint & eRestyle_LaterSiblings),
"eRestyle_LaterSiblings must not be part of aRestyleHint");
@ -3323,14 +3528,44 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
RestyleManager::RestyleHintToString(aRestyleHint).get());
LOG_RESTYLE_INDENT();
RestyleResult result;
// Initially assume that it is safe to stop restyling.
//
// Throughout most of this function, we update the following two variables
// independently. |result| is set to eRestyleResult_Continue when we
// detect a condition that would not allow us to return eRestyleResult_Stop.
// |canStopWithStyleChange| is set to false when we detect a condition
// that would not allow us to return eRestyleResult_StopWithStyleChange.
//
// Towards the end of this function, we reconcile these two variables --
// if |canStopWithStyleChange| is true, we convert |result| into
// eRestyleResult_StopWithStyleChange.
RestyleResult result = eRestyleResult_Stop;
bool canStopWithStyleChange = true;
if (aRestyleHint & ~eRestyle_SomeDescendants) {
// If we are doing any restyling of the current element, or if we're
// forced to continue, we must.
result = eRestyleResult_Continue;
} else {
result = ComputeRestyleResultFromFrame(aSelf);
// If we have to restyle children, we can't return
// eRestyleResult_StopWithStyleChange.
if (aRestyleHint & (eRestyle_Subtree | eRestyle_Force |
eRestyle_ForceDescendants)) {
canStopWithStyleChange = false;
}
}
// We only consider returning eRestyleResult_StopWithStyleChange if this
// is the root of the restyle. (Otherwise, we would need to track the
// style changes of the ancestors we just restyled.)
if (!mIsRootOfRestyle) {
canStopWithStyleChange = false;
}
// Look at the frame and its current style context for conditions
// that would change our RestyleResult.
ComputeRestyleResultFromFrame(aSelf, result, canStopWithStyleChange);
nsChangeHint assumeDifferenceHint = NS_STYLE_HINT_NONE;
nsRefPtr<nsStyleContext> oldContext = aSelf->StyleContext();
nsStyleSet* styleSet = mPresContext->StyleSet();
@ -3378,6 +3613,7 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
LOG_RESTYLE_CONTINUE("we had a provider frame");
// Continue restyling past the odd style context inheritance.
result = eRestyleResult_Continue;
canStopWithStyleChange = false;
}
if (providerFrame != aSelf->GetParent()) {
@ -3515,6 +3751,7 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
newContext = oldContext;
// Never consider stopping restyling at the root.
result = eRestyleResult_Continue;
canStopWithStyleChange = false;
}
}
@ -3524,22 +3761,21 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
(const char*) "");
if (newContext != oldContext) {
if (result == eRestyleResult_Stop) {
if (oldContext->IsShared()) {
// If the old style context was shared, then we can't return
// eRestyleResult_Stop and patch its parent to point to the
// new parent style context, as that change might not be valid
// for the other frames sharing the style context.
LOG_RESTYLE_CONTINUE("the old style context is shared");
result = eRestyleResult_Continue;
} else {
// Look at some details of the new style context to see if it would
// be safe to stop restyling, if we discover it has the same style
// data as the old style context.
result = ComputeRestyleResultFromNewContext(aSelf, newContext);
}
if (oldContext->IsShared()) {
// If the old style context was shared, then we can't return
// eRestyleResult_Stop and patch its parent to point to the
// new parent style context, as that change might not be valid
// for the other frames sharing the style context.
LOG_RESTYLE_CONTINUE("the old style context is shared");
result = eRestyleResult_Continue;
}
// Look at some details of the new style context to see if it would
// be safe to stop restyling, if we discover it has the same style
// data as the old style context.
ComputeRestyleResultFromNewContext(aSelf, newContext,
result, canStopWithStyleChange);
uint32_t equalStructs = 0;
uint32_t samePointerStructs = 0;
@ -3569,6 +3805,7 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
if (changedStyle) {
LOG_RESTYLE_CONTINUE("TryStartingTransition changed the new style context");
result = eRestyleResult_Continue;
canStopWithStyleChange = false;
}
CaptureChange(oldContext, newContext, assumeDifferenceHint,
&equalStructs, &samePointerStructs);
@ -3582,6 +3819,25 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
}
}
if (canStopWithStyleChange) {
// If any inherited struct pointers are different, or if any
// reset struct pointers are different and we have descendants
// that rely on those reset struct pointers, we can't return
// eRestyleResult_StopWithStyleChange.
if ((samePointerStructs & NS_STYLE_INHERITED_STRUCT_MASK) !=
NS_STYLE_INHERITED_STRUCT_MASK) {
LOG_RESTYLE("can't return eRestyleResult_StopWithStyleChange since "
"there is different inherited data");
canStopWithStyleChange = false;
} else if ((samePointerStructs & NS_STYLE_RESET_STRUCT_MASK) !=
NS_STYLE_RESET_STRUCT_MASK &&
oldContext->HasChildThatUsesResetStyle()) {
LOG_RESTYLE("can't return eRestyleResult_StopWithStyleChange since "
"there is different reset data and descendants use it");
canStopWithStyleChange = false;
}
}
if (result == eRestyleResult_Stop) {
// Since we currently have eRestyleResult_Stop, we know at this
// point that all of our style structs are equal in terms of styles.
@ -3616,6 +3872,21 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
}
}
// From this point we no longer do any assignments of
// eRestyleResult_Continue to |result|. If canStopWithStyleChange is true,
// it means that we can convert |result| (whether it is
// eRestyleResult_Continue or eRestyleResult_Stop) into
// eRestyleResult_StopWithStyleChange.
if (canStopWithStyleChange) {
LOG_RESTYLE("converting %s into eRestyleResult_StopWithStyleChange",
RestyleResultToString(result).get());
result = eRestyleResult_StopWithStyleChange;
}
if (aRestyleHint & eRestyle_ForceDescendants) {
result = eRestyleResult_ContinueAndForceDescendants;
}
if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
// If the frame gets regenerated, let it keep its old context,
// which is important to maintain various invariants about
@ -3639,10 +3910,20 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
LOG_RESTYLE("not swapping style structs, since the new context is "
"shared");
} else {
LOG_RESTYLE("swapping style structs between %p and %p",
oldContext.get(), newContext.get());
oldContext->SwapStyleData(newContext, equalStructs);
*aSwappedStructs |= equalStructs;
if (result == eRestyleResult_StopWithStyleChange) {
LOG_RESTYLE("recording a style struct swap between %p and %p to "
"do if eRestyleResult_StopWithStyleChange fails",
oldContext.get(), newContext.get());
SwapInstruction* swap = aSwaps.AppendElement();
swap->mOldContext = oldContext;
swap->mNewContext = newContext;
swap->mStructsToSwap = equalStructs;
} else {
LOG_RESTYLE("swapping style structs between %p and %p",
oldContext.get(), newContext.get());
oldContext->SwapStyleData(newContext, equalStructs);
*aSwappedStructs |= equalStructs;
}
#ifdef RESTYLE_LOGGING
uint32_t structs = RestyleManager::StructsToLog() & equalStructs;
if (structs) {
@ -3669,6 +3950,10 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
// parent, but we don't have that information here.
mSwappedStructOwners.AppendElement(newContext->GetParent());
}
} else {
if (aRestyleHint & eRestyle_ForceDescendants) {
result = eRestyleResult_ContinueAndForceDescendants;
}
}
oldContext = nullptr;
@ -3743,10 +4028,6 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
}
}
if (aRestyleHint & eRestyle_ForceDescendants) {
result = eRestyleResult_ContinueAndForceDescendants;
}
LOG_RESTYLE("returning %s", RestyleResultToString(result).get());
return result;
@ -3924,8 +4205,16 @@ ElementRestyler::ComputeStyleChangeFor(nsIFrame* aFrame,
selectorsForDescendants.AppendElements(
aRestyleHintData.mSelectorsForDescendants);
nsTArray<nsIContent*> visibleKidsOfHiddenElement;
for (nsIFrame* ibSibling = aFrame; ibSibling;
ibSibling = GetNextBlockInInlineSibling(propTable, ibSibling)) {
nsIFrame* nextIBSibling;
for (nsIFrame* ibSibling = aFrame; ibSibling; ibSibling = nextIBSibling) {
nextIBSibling = GetNextBlockInInlineSibling(propTable, ibSibling);
if (nextIBSibling) {
// Don't allow some ib-split siblings to be processed with
// eRestyleResult_StopWithStyleChange and others not.
aRestyleHint |= eRestyle_Force;
}
// Outer loop over ib-split siblings
for (nsIFrame* cont = ibSibling; cont; cont = cont->GetNextContinuation()) {
if (GetPrevContinuationWithSameStyle(cont)) {
@ -4592,6 +4881,9 @@ ElementRestyler::RestyleResultToString(RestyleResult aRestyleResult)
case eRestyleResult_Stop:
result.AssignLiteral("eRestyleResult_Stop");
break;
case eRestyleResult_StopWithStyleChange:
result.AssignLiteral("eRestyleResult_StopWithStyleChange");
break;
case eRestyleResult_Continue:
result.AssignLiteral("eRestyleResult_Continue");
break;

View File

@ -620,9 +620,13 @@ private:
// the work of the earlier values is also done.
enum RestyleResult {
// do not restyle children
// we left the old style context on the frame; do not restyle children
eRestyleResult_Stop = 1,
// we got a new style context on this frame, but we know that children
// do not depend on the changed values; do not restyle children
eRestyleResult_StopWithStyleChange,
// continue restyling children
eRestyleResult_Continue,
@ -630,12 +634,20 @@ private:
eRestyleResult_ContinueAndForceDescendants
};
struct SwapInstruction
{
nsRefPtr<nsStyleContext> mOldContext;
nsRefPtr<nsStyleContext> mNewContext;
uint32_t mStructsToSwap;
};
/**
* First half of Restyle().
*/
RestyleResult RestyleSelf(nsIFrame* aSelf,
nsRestyleHint aRestyleHint,
uint32_t* aSwappedStructs);
uint32_t* aSwappedStructs,
nsTArray<SwapInstruction>& aSwaps);
/**
* Restyle the children of this frame (and, in turn, their children).
@ -674,6 +686,11 @@ private:
*/
void AddLayerChangesForAnimation();
bool MoveStyleContextsForContentChildren(nsIFrame* aParent,
nsStyleContext* aOldContext,
nsTArray<nsStyleContext*>& aContextsToMove);
bool MoveStyleContextsForChildren(nsStyleContext* aOldContext);
/**
* Helpers for RestyleSelf().
*/
@ -682,9 +699,13 @@ private:
nsChangeHint aChangeToAssume,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs);
RestyleResult ComputeRestyleResultFromFrame(nsIFrame* aSelf);
RestyleResult ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
nsStyleContext* aNewContext);
void ComputeRestyleResultFromFrame(nsIFrame* aSelf,
RestyleResult& aRestyleResult,
bool& aCanStopWithStyleChange);
void ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
nsStyleContext* aNewContext,
RestyleResult& aRestyleResult,
bool& aCanStopWithStyleChange);
// Helpers for RestyleChildren().
void RestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint);

View File

@ -41,6 +41,14 @@ class imgIContainer;
// NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
#define NS_STYLE_INHERIT_MASK 0x000ffffff
// Bits for inherited structs.
#define NS_STYLE_INHERITED_STRUCT_MASK \
((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1)
// Bits for reset structs.
#define NS_STYLE_RESET_STRUCT_MASK \
(((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \
<< nsStyleStructID_Inherited_Count)
// Additional bits for nsStyleContext's mBits:
// See nsStyleContext::HasTextDecorationLines
#define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000

View File

@ -65,4 +65,6 @@ eStyleStruct_BackendOnly = nsStyleStructID_Length
// A bit corresponding to each struct ID
#define NS_STYLE_INHERIT_BIT(sid_) (1 << uint64_t(eStyleStruct_##sid_))
typedef decltype(nsStyleStructID(0) + nsStyleStructID(0)) nsStyleStructID_size_t;
#endif /* nsStyleStructFwd_h_ */