Correctly handle a style change reflow on a subtree that has placeholders with out of flows outside that subtree. (Bug 363247) r+sr=bzbarsky a1.9.0.14=ss
git-svn-id: svn://10.0.0.236/trunk@258035 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -3237,88 +3237,106 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Grab |wasDirty| now so we can go ahead and update the bits on aFrame.
|
||||
PRBool wasDirty = NS_SUBTREE_DIRTY(aFrame);
|
||||
aFrame->AddStateBits(aBitToAdd);
|
||||
nsAutoTArray<nsIFrame*, 4> subtrees;
|
||||
subtrees.AppendElement(aFrame);
|
||||
|
||||
// Now if aFrame is a reflow root we can cut off this reflow at it if the bit
|
||||
// being added is NS_FRAME_HAS_DIRTY_CHILDREN.
|
||||
PRBool targetFrameDirty = (aBitToAdd == NS_FRAME_IS_DIRTY);
|
||||
do {
|
||||
nsIFrame *subtreeRoot = subtrees.ElementAt(subtrees.Length() - 1);
|
||||
subtrees.RemoveElementAt(subtrees.Length() - 1);
|
||||
|
||||
// Grab |wasDirty| now so we can go ahead and update the bits on
|
||||
// subtreeRoot.
|
||||
PRBool wasDirty = NS_SUBTREE_DIRTY(subtreeRoot);
|
||||
subtreeRoot->AddStateBits(aBitToAdd);
|
||||
|
||||
// Now if subtreeRoot is a reflow root we can cut off this reflow at it if
|
||||
// the bit being added is NS_FRAME_HAS_DIRTY_CHILDREN.
|
||||
PRBool targetFrameDirty = (aBitToAdd == NS_FRAME_IS_DIRTY);
|
||||
|
||||
#define FRAME_IS_REFLOW_ROOT(_f) \
|
||||
((_f->GetStateBits() & NS_FRAME_REFLOW_ROOT) && \
|
||||
(_f != aFrame || !targetFrameDirty))
|
||||
(_f != subtreeRoot || !targetFrameDirty))
|
||||
|
||||
|
||||
// Mark the intrinsic widths as dirty on the frame, all of its ancestors,
|
||||
// and all of its descendants, if needed:
|
||||
// Mark the intrinsic widths as dirty on the frame, all of its ancestors,
|
||||
// and all of its descendants, if needed:
|
||||
|
||||
if (aIntrinsicDirty != eResize) {
|
||||
// Mark argument and all ancestors dirty. (Unless we hit a reflow root that
|
||||
// should contain the reflow. That root could be aFrame itself if it's not
|
||||
// dirty, or it could be some ancestor of aFrame.)
|
||||
for (nsIFrame *a = aFrame;
|
||||
a && !FRAME_IS_REFLOW_ROOT(a);
|
||||
a = a->GetParent())
|
||||
a->MarkIntrinsicWidthsDirty();
|
||||
}
|
||||
if (aIntrinsicDirty != eResize) {
|
||||
// Mark argument and all ancestors dirty. (Unless we hit a reflow
|
||||
// root that should contain the reflow. That root could be
|
||||
// subtreeRoot itself if it's not dirty, or it could be some
|
||||
// ancestor of subtreeRoot.)
|
||||
for (nsIFrame *a = subtreeRoot;
|
||||
a && !FRAME_IS_REFLOW_ROOT(a);
|
||||
a = a->GetParent())
|
||||
a->MarkIntrinsicWidthsDirty();
|
||||
}
|
||||
|
||||
if (aIntrinsicDirty == eStyleChange) {
|
||||
// Mark all descendants dirty (using an nsVoidArray stack rather than
|
||||
// recursion).
|
||||
nsVoidArray stack;
|
||||
stack.AppendElement(aFrame);
|
||||
if (aIntrinsicDirty == eStyleChange) {
|
||||
// Mark all descendants dirty (using an nsTArray stack rather than
|
||||
// recursion).
|
||||
nsAutoTArray<nsIFrame*, 32> stack;
|
||||
stack.AppendElement(subtreeRoot);
|
||||
|
||||
while (stack.Count() != 0) {
|
||||
nsIFrame *f =
|
||||
static_cast<nsIFrame*>(stack.FastElementAt(stack.Count() - 1));
|
||||
stack.RemoveElementAt(stack.Count() - 1);
|
||||
|
||||
PRInt32 childListIndex = 0;
|
||||
nsIAtom *childListName;
|
||||
do {
|
||||
childListName = f->GetAdditionalChildListName(childListIndex++);
|
||||
for (nsIFrame *kid = f->GetFirstChild(childListName); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
kid->MarkIntrinsicWidthsDirty();
|
||||
stack.AppendElement(kid);
|
||||
nsIFrame *f = stack.ElementAt(stack.Length() - 1);
|
||||
stack.RemoveElementAt(stack.Length() - 1);
|
||||
|
||||
if (f->GetType() == nsGkAtoms::placeholderFrame) {
|
||||
nsIFrame *oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
|
||||
if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) {
|
||||
// We have another distinct subtree we need to mark.
|
||||
subtrees.AppendElement(oof);
|
||||
}
|
||||
}
|
||||
} while (childListName);
|
||||
}
|
||||
}
|
||||
|
||||
// Set NS_FRAME_HAS_DIRTY_CHILDREN bits (via nsIFrame::ChildIsDirty) up the
|
||||
// tree until we reach either a frame that's already dirty or a reflow root.
|
||||
nsIFrame *f = aFrame;
|
||||
for (;;) {
|
||||
if (FRAME_IS_REFLOW_ROOT(f) || !f->GetParent()) {
|
||||
// we've hit a reflow root or the root frame
|
||||
if (!wasDirty) {
|
||||
mDirtyRoots.AppendElement(f);
|
||||
}
|
||||
PRInt32 childListIndex = 0;
|
||||
nsIAtom *childListName;
|
||||
do {
|
||||
childListName = f->GetAdditionalChildListName(childListIndex++);
|
||||
for (nsIFrame *kid = f->GetFirstChild(childListName); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
kid->MarkIntrinsicWidthsDirty();
|
||||
stack.AppendElement(kid);
|
||||
}
|
||||
} while (childListName);
|
||||
} while (stack.Length() != 0);
|
||||
}
|
||||
|
||||
// Set NS_FRAME_HAS_DIRTY_CHILDREN bits (via nsIFrame::ChildIsDirty)
|
||||
// up the tree until we reach either a frame that's already dirty or
|
||||
// a reflow root.
|
||||
nsIFrame *f = subtreeRoot;
|
||||
for (;;) {
|
||||
if (FRAME_IS_REFLOW_ROOT(f) || !f->GetParent()) {
|
||||
// we've hit a reflow root or the root frame
|
||||
if (!wasDirty) {
|
||||
mDirtyRoots.AppendElement(f);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
VerifyHasDirtyRootAncestor(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
nsIFrame *child = f;
|
||||
f = f->GetParent();
|
||||
wasDirty = NS_SUBTREE_DIRTY(f);
|
||||
f->ChildIsDirty(child);
|
||||
NS_ASSERTION(f->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN,
|
||||
"ChildIsDirty didn't do its job");
|
||||
if (wasDirty) {
|
||||
// This frame was already marked dirty.
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
VerifyHasDirtyRootAncestor(f);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
nsIFrame *child = f;
|
||||
f = f->GetParent();
|
||||
wasDirty = NS_SUBTREE_DIRTY(f);
|
||||
f->ChildIsDirty(child);
|
||||
NS_ASSERTION(f->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN,
|
||||
"ChildIsDirty didn't do its job");
|
||||
if (wasDirty) {
|
||||
// This frame was already marked dirty.
|
||||
#ifdef DEBUG
|
||||
VerifyHasDirtyRootAncestor(f);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (subtrees.Length() != 0);
|
||||
|
||||
PostReflowEvent();
|
||||
|
||||
|
||||
15
mozilla/layout/reftests/bugs/363247-1-ref.html
Normal file
15
mozilla/layout/reftests/bugs/363247-1-ref.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>bug 363247</title>
|
||||
<link rel="stylesheet" href="data:text/css,body {font-size: 20pt}" id="main-css">
|
||||
</head>
|
||||
<body>
|
||||
<table id="table" style="position: absolute; font-size: inherit;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>foo</td><td>bar</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
20
mozilla/layout/reftests/bugs/363247-1.html
Normal file
20
mozilla/layout/reftests/bugs/363247-1.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>bug 363247</title>
|
||||
<link rel="stylesheet" href="data:text/css,body {font-size: 10pt}" id="main-css">
|
||||
</head>
|
||||
<body>
|
||||
<table id="table" style="position: absolute; font-size: inherit;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>foo</td><td>bar</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
document.body.offsetHeight;
|
||||
var node = document.getElementById("main-css");
|
||||
node.setAttribute("href", 'data:text/css,body {font-size: 20pt}');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -381,6 +381,7 @@ skip-if(MOZ_WIDGET_TOOLKIT=="windows") == 347496-1.xhtml 347496-1-ref.xhtml # Bu
|
||||
== 362594-2b.html 362594-2-standards-ref.html
|
||||
== 362594-2c.html 362594-2-standards-ref.html
|
||||
== 362901-1.html 362901-1-ref.html
|
||||
== 363247-1.html 363247-1-ref.html
|
||||
== 363329-1.html 363329-1-ref.html
|
||||
== 363329-2.html 363329-2-ref.html
|
||||
== 363370-1.html 363370-1-ref.html
|
||||
|
||||
Reference in New Issue
Block a user