Bug 1581237 - Use <coord-box> as the reference box of the containing block for ray(). r=emilio

So now we use <coord-box> to decide which box we should use. Also, we
have to tweak the calculation of path length to take the top left point
into consideration, for padding-box and content-box. border-box is the
default value, so other tests should cover it.

Differential Revision: https://phabricator.services.mozilla.com/D180397
This commit is contained in:
Boris Chiou 2023-06-16 22:43:34 +00:00
parent 2af89d148a
commit 97e7095dbd
11 changed files with 282 additions and 31 deletions

View File

@ -30,6 +30,11 @@ using nsStyleTransformMatrix::TransformReferenceBox;
// https://drafts.fxtf.org/motion-1/#valdef-offset-path-coord-box
static const nsIFrame* GetOffsetPathReferenceBox(const nsIFrame* aFrame,
nsRect& aOutputRect) {
const StyleOffsetPath& offsetPath = aFrame->StyleDisplay()->mOffsetPath;
if (offsetPath.IsNone()) {
return nullptr;
}
if (aFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement());
auto* viewportElement =
@ -39,14 +44,11 @@ static const nsIFrame* GetOffsetPathReferenceBox(const nsIFrame* aFrame,
}
const nsIFrame* containingBlock = aFrame->GetContainingBlock();
// FIXME: Bug 1581237: We should use <coord-box> as the box of its containing.
// Also, we will add <coord-box> into offset-path syntax in Bug 1598156.
// For now, we always use the default value, border-box.
// block.
// https://drafts.fxtf.org/motion-1/#valdef-offset-path-coord-box
constexpr StyleGeometryBox styleCoordBox = StyleGeometryBox::BorderBox;
aOutputRect =
nsLayoutUtils::ComputeHTMLReferenceRect(containingBlock, styleCoordBox);
const StyleCoordBox coordBox = offsetPath.IsCoordBox()
? offsetPath.AsCoordBox()
: offsetPath.AsOffsetPath().coord_box;
aOutputRect = nsLayoutUtils::ComputeHTMLReferenceRect(
containingBlock, nsLayoutUtils::CoordBoxToGeometryBox(coordBox));
return containingBlock;
}
@ -82,12 +84,15 @@ RayReferenceData::RayReferenceData(const nsIFrame* aFrame) {
.Size());
}
// The distance is measured between the initial position and the intersection of
// the ray with the box.
// The distance is measured between the origin and the intersection of the ray
// with the reference box of the containing block.
// Note: |aOrigin| and |aContaingBlock| should be in the same coordinate system
// (i.e. the nsIFrame::mRect of the containing block).
// https://drafts.fxtf.org/motion-1/#size-sides
static CSSCoord ComputeSides(const CSSPoint& aInitialPosition,
const CSSSize& aContainerSize,
static CSSCoord ComputeSides(const CSSPoint& aOrigin,
const CSSRect& aContainingBlock,
const StyleAngle& aAngle) {
const CSSPoint& topLeft = aContainingBlock.TopLeft();
// Given an acute angle |theta| (i.e. |t|) of a right-angled triangle, the
// hypotenuse |h| is the side that connects the two acute angles. The side
// |b| adjacent to |theta| is the side of the triangle that connects |theta|
@ -96,28 +101,29 @@ static CSSCoord ComputeSides(const CSSPoint& aInitialPosition,
// e.g. if the angle |t| is 0 ~ 90 degrees, and b * tan(theta) <= b',
// h = b / cos(t):
// b*tan(t)
// (0, 0) #--------*-----*--# (aContainerSize.width, 0)
// (topLeft) #--------*-----*--# (aContainingBlock.XMost(), topLeft.y)
// | | / |
// | | / |
// | b h |
// | |t/ |
// | |/ |
// (aInitialPosition) *---b'---* (aContainerSize.width, aInitialPosition.y)
// (aOrigin) *---b'---* (aContainingBlock.XMost(), aOrigin.y)
// | | |
// | | |
// | | |
// | | |
// | | |
// #-----------------# (aContainerSize.width,
// (0, aContainerSize.height) aContainerSize.height)
double theta = aAngle.ToRadians();
// #-----------------# (aContainingBlock.XMost(),
// (topLeft.x, aContainingBlock.YMost())
// aContainingBlock.YMost())
const double theta = aAngle.ToRadians();
double sint = std::sin(theta);
double cost = std::cos(theta);
double b = cost >= 0 ? aInitialPosition.y.value
: aContainerSize.height - aInitialPosition.y.value;
double bPrime = sint >= 0 ? aContainerSize.width - aInitialPosition.x.value
: aInitialPosition.x.value;
const double b = cost >= 0 ? aOrigin.y.value - topLeft.y
: aContainingBlock.YMost() - aOrigin.y.value;
const double bPrime = sint >= 0 ? aContainingBlock.XMost() - aOrigin.x.value
: aOrigin.x.value - topLeft.x;
sint = std::fabs(sint);
cost = std::fabs(cost);
@ -184,17 +190,18 @@ static CSSCoord ComputeRayPathLength(const StyleRaySize aRaySizeType,
return 0.0;
}
return ComputeSides(aOrigin, aContainingBlock.Size(), aAngle);
return ComputeSides(aOrigin, aContainingBlock, aAngle);
}
// left: the length between the initial point and the left side.
// right: the length between the initial point and the right side.
// top: the length between the initial point and the top side.
// bottom: the lenght between the initial point and the bottom side.
CSSCoord left = std::abs(aOrigin.x);
CSSCoord right = std::abs(aContainingBlock.width - aOrigin.x);
CSSCoord top = std::abs(aOrigin.y);
CSSCoord bottom = std::abs(aContainingBlock.height - aOrigin.y);
// left: the length between the origin and the left side.
// right: the length between the origin and the right side.
// top: the length between the origin and the top side.
// bottom: the lenght between the origin and the bottom side.
const CSSPoint& topLeft = aContainingBlock.TopLeft();
const CSSCoord left = std::abs(aOrigin.x - topLeft.x);
const CSSCoord right = std::abs(aContainingBlock.XMost() - aOrigin.x);
const CSSCoord top = std::abs(aOrigin.y - topLeft.y);
const CSSCoord bottom = std::abs(aContainingBlock.YMost() - aOrigin.y);
switch (aRaySizeType) {
case StyleRaySize::ClosestSide:
@ -216,7 +223,7 @@ static CSSCoord ComputeRayPathLength(const StyleRaySize aRaySizeType,
}
return sqrt(h.value * h.value + v.value * v.value);
}
default:
case StyleRaySize::Sides:
MOZ_ASSERT_UNREACHABLE("Unsupported ray size");
}

View File

@ -9572,6 +9572,26 @@ nsRect nsLayoutUtils::ComputeHTMLReferenceRect(const nsIFrame* aFrame,
return r;
}
/* static */
StyleGeometryBox nsLayoutUtils::CoordBoxToGeometryBox(StyleCoordBox aCoordBox) {
switch (aCoordBox) {
case StyleCoordBox::ContentBox:
return StyleGeometryBox::ContentBox;
case StyleCoordBox::PaddingBox:
return StyleGeometryBox::PaddingBox;
case StyleCoordBox::BorderBox:
return StyleGeometryBox::BorderBox;
case StyleCoordBox::FillBox:
return StyleGeometryBox::FillBox;
case StyleCoordBox::StrokeBox:
return StyleGeometryBox::StrokeBox;
case StyleCoordBox::ViewBox:
return StyleGeometryBox::ViewBox;
}
MOZ_ASSERT_UNREACHABLE("Unknown coord-box type");
return StyleGeometryBox::BorderBox;
}
static StyleGeometryBox ShapeBoxToGeometryBox(const StyleShapeBox& aBox) {
switch (aBox) {
case StyleShapeBox::BorderBox:

View File

@ -2946,6 +2946,8 @@ class nsLayoutUtils {
static nsRect ComputeHTMLReferenceRect(const nsIFrame*, StyleGeometryBox);
static StyleGeometryBox CoordBoxToGeometryBox(mozilla::StyleCoordBox);
static nsRect ComputeGeometryBox(nsIFrame*, StyleGeometryBox);
static nsRect ComputeGeometryBox(nsIFrame*,

View File

@ -0,0 +1,25 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test reference: ray() path with padding-box</title>
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
transform: translate(-50px, -50px);
width: 100px;
height: 100px;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,30 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test: ray() path with padding-box</title>
<link rel="match" href="offset-path-ray-015-ref.html">
<link rel="help" href="https://drafts.fxtf.org/motion/#ray-function">
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
offset-path: ray(0deg sides at 0% 0%) padding-box;
offset-rotate: 0deg;
offset-anchor: 0% 0%;
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,24 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test reference: ray() path with content-box</title>
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
width: 100px;
height: 100px;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test: ray() path with content-box</title>
<link rel="match" href="offset-path-ray-016-ref.html">
<link rel="help" href="https://drafts.fxtf.org/motion/#ray-function">
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
offset-path: ray(0deg sides at 0% 0%) content-box;
offset-rotate: 0deg;
offset-anchor: 0% 0%;
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="outer">
<div style="width: 100px; height: 100px; background-color: red;"></div>
<div id="box"></div>
</div>

View File

@ -0,0 +1,25 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test reference: ray() path with padding-box</title>
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
transform: translate(100px, -50px);
width: 100px;
height: 100px;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test: ray() path with padding-box</title>
<link rel="match" href="offset-path-ray-017-ref.html">
<link rel="help" href="https://drafts.fxtf.org/motion/#ray-function">
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
offset-path: ray(0deg sides at 50% 50%) padding-box;
offset-distance: 100%;
offset-rotate: 0deg;
offset-anchor: 0% 0%;
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,25 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test reference: ray() path with content-box</title>
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
transform: translate(100px, 0px);
width: 100px;
height: 100px;
}
</style>
<div id="outer">
<div id="box"></div>
</div>

View File

@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Motion Path test: ray() path with content-box</title>
<link rel="match" href="offset-path-ray-018-ref.html">
<link rel="help" href="https://drafts.fxtf.org/motion/#ray-function">
<style>
#outer {
top: 100px;
left: 100px;
position: relative;
width: 200px;
height: 200px;
padding: 50px;
border: 50px solid black;
}
#box {
background-color: green;
offset-path: ray(0deg sides at 50% 50%) content-box;
offset-distance: 100%;
offset-rotate: 0deg;
offset-anchor: 0% 0%;
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="outer">
<div id="box"></div>
</div>