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 |