diff --git a/css-borders-4/Overview.bs b/css-borders-4/Overview.bs
index 3e311e41d5c..3b92ae024f1 100644
--- a/css-borders-4/Overview.bs
+++ b/css-borders-4/Overview.bs
@@ -20,6 +20,12 @@ Warning: Not Ready
spec:css-text-4; type:value; text:collapse
spec:css-shapes-2; type:function; text:path()
spec:css-shapes-2; type:property; text:shape-inside
+spec:geometry-1; type: dfn; text: width dimension
+spec:geometry-1; type: dfn; text: height dimension
+spec:geometry-1; type: dfn; text: x coordinate; for: rectangle
+spec:geometry-1; type: dfn; text: y coordinate; for: rectangle
+spec:geometry-1; type: dfn; text: rectangle
+spec:dom; type: dfn; text: element;
@@ -358,10 +364,144 @@ Like 'border-radius', 'corner-shape' clips elements according to the [=overflow=
Since stroking a superellipse accurately may be computationally intensive, user agents may approximate the path using bezier curves,
as well as account for sharp edges and overlaps.
-Issue: 'border-radius' already handles *adjacent* corners overlapping by shrinking the radiuses proportionally.
-A negative ''superellipse()'' parameter allows for *opposite* corners to sometimes overlap, and needs additional restrictions defined.
-
-Issue #11610: check if we need additional rendering restrictions.
+When rendering a [=border=] for a box that has a 'border-radius' and a 'corner-shape',
+the inner border follows the curve of the outer shape, with a nearly consistent distance from the outer path throughout,
+or a linearly increasing distance if the 'border-width' of the two edges of the corner is not uniform.
+
+In contrast, when rendering a 'box shadow' or when extending the [=overflow clip edge=], the resulting path does not trace border contour.
+Instead, it preserves the original shape and scales it in an axis-aligned manner.
+
+
+
+ Borders are aligned to the curve, shadows and clip are aligned to the axis.
+
+
+
+An [=/element=] |element|'s outer contour is the [=border contour path=] given |element| and |element|'s [=border edge=].
+
+An [=/element=] |element|'s inner contour is the [=border contour path=] given |element| and |element|'s [=padding edge=].
+
+An [=/element=]'s [=border=] is rendered in the area between its [=outer contour=] and its [=inner contour=].
+
+An [=/element=]'s [=overflow=] area is shaped by its [=inner contour=].
+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'.
+
+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'.
+
+
+To compute an [=/element=] |element|'s border contour path given an an [=edge=] |targetEdge| and an optional number |spread| (default 0):
+ 1. Let |outerLeft|, |outerTop|, |outerRight|, |outerBottom| be |element|'s [=unshaped edge|unshaped=] [=border edge=].
+ 1. Let |topLeftHorizontalRadius|, |topLeftVericalRadius|, |topRightHorizontalRadius|, |topRightVerticalRadius|, |bottomRightHorizontalRadius|,
+ |bottomRightVerticalRadius|, |bottomLeftHorizontalRadius|, and |bottomLeftVerticalRadius| be |element| [=border edge=]'s radii.
+ 1. Let |topLeftShape|, |topRightShape|, |bottomRightShape|, and |bottomLeftShape| be |element|'s [=computed value|computed=] 'corner-*-shape' values.
+ 1. Let |targetLeft|, |targetTop|, |targetRight|, |targetBottom| [=unshaped edge|unshaped=] |targetEdge|.
+ 1. Let |path| be a new path [[SVG2]].
+ 1. Compute a [=corner path=] given
+ the [=rectangle=] (|outerRight| - |topRightHorizontalRadius|, |outerTop|, |topRightHorizontalRadius|, |topRightVerticalRadius|),
+ 0, |targetTop| - |outerTop|, |outerRight| - |targetRight|, and |topRightShape|,
+ and append it to |path|.
+ 1. Compute a [=corner path=] given
+ the rectangle (|outerRight| - |bottomRightHorizontalRadius|, |outerBottom| - |bottomRightVerticalRadius|, |bottomRightHorizontalRadius|, |bottomRightVerticalRadius|), |targetEdge|,
+ 1, |outerRight| - |targetRight|, |outerBottom| - |targetBottom|, and |bottomRightShape|,
+ and append it to |path|.
+ 1. Compute a [=corner path=] given
+ the rectangle (|outerLeft|, |outerBottom| - |bottomLeftVerticalRadius|, |bottomLeftHorizontalRadius|, |bottomLeftVerticalRadius|), |targetEdge|,
+ 2, |outerBottom| - |targetBottom|, |targetLeft| - |outerLeft|, and |bottomLeftShape|,
+ and append it to |path|.
+ 1. Compute a [=corner path=] given
+ the rectangle (|outerLeft|, |outerTop|, |topLeftHorizontalRadius|, |topLeftVericalRadius|), |targetEdge|,
+ 3, |targetLeft| - |outerLeft|, |targetTop| - |outerTop|, and |topLeftShape|,
+ and append it to |path|.
+ 1. If |spread| is not 0, then:
+ 1. Scale |path| by 1 + (|spread| * 2) / (|targetRect|'s [=width dimension|width=]), 1 + (|spread| * 2) / (|targetEdge|'s [=height dimension|height=]).
+ 1. Translate |path| by -|spread|, -|spread|.
+
+ Note: this creates an effect where the resulting path has the same shape as the original path, but scaled to fit the given spread.
+ 1. Return |path|.
+
+To compute the corner path given a rectangle |cornerRect|, a rectangle |trimRect|, and numbers |startThickness|, |endThickness|, |orientation|, and |curvature|:
+ 1. Assert: |orientation| is 0, 1, 2, or 3.
+ 1. If |curvature| is less than zero, then:
+ 1. Set |curvature| to -|curvature|.
+ 1. Swap between |startThickness| and |endThickness|.
+ 1. Set |orientation| to (|orientation| + 2) % 4.
+ 1. Let |cornerPath| be a path that begins at (0, 1).
+ 1. Switch on |curvature|:
+
+ : 0
+ :: Extend |cornerPath| by adding a straight line to (1, 0).
+
+ : ∞
+ ::
+ 1. Extend |cornerPath| by adding a straight line to (1, 1).
+ 1. Extend |cornerPath| by adding a straight line to (1, 0).
+
+ : Otherwise
+ ::
+ 1. Let |K| be 0.5|curvature|.
+ 1. For each |T| between 0 and 1, extend |cornerPath| through (|T||K|, (1−|T|)|K|).
+
+ User agents may approximate this path, for instance, by using concatenated Bezier curves, to balance between performance and rendering accuracy.
+
+
+ 1. Let (|x|, |y|, |width|, |height|) be |targetRect|.
+ 1. Let |clockwiseRectQuad| be « (|x|, |y|), (|x| + |width|, |y|), (|x| + |width|, |y| + |height|), (|x|, |y| + height|) ».
+ 1. Let |curveStartPoint| be |clockwiseRectQuad|[|orientation|].
+ 1. Let |curveEndPoint| be |clockwiseRectQuad|[(|orientation| + 2) % 4].
+ 1. If either |startThickness| or |endThickness| is greater than 0, then:
+
+ Note: the following substeps compute a new |curveStartPoint| and |curveEndPoint|, based on the thickness and |curvature|.
+ The start and end points are offset inwards, perpendicular to the direction of the curve, with the corresponding |startThickness| or |endThickness|.
+
+ 1. Let |tangentUnitVector| be (1, 0).
+
+ Note: |tangentUnitVector| is a unit vector (length of 1 pixel) that points along a curve with both positive X and Y components
+ (like a top-right corner) and reflects the given |curvature|. This base vector can then be rotated to align with the specific corner's orientation
+ and scaled to match the required border thickness.
+ For round curvatures, or for hyperellipses (|curvature| greater than 1), the tangent is a horizontal line to the right.
+
+
+
+ When the 'corner-shape' is ''corner-shape/round'' or more convex (>= 1), the unit vector is 1, 0.
+
+
+
+ 1. If |curvature| is less than 1:
+ 1. Let |halfCorner| be the [=normalized superellipse half corner=] given |curvature|.
+ 1. Let |offsetX| be max(0, (|halfCorner| - 1) * 2 + √2).
+ 1. Let |offsetY| be max(0, √2 - |halfCorner| * 2).
+
+ Note: This formula defines the tangent of a quadratic Bezier curve that's equivalent to a superellipse quadrant.
+ Notably, convex hypoellipses (superellipses with a [=superellipse parameter|parameter=] between 0 and 1) can be very precisely represented by quadratic curves.
+
+ 1. Let |length| be hypot(|offsetX|, |offsetY|).
+ 1. Set |tangentUnitVector| to (|offsetX| / |length|, |offsetY| / |length|).
+
+ At this point |curvature| is guaranteed to be convex (>=1), so ther resulting |tangentUnitVector| would be in the range between (1, 0) and (√2/2, √2/2).
+
+
+
+ When the 'corner-shape' is ''corner-shape/bevel'' (0), the unit vector is √2/2, √2/2.
+
+
+
+ 1. Let |startOffset| be |tangentUnitVector|, scaled by |startThickness| and rotated 90° * ((|orientation| + 1) % 4) clockwise.
+ 1. Let |endOffset| be |tangentUnitVector|, scaled by |endThickness| and rotated by 90° * ((|orientation| + 2) % 4) clockwise.
+ 1. Translate |curveStartPoint| by |startOffset|.
+ 1. Translate |curveEndPoint| by |endOffset|.
+ 1. Set |cornerRect| to a rectangle that contains |curveStartPoint| and |curveEndPoint|.
+ 1. Rotate |cornerPath| by 90° * |orientation|, with (0.5, 0.5) as the origin, as described [=transformation matrix|here=].
+ 1. Scale |cornerPath| by |cornerRect|'s [=width dimension|width=], |cornerRect|'s [=width dimension|height=].
+ 1. translate |cornerPath| by |cornerRect|'s [=x coordinate|x=], |cornerRect|'s [=y coordinate|y=].
+ 1. Trim |cornerPath| to |trimRect|.
+ 1. Return |cornerPath|.
+
'corner-shape' values
@@ -396,7 +536,7 @@ Issue #11610: che
It is a number between -infinity and infinity, with -infinity corresponding to a straight concave corner,
infinity corresponding to a square convex corner.
- The canonical superellipse formula can be described in Cartesian coordinates, as follows,
+ The canonical superellipse formula can be described in Cartesian coordinates, as follows,
where s is the [=superellipse parameter=]:
@@ -415,10 +555,10 @@ Issue #11610: che
+ width="320" height="240"
+ style="background: white; padding: 8px;"
+ title="rendering of different superellipse parameter values"
+ alt="Rendering of different superellipse parameter values.">
Rendering examples of different ''superellipse()'' values.
@@ -504,7 +644,7 @@ Since it uses a log2, interpolating it linearly would result in an
To balance that, the superellipse interpolation formula describes how a [=superellipse parameter=] is converted to a value between 0 and 1, and vice versa:
-To interpolate a <> |s| to an interpolation value between 0 and 1, return the first matching statement, switch on |s|:
+To compute the normalized superellipse half corner given a [=superellipse parameter=] |s|, return the first matching statement, switching on |s|:
: -∞
:: Return 0.
@@ -518,9 +658,10 @@ To interpolate a <> |s| to an interpolation value bet
1. Let |convexHalfCorner| be 0.5|k|.
1. If |param| is less than 0, return 1 - |convexHalfCorner|.
1. Return |convexHalfCorner|.
-
+To interpolate a [=superellipse parameter=] |s| to an interpolation value between 0 and 1, return the [=normalized superellipse half corner=] given |s|.
+
To convert a <> |interpolationValue| back to a [=superellipse parameter=], switch on |interpolationValue|: