| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 } | 166 } |
| 167 | 167 |
| 168 double CSSCalcValue::computeLengthPx(const CSSToLengthConversionData& conversion
Data) const | 168 double CSSCalcValue::computeLengthPx(const CSSToLengthConversionData& conversion
Data) const |
| 169 { | 169 { |
| 170 return clampToPermittedRange(m_expression->computeLengthPx(conversionData)); | 170 return clampToPermittedRange(m_expression->computeLengthPx(conversionData)); |
| 171 } | 171 } |
| 172 | 172 |
| 173 class CSSCalcPrimitiveValue final : public CSSCalcExpressionNode { | 173 class CSSCalcPrimitiveValue final : public CSSCalcExpressionNode { |
| 174 public: | 174 public: |
| 175 | 175 |
| 176 static RawPtr<CSSCalcPrimitiveValue> create(RawPtr<CSSPrimitiveValue> value,
bool isInteger) | 176 static CSSCalcPrimitiveValue* create(CSSPrimitiveValue* value, bool isIntege
r) |
| 177 { | 177 { |
| 178 return new CSSCalcPrimitiveValue(value, isInteger); | 178 return new CSSCalcPrimitiveValue(value, isInteger); |
| 179 } | 179 } |
| 180 | 180 |
| 181 static RawPtr<CSSCalcPrimitiveValue> create(double value, CSSPrimitiveValue:
:UnitType type, bool isInteger) | 181 static CSSCalcPrimitiveValue* create(double value, CSSPrimitiveValue::UnitTy
pe type, bool isInteger) |
| 182 { | 182 { |
| 183 if (std::isnan(value) || std::isinf(value)) | 183 if (std::isnan(value) || std::isinf(value)) |
| 184 return nullptr; | 184 return nullptr; |
| 185 return new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type).
get(), isInteger); | 185 return new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type),
isInteger); |
| 186 } | 186 } |
| 187 | 187 |
| 188 bool isZero() const override | 188 bool isZero() const override |
| 189 { | 189 { |
| 190 return !m_value->getDoubleValue(); | 190 return !m_value->getDoubleValue(); |
| 191 } | 191 } |
| 192 | 192 |
| 193 String customCSSText() const override | 193 String customCSSText() const override |
| 194 { | 194 { |
| 195 return m_value->cssText(); | 195 return m_value->cssText(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } | 260 } |
| 261 | 261 |
| 262 | 262 |
| 263 DEFINE_INLINE_VIRTUAL_TRACE() | 263 DEFINE_INLINE_VIRTUAL_TRACE() |
| 264 { | 264 { |
| 265 visitor->trace(m_value); | 265 visitor->trace(m_value); |
| 266 CSSCalcExpressionNode::trace(visitor); | 266 CSSCalcExpressionNode::trace(visitor); |
| 267 } | 267 } |
| 268 | 268 |
| 269 private: | 269 private: |
| 270 CSSCalcPrimitiveValue(RawPtr<CSSPrimitiveValue> value, bool isInteger) | 270 CSSCalcPrimitiveValue(CSSPrimitiveValue* value, bool isInteger) |
| 271 : CSSCalcExpressionNode(unitCategory(value->typeWithCalcResolved()), isI
nteger) | 271 : CSSCalcExpressionNode(unitCategory(value->typeWithCalcResolved()), isI
nteger) |
| 272 , m_value(value) | 272 , m_value(value) |
| 273 { | 273 { |
| 274 } | 274 } |
| 275 | 275 |
| 276 Member<CSSPrimitiveValue> m_value; | 276 Member<CSSPrimitiveValue> m_value; |
| 277 }; | 277 }; |
| 278 | 278 |
| 279 static const CalculationCategory addSubtractResult[CalcOther][CalcOther] = { | 279 static const CalculationCategory addSubtractResult[CalcOther][CalcOther] = { |
| 280 // CalcNumber CalcLength CalcPercent
CalcPercentNumber CalcPercentLength CalcAngle CalcTime CalcFrequency | 280 // CalcNumber CalcLength CalcPercent
CalcPercentNumber CalcPercentLength CalcAngle CalcTime CalcFrequency |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 static bool isIntegerResult(const CSSCalcExpressionNode* leftSide, const CSSCalc
ExpressionNode* rightSide, CalcOperator op) | 317 static bool isIntegerResult(const CSSCalcExpressionNode* leftSide, const CSSCalc
ExpressionNode* rightSide, CalcOperator op) |
| 318 { | 318 { |
| 319 // Not testing for actual integer values. | 319 // Not testing for actual integer values. |
| 320 // Performs W3C spec's type checking for calc integers. | 320 // Performs W3C spec's type checking for calc integers. |
| 321 // http://www.w3.org/TR/css3-values/#calc-type-checking | 321 // http://www.w3.org/TR/css3-values/#calc-type-checking |
| 322 return op != CalcDivide && leftSide->isInteger() && rightSide->isInteger(); | 322 return op != CalcDivide && leftSide->isInteger() && rightSide->isInteger(); |
| 323 } | 323 } |
| 324 | 324 |
| 325 class CSSCalcBinaryOperation final : public CSSCalcExpressionNode { | 325 class CSSCalcBinaryOperation final : public CSSCalcExpressionNode { |
| 326 public: | 326 public: |
| 327 static RawPtr<CSSCalcExpressionNode> create(RawPtr<CSSCalcExpressionNode> le
ftSide, RawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) | 327 static CSSCalcExpressionNode* create(CSSCalcExpressionNode* leftSide, CSSCal
cExpressionNode* rightSide, CalcOperator op) |
| 328 { | 328 { |
| 329 ASSERT(leftSide->category() != CalcOther && rightSide->category() != Cal
cOther); | 329 ASSERT(leftSide->category() != CalcOther && rightSide->category() != Cal
cOther); |
| 330 | 330 |
| 331 CalculationCategory newCategory = determineCategory(*leftSide, *rightSid
e, op); | 331 CalculationCategory newCategory = determineCategory(*leftSide, *rightSid
e, op); |
| 332 if (newCategory == CalcOther) | 332 if (newCategory == CalcOther) |
| 333 return nullptr; | 333 return nullptr; |
| 334 | 334 |
| 335 return new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory); | 335 return new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory); |
| 336 } | 336 } |
| 337 | 337 |
| 338 static RawPtr<CSSCalcExpressionNode> createSimplified(RawPtr<CSSCalcExpressi
onNode> leftSide, RawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) | 338 static CSSCalcExpressionNode* createSimplified(CSSCalcExpressionNode* leftSi
de, CSSCalcExpressionNode* rightSide, CalcOperator op) |
| 339 { | 339 { |
| 340 CalculationCategory leftCategory = leftSide->category(); | 340 CalculationCategory leftCategory = leftSide->category(); |
| 341 CalculationCategory rightCategory = rightSide->category(); | 341 CalculationCategory rightCategory = rightSide->category(); |
| 342 ASSERT(leftCategory != CalcOther && rightCategory != CalcOther); | 342 ASSERT(leftCategory != CalcOther && rightCategory != CalcOther); |
| 343 | 343 |
| 344 bool isInteger = isIntegerResult(leftSide.get(), rightSide.get(), op); | 344 bool isInteger = isIntegerResult(leftSide, rightSide, op); |
| 345 | 345 |
| 346 // Simplify numbers. | 346 // Simplify numbers. |
| 347 if (leftCategory == CalcNumber && rightCategory == CalcNumber) { | 347 if (leftCategory == CalcNumber && rightCategory == CalcNumber) { |
| 348 return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doub
leValue(), rightSide->doubleValue(), op), CSSPrimitiveValue::UnitType::Number, i
sInteger); | 348 return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doub
leValue(), rightSide->doubleValue(), op), CSSPrimitiveValue::UnitType::Number, i
sInteger); |
| 349 } | 349 } |
| 350 | 350 |
| 351 // Simplify addition and subtraction between same types. | 351 // Simplify addition and subtraction between same types. |
| 352 if (op == CalcAdd || op == CalcSubtract) { | 352 if (op == CalcAdd || op == CalcSubtract) { |
| 353 if (leftCategory == rightSide->category()) { | 353 if (leftCategory == rightSide->category()) { |
| 354 CSSPrimitiveValue::UnitType leftType = leftSide->typeWithCalcRes
olved(); | 354 CSSPrimitiveValue::UnitType leftType = leftSide->typeWithCalcRes
olved(); |
| 355 if (hasDoubleValue(leftType)) { | 355 if (hasDoubleValue(leftType)) { |
| 356 CSSPrimitiveValue::UnitType rightType = rightSide->typeWithC
alcResolved(); | 356 CSSPrimitiveValue::UnitType rightType = rightSide->typeWithC
alcResolved(); |
| 357 if (leftType == rightType) | 357 if (leftType == rightType) |
| 358 return CSSCalcPrimitiveValue::create(evaluateOperator(le
ftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger); | 358 return CSSCalcPrimitiveValue::create(evaluateOperator(le
ftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger); |
| 359 CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimit
iveValue::unitTypeToUnitCategory(leftType); | 359 CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimit
iveValue::unitTypeToUnitCategory(leftType); |
| 360 if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUni
tCategory == CSSPrimitiveValue::unitTypeToUnitCategory(rightType)) { | 360 if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUni
tCategory == CSSPrimitiveValue::unitTypeToUnitCategory(rightType)) { |
| 361 CSSPrimitiveValue::UnitType canonicalType = CSSPrimitive
Value::canonicalUnitTypeForCategory(leftUnitCategory); | 361 CSSPrimitiveValue::UnitType canonicalType = CSSPrimitive
Value::canonicalUnitTypeForCategory(leftUnitCategory); |
| 362 if (canonicalType != CSSPrimitiveValue::UnitType::Unknow
n) { | 362 if (canonicalType != CSSPrimitiveValue::UnitType::Unknow
n) { |
| 363 double leftValue = leftSide->doubleValue() * CSSPrim
itiveValue::conversionToCanonicalUnitsScaleFactor(leftType); | 363 double leftValue = leftSide->doubleValue() * CSSPrim
itiveValue::conversionToCanonicalUnitsScaleFactor(leftType); |
| 364 double rightValue = rightSide->doubleValue() * CSSPr
imitiveValue::conversionToCanonicalUnitsScaleFactor(rightType); | 364 double rightValue = rightSide->doubleValue() * CSSPr
imitiveValue::conversionToCanonicalUnitsScaleFactor(rightType); |
| 365 return CSSCalcPrimitiveValue::create(evaluateOperato
r(leftValue, rightValue, op), canonicalType, isInteger); | 365 return CSSCalcPrimitiveValue::create(evaluateOperato
r(leftValue, rightValue, op), canonicalType, isInteger); |
| 366 } | 366 } |
| 367 } | 367 } |
| 368 } | 368 } |
| 369 } | 369 } |
| 370 } else { | 370 } else { |
| 371 // Simplify multiplying or dividing by a number for simplifiable typ
es. | 371 // Simplify multiplying or dividing by a number for simplifiable typ
es. |
| 372 ASSERT(op == CalcMultiply || op == CalcDivide); | 372 ASSERT(op == CalcMultiply || op == CalcDivide); |
| 373 CSSCalcExpressionNode* numberSide = getNumberSide(leftSide.get(), ri
ghtSide.get()); | 373 CSSCalcExpressionNode* numberSide = getNumberSide(leftSide, rightSid
e); |
| 374 if (!numberSide) | 374 if (!numberSide) |
| 375 return create(leftSide, rightSide, op); | 375 return create(leftSide, rightSide, op); |
| 376 if (numberSide == leftSide && op == CalcDivide) | 376 if (numberSide == leftSide && op == CalcDivide) |
| 377 return nullptr; | 377 return nullptr; |
| 378 CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSid
e.get() : leftSide.get(); | 378 CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSid
e : leftSide; |
| 379 | 379 |
| 380 double number = numberSide->doubleValue(); | 380 double number = numberSide->doubleValue(); |
| 381 if (std::isnan(number) || std::isinf(number)) | 381 if (std::isnan(number) || std::isinf(number)) |
| 382 return nullptr; | 382 return nullptr; |
| 383 if (op == CalcDivide && !number) | 383 if (op == CalcDivide && !number) |
| 384 return nullptr; | 384 return nullptr; |
| 385 | 385 |
| 386 CSSPrimitiveValue::UnitType otherType = otherSide->typeWithCalcResol
ved(); | 386 CSSPrimitiveValue::UnitType otherType = otherSide->typeWithCalcResol
ved(); |
| 387 if (hasDoubleValue(otherType)) | 387 if (hasDoubleValue(otherType)) |
| 388 return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide-
>doubleValue(), number, op), otherType, isInteger); | 388 return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide-
>doubleValue(), number, op), otherType, isInteger); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 } | 527 } |
| 528 | 528 |
| 529 DEFINE_INLINE_VIRTUAL_TRACE() | 529 DEFINE_INLINE_VIRTUAL_TRACE() |
| 530 { | 530 { |
| 531 visitor->trace(m_leftSide); | 531 visitor->trace(m_leftSide); |
| 532 visitor->trace(m_rightSide); | 532 visitor->trace(m_rightSide); |
| 533 CSSCalcExpressionNode::trace(visitor); | 533 CSSCalcExpressionNode::trace(visitor); |
| 534 } | 534 } |
| 535 | 535 |
| 536 private: | 536 private: |
| 537 CSSCalcBinaryOperation(RawPtr<CSSCalcExpressionNode> leftSide, RawPtr<CSSCal
cExpressionNode> rightSide, CalcOperator op, CalculationCategory category) | 537 CSSCalcBinaryOperation(CSSCalcExpressionNode* leftSide, CSSCalcExpressionNod
e* rightSide, CalcOperator op, CalculationCategory category) |
| 538 : CSSCalcExpressionNode(category, isIntegerResult(leftSide.get(), rightS
ide.get(), op)) | 538 : CSSCalcExpressionNode(category, isIntegerResult(leftSide, rightSide, o
p)) |
| 539 , m_leftSide(leftSide) | 539 , m_leftSide(leftSide) |
| 540 , m_rightSide(rightSide) | 540 , m_rightSide(rightSide) |
| 541 , m_operator(op) | 541 , m_operator(op) |
| 542 { | 542 { |
| 543 } | 543 } |
| 544 | 544 |
| 545 static CSSCalcExpressionNode* getNumberSide(CSSCalcExpressionNode* leftSide,
CSSCalcExpressionNode* rightSide) | 545 static CSSCalcExpressionNode* getNumberSide(CSSCalcExpressionNode* leftSide,
CSSCalcExpressionNode* rightSide) |
| 546 { | 546 { |
| 547 if (leftSide->category() == CalcNumber) | 547 if (leftSide->category() == CalcNumber) |
| 548 return leftSide; | 548 return leftSide; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 if (tokens.atEnd()) | 584 if (tokens.atEnd()) |
| 585 return NoMoreTokens; | 585 return NoMoreTokens; |
| 586 if (*depth > maxExpressionDepth) | 586 if (*depth > maxExpressionDepth) |
| 587 return TooDeep; | 587 return TooDeep; |
| 588 return OK; | 588 return OK; |
| 589 } | 589 } |
| 590 | 590 |
| 591 class CSSCalcExpressionNodeParser { | 591 class CSSCalcExpressionNodeParser { |
| 592 STACK_ALLOCATED(); | 592 STACK_ALLOCATED(); |
| 593 public: | 593 public: |
| 594 RawPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange tokens) | 594 CSSCalcExpressionNode* parseCalc(CSSParserTokenRange tokens) |
| 595 { | 595 { |
| 596 Value result; | 596 Value result; |
| 597 tokens.consumeWhitespace(); | 597 tokens.consumeWhitespace(); |
| 598 bool ok = parseValueExpression(tokens, 0, &result); | 598 bool ok = parseValueExpression(tokens, 0, &result); |
| 599 if (!ok || !tokens.atEnd()) | 599 if (!ok || !tokens.atEnd()) |
| 600 return nullptr; | 600 return nullptr; |
| 601 return result.value; | 601 return result.value; |
| 602 } | 602 } |
| 603 | 603 |
| 604 private: | 604 private: |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 | 702 |
| 703 return true; | 703 return true; |
| 704 } | 704 } |
| 705 | 705 |
| 706 bool parseValueExpression(CSSParserTokenRange& tokens, int depth, Value* res
ult) | 706 bool parseValueExpression(CSSParserTokenRange& tokens, int depth, Value* res
ult) |
| 707 { | 707 { |
| 708 return parseAdditiveValueExpression(tokens, depth, result); | 708 return parseAdditiveValueExpression(tokens, depth, result); |
| 709 } | 709 } |
| 710 }; | 710 }; |
| 711 | 711 |
| 712 RawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(RawPtr<CSSPrimi
tiveValue> value, bool isInteger) | 712 CSSCalcExpressionNode* CSSCalcValue::createExpressionNode(CSSPrimitiveValue* val
ue, bool isInteger) |
| 713 { | 713 { |
| 714 return CSSCalcPrimitiveValue::create(value, isInteger); | 714 return CSSCalcPrimitiveValue::create(value, isInteger); |
| 715 } | 715 } |
| 716 | 716 |
| 717 RawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(RawPtr<CSSCalcE
xpressionNode> leftSide, RawPtr<CSSCalcExpressionNode> rightSide, CalcOperator o
p) | 717 CSSCalcExpressionNode* CSSCalcValue::createExpressionNode(CSSCalcExpressionNode*
leftSide, CSSCalcExpressionNode* rightSide, CalcOperator op) |
| 718 { | 718 { |
| 719 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); | 719 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); |
| 720 } | 720 } |
| 721 | 721 |
| 722 RawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(double pixels,
double percent) | 722 CSSCalcExpressionNode* CSSCalcValue::createExpressionNode(double pixels, double
percent) |
| 723 { | 723 { |
| 724 return createExpressionNode( | 724 return createExpressionNode( |
| 725 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue
::UnitType::Pixels), pixels == trunc(pixels)), | 725 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue
::UnitType::Pixels), pixels == trunc(pixels)), |
| 726 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu
e::UnitType::Percentage), percent == trunc(percent)), | 726 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu
e::UnitType::Percentage), percent == trunc(percent)), |
| 727 CalcAdd); | 727 CalcAdd); |
| 728 } | 728 } |
| 729 | 729 |
| 730 RawPtr<CSSCalcValue> CSSCalcValue::create(const CSSParserTokenRange& tokens, Val
ueRange range) | 730 CSSCalcValue* CSSCalcValue::create(const CSSParserTokenRange& tokens, ValueRange
range) |
| 731 { | 731 { |
| 732 CSSCalcExpressionNodeParser parser; | 732 CSSCalcExpressionNodeParser parser; |
| 733 RawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(tokens); | 733 CSSCalcExpressionNode* expression = parser.parseCalc(tokens); |
| 734 | 734 |
| 735 return expression ? new CSSCalcValue(expression, range) : nullptr; | 735 return expression ? new CSSCalcValue(expression, range) : nullptr; |
| 736 } | 736 } |
| 737 | 737 |
| 738 RawPtr<CSSCalcValue> CSSCalcValue::create(RawPtr<CSSCalcExpressionNode> expressi
on, ValueRange range) | 738 CSSCalcValue* CSSCalcValue::create(CSSCalcExpressionNode* expression, ValueRange
range) |
| 739 { | 739 { |
| 740 return new CSSCalcValue(expression, range); | 740 return new CSSCalcValue(expression, range); |
| 741 } | 741 } |
| 742 | 742 |
| 743 } // namespace blink | 743 } // namespace blink |
| OLD | NEW |