Changeset 127220 in webkit


Ignore:
Timestamp:
Aug 30, 2012 6:13:50 PM (12 years ago)
Author:
macpherson@chromium.org
Message:

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):

Location:
trunk
Files:
10 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r127217 r127220  
     12012-08-30  Luke Macpherson   <macpherson@chromium.org>
     2
     3        Make it possible to use CSS Variables inside Calc expressions.
     4        https://bugs.webkit.org/show_bug.cgi?id=95284
     5
     6        Reviewed by Tony Chang.
     7
     8        Allows calc expressions to contain unevaluated variables, which are then resolved in StyleResolver.cpp when building the RenderStyle tree.
     9
     10        Tests:
     11        fast/css/variables/calc.html
     12
     13        * css/CSSCalculationValue.cpp:
     14        (WebCore::unitCategory):
     15        (WebCore):
     16        (WebCore::CSSCalcValue::customSerializeResolvingVariables):
     17        Generates a CSS expression with variables resolved into their corresponding values.
     18        (WebCore::CSSCalcValue::hasVariableReference):
     19        Returns true if the calculation's expression tree refers to a variable (that needs to be resolved).
     20        (CSSCalcPrimitiveValue):
     21        (WebCore::CSSCalcPrimitiveValue::serializeResolvingVariables):
     22        Resolves the variable using the underlying CSSPrimitiveValue's serializeResolvingVariables function.
     23        (WebCore::CSSCalcPrimitiveValue::hasVariableReference):
     24        (WebCore::CSSCalcPrimitiveValue::toCalcValue):
     25        (WebCore::CSSCalcPrimitiveValue::doubleValue):
     26        (WebCore::CSSCalcPrimitiveValue::computeLengthPx):
     27        (WebCore::CSSCalcBinaryOperation::create):
     28        (CSSCalcBinaryOperation):
     29        (WebCore::CSSCalcBinaryOperation::serializeResolvingVariables):
     30        Builds a CSS expression for contained subtrees.
     31        (WebCore::CSSCalcBinaryOperation::hasVariableReference):
     32        Returns true if either subtree contains a variable.
     33        * css/CSSCalculationValue.h:
     34        (CSSCalcExpressionNode):
     35        (CSSCalcValue):
     36        * css/CSSGrammar.y:
     37        * css/CSSParser.cpp:
     38        (WebCore::CSSParser::validCalculationUnit):
     39        * css/CSSPrimitiveValue.cpp:
     40        (WebCore::CSSPrimitiveValue::primitiveType):
     41        (WebCore::CSSPrimitiveValue::customSerializeResolvingVariables):
     42        * css/StyleResolver.cpp:
     43        (WebCore::StyleResolver::collectMatchingRulesForList):
     44
    1452012-08-30  Max Vujovic  <mvujovic@adobe.com>
    246
  • trunk/Source/WebCore/css/CSSCalculationValue.cpp

    r124884 r127220  
    6969    case CSSPrimitiveValue::CSS_REMS:
    7070        return CalcLength;
     71#if ENABLE(CSS_VARIABLES)
     72    case CSSPrimitiveValue::CSS_VARIABLE_NAME:
     73        return CalcVariable;
     74#endif
    7175    default:
    7276        return CalcOther;
    7377    }
    7478}
    75    
    76 String CSSCalcValue::customCssText() const
     79
     80static String buildCssText(const String& expression)
    7781{
    7882    StringBuilder result;
    79    
    8083    result.append("-webkit-calc");
    81     String expression = m_expression->customCssText();
    8284    bool expressionHasSingleTerm = expression[0] != '(';
    8385    if (expressionHasSingleTerm)
     
    8991}
    9092
     93String CSSCalcValue::customCssText() const
     94{
     95    return buildCssText(m_expression->customCssText());
     96}
     97
     98#if ENABLE(CSS_VARIABLES)
     99String CSSCalcValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
     100{
     101    return buildCssText(m_expression->serializeResolvingVariables(variables));
     102}
     103
     104bool CSSCalcValue::hasVariableReference() const
     105{
     106    return m_expression->hasVariableReference();
     107}
     108#endif
     109
    91110void CSSCalcValue::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    92111{
     
    130149        return m_value->cssText();
    131150    }
     151
     152#if ENABLE(CSS_VARIABLES)
     153    virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
     154    {
     155        return m_value->customSerializeResolvingVariables(variables);
     156    }
     157   
     158    virtual bool hasVariableReference() const
     159    {
     160        return m_value->isVariableName();
     161    }
     162#endif
    132163
    133164    virtual PassOwnPtr<CalcExpressionNode> toCalcValue(RenderStyle* style, RenderStyle* rootStyle, double zoom) const
     
    144175        // to a CalcExpressionNode. CalcPercentNumber makes no sense as a Length.
    145176        case CalcPercentNumber:
     177#if ENABLE(CSS_VARIABLES)
     178        case CalcVariable:
     179#endif
    146180        case CalcOther:
    147181            ASSERT_NOT_REACHED();
     
    159193        case CalcPercentLength:
    160194        case CalcPercentNumber:
     195#if ENABLE(CSS_VARIABLES)
     196        case CalcVariable:
     197#endif
    161198        case CalcOther:
    162199            ASSERT_NOT_REACHED();
     
    176213        case CalcPercentLength:
    177214        case CalcPercentNumber:
     215#if ENABLE(CSS_VARIABLES)
     216        case CalcVariable:
     217#endif
    178218        case CalcOther:
    179219            ASSERT_NOT_REACHED();
     
    192232    explicit CSSCalcPrimitiveValue(CSSPrimitiveValue* value, bool isInteger)
    193233        : CSSCalcExpressionNode(unitCategory((CSSPrimitiveValue::UnitTypes)value->primitiveType()), isInteger)
    194         , m_value(value)                 
     234        , m_value(value)
    195235    {
    196236    }
     
    206246    { CalcOther,         CalcPercentLength, CalcPercentLength, CalcOther,         CalcPercentLength },
    207247};   
    208    
     248
     249static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSide, const CSSCalcExpressionNode& rightSide, CalcOperator op)
     250{
     251    CalculationCategory leftCategory = leftSide.category();
     252    CalculationCategory rightCategory = rightSide.category();
     253
     254    if (leftCategory == CalcOther || rightCategory == CalcOther)
     255        return CalcOther;
     256
     257#if ENABLE(CSS_VARIABLES)
     258    if (leftCategory == CalcVariable || rightCategory == CalcVariable)
     259        return CalcVariable;
     260#endif
     261
     262    switch (op) {
     263    case CalcAdd:
     264    case CalcSubtract:             
     265        return addSubtractResult[leftCategory][rightCategory];
     266    case CalcMultiply:
     267        if (leftCategory != CalcNumber && rightCategory != CalcNumber)
     268            return CalcOther;
     269        return leftCategory == CalcNumber ? rightCategory : leftCategory;
     270    case CalcDivide:
     271        if (rightCategory != CalcNumber || rightSide.isZero())
     272            return CalcOther;
     273        return leftCategory;
     274    }
     275   
     276    ASSERT_NOT_REACHED();
     277    return CalcOther;
     278}
     279
    209280class CSSCalcBinaryOperation : public CSSCalcExpressionNode {
     281
    210282public:
    211283    static PassRefPtr<CSSCalcBinaryOperation> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
    212284    {
    213         CalculationCategory leftCategory = leftSide->category();
    214         CalculationCategory rightCategory = rightSide->category();
    215         CalculationCategory newCategory = CalcOther;
     285        ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther);
    216286       
    217         ASSERT(leftCategory != CalcOther && rightCategory != CalcOther);
    218        
    219         switch (op) {
    220         case CalcAdd:
    221         case CalcSubtract:             
    222             if (leftCategory == CalcOther || rightCategory == CalcOther)
    223                 return 0;
    224             newCategory = addSubtractResult[leftCategory][rightCategory];
    225             break;   
    226                
    227         case CalcMultiply:
    228             if (leftCategory != CalcNumber && rightCategory != CalcNumber)
    229                 return 0;
    230            
    231             newCategory = leftCategory == CalcNumber ? rightCategory : leftCategory;
    232             break;
    233                
    234         case CalcDivide:
    235             if (rightCategory != CalcNumber || rightSide->isZero())
    236                 return 0;
    237             newCategory = leftCategory;
    238             break;
    239         }
    240        
     287        CalculationCategory newCategory = determineCategory(*leftSide, *rightSide, op);
     288
    241289        if (newCategory == CalcOther)
    242290            return 0;
    243            
     291
    244292        return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory));
    245293    }
     
    280328    }
    281329
    282     virtual String customCssText() const
     330    static String buildCssText(const String& leftExpression, const String& rightExpression, CalcOperator op)
    283331    {
    284332        StringBuilder result;
    285333        result.append('(');
    286         result.append(m_leftSide->customCssText());
     334        result.append(leftExpression);
    287335        result.append(' ');
    288         result.append(static_cast<char>(m_operator));
     336        result.append(static_cast<char>(op));
    289337        result.append(' ');
    290         result.append(m_rightSide->customCssText());
     338        result.append(rightExpression);
    291339        result.append(')');
    292340   
    293         return result.toString();   
    294     }
     341        return result.toString(); 
     342    }
     343
     344    virtual String customCssText() const
     345    {
     346        return buildCssText(m_leftSide->customCssText(), m_rightSide->customCssText(), m_operator);
     347    }
     348
     349#if ENABLE(CSS_VARIABLES)
     350    virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
     351    {
     352        return buildCssText(m_leftSide->serializeResolvingVariables(variables), m_rightSide->serializeResolvingVariables(variables), m_operator);
     353    }
     354
     355    virtual bool hasVariableReference() const
     356    {
     357        return m_leftSide->hasVariableReference() || m_rightSide->hasVariableReference();
     358    }
     359#endif
    295360
    296361private:
  • trunk/Source/WebCore/css/CSSCalculationValue.h

    r124768 r127220  
    5353    CalcPercentNumber,
    5454    CalcPercentLength,
     55#if ENABLE(CSS_VARIABLES)
     56    CalcVariable,
     57#endif
    5558    CalcOther
    5659};
     
    6568    virtual double computeLengthPx(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const = 0;
    6669    virtual String customCssText() const = 0;
     70#if ENABLE(CSS_VARIABLES)
     71    virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const = 0;
     72    virtual bool hasVariableReference() const = 0;
     73#endif
    6774
    6875    virtual void reportMemoryUsage(MemoryObjectInfo*) const = 0;
     
    98105       
    99106    String customCssText() const;
     107#if ENABLE(CSS_VARIABLES)
     108    String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const;
     109    bool hasVariableReference() const;
     110#endif
    100111
    101112    void reportDescendantMemoryUsage(MemoryObjectInfo*) const;
  • trunk/Source/WebCore/css/CSSGrammar.y

    r125252 r127220  
    101101%}
    102102
    103 %expect 62
     103%expect 63
    104104
    105105%nonassoc LOWEST_PREC
     
    15511551calc_func_term:
    15521552  unary_term { $$ = $1; }
     1553  | VARFUNCTION maybe_space IDENT ')' maybe_space {
     1554#if ENABLE(CSS_VARIABLES)
     1555      $$.id = 0;
     1556      $$.string = $3;
     1557      $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
     1558#endif
     1559  }
    15531560  | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
    15541561  ;
  • trunk/Source/WebCore/css/CSSParser.cpp

    r127155 r127220  
    14441444        b = (unitflags & FPercent) && (unitflags & FNumber);
    14451445        break;
     1446#if ENABLE(CSS_VARIABLES)
     1447    case CalcVariable:
     1448        b = true;
     1449        break;
     1450#endif
    14461451    case CalcOther:
    14471452        break;
  • trunk/Source/WebCore/css/CSSPrimitiveValue.cpp

    r127155 r127220  
    187187    case CalcPercentLength:
    188188        return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH;
     189#if ENABLE(CSS_VARIABLES)
     190    case CalcVariable:
     191        return CSSPrimitiveValue::CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined.
     192#endif
    189193    case CalcOther:
    190194        return CSSPrimitiveValue::CSS_UNKNOWN;
     
    11201124String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
    11211125{
    1122     if (m_primitiveUnitType == CSS_VARIABLE_NAME && variables.contains(m_value.string))
     1126    if (isVariableName() && variables.contains(m_value.string))
    11231127        return variables.get(m_value.string);
     1128    if (isCalculated())
     1129        return cssCalcValue()->customSerializeResolvingVariables(variables);
    11241130    return customCssText();
    11251131}
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r127162 r127220  
    33623362static bool hasVariableReference(CSSValue* value)
    33633363{
    3364     if (value->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(value)->isVariableName())
    3365         return true;
     3364    if (value->isPrimitiveValue()) {
     3365        CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
     3366        if (CSSCalcValue* calcValue = primitiveValue->cssCalcValue())
     3367            return calcValue->hasVariableReference();
     3368        return primitiveValue->isVariableName();
     3369    }
     3370
     3371    if (value->isCalculationValue())
     3372        return static_cast<CSSCalcValue*>(value)->hasVariableReference();
    33663373
    33673374    for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
Note: See TracChangeset for help on using the changeset viewer.