Bug 455280. Distinguish pre-transform overflow area from post-transform overflow area and have nsDisplaySVGEffects use the pre-transform area. r=kschwarz,sr=dbaron

This commit is contained in:
Robert O'Callahan 2008-09-16 13:51:52 +12:00
parent 07665de93e
commit b7f3ce1f50
7 changed files with 101 additions and 21 deletions

View File

@ -1616,6 +1616,7 @@ GK_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
GK_ATOM(overflowOutOfFlowsProperty, "OverflowOutOfFlowsProperty") // nsFrameList*
GK_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsFrameList*
GK_ATOM(preEffectsBBoxProperty, "PreEffectsBBoxProperty") // nsRect*
GK_ATOM(preTransformBBoxProperty, "PreTransformBBoxProperty") // nsRect*
GK_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
GK_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
GK_ATOM(tabWidthProperty, "TabWidthProperty") // nsTArray<TabSetting>* array of tab widths

View File

@ -1329,7 +1329,7 @@ nsRect nsDisplayTransform::UntransformRect(const nsRect &aUntransformedBounds,
#ifdef MOZ_SVG
nsDisplaySVGEffects::nsDisplaySVGEffects(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList), mEffectsFrame(aFrame),
mBounds(aFrame->GetOverflowRect())
mBounds(aFrame->GetOverflowRectRelativeToSelf())
{
MOZ_COUNT_CTOR(nsDisplaySVGEffects);
}

View File

@ -3920,6 +3920,22 @@ nsIFrame::GetOverflowRect() const
// but the mRect hasn't been set yet!
return nsRect(nsPoint(0, 0), GetSize());
}
nsRect
nsIFrame::GetOverflowRectRelativeToParent() const
{
return GetOverflowRect() + mRect.TopLeft();
}
nsRect
nsIFrame::GetOverflowRectRelativeToSelf() const
{
if (!(mState & NS_FRAME_MAY_BE_TRANSFORMED) ||
!GetStyleDisplay()->HasTransform())
return GetOverflowRect();
return *static_cast<nsRect*>
(GetProperty(nsGkAtoms::preEffectsBBoxProperty));
}
void
nsFrame::CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize)
@ -5598,17 +5614,6 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize)
aOverflowArea->UnionRectIncludeEmpty(*aOverflowArea,
nsRect(nsPoint(0, 0), aNewSize));
/* If we're transformed, transform the overflow rect by the current transformation. */
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
GetStyleDisplay()->HasTransform()) {
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
*/
nsRect newBounds(nsPoint(0, 0), aNewSize);
*aOverflowArea = nsDisplayTransform::TransformRect(*aOverflowArea, this, nsPoint(0, 0), &newBounds);
}
PRBool geometricOverflow =
aOverflowArea->x < 0 || aOverflowArea->y < 0 ||
aOverflowArea->XMost() > aNewSize.width || aOverflowArea->YMost() > aNewSize.height;
@ -5622,21 +5627,35 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize)
geometricOverflow = PR_FALSE;
}
nsRect overflowRect = GetAdditionalOverflow(*aOverflowArea, aNewSize);
*aOverflowArea = GetAdditionalOverflow(*aOverflowArea, aNewSize);
if (overflowRect != nsRect(nsPoint(0, 0), aNewSize)) {
/* If we're transformed, transform the overflow rect by the current transformation. */
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
GetStyleDisplay()->HasTransform()) {
// Save overflow area before the transform
SetRectProperty(this, nsGkAtoms::preTransformBBoxProperty, *aOverflowArea);
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
*/
nsRect newBounds(nsPoint(0, 0), aNewSize);
*aOverflowArea = nsDisplayTransform::TransformRect(*aOverflowArea, this, nsPoint(0, 0), &newBounds);
}
if (*aOverflowArea != nsRect(nsPoint(0, 0), aNewSize)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
nsRect* overflowArea = GetOverflowAreaProperty(PR_TRUE);
NS_ASSERTION(overflowArea, "should have created rect");
*aOverflowArea = *overflowArea = overflowRect;
}
*overflowArea = *aOverflowArea;
}
else {
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
// remove the previously stored overflow area
DeleteProperty(nsGkAtoms::overflowAreaProperty);
}
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
}
}
void

View File

@ -105,10 +105,10 @@ struct nsMargin;
typedef class nsIFrame nsIBox;
// IID for the nsIFrame interface
// 98a0c040-09cf-408b-b55f-321b4f8d9d67
// bc99463c-5ff7-4ff3-b2c8-b4172646f793
#define NS_IFRAME_IID \
{ 0x98a0c040, 0x09cf, 0x408b, \
{ 0xb5, 0x5f, 0x32, 0x1b, 0x4f, 0x8d, 0x9d, 0x67 } }
{ 0xbc99463c, 0x5ff7, 0x4ff3, \
{ 0xb2, 0xc8, 0xb4, 0x17, 0x26, 0x46, 0xf7, 0x93 } }
/**
* Indication of how the frame can be split. This is used when doing runaround
@ -1731,10 +1731,42 @@ public:
* FinishAndStoreOverflow has been called but mRect hasn't yet been
* updated yet.
*
* @return the rect relative to this frame's origin
* @return the rect relative to this frame's origin, but after
* CSS transforms have been applied (i.e. not really this frame's coordinate
* system, and may not contain the frame's border-box, e.g. if there
* is a CSS transform scaling it down)
*/
nsRect GetOverflowRect() const;
/**
* Computes a rect that encompasses everything that might be painted by
* this frame. This includes this frame, all its descendent frames, this
* frame's outline, and descentant frames' outline, but does not include
* areas clipped out by the CSS "overflow" and "clip" properties.
*
* The NS_FRAME_OUTSIDE_CHILDREN state bit is set when this overflow rect
* is different from nsRect(0, 0, GetRect().width, GetRect().height).
* XXX Note: because of a space optimization using the formula above,
* during reflow this function does not give accurate data if
* FinishAndStoreOverflow has been called but mRect hasn't yet been
* updated yet.
*
* @return the rect relative to the parent frame, in the parent frame's
* coordinate system
*/
nsRect GetOverflowRectRelativeToParent() const;
/**
* Computes a rect that encompasses everything that might be painted by
* this frame. This includes this frame, all its descendent frames, this
* frame's outline, and descentant frames' outline, but does not include
* areas clipped out by the CSS "overflow" and "clip" properties.
*
* @return the rect relative to this frame, before any CSS transforms have
* been applied, i.e. in this frame's coordinate system
*/
nsRect GetOverflowRectRelativeToSelf() const;
/**
* Set/unset the NS_FRAME_OUTSIDE_CHILDREN flag and store the overflow area
* as a frame property in the frame manager so that it can be retrieved

View File

@ -0,0 +1,10 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<div style="width:160px; height:160px; position:relative; left:120px; top:120px; background:lime;"></div>
</body>
</html>

View File

@ -0,0 +1,16 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<div style="width:400px; height:400px; clip-path: url(#c1); background:lime; -moz-transform:scale(0.5)"></div>
<svg:svg height="0">
<svg:clipPath id="c1" clipPathUnits="objectBoundingBox">
<svg:rect x="0.1" y="0.1" width="0.8" height="0.8"/>
</svg:clipPath>
</svg:svg>
</body>
</html>

View File

@ -912,3 +912,5 @@ fails == 441259-2.html 441259-2-ref.html # bug 441400
== 450670-1.html 450670-1-ref.html
== 451168-1.html 451168-1-ref.html
== 454361.html about:blank
== 455280-1.xhtml 455280-1-ref.xhtml