Changeset 283359 in webkit
- Timestamp:
- Oct 1, 2021, 12:58:12 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/css/calc-parsing-expected.txt (modified) (4 diffs)
-
LayoutTests/fast/css/calc-parsing.html (modified) (2 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/css/CSSValueKeywords.in (modified) (1 diff)
-
Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (modified) (3 diffs)
-
Source/WebCore/css/calc/CSSCalcOperationNode.cpp (modified) (17 diffs)
-
Source/WebCore/css/calc/CSSCalcOperationNode.h (modified) (3 diffs)
-
Source/WebCore/css/calc/CSSCalcValue.cpp (modified) (2 diffs)
-
Source/WebCore/platform/calc/CalcExpressionOperation.cpp (modified) (1 diff)
-
Source/WebCore/platform/calc/CalcOperator.cpp (modified) (1 diff)
-
Source/WebCore/platform/calc/CalcOperator.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r283358 r283359 1 2021-10-01 Kevin Turner <kevin_turner@apple.com> 2 3 Add support for pow(), sqrt() and hypot() per https://drafts.csswg.org/css-values-4/#exponent-funcs. 4 https://bugs.webkit.org/show_bug.cgi?id=203312 5 6 Reviewed by Simon Fraser. 7 8 Tests performing CSS calculations with pow(), sqrt(), and hypot() with a range of inputs. 9 * fast/css/calc-parsing-expected.txt: 10 * fast/css/calc-parsing.html: 11 1 12 2021-09-30 Lauro Moura <lmoura@igalia.com> 2 13 -
trunk/LayoutTests/fast/css/calc-parsing-expected.txt
r282162 r283359 53 53 PASS getComputedStyle(element).getPropertyValue('width') is "100px" 54 54 55 element.style["width"] = "calc(100px * pow(2, pow(2, 2)))" 56 PASS element.style['width'] is "calc(1600px)" 57 PASS getComputedStyle(element).getPropertyValue('width') is "1600px" 58 59 element.style["width"] = "calc(1px * pow(2, 3))" 60 PASS element.style['width'] is "calc(8px)" 61 PASS getComputedStyle(element).getPropertyValue('width') is "8px" 62 63 element.style["width"] = "calc(100px * sqrt(100))" 64 PASS element.style['width'] is "calc(1000px)" 65 PASS getComputedStyle(element).getPropertyValue('width') is "1000px" 66 67 element.style["width"] = "calc(1px * sqrt(999))" 68 PASS element.style['width'] is "calc(31.606961258558215px)" 69 PASS getComputedStyle(element).getPropertyValue('width') is "31.59375px" 70 71 element.style["width"] = "calc(1px * pow(2, sqrt(100))" 72 PASS element.style['width'] is "calc(1024px)" 73 PASS getComputedStyle(element).getPropertyValue('width') is "1024px" 74 75 element.style["width"] = "hypot(4px, 5px, 7px, 9px)" 76 PASS element.style['width'] is "hypot(13.076696830622021px)" 77 PASS getComputedStyle(element).getPropertyValue('width') is "13.0625px" 78 79 element.style["width"] = "hypot(3px, 4px)" 80 PASS element.style['width'] is "hypot(5px)" 81 PASS getComputedStyle(element).getPropertyValue('width') is "5px" 82 83 element.style["width"] = "calc(100px * hypot(3, 4))" 84 PASS element.style['width'] is "calc(500px)" 85 PASS getComputedStyle(element).getPropertyValue('width') is "500px" 86 87 element.style["width"] = "hypot(-5px)" 88 PASS element.style['width'] is "hypot(5px)" 89 PASS getComputedStyle(element).getPropertyValue('width') is "5px" 90 91 element.style["width"] = "calc(1px * hypot(-5))" 92 PASS element.style['width'] is "calc(5px)" 93 PASS getComputedStyle(element).getPropertyValue('width') is "5px" 94 95 element.style["width"] = "calc(1px * hypot(10000))" 96 PASS element.style['width'] is "calc(10000px)" 97 PASS getComputedStyle(element).getPropertyValue('width') is "10000px" 98 99 element.style["width"] = "calc(2px * sqrt(100000000))" 100 PASS element.style['width'] is "calc(20000px)" 101 PASS getComputedStyle(element).getPropertyValue('width') is "20000px" 102 103 element.style["width"] = "calc(3px * pow(200, 4))" 104 PASS element.style['width'] is "calc(4800000000px)" 105 PASS getComputedStyle(element).getPropertyValue('width') is "33554428px" 106 55 107 element.style["width"] = "calc(sin(90deg) * 100px)" 56 108 PASS 100 is 100 … … 126 178 127 179 element.style["width"] = "clamp(1px,2px,2px,4px)" 180 PASS element.style['width'] is "999px" 181 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 182 183 element.style["width"] = "calc(1px * pow(1))" 184 PASS element.style['width'] is "999px" 185 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 186 187 element.style["width"] = "calc(1px * pow(2px, 3px))" 188 PASS element.style['width'] is "999px" 189 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 190 191 element.style["width"] = "calc(sqrt(100px)" 192 PASS element.style['width'] is "999px" 193 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 194 195 element.style["width"] = "hypot(2px, 40%)" 196 PASS element.style['width'] is "999px" 197 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 198 199 element.style["width"] = "hypot(2px, 3)" 200 PASS element.style['width'] is "999px" 201 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 202 203 element.style["width"] = "hypot(3, ,4)" 204 PASS element.style['width'] is "999px" 205 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 206 207 element.style["width"] = "calc(1px * pow(2 3))" 208 PASS element.style['width'] is "999px" 209 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 210 211 element.style["width"] = "hypot()" 212 PASS element.style['width'] is "999px" 213 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 214 215 element.style["width"] = "calc(pow(2))" 216 PASS element.style['width'] is "999px" 217 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 218 219 element.style["width"] = "pow())" 220 PASS element.style['width'] is "999px" 221 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 222 223 element.style["width"] = "calc(sqrt())" 224 PASS element.style['width'] is "999px" 225 PASS getComputedStyle(element).getPropertyValue('width') is "999px" 226 227 element.style["width"] = "calc(sqrt(100, 200))" 128 228 PASS element.style['width'] is "999px" 129 229 PASS getComputedStyle(element).getPropertyValue('width') is "999px" … … 213 313 PASS getComputedStyle(element).getPropertyValue('min-width') is "clamp(100px, 0%, 1%)" 214 314 315 element.style["min-width"] = "calc(100px * pow(2, pow(2, 2)))" 316 PASS element.style['min-width'] is "calc(1600px)" 317 PASS getComputedStyle(element).getPropertyValue('min-width') is "1600px" 318 319 element.style["min-width"] = "calc(1px * pow(2, 3))" 320 PASS element.style['min-width'] is "calc(8px)" 321 PASS getComputedStyle(element).getPropertyValue('min-width') is "8px" 322 323 element.style["min-width"] = "calc(100px * sqrt(100))" 324 PASS element.style['min-width'] is "calc(1000px)" 325 PASS getComputedStyle(element).getPropertyValue('min-width') is "1000px" 326 327 element.style["min-width"] = "calc(1px * sqrt(999))" 328 PASS element.style['min-width'] is "calc(31.606961258558215px)" 329 PASS getComputedStyle(element).getPropertyValue('min-width') is "31.606962203979492px" 330 331 element.style["min-width"] = "calc(1px * pow(2, sqrt(100))" 332 PASS element.style['min-width'] is "calc(1024px)" 333 PASS getComputedStyle(element).getPropertyValue('min-width') is "1024px" 334 335 element.style["min-width"] = "hypot(4px, 5px, 7px, 9px)" 336 PASS element.style['min-width'] is "hypot(13.076696830622021px)" 337 PASS getComputedStyle(element).getPropertyValue('min-width') is "13.076696395874023px" 338 339 element.style["min-width"] = "hypot(3px, 4px)" 340 PASS element.style['min-width'] is "hypot(5px)" 341 PASS getComputedStyle(element).getPropertyValue('min-width') is "5px" 342 343 element.style["min-width"] = "calc(100px * hypot(3, 4))" 344 PASS element.style['min-width'] is "calc(500px)" 345 PASS getComputedStyle(element).getPropertyValue('min-width') is "500px" 346 347 element.style["min-width"] = "hypot(-5px)" 348 PASS element.style['min-width'] is "hypot(5px)" 349 PASS getComputedStyle(element).getPropertyValue('min-width') is "5px" 350 351 element.style["min-width"] = "calc(1px * hypot(-5))" 352 PASS element.style['min-width'] is "calc(5px)" 353 PASS getComputedStyle(element).getPropertyValue('min-width') is "5px" 354 355 element.style["min-width"] = "calc(1px * hypot(10000))" 356 PASS element.style['min-width'] is "calc(10000px)" 357 PASS getComputedStyle(element).getPropertyValue('min-width') is "10000px" 358 359 element.style["min-width"] = "calc(2px * sqrt(100000000))" 360 PASS element.style['min-width'] is "calc(20000px)" 361 PASS getComputedStyle(element).getPropertyValue('min-width') is "20000px" 362 363 element.style["min-width"] = "calc(3px * pow(200, 4))" 364 PASS element.style['min-width'] is "calc(4800000000px)" 365 PASS getComputedStyle(element).getPropertyValue('min-width') is "33554428px" 366 215 367 element.style["min-width"] = "calc(sin(90deg) * 100px)" 216 368 PASS 100 is 100 … … 289 441 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 290 442 443 element.style["min-width"] = "calc(1px * pow(1))" 444 PASS element.style['min-width'] is "999px" 445 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 446 447 element.style["min-width"] = "calc(1px * pow(2px, 3px))" 448 PASS element.style['min-width'] is "999px" 449 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 450 451 element.style["min-width"] = "calc(sqrt(100px)" 452 PASS element.style['min-width'] is "999px" 453 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 454 455 element.style["min-width"] = "hypot(2px, 40%)" 456 PASS element.style['min-width'] is "999px" 457 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 458 459 element.style["min-width"] = "hypot(2px, 3)" 460 PASS element.style['min-width'] is "999px" 461 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 462 463 element.style["min-width"] = "hypot(3, ,4)" 464 PASS element.style['min-width'] is "999px" 465 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 466 467 element.style["min-width"] = "calc(1px * pow(2 3))" 468 PASS element.style['min-width'] is "999px" 469 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 470 471 element.style["min-width"] = "hypot()" 472 PASS element.style['min-width'] is "999px" 473 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 474 475 element.style["min-width"] = "calc(pow(2))" 476 PASS element.style['min-width'] is "999px" 477 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 478 479 element.style["min-width"] = "pow())" 480 PASS element.style['min-width'] is "999px" 481 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 482 483 element.style["min-width"] = "calc(sqrt())" 484 PASS element.style['min-width'] is "999px" 485 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 486 487 element.style["min-width"] = "calc(sqrt(100, 200))" 488 PASS element.style['min-width'] is "999px" 489 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px" 490 291 491 element.style["min-width"] = "calc(sin(90px) * 100px)" 292 492 PASS element.style['min-width'] is "999px" -
trunk/LayoutTests/fast/css/calc-parsing.html
r282162 r283359 43 43 testExpression('max(100px,0%)', 'max(100px, 0%)', propertyName == 'width' ? '100px' : "max(100px, 0%)"); 44 44 testExpression('clamp(100px,0%,1%)', 'clamp(100px, 0%, 1%)', propertyName == 'width' ? '100px' : "clamp(100px, 0%, 1%)"); 45 testExpression('calc(100px * pow(2, pow(2, 2)))', 'calc(1600px)', '1600px'); 46 testExpression('calc(1px * pow(2, 3))', 'calc(8px)', '8px') 47 testExpression('calc(100px * sqrt(100))', 'calc(1000px)', '1000px'); 48 testExpression('calc(1px * sqrt(999))', 'calc(31.606961258558215px)', propertyName == 'width' ? '31.59375px' : '31.606962203979492px'); 49 testExpression('calc(1px * pow(2, sqrt(100))', 'calc(1024px)', '1024px'); 50 testExpression('hypot(4px, 5px, 7px, 9px)', 'hypot(13.076696830622021px)', propertyName == 'width' ? '13.0625px' : '13.076696395874023px'); 51 testExpression('hypot(3px, 4px)', 'hypot(5px)', '5px'); 52 testExpression('calc(100px * hypot(3, 4))', 'calc(500px)', '500px'); 53 testExpression('hypot(-5px)', 'hypot(5px)', '5px'); 54 testExpression('calc(1px * hypot(-5))', 'calc(5px)', '5px'); 55 testExpression('calc(1px * hypot(10000))', 'calc(10000px)', '10000px'); 56 testExpression('calc(2px * sqrt(100000000))', 'calc(20000px)', '20000px'); 57 testExpression('calc(3px * pow(200, 4))', 'calc(4800000000px)', '33554428px'); 45 58 testValue('calc(sin(90deg) * 100px)', '100'); 46 59 testValue('calc(sin(45deg + 45deg ) * 100px)', '100'); … … 66 79 testExpression('clamp((),,300px)', '999px', '999px'); 67 80 testExpression('clamp(1px,2px,2px,4px)', '999px', '999px'); 81 testExpression('calc(1px * pow(1))', '999px', '999px'); 82 testExpression('calc(1px * pow(2px, 3px))', '999px', '999px'); 83 testExpression('calc(sqrt(100px)', '999px', '999px'); 84 testExpression('hypot(2px, 40%)', '999px', '999px'); 85 testExpression('hypot(2px, 3)', '999px', '999px'); 86 testExpression('hypot(3, ,4)', '999px', '999px'); 87 testExpression('calc(1px * pow(2 3))', '999px', '999px'); 88 testExpression('hypot()', '999px', '999px'); 89 testExpression('calc(pow(2))', '999px', '999px'); 90 testExpression('pow())', '999px', '999px', '999px'); 91 testExpression('calc(sqrt())', '999px', '999px'); 92 testExpression('calc(sqrt(100, 200))', '999px', '999px'); 68 93 testExpression('calc(sin(90px) * 100px)', '999px', '999px'); 69 94 testExpression('calc(sin(30deg + 1.0471967rad, 0) * 100px)', '999px', '999px'); -
trunk/Source/WebCore/ChangeLog
r283355 r283359 1 2021-10-01 Kevin Turner <kevin_turner@apple.com> 2 3 Add support for pow(), sqrt() and hypot() 4 https://bugs.webkit.org/show_bug.cgi?id=203312 5 <rdar://82640883> 6 7 Reviewed by Simon Fraser. 8 9 Implements pow(), sqrt() and hypot() functions as specified by https://drafts.csswg.org/css-values-4/#exponent-funcs. 10 11 Test: fast/css/calc-parsing.html 12 13 * css/CSSValueKeywords.in: Adds pow, sqrt, and hypot keywords. 14 * css/calc/CSSCalcExpressionNodeParser.cpp: 15 (WebCore::CSSCalcExpressionNodeParser::parseCalcFunction): 16 * css/calc/CSSCalcOperationNode.cpp: 17 (WebCore::determineCategory): 18 (WebCore::functionFromOperator): 19 (WebCore::CSSCalcOperationNode::createPowOrSqrt): 20 (WebCore::CSSCalcOperationNode::createHypot): 21 (WebCore::CSSCalcOperationNode::canCombineAllChildren const): Ensures nodes that are identity functions cannot have their children combined. 22 (WebCore::CSSCalcOperationNode::combineChildren): Early exit if node behaves as an identity function. Performs combine of children if node is an exponential function. 23 (WebCore::CSSCalcOperationNode::simplifyNode): Avoid simplifying if node does not behave as an identify function. Calls combineChildren() if node is an exponential function. 24 (WebCore::functionPrefixForOperator): 25 (WebCore::CSSCalcOperationNode::evaluateOperator): 26 * css/calc/CSSCalcOperationNode.h: Adds isExponentialFunction() and isIdentity() methods. Exponential functions include hypot, sqrt, and pow. Identity functions are min and max when they contain one child. 27 * css/calc/CSSCalcValue.cpp: 28 (WebCore::createCSS): 29 (WebCore::CSSCalcValue::isCalcFunction): 30 * platform/calc/CalcExpressionOperation.cpp: 31 (WebCore::CalcExpressionOperation::evaluate const): 32 * platform/calc/CalcOperator.cpp: 33 (WebCore::operator<<): 34 * platform/calc/CalcOperator.h: 35 1 36 2021-09-30 Simon Fraser <simon.fraser@apple.com> 2 37 -
trunk/Source/WebCore/css/CSSValueKeywords.in
r283073 r283359 1348 1348 max 1349 1349 clamp 1350 pow 1351 sqrt 1352 hypot 1350 1353 sin 1351 1354 cos -
trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp
r283073 r283359 124 124 case CSSValueMin: 125 125 case CSSValueMax: 126 case CSSValueHypot: 126 127 maxArgumentCount = std::nullopt; 127 128 break; … … 157 158 maxArgumentCount = 2; 158 159 break; 159 // TODO: pow, sqrt, hypot. 160 case CSSValuePow: 161 minArgumentCount = 2; 162 maxArgumentCount = 2; 163 break; 164 case CSSValueSqrt: 165 maxArgumentCount = 1; 166 break; 160 167 default: 161 168 break; … … 242 249 result = CSSCalcOperationNode::createSign(CalcOperator::Sign, WTFMove(nodes)); 243 250 break; 244 // TODO: pow, sqrt, hypot 251 case CSSValuePow: 252 result = CSSCalcOperationNode::createPowOrSqrt(CalcOperator::Pow, WTFMove(nodes)); 253 break; 254 case CSSValueSqrt: 255 result = CSSCalcOperationNode::createPowOrSqrt(CalcOperator::Sqrt, WTFMove(nodes)); 256 break; 257 case CSSValueHypot: 258 result = CSSCalcOperationNode::createHypot(WTFMove(nodes)); 259 break; 245 260 default: 246 261 break; -
trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp
r283073 r283359 95 95 case CalcOperator::Nearest: 96 96 case CalcOperator::ToZero: 97 case CalcOperator::Pow: 98 case CalcOperator::Sqrt: 99 case CalcOperator::Hypot: 97 100 ASSERT_NOT_REACHED(); 98 101 return CalculationCategory::Other; … … 181 184 case CalcOperator::Nearest: 182 185 case CalcOperator::ToZero: 183 // The type of a min(), max(), or clamp() expression is the result of adding the types of its comma-separated calculations186 case CalcOperator::Hypot: 184 187 return CalculationCategory::Other; 188 case CalcOperator::Pow: 189 case CalcOperator::Sqrt: 190 // The type of pow() and sqrt() functions must evaluate to a number. 191 return CalculationCategory::Number; 185 192 } 186 193 } … … 276 283 return CSSCalcPrimitiveValueNode::UnitConversion::Invalid; 277 284 } 278 279 285 280 286 static CSSValueID functionFromOperator(CalcOperator op) … … 292 298 case CalcOperator::Clamp: 293 299 return CSSValueClamp; 300 case CalcOperator::Pow: 301 return CSSValuePow; 302 case CalcOperator::Sqrt: 303 return CSSValueSqrt; 304 case CalcOperator::Hypot: 305 return CSSValueHypot; 294 306 case CalcOperator::Sin: 295 307 return CSSValueSin; … … 332 344 } 333 345 346 static std::optional<CalculationCategory> commonCategory(const Vector<Ref<CSSCalcExpressionNode>>& values) 347 { 348 if (values.isEmpty()) 349 return std::nullopt; 350 351 auto expectedCategory = values[0]->category(); 352 for (size_t i = 1; i < values.size(); ++i) { 353 if (values[i]->category() != expectedCategory) 354 return std::nullopt; 355 } 356 357 return expectedCategory; 358 } 359 334 360 RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::create(CalcOperator op, RefPtr<CSSCalcExpressionNode>&& leftSide, RefPtr<CSSCalcExpressionNode>&& rightSide) 335 361 { … … 440 466 441 467 return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, CalcOperator::Exp, WTFMove(values))); 468 } 469 470 RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createPowOrSqrt(CalcOperator op, Vector<Ref<CSSCalcExpressionNode>>&& values) 471 { 472 if (op == CalcOperator::Pow && values.size() != 2) 473 return nullptr; 474 475 if (op == CalcOperator::Sqrt && values.size() != 1) 476 return nullptr; 477 478 if (commonCategory(values) != CalculationCategory::Number) { 479 LOG_WITH_STREAM(Calc, stream << "Failed to create " << op << "node because unable to determine category from " << prettyPrintNodes(values)); 480 return nullptr; 481 } 482 483 return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, op, WTFMove(values))); 484 } 485 486 RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createHypot(Vector<Ref<CSSCalcExpressionNode>>&& values) 487 { 488 auto expectedCategory = commonCategory(values); 489 490 if (expectedCategory == CalculationCategory::Other) { 491 LOG_WITH_STREAM(Calc, stream << "Failed to create hypot node because unable to determine category from " << prettyPrintNodes(values)); 492 return nullptr; 493 } 494 495 return adoptRef(new CSSCalcOperationNode(*expectedCategory, CalcOperator::Hypot, WTFMove(values))); 442 496 } 443 497 … … 598 652 bool CSSCalcOperationNode::canCombineAllChildren() const 599 653 { 600 if ( m_children.size() < 2)654 if (isIdentity() || !m_children.size()) 601 655 return false; 602 656 … … 631 685 void CSSCalcOperationNode::combineChildren() 632 686 { 687 if (isIdentity() || !m_children.size()) 688 return; 689 633 690 if (m_children.size() < 2) { 634 691 if (m_children.size() == 1 && isTrigNode()) { … … 645 702 m_children.append(WTFMove(newChild)); 646 703 } 647 648 704 if (m_children.size() == 1 && isInverseTrigNode()) { 649 705 double resolvedValue = doubleValue(m_children[0]->primitiveType()); … … 652 708 m_children.append(WTFMove(newChild)); 653 709 } 654 if (isSignNode() ) {710 if (isSignNode() || isHypotNode()) { 655 711 auto combinedUnitType = m_children[0]->primitiveType(); 656 712 if (calcOperator() == CalcOperator::Sign) … … 661 717 m_children.append(WTFMove(newChild)); 662 718 } 719 if (calcOperator() == CalcOperator::Sqrt) { 720 double resolvedValue = doubleValue(m_children[0]->primitiveType()); 721 auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, CSSUnitType::CSS_NUMBER)); 722 m_children.clear(); 723 m_children.append(WTFMove(newChild)); 724 } 663 725 return; 664 726 } 665 727 666 728 if (shouldSortChildren()) { 667 729 // <https://drafts.csswg.org/css-values-4/#sort-a-calculations-children> … … 782 844 } 783 845 784 if ( isMinOrMaxNode() && canCombineAllChildren()) {846 if ((isMinOrMaxNode() || isHypotNode()) && canCombineAllChildren()) { 785 847 auto combinedUnitType = m_children[0]->primitiveType(); 786 848 auto category = calculationCategoryForCombination(combinedUnitType); … … 794 856 m_children.append(WTFMove(newChild)); 795 857 } 796 858 859 if (calcOperator() == CalcOperator::Pow) { 860 auto resolvedValue = doubleValue(m_children[0]->primitiveType()); 861 auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, CSSUnitType::CSS_NUMBER)); 862 m_children.clear(); 863 m_children.append(WTFMove(newChild)); 864 } 865 797 866 if (calcOperator() == CalcOperator::Atan2) { 798 867 double resolvedValue = doubleValue(m_children[0]->primitiveType()); … … 872 941 if (is<CSSCalcOperationNode>(rootNode)) { 873 942 auto& calcOperationNode = downcast<CSSCalcOperationNode>(rootNode.get()); 874 // Simplify operations with only one child node (other than root and operations that only need one node).875 if (calcOperationNode. children().size() == 1 && depth && !calcOperationNode.isTrigNode() && !calcOperationNode.isExpNode() && !calcOperationNode.isInverseTrigNode() && !calcOperationNode.isSignNode())943 // Identity nodes have only one child and perform no operation on their child. 944 if (calcOperationNode.isIdentity() && depth) 876 945 return WTFMove(calcOperationNode.children()[0]); 877 946 … … 908 977 if (calcOperationNode.isRoundOperation() && depth) 909 978 calcOperationNode.combineChildren(); 979 980 if (calcOperationNode.isHypotNode()) 981 calcOperationNode.combineChildren(); 982 983 if (calcOperationNode.isPowOrSqrtNode() && depth) 984 calcOperationNode.combineChildren(); 985 910 986 // If only one child remains, return the child (except at the root). 911 987 auto shouldCombineParentWithOnlyChild = [](const CSSCalcOperationNode& parent, int depth) … … 1120 1196 case CalcOperator::Nearest: return "round(nearest, "; 1121 1197 case CalcOperator::ToZero: return "round(to-zero, "; 1198 case CalcOperator::Pow: return "pow("; 1199 case CalcOperator::Sqrt: return "sqrt("; 1200 case CalcOperator::Hypot: return "hypot("; 1122 1201 } 1123 1202 … … 1328 1407 return std::max(min, std::min(value, max)); 1329 1408 } 1409 case CalcOperator::Pow: 1410 if (children.size() != 2) 1411 return std::numeric_limits<double>::quiet_NaN(); 1412 return std::pow(children[0], children[1]); 1413 case CalcOperator::Sqrt: { 1414 if (children.size() != 1) 1415 return std::numeric_limits<double>::quiet_NaN(); 1416 return std::sqrt(children[0]); 1417 } 1418 case CalcOperator::Hypot: { 1419 if (children.isEmpty()) 1420 return std::numeric_limits<double>::quiet_NaN(); 1421 if (children.size() == 1) 1422 return std::abs(children[0]); 1423 double sum = 0; 1424 for (auto child : children) 1425 sum += (child * child); 1426 return std::sqrt(sum); 1427 } 1330 1428 case CalcOperator::Sin: { 1331 1429 if (children.size() != 1) -
trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h
r283073 r283359 38 38 static RefPtr<CSSCalcOperationNode> createProduct(Vector<Ref<CSSCalcExpressionNode>>&& values); 39 39 static RefPtr<CSSCalcOperationNode> createMinOrMaxOrClamp(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values, CalculationCategory destinationCategory); 40 static RefPtr<CSSCalcOperationNode> createPowOrSqrt(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values); 41 static RefPtr<CSSCalcOperationNode> createHypot(Vector<Ref<CSSCalcExpressionNode>>&& values); 40 42 static RefPtr<CSSCalcOperationNode> createTrig(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values); 41 43 static RefPtr<CSSCalcOperationNode> createLog(Vector<Ref<CSSCalcExpressionNode>>&& values); … … 64 66 bool isRoundOperation() const { return m_operator == CalcOperator::Down || m_operator == CalcOperator::Up || m_operator == CalcOperator::ToZero || m_operator == CalcOperator::Nearest; } 65 67 bool isRoundConstant() const { return (isRoundOperation()) && !m_children.size(); } 68 bool isHypotNode() const { return m_operator == CalcOperator::Hypot; } 69 bool isPowOrSqrtNode() const { return m_operator == CalcOperator::Pow || m_operator == CalcOperator::Sqrt; } 66 70 67 71 void hoistChildrenWithOperator(CalcOperator); … … 69 73 70 74 bool canCombineAllChildren() const; 75 76 bool isIdentity() const { return m_children.size() == 1 && (m_operator == CalcOperator::Min || m_operator == CalcOperator::Max || m_operator == CalcOperator::Add || m_operator == CalcOperator::Multiply); } 71 77 72 78 const Vector<Ref<CSSCalcExpressionNode>>& children() const { return m_children; } -
trunk/Source/WebCore/css/calc/CSSCalcValue.cpp
r283073 r283359 214 214 return CSSCalcOperationNode::createSign(op, WTFMove(children)); 215 215 } 216 case CalcOperator::Sqrt: 217 case CalcOperator::Pow: { 218 auto children = createCSS(operationChildren, style); 219 if (children.isEmpty()) 220 return nullptr; 221 return CSSCalcOperationNode::createPowOrSqrt(op, WTFMove(children)); 222 } 223 case CalcOperator::Hypot: { 224 auto children = createCSS(operationChildren, style); 225 if (children.isEmpty()) 226 return nullptr; 227 return CSSCalcOperationNode::createHypot(WTFMove(children)); 228 } 216 229 case CalcOperator::Mod: 217 230 case CalcOperator::Rem: … … 339 352 case CSSValueMax: 340 353 case CSSValueClamp: 354 case CSSValuePow: 355 case CSSValueSqrt: 356 case CSSValueHypot: 341 357 case CSSValueSin: 342 358 case CSSValueCos: -
trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp
r283073 r283359 96 96 return std::max(min, std::min(value, max)); 97 97 } 98 case CalcOperator::Pow: { 99 if (m_children.size() != 2) 100 return std::numeric_limits<float>::quiet_NaN(); 101 float base = m_children[0]->evaluate(maxValue); 102 float power = m_children[1]->evaluate(maxValue); 103 return std::pow(base, power); 104 } 105 case CalcOperator::Sqrt: { 106 if (m_children.size() != 1) 107 return std::numeric_limits<float>::quiet_NaN(); 108 return std::sqrt(m_children[0]->evaluate(maxValue)); 109 } 110 case CalcOperator::Hypot: { 111 if (m_children.isEmpty()) 112 return std::numeric_limits<float>::quiet_NaN(); 113 if (m_children.size() == 1) 114 return std::abs(m_children[0]->evaluate(maxValue)); 115 float sum = 0; 116 for (auto& child : m_children) { 117 float value = child->evaluate(maxValue); 118 sum += (value * value); 119 } 120 return sum; 121 } 98 122 case CalcOperator::Sin: { 99 123 if (m_children.size() != 1) -
trunk/Source/WebCore/platform/calc/CalcOperator.cpp
r283073 r283359 41 41 case CalcOperator::Max: ts << "max"; break; 42 42 case CalcOperator::Clamp: ts << "clamp"; break; 43 case CalcOperator::Pow: ts << "pow"; break; 44 case CalcOperator::Sqrt: ts << "sqrt"; break; 45 case CalcOperator::Hypot: ts << "hypot"; break; 43 46 case CalcOperator::Sin: ts << "sin"; break; 44 47 case CalcOperator::Cos: ts << "cos"; break; -
trunk/Source/WebCore/platform/calc/CalcOperator.h
r283073 r283359 39 39 Max, 40 40 Clamp, 41 Pow, 42 Sqrt, 43 Hypot, 41 44 Sin, 42 45 Cos,
Note:
See TracChangeset
for help on using the changeset viewer.