Implementation
@override
List<Radius>? get borderRadius {
// Fast path: if all corners are zero, no radii.
final CSSBorderRadius tl = _borderTopLeftRadius ?? CSSBorderRadius.zero;
final CSSBorderRadius tr = _borderTopRightRadius ?? CSSBorderRadius.zero;
final CSSBorderRadius br = _borderBottomRightRadius ?? CSSBorderRadius.zero;
final CSSBorderRadius bl = _borderBottomLeftRadius ?? CSSBorderRadius.zero;
final bool hasAnyRadius = !(tl == CSSBorderRadius.zero && tr == CSSBorderRadius.zero &&
br == CSSBorderRadius.zero && bl == CSSBorderRadius.zero);
if (!hasAnyRadius) return null;
// Cache to avoid recomputing per paint phase.
// When any axis uses percentages, the result depends on the border box size.
final bool tlPct = tl.x.isPercentage || tl.y.isPercentage;
final bool trPct = tr.x.isPercentage || tr.y.isPercentage;
final bool brPct = br.x.isPercentage || br.y.isPercentage;
final bool blPct = bl.x.isPercentage || bl.y.isPercentage;
final bool anyPct = tlPct || trPct || brPct || blPct;
final double? bw = borderBoxWidth ?? borderBoxLogicalWidth;
final double? bh = borderBoxHeight ?? borderBoxLogicalHeight;
// Reuse cached radii when inputs are identical and the size anchor (for %) is unchanged.
if (_cachedComputedBorderRadius != null &&
identical(_cachedTLRef, _borderTopLeftRadius) &&
identical(_cachedTRRef, _borderTopRightRadius) &&
identical(_cachedBRRef, _borderBottomRightRadius) &&
identical(_cachedBLRef, _borderBottomLeftRadius) &&
(!anyPct || (_cachedBorderRadiusW == bw && _cachedBorderRadiusH == bh))) {
return _cachedComputedBorderRadius;
}
final radii = <Radius>[
tl.computedRadius,
tr.computedRadius,
br.computedRadius,
bl.computedRadius,
];
_cachedComputedBorderRadius = radii;
_cachedBorderRadiusW = anyPct ? bw : _cachedBorderRadiusW; // only bind size when needed
_cachedBorderRadiusH = anyPct ? bh : _cachedBorderRadiusH;
_cachedTLRef = _borderTopLeftRadius;
_cachedTRRef = _borderTopRightRadius;
_cachedBRRef = _borderBottomRightRadius;
_cachedBLRef = _borderBottomLeftRadius;
if (DebugFlags.enableBorderRadiusLogs) {
try {
final el = target;
renderingLogger.finer('[BorderRadius] compute for <${el.tagName.toLowerCase()}> '
'borderBox=${(bw)?.toStringAsFixed(2) ?? 'null'}×${(bh)?.toStringAsFixed(2) ?? 'null'} '
'tl=(${radii[0].x.toStringAsFixed(2)},${radii[0].y.toStringAsFixed(2)}) '
'tr=(${radii[1].x.toStringAsFixed(2)},${radii[1].y.toStringAsFixed(2)}) '
'br=(${radii[2].x.toStringAsFixed(2)},${radii[2].y.toStringAsFixed(2)}) '
'bl=(${radii[3].x.toStringAsFixed(2)},${radii[3].y.toStringAsFixed(2)})');
} catch (_) {}
}
return radii;
}