Bug 996796 patch 18 - Fix RestyleTracker to handle restyle hints exactly rather than pessimistically when restyling continuations with varying styles (e.g., spans inside ::first-line or ::first-letter). r=heycam

This will be necessary when we use the restyle tracker for the
animation-only style flush, because animation-only style flushes need to
update *only* the animation style data and no other style data.  Thus
using the RestyleTracker for animation-only style flushes requires that
we do this.
This commit is contained in:
L. David Baron 2014-08-02 19:37:47 -07:00
Родитель 242b2eae80
Коммит d2fe2e8c79
2 изменённых файлов: 41 добавлений и 17 удалений

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

@ -1943,7 +1943,8 @@ GetPrevContinuationWithSameStyle(nsIFrame* aFrame)
*/
static nsIFrame*
GetNextContinuationWithSameStyle(nsIFrame* aFrame,
nsStyleContext* aOldStyleContext)
nsStyleContext* aOldStyleContext,
bool* aHaveMoreContinuations = nullptr)
{
// See GetPrevContinuationWithSameStyle about {ib} splits.
@ -1973,6 +1974,9 @@ GetNextContinuationWithSameStyle(nsIFrame* aFrame,
aOldStyleContext->GetParent() != nextStyle->GetParent(),
"continuations should have the same style context");
nextContinuation = nullptr;
if (aHaveMoreContinuations) {
*aHaveMoreContinuations = true;
}
}
return nextContinuation;
}
@ -2335,6 +2339,7 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
MOZ_ASSERT(!(aRestyleHint & eRestyle_LaterSiblings),
"eRestyle_LaterSiblings must not be part of aRestyleHint");
nsRestyleHint hintToRestore = nsRestyleHint(0);
if (mContent && mContent->IsElement()) {
mContent->OwnerDoc()->FlushPendingLinkUpdates();
RestyleTracker::RestyleData restyleData;
@ -2342,6 +2347,7 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
mChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
}
hintToRestore = restyleData.mRestyleHint;
aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
}
}
@ -2354,10 +2360,20 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
// TEMPORARY (until bug 918064): Call RestyleSelf for each
// continuation or block-in-inline sibling.
bool haveMoreContinuations = false;
for (nsIFrame* f = mFrame; f;
f = GetNextContinuationWithSameStyle(f, oldContext)) {
f = GetNextContinuationWithSameStyle(f, oldContext,
&haveMoreContinuations)) {
RestyleSelf(f, aRestyleHint);
}
if (haveMoreContinuations && hintToRestore) {
// If we have more continuations with different style (e.g., because
// we're inside a ::first-letter or ::first-line), put the restyle
// hint back.
mRestyleTracker.AddPendingRestyleToTable(mContent->AsElement(),
hintToRestore, nsChangeHint(0));
}
}
RestyleChildren(childRestyleHint);
@ -2455,17 +2471,7 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf, nsRestyleHint aRestyleHint)
"non pseudo-element frame without content node");
newContext = styleSet->ResolveStyleForNonElement(parentContext);
}
else if (!(aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) &&
!prevContinuation) {
// Unfortunately, if prevContinuation is non-null then we may have
// already stolen the restyle tracker entry for this element while
// processing prevContinuation. So we don't know whether aRestyleHint
// should really be 0 here or whether it should be eRestyle_Self. Be
// pessimistic and force an actual reresolve in that situation. The good
// news is that in the common case when prevContinuation is non-null we
// just used prevContinuationContext anyway and aren't reaching this code
// to start with.
else if (!(aRestyleHint & (eRestyle_Self | eRestyle_Subtree))) {
Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
if (aRestyleHint == nsRestyleHint(0)) {
newContext =

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

@ -19,6 +19,7 @@
namespace mozilla {
class RestyleManager;
class ElementRestyler;
/**
* Helper class that collects a list of frames that need
@ -230,6 +231,8 @@ class RestyleTracker {
public:
typedef mozilla::dom::Element Element;
friend class ElementRestyler; // for AddPendingRestyleToTable
RestyleTracker(Element::FlagsType aRestyleBits) :
mRestyleBits(aRestyleBits),
mHaveLaterSiblingRestyles(false)
@ -261,7 +264,7 @@ public:
* if the element already had eRestyle_LaterSiblings set on it.
*/
bool AddPendingRestyle(Element* aElement, nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint);
nsChangeHint aMinChangeHint);
/**
* Process the restyles we've been tracking.
@ -312,6 +315,9 @@ public:
};
private:
bool AddPendingRestyleToTable(Element* aElement, nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint);
/**
* Handle a single mPendingRestyles entry. aRestyleHint must not
* include eRestyle_LaterSiblings; that needs to be dealt with
@ -352,9 +358,10 @@ private:
bool mHaveLaterSiblingRestyles;
};
inline bool RestyleTracker::AddPendingRestyle(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
inline bool
RestyleTracker::AddPendingRestyleToTable(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
RestyleData existingData;
existingData.mRestyleHint = nsRestyleHint(0);
@ -377,6 +384,17 @@ inline bool RestyleTracker::AddPendingRestyle(Element* aElement,
mPendingRestyles.Put(aElement, existingData);
return hadRestyleLaterSiblings;
}
inline bool
RestyleTracker::AddPendingRestyle(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
bool hadRestyleLaterSiblings =
AddPendingRestyleToTable(aElement, aRestyleHint, aMinChangeHint);
// We can only treat this element as a restyle root if we would
// actually restyle its descendants (so either call
// ReResolveStyleContext on it or just reframe it).