mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 721082 - Make perspective-origin relative to the parent elements border box. r=roc
This commit is contained in:
parent
6905e450dd
commit
cca8fbcca8
@ -2449,6 +2449,8 @@ gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
|
||||
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
|
||||
NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
|
||||
"Can't get a delta for an untransformed frame!");
|
||||
NS_PRECONDITION(aFrame->GetParentStyleContextFrame(),
|
||||
"Can't get delta without a style parent!");
|
||||
|
||||
/* For both of the coordinates, if the value of -moz-perspective-origin is a
|
||||
* percentage, it's relative to the size of the frame. Otherwise, if it's
|
||||
@ -2457,9 +2459,10 @@ gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
|
||||
|
||||
//TODO: Should this be using our bounds or the parent's bounds?
|
||||
// How do we handle aBoundsOverride in the latter case?
|
||||
nsIFrame* parent = aFrame->GetParentStyleContextFrame();
|
||||
const nsStyleDisplay* display = aFrame->GetParent()->GetStyleDisplay();
|
||||
nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
|
||||
nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
|
||||
nsDisplayTransform::GetFrameBoundsForTransform(parent));
|
||||
|
||||
/* Allows us to access named variables by index. */
|
||||
gfxPoint3D result;
|
||||
@ -2487,7 +2490,12 @@ gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
nsPoint parentOffset = aFrame->GetOffsetTo(parent);
|
||||
gfxPoint3D gfxOffset(NSAppUnitsToFloatPixels(parentOffset.x, aFactor),
|
||||
NSAppUnitsToFloatPixels(parentOffset.y, aFactor),
|
||||
0);
|
||||
|
||||
return result - gfxOffset;
|
||||
}
|
||||
|
||||
/* Wraps up the -moz-transform matrix in a change-of-basis matrix pair that
|
||||
@ -2511,7 +2519,6 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
|
||||
* coordinate space to the new origin.
|
||||
*/
|
||||
gfxPoint3D toMozOrigin = GetDeltaToMozTransformOrigin(aFrame, aFactor, aBoundsOverride);
|
||||
gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aFactor, aBoundsOverride);
|
||||
gfxPoint3D newOrigin = gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aFactor),
|
||||
NSAppUnitsToFloatPixels(aOrigin.y, aFactor),
|
||||
0.0f);
|
||||
@ -2552,6 +2559,7 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
|
||||
/* At the point when perspective is applied, we have been translated to the transform origin.
|
||||
* The translation to the perspective origin is the difference between these values.
|
||||
*/
|
||||
gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aFactor, aBoundsOverride);
|
||||
result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
|
||||
}
|
||||
|
||||
|
@ -975,6 +975,26 @@ nsIFrame::Preserves3D() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::HasPerspective() const
|
||||
{
|
||||
if (!IsTransformed()) {
|
||||
return false;
|
||||
}
|
||||
const nsStyleDisplay* parentDisp = nsnull;
|
||||
nsStyleContext* parentStyleContext = GetStyleContext()->GetParent();
|
||||
if (parentStyleContext) {
|
||||
parentDisp = parentStyleContext->GetStyleDisplay();
|
||||
}
|
||||
|
||||
if (parentDisp &&
|
||||
parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
|
||||
parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsIFrame::GetContentRectRelativeToSelf() const
|
||||
{
|
||||
@ -6634,7 +6654,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
nsRect bounds(nsPoint(0, 0), aNewSize);
|
||||
// Store the passed in overflow area if we are a preserve-3d frame,
|
||||
// and it's not just the frame bounds.
|
||||
if (Preserves3D() && (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
|
||||
if ((Preserves3D() || HasPerspective()) && (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
|
||||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
|
||||
nsOverflowAreas* initial =
|
||||
static_cast<nsOverflowAreas*>(Properties().Get(nsIFrame::InitialOverflowProperty()));
|
||||
@ -6749,6 +6769,8 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
}
|
||||
if (Preserves3DChildren()) {
|
||||
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
|
||||
} else if (HasPerspective()) {
|
||||
RecomputePerspectiveChildrenOverflow(this, &newBounds);
|
||||
}
|
||||
} else {
|
||||
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
|
||||
@ -6808,6 +6830,39 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
return anyOverflowChanged;
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds)
|
||||
{
|
||||
// Children may check our size when getting our transform, make sure it's valid.
|
||||
nsSize oldSize = GetSize();
|
||||
if (aBounds) {
|
||||
SetSize(aBounds->Size());
|
||||
}
|
||||
nsIFrame::ChildListIterator lists(this);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
nsIFrame* child = childFrames.get();
|
||||
if (child->HasPerspective()) {
|
||||
nsOverflowAreas* overflow =
|
||||
static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
|
||||
nsRect bounds(nsPoint(0, 0), child->GetSize());
|
||||
if (overflow) {
|
||||
child->FinishAndStoreOverflow(*overflow, bounds.Size());
|
||||
} else {
|
||||
nsOverflowAreas boundsOverflow;
|
||||
boundsOverflow.SetAllTo(bounds);
|
||||
child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
|
||||
}
|
||||
} else if (child->GetParentStyleContextFrame() != aStartFrame) {
|
||||
child->RecomputePerspectiveChildrenOverflow(aStartFrame, nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Restore our old size just in case something depends on this elesewhere.
|
||||
SetSize(oldSize);
|
||||
}
|
||||
|
||||
/* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
|
||||
* the mRect value for their parents (since we use their transform, and transform
|
||||
* depends on this for transform-origin etc). These weren't necessarily correct
|
||||
|
@ -1247,9 +1247,13 @@ public:
|
||||
*/
|
||||
bool Preserves3D() const;
|
||||
|
||||
bool HasPerspective() const;
|
||||
|
||||
// Calculate the overflow size of all child frames, taking preserve-3d into account
|
||||
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
|
||||
|
||||
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds);
|
||||
|
||||
/**
|
||||
* Event handling of GUI events.
|
||||
*
|
||||
|
31
layout/reftests/transform-3d/perspective-origin-2-ref.html
Normal file
31
layout/reftests/transform-3d/perspective-origin-2-ref.html
Normal file
@ -0,0 +1,31 @@
|
||||
<html>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
.stage{
|
||||
-moz-perspective: 100px;
|
||||
-moz-perspective-origin: 30px 30px;
|
||||
height:100px;
|
||||
width:100px;
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
border:5px solid gray;
|
||||
}
|
||||
|
||||
.box {
|
||||
-moz-transform:rotateX(45deg);
|
||||
height:70px;
|
||||
width:70px;
|
||||
background:green;
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
border:5px solid black;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="box"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
31
layout/reftests/transform-3d/perspective-origin-2a.html
Normal file
31
layout/reftests/transform-3d/perspective-origin-2a.html
Normal file
@ -0,0 +1,31 @@
|
||||
<html>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
.stage{
|
||||
-moz-perspective: 100px;
|
||||
-moz-perspective-origin: 25% 25%;
|
||||
height:100px;
|
||||
width:100px;
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
border:5px solid gray;
|
||||
}
|
||||
|
||||
.box {
|
||||
-moz-transform:rotateX(45deg);
|
||||
height:70px;
|
||||
width:70px;
|
||||
background:green;
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
border:5px solid black;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="box"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -33,6 +33,7 @@ fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == preserve3d-1a.html preser
|
||||
== backface-visibility-1b.html about:blank
|
||||
!= perspective-origin-1a.html rotatex-perspective-1a.html
|
||||
== perspective-origin-1b.html perspective-origin-1a.html
|
||||
== perspective-origin-2a.html perspective-origin-2-ref.html
|
||||
!= sorting-1a.html sorting-1-ref.html
|
||||
# Parallel planes, different z depth
|
||||
== sorting-2a.html sorting-2-ref.html
|
||||
|
Loading…
Reference in New Issue
Block a user