1- import type { Calculation } from '../calculation' ;
1+ import { solve , type Calculation } from '../calculation' ;
22import type { FunctionNode , TokenNode } from '@csstools/css-parser-algorithms' ;
33import { convertUnit } from '../unit-conversions' ;
44import { resultToCalculation } from './result-to-calculation' ;
55import { twoOfSameNumeric } from '../util/kind-of-number' ;
6- import { isTokenNumeric , isTokenPercentage } from '@csstools/css-tokenizer' ;
6+ import { isTokenDimension , isTokenNumeric , isTokenPercentage } from '@csstools/css-tokenizer' ;
77import type { conversionOptions } from '../options' ;
8+ import { snapAsBorderWidth } from '../util/snap-to-border-width' ;
89
910export function solveRound ( roundNode : FunctionNode , roundingStrategy : string , a : TokenNode , b : TokenNode , options : conversionOptions ) : Calculation | - 1 {
1011 const aToken = a . value ;
1112 if ( ! isTokenNumeric ( aToken ) ) {
1213 return - 1 ;
1314 }
1415
16+ if ( roundingStrategy === 'line-width' && ! isTokenDimension ( aToken ) ) {
17+ return - 1 ;
18+ }
19+
1520 if ( ! options . rawPercentages && isTokenPercentage ( aToken ) ) {
1621 return - 1 ;
1722 }
@@ -22,14 +27,20 @@ export function solveRound(roundNode: FunctionNode, roundingStrategy: string, a:
2227 }
2328
2429 let result ;
30+ // https://drafts.csswg.org/css-values-4/#round-infinities
2531 if ( bToken [ 4 ] . value === 0 ) {
32+ // In round(A, B), if B is 0, the result is NaN.
2633 result = Number . NaN ;
2734 } else if ( ! Number . isFinite ( aToken [ 4 ] . value ) && ! Number . isFinite ( bToken [ 4 ] . value ) ) {
35+ // If A and B are both infinite, the result is NaN.
2836 result = Number . NaN ;
2937 } else if ( ! Number . isFinite ( aToken [ 4 ] . value ) && Number . isFinite ( bToken [ 4 ] . value ) ) {
38+ // If A is infinite but B is finite, the result is the same infinity.
3039 result = aToken [ 4 ] . value ;
3140 } else if ( Number . isFinite ( aToken [ 4 ] . value ) && ! Number . isFinite ( bToken [ 4 ] . value ) ) {
41+ // If A is finite but B is infinite, the result depends on the <rounding-strategy> and the sign of A:
3242 switch ( roundingStrategy ) {
43+ // If A is negative (not zero), return −∞. If A is 0⁻, return 0⁻. Otherwise, return 0⁺.
3344 case 'down' :
3445 if ( aToken [ 4 ] . value < 0 ) {
3546 result = - Infinity ;
@@ -40,6 +51,7 @@ export function solveRound(roundNode: FunctionNode, roundingStrategy: string, a:
4051 }
4152 break ;
4253 case 'up' :
54+ // If A is positive (not zero), return +∞. If A is 0⁺, return 0⁺. Otherwise, return 0⁻.
4355 if ( aToken [ 4 ] . value > 0 ) {
4456 result = + Infinity ;
4557 } else if ( Object . is ( + 0 , aToken [ 4 ] . value * 0 ) ) {
@@ -50,16 +62,16 @@ export function solveRound(roundNode: FunctionNode, roundingStrategy: string, a:
5062 break ;
5163 case 'to-zero' :
5264 case 'nearest' :
65+ case 'line-width' :
5366 default : {
67+ // If A is positive or 0⁺, return 0⁺. Otherwise, return 0⁻.
5468 if ( Object . is ( + 0 , aToken [ 4 ] . value * 0 ) ) {
5569 result = + 0 ;
5670 } else {
5771 result = - 0 ;
5872 }
5973 }
6074 }
61- } else if ( ! Number . isFinite ( bToken [ 4 ] . value ) ) {
62- result = aToken [ 4 ] . value ;
6375 } else {
6476 switch ( roundingStrategy ) {
6577 case 'down' :
@@ -72,6 +84,7 @@ export function solveRound(roundNode: FunctionNode, roundingStrategy: string, a:
7284 result = Math . trunc ( aToken [ 4 ] . value / bToken [ 4 ] . value ) * bToken [ 4 ] . value ;
7385 break ;
7486 case 'nearest' :
87+ case 'line-width' :
7588 default : {
7689 let down = Math . floor ( aToken [ 4 ] . value / bToken [ 4 ] . value ) * bToken [ 4 ] . value ;
7790 let up = Math . ceil ( aToken [ 4 ] . value / bToken [ 4 ] . value ) * bToken [ 4 ] . value ;
@@ -84,14 +97,25 @@ export function solveRound(roundNode: FunctionNode, roundingStrategy: string, a:
8497 const downDiff = Math . abs ( aToken [ 4 ] . value - down ) ;
8598 const upDiff = Math . abs ( aToken [ 4 ] . value - up ) ;
8699
87- if ( downDiff === upDiff ) {
100+ if ( roundingStrategy === 'line-width' && aToken [ 4 ] . value > 0 && ( up === 0 || down === 0 ) ) {
101+ result = up !== 0 ? up : down ;
102+ } else if ( downDiff === upDiff ) {
88103 result = up ;
89104 } else if ( downDiff < upDiff ) {
90105 result = down ;
91106 } else {
92107 result = up ;
93108 }
94109
110+ if ( roundingStrategy === 'line-width' ) {
111+ const solved = solve ( resultToCalculation ( roundNode , aToken , result ) , options ) ;
112+ if ( solved === - 1 ) {
113+ return - 1 ;
114+ }
115+
116+ return snapAsBorderWidth ( roundNode , solved . value , options ) ;
117+ }
118+
95119 break ;
96120 }
97121 }
0 commit comments