summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhmuller@adobe.com <hmuller@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>2013-09-27 23:17:34 +0000
committerKonstantin Tokarev <annulen@yandex.ru>2016-09-27 07:16:46 +0000
commit7cdd855e3287492093749a833b8b56c67e8db800 (patch)
tree44dba000af3df4eb85751e1f0acca62d358a0b4c
parent3bb3f4e49fec10dfe1bd58e3466384317d71ffbe (diff)
downloadqtwebkit-7cdd855e3287492093749a833b8b56c67e8db800.tar.gz
Crash on shape-outside when using calc()
https://bugs.webkit.org/show_bug.cgi?id=121020 Reviewed by Dirk Schulze. Source/WebCore: This change prevents a crash caused by specifying a CSS Shape geometry Length attribute with a calc() expression. It adds support for converting Lengths to CSSPrimitive Values, in large part by migrating Blink changes made to the calc classes since the split. Doing so required a few supporting changes in some related classes, notably CSSPrimitiveValue. Tests: fast/shapes/shape-inside/shape-inside-calc-crash.html css3/calc/simplification.html * css/BasicShapeFunctions.cpp: (WebCore::convertToCSSPrimitiveValue): Effectively use the new CSSPrimtiveValue(length,style) constructor to convert Lengths to CSSValues. (WebCore::valueForBasicShape): Use the convertToCSSPrimitiveValue() function. (WebCore::convertToLength): Added the CalculatedConversion convertToLength() flag to enable support for calc() valued Length Shape attributes. * css/BasicShapeFunctions.h: * css/CSSCalculationValue.cpp: (WebCore::hasDoubleValue): (WebCore::buildCssText): (WebCore::CSSCalcValue::clampToPermittedRange): (WebCore::CSSCalcValue::doubleValue): (WebCore::CSSCalcExpressionNode::~CSSCalcExpressionNode): (WebCore::CSSCalcPrimitiveValue::create): (WebCore::CSSCalcPrimitiveValue::toCalcValue): (WebCore::CSSCalcPrimitiveValue::doubleValue): (WebCore::CSSCalcPrimitiveValue::computeLengthPx): (WebCore::CSSCalcPrimitiveValue::primitiveType): (WebCore::CSSCalcPrimitiveValue::CSSCalcPrimitiveValue): (WebCore::determineCategory): (WebCore::isIntegerResult): (WebCore::CSSCalcBinaryOperation::create): (WebCore::CSSCalcBinaryOperation::createSimplified): (WebCore::CSSCalcBinaryOperation::doubleValue): (WebCore::CSSCalcBinaryOperation::buildCssText): (WebCore::CSSCalcBinaryOperation::primitiveType): (WebCore::CSSCalcBinaryOperation::CSSCalcBinaryOperation): (WebCore::CSSCalcBinaryOperation::getNumberSide): (WebCore::CSSCalcBinaryOperation::evaluate): (WebCore::CSSCalcBinaryOperation::evaluateOperator): (WebCore::CSSCalcExpressionNodeParser::parseValue): (WebCore::CSSCalcExpressionNodeParser::parseValueTerm): (WebCore::CSSCalcExpressionNodeParser::parseValueMultiplicativeExpression): (WebCore::CSSCalcExpressionNodeParser::parseAdditiveValueExpression): (WebCore::CSSCalcValue::createExpressionNode): (WebCore::CSSCalcValue::create): * css/CSSCalculationValue.h: (WebCore::CSSCalcExpressionNode::category): (WebCore::CSSCalcValue::create): (WebCore::CSSCalcValue::isInt): (WebCore::CSSCalcValue::permittedValueRange): (WebCore::CSSCalcValue::expressionNode): (WebCore::CSSCalcValue::CSSCalcValue): (WebCore::toCSSCalcValue): * css/CSSComputedStyleDeclaration.cpp: (WebCore::ComputedStyleExtractor::propertyValue): Pass the style along to the new valueForBasicShape() function. * css/CSSPrimitiveValue.cpp: (WebCore::CSSPrimitiveValue::unitCategory): Made this function public so that CSSCalculationValue could use it. (WebCore::CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor): Ditto. (WebCore::CSSPrimitiveValue::primitiveType): Cleared trailing whitespace. (WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Construct a CSSPrimitiveValue from a Length and a RenderStyle*. (WebCore::CSSPrimitiveValue::init): The common part of the two Length CSSPrimitiveValue constructors. (WebCore::CSSPrimitiveValue::computeLengthDouble): Moved the case labels to the left per check-webkit-style. (WebCore::CSSPrimitiveValue::getStringValue): Ditto. (WebCore::CSSPrimitiveValue::getDoubleValue): Removed trailing whitespace. * css/CSSPrimitiveValue.h: (WebCore::CSSPrimitiveValue::create): Construct a CSSPrimitiveValue from a Length and a RenderStyle*. (WebCore::toCSSPrimitiveValue): Check the CSSValue*'s validity with ASSERT_WITH_SECURITY_IMPLICATION before casting to CSSPrimitiveValue*. * css/CSSValuePool.h: (WebCore::CSSValuePool::createValue): A new overload that delegates to the new CSSPrimitiveValue(length,style) constructor. * platform/CalculationValue.h: (WebCore::CalculationValue::operator==): (WebCore::CalculationValue::isNonNegative): (WebCore::CalculationValue::expression): (WebCore::CalcExpressionNumber::value): (WebCore::toCalcExpressionNumber): (WebCore::CalcExpressionLength::CalcExpressionLength): (WebCore::CalcExpressionLength::length): (WebCore::toCalcExpressionLength): (WebCore::CalcExpressionBinaryOperation::leftSide): (WebCore::CalcExpressionBinaryOperation::rightSide): (WebCore::CalcExpressionBinaryOperation::getOperator): (WebCore::toCalcExpressionBinaryOperation): (WebCore::CalcExpressionBlendLength::CalcExpressionBlendLength): (WebCore::CalcExpressionBlendLength::from): (WebCore::CalcExpressionBlendLength::to): (WebCore::CalcExpressionBlendLength::progress): (WebCore::toCalcExpressionBlendLength): LayoutTests: Specifying a CSS Shape geometry Length attribute with a calc() expression or looking up the value with getComputedStyle(), caused crashes. * fast/shapes/shape-inside/shape-inside-calc-crash-expected.txt: Added. * fast/shapes/shape-inside/shape-inside-calc-crash.html: Added. * css3/calc/simplification-expected.txt: Added * css3/calc/simplification.html: Added * LayoutTests/css3/calc/cssom-expected.txt: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156586 268f45cc-cd09-0410-ab3c-d52691b4dbfc Change-Id: I38216be400bd7024999444d9c1c7e5ad79cce2de Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--Source/WebCore/css/BasicShapeFunctions.cpp44
-rw-r--r--Source/WebCore/css/BasicShapeFunctions.h2
-rw-r--r--Source/WebCore/css/CSSCalculationValue.cpp390
-rw-r--r--Source/WebCore/css/CSSCalculationValue.h58
-rw-r--r--Source/WebCore/css/CSSComputedStyleDeclaration.cpp6
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.cpp467
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.h27
-rw-r--r--Source/WebCore/css/CSSValuePool.h3
-rw-r--r--Source/WebCore/platform/CalculationValue.h98
9 files changed, 741 insertions, 354 deletions
diff --git a/Source/WebCore/css/BasicShapeFunctions.cpp b/Source/WebCore/css/BasicShapeFunctions.cpp
index c5885095e..a99739a78 100644
--- a/Source/WebCore/css/BasicShapeFunctions.cpp
+++ b/Source/WebCore/css/BasicShapeFunctions.cpp
@@ -38,7 +38,7 @@
namespace WebCore {
-PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
+PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle* style, const BasicShape* basicShape)
{
RefPtr<CSSBasicShape> basicShapeValue;
switch (basicShape->type()) {
@@ -46,12 +46,12 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create();
- rectangleValue->setX(cssValuePool().createValue(rectangle->x()));
- rectangleValue->setY(cssValuePool().createValue(rectangle->y()));
- rectangleValue->setWidth(cssValuePool().createValue(rectangle->width()));
- rectangleValue->setHeight(cssValuePool().createValue(rectangle->height()));
- rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX()));
- rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY()));
+ rectangleValue->setX(cssValuePool().createValue(rectangle->x(), style));
+ rectangleValue->setY(cssValuePool().createValue(rectangle->y(), style));
+ rectangleValue->setWidth(cssValuePool().createValue(rectangle->width(), style));
+ rectangleValue->setHeight(cssValuePool().createValue(rectangle->height(), style));
+ rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX(), style));
+ rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY(), style));
basicShapeValue = rectangleValue.release();
break;
@@ -60,9 +60,9 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create();
- circleValue->setCenterX(cssValuePool().createValue(circle->centerX()));
- circleValue->setCenterY(cssValuePool().createValue(circle->centerY()));
- circleValue->setRadius(cssValuePool().createValue(circle->radius()));
+ circleValue->setCenterX(cssValuePool().createValue(circle->centerX(), style));
+ circleValue->setCenterY(cssValuePool().createValue(circle->centerY(), style));
+ circleValue->setRadius(cssValuePool().createValue(circle->radius(), style));
basicShapeValue = circleValue.release();
break;
@@ -71,10 +71,10 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create();
- ellipseValue->setCenterX(cssValuePool().createValue(ellipse->centerX()));
- ellipseValue->setCenterY(cssValuePool().createValue(ellipse->centerY()));
- ellipseValue->setRadiusX(cssValuePool().createValue(ellipse->radiusX()));
- ellipseValue->setRadiusY(cssValuePool().createValue(ellipse->radiusY()));
+ ellipseValue->setCenterX(cssValuePool().createValue(ellipse->centerX(), style));
+ ellipseValue->setCenterY(cssValuePool().createValue(ellipse->centerY(), style));
+ ellipseValue->setRadiusX(cssValuePool().createValue(ellipse->radiusX(), style));
+ ellipseValue->setRadiusY(cssValuePool().createValue(ellipse->radiusY(), style));
basicShapeValue = ellipseValue.release();
break;
@@ -86,7 +86,7 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
polygonValue->setWindRule(polygon->windRule());
const Vector<Length>& values = polygon->values();
for (unsigned i = 0; i < values.size(); i += 2)
- polygonValue->appendPoint(cssValuePool().createValue(values.at(i)), cssValuePool().createValue(values.at(i + 1)));
+ polygonValue->appendPoint(cssValuePool().createValue(values.at(i), style), cssValuePool().createValue(values.at(i + 1), style));
basicShapeValue = polygonValue.release();
break;
@@ -95,12 +95,12 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape);
RefPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create();
- rectangleValue->setTop(cssValuePool().createValue(rectangle->top()));
- rectangleValue->setRight(cssValuePool().createValue(rectangle->right()));
- rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom()));
- rectangleValue->setLeft(cssValuePool().createValue(rectangle->left()));
- rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX()));
- rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY()));
+ rectangleValue->setTop(cssValuePool().createValue(rectangle->top(), style));
+ rectangleValue->setRight(cssValuePool().createValue(rectangle->right(), style));
+ rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom(), style));
+ rectangleValue->setLeft(cssValuePool().createValue(rectangle->left(), style));
+ rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX(), style));
+ rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY(), style));
basicShapeValue = rectangleValue.release();
break;
@@ -113,7 +113,7 @@ PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
static Length convertToLength(const RenderStyle* style, const RenderStyle* rootStyle, CSSPrimitiveValue* value)
{
- return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | ViewportPercentageConversion>(style, rootStyle, style->effectiveZoom());
+ return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | CalculatedConversion | ViewportPercentageConversion>(style, rootStyle, style->effectiveZoom());
}
PassRefPtr<BasicShape> basicShapeForValue(const RenderStyle* style, const RenderStyle* rootStyle, const CSSBasicShape* basicShapeValue)
diff --git a/Source/WebCore/css/BasicShapeFunctions.h b/Source/WebCore/css/BasicShapeFunctions.h
index 9bbc7c762..ddf7659a2 100644
--- a/Source/WebCore/css/BasicShapeFunctions.h
+++ b/Source/WebCore/css/BasicShapeFunctions.h
@@ -39,7 +39,7 @@ class CSSBasicShape;
class CSSValue;
class RenderStyle;
-PassRefPtr<CSSValue> valueForBasicShape(const BasicShape*);
+PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle*, const BasicShape*);
PassRefPtr<BasicShape> basicShapeForValue(const RenderStyle*, const RenderStyle* rootStyle, const CSSBasicShape*);
}
diff --git a/Source/WebCore/css/CSSCalculationValue.cpp b/Source/WebCore/css/CSSCalculationValue.cpp
index dca177991..b42a520c2 100644
--- a/Source/WebCore/css/CSSCalculationValue.cpp
+++ b/Source/WebCore/css/CSSCalculationValue.cpp
@@ -31,10 +31,12 @@
#include "config.h"
#include "CSSCalculationValue.h"
+#include "CSSPrimitiveValueMappings.h"
#include "CSSValueList.h"
#include "Length.h"
#include "StyleResolver.h"
+#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/text/StringBuilder.h>
@@ -77,6 +79,72 @@ static CalculationCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
}
}
+static bool hasDoubleValue(CSSPrimitiveValue::UnitTypes type)
+{
+ switch (type) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ case CSSPrimitiveValue::CSS_PARSER_INTEGER:
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ case CSSPrimitiveValue::CSS_EMS:
+ case CSSPrimitiveValue::CSS_EXS:
+ case CSSPrimitiveValue::CSS_CHS:
+ case CSSPrimitiveValue::CSS_REMS:
+ case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_CM:
+ case CSSPrimitiveValue::CSS_MM:
+ case CSSPrimitiveValue::CSS_IN:
+ case CSSPrimitiveValue::CSS_PT:
+ case CSSPrimitiveValue::CSS_PC:
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_RAD:
+ case CSSPrimitiveValue::CSS_GRAD:
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_S:
+ case CSSPrimitiveValue::CSS_HZ:
+ case CSSPrimitiveValue::CSS_KHZ:
+ case CSSPrimitiveValue::CSS_DIMENSION:
+ case CSSPrimitiveValue::CSS_VW:
+ case CSSPrimitiveValue::CSS_VH:
+ case CSSPrimitiveValue::CSS_VMIN:
+ case CSSPrimitiveValue::CSS_VMAX:
+ case CSSPrimitiveValue::CSS_DPPX:
+ case CSSPrimitiveValue::CSS_DPI:
+ case CSSPrimitiveValue::CSS_DPCM:
+ return true;
+ case CSSPrimitiveValue::CSS_UNKNOWN:
+ case CSSPrimitiveValue::CSS_STRING:
+ case CSSPrimitiveValue::CSS_URI:
+ case CSSPrimitiveValue::CSS_IDENT:
+ case CSSPrimitiveValue::CSS_ATTR:
+ case CSSPrimitiveValue::CSS_COUNTER:
+ case CSSPrimitiveValue::CSS_RECT:
+ case CSSPrimitiveValue::CSS_RGBCOLOR:
+ case CSSPrimitiveValue::CSS_PAIR:
+ case CSSPrimitiveValue::CSS_UNICODE_RANGE:
+ case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
+ case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
+ case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
+ case CSSPrimitiveValue::CSS_TURN:
+ case CSSPrimitiveValue::CSS_COUNTER_NAME:
+ case CSSPrimitiveValue::CSS_SHAPE:
+ case CSSPrimitiveValue::CSS_QUAD:
+ case CSSPrimitiveValue::CSS_CALC:
+ case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
+ case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
+#if ENABLE(CSS_VARIABLES)
+ case CSSPrimitiveValue::CSS_VARIABLE_NAME:
+#endif
+ case CSSPrimitiveValue::CSS_PROPERTY_ID:
+ case CSSPrimitiveValue::CSS_VALUE_ID:
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPrimitiveValue::CSS_DASHBOARD_REGION:
+#endif
+ return false;
+ };
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
static String buildCssText(const String& expression)
{
StringBuilder result;
@@ -87,7 +155,7 @@ static String buildCssText(const String& expression)
result.append(expression);
if (expressionHasSingleTerm)
result.append(')');
- return result.toString();
+ return result.toString();
}
String CSSCalcValue::customCssText() const
@@ -115,10 +183,10 @@ bool CSSCalcValue::hasVariableReference() const
double CSSCalcValue::clampToPermittedRange(double value) const
{
return m_nonNegative && value < 0 ? 0 : value;
-}
-
-double CSSCalcValue::doubleValue() const
-{
+}
+
+double CSSCalcValue::doubleValue() const
+{
return clampToPermittedRange(m_expression->doubleValue());
}
@@ -126,20 +194,27 @@ double CSSCalcValue::computeLengthPx(const RenderStyle* currentStyle, const Rend
{
return clampToPermittedRange(m_expression->computeLengthPx(currentStyle, rootStyle, multiplier, computingFontSize));
}
-
-CSSCalcExpressionNode::~CSSCalcExpressionNode()
+
+CSSCalcExpressionNode::~CSSCalcExpressionNode()
{
}
-
+
class CSSCalcPrimitiveValue : public CSSCalcExpressionNode {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<CSSCalcPrimitiveValue> create(CSSPrimitiveValue* value, bool isInteger)
+ static PassRefPtr<CSSCalcPrimitiveValue> create(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
{
return adoptRef(new CSSCalcPrimitiveValue(value, isInteger));
}
-
+
+ static PassRefPtr<CSSCalcPrimitiveValue> create(double value, CSSPrimitiveValue::UnitTypes type, bool isInteger)
+ {
+ if (std::isnan(value) || std::isinf(value))
+ return 0;
+ return adoptRef(new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type).get(), isInteger));
+ }
+
virtual bool isZero() const
{
return !m_value->getDoubleValue();
@@ -155,7 +230,7 @@ public:
{
return m_value->customSerializeResolvingVariables(variables);
}
-
+
virtual bool hasVariableReference() const
{
return m_value->isVariableName();
@@ -170,8 +245,12 @@ public:
case CalcLength:
return adoptPtr(new CalcExpressionNumber(m_value->computeLength<float>(style, rootStyle, zoom)));
case CalcPercent:
- case CalcPercentLength:
- return adoptPtr(new CalcExpressionLength(StyleResolver::convertToFloatLength(m_value.get(), style, rootStyle, zoom)));
+ case CalcPercentLength: {
+ CSSPrimitiveValue* primitiveValue = m_value.get();
+ return adoptPtr(new CalcExpressionLength(primitiveValue
+ ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | FractionConversion>(style, rootStyle, zoom)
+ : Length(Undefined)));
+ }
// Only types that could be part of a Length expression can be converted
// to a CalcExpressionNode. CalcPercentNumber makes no sense as a Length.
case CalcPercentNumber:
@@ -186,23 +265,12 @@ public:
virtual double doubleValue() const
{
- switch (m_category) {
- case CalcNumber:
- case CalcPercent:
+ if (hasDoubleValue(primitiveType()))
return m_value->getDoubleValue();
- case CalcLength:
- case CalcPercentLength:
- case CalcPercentNumber:
-#if ENABLE(CSS_VARIABLES)
- case CalcVariable:
-#endif
- case CalcOther:
- ASSERT_NOT_REACHED();
- break;
- }
+ ASSERT_NOT_REACHED();
return 0;
}
-
+
virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const
{
switch (m_category) {
@@ -220,7 +288,8 @@ public:
ASSERT_NOT_REACHED();
break;
}
- return 0;
+ ASSERT_NOT_REACHED();
+ return 0;
}
virtual bool equals(const CSSCalcExpressionNode& other) const
@@ -232,9 +301,13 @@ public:
}
virtual Type type() const { return CssCalcPrimitiveValue; }
-
+ virtual CSSPrimitiveValue::UnitTypes primitiveType() const
+ {
+ return CSSPrimitiveValue::UnitTypes(m_value->primitiveType());
+ }
+
private:
- explicit CSSCalcPrimitiveValue(CSSPrimitiveValue* value, bool isInteger)
+ explicit CSSCalcPrimitiveValue(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
: CSSCalcExpressionNode(unitCategory((CSSPrimitiveValue::UnitTypes)value->primitiveType()), isInteger)
, m_value(value)
{
@@ -244,12 +317,13 @@ private:
};
static const CalculationCategory addSubtractResult[CalcOther][CalcOther] = {
- { CalcNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther },
- { CalcOther, CalcLength, CalcPercentLength, CalcOther, CalcPercentLength },
- { CalcPercentNumber, CalcPercentLength, CalcPercent, CalcPercentNumber, CalcPercentLength },
- { CalcPercentNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther },
- { CalcOther, CalcPercentLength, CalcPercentLength, CalcOther, CalcPercentLength },
-};
+// CalcNumber CalcLength CalcPercent CalcPercentNumber CalcPercentLength
+ { CalcNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, // CalcNumber
+ { CalcOther, CalcLength, CalcPercentLength, CalcOther, CalcPercentLength }, // CalcLength
+ { CalcPercentNumber, CalcPercentLength, CalcPercent, CalcPercentNumber, CalcPercentLength }, // CalcPercent
+ { CalcPercentNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, // CalcPercentNumber
+ { CalcOther, CalcPercentLength, CalcPercentLength, CalcOther, CalcPercentLength }, // CalcPercentLength
+};
static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSide, const CSSCalcExpressionNode& rightSide, CalcOperator op)
{
@@ -266,10 +340,10 @@ static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSi
switch (op) {
case CalcAdd:
- case CalcSubtract:
+ case CalcSubtract:
return addSubtractResult[leftCategory][rightCategory];
case CalcMultiply:
- if (leftCategory != CalcNumber && rightCategory != CalcNumber)
+ if (leftCategory != CalcNumber && rightCategory != CalcNumber)
return CalcOther;
return leftCategory == CalcNumber ? rightCategory : leftCategory;
case CalcDivide:
@@ -277,18 +351,25 @@ static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSi
return CalcOther;
return leftCategory;
}
-
+
ASSERT_NOT_REACHED();
return CalcOther;
}
+static bool isIntegerResult(const CSSCalcExpressionNode* leftSide, const CSSCalcExpressionNode* rightSide, CalcOperator op)
+{
+ // Performs W3C spec's type checking for calc integers.
+ // http://www.w3.org/TR/css3-values/#calc-type-checking
+ return op != CalcDivide && leftSide->isInteger() && rightSide->isInteger();
+}
+
class CSSCalcBinaryOperation : public CSSCalcExpressionNode {
public:
- static PassRefPtr<CSSCalcBinaryOperation> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
+ static PassRefPtr<CSSCalcExpressionNode> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
{
ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther);
-
+
CalculationCategory newCategory = determineCategory(*leftSide, *rightSide, op);
if (newCategory == CalcOther)
@@ -296,7 +377,64 @@ public:
return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory));
}
-
+
+ static PassRefPtr<CSSCalcExpressionNode> createSimplified(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<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) {
+ CSSPrimitiveValue::UnitTypes evaluationType = isInteger ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER;
+ return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), evaluationType, isInteger);
+ }
+
+ // Simplify addition and subtraction between same types.
+ if (op == CalcAdd || op == CalcSubtract) {
+ if (leftCategory == rightSide->category()) {
+ CSSPrimitiveValue::UnitTypes leftType = leftSide->primitiveType();
+ if (hasDoubleValue(leftType)) {
+ CSSPrimitiveValue::UnitTypes rightType = rightSide->primitiveType();
+ 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::UnitTypes canonicalType = CSSPrimitiveValue::canonicalUnitTypeForCategory(leftUnitCategory);
+ if (canonicalType != CSSPrimitiveValue::CSS_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 0;
+ CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSide.get() : leftSide.get();
+
+ double number = numberSide->doubleValue();
+ if (std::isnan(number) || std::isinf(number))
+ return 0;
+ if (op == CalcDivide && !number)
+ return 0;
+
+ CSSPrimitiveValue::UnitTypes otherType = otherSide->primitiveType();
+ if (hasDoubleValue(otherType))
+ return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide->doubleValue(), number, op), otherType, isInteger);
+ }
+
+ return create(leftSide, rightSide, op);
+ }
+
virtual bool isZero() const
{
return !doubleValue();
@@ -313,11 +451,11 @@ public:
return adoptPtr(new CalcExpressionBinaryOperation(left.release(), right.release(), m_operator));
}
- virtual double doubleValue() const
+ virtual double doubleValue() const
{
return evaluate(m_leftSide->doubleValue(), m_rightSide->doubleValue());
}
-
+
virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const
{
const double leftValue = m_leftSide->computeLengthPx(currentStyle, rootStyle, multiplier, computingFontSize);
@@ -335,8 +473,8 @@ public:
result.append(' ');
result.append(rightExpression);
result.append(')');
-
- return result.toString();
+
+ return result.toString();
}
virtual String customCssText() const
@@ -369,18 +507,64 @@ public:
virtual Type type() const { return CssCalcBinaryOperation; }
+ virtual CSSPrimitiveValue::UnitTypes primitiveType() const
+ {
+ switch (m_category) {
+ case CalcNumber:
+ ASSERT(m_leftSide->category() == CalcNumber && m_rightSide->category() == CalcNumber);
+ if (m_isInteger)
+ return CSSPrimitiveValue::CSS_PARSER_INTEGER;
+ return CSSPrimitiveValue::CSS_NUMBER;
+ case CalcLength:
+ case CalcPercent: {
+ if (m_leftSide->category() == CalcNumber)
+ return m_rightSide->primitiveType();
+ if (m_rightSide->category() == CalcNumber)
+ return m_leftSide->primitiveType();
+ CSSPrimitiveValue::UnitTypes leftType = m_leftSide->primitiveType();
+ if (leftType == m_rightSide->primitiveType())
+ return leftType;
+ return CSSPrimitiveValue::CSS_UNKNOWN;
+ }
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+ return CSSPrimitiveValue::CSS_VARIABLE_NAME;
+#endif
+ case CalcPercentLength:
+ case CalcPercentNumber:
+ case CalcOther:
+ return CSSPrimitiveValue::CSS_UNKNOWN;
+ }
+ ASSERT_NOT_REACHED();
+ return CSSPrimitiveValue::CSS_UNKNOWN;
+ }
+
private:
CSSCalcBinaryOperation(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category)
- : CSSCalcExpressionNode(category, leftSide->isInteger() && rightSide->isInteger())
+ : CSSCalcExpressionNode(category, isIntegerResult(leftSide.get(), rightSide.get(), op))
, m_leftSide(leftSide)
, m_rightSide(rightSide)
, m_operator(op)
{
}
-
- double evaluate(double leftValue, double rightValue) const
+
+ static CSSCalcExpressionNode* getNumberSide(CSSCalcExpressionNode* leftSide, CSSCalcExpressionNode* rightSide)
+ {
+ if (leftSide->category() == CalcNumber)
+ return leftSide;
+ if (rightSide->category() == CalcNumber)
+ return rightSide;
+ return 0;
+ }
+
+ double evaluate(double leftSide, double rightSide) const
+ {
+ return evaluateOperator(leftSide, rightSide, m_operator);
+ }
+
+ static double evaluateOperator(double leftValue, double rightValue, CalcOperator op)
{
- switch (m_operator) {
+ switch (op) {
case CalcAdd:
return leftValue + rightValue;
case CalcSubtract:
@@ -394,7 +578,7 @@ private:
}
return 0;
}
-
+
const RefPtr<CSSCalcExpressionNode> m_leftSide;
const RefPtr<CSSCalcExpressionNode> m_rightSide;
const CalcOperator m_operator;
@@ -449,7 +633,7 @@ private:
if (!value || !value->isPrimitiveValue())
return false;
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value.get());
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get());
result->value = CSSCalcPrimitiveValue::create(primitiveValue, parserValue->isInt);
++*index;
@@ -459,8 +643,8 @@ private:
bool parseValueTerm(CSSParserValueList* tokens, int depth, unsigned* index, Value* result)
{
if (checkDepthAndIndex(&depth, *index, tokens) != OK)
- return false;
-
+ return false;
+
if (operatorValue(tokens, *index) == '(') {
unsigned currentIndex = *index + 1;
if (!parseValueExpression(tokens, depth, &currentIndex, result))
@@ -478,7 +662,7 @@ private:
bool parseValueMultiplicativeExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result)
{
if (checkDepthAndIndex(&depth, *index, tokens) != OK)
- return false;
+ return false;
if (!parseValueTerm(tokens, depth, index, result))
return false;
@@ -493,7 +677,7 @@ private:
if (!parseValueTerm(tokens, depth, index, &rhs))
return false;
- result->value = CSSCalcBinaryOperation::create(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
+ result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
if (!result->value)
return false;
}
@@ -505,7 +689,7 @@ private:
bool parseAdditiveValueExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result)
{
if (checkDepthAndIndex(&depth, *index, tokens) != OK)
- return false;
+ return false;
if (!parseValueMultiplicativeExpression(tokens, depth, index, result))
return false;
@@ -520,7 +704,7 @@ private:
if (!parseValueMultiplicativeExpression(tokens, depth, index, &rhs))
return false;
- result->value = CSSCalcBinaryOperation::create(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
+ result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
if (!result->value)
return false;
}
@@ -535,16 +719,96 @@ private:
}
};
+PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
+{
+ return CSSCalcPrimitiveValue::create(value, isInteger);
+}
+
+PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
+{
+ return CSSCalcBinaryOperation::create(leftSide, rightSide, op);
+}
+
+PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const CalcExpressionNode* node, const RenderStyle* style)
+{
+ switch (node->type()) {
+ case CalcExpressionNodeNumber: {
+ float value = toCalcExpressionNumber(node)->value();
+ return createExpressionNode(CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER), value == trunc(value));
+ }
+ case CalcExpressionNodeLength:
+ return createExpressionNode(toCalcExpressionLength(node)->length(), style);
+ case CalcExpressionNodeBinaryOperation: {
+ const CalcExpressionBinaryOperation* binaryNode = toCalcExpressionBinaryOperation(node);
+ return createExpressionNode(createExpressionNode(binaryNode->leftSide(), style), createExpressionNode(binaryNode->rightSide(), style), binaryNode->getOperator());
+ }
+ case CalcExpressionNodeBlendLength: {
+ // FIXME: (http://webkit.org/b/122036) Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength.
+ const CalcExpressionBlendLength* blendNode = toCalcExpressionBlendLength(node);
+ const double progress = blendNode->progress();
+ const bool isInteger = !progress || (progress == 1);
+ return createExpressionNode(
+ createExpressionNode(
+ createExpressionNode(blendNode->from(), style),
+ createExpressionNode(CSSPrimitiveValue::create(1 - progress, CSSPrimitiveValue::CSS_NUMBER), isInteger),
+ CalcMultiply),
+ createExpressionNode(
+ createExpressionNode(blendNode->to(), style),
+ createExpressionNode(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER), isInteger),
+ CalcMultiply),
+ CalcAdd);
+ }
+ case CalcExpressionNodeUndefined:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const Length& length, const RenderStyle* style)
+{
+ switch (length.type()) {
+ case Percent:
+ case ViewportPercentageWidth:
+ case ViewportPercentageHeight:
+ case ViewportPercentageMin:
+ case ViewportPercentageMax:
+ case Fixed:
+ return createExpressionNode(CSSPrimitiveValue::create(length, style), length.value() == trunc(length.value()));
+ case Calculated:
+ return createExpressionNode(length.calculationValue()->expression(), style);
+ case Auto:
+ case Intrinsic:
+ case MinIntrinsic:
+ case MinContent:
+ case MaxContent:
+ case FillAvailable:
+ case FitContent:
+ case Relative:
+ case Undefined:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
PassRefPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList* parserValueList, CalculationPermittedValueRange range)
-{
- CSSCalcExpressionNodeParser parser;
+{
+ CSSCalcExpressionNodeParser parser;
RefPtr<CSSCalcExpressionNode> expression;
-
+
if (equalIgnoringCase(name, "calc(") || equalIgnoringCase(name, "-webkit-calc("))
- expression = parser.parseCalc(parserValueList);
- // FIXME calc (http://webkit.org/b/16662) Add parsing for min and max here
+ expression = parser.parseCalc(parserValueList);
+ // FIXME: calc (http://webkit.org/b/16662) Add parsing for min and max here
return expression ? adoptRef(new CSSCalcValue(expression, range)) : 0;
}
+PassRefPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtr<CSSCalcExpressionNode> expression, CalculationPermittedValueRange range)
+{
+ return adoptRef(new CSSCalcValue(expression, range));
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/css/CSSCalculationValue.h b/Source/WebCore/css/CSSCalculationValue.h
index 266e8f76c..13a17a3b7 100644
--- a/Source/WebCore/css/CSSCalculationValue.h
+++ b/Source/WebCore/css/CSSCalculationValue.h
@@ -32,6 +32,7 @@
#define CSSCalculationValue_h
#include "CSSParserValues.h"
+#include "CSSPrimitiveValue.h"
#include "CSSValue.h"
#include "CalculationValue.h"
#include <wtf/PassOwnPtr.h>
@@ -42,9 +43,10 @@ namespace WebCore {
class CSSParserValueList;
class CSSValueList;
-class RenderStyle;
class CalculationValue;
class CalcExpressionNode;
+class RenderStyle;
+struct Length;
enum CalculationCategory {
CalcNumber = 0,
@@ -57,7 +59,7 @@ enum CalculationCategory {
#endif
CalcOther
};
-
+
class CSSCalcExpressionNode : public RefCounted<CSSCalcExpressionNode> {
public:
enum Type {
@@ -67,7 +69,7 @@ public:
virtual ~CSSCalcExpressionNode() = 0;
virtual bool isZero() const = 0;
- virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;
+ virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;
virtual double doubleValue() const = 0;
virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const = 0;
virtual String customCssText() const = 0;
@@ -78,56 +80,84 @@ public:
virtual bool equals(const CSSCalcExpressionNode& other) const { return m_category == other.m_category && m_isInteger == other.m_isInteger; }
virtual Type type() const = 0;
- CalculationCategory category() const { return m_category; }
+ CalculationCategory category() const { return m_category; }
+ virtual CSSPrimitiveValue::UnitTypes primitiveType() const = 0;
bool isInteger() const { return m_isInteger; }
-
+
protected:
CSSCalcExpressionNode(CalculationCategory category, bool isInteger)
: m_category(category)
, m_isInteger(isInteger)
{
}
-
+
CalculationCategory m_category;
bool m_isInteger;
};
-
+
class CSSCalcValue : public CSSValue {
public:
static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*, CalculationPermittedValueRange);
- static PassRefPtr<CSSCalcValue> create(CalculationValue*);
+ static PassRefPtr<CSSCalcValue> create(PassRefPtr<CSSCalcExpressionNode>, CalculationPermittedValueRange = CalculationRangeAll);
+ static PassRefPtr<CSSCalcValue> create(const CalculationValue* value, const RenderStyle* style) { return adoptRef(new CSSCalcValue(value, style)); }
+
+ static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSPrimitiveValue>, bool isInteger = false);
+ static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSCalcExpressionNode>, PassRefPtr<CSSCalcExpressionNode>, CalcOperator);
+ static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const CalcExpressionNode*, const RenderStyle*);
+ static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const Length&, const RenderStyle*);
PassRefPtr<CalculationValue> toCalcValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom = 1.0) const
{
return CalculationValue::create(m_expression->toCalcValue(style, rootStyle, zoom), m_nonNegative ? CalculationRangeNonNegative : CalculationRangeAll);
}
CalculationCategory category() const { return m_expression->category(); }
- bool isInt() const { return m_expression->isInteger(); }
+ bool isInt() const { return m_expression->isInteger(); }
double doubleValue() const;
bool isNegative() const { return m_expression->doubleValue() < 0; }
+ CalculationPermittedValueRange permittedValueRange() { return m_nonNegative ? CalculationRangeNonNegative : CalculationRangeAll; }
double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const;
-
+
+ CSSCalcExpressionNode* expressionNode() const { return m_expression.get(); }
+
String customCssText() const;
bool equals(const CSSCalcValue&) const;
#if ENABLE(CSS_VARIABLES)
String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const;
bool hasVariableReference() const;
#endif
-
-private:
+
+private:
CSSCalcValue(PassRefPtr<CSSCalcExpressionNode> expression, CalculationPermittedValueRange range)
: CSSValue(CalculationClass)
, m_expression(expression)
, m_nonNegative(range == CalculationRangeNonNegative)
{
}
-
+ CSSCalcValue(const CalculationValue* value, const RenderStyle* style)
+ : CSSValue(CalculationClass)
+ , m_expression(createExpressionNode(value->expression(), style))
+ , m_nonNegative(value->isNonNegative())
+ {
+ }
+
double clampToPermittedRange(double) const;
const RefPtr<CSSCalcExpressionNode> m_expression;
const bool m_nonNegative;
};
-
+
+inline CSSCalcValue* toCSSCalcValue(CSSValue* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isCalculationValue());
+ return static_cast<CSSCalcValue*>(value);
+}
+
+inline const CSSCalcValue* toCSSCalcValue(const CSSValue* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isCalculationValue());
+ return static_cast<const CSSCalcValue*>(value);
+}
+
} // namespace WebCore
#endif // CSSCalculationValue_h
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
index f645ace2c..621cdf038 100644
--- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -2707,7 +2707,7 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
case CSSPropertyWebkitClipPath:
if (ClipPathOperation* operation = style->clipPath()) {
if (operation->getOperationType() == ClipPathOperation::SHAPE)
- return valueForBasicShape(static_cast<ShapeClipPathOperation*>(operation)->basicShape());
+ return valueForBasicShape(style.get(), static_cast<ShapeClipPathOperation*>(operation)->basicShape());
#if ENABLE(SVG)
else if (operation->getOperationType() == ClipPathOperation::REFERENCE) {
ReferenceClipPathOperation* referenceOperation = static_cast<ReferenceClipPathOperation*>(operation);
@@ -2750,7 +2750,7 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
return cssValuePool().createIdentifierValue(CSSValueNone);
}
ASSERT(style->shapeInside()->type() == ShapeValue::Shape);
- return valueForBasicShape(style->shapeInside()->shape());
+ return valueForBasicShape(style.get(), style->shapeInside()->shape());
case CSSPropertyWebkitShapeOutside:
if (!style->shapeOutside())
return cssValuePool().createIdentifierValue(CSSValueAuto);
@@ -2760,7 +2760,7 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
return cssValuePool().createIdentifierValue(CSSValueNone);
}
ASSERT(style->shapeOutside()->type() == ShapeValue::Shape);
- return valueForBasicShape(style->shapeOutside()->shape());
+ return valueForBasicShape(style.get(), style->shapeOutside()->shape());
#endif
#if ENABLE(CSS_FILTERS)
case CSSPropertyWebkitFilter:
diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp
index d0c852465..bd544aab5 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.cpp
+++ b/Source/WebCore/css/CSSPrimitiveValue.cpp
@@ -52,7 +52,7 @@
using namespace WTF;
namespace WebCore {
-
+
// Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
// Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2;
@@ -132,46 +132,46 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit
return false;
}
-static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
+CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValue::UnitTypes type)
{
// Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
// between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
switch (type) {
- case CSSPrimitiveValue::CSS_NUMBER:
- return CSSPrimitiveValue::UNumber;
- case CSSPrimitiveValue::CSS_PERCENTAGE:
- return CSSPrimitiveValue::UPercent;
- case CSSPrimitiveValue::CSS_PX:
- case CSSPrimitiveValue::CSS_CM:
- case CSSPrimitiveValue::CSS_MM:
- case CSSPrimitiveValue::CSS_IN:
- case CSSPrimitiveValue::CSS_PT:
- case CSSPrimitiveValue::CSS_PC:
- return CSSPrimitiveValue::ULength;
- case CSSPrimitiveValue::CSS_MS:
- case CSSPrimitiveValue::CSS_S:
- return CSSPrimitiveValue::UTime;
- case CSSPrimitiveValue::CSS_DEG:
- case CSSPrimitiveValue::CSS_RAD:
- case CSSPrimitiveValue::CSS_GRAD:
- case CSSPrimitiveValue::CSS_TURN:
- return CSSPrimitiveValue::UAngle;
- case CSSPrimitiveValue::CSS_HZ:
- case CSSPrimitiveValue::CSS_KHZ:
- return CSSPrimitiveValue::UFrequency;
- case CSSPrimitiveValue::CSS_VW:
- case CSSPrimitiveValue::CSS_VH:
- case CSSPrimitiveValue::CSS_VMIN:
- case CSSPrimitiveValue::CSS_VMAX:
- return CSSPrimitiveValue::UViewportPercentageLength;
+ case CSS_NUMBER:
+ return UNumber;
+ case CSS_PERCENTAGE:
+ return UPercent;
+ case CSS_PX:
+ case CSS_CM:
+ case CSS_MM:
+ case CSS_IN:
+ case CSS_PT:
+ case CSS_PC:
+ return ULength;
+ case CSS_MS:
+ case CSS_S:
+ return UTime;
+ case CSS_DEG:
+ case CSS_RAD:
+ case CSS_GRAD:
+ case CSS_TURN:
+ return UAngle;
+ case CSS_HZ:
+ case CSS_KHZ:
+ return UFrequency;
+ case CSS_VW:
+ case CSS_VH:
+ case CSS_VMIN:
+ case CSS_VMAX:
+ return UViewportPercentageLength;
#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
- case CSSPrimitiveValue::CSS_DPPX:
- case CSSPrimitiveValue::CSS_DPI:
- case CSSPrimitiveValue::CSS_DPCM:
- return CSSPrimitiveValue::UResolution;
+ case CSS_DPPX:
+ case CSS_DPI:
+ case CSS_DPCM:
+ return UResolution;
#endif
default:
- return CSSPrimitiveValue::UOther;
+ return UOther;
}
}
@@ -182,14 +182,14 @@ static CSSTextCache& cssTextCache()
return cache;
}
-unsigned short CSSPrimitiveValue::primitiveType() const
+unsigned short CSSPrimitiveValue::primitiveType() const
{
if (m_primitiveUnitType == CSS_PROPERTY_ID || m_primitiveUnitType == CSS_VALUE_ID)
return CSS_IDENT;
if (m_primitiveUnitType != CSSPrimitiveValue::CSS_CALC)
- return m_primitiveUnitType;
-
+ return m_primitiveUnitType;
+
switch (m_value.calc->category()) {
case CalcNumber:
return CSSPrimitiveValue::CSS_NUMBER;
@@ -285,65 +285,102 @@ CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
: CSSValue(PrimitiveClass)
{
+ init(length);
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, const RenderStyle* style)
+ : CSSValue(PrimitiveClass)
+{
switch (length.type()) {
- case Auto:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueAuto;
- break;
- case WebCore::Fixed:
- m_primitiveUnitType = CSS_PX;
- m_value.num = length.value();
- break;
- case Intrinsic:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueIntrinsic;
- break;
- case MinIntrinsic:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueMinIntrinsic;
- break;
- case MinContent:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueWebkitMinContent;
- break;
- case MaxContent:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueWebkitMaxContent;
- break;
- case FillAvailable:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueWebkitFillAvailable;
- break;
- case FitContent:
- m_primitiveUnitType = CSS_VALUE_ID;
- m_value.valueID = CSSValueWebkitFitContent;
- break;
- case Percent:
- m_primitiveUnitType = CSS_PERCENTAGE;
- ASSERT(std::isfinite(length.percent()));
- m_value.num = length.percent();
- break;
- case ViewportPercentageWidth:
- m_primitiveUnitType = CSS_VW;
- m_value.num = length.viewportPercentageLength();
- break;
- case ViewportPercentageHeight:
- m_primitiveUnitType = CSS_VH;
- m_value.num = length.viewportPercentageLength();
- break;
- case ViewportPercentageMin:
- m_primitiveUnitType = CSS_VMIN;
- m_value.num = length.viewportPercentageLength();
- break;
- case ViewportPercentageMax:
- m_primitiveUnitType = CSS_VMAX;
- m_value.num = length.viewportPercentageLength();
- break;
- case Calculated:
- case Relative:
- case Undefined:
- ASSERT_NOT_REACHED();
- break;
+ case Auto:
+ case Intrinsic:
+ case MinIntrinsic:
+ case MinContent:
+ case MaxContent:
+ case FillAvailable:
+ case FitContent:
+ case Percent:
+ case ViewportPercentageWidth:
+ case ViewportPercentageHeight:
+ case ViewportPercentageMin:
+ case ViewportPercentageMax:
+ init(length);
+ return;
+ case Fixed:
+ m_primitiveUnitType = CSS_PX;
+ m_value.num = adjustFloatForAbsoluteZoom(length.value(), style);
+ return;
+ case Calculated:
+ init(CSSCalcValue::create(length.calculationValue().get(), style));
+ return;
+ case Relative:
+ case Undefined:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+void CSSPrimitiveValue::init(const Length& length)
+{
+ switch (length.type()) {
+ case Auto:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueAuto;
+ break;
+ case WebCore::Fixed:
+ m_primitiveUnitType = CSS_PX;
+ m_value.num = length.value();
+ break;
+ case Intrinsic:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueIntrinsic;
+ break;
+ case MinIntrinsic:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueMinIntrinsic;
+ break;
+ case MinContent:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueWebkitMinContent;
+ break;
+ case MaxContent:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueWebkitMaxContent;
+ break;
+ case FillAvailable:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueWebkitFillAvailable;
+ break;
+ case FitContent:
+ m_primitiveUnitType = CSS_VALUE_ID;
+ m_value.valueID = CSSValueWebkitFitContent;
+ break;
+ case Percent:
+ m_primitiveUnitType = CSS_PERCENTAGE;
+ ASSERT(std::isfinite(length.percent()));
+ m_value.num = length.percent();
+ break;
+ case ViewportPercentageWidth:
+ m_primitiveUnitType = CSS_VW;
+ m_value.num = length.viewportPercentageLength();
+ break;
+ case ViewportPercentageHeight:
+ m_primitiveUnitType = CSS_VH;
+ m_value.num = length.viewportPercentageLength();
+ break;
+ case ViewportPercentageMin:
+ m_primitiveUnitType = CSS_VMIN;
+ m_value.num = length.viewportPercentageLength();
+ break;
+ case ViewportPercentageMax:
+ m_primitiveUnitType = CSS_VMAX;
+ m_value.num = length.viewportPercentageLength();
+ break;
+ case Calculated:
+ case Relative:
+ case Undefined:
+ ASSERT_NOT_REACHED();
+ break;
}
}
@@ -552,63 +589,63 @@ double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const Re
if (m_primitiveUnitType == CSS_CALC)
// The multiplier and factor is applied to each value in the calc expression individually
return m_value.calc->computeLengthPx(style, rootStyle, multiplier, computingFontSize);
-
+
double factor;
switch (primitiveType()) {
- case CSS_EMS:
- factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
- break;
- case CSS_EXS:
- // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
- // We really need to compute EX using fontMetrics for the original specifiedSize and not use
- // our actual constructed rendering font.
- if (style->fontMetrics().hasXHeight())
- factor = style->fontMetrics().xHeight();
- else
- factor = (computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize()) / 2.0;
- break;
- case CSS_REMS:
- if (rootStyle)
- factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
- else
- factor = 1.0;
- break;
- case CSS_CHS:
- factor = style->fontMetrics().zeroWidth();
- break;
- case CSS_PX:
- factor = 1.0;
- break;
- case CSS_CM:
- factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
- break;
- case CSS_MM:
- factor = cssPixelsPerInch / 25.4;
- break;
- case CSS_IN:
- factor = cssPixelsPerInch;
- break;
- case CSS_PT:
- factor = cssPixelsPerInch / 72.0;
- break;
- case CSS_PC:
- // 1 pc == 12 pt
- factor = cssPixelsPerInch * 12.0 / 72.0;
- break;
- case CSS_CALC_PERCENTAGE_WITH_LENGTH:
- case CSS_CALC_PERCENTAGE_WITH_NUMBER:
- ASSERT_NOT_REACHED();
- return -1.0;
- case CSS_VH:
- case CSS_VW:
- case CSS_VMAX:
- case CSS_VMIN:
+ case CSS_EMS:
+ factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
+ break;
+ case CSS_EXS:
+ // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
+ // We really need to compute EX using fontMetrics for the original specifiedSize and not use
+ // our actual constructed rendering font.
+ if (style->fontMetrics().hasXHeight())
+ factor = style->fontMetrics().xHeight();
+ else
+ factor = (computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize()) / 2.0;
+ break;
+ case CSS_REMS:
+ if (rootStyle)
+ factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
+ else
factor = 1.0;
- break;
- default:
- ASSERT_NOT_REACHED();
- return -1.0;
+ break;
+ case CSS_CHS:
+ factor = style->fontMetrics().zeroWidth();
+ break;
+ case CSS_PX:
+ factor = 1.0;
+ break;
+ case CSS_CM:
+ factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
+ break;
+ case CSS_MM:
+ factor = cssPixelsPerInch / 25.4;
+ break;
+ case CSS_IN:
+ factor = cssPixelsPerInch;
+ break;
+ case CSS_PT:
+ factor = cssPixelsPerInch / 72.0;
+ break;
+ case CSS_PC:
+ // 1 pc == 12 pt
+ factor = cssPixelsPerInch * 12.0 / 72.0;
+ break;
+ case CSS_CALC_PERCENTAGE_WITH_LENGTH:
+ case CSS_CALC_PERCENTAGE_WITH_NUMBER:
+ ASSERT_NOT_REACHED();
+ return -1.0;
+ case CSS_VH:
+ case CSS_VW:
+ case CSS_VMAX:
+ case CSS_VMIN:
+ factor = 1.0;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return -1.0;
}
// We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
@@ -629,53 +666,53 @@ void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
ec = NO_MODIFICATION_ALLOWED_ERR;
}
-static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
+double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
{
double factor = 1.0;
// FIXME: the switch can be replaced by an array of scale factors.
switch (unitType) {
- // These are "canonical" units in their respective categories.
- case CSSPrimitiveValue::CSS_PX:
- case CSSPrimitiveValue::CSS_DEG:
- case CSSPrimitiveValue::CSS_MS:
- case CSSPrimitiveValue::CSS_HZ:
- break;
- case CSSPrimitiveValue::CSS_CM:
- factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
- break;
- case CSSPrimitiveValue::CSS_DPCM:
- factor = 2.54 / cssPixelsPerInch; // (2.54 cm/in)
- break;
- case CSSPrimitiveValue::CSS_MM:
- factor = cssPixelsPerInch / 25.4;
- break;
- case CSSPrimitiveValue::CSS_IN:
- factor = cssPixelsPerInch;
- break;
- case CSSPrimitiveValue::CSS_DPI:
- factor = 1 / cssPixelsPerInch;
- break;
- case CSSPrimitiveValue::CSS_PT:
- factor = cssPixelsPerInch / 72.0;
- break;
- case CSSPrimitiveValue::CSS_PC:
- factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
- break;
- case CSSPrimitiveValue::CSS_RAD:
- factor = 180 / piDouble;
- break;
- case CSSPrimitiveValue::CSS_GRAD:
- factor = 0.9;
- break;
- case CSSPrimitiveValue::CSS_TURN:
- factor = 360;
- break;
- case CSSPrimitiveValue::CSS_S:
- case CSSPrimitiveValue::CSS_KHZ:
- factor = 1000;
- break;
- default:
- break;
+ // These are "canonical" units in their respective categories.
+ case CSS_PX:
+ case CSS_DEG:
+ case CSS_MS:
+ case CSS_HZ:
+ break;
+ case CSS_CM:
+ factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
+ break;
+ case CSS_DPCM:
+ factor = 2.54 / cssPixelsPerInch; // (2.54 cm/in)
+ break;
+ case CSS_MM:
+ factor = cssPixelsPerInch / 25.4;
+ break;
+ case CSS_IN:
+ factor = cssPixelsPerInch;
+ break;
+ case CSS_DPI:
+ factor = 1 / cssPixelsPerInch;
+ break;
+ case CSS_PT:
+ factor = cssPixelsPerInch / 72.0;
+ break;
+ case CSS_PC:
+ factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
+ break;
+ case CSS_RAD:
+ factor = 180 / piDouble;
+ break;
+ case CSS_GRAD:
+ factor = 0.9;
+ break;
+ case CSS_TURN:
+ factor = 360;
+ break;
+ case CSS_S:
+ case CSS_KHZ:
+ factor = 1000;
+ break;
+ default:
+ break;
}
return factor;
@@ -702,7 +739,7 @@ double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
}
double CSSPrimitiveValue::getDoubleValue() const
-{
+{
return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue();
}
@@ -796,20 +833,20 @@ String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
{
ec = 0;
switch (m_primitiveUnitType) {
- case CSS_STRING:
- case CSS_ATTR:
- case CSS_URI:
+ case CSS_STRING:
+ case CSS_ATTR:
+ case CSS_URI:
#if ENABLE(CSS_VARIABLES)
- case CSS_VARIABLE_NAME:
+ case CSS_VARIABLE_NAME:
#endif
- return m_value.string;
- case CSS_VALUE_ID:
- return valueName(m_value.valueID);
- case CSS_PROPERTY_ID:
- return propertyName(m_value.propertyID);
- default:
- ec = INVALID_ACCESS_ERR;
- break;
+ return m_value.string;
+ case CSS_VALUE_ID:
+ return valueName(m_value.valueID);
+ case CSS_PROPERTY_ID:
+ return propertyName(m_value.propertyID);
+ default:
+ ec = INVALID_ACCESS_ERR;
+ break;
}
return String();
@@ -818,19 +855,19 @@ String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
String CSSPrimitiveValue::getStringValue() const
{
switch (m_primitiveUnitType) {
- case CSS_STRING:
- case CSS_ATTR:
- case CSS_URI:
+ case CSS_STRING:
+ case CSS_ATTR:
+ case CSS_URI:
#if ENABLE(CSS_VARIABLES)
- case CSS_VARIABLE_NAME:
+ case CSS_VARIABLE_NAME:
#endif
- return m_value.string;
- case CSS_VALUE_ID:
- return valueName(m_value.valueID);
- case CSS_PROPERTY_ID:
- return propertyName(m_value.propertyID);
- default:
- break;
+ return m_value.string;
+ case CSS_VALUE_ID:
+ return valueName(m_value.valueID);
+ case CSS_PROPERTY_ID:
+ return propertyName(m_value.propertyID);
+ default:
+ break;
}
return String();
diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h
index 6bf437ac5..9ccb1eeb3 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.h
+++ b/Source/WebCore/css/CSSPrimitiveValue.h
@@ -154,6 +154,7 @@ public:
#endif
UOther
};
+ static UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes);
bool isAngle() const
{
@@ -207,7 +208,7 @@ public:
bool isViewportPercentageMax() const { return m_primitiveUnitType == CSS_VMAX; }
bool isViewportPercentageMin() const { return m_primitiveUnitType == CSS_VMIN; }
bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
-
+
static PassRefPtr<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(new CSSPrimitiveValue(valueID)); }
static PassRefPtr<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID) { return adoptRef(new CSSPrimitiveValue(propertyID)); }
static PassRefPtr<CSSPrimitiveValue> createParserOperator(int parserOperator) { return adoptRef(new CSSPrimitiveValue(parserOperator)); }
@@ -215,6 +216,7 @@ public:
static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); }
static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
+ static PassRefPtr<CSSPrimitiveValue> create(const Length& value, const RenderStyle* style) { return adoptRef(new CSSPrimitiveValue(value, style)); }
template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value)
{
@@ -314,7 +316,7 @@ public:
#endif
CSSBasicShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
-
+
CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_value.calc; }
CSSPropertyID getPropertyID() const { return m_primitiveUnitType == CSS_PROPERTY_ID ? m_value.propertyID : CSSPropertyInvalid; }
@@ -333,12 +335,15 @@ public:
void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const;
Length viewportPercentageLength() const;
-
+
PassRefPtr<CSSPrimitiveValue> cloneForCSSOM() const;
void setCSSOMSafe() { m_isCSSOMSafe = true; }
bool equals(const CSSPrimitiveValue&) const;
+ static UnitTypes canonicalUnitTypeForCategory(UnitCategory);
+ static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType);
+
private:
CSSPrimitiveValue(CSSValueID);
CSSPrimitiveValue(CSSPropertyID);
@@ -346,6 +351,7 @@ private:
CSSPrimitiveValue(int parserOperator);
CSSPrimitiveValue(unsigned color); // RGB value
CSSPrimitiveValue(const Length&);
+ CSSPrimitiveValue(const Length&, const RenderStyle*);
CSSPrimitiveValue(const String&, UnitTypes);
CSSPrimitiveValue(double, UnitTypes);
@@ -366,8 +372,7 @@ private:
static void create(unsigned); // compile-time guard
template<typename T> operator T*(); // compile-time guard
- static UnitTypes canonicalUnitTypeForCategory(UnitCategory category);
-
+ void init(const Length&);
void init(PassRefPtr<Counter>);
void init(PassRefPtr<Rect>);
void init(PassRefPtr<Pair>);
@@ -396,6 +401,18 @@ private:
} m_value;
};
+inline CSSPrimitiveValue* toCSSPrimitiveValue(CSSValue* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isPrimitiveValue());
+ return static_cast<CSSPrimitiveValue*>(value);
+}
+
+inline const CSSPrimitiveValue* toCSSPrimitiveValue(const CSSValue* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isPrimitiveValue());
+ return static_cast<const CSSPrimitiveValue*>(value);
+}
+
} // namespace WebCore
#endif // CSSPrimitiveValue_h
diff --git a/Source/WebCore/css/CSSValuePool.h b/Source/WebCore/css/CSSValuePool.h
index 421d74d6e..e2ceb6e4c 100644
--- a/Source/WebCore/css/CSSValuePool.h
+++ b/Source/WebCore/css/CSSValuePool.h
@@ -31,9 +31,9 @@
#include "CSSPrimitiveValue.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
-#include <wtf/text/AtomicStringHash.h>
#include <wtf/HashMap.h>
#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicStringHash.h>
namespace WebCore {
@@ -52,6 +52,7 @@ public:
PassRefPtr<CSSPrimitiveValue> createColorValue(unsigned rgbValue);
PassRefPtr<CSSPrimitiveValue> createValue(double value, CSSPrimitiveValue::UnitTypes);
PassRefPtr<CSSPrimitiveValue> createValue(const String& value, CSSPrimitiveValue::UnitTypes type) { return CSSPrimitiveValue::create(value, type); }
+ PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle* style) { return CSSPrimitiveValue::create(value, style); }
template<typename T> static PassRefPtr<CSSPrimitiveValue> createValue(T value) { return CSSPrimitiveValue::create(value); }
void drain();
diff --git a/Source/WebCore/platform/CalculationValue.h b/Source/WebCore/platform/CalculationValue.h
index 72543ff60..3dcbf1b78 100644
--- a/Source/WebCore/platform/CalculationValue.h
+++ b/Source/WebCore/platform/CalculationValue.h
@@ -59,7 +59,7 @@ enum CalcExpressionNodeType {
CalcExpressionNodeBinaryOperation,
CalcExpressionNodeBlendLength,
};
-
+
class CalcExpressionNode {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -67,37 +67,40 @@ public:
: m_type(CalcExpressionNodeUndefined)
{
}
-
+
virtual ~CalcExpressionNode()
{
}
-
+
virtual float evaluate(float maxValue) const = 0;
virtual bool operator==(const CalcExpressionNode&) const = 0;
CalcExpressionNodeType type() const { return m_type; }
-
+
protected:
CalcExpressionNodeType m_type;
};
-
+
class CalculationValue : public RefCounted<CalculationValue> {
public:
static PassRefPtr<CalculationValue> create(PassOwnPtr<CalcExpressionNode> value, CalculationPermittedValueRange);
float evaluate(float maxValue) const;
- bool operator==(const CalculationValue& o) const
- {
+ bool operator==(const CalculationValue& o) const
+ {
return *(m_value.get()) == *(o.m_value.get());
}
-
+
+ bool isNonNegative() const { return m_isNonNegative; }
+ const CalcExpressionNode* expression() const { return m_value.get(); }
+
private:
CalculationValue(PassOwnPtr<CalcExpressionNode> value, CalculationPermittedValueRange range)
: m_value(value)
, m_isNonNegative(range == CalculationRangeNonNegative)
{
}
-
+
OwnPtr<CalcExpressionNode> m_value;
bool m_isNonNegative;
};
@@ -115,20 +118,28 @@ public:
return m_value == o.m_value;
}
- virtual bool operator==(const CalcExpressionNode& o) const
+ virtual bool operator==(const CalcExpressionNode& o) const OVERRIDE
{
return type() == o.type() && *this == static_cast<const CalcExpressionNumber&>(o);
}
-
- virtual float evaluate(float) const
+
+ virtual float evaluate(float) const OVERRIDE
{
return m_value;
}
-
+
+ float value() const { return m_value; }
+
private:
float m_value;
};
+inline const CalcExpressionNumber* toCalcExpressionNumber(const CalcExpressionNode* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeNumber);
+ return static_cast<const CalcExpressionNumber*>(value);
+}
+
class CalcExpressionLength : public CalcExpressionNode {
public:
explicit CalcExpressionLength(Length length)
@@ -141,21 +152,29 @@ public:
{
return m_length == o.m_length;
}
-
- virtual bool operator==(const CalcExpressionNode& o) const
+
+ virtual bool operator==(const CalcExpressionNode& o) const OVERRIDE
{
return type() == o.type() && *this == static_cast<const CalcExpressionLength&>(o);
}
-
- virtual float evaluate(float maxValue) const
+
+ virtual float evaluate(float maxValue) const OVERRIDE
{
return floatValueForLength(m_length, maxValue);
}
-
+
+ const Length& length() const { return m_length; }
+
private:
Length m_length;
};
+inline const CalcExpressionLength* toCalcExpressionLength(const CalcExpressionNode* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeLength);
+ return static_cast<const CalcExpressionLength*>(value);
+}
+
class CalcExpressionBinaryOperation : public CalcExpressionNode {
public:
CalcExpressionBinaryOperation(PassOwnPtr<CalcExpressionNode> leftSide, PassOwnPtr<CalcExpressionNode> rightSide, CalcOperator op)
@@ -171,13 +190,16 @@ public:
return m_operator == o.m_operator && *m_leftSide == *o.m_leftSide && *m_rightSide == *o.m_rightSide;
}
- virtual bool operator==(const CalcExpressionNode& o) const
+ virtual bool operator==(const CalcExpressionNode& o) const OVERRIDE
{
return type() == o.type() && *this == static_cast<const CalcExpressionBinaryOperation&>(o);
}
-
-
- virtual float evaluate(float) const;
+
+ virtual float evaluate(float) const OVERRIDE;
+
+ const CalcExpressionNode* leftSide() const { return m_leftSide.get(); }
+ const CalcExpressionNode* rightSide() const { return m_rightSide.get(); }
+ CalcOperator getOperator() const { return m_operator; }
private:
OwnPtr<CalcExpressionNode> m_leftSide;
@@ -185,6 +207,12 @@ private:
CalcOperator m_operator;
};
+inline const CalcExpressionBinaryOperation* toCalcExpressionBinaryOperation(const CalcExpressionNode* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeBinaryOperation);
+ return static_cast<const CalcExpressionBinaryOperation*>(value);
+}
+
class CalcExpressionBlendLength : public CalcExpressionNode {
public:
CalcExpressionBlendLength(Length from, Length to, float progress)
@@ -194,28 +222,38 @@ public:
{
m_type = CalcExpressionNodeBlendLength;
}
-
+
bool operator==(const CalcExpressionBlendLength& o) const
{
return m_progress == o.m_progress && m_from == o.m_from && m_to == o.m_to;
}
-
- virtual bool operator==(const CalcExpressionNode& o) const
+
+ virtual bool operator==(const CalcExpressionNode& o) const OVERRIDE
{
return type() == o.type() && *this == static_cast<const CalcExpressionBlendLength&>(o);
}
-
- virtual float evaluate(float maxValue) const
+
+ virtual float evaluate(float maxValue) const OVERRIDE
{
return (1.0f - m_progress) * floatValueForLength(m_from, maxValue) + m_progress * floatValueForLength(m_to, maxValue);
}
-
-private:
+
+ const Length& from() const { return m_from; }
+ const Length& to() const { return m_to; }
+ float progress() const { return m_progress; }
+
+private:
Length m_from;
Length m_to;
float m_progress;
};
-
+
+inline const CalcExpressionBlendLength* toCalcExpressionBlendLength(const CalcExpressionNode* value)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeBlendLength);
+ return static_cast<const CalcExpressionBlendLength*>(value);
+}
+
} // namespace WebCore
#endif // CalculationValue_h