Skip to content

Commit 8b60dd2

Browse files
noamrSebastianZ
andauthored
[css-borders-4] Refactor contour path algorithm (#13173)
* [css-borders-4] Refactor contour path algorithm Use vector math to better describe how to draw a border-align contour. Also use the miter points (which are the axisAlignedCornerStart/End points) to make sure shadows are rendered in a border-aligned manner. Closes #13037 * Add note * nit * Fix notch * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * Update css-borders-4/Overview.bs Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com> * nits --------- Co-authored-by: Sebastian Zartner <sebastianzartner@gmail.com>
1 parent 24d8e72 commit 8b60dd2

1 file changed

Lines changed: 138 additions & 85 deletions

File tree

css-borders-4/Overview.bs

Lines changed: 138 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,104 +1467,157 @@ The 'corner' shorthand</h4>
14671467
<h4 id=corner-shape-rendering>
14681468
Rendering 'corner-shape'</h4>
14691469

1470-
When rendering elements with shaped corners, the element's path needs to be offset,
1470+
When rendering elements with shaped corners, the element's [=border contour path=] needs to be offset,
14711471
based on [=border=], [=outline=], 'box-shadow', 'overflow-clip-margin' and more.
14721472

1473-
When rendering borders or outlines, the offset is aligned to the curve of the element's shape,
1474-
while when rendering 'box-shadow' or offsetting for 'overflow-clip-margin', the offset is aligned to the axis.
1475-
1476-
<figure>
1477-
<img src="images/corner-shape-adjusting.svg" width="600" height="537"
1478-
alt="Adjusting corner shapes"
1479-
>
1480-
<figcaption>Borders are aligned to the curve, shadows and clip are aligned to the axis.</figcaption>
1481-
</figure>
1482-
1473+
When rendering borders or outlines, the offset is aligned to the curve of the element's shape.
1474+
When rendering 'box-shadow' or offsetting for 'overflow-clip-margin', the offset is also aligned to the same curve in the other direction, and the curve continues to the outer edge.
14831475

14841476
An [=/element=] |element|'s <dfn>outer contour</dfn> is the [=border contour path=] given |element| and |element|'s [=border edge=].
14851477

1486-
An [=/element=] |element|'s <dfn>inner contour</dfn> is the [=border contour path=] given |element| and |element|'s [=padding edge=].
1478+
An [=/element=] |element|'s <dfn>inner contour</dfn> is the [=border contour path=] given |element| and |element|'s [=border width=].
14871479

14881480
An [=/element=]'s [=border=] is rendered in the area between its [=outer contour=] and its [=inner contour=].
14891481

14901482
An [=/element=]'s [=outline=] follows the [=outer contour=] with the [=used value|used=] 'outline-width' and 'outline-offset'.
14911483
The precise way in which it is rendered is implementation-defined.
14921484

14931485
An [=/element=]'s [=overflow=] area is shaped by its [=inner contour=].
1494-
An [=/element=]'s [=overflow clip edge=] is shaped by the [=border contour path=] given |element|, and |element|'s [=padding edge=], and |element|'s [=used value|used=] 'overflow-clip-margin'.
1495-
1496-
Each shadow of [=/element=]'s 'box shadow' is shaped by the [=border contour path=] given |element|, and |element|'s [=border edge=], and the shadow's [=used value|used=] 'box-shadow-spread'.
1497-
1498-
<div algorithm="adjust-border-inner-path-for-corner-shape">
1499-
To compute an [=/element=] |element|'s <dfn>border contour path</dfn> given an [=edge=] |targetEdge| and an optional number |spread| (default 0):
1500-
1. Let |outerLeft|, |outerTop|, |outerRight|, |outerBottom| be |element|'s [=unshaped edge|unshaped=] [=border edge=], outset by |spread|.
1501-
1. Let |topLeftHorizontalRadius|, |topLeftVericalRadius|, |topRightHorizontalRadius|, |topRightVerticalRadius|, |bottomRightHorizontalRadius|,
1502-
|bottomRightVerticalRadius|, |bottomLeftHorizontalRadius|, and |bottomLeftVerticalRadius| be |element| [=border edge=]'s radii,
1503-
scaled by |element|'s [=opposite corner scale factor=] and [=outset-adjusted border radius|outset-adjusted=].
1504-
1. Let |topLeftShape|, |topRightShape|, |bottomRightShape|, and |bottomLeftShape| be |element|'s [=computed value|computed=] 'corner-*-shape' values.
1505-
1. Let |targetLeft|, |targetTop|, |targetRight|, |targetBottom| [=unshaped edge|unshaped=] |targetEdge|.
1506-
1. Let |path| be a new path [[SVG2]].
1507-
1. [=Add corner to path=] given |path|,
1508-
the [=rectangle=] <code>(|outerRight| - |topRightHorizontalRadius|, |outerTop|, |topRightHorizontalRadius|, |topRightVerticalRadius|)</code>, |targetEdge|,
1509-
0, |targetTop| - |outerTop|, |outerRight| - |targetRight|, and |topRightShape|.
1510-
1. [=Add corner to path=] given |path|,
1511-
the [=rectangle=] <code>(|outerRight| - |bottomRightHorizontalRadius|, |outerBottom| - |bottomRightVerticalRadius|, |bottomRightHorizontalRadius|, |bottomRightVerticalRadius|)</code>, |targetEdge|,
1512-
1, |outerRight| - |targetRight|, |outerBottom| - |targetBottom|, and |bottomRightShape|.
1513-
1. [=Add corner to path=] given |path|,
1514-
the [=rectangle=] <code>(|outerLeft|, |outerBottom| - |bottomLeftVerticalRadius|, |bottomLeftHorizontalRadius|, |bottomLeftVerticalRadius|)</code>, |targetEdge|,
1515-
2, |outerBottom| - |targetBottom|, |targetLeft| - |outerLeft|, and |bottomLeftShape|.
1516-
1. [=Add corner to path=] given |path|,
1517-
the [=rectangle=] <code>(|outerLeft|, |outerTop|, |topLeftHorizontalRadius|, |topLeftVericalRadius|)</code>, |targetEdge|,
1518-
3, |targetLeft| - |outerLeft|, |targetTop| - |outerTop|, and |topLeftShape|.
1519-
1. Return |path|.
1486+
An [=/element=]'s [=overflow clip edge=] is shaped by the [=border contour path=] given |element|, and an [=uniform inset from an outset=] given |element|'s [=used value|used=] 'overflow-clip-margin'.
1487+
1488+
Each shadow of [=/element=]'s 'box-shadow' is shaped by the [=border contour path=] given |element|, and an [=uniform inset from an outset=] given the shadow's [=used value|used=] 'box-shadow-spread'.
1489+
1490+
An <dfn>uniform inset from an outset</dfn> given a number |outset| is an [=edge=] whose value is <code>-|outset|</code> in all directions.
1491+
1492+
<h5 id=vector-math-helpers>Vector Math Helpers</h5>
1493+
1494+
A <dfn>two-dimensional vector</dfn> is a pair of numbers (x, y).
1495+
<div algorithm="extend-point">
1496+
A <dfn>point extended by vectors</dfn> given a {{DOMPointReadOnly}} |p| and a [=/list=] of [=two-dimensional vector=]s |vectors|:
1497+
1. Let |x| be |p|'s {{DOMPointReadOnly/x}}.
1498+
1. Let |y| be |p|'s {{DOMPointReadOnly/y}}.
1499+
1. [=list/For each=] |v| in |vectors|:
1500+
1. Increment |x| by |v|[0];
1501+
1. Increment |y| by |v|[1];
1502+
1. Return a new {{DOMPointReadOnly}} whose {{DOMPointReadOnly/x}} is |x| and whose {{DOMPointReadOnly/y}} is |y|.
1503+
</div>
15201504

1521-
To <dfn>add corner to path</dfn> given a path |path|, a rectangle |cornerRect|, a rectangle |trimRect|,
1522-
and numbers |orientation|, |startThickness|, |endThickness|, |curvature|:
1523-
1524-
1. If |cornerRect| is empty, or if |curvature| is ∞:
1525-
1. Let |innerQuad| be |trimRect|'s [=clockwise quad=] .
1526-
1. Extend |path| by drawing a line to |innerQuad|[<code>(|orienation| + 1) % 4</code>].
1527-
1. Return.
1528-
1529-
1. Let |cornerQuad| be |cornerRect|'s [=clockwise quad=].
1530-
1. If |curvature| is -∞:
1531-
1. Extend |path| by drawing a line from |cornerQuad|[0] to |cornerQuad|[3], trimmed by |trimRect|.
1532-
1. Extend |path| by drawing a line from |cornerQuad|[3] to |cornerQuad|[2], trimmed by |trimRect|.
1533-
1. Return.
1534-
1535-
1. Let |clampedNormalizedHalfCorner| be the [=normalized superellipse half corner=] given <code>clamp(|curvature|, -1, 1)</code>.
1536-
1. Let |equivalentQuadraticControlPointX| be <code>|clampedNormalizedHalfCorner| * 2 - 0.5</code>.
1537-
1. Let |curveStartPoint| be the [=aligned corner point=] given |cornerQuad|[|orienation|], the vector (|equivalentQuadraticControlPointX|, <code>1 - |equivalentQuadraticControlPointX|</code>), |startThickness|, and |orientation| + 1.
1538-
1. Let |curveEndPoint| by the [=aligned corner point=] given |cornerQuad|[(|orientation| + 2) % 4], the vector (<code>|equivalentQuadraticControlPointX| - 1</code>, <code>-|equivalentQuadraticControlPointX|</code>), |endThickness|, and |orientation| + 3.
1539-
1. Let |alignedCornerRect| be a [=rectangle=] that includes the points |curveStartPoint| and |curveEndPoint|.
1540-
1. Let |projectionToCornerRect| be a [=transformation matrix=],
1541-
translated by <code>(|alignedCornerRect|'s [=x coordinate=], |alignedCornerRect|'s [=y coordinate=])</code>,
1542-
scaled by <code>(|alignedCornerRect|'s [=width dimension=], |alignedCornerRect|'s [=height dimension=])</code>,
1543-
translated by <code>(0.5, 0.5)</code>,
1544-
rotated by <code>90deg * orientation</code>,
1545-
and translated by <code>(-0.5, -0.5)</code>.
1546-
1547-
1. Let |K| be <code>0.5<sup>abs(|curvature|)</sup></code>.
1548-
1. For each |T| between 0 and 1:
1549-
1. Let |A| be <code>|T|<sup>|K|</sup></code>.
1550-
1. Let |B| be <code>1 - (1 - |T|)<sup>|K|</sup></code>.
1551-
1. Let |normalizedPoint| be <code>(|A|, |B|)</code> if |curvature| is positive, otherwise <code>(|B|, |A|)</code>.
1552-
1. Let |absolutePoint| be |normalizedPoint|, transformed by |projectionToCornerRect|.
1553-
1. If |absolutePoint| is within |trimRect|, extend |path| through |absolutePoint|.
1554-
1555-
Note: User agents may approximate this algorithm, for instance, by using concatenated Bezier curves, to balance between performance and rendering accuracy.
1556-
1557-
To compute the <dfn>aligned corner point</dfn> given a point |originalPoint|, a two-component vector |offsetFromControlPoint|, a number |thickness|, and a number |orientation|:
1558-
1. Let |length| be <code>hypot(|offsetFromControlPoint|.x, |offsetFromControlPoint|.y)</code>.
1559-
1. Rotate |offsetFromControlPoint| by <code>90deg * |orientation|</code>, and scale by |thickness|.
1560-
1. Translate |originalPoint| by <code>|offsetFromControlPoint|.x / |length|, |offsetFromControlPoint|.y / |length|</code>, and return the result.
1561-
1562-
The <dfn>clockwise quad</dfn> given a [=rectangle=] |rect|, is a [=quadrilateral=] with the points
1563-
(|rect|'s [=x coordinate=], |rect|'s [=y coordinate=]),
1564-
(|rect|'s [=x coordinate=] + |rect|'s [=width dimension=], |rect|'s [=y coordinate=]),
1565-
(|rect|'s [=x coordinate=] + |rect|'s [=width dimension=], |rect|'s [=y coordinate=] + |rect|'s [=height dimension=]),
1566-
(|rect|'s [=x coordinate=], |rect|'s [=y coordinate=] + |rect|'s [=height dimension=]).
1505+
To <dfn for="two-dimensional vector">scale</dfn> a [=two-dimensional vector=] |v| by a number |factor|, return <code>(|v|[0] ⋅ |factor|, |v|[1] ⋅ |factor|)</code>.
15671506

1507+
<div algorithm="normalize-vector">
1508+
To <dfn for="two-dimensional vector">normalize</dfn> a [=two-dimensional vector=] |v|:
1509+
1. Let |l| be <code>hypot(|v|[0], |v|[1])</code>.
1510+
1. If |l| is 0, return |v|.
1511+
1. Return <code>(|v|[0] / |l|, |v|[1] / |l|)</code>.
1512+
</div>
1513+
1514+
The <dfn for="two-dimensional vector">perpendicular</dfn> of a [=two-dimensional vector=] |v| is <code>(-|v|[1], |v|[0])</code>.
1515+
1516+
The <dfn>vector between two points</dfn>, given {{DOMPoint}}s |a| and |b|, is <code>(|b|'s {{DOMPointReadOnly/x}} - |a|'s {{DOMPointReadOnly/x}}, |b|'s {{DOMPointReadOnly/y}} - |a|'s {{DOMPointReadOnly/y}})</code>.
1517+
1518+
<h5 id=contour-path>Computing a contoured path</h5>
1519+
1520+
This algorithm describes how to compute a path with shaped corners (a path that is either inset or outset from the original).
1521+
To avoid the complexities of defining how superellipses intersect, the algorithm simplifies the process by specifying that each corner is "clipped out" of the path.
1522+
The specific implementation details of this clipping operation are left to implementations.
1523+
1524+
<div algorithm="border-aligned-contour-path">
1525+
To compute an [=/element=] |element|'s <dfn>border contour path</dfn> given numbers |topInset|, |rightInset|, |bottomInset|, |leftInset|:
1526+
1. Let |borderRect| be |element|'s [=border box=].
1527+
1. Let |unshapedTargetRect| be |borderRect|, inset by |topInset|, |rightInset|, |bottomInset|, |leftInset|.
1528+
1529+
Note: If this is a shadow or 'overflow-clip-margin', the insets would have negative values and |unshapedTargetRect| would become an outset of |borderRect|.
1530+
1531+
1. Let |path| be a path that contains |unshapedTargetRect|.
1532+
1533+
1. Let |scaleFactor| be the [=opposite corner scale factor=] given |element|.
1534+
1535+
1. Let |adjustedRadius| be the following steps given a property |P|, and numbers |insetX| and |insetY|:
1536+
1. Let |radius| be |element|'s [=used value=] of |P|.
1537+
1. If |insetX| and |insetY| are zero, return |radius|.
1538+
1. If |insetX| or |insetY| are positive, then return <code>(|radius|'s [=width=] ⋅ |scaleFactor|, |radius|'s [=height=] ⋅ |scaleFactor|)</code>.
1539+
1. Let |adjustedRadiusInOutsetCoordinates| be the [=outset-adjusted border radius=] given |borderRect|'s size, |radius|, and <code>(-|insetX|, -|insetY|)</code>.
1540+
1. Return <code>(|adjustedRadiusInOutsetCoordinates|'s [=width=] - |insetX|, |adjustedRadiusInOutsetCoordinates|'s [=height=] - |insetY|)</code>.
1541+
1542+
1. Let |adjustedTopRightRadius| be the |adjustedRadius| given 'border-top-right-radius', |insetRight|, and |insetTop|.
1543+
1. Let |adjustedBottomRightRadius| be the |adjustedRadius| given 'border-bottom-right-radius', |insetRight|, and |insetBottom|.
1544+
1. Let |adjustedBottomLeftRadius| be the |adjustedRadius| given 'border-bottom-left-radius', |insetLeft|, and |insetBottom|.
1545+
1. Let |adjustedTopLeftRadius| be the |adjustedRadius| given 'border-top-left-radius', |insetLeft|, and |insetTop|.
1546+
1547+
1. Clip out from |path|, the [=border-aligned corner clip-out path=] given
1548+
|borderRect|'s right, |borderRect|'s top,
1549+
<code>(-|adjustedTopRightRadius|[0], 0)</code>, <code>(0, |adjustedTopRightRadius|[1])</code>,
1550+
|element|'s [=computed value|computed=] 'corner-top-right-shape',
1551+
|topInset|, and |rightInset|.
1552+
1553+
1. Clip out from |path|, the [=border-aligned corner clip-out path=] given
1554+
|borderRect|'s right, |borderRect|'s bottom,
1555+
<code>(0, -|adjustedBottomRightRadius|[1])</code>, <code>(-|adjustedBottomRightRadius|[0], 0)</code>,
1556+
|element|'s [=computed value|computed=] 'corner-bottom-right-shape',
1557+
|rightInset|, and |bottomInset|.
1558+
1559+
1. Clip out from |path|, the [=border-aligned corner clip-out path=] given
1560+
|borderRect|'s left, |borderRect|'s bottom,
1561+
<code>(|adjustedBottomLeftRadius|[0], 0)</code>, <code>(0, -|adjustedBottomLeftRadius|[1])</code>,
1562+
|element|'s [=computed value|computed=] 'corner-bottom-left-shape',
1563+
|bottomInset|, and |leftInset|.
1564+
1565+
1. Clip out from |path|, the [=border-aligned corner clip-out path=] given
1566+
|borderRect|'s left, |borderRect|'s top,
1567+
<code>(0, |adjustedTopLeftRadius|[1])</code>, <code>(|adjustedTopLeftRadius|[0], 0)</code>,
1568+
|element|'s [=computed value|computed=] 'corner-top-left-shape',
1569+
|leftInset|, and |topInset|.
1570+
1571+
1. Return |path|.
1572+
1573+
To get the <dfn>border-aligned corner clip-out path</dfn> given a {{DOMPointReadOnly}} |originalCornerOuter|, a [=two-dimensional vector=] |vectorTowardsStart|, a [=two-dimensional vector=] |vectorTowardsEnd|, a [=superellipse parameter=] |curvature|, and numbers |startInset| and |endInset|:
1574+
1. If |curvature| is ∞, then return an empty path.
1575+
1. Let |clampedHalfCorner| be the [=normalized superellipse half corner=] given <code>clamp(|curvature|, -1, 1)</code>.
1576+
1. Let |originalCornerStart| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsStart| ».
1577+
1. Let |originalCornerEnd| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsEnd| ».
1578+
1. Let |originalCornerCenter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsStart|, |vectorTowardsEnd| ».
1579+
1. Let |extendStart| be a [=vector between two points|vector between=] |originalCornerStart| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] |startInset|.
1580+
1. Let |extendEnd| be a [=vector between two points|vector between=] |originalCornerEnd| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] |endInset|.
1581+
1. Let |clipStart| be |originalCornerStart|, [=point extended by vectors|extended by=] « |extendStart| ».
1582+
1. Let |clipEnd| be |originalCornerEnd|, [=point extended by vectors|extended by=] « |extendEnd| ».
1583+
1. Let |clipOuter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |extendStart|, |extendEnd| ».
1584+
1. Let |vectorFromStartToControlPoint| be the the [=two-dimensional vector=] <code>(2 ⋅ |clampedHalfCorner| - 0.5, 1.5 - 2 ⋅ |clampedHalfCorner|)</code>.
1585+
1. Let |singlePixelVectorFromStartToControlPoint| be the |vectorFromStartToControlPoint|, [=two-dimensional vector/normalize|normalized=].
1586+
1. Let <code>|strokeA|, |strokeB|</code> be the [=two-dimensional vector/perpendicular=] of |singlePixelVectorFromStartToControlPoint|.
1587+
1. Let |offset1| be [=vector between two points|the vector between=] |originalCornerStart| and |outerCorner|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|startInset| ⋅ |strokeA|</code>.
1588+
1. Let |offset2| be [=vector between two points|the vector between=] |outerCorner| and |originalCornerEnd|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|startInset| ⋅ |strokeB|</code>.
1589+
1. Let |offset3| be [=vector between two points|the vector between=] |originalCornerEnd| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|endInset| ⋅ |strokeB|</code>.
1590+
1. Let |offset4| be [=vector between two points|the vector between=] |originalCornerCenter| and |originalCornerStart|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|endInset| ⋅ |strokeA|</code>.
1591+
1. Let |adjustedCornerStart| be |originalCornerStart|, [=point extended by vectors|extended by=] « |offset1|, |offset2| ».
1592+
1. Let |adjustedCornerEnd| be |originalCornerEnd|, [=point extended by vectors|extended by=] « |offset3|, |offset4| ».
1593+
1. Let |adjustedCornerCenter| be |originalCornerCenter|, [=point extended by vectors|extended by=] « |offset4|, |offset1| ».
1594+
1. Let |adjustedCornerOuter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |offset2|, |offset3| ».
1595+
1. Let |curveCenter| be |adjustedCornerOuter| if |curvature| is less than 0, |adjustedCornerCenter| otherwise.
1596+
1. Let |mapPointToCorner| be the following steps: given numbers |x| and |y|:
1597+
1. Let |v1| be [=vector between two points|the vector between=] |curveCenter| and |adjustedCornerEnd|, [=two-dimensional vector/scale|scaled by=] |x|.
1598+
1. Let |v2| be [=vector between two points|the vector between=] |curveCenter| and |adjustedCornerStart|, [=two-dimensional vector/scale|scaled by=] |y|.
1599+
1. Return the {{DOMPointReadOnly}} at <code>(|x|, |y|)</code>, [=point extended by vectors|extended by=] « |v1|, |v2| ».
1600+
1601+
1. Let |controlPoint| be the result of calling |mapPointToCorner| given |vectorFromStartToControlPoint|'s {{DOMPointReadOnly/y}} and <code>1 - |unitVectorFromStartToControlPoint|'s {{DOMPointReadOnly/x}}</code>.
1602+
1. Let |axisAlignedCornerStart| be the intersection between the lines <code>(|adjustedCornerStart|, |controlPoint|)</code> and <code>(|clipStart|, |clipOuter|)</code>. If the lines are parallel, let it be <code>adjustedCornerStart</code>.
1603+
1. Let |axisAlignedCornerEnd| be the intersection between the lines <code>(|adjustedCornerEnd|, |controlPoint|)</code> and <code>(|clipEnd|, |clipOuter|)</code>. If the lines are parallel, let it be <code>adjustedCornerEnd</code>.
1604+
1605+
Note: |axisAlignedCornerStart| and |axisAlignedCornerEnd| act as "miters" when rendering an outset.
1606+
They are a straight extension of the curve's tangent, intersecting with the unshaped target rect.
1607+
1608+
1. Let |path| be a path, starting at |axisAlignedCornerStart|.
1609+
1. If |curvature| is -∞:
1610+
1. Extend |path| to |adjustedCornerStart|.
1611+
1. Extend |path| to |adjustedCornerCenter|.
1612+
1. Extend |path| to |adjustedCornerEnd|.
1613+
1. Otherwise:
1614+
1. Let |K| be <code>0.5<sup>-abs(|curvature|)</sup></code>.
1615+
1. For every |T| between 0 and 1, in an [=implementation-approximated=] manner,
1616+
extend |path| to the result of calling |mapPointToCorner| given <code>|T|<sup>|K|</sup></code> and <code>(1 - |T|)<sup>|K|</sup></code>.
1617+
1618+
1. Extend |path| to |axisAlignedCornerEnd|.
1619+
1. Extend |path| to |clipOuter|.
1620+
1. Return |path|.
15681621
</div>
15691622

15701623
<wpt>
@@ -1635,7 +1688,7 @@ To compute the <dfn>normalized superellipse half corner</dfn> given a [=superell
16351688
: Otherwise
16361689
::
16371690
1. Let |k| be <code>0.5<sup>abs(|s|)</sup></code>.
1638-
1. Let |convexHalfCorner| be <code>0.5<sup>|k|</sup></code>.
1691+
1. Let |convexHalfCorner| be <code>0.5<sup>1/|k|</sup></code>.
16391692
1. If |s| is less than 0, return <code>1 - |convexHalfCorner|</code>.
16401693
1. Return |convexHalfCorner|.
16411694
</dl>

0 commit comments

Comments
 (0)