Diff
Added: trunk/LayoutTests/fast/css/variables/calc-expected.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-expected.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: 3px 10px;
+}
+</style>
+<div>This text should have top and bottom borders of 3px and left and right borders of 10px</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-inside-calc-expected.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-inside-calc-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-inside-calc-expected.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-inside-calc.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-inside-calc.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-inside-calc.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<script>
+internals.settings.setCSSVariablesEnabled(true);
+</script>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: -webkit-calc(-webkit-var(a) + 1px);
+ -webkit-var-a: -webkit-calc(1px + 3px);
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-invalid-value-expected.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-invalid-value-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-invalid-value-expected.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-invalid-value.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-invalid-value.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-invalid-value.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<script>
+internals.settings.setCSSVariablesEnabled(true);
+</script>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: -webkit-calc(-webkit-var(a) + 1px);
+ -webkit-var-a: black;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-invalid-variable-expected.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-invalid-variable-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-invalid-variable-expected.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-invalid-variable.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-invalid-variable.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-invalid-variable.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<script>
+internals.settings.setCSSVariablesEnabled(true);
+</script>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: -webkit-calc(-webkit-var(a) + 1px);
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-negated-variable-expected.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-negated-variable-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-negated-variable-expected.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc-negated-variable.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc-negated-variable.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc-negated-variable.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<script>
+internals.settings.setCSSVariablesEnabled(true);
+</script>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: -webkit-calc(--webkit-var(a) + 1px);
+ -webkit-var-a: 5px;
+}
+</style>
+<div>This text should have the default border width</div>
+</html>
Added: trunk/LayoutTests/fast/css/variables/calc.html (0 => 127220)
--- trunk/LayoutTests/fast/css/variables/calc.html (rev 0)
+++ trunk/LayoutTests/fast/css/variables/calc.html 2012-08-31 01:13:50 UTC (rev 127220)
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<script>
+internals.settings.setCSSVariablesEnabled(true);
+</script>
+<style>
+div {
+ border-color: green;
+ border-style: solid;
+ border-width: -webkit-calc(-webkit-var(a) + -webkit-var(b)) -webkit-calc(-webkit-var(c) * -webkit-var(d));
+ -webkit-var-a: 2px;
+ -webkit-var-b: 1px;
+ -webkit-var-c: 5;
+ -webkit-var-d: 2px;
+
+}
+</style>
+<div>This text should have top and bottom borders of 3px and left and right borders of 10px</div>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (127219 => 127220)
--- trunk/Source/WebCore/ChangeLog 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/ChangeLog 2012-08-31 01:13:50 UTC (rev 127220)
@@ -1,3 +1,47 @@
+2012-08-30 Luke Macpherson <[email protected]>
+
+ Make it possible to use CSS Variables inside Calc expressions.
+ https://bugs.webkit.org/show_bug.cgi?id=95284
+
+ Reviewed by Tony Chang.
+
+ Allows calc expressions to contain unevaluated variables, which are then resolved in StyleResolver.cpp when building the RenderStyle tree.
+
+ Tests:
+ fast/css/variables/calc.html
+
+ * css/CSSCalculationValue.cpp:
+ (WebCore::unitCategory):
+ (WebCore):
+ (WebCore::CSSCalcValue::customSerializeResolvingVariables):
+ Generates a CSS _expression_ with variables resolved into their corresponding values.
+ (WebCore::CSSCalcValue::hasVariableReference):
+ Returns true if the calculation's _expression_ tree refers to a variable (that needs to be resolved).
+ (CSSCalcPrimitiveValue):
+ (WebCore::CSSCalcPrimitiveValue::serializeResolvingVariables):
+ Resolves the variable using the underlying CSSPrimitiveValue's serializeResolvingVariables function.
+ (WebCore::CSSCalcPrimitiveValue::hasVariableReference):
+ (WebCore::CSSCalcPrimitiveValue::toCalcValue):
+ (WebCore::CSSCalcPrimitiveValue::doubleValue):
+ (WebCore::CSSCalcPrimitiveValue::computeLengthPx):
+ (WebCore::CSSCalcBinaryOperation::create):
+ (CSSCalcBinaryOperation):
+ (WebCore::CSSCalcBinaryOperation::serializeResolvingVariables):
+ Builds a CSS _expression_ for contained subtrees.
+ (WebCore::CSSCalcBinaryOperation::hasVariableReference):
+ Returns true if either subtree contains a variable.
+ * css/CSSCalculationValue.h:
+ (CSSCalcExpressionNode):
+ (CSSCalcValue):
+ * css/CSSGrammar.y:
+ * css/CSSParser.cpp:
+ (WebCore::CSSParser::validCalculationUnit):
+ * css/CSSPrimitiveValue.cpp:
+ (WebCore::CSSPrimitiveValue::primitiveType):
+ (WebCore::CSSPrimitiveValue::customSerializeResolvingVariables):
+ * css/StyleResolver.cpp:
+ (WebCore::StyleResolver::collectMatchingRulesForList):
+
2012-08-30 Max Vujovic <[email protected]>
[CSS Shaders] Implement normal blend mode and source-atop compositing mode
Modified: trunk/Source/WebCore/css/CSSCalculationValue.cpp (127219 => 127220)
--- trunk/Source/WebCore/css/CSSCalculationValue.cpp 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/CSSCalculationValue.cpp 2012-08-31 01:13:50 UTC (rev 127220)
@@ -68,17 +68,19 @@
case CSSPrimitiveValue::CSS_PC:
case CSSPrimitiveValue::CSS_REMS:
return CalcLength;
+#if ENABLE(CSS_VARIABLES)
+ case CSSPrimitiveValue::CSS_VARIABLE_NAME:
+ return CalcVariable;
+#endif
default:
return CalcOther;
}
}
-
-String CSSCalcValue::customCssText() const
+
+static String buildCssText(const String& _expression_)
{
StringBuilder result;
-
result.append("-webkit-calc");
- String _expression_ = m_expression->customCssText();
bool expressionHasSingleTerm = _expression_[0] != '(';
if (expressionHasSingleTerm)
result.append('(');
@@ -88,6 +90,23 @@
return result.toString();
}
+String CSSCalcValue::customCssText() const
+{
+ return buildCssText(m_expression->customCssText());
+}
+
+#if ENABLE(CSS_VARIABLES)
+String CSSCalcValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
+{
+ return buildCssText(m_expression->serializeResolvingVariables(variables));
+}
+
+bool CSSCalcValue::hasVariableReference() const
+{
+ return m_expression->hasVariableReference();
+}
+#endif
+
void CSSCalcValue::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS);
@@ -130,6 +149,18 @@
return m_value->cssText();
}
+#if ENABLE(CSS_VARIABLES)
+ virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
+ {
+ return m_value->customSerializeResolvingVariables(variables);
+ }
+
+ virtual bool hasVariableReference() const
+ {
+ return m_value->isVariableName();
+ }
+#endif
+
virtual PassOwnPtr<CalcExpressionNode> toCalcValue(RenderStyle* style, RenderStyle* rootStyle, double zoom) const
{
switch (m_category) {
@@ -143,6 +174,9 @@
// 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:
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+#endif
case CalcOther:
ASSERT_NOT_REACHED();
}
@@ -158,6 +192,9 @@
case CalcLength:
case CalcPercentLength:
case CalcPercentNumber:
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+#endif
case CalcOther:
ASSERT_NOT_REACHED();
break;
@@ -175,6 +212,9 @@
return m_value->getDoubleValue();
case CalcPercentLength:
case CalcPercentNumber:
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+#endif
case CalcOther:
ASSERT_NOT_REACHED();
break;
@@ -191,7 +231,7 @@
private:
explicit CSSCalcPrimitiveValue(CSSPrimitiveValue* value, bool isInteger)
: CSSCalcExpressionNode(unitCategory((CSSPrimitiveValue::UnitTypes)value->primitiveType()), isInteger)
- , m_value(value)
+ , m_value(value)
{
}
@@ -205,42 +245,50 @@
{ CalcPercentNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther },
{ CalcOther, CalcPercentLength, CalcPercentLength, CalcOther, CalcPercentLength },
};
+
+static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSide, const CSSCalcExpressionNode& rightSide, CalcOperator op)
+{
+ CalculationCategory leftCategory = leftSide.category();
+ CalculationCategory rightCategory = rightSide.category();
+
+ if (leftCategory == CalcOther || rightCategory == CalcOther)
+ return CalcOther;
+
+#if ENABLE(CSS_VARIABLES)
+ if (leftCategory == CalcVariable || rightCategory == CalcVariable)
+ return CalcVariable;
+#endif
+
+ switch (op) {
+ case CalcAdd:
+ case CalcSubtract:
+ return addSubtractResult[leftCategory][rightCategory];
+ case CalcMultiply:
+ if (leftCategory != CalcNumber && rightCategory != CalcNumber)
+ return CalcOther;
+ return leftCategory == CalcNumber ? rightCategory : leftCategory;
+ case CalcDivide:
+ if (rightCategory != CalcNumber || rightSide.isZero())
+ return CalcOther;
+ return leftCategory;
+ }
+ ASSERT_NOT_REACHED();
+ return CalcOther;
+}
+
class CSSCalcBinaryOperation : public CSSCalcExpressionNode {
+
public:
static PassRefPtr<CSSCalcBinaryOperation> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
{
- CalculationCategory leftCategory = leftSide->category();
- CalculationCategory rightCategory = rightSide->category();
- CalculationCategory newCategory = CalcOther;
+ ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther);
- ASSERT(leftCategory != CalcOther && rightCategory != CalcOther);
-
- switch (op) {
- case CalcAdd:
- case CalcSubtract:
- if (leftCategory == CalcOther || rightCategory == CalcOther)
- return 0;
- newCategory = addSubtractResult[leftCategory][rightCategory];
- break;
-
- case CalcMultiply:
- if (leftCategory != CalcNumber && rightCategory != CalcNumber)
- return 0;
-
- newCategory = leftCategory == CalcNumber ? rightCategory : leftCategory;
- break;
-
- case CalcDivide:
- if (rightCategory != CalcNumber || rightSide->isZero())
- return 0;
- newCategory = leftCategory;
- break;
- }
-
+ CalculationCategory newCategory = determineCategory(*leftSide, *rightSide, op);
+
if (newCategory == CalcOther)
return 0;
-
+
return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory));
}
@@ -279,20 +327,37 @@
info.addInstrumentedMember(m_rightSide);
}
- virtual String customCssText() const
+ static String buildCssText(const String& leftExpression, const String& rightExpression, CalcOperator op)
{
StringBuilder result;
result.append('(');
- result.append(m_leftSide->customCssText());
+ result.append(leftExpression);
result.append(' ');
- result.append(static_cast<char>(m_operator));
+ result.append(static_cast<char>(op));
result.append(' ');
- result.append(m_rightSide->customCssText());
+ result.append(rightExpression);
result.append(')');
- return result.toString();
+ return result.toString();
}
+ virtual String customCssText() const
+ {
+ return buildCssText(m_leftSide->customCssText(), m_rightSide->customCssText(), m_operator);
+ }
+
+#if ENABLE(CSS_VARIABLES)
+ virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
+ {
+ return buildCssText(m_leftSide->serializeResolvingVariables(variables), m_rightSide->serializeResolvingVariables(variables), m_operator);
+ }
+
+ virtual bool hasVariableReference() const
+ {
+ return m_leftSide->hasVariableReference() || m_rightSide->hasVariableReference();
+ }
+#endif
+
private:
CSSCalcBinaryOperation(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category)
: CSSCalcExpressionNode(category, leftSide->isInteger() && rightSide->isInteger())
Modified: trunk/Source/WebCore/css/CSSCalculationValue.h (127219 => 127220)
--- trunk/Source/WebCore/css/CSSCalculationValue.h 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/CSSCalculationValue.h 2012-08-31 01:13:50 UTC (rev 127220)
@@ -52,6 +52,9 @@
CalcPercent,
CalcPercentNumber,
CalcPercentLength,
+#if ENABLE(CSS_VARIABLES)
+ CalcVariable,
+#endif
CalcOther
};
@@ -64,6 +67,10 @@
virtual double doubleValue() const = 0;
virtual double computeLengthPx(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const = 0;
virtual String customCssText() const = 0;
+#if ENABLE(CSS_VARIABLES)
+ virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const = 0;
+ virtual bool hasVariableReference() const = 0;
+#endif
virtual void reportMemoryUsage(MemoryObjectInfo*) const = 0;
@@ -97,6 +104,10 @@
double computeLengthPx(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const;
String customCssText() const;
+#if ENABLE(CSS_VARIABLES)
+ String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const;
+ bool hasVariableReference() const;
+#endif
void reportDescendantMemoryUsage(MemoryObjectInfo*) const;
Modified: trunk/Source/WebCore/css/CSSGrammar.y (127219 => 127220)
--- trunk/Source/WebCore/css/CSSGrammar.y 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/CSSGrammar.y 2012-08-31 01:13:50 UTC (rev 127220)
@@ -100,7 +100,7 @@
%}
-%expect 62
+%expect 63
%nonassoc LOWEST_PREC
@@ -1550,6 +1550,13 @@
calc_func_term:
unary_term { $$ = $1; }
+ | VARFUNCTION maybe_space IDENT ')' maybe_space {
+#if ENABLE(CSS_VARIABLES)
+ $$.id = 0;
+ $$.string = $3;
+ $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
+#endif
+ }
| unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
;
Modified: trunk/Source/WebCore/css/CSSParser.cpp (127219 => 127220)
--- trunk/Source/WebCore/css/CSSParser.cpp 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/CSSParser.cpp 2012-08-31 01:13:50 UTC (rev 127220)
@@ -1443,6 +1443,11 @@
case CalcPercentNumber:
b = (unitflags & FPercent) && (unitflags & FNumber);
break;
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+ b = true;
+ break;
+#endif
case CalcOther:
break;
}
Modified: trunk/Source/WebCore/css/CSSPrimitiveValue.cpp (127219 => 127220)
--- trunk/Source/WebCore/css/CSSPrimitiveValue.cpp 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/CSSPrimitiveValue.cpp 2012-08-31 01:13:50 UTC (rev 127220)
@@ -186,6 +186,10 @@
return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER;
case CalcPercentLength:
return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH;
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+ return CSSPrimitiveValue::CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined.
+#endif
case CalcOther:
return CSSPrimitiveValue::CSS_UNKNOWN;
}
@@ -1119,8 +1123,10 @@
#if ENABLE(CSS_VARIABLES)
String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
{
- if (m_primitiveUnitType == CSS_VARIABLE_NAME && variables.contains(m_value.string))
+ if (isVariableName() && variables.contains(m_value.string))
return variables.get(m_value.string);
+ if (isCalculated())
+ return cssCalcValue()->customSerializeResolvingVariables(variables);
return customCssText();
}
#endif
Modified: trunk/Source/WebCore/css/StyleResolver.cpp (127219 => 127220)
--- trunk/Source/WebCore/css/StyleResolver.cpp 2012-08-31 00:43:15 UTC (rev 127219)
+++ trunk/Source/WebCore/css/StyleResolver.cpp 2012-08-31 01:13:50 UTC (rev 127220)
@@ -3361,9 +3361,16 @@
#if ENABLE(CSS_VARIABLES)
static bool hasVariableReference(CSSValue* value)
{
- if (value->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(value)->isVariableName())
- return true;
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (CSSCalcValue* calcValue = primitiveValue->cssCalcValue())
+ return calcValue->hasVariableReference();
+ return primitiveValue->isVariableName();
+ }
+ if (value->isCalculationValue())
+ return static_cast<CSSCalcValue*>(value)->hasVariableReference();
+
for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
if (hasVariableReference(i.value()))
return true;