Changeset 83122 in webkit


Ignore:
Timestamp:
Apr 6, 2011 4:41:51 PM (13 years ago)
Author:
Simon Fraser
Message:

2011-04-06 Ian Henderson <ianh@apple.com>

Reviewed by Simon Fraser, Antti Koivisto.

Fast path for parsing simple CSS values
https://bugs.webkit.org/show_bug.cgi?id=57964

Add functions to parse simple color or dimension values, skipping the
overhead of full CSS parsing.

Change parseValue to a static method to avoid unnecessary allocation
of a CSSParser in the fast case.

  • css/CSSMutableStyleDeclaration.cpp: (WebCore::CSSMutableStyleDeclaration::setProperty): Changed to use the new, static parseValue method.
  • css/CSSParser.cpp: (WebCore::isColorPropertyID): (WebCore::parseColorValue): Parses any color accepted by the existing parseColor() static method. We must handle color identifiers separately, since parseColor() will change 'red' into 'rgb(255, 0, 0)'. (WebCore::isSimpleLengthPropertyID): (WebCore::parseSimpleLengthValue): Parses a value of the form 'NNpx', 'NN%', or 'NN' (when strict is false, or 'NN' is '0'). Returns false to fall back to the slow path. (WebCore::CSSParser::parseValue):
  • css/CSSParser.h:
  • css/WebKitCSSMatrix.cpp: (WebCore::WebKitCSSMatrix::setMatrixValue): Changed to use the new, static parseValue method.
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r83121 r83122  
     12011-04-06  Ian Henderson  <ianh@apple.com>
     2
     3        Reviewed by Simon Fraser, Antti Koivisto.
     4
     5        Fast path for parsing simple CSS values
     6        https://bugs.webkit.org/show_bug.cgi?id=57964
     7
     8        Add functions to parse simple color or dimension values, skipping the
     9        overhead of full CSS parsing.
     10
     11        Change parseValue to a static method to avoid unnecessary allocation
     12        of a CSSParser in the fast case.
     13
     14        * css/CSSMutableStyleDeclaration.cpp:
     15        (WebCore::CSSMutableStyleDeclaration::setProperty):
     16        Changed to use the new, static parseValue method.
     17        * css/CSSParser.cpp:
     18        (WebCore::isColorPropertyID):
     19        (WebCore::parseColorValue):
     20        Parses any color accepted by the existing parseColor() static method.
     21        We must handle color identifiers separately, since parseColor() will
     22        change 'red' into 'rgb(255, 0, 0)'.
     23        (WebCore::isSimpleLengthPropertyID):
     24        (WebCore::parseSimpleLengthValue):
     25        Parses a value of the form 'NNpx', 'NN%', or 'NN' (when strict is
     26        false, or 'NN' is '0').  Returns false to fall back to the slow path.
     27        (WebCore::CSSParser::parseValue):
     28        * css/CSSParser.h:
     29        * css/WebKitCSSMatrix.cpp:
     30        (WebCore::WebKitCSSMatrix::setMatrixValue):
     31        Changed to use the new, static parseValue method.
     32
    1332011-04-06  Kevin Ollivier  <kevino@theolliviers.com>
    234
  • trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp

    r82899 r83122  
    572572    // When replacing an existing property value, this moves the property to the end of the list.
    573573    // Firefox preserves the position, and MSIE moves the property to the beginning.
    574     CSSParser parser(useStrictParsing());
    575     bool success = parser.parseValue(this, propertyID, value, important);
     574    bool success = CSSParser::parseValue(this, propertyID, value, important, useStrictParsing());
    576575    if (!success) {
    577576        // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
  • trunk/Source/WebCore/css/CSSParser.cpp

    r82545 r83122  
    260260}
    261261
    262 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int id, const String& string, bool important)
     262static inline bool isColorPropertyID(int propertyId)
     263{
     264    switch (propertyId) {
     265    case CSSPropertyColor:
     266    case CSSPropertyBackgroundColor:
     267    case CSSPropertyBorderBottomColor:
     268    case CSSPropertyBorderLeftColor:
     269    case CSSPropertyBorderRightColor:
     270    case CSSPropertyBorderTopColor:
     271    case CSSPropertyOutlineColor:
     272    case CSSPropertyTextLineThroughColor:
     273    case CSSPropertyTextOverlineColor:
     274    case CSSPropertyTextUnderlineColor:
     275    case CSSPropertyWebkitBorderAfterColor:
     276    case CSSPropertyWebkitBorderBeforeColor:
     277    case CSSPropertyWebkitBorderEndColor:
     278    case CSSPropertyWebkitBorderStartColor:
     279    case CSSPropertyWebkitColumnRuleColor:
     280    case CSSPropertyWebkitTextEmphasisColor:
     281    case CSSPropertyWebkitTextFillColor:
     282    case CSSPropertyWebkitTextStrokeColor:
     283        return true;
     284    default:
     285        return false;
     286    }
     287}
     288
     289static bool parseColorValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
     290{
     291    if (!string.length())
     292        return false;
     293    if (!isColorPropertyID(propertyId))
     294        return false;
     295    CSSParserString cssString;
     296    cssString.characters = const_cast<UChar*>(string.characters());
     297    cssString.length = string.length();
     298    int valueID = cssValueKeywordID(cssString);
     299    bool validPrimitive = false;
     300    if (valueID == CSSValueWebkitText)
     301        validPrimitive = true;
     302    else if (valueID == CSSValueCurrentcolor)
     303        validPrimitive = true;
     304    else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
     305             || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
     306        validPrimitive = true;
     307    }
     308
     309    CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
     310    if (!stylesheet || !stylesheet->document())
     311        return false;
     312    if (validPrimitive) {
     313        CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createIdentifierValue(valueID), important);
     314        declaration->addParsedProperty(property);
     315        return true;
     316    }
     317    RGBA32 color;
     318    if (!CSSParser::parseColor(string, color, strict && string[0] != '#'))
     319        return false;
     320    CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createColorValue(color), important);
     321    declaration->addParsedProperty(property);
     322    return true;
     323}
     324
     325static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers)
     326{
     327    switch (propertyId) {
     328    case CSSPropertyFontSize:
     329    case CSSPropertyHeight:
     330    case CSSPropertyWidth:
     331    case CSSPropertyMinHeight:
     332    case CSSPropertyMinWidth:
     333    case CSSPropertyPaddingBottom:
     334    case CSSPropertyPaddingLeft:
     335    case CSSPropertyPaddingRight:
     336    case CSSPropertyPaddingTop:
     337    case CSSPropertyWebkitLogicalWidth:
     338    case CSSPropertyWebkitLogicalHeight:
     339    case CSSPropertyWebkitMinLogicalWidth:
     340    case CSSPropertyWebkitMinLogicalHeight:
     341    case CSSPropertyWebkitPaddingAfter:
     342    case CSSPropertyWebkitPaddingBefore:
     343    case CSSPropertyWebkitPaddingEnd:
     344    case CSSPropertyWebkitPaddingStart:
     345        acceptsNegativeNumbers = false;
     346        return true;
     347    case CSSPropertyBottom:
     348    case CSSPropertyLeft:
     349    case CSSPropertyMarginBottom:
     350    case CSSPropertyMarginLeft:
     351    case CSSPropertyMarginRight:
     352    case CSSPropertyMarginTop:
     353    case CSSPropertyRight:
     354    case CSSPropertyTextIndent:
     355    case CSSPropertyTop:
     356    case CSSPropertyWebkitMarginAfter:
     357    case CSSPropertyWebkitMarginBefore:
     358    case CSSPropertyWebkitMarginEnd:
     359    case CSSPropertyWebkitMarginStart:
     360        acceptsNegativeNumbers = true;
     361        return true;
     362    default:
     363        return false;
     364    }
     365}
     366
     367static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
     368{
     369    const UChar* characters = string.characters();
     370    unsigned length = string.length();
     371    if (!characters || !length)
     372        return false;
     373    bool acceptsNegativeNumbers;
     374    if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
     375        return false;
     376
     377    CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
     378    if (length > 2 && characters[length - 2] == 'p' && characters[length - 1] == 'x') {
     379        length -= 2;
     380        unit = CSSPrimitiveValue::CSS_PX;
     381    } else if (length > 1 && characters[length - 1] == '%') {
     382        length -= 1;
     383        unit = CSSPrimitiveValue::CSS_PERCENTAGE;
     384    }
     385
     386    // We rely on charactersToDouble for validation as well. The function
     387    // will set "ok" to "false" if the entire passed-in character range does
     388    // not represent a double.
     389    bool ok;
     390    double number = charactersToDouble(characters, length, &ok);
     391    if (!ok)
     392        return false;
     393    if (unit == CSSPrimitiveValue::CSS_NUMBER) {
     394        if (number && strict)
     395            return false;
     396        unit = CSSPrimitiveValue::CSS_PX;
     397    }
     398    if (number < 0 && !acceptsNegativeNumbers)
     399        return false;
     400
     401    CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
     402    if (!stylesheet || !stylesheet->document())
     403        return false;
     404    CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createValue(number, unit), important);
     405    declaration->addParsedProperty(property);
     406    return true;
     407}
     408
     409bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
     410{
     411    if (parseSimpleLengthValue(declaration, propertyId, string, important, strict))
     412        return true;
     413    if (parseColorValue(declaration, propertyId, string, important, strict))
     414        return true;
     415    CSSParser parser(strict);
     416    return parser.parseValue(declaration, propertyId, string, important);
     417}
     418
     419bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important)
    263420{
    264421    ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
     
    267424    setupParser("@-webkit-value{", string, "} ");
    268425
    269     m_id = id;
     426    m_id = propertyId;
    270427    m_important = important;
    271428
  • trunk/Source/WebCore/css/CSSParser.h

    r82545 r83122  
    6464        PassRefPtr<CSSRule> parseRule(CSSStyleSheet*, const String&);
    6565        PassRefPtr<CSSRule> parseKeyframeRule(CSSStyleSheet*, const String&);
    66         bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important);
     66        static bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important, bool strict);
    6767        static bool parseColor(RGBA32& color, const String&, bool strict = false);
    6868        static bool parseSystemColor(RGBA32& color, const String&, Document*);
     
    292292        bool parseGeneratedImage(RefPtr<CSSValue>&);
    293293
     294        bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important);
     295
    294296        enum SizeParameterType {
    295297            None,
  • trunk/Source/WebCore/css/WebKitCSSMatrix.cpp

    r76537 r83122  
    5353void WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec)
    5454{
    55     CSSParser p(true);
    5655    RefPtr<CSSMutableStyleDeclaration> styleDeclaration = CSSMutableStyleDeclaration::create();
    57     if (p.parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true)) {
     56    if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, true)) {
    5857        // Convert to TransformOperations. This can fail if a property
    5958        // requires style (i.e., param uses 'ems' or 'exs')
Note: See TracChangeset for help on using the changeset viewer.