Skip to content

Commit dbedc50

Browse files
authored
[css-borders-4] Constrain radii for concave opposite corners (#12272)
* [css-borders-4] Constrain radii for concave opposite corners If the hulls of opposite corners overlap, find a scale factor that would prevent the overlap, and apply to all radii. Resolution: #12098 (comment) Closes #12098 * Fix hull computation for convex/concave
1 parent f48a484 commit dbedc50

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

css-borders-4/Overview.bs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,8 @@ Each shadow of [=/element=]'s 'box shadow' is shaped by the [=border contour pat
394394
To compute an [=/element=] |element|'s <dfn>border contour path</dfn> given an an [=edge=] |targetEdge| and an optional number |spread| (default 0):
395395
1. Let |outerLeft|, |outerTop|, |outerRight|, |outerBottom| be |element|'s [=unshaped edge|unshaped=] [=border edge=].
396396
1. Let |topLeftHorizontalRadius|, |topLeftVericalRadius|, |topRightHorizontalRadius|, |topRightVerticalRadius|, |bottomRightHorizontalRadius|,
397-
|bottomRightVerticalRadius|, |bottomLeftHorizontalRadius|, and |bottomLeftVerticalRadius| be |element| [=border edge=]'s radii.
397+
|bottomRightVerticalRadius|, |bottomLeftHorizontalRadius|, and |bottomLeftVerticalRadius| be |element| [=border edge=]'s radii,
398+
scaled by |element|'s [=opposite corner scale factor=].
398399
1. Let |topLeftShape|, |topRightShape|, |bottomRightShape|, and |bottomLeftShape| be |element|'s [=computed value|computed=] 'corner-*-shape' values.
399400
1. Let |targetLeft|, |targetTop|, |targetRight|, |targetBottom| [=unshaped edge|unshaped=] |targetEdge|.
400401
1. Let |path| be a new path [[SVG2]].
@@ -503,6 +504,47 @@ To compute the <dfn>corner path</dfn> given a rectangle |cornerRect|, a rectangl
503504
1. Return |cornerPath|.
504505
</div>
505506

507+
<h4 id=corner-shape-constrain-radii>
508+
Constraining opposite radii</h4>
509+
510+
When concave 'corner-shape' values are present (the [=superellipse parameter=] is negative), diagonally opposite corners might overlap each other.
511+
512+
<div class="example">
513+
<p>The following example would create overlapping corners if not constrained.</p>
514+
<pre class="lang-css">
515+
div {
516+
corner-shape: scoop;
517+
border-top-left-radius: 80%;
518+
border-bottom-right-radius: 80%;
519+
}
520+
</pre>
521+
</div>
522+
523+
To prevent this, the four radii are constrained to prevent overlaps.
524+
This is done by computing a hull polygon for each of the opposite corners, and finding the highest downscale factor which, if applied to both corners, would make it so that the polygons would not intersect.
525+
526+
<div algorithm="constrain-radii-for-concave-corner-shape">
527+
To compute the <dfn>opposite corner scale factor</dfn> given an [=/element=] |element|:
528+
1. Let |rect| be |element|'s [=border box=].
529+
1. Let |topRightHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-top-right-shape',
530+
mapped to the rectangle (|rect|'s [=width dimension=] - |element|'s [=computed value|computed=] horizontal 'border-top-right-radius', 0, |rect|'s [=computed value|computed=] 'border-top-right-radius').
531+
1. Let |bottomRightHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-bottom-right-shape',
532+
rotated by 90deg with (0.5, 0.5) as an origin,
533+
and mapped to the rectangle (|rect|'s [=width dimension=] - |element|'s [=computed value|computed=] horizontal 'border-bottom-right-radius', |rect|'s [=height dimension=] - |element|'s [=computed value|computed=] vertical 'border-bottom-right-radius',
534+
|element|'s [=computed value|computed=] 'border-bottom-right-radius').
535+
1. Let |bottomLeftHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-bottom-right-shape',
536+
rotated by 180deg with (0.5, 0.5) as an origin,
537+
and mapped to the rectangle (0, |rect|'s [=height dimension=] - |element|'s [=computed value|computed=] vertical 'border-bottom-left-radius',
538+
|element|'s [=computed value|computed=] 'border-bottom-left-radius').
539+
1. Let |topLeftHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-top-left-shape',
540+
rotated by 270deg with (0.5, 0.5) as an origin,
541+
mapped to (0, 0, |element|'s [=computed value|computed=] 'border-top-left-radius').
542+
1. Let |scaleFactorA| be the highest number which, if both |topLeftHull| and |bottomRightHull| were scaled by, using their first point as the origin, those polygons would not intersect.
543+
1. Let |scaleFactorB| be the highest number which, if both |topRightHull| and |bottomLeftHull| were scaled by, using their first point as the origin, those polygons would not intersect.
544+
1. Return <code>min(1, |scaleFactorA|, |scaleFactorB|)</code>.
545+
</div>
546+
547+
506548
<h4 id=corner-shape-value>
507549
'corner-shape' values</h4>
508550

@@ -660,6 +702,20 @@ To compute the <dfn>normalized superellipse half corner</dfn> given a [=superell
660702
1. Return |convexHalfCorner|.
661703
</dl>
662704

705+
<div algorithm="superellipse-param-to-hull">
706+
To compute the <dfn>normalized inner corner hull</dfn> given a [=superellipse parameter=] |curvature|:
707+
1. If |curvature| is greater than or equal to zero, return a triangle betwen « (1, 1), (1, 0), (0, 1) ».
708+
1. Let |axisLineA| be a line between <code>(1, 0)</code> and <code>(1, 1)</code>.
709+
1. Let |axisLineB| be a line between <code>(0, 1)</code> and <code>(1, 1)</code>.
710+
1. Let |normalizedHalfCorner| be the [=normalized superellipse half corner=] given |curvature|.
711+
1. Let |halfCornerPoint| be <code>(|normalizedHalfCorner|, 1 - |normalizedHalfCorner|)</code>.
712+
1. Let |lineFromCenterToHalfCorner| be a line between <code>(0, 0)</code> and |halfCornerPoint|.
713+
1. Let |tangentLine| be the line perpendicular to |lineFromCenterToHalfCorner|, at |halfCornerPoint|.
714+
1. Let |intersectionA| be the intersection between |axisLineA| and |tangentLine|.
715+
1. Let |intersectionB| be the intersection between |axisLineB| and |tangentLine|.
716+
1. Return a pentagon between the points « (1, 1), (1, 0), |intersectionA|, |intersectionB|, (0, 1), (1, 1) ».
717+
</div>
718+
663719
To interpolate a [=superellipse parameter=] |s| to an interpolation value between 0 and 1, return the [=normalized superellipse half corner=] given |s|.
664720

665721
To convert a <<number [0,1]>> |interpolationValue| back to a [=superellipse parameter=], switch on |interpolationValue|:

0 commit comments

Comments
 (0)