static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> create(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther); CalculationCategory newCategory = determineCategory(*leftSide, *rightSide, op); if (newCategory == CalcOther) return nullptr; return adoptRefWillBeNoop(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory)); }
static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createSimplified(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { CalculationCategory leftCategory = leftSide->category(); CalculationCategory rightCategory = rightSide->category(); ASSERT(leftCategory != CalcOther && rightCategory != CalcOther); bool isInteger = isIntegerResult(leftSide.get(), rightSide.get(), op); // Simplify numbers. if (leftCategory == CalcNumber && rightCategory == CalcNumber) { return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), CSSPrimitiveValue::UnitType::Number, isInteger); } // Simplify addition and subtraction between same types. if (op == CalcAdd || op == CalcSubtract) { if (leftCategory == rightSide->category()) { CSSPrimitiveValue::UnitType leftType = leftSide->typeWithCalcResolved(); if (hasDoubleValue(leftType)) { CSSPrimitiveValue::UnitType rightType = rightSide->typeWithCalcResolved(); if (leftType == rightType) return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger); CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimitiveValue::unitCategory(leftType); if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUnitCategory == CSSPrimitiveValue::unitCategory(rightType)) { CSSPrimitiveValue::UnitType canonicalType = CSSPrimitiveValue::canonicalUnitTypeForCategory(leftUnitCategory); if (canonicalType != CSSPrimitiveValue::UnitType::Unknown) { double leftValue = leftSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(leftType); double rightValue = rightSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(rightType); return CSSCalcPrimitiveValue::create(evaluateOperator(leftValue, rightValue, op), canonicalType, isInteger); } } } } } else { // Simplify multiplying or dividing by a number for simplifiable types. ASSERT(op == CalcMultiply || op == CalcDivide); CSSCalcExpressionNode* numberSide = getNumberSide(leftSide.get(), rightSide.get()); if (!numberSide) return create(leftSide, rightSide, op); if (numberSide == leftSide && op == CalcDivide) return nullptr; CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSide.get() : leftSide.get(); double number = numberSide->doubleValue(); if (std::isnan(number) || std::isinf(number)) return nullptr; if (op == CalcDivide && !number) return nullptr; CSSPrimitiveValue::UnitType otherType = otherSide->typeWithCalcResolved(); if (hasDoubleValue(otherType)) return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide->doubleValue(), number, op), otherType, isInteger); } return create(leftSide, rightSide, op); }