Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  *
     11  * This library is free software; you can redistribute it and/or
     12  * modify it under the terms of the GNU Library General Public
     13  * License as published by the Free Software Foundation; either
     14  * version 2 of the License, or (at your option) any later version.
     15  *
     16  * This library is distributed in the hope that it will be useful,
     17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19  * Library General Public License for more details.
     20  *
     21  * You should have received a copy of the GNU Library General Public License
     22  * along with this library; see the file COPYING.LIB.  If not, write to
     23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     24  * Boston, MA 02110-1301, USA.
     25  */
     26 
     27 #include "config.h"
     28 #include "CSSStyleSelector.h"
     29 
     30 #include "Attribute.h"
     31 #include "ContentData.h"
     32 #include "CounterContent.h"
     33 #include "CursorList.h"
     34 #include "CSSBorderImageValue.h"
     35 #include "CSSCursorImageValue.h"
     36 #include "CSSFontFaceRule.h"
     37 #include "CSSImportRule.h"
     38 #include "CSSLineBoxContainValue.h"
     39 #include "CSSMediaRule.h"
     40 #include "CSSPageRule.h"
     41 #include "CSSParser.h"
     42 #include "CSSPrimitiveValueMappings.h"
     43 #include "CSSPropertyNames.h"
     44 #include "CSSReflectValue.h"
     45 #include "CSSRuleList.h"
     46 #include "CSSSelector.h"
     47 #include "CSSSelectorList.h"
     48 #include "CSSStyleApplyProperty.h"
     49 #include "CSSStyleRule.h"
     50 #include "CSSStyleSheet.h"
     51 #include "CSSTimingFunctionValue.h"
     52 #include "CSSValueList.h"
     53 #include "CachedImage.h"
     54 #include "Counter.h"
     55 #include "FocusController.h"
     56 #include "FontFamilyValue.h"
     57 #include "FontValue.h"
     58 #include "Frame.h"
     59 #include "FrameView.h"
     60 #include "HTMLDocument.h"
     61 #include "HTMLElement.h"
     62 #include "HTMLInputElement.h"
     63 #include "HTMLNames.h"
     64 #include "HTMLTextAreaElement.h"
     65 #include "KeyframeList.h"
     66 #include "LinkHash.h"
     67 #include "Matrix3DTransformOperation.h"
     68 #include "MatrixTransformOperation.h"
     69 #include "MediaList.h"
     70 #include "MediaQueryEvaluator.h"
     71 #include "NodeRenderStyle.h"
     72 #include "Page.h"
     73 #include "PageGroup.h"
     74 #include "Pair.h"
     75 #include "PerspectiveTransformOperation.h"
     76 #include "QuotesData.h"
     77 #include "Rect.h"
     78 #include "RenderScrollbar.h"
     79 #include "RenderScrollbarTheme.h"
     80 #include "RenderStyleConstants.h"
     81 #include "RenderTheme.h"
     82 #include "RotateTransformOperation.h"
     83 #include "ScaleTransformOperation.h"
     84 #include "SelectionController.h"
     85 #include "Settings.h"
     86 #include "ShadowData.h"
     87 #include "ShadowValue.h"
     88 #include "SkewTransformOperation.h"
     89 #include "StyleCachedImage.h"
     90 #include "StylePendingImage.h"
     91 #include "StyleGeneratedImage.h"
     92 #include "StyleSheetList.h"
     93 #include "Text.h"
     94 #include "TransformationMatrix.h"
     95 #include "TranslateTransformOperation.h"
     96 #include "UserAgentStyleSheets.h"
     97 #include "WebKitCSSKeyframeRule.h"
     98 #include "WebKitCSSKeyframesRule.h"
     99 #include "WebKitCSSTransformValue.h"
    100 #include "XMLNames.h"
    101 #include <wtf/StdLibExtras.h>
    102 #include <wtf/Vector.h>
    103 
    104 #if USE(PLATFORM_STRATEGIES)
    105 #include "PlatformStrategies.h"
    106 #include "VisitedLinkStrategy.h"
    107 #endif
    108 
    109 #if ENABLE(DASHBOARD_SUPPORT)
    110 #include "DashboardRegion.h"
    111 #endif
    112 
    113 #if ENABLE(SVG)
    114 #include "XLinkNames.h"
    115 #include "SVGNames.h"
    116 #endif
    117 
    118 #if ENABLE(WML)
    119 #include "WMLNames.h"
    120 #endif
    121 
    122 #if PLATFORM(QT)
    123 #include <qwebhistoryinterface.h>
    124 #endif
    125 
    126 using namespace std;
    127 
    128 namespace WebCore {
    129 
    130 using namespace HTMLNames;
    131 
    132 #define HANDLE_INHERIT(prop, Prop) \
    133 if (isInherit) { \
    134     m_style->set##Prop(m_parentStyle->prop()); \
    135     return; \
    136 }
    137 
    138 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
    139 HANDLE_INHERIT(prop, Prop) \
    140 if (isInitial) { \
    141     m_style->set##Prop(RenderStyle::initial##Prop()); \
    142     return; \
    143 }
    144 
    145 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
    146 HANDLE_INHERIT(prop, Prop) \
    147 if (isInitial) { \
    148     m_style->set##Prop(RenderStyle::initial##Value());\
    149     return;\
    150 }
    151 
    152 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
    153 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
    154 if (primitiveValue) \
    155     m_style->set##Prop(*primitiveValue);
    156 
    157 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
    158 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
    159 if (primitiveValue) \
    160     m_style->set##Prop(*primitiveValue);
    161 
    162 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
    163 if (isInherit) { \
    164     AnimationList* list = m_style->accessAnimations(); \
    165     const AnimationList* parentList = m_parentStyle->animations(); \
    166     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
    167     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
    168         if (list->size() <= i) \
    169             list->append(Animation::create()); \
    170         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
    171     } \
    172     \
    173     /* Reset any remaining animations to not have the property set. */ \
    174     for ( ; i < list->size(); ++i) \
    175         list->animation(i)->clear##Prop(); \
    176 } else if (isInitial) { \
    177     AnimationList* list = m_style->accessAnimations(); \
    178     if (list->isEmpty()) \
    179         list->append(Animation::create()); \
    180     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
    181     for (size_t i = 1; i < list->size(); ++i) \
    182         list->animation(0)->clear##Prop(); \
    183 }
    184 
    185 #define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \
    186 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
    187 if (isInherit || isInitial) \
    188     return; \
    189 AnimationList* list = m_style->accessAnimations(); \
    190 size_t childIndex = 0; \
    191 if (value->isValueList()) { \
    192     /* Walk each value and put it into an animation, creating new animations as needed. */ \
    193     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
    194     for (unsigned int i = 0; i < valueList->length(); i++) { \
    195         if (childIndex <= list->size()) \
    196             list->append(Animation::create()); \
    197         mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
    198         ++childIndex; \
    199     } \
    200 } else { \
    201     if (list->isEmpty()) \
    202         list->append(Animation::create()); \
    203     mapAnimation##Prop(list->animation(childIndex), value); \
    204     childIndex = 1; \
    205 } \
    206 for ( ; childIndex < list->size(); ++childIndex) { \
    207     /* Reset all remaining animations to not have the property set. */ \
    208     list->animation(childIndex)->clear##Prop(); \
    209 } \
    210 }
    211 
    212 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
    213 if (isInherit) { \
    214     AnimationList* list = m_style->accessTransitions(); \
    215     const AnimationList* parentList = m_parentStyle->transitions(); \
    216     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
    217     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
    218         if (list->size() <= i) \
    219             list->append(Animation::create()); \
    220         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
    221     } \
    222     \
    223     /* Reset any remaining transitions to not have the property set. */ \
    224     for ( ; i < list->size(); ++i) \
    225         list->animation(i)->clear##Prop(); \
    226 } else if (isInitial) { \
    227     AnimationList* list = m_style->accessTransitions(); \
    228     if (list->isEmpty()) \
    229         list->append(Animation::create()); \
    230     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
    231     for (size_t i = 1; i < list->size(); ++i) \
    232         list->animation(0)->clear##Prop(); \
    233 }
    234 
    235 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
    236 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
    237 if (isInherit || isInitial) \
    238     return; \
    239 AnimationList* list = m_style->accessTransitions(); \
    240 size_t childIndex = 0; \
    241 if (value->isValueList()) { \
    242     /* Walk each value and put it into a transition, creating new animations as needed. */ \
    243     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
    244     for (unsigned int i = 0; i < valueList->length(); i++) { \
    245         if (childIndex <= list->size()) \
    246             list->append(Animation::create()); \
    247         mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
    248         ++childIndex; \
    249     } \
    250 } else { \
    251     if (list->isEmpty()) \
    252         list->append(Animation::create()); \
    253     mapAnimation##Prop(list->animation(childIndex), value); \
    254     childIndex = 1; \
    255 } \
    256 for ( ; childIndex < list->size(); ++childIndex) { \
    257     /* Reset all remaining transitions to not have the property set. */ \
    258     list->animation(childIndex)->clear##Prop(); \
    259 } \
    260 }
    261 
    262 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
    263 if (id == propID) { \
    264     m_style->set##Prop(m_parentStyle->prop()); \
    265     return; \
    266 }
    267 
    268 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
    269 if (id == propID) { \
    270     if (m_parentStyle->prop().isValid()) \
    271         m_style->set##Prop(m_parentStyle->prop()); \
    272     else \
    273         m_style->set##Prop(m_parentStyle->propAlt()); \
    274     return; \
    275 }
    276 
    277 #define HANDLE_INITIAL_COND(propID, Prop) \
    278 if (id == propID) { \
    279     m_style->set##Prop(RenderStyle::initial##Prop()); \
    280     return; \
    281 }
    282 
    283 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
    284 if (id == propID) { \
    285     m_style->set##Prop(RenderStyle::initial##Value()); \
    286     return; \
    287 }
    288 
    289 class RuleData {
    290 public:
    291     RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
    292 
    293     unsigned position() const { return m_position; }
    294     CSSStyleRule* rule() const { return m_rule; }
    295     CSSSelector* selector() const { return m_selector; }
    296 
    297     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
    298     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
    299     bool hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; }
    300     unsigned specificity() const { return m_specificity; }
    301 
    302     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
    303     static const unsigned maximumIdentifierCount = 4;
    304     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
    305 
    306 private:
    307     void collectDescendantSelectorIdentifierHashes();
    308     void collectIdentifierHashes(const CSSSelector*, unsigned& identifierCount);
    309 
    310     CSSStyleRule* m_rule;
    311     CSSSelector* m_selector;
    312     unsigned m_specificity;
    313     unsigned m_position : 29;
    314     bool m_hasFastCheckableSelector : 1;
    315     bool m_hasMultipartSelector : 1;
    316     bool m_hasTopSelectorMatchingHTMLBasedOnRuleHash : 1;
    317     // Use plain array instead of a Vector to minimize memory overhead.
    318     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
    319 };
    320 
    321 class RuleSet {
    322     WTF_MAKE_NONCOPYABLE(RuleSet);
    323 public:
    324     RuleSet();
    325     ~RuleSet();
    326 
    327     typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap;
    328 
    329     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
    330 
    331     void addStyleRule(CSSStyleRule* item);
    332     void addRule(CSSStyleRule* rule, CSSSelector* sel);
    333     void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
    334     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
    335                       CSSStyleRule* rule, CSSSelector* sel);
    336     void shrinkToFit();
    337     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
    338 
    339     void collectFeatures(CSSStyleSelector::Features&) const;
    340 
    341     const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
    342     const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
    343     const Vector<RuleData>* getTagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
    344     const Vector<RuleData>* getPseudoRules(AtomicStringImpl* key) const { return m_pseudoRules.get(key); }
    345     const Vector<RuleData>* getUniversalRules() const { return &m_universalRules; }
    346     const Vector<RuleData>* getPageRules() const { return &m_pageRules; }
    347 
    348 public:
    349     AtomRuleMap m_idRules;
    350     AtomRuleMap m_classRules;
    351     AtomRuleMap m_tagRules;
    352     AtomRuleMap m_pseudoRules;
    353     Vector<RuleData> m_universalRules;
    354     Vector<RuleData> m_pageRules;
    355     unsigned m_ruleCount;
    356     bool m_autoShrinkToFitEnabled;
    357 };
    358 
    359 static RuleSet* defaultStyle;
    360 static RuleSet* defaultQuirksStyle;
    361 static RuleSet* defaultPrintStyle;
    362 static RuleSet* defaultViewSourceStyle;
    363 static CSSStyleSheet* simpleDefaultStyleSheet;
    364 
    365 static RuleSet* siblingRulesInDefaultStyle;
    366 
    367 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
    368 
    369 static void loadFullDefaultStyle();
    370 static void loadSimpleDefaultStyle();
    371 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
    372 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
    373 
    374 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
    375 {
    376     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
    377 }
    378 
    379 static inline void collectSiblingRulesInDefaultStyle()
    380 {
    381     CSSStyleSelector::Features features;
    382     defaultStyle->collectFeatures(features);
    383     ASSERT(features.idsInRules.isEmpty());
    384     delete siblingRulesInDefaultStyle;
    385     siblingRulesInDefaultStyle = features.siblingRules.leakPtr();
    386 }
    387 
    388 static inline void assertNoSiblingRulesInDefaultStyle()
    389 {
    390 #ifndef NDEBUG
    391     if (siblingRulesInDefaultStyle)
    392         return;
    393     collectSiblingRulesInDefaultStyle();
    394     ASSERT(!siblingRulesInDefaultStyle);
    395 #endif
    396 }
    397 
    398 static const MediaQueryEvaluator& screenEval()
    399 {
    400     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
    401     return staticScreenEval;
    402 }
    403 
    404 static const MediaQueryEvaluator& printEval()
    405 {
    406     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
    407     return staticPrintEval;
    408 }
    409 
    410 static CSSMutableStyleDeclaration* leftToRightDeclaration()
    411 {
    412     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
    413     if (!leftToRightDecl->length()) {
    414         leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false);
    415         leftToRightDecl->setStrictParsing(false);
    416     }
    417     return leftToRightDecl.get();
    418 }
    419 
    420 static CSSMutableStyleDeclaration* rightToLeftDeclaration()
    421 {
    422     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create()));
    423     if (!rightToLeftDecl->length()) {
    424         rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false);
    425         rightToLeftDecl->setStrictParsing(false);
    426     }
    427     return rightToLeftDecl.get();
    428 }
    429 
    430 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
    431                                    CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
    432                                    bool strictParsing, bool matchAuthorAndUserStyles)
    433     : m_backgroundData(BackgroundFillLayer)
    434     , m_checker(document, strictParsing)
    435     , m_element(0)
    436     , m_styledElement(0)
    437     , m_elementLinkState(NotInsideLink)
    438     , m_fontSelector(CSSFontSelector::create(document))
    439     , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
    440 {
    441     m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
    442 
    443     Element* root = document->documentElement();
    444 
    445     if (!defaultStyle) {
    446         if (!root || elementCanUseSimpleDefaultStyle(root))
    447             loadSimpleDefaultStyle();
    448         else {
    449             loadFullDefaultStyle();
    450         }
    451     }
    452 
    453     // construct document root element default style. this is needed
    454     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
    455     // This is here instead of constructor, because when constructor is run,
    456     // document doesn't have documentElement
    457     // NOTE: this assumes that element that gets passed to styleForElement -call
    458     // is always from the document that owns the style selector
    459     FrameView* view = document->view();
    460     if (view)
    461         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
    462     else
    463         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
    464 
    465     if (root)
    466         m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
    467 
    468     if (m_rootDefaultStyle && view)
    469         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
    470 
    471     m_authorStyle = adoptPtr(new RuleSet);
    472     // Adding rules from multiple sheets, shrink at the end.
    473     m_authorStyle->disableAutoShrinkToFit();
    474 
    475     // FIXME: This sucks! The user sheet is reparsed every time!
    476     OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
    477     if (pageUserSheet)
    478         tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
    479     if (pageGroupUserSheets) {
    480         unsigned length = pageGroupUserSheets->size();
    481         for (unsigned i = 0; i < length; i++) {
    482             if (pageGroupUserSheets->at(i)->isUserStyleSheet())
    483                 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
    484             else
    485                 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
    486         }
    487     }
    488 
    489     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
    490         m_userStyle = tempUserStyle.release();
    491 
    492     // Add rules from elements like SVG's <font-face>
    493     if (mappedElementSheet)
    494         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
    495 
    496     // add stylesheets from document
    497     unsigned length = styleSheets->length();
    498     for (unsigned i = 0; i < length; i++) {
    499         StyleSheet* sheet = styleSheets->item(i);
    500         if (sheet->isCSSStyleSheet() && !sheet->disabled())
    501             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
    502     }
    503     // Collect all ids and rules using sibling selectors (:first-child and similar)
    504     // in the current set of stylesheets. Style sharing code uses this information to reject
    505     // sharing candidates.
    506     // Usually there are no sibling rules in the default style but the MathML sheet has some.
    507     if (siblingRulesInDefaultStyle)
    508         siblingRulesInDefaultStyle->collectFeatures(m_features);
    509     m_authorStyle->collectFeatures(m_features);
    510     if (m_userStyle)
    511         m_userStyle->collectFeatures(m_features);
    512 
    513     m_authorStyle->shrinkToFit();
    514     if (m_features.siblingRules)
    515         m_features.siblingRules->shrinkToFit();
    516 
    517     if (document->renderer() && document->renderer()->style())
    518         document->renderer()->style()->font().update(fontSelector());
    519 }
    520 
    521 // This is a simplified style setting function for keyframe styles
    522 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
    523 {
    524     AtomicString s(rule->name());
    525     m_keyframesRuleMap.add(s.impl(), rule);
    526 }
    527 
    528 CSSStyleSelector::~CSSStyleSelector()
    529 {
    530     m_fontSelector->clearDocument();
    531     deleteAllValues(m_viewportDependentMediaQueryResults);
    532 }
    533 
    534 CSSStyleSelector::Features::Features()
    535     : usesFirstLineRules(false)
    536     , usesBeforeAfterRules(false)
    537     , usesLinkRules(false)
    538 {
    539 }
    540 
    541 CSSStyleSelector::Features::~Features()
    542 {
    543 }
    544 
    545 static CSSStyleSheet* parseUASheet(const String& str)
    546 {
    547     CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
    548     sheet->parseString(str);
    549     return sheet;
    550 }
    551 
    552 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
    553 {
    554     return parseUASheet(String(characters, size));
    555 }
    556 
    557 static void loadFullDefaultStyle()
    558 {
    559     if (simpleDefaultStyleSheet) {
    560         ASSERT(defaultStyle);
    561         delete defaultStyle;
    562         simpleDefaultStyleSheet->deref();
    563         defaultStyle = new RuleSet;
    564         simpleDefaultStyleSheet = 0;
    565     } else {
    566         ASSERT(!defaultStyle);
    567         defaultStyle = new RuleSet;
    568         defaultPrintStyle = new RuleSet;
    569         defaultQuirksStyle = new RuleSet;
    570     }
    571 
    572     // Strict-mode rules.
    573     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
    574     CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
    575     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
    576     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
    577 
    578     // Quirks-mode rules.
    579     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
    580     CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
    581     defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
    582 }
    583 
    584 static void loadSimpleDefaultStyle()
    585 {
    586     ASSERT(!defaultStyle);
    587     ASSERT(!simpleDefaultStyleSheet);
    588 
    589     defaultStyle = new RuleSet;
    590     defaultPrintStyle = new RuleSet;
    591     defaultQuirksStyle = new RuleSet;
    592 
    593     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
    594     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
    595 
    596     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
    597 }
    598 
    599 static void loadViewSourceStyle()
    600 {
    601     ASSERT(!defaultViewSourceStyle);
    602     defaultViewSourceStyle = new RuleSet;
    603     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
    604 }
    605 
    606 static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
    607 {
    608     identifierHashes.append(element->localName().impl()->existingHash());
    609     if (element->hasID())
    610         identifierHashes.append(element->idForStyleResolution().impl()->existingHash());
    611     const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0;
    612     if (styledElement && styledElement->hasClass()) {
    613         const SpaceSplitString& classNames = styledElement->classNames();
    614         size_t count = classNames.size();
    615         for (size_t i = 0; i < count; ++i)
    616             identifierHashes.append(classNames[i].impl()->existingHash());
    617     }
    618 }
    619 
    620 void CSSStyleSelector::pushParentStackFrame(Element* parent)
    621 {
    622     ASSERT(m_ancestorIdentifierFilter);
    623     ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentElement());
    624     ASSERT(!m_parentStack.isEmpty() || !parent->parentElement());
    625     m_parentStack.append(ParentStackFrame(parent));
    626     ParentStackFrame& parentFrame = m_parentStack.last();
    627     // Mix tags, class names and ids into some sort of weird bouillabaisse.
    628     // The filter is used for fast rejection of child and descendant selectors.
    629     collectElementIdentifierHashes(parent, parentFrame.identifierHashes);
    630     size_t count = parentFrame.identifierHashes.size();
    631     for (size_t i = 0; i < count; ++i)
    632         m_ancestorIdentifierFilter->add(parentFrame.identifierHashes[i]);
    633 }
    634 
    635 void CSSStyleSelector::popParentStackFrame()
    636 {
    637     ASSERT(!m_parentStack.isEmpty());
    638     ASSERT(m_ancestorIdentifierFilter);
    639     const ParentStackFrame& parentFrame = m_parentStack.last();
    640     size_t count = parentFrame.identifierHashes.size();
    641     for (size_t i = 0; i < count; ++i)
    642         m_ancestorIdentifierFilter->remove(parentFrame.identifierHashes[i]);
    643     m_parentStack.removeLast();
    644     if (m_parentStack.isEmpty()) {
    645         ASSERT(m_ancestorIdentifierFilter->likelyEmpty());
    646         m_ancestorIdentifierFilter.clear();
    647     }
    648 }
    649 
    650 void CSSStyleSelector::pushParent(Element* parent)
    651 {
    652     if (m_parentStack.isEmpty()) {
    653         ASSERT(!m_ancestorIdentifierFilter);
    654         m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>);
    655         // If the element is not the root itself, build the stack starting from the root.
    656         if (parent->parentElement()) {
    657             Vector<Element*, 30> ancestors;
    658             for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentElement())
    659                 ancestors.append(ancestor);
    660             int count = ancestors.size();
    661             for (int n = count - 1; n >= 0; --n)
    662                 pushParentStackFrame(ancestors[n]);
    663             return;
    664         }
    665     } else if (!parent->parentElement()) {
    666         // We are not always invoked consistently. For example, script execution can cause us to enter
    667         // style recalc in the middle of tree building. Reset the stack if we see a new root element.
    668         ASSERT(m_ancestorIdentifierFilter);
    669         m_ancestorIdentifierFilter->clear();
    670         m_parentStack.resize(0);
    671     } else {
    672         ASSERT(m_ancestorIdentifierFilter);
    673         // We may get invoked for some random elements in some wacky cases during style resolve.
    674         // Pause maintaining the stack in this case.
    675         if (m_parentStack.last().element != parent->parentElement())
    676             return;
    677     }
    678     pushParentStackFrame(parent);
    679 }
    680 
    681 void CSSStyleSelector::popParent(Element* parent)
    682 {
    683     if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)
    684         return;
    685     popParentStackFrame();
    686 }
    687 
    688 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
    689 {
    690     m_matchedDecls.append(decl);
    691 }
    692 
    693 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
    694 {
    695     m_matchedRules.clear();
    696 
    697     if (!rules || !m_element)
    698         return;
    699 
    700     // We need to collect the rules for id, class, tag, and everything else into a buffer and
    701     // then sort the buffer.
    702     if (m_element->hasID())
    703         matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    704     if (m_element->hasClass()) {
    705         ASSERT(m_styledElement);
    706         const SpaceSplitString& classNames = m_styledElement->classNames();
    707         size_t size = classNames.size();
    708         for (size_t i = 0; i < size; ++i)
    709             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    710     }
    711     if (!m_element->shadowPseudoId().isEmpty()) {
    712         ASSERT(m_styledElement);
    713         matchRulesForList(rules->getPseudoRules(m_element->shadowPseudoId().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    714     }
    715     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    716     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    717 
    718     // If we didn't match any rules, we're done.
    719     if (m_matchedRules.isEmpty())
    720         return;
    721 
    722     // Sort the set of matched rules.
    723     sortMatchedRules();
    724 
    725     // Now transfer the set of matched rules over to our list of decls.
    726     if (!m_checker.m_collectRulesOnly) {
    727         for (unsigned i = 0; i < m_matchedRules.size(); i++)
    728             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
    729     } else {
    730         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
    731             if (!m_ruleList)
    732                 m_ruleList = CSSRuleList::create();
    733             m_ruleList->append(m_matchedRules[i]->rule());
    734         }
    735     }
    736 }
    737 
    738 inline bool CSSStyleSelector::fastRejectSelector(const RuleData& ruleData) const
    739 {
    740     ASSERT(m_ancestorIdentifierFilter);
    741     const unsigned* descendantSelectorIdentifierHashes = ruleData.descendantSelectorIdentifierHashes();
    742     for (unsigned n = 0; n < RuleData::maximumIdentifierCount && descendantSelectorIdentifierHashes[n]; ++n) {
    743         if (!m_ancestorIdentifierFilter->mayContain(descendantSelectorIdentifierHashes[n]))
    744             return true;
    745     }
    746     return false;
    747 }
    748 
    749 void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
    750 {
    751     if (!rules)
    752         return;
    753     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
    754     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
    755     bool canUseFastReject = !m_parentStack.isEmpty() && m_parentStack.last().element == m_parentNode;
    756 
    757     unsigned size = rules->size();
    758     for (unsigned i = 0; i < size; ++i) {
    759         const RuleData& ruleData = rules->at(i);
    760         if (canUseFastReject && fastRejectSelector(ruleData))
    761             continue;
    762         if (checkSelector(ruleData)) {
    763             // If the rule has no properties to apply, then ignore it in the non-debug mode.
    764             CSSStyleRule* rule = ruleData.rule();
    765             CSSMutableStyleDeclaration* decl = rule->declaration();
    766             if (!decl || (!decl->length() && !includeEmptyRules))
    767                 continue;
    768             if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
    769                 continue;
    770             // If we're matching normal rules, set a pseudo bit if
    771             // we really just matched a pseudo-element.
    772             if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) {
    773                 if (m_checker.m_collectRulesOnly)
    774                     continue;
    775                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
    776                     m_style->setHasPseudoStyle(m_dynamicPseudo);
    777             } else {
    778                 // Update our first/last rule indices in the matched rules array.
    779                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
    780                 if (firstRuleIndex == -1)
    781                     firstRuleIndex = lastRuleIndex;
    782 
    783                 // Add this rule to our list of matched rules.
    784                 addMatchedRule(&ruleData);
    785             }
    786         }
    787     }
    788 }
    789 
    790 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
    791 {
    792     unsigned specificity1 = r1->specificity();
    793     unsigned specificity2 = r2->specificity();
    794     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
    795 }
    796 
    797 void CSSStyleSelector::sortMatchedRules()
    798 {
    799     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
    800 }
    801 
    802 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const
    803 {
    804     if (!element || !element->isLink())
    805         return NotInsideLink;
    806     return determineLinkStateSlowCase(element);
    807 }
    808 
    809 inline void CSSStyleSelector::initElement(Element* e)
    810 {
    811     if (m_element != e) {
    812         m_element = e;
    813         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
    814         m_elementLinkState = m_checker.determineLinkState(m_element);
    815         if (e && e == e->document()->documentElement()) {
    816             e->document()->setDirectionSetOnDocumentElement(false);
    817             e->document()->setWritingModeSetOnDocumentElement(false);
    818         }
    819     }
    820 }
    821 
    822 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
    823 {
    824     m_checker.m_pseudoStyle = pseudoID;
    825 
    826     m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
    827 
    828     if (parentStyle)
    829         m_parentStyle = parentStyle;
    830     else
    831         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
    832 
    833     Node* docElement = e ? e->document()->documentElement() : 0;
    834     RenderStyle* docStyle = m_checker.m_document->renderStyle();
    835     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
    836 
    837     m_style = 0;
    838 
    839     m_matchedDecls.clear();
    840 
    841     m_pendingImageProperties.clear();
    842 
    843     m_ruleList = 0;
    844 
    845     m_fontDirty = false;
    846 }
    847 
    848 static inline const AtomicString* linkAttribute(Node* node)
    849 {
    850     if (!node->isLink())
    851         return 0;
    852 
    853     ASSERT(node->isElementNode());
    854     Element* element = static_cast<Element*>(node);
    855     if (element->isHTMLElement())
    856         return &element->fastGetAttribute(hrefAttr);
    857 
    858 #if ENABLE(WML)
    859     if (element->isWMLElement()) {
    860         // <anchor> elements don't have href attributes, but we still want to
    861         // appear as link, so linkAttribute() has to return a non-null value!
    862         if (element->hasTagName(WMLNames::anchorTag))
    863             return &emptyAtom;
    864 
    865         return &element->fastGetAttribute(hrefAttr);
    866     }
    867 #endif
    868 
    869 #if ENABLE(SVG)
    870     if (element->isSVGElement())
    871         return &element->fastGetAttribute(XLinkNames::hrefAttr);
    872 #endif
    873 
    874     return 0;
    875 }
    876 
    877 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
    878     : m_document(document)
    879     , m_strictParsing(strictParsing)
    880     , m_collectRulesOnly(false)
    881     , m_sameOriginOnly(false)
    882     , m_pseudoStyle(NOPSEUDO)
    883     , m_documentIsHTML(document->isHTMLDocument())
    884     , m_matchVisitedPseudoClass(false)
    885 {
    886 }
    887 
    888 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const
    889 {
    890     ASSERT(element->isLink());
    891 
    892     const AtomicString* attr = linkAttribute(element);
    893     if (!attr || attr->isNull())
    894         return NotInsideLink;
    895 
    896 #if PLATFORM(QT)
    897     Vector<UChar, 512> url;
    898     visitedURL(m_document->baseURL(), *attr, url);
    899     if (url.isEmpty())
    900         return InsideUnvisitedLink;
    901 
    902     // If the Qt4.4 interface for the history is used, we will have to fallback
    903     // to the old global history.
    904     QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface();
    905     if (iface)
    906         return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink;
    907 
    908     LinkHash hash = visitedLinkHash(url.data(), url.size());
    909     if (!hash)
    910         return InsideUnvisitedLink;
    911 #else
    912     LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr);
    913     if (!hash)
    914         return InsideUnvisitedLink;
    915 #endif
    916 
    917     Frame* frame = m_document->frame();
    918     if (!frame)
    919         return InsideUnvisitedLink;
    920 
    921     Page* page = frame->page();
    922     if (!page)
    923         return InsideUnvisitedLink;
    924 
    925     m_linksCheckedForVisitedState.add(hash);
    926 
    927 #if USE(PLATFORM_STRATEGIES)
    928     return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink;
    929 #else
    930     return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
    931 #endif
    932 }
    933 
    934 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
    935 {
    936     PseudoId dynamicPseudo = NOPSEUDO;
    937     return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches;
    938 }
    939 
    940 static const unsigned cStyleSearchThreshold = 10;
    941 static const unsigned cStyleSearchLevelThreshold = 10;
    942 
    943 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
    944 {
    945     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
    946         return 0;
    947     if (!parent || !parent->isStyledElement())
    948         return 0;
    949     StyledElement* p = static_cast<StyledElement*>(parent);
    950     if (p->inlineStyleDecl())
    951         return 0;
    952     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
    953         return 0;
    954 
    955     RenderStyle* parentStyle = p->renderStyle();
    956     unsigned subcount = 0;
    957     Node* thisCousin = p;
    958     Node* currentNode = p->previousSibling();
    959 
    960     // Reserve the tries for this level. This effectively makes sure that the algorithm
    961     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
    962     visitedNodeCount += cStyleSearchThreshold;
    963     while (thisCousin) {
    964         while (currentNode) {
    965             ++subcount;
    966             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
    967                 // Adjust for unused reserved tries.
    968                 visitedNodeCount -= cStyleSearchThreshold - subcount;
    969                 return currentNode->lastChild();
    970             }
    971             if (subcount >= cStyleSearchThreshold)
    972                 return 0;
    973             currentNode = currentNode->previousSibling();
    974         }
    975         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
    976         thisCousin = currentNode;
    977     }
    978 
    979     return 0;
    980 }
    981 
    982 bool CSSStyleSelector::matchesSiblingRules()
    983 {
    984     int firstSiblingRule = -1, lastSiblingRule = -1;
    985     matchRules(m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false);
    986     if (m_matchedDecls.isEmpty())
    987         return false;
    988     m_matchedDecls.clear();
    989     return true;
    990 }
    991 
    992 bool CSSStyleSelector::canShareStyleWithElement(Node* node) const
    993 {
    994     if (!node->isStyledElement())
    995         return false;
    996 
    997     StyledElement* element = static_cast<StyledElement*>(node);
    998     RenderStyle* style = element->renderStyle();
    999 
   1000     if (!style)
   1001         return false;
   1002     if (style->unique())
   1003         return false;
   1004     if (element->tagQName() != m_element->tagQName())
   1005         return false;
   1006     if (element->hasClass() != m_element->hasClass())
   1007         return false;
   1008     if (element->inlineStyleDecl())
   1009         return false;
   1010     if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
   1011         return false;
   1012     if (element->isLink() != m_element->isLink())
   1013         return false;
   1014     if (style->affectedByAttributeSelectors())
   1015         return false;
   1016     if (element->hovered() != m_element->hovered())
   1017         return false;
   1018     if (element->active() != m_element->active())
   1019         return false;
   1020     if (element->focused() != m_element->focused())
   1021         return false;
   1022     if (element->shadowPseudoId() != m_element->shadowPseudoId())
   1023         return false;
   1024     if (element == element->document()->cssTarget())
   1025         return false;
   1026     if (m_element == m_element->document()->cssTarget())
   1027         return false;
   1028     if (element->fastGetAttribute(typeAttr) != m_element->fastGetAttribute(typeAttr))
   1029         return false;
   1030     if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
   1031         return false;
   1032     if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
   1033         return false;
   1034     if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
   1035         return false;
   1036     if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
   1037         return false;
   1038 
   1039     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
   1040         return false;
   1041 
   1042     bool isControl = element->isFormControlElement();
   1043 
   1044     if (isControl != m_element->isFormControlElement())
   1045         return false;
   1046 
   1047     if (isControl) {
   1048         InputElement* thisInputElement = element->toInputElement();
   1049         InputElement* otherInputElement = m_element->toInputElement();
   1050 
   1051         if (!thisInputElement || !otherInputElement)
   1052             return false;
   1053 
   1054         if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
   1055             return false;
   1056         if (thisInputElement->isChecked() != otherInputElement->isChecked())
   1057             return false;
   1058         if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
   1059             return false;
   1060 
   1061         if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
   1062             return false;
   1063 
   1064         if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
   1065             return false;
   1066 
   1067         if (!m_element->document()->containsValidityStyleRules())
   1068             return false;
   1069 
   1070         bool willValidate = element->willValidate();
   1071 
   1072         if (willValidate != m_element->willValidate())
   1073             return false;
   1074 
   1075         if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
   1076             return false;
   1077 
   1078         if (element->isInRange() != m_element->isInRange())
   1079             return false;
   1080 
   1081         if (element->isOutOfRange() != m_element->isOutOfRange())
   1082             return false;
   1083     }
   1084 
   1085     if (style->transitions() || style->animations())
   1086         return false;
   1087 
   1088 #if USE(ACCELERATED_COMPOSITING)
   1089     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
   1090     // See comments in RenderObject::setStyle().
   1091     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag))
   1092         return false;
   1093 #endif
   1094 
   1095     if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
   1096         return false;
   1097 
   1098     if (element->hasClass() && m_element->fastGetAttribute(classAttr) != element->fastGetAttribute(classAttr))
   1099         return false;
   1100 
   1101     if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
   1102         return false;
   1103 
   1104     if (element->isLink() && m_elementLinkState != style->insideLink())
   1105         return false;
   1106 
   1107     return true;
   1108 }
   1109 
   1110 inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
   1111 {
   1112     for (; node; node = node->previousSibling()) {
   1113         if (!node->isElementNode())
   1114             continue;
   1115         if (canShareStyleWithElement(node))
   1116             break;
   1117         if (count++ == cStyleSearchThreshold)
   1118             return 0;
   1119     }
   1120     return node;
   1121 }
   1122 
   1123 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
   1124 {
   1125     return parentStyle->childrenAffectedByPositionalRules()
   1126         || parentStyle->childrenAffectedByFirstChildRules()
   1127         || parentStyle->childrenAffectedByLastChildRules()
   1128         || parentStyle->childrenAffectedByDirectAdjacentRules();
   1129 }
   1130 
   1131 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
   1132 {
   1133     if (!m_styledElement || !m_parentStyle)
   1134         return 0;
   1135     // If the element has inline style it is probably unique.
   1136     if (m_styledElement->inlineStyleDecl())
   1137         return 0;
   1138     // Ids stop style sharing if they show up in the stylesheets.
   1139     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
   1140         return 0;
   1141     if (parentStylePreventsSharing(m_parentStyle))
   1142         return 0;
   1143 
   1144     // Check previous siblings and their cousins.
   1145     unsigned count = 0;
   1146     unsigned visitedNodeCount = 0;
   1147     Node* shareNode = 0;
   1148     Node* cousinList = m_styledElement->previousSibling();
   1149     while (cousinList) {
   1150         shareNode = findSiblingForStyleSharing(cousinList, count);
   1151         if (shareNode)
   1152             break;
   1153         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
   1154     }
   1155 
   1156     // If we have exhausted all our budget or our cousins.
   1157     if (!shareNode)
   1158         return 0;
   1159 
   1160     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
   1161     if (matchesSiblingRules())
   1162         return 0;
   1163     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
   1164     if (parentStylePreventsSharing(m_parentStyle))
   1165         return 0;
   1166     return shareNode->renderStyle();
   1167 }
   1168 
   1169 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
   1170 {
   1171     // First we match rules from the user agent sheet.
   1172     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
   1173         ? defaultPrintStyle : defaultStyle;
   1174     matchRules(userAgentStyleSheet, firstUARule, lastUARule, false);
   1175 
   1176     // In quirks mode, we match rules from the quirks user agent sheet.
   1177     if (!m_checker.m_strictParsing)
   1178         matchRules(defaultQuirksStyle, firstUARule, lastUARule, false);
   1179 
   1180     // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
   1181     if (m_checker.m_document->usesViewSourceStyles()) {
   1182         if (!defaultViewSourceStyle)
   1183             loadViewSourceStyle();
   1184         matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false);
   1185     }
   1186 }
   1187 
   1188 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
   1189 {
   1190     Frame* frame = document->frame();
   1191 
   1192     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
   1193     documentStyle->setDisplay(BLOCK);
   1194     documentStyle->setVisuallyOrdered(document->visuallyOrdered());
   1195     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
   1196     documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1);
   1197     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
   1198 
   1199     Element* docElement = document->documentElement();
   1200     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
   1201     if (docElementRenderer) {
   1202         // Use the direction and writing-mode of the body to set the
   1203         // viewport's direction and writing-mode unless the property is set on the document element.
   1204         // If there is no body, then use the document element.
   1205         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
   1206         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
   1207             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
   1208         else
   1209             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
   1210         if (bodyRenderer && !document->directionSetOnDocumentElement())
   1211             documentStyle->setDirection(bodyRenderer->style()->direction());
   1212         else
   1213             documentStyle->setDirection(docElementRenderer->style()->direction());
   1214     }
   1215 
   1216     FontDescription fontDescription;
   1217     fontDescription.setUsePrinterFont(document->printing());
   1218     if (Settings* settings = document->settings()) {
   1219         fontDescription.setRenderingMode(settings->fontRenderingMode());
   1220         if (document->printing() && !settings->shouldPrintBackgrounds())
   1221             documentStyle->setForceBackgroundsToWhite(true);
   1222         const AtomicString& stdfont = settings->standardFontFamily();
   1223         if (!stdfont.isEmpty()) {
   1224             fontDescription.firstFamily().setFamily(stdfont);
   1225             fontDescription.firstFamily().appendFamily(0);
   1226         }
   1227         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
   1228         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
   1229         fontDescription.setSpecifiedSize(size);
   1230         bool useSVGZoomRules = document->isSVGDocument();
   1231         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
   1232     }
   1233 
   1234     documentStyle->setFontDescription(fontDescription);
   1235     documentStyle->font().update(0);
   1236 
   1237     return documentStyle.release();
   1238 }
   1239 
   1240 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
   1241 // relative units are interpreted according to document root element style, styled only with UA stylesheet
   1242 
   1243 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass)
   1244 {
   1245     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
   1246     // will vanish if a style recalc happens during loading.
   1247     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
   1248         if (!s_styleNotYetAvailable) {
   1249             s_styleNotYetAvailable = RenderStyle::create().releaseRef();
   1250             s_styleNotYetAvailable->ref();
   1251             s_styleNotYetAvailable->setDisplay(NONE);
   1252             s_styleNotYetAvailable->font().update(m_fontSelector);
   1253         }
   1254         s_styleNotYetAvailable->ref();
   1255         e->document()->setHasNodesWithPlaceholderStyle();
   1256         return s_styleNotYetAvailable;
   1257     }
   1258 
   1259     initElement(e);
   1260     initForStyleResolve(e, defaultParent);
   1261     if (allowSharing) {
   1262         RenderStyle* sharedStyle = locateSharedStyle();
   1263         if (sharedStyle)
   1264             return sharedStyle;
   1265     }
   1266 
   1267     // Compute our style allowing :visited to match first.
   1268     RefPtr<RenderStyle> visitedStyle;
   1269     if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) {
   1270         // Fetch our parent style.
   1271         RenderStyle* parentStyle = m_parentStyle;
   1272         if (!e->isLink()) {
   1273             // Use the parent's visited style if one exists.
   1274             RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK);
   1275             if (parentVisitedStyle)
   1276                 parentStyle = parentVisitedStyle;
   1277         }
   1278         visitedStyle = styleForElement(e, parentStyle, false, false, true);
   1279         initForStyleResolve(e, defaultParent);
   1280     }
   1281 
   1282     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
   1283 
   1284     m_style = RenderStyle::create();
   1285 
   1286     if (m_parentStyle)
   1287         m_style->inheritFrom(m_parentStyle);
   1288     else {
   1289         m_parentStyle = style();
   1290         // Make sure our fonts are initialized if we don't inherit them from our parent style.
   1291         m_style->font().update(0);
   1292     }
   1293 
   1294     if (e->isLink()) {
   1295         m_style->setIsLink(true);
   1296         m_style->setInsideLink(m_elementLinkState);
   1297     }
   1298 
   1299     if (visitedStyle) {
   1300         // Copy any pseudo bits that the visited style has to the primary style so that
   1301         // pseudo element styles will continue to work for pseudo elements inside :visited
   1302         // links.
   1303         for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) {
   1304             if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo)))
   1305                 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo));
   1306         }
   1307         if (m_elementLinkState == InsideUnvisitedLink)
   1308             visitedStyle = 0;  // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it.
   1309         else
   1310             visitedStyle->setStyleType(VISITED_LINK);
   1311     }
   1312 
   1313     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) {
   1314         loadFullDefaultStyle();
   1315         assertNoSiblingRulesInDefaultStyle();
   1316     }
   1317 
   1318 #if ENABLE(SVG)
   1319     static bool loadedSVGUserAgentSheet;
   1320     if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
   1321         // SVG rules.
   1322         loadedSVGUserAgentSheet = true;
   1323         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
   1324         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
   1325         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
   1326         assertNoSiblingRulesInDefaultStyle();
   1327     }
   1328 #endif
   1329 
   1330 #if ENABLE(MATHML)
   1331     static bool loadedMathMLUserAgentSheet;
   1332     if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) {
   1333         // MathML rules.
   1334         loadedMathMLUserAgentSheet = true;
   1335         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
   1336         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
   1337         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
   1338         // There are some sibling rules here.
   1339         collectSiblingRulesInDefaultStyle();
   1340     }
   1341 #endif
   1342 
   1343 #if ENABLE(WML)
   1344     static bool loadedWMLUserAgentSheet;
   1345     if (e->isWMLElement() && !loadedWMLUserAgentSheet) {
   1346         // WML rules.
   1347         loadedWMLUserAgentSheet = true;
   1348         CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
   1349         defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
   1350         defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
   1351         assertNoSiblingRulesInDefaultStyle();
   1352     }
   1353 #endif
   1354 
   1355 #if ENABLE(VIDEO)
   1356     static bool loadedMediaStyleSheet;
   1357     if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) {
   1358         loadedMediaStyleSheet = true;
   1359         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(e->document()->page())->extraMediaControlsStyleSheet();
   1360         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
   1361         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
   1362         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
   1363         assertNoSiblingRulesInDefaultStyle();
   1364     }
   1365 #endif
   1366 
   1367 #if ENABLE(FULLSCREEN_API)
   1368     static bool loadedFullScreenStyleSheet;
   1369     if (!loadedFullScreenStyleSheet && e->document()->webkitIsFullScreen()) {
   1370         loadedFullScreenStyleSheet = true;
   1371         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
   1372         CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
   1373         defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
   1374         defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
   1375     }
   1376 #endif
   1377 
   1378     int firstUARule = -1, lastUARule = -1;
   1379     int firstUserRule = -1, lastUserRule = -1;
   1380     int firstAuthorRule = -1, lastAuthorRule = -1;
   1381     matchUARules(firstUARule, lastUARule);
   1382 
   1383     if (!resolveForRootDefault) {
   1384         // 4. Now we check user sheet rules.
   1385         if (m_matchAuthorAndUserStyles)
   1386             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
   1387 
   1388         // 5. Now check author rules, beginning first with presentational attributes
   1389         // mapped from HTML.
   1390         if (m_styledElement) {
   1391             // Ask if the HTML element has mapped attributes.
   1392             if (m_styledElement->hasMappedAttributes()) {
   1393                 // Walk our attribute list and add in each decl.
   1394                 const NamedNodeMap* map = m_styledElement->attributeMap();
   1395                 for (unsigned i = 0; i < map->length(); i++) {
   1396                     Attribute* attr = map->attributeItem(i);
   1397                     if (attr->isMappedAttribute() && attr->decl()) {
   1398                         lastAuthorRule = m_matchedDecls.size();
   1399                         if (firstAuthorRule == -1)
   1400                             firstAuthorRule = lastAuthorRule;
   1401                         addMatchedDeclaration(attr->decl());
   1402                     }
   1403                 }
   1404             }
   1405 
   1406             // Now we check additional mapped declarations.
   1407             // Tables and table cells share an additional mapped rule that must be applied
   1408             // after all attributes, since their mapped style depends on the values of multiple attributes.
   1409             if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
   1410                 m_additionalAttributeStyleDecls.clear();
   1411                 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
   1412                 if (!m_additionalAttributeStyleDecls.isEmpty()) {
   1413                     unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
   1414                     if (firstAuthorRule == -1)
   1415                         firstAuthorRule = m_matchedDecls.size();
   1416                     lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
   1417                     for (unsigned i = 0; i < additionalDeclsSize; i++)
   1418                         addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
   1419                 }
   1420             }
   1421             if (m_styledElement->isHTMLElement()) {
   1422                 bool isAuto;
   1423                 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
   1424                 if (isAuto)
   1425                     addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
   1426             }
   1427         }
   1428 
   1429         // 6. Check the rules in author sheets next.
   1430         if (m_matchAuthorAndUserStyles)
   1431             matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
   1432 
   1433         // 7. Now check our inline style attribute.
   1434         if (m_matchAuthorAndUserStyles && m_styledElement) {
   1435             CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
   1436             if (inlineDecl) {
   1437                 lastAuthorRule = m_matchedDecls.size();
   1438                 if (firstAuthorRule == -1)
   1439                     firstAuthorRule = lastAuthorRule;
   1440                 addMatchedDeclaration(inlineDecl);
   1441             }
   1442         }
   1443     }
   1444 
   1445     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
   1446     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
   1447 
   1448     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
   1449     // high-priority properties first, i.e., those properties that other properties depend on.
   1450     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
   1451     // and (4) normal important.
   1452     m_lineHeightValue = 0;
   1453     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
   1454     if (!resolveForRootDefault) {
   1455         applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
   1456         applyDeclarations<true>(true, firstUserRule, lastUserRule);
   1457     }
   1458     applyDeclarations<true>(true, firstUARule, lastUARule);
   1459 
   1460     // If our font got dirtied, go ahead and update it now.
   1461     if (m_fontDirty)
   1462         updateFont();
   1463 
   1464     // Line-height is set when we are sure we decided on the font-size
   1465     if (m_lineHeightValue)
   1466         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
   1467 
   1468     // Now do the normal priority UA properties.
   1469     applyDeclarations<false>(false, firstUARule, lastUARule);
   1470 
   1471     // Cache our border and background so that we can examine them later.
   1472     cacheBorderAndBackground();
   1473 
   1474     // Now do the author and user normal priority properties and all the !important properties.
   1475     if (!resolveForRootDefault) {
   1476         applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
   1477         applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
   1478         applyDeclarations<false>(true, firstUserRule, lastUserRule);
   1479     }
   1480     applyDeclarations<false>(true, firstUARule, lastUARule);
   1481 
   1482     ASSERT(!m_fontDirty);
   1483     // If our font got dirtied by one of the non-essential font props,
   1484     // go ahead and update it a second time.
   1485     if (m_fontDirty)
   1486         updateFont();
   1487 
   1488     // Clean up our style object's display and text decorations (among other fixups).
   1489     adjustRenderStyle(style(), m_parentStyle, e);
   1490 
   1491     // Start loading images referenced by this style.
   1492     loadPendingImages();
   1493 
   1494     // If we have first-letter pseudo style, do not share this style
   1495     if (m_style->hasPseudoStyle(FIRST_LETTER))
   1496         m_style->setUnique();
   1497 
   1498     if (visitedStyle) {
   1499         // Add the visited style off the main style.
   1500         m_style->addCachedPseudoStyle(visitedStyle.release());
   1501     }
   1502 
   1503     if (!matchVisitedPseudoClass)
   1504         initElement(0); // Clear out for the next resolve.
   1505 
   1506     // Now return the style.
   1507     return m_style.release();
   1508 }
   1509 
   1510 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
   1511 {
   1512     if (keyframeRule->style())
   1513         addMatchedDeclaration(keyframeRule->style());
   1514 
   1515     ASSERT(!m_style);
   1516 
   1517     // Create the style
   1518     m_style = RenderStyle::clone(elementStyle);
   1519 
   1520     m_lineHeightValue = 0;
   1521 
   1522     // We don't need to bother with !important. Since there is only ever one
   1523     // decl, there's nothing to override. So just add the first properties.
   1524     if (keyframeRule->style())
   1525         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
   1526 
   1527     // If our font got dirtied, go ahead and update it now.
   1528     if (m_fontDirty)
   1529         updateFont();
   1530 
   1531     // Line-height is set when we are sure we decided on the font-size
   1532     if (m_lineHeightValue)
   1533         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
   1534 
   1535     // Now do rest of the properties.
   1536     if (keyframeRule->style())
   1537         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
   1538 
   1539     // If our font got dirtied by one of the non-essential font props,
   1540     // go ahead and update it a second time.
   1541     if (m_fontDirty)
   1542         updateFont();
   1543 
   1544     // Start loading images referenced by this style.
   1545     loadPendingImages();
   1546 
   1547     // Add all the animating properties to the keyframe.
   1548     if (keyframeRule->style()) {
   1549         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
   1550         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
   1551             int property = (*it).id();
   1552             // Timing-function within keyframes is special, because it is not animated; it just
   1553             // describes the timing function between this keyframe and the next.
   1554             if (property != CSSPropertyWebkitAnimationTimingFunction)
   1555                 keyframe.addProperty(property);
   1556         }
   1557     }
   1558 
   1559     return m_style.release();
   1560 }
   1561 
   1562 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
   1563 {
   1564     list.clear();
   1565 
   1566     // Get the keyframesRule for this name
   1567     if (!e || list.animationName().isEmpty())
   1568         return;
   1569 
   1570     m_keyframesRuleMap.checkConsistency();
   1571 
   1572     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
   1573         return;
   1574 
   1575     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
   1576 
   1577     // Construct and populate the style for each keyframe
   1578     for (unsigned i = 0; i < rule->length(); ++i) {
   1579         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
   1580         initElement(e);
   1581         initForStyleResolve(e);
   1582 
   1583         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
   1584 
   1585         KeyframeValue keyframe(0, 0);
   1586         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
   1587 
   1588         // Add this keyframe style to all the indicated key times
   1589         Vector<float> keys;
   1590         keyframeRule->getKeys(keys);
   1591         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
   1592             keyframe.setKey(keys[keyIndex]);
   1593             list.insert(keyframe);
   1594         }
   1595     }
   1596 
   1597     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
   1598     int initialListSize = list.size();
   1599     if (initialListSize > 0 && list[0].key() != 0) {
   1600         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
   1601         keyframeRule->setKeyText("0%");
   1602         KeyframeValue keyframe(0, 0);
   1603         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
   1604         list.insert(keyframe);
   1605     }
   1606 
   1607     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
   1608     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
   1609         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
   1610         keyframeRule->setKeyText("100%");
   1611         KeyframeValue keyframe(1, 0);
   1612         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
   1613         list.insert(keyframe);
   1614     }
   1615 }
   1616 
   1617 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass)
   1618 {
   1619     if (!e)
   1620         return 0;
   1621 
   1622     initElement(e);
   1623 
   1624     // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it
   1625     // off of.
   1626     RefPtr<RenderStyle> visitedStyle;
   1627     if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) {
   1628         // Fetch our parent style with :visited in effect.
   1629         RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK);
   1630         visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true);
   1631         if (visitedStyle)
   1632             visitedStyle->setStyleType(VISITED_LINK);
   1633     }
   1634 
   1635     initForStyleResolve(e, parentStyle, pseudo);
   1636     m_style = RenderStyle::create();
   1637     if (parentStyle)
   1638         m_style->inheritFrom(parentStyle);
   1639 
   1640     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
   1641 
   1642     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
   1643     // those rules.
   1644 
   1645     // Check UA, user and author rules.
   1646     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
   1647     matchUARules(firstUARule, lastUARule);
   1648 
   1649     if (m_matchAuthorAndUserStyles) {
   1650         matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
   1651         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
   1652     }
   1653 
   1654     if (m_matchedDecls.isEmpty() && !visitedStyle)
   1655         return 0;
   1656 
   1657     m_style->setStyleType(pseudo);
   1658 
   1659     m_lineHeightValue = 0;
   1660 
   1661     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
   1662     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
   1663 
   1664     // High-priority properties.
   1665     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
   1666     applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
   1667     applyDeclarations<true>(true, firstUserRule, lastUserRule);
   1668     applyDeclarations<true>(true, firstUARule, lastUARule);
   1669 
   1670     // If our font got dirtied, go ahead and update it now.
   1671     if (m_fontDirty)
   1672         updateFont();
   1673 
   1674     // Line-height is set when we are sure we decided on the font-size
   1675     if (m_lineHeightValue)
   1676         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
   1677 
   1678     // Now do the normal priority properties.
   1679     applyDeclarations<false>(false, firstUARule, lastUARule);
   1680 
   1681     // Cache our border and background so that we can examine them later.
   1682     cacheBorderAndBackground();
   1683 
   1684     applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
   1685     applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
   1686     applyDeclarations<false>(true, firstUserRule, lastUserRule);
   1687     applyDeclarations<false>(true, firstUARule, lastUARule);
   1688 
   1689     // If our font got dirtied by one of the non-essential font props,
   1690     // go ahead and update it a second time.
   1691     if (m_fontDirty)
   1692         updateFont();
   1693 
   1694     // Clean up our style object's display and text decorations (among other fixups).
   1695     adjustRenderStyle(style(), parentStyle, 0);
   1696 
   1697     // Start loading images referenced by this style.
   1698     loadPendingImages();
   1699 
   1700     // Hang our visited style off m_style.
   1701     if (visitedStyle)
   1702         m_style->addCachedPseudoStyle(visitedStyle.release());
   1703 
   1704     // Now return the style.
   1705     return m_style.release();
   1706 }
   1707 
   1708 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
   1709 {
   1710     initForStyleResolve(m_checker.m_document->documentElement()); // m_rootElementStyle will be set to the document style.
   1711 
   1712     m_style = RenderStyle::create();
   1713     m_style->inheritFrom(m_rootElementStyle);
   1714 
   1715     const bool isLeft = isLeftPage(pageIndex);
   1716     const bool isFirst = isFirstPage(pageIndex);
   1717     const String page = pageName(pageIndex);
   1718     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
   1719     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
   1720     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
   1721     m_lineHeightValue = 0;
   1722     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
   1723 
   1724     // If our font got dirtied, go ahead and update it now.
   1725     if (m_fontDirty)
   1726         updateFont();
   1727 
   1728     // Line-height is set when we are sure we decided on the font-size
   1729     if (m_lineHeightValue)
   1730         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
   1731 
   1732     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
   1733 
   1734     // Start loading images referenced by this style.
   1735     loadPendingImages();
   1736 
   1737     // Now return the style.
   1738     return m_style.release();
   1739 }
   1740 
   1741 #if ENABLE(DATAGRID)
   1742 
   1743 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*)
   1744 {
   1745     // FIXME: Implement
   1746     return 0;
   1747 }
   1748 
   1749 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*)
   1750 {
   1751     // FIXME: Implement
   1752     return 0;
   1753 }
   1754 
   1755 #endif
   1756 
   1757 static void addIntrinsicMargins(RenderStyle* style)
   1758 {
   1759     // Intrinsic margin value.
   1760     const int intrinsicMargin = 2 * style->effectiveZoom();
   1761 
   1762     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
   1763     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
   1764     if (style->width().isIntrinsicOrAuto()) {
   1765         if (style->marginLeft().quirk())
   1766             style->setMarginLeft(Length(intrinsicMargin, Fixed));
   1767         if (style->marginRight().quirk())
   1768             style->setMarginRight(Length(intrinsicMargin, Fixed));
   1769     }
   1770 
   1771     if (style->height().isAuto()) {
   1772         if (style->marginTop().quirk())
   1773             style->setMarginTop(Length(intrinsicMargin, Fixed));
   1774         if (style->marginBottom().quirk())
   1775             style->setMarginBottom(Length(intrinsicMargin, Fixed));
   1776     }
   1777 }
   1778 
   1779 static inline bool isAtShadowBoundary(Element* element)
   1780 {
   1781     if (!element)
   1782         return false;
   1783 
   1784     ContainerNode* parentNode = element->parentNode();
   1785     return parentNode && parentNode->isShadowBoundary();
   1786 }
   1787 
   1788 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
   1789 {
   1790     // Cache our original display.
   1791     style->setOriginalDisplay(style->display());
   1792 
   1793     if (style->display() != NONE) {
   1794         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
   1795         // property.
   1796         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
   1797         // these tags to retain their display types.
   1798         if (!m_checker.m_strictParsing && e) {
   1799             if (e->hasTagName(tdTag)) {
   1800                 style->setDisplay(TABLE_CELL);
   1801                 style->setFloating(FNONE);
   1802             }
   1803             else if (e->hasTagName(tableTag))
   1804                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
   1805         }
   1806 
   1807         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
   1808             if (style->whiteSpace() == KHTML_NOWRAP) {
   1809                 // Figure out if we are really nowrapping or if we should just
   1810                 // use normal instead.  If the width of the cell is fixed, then
   1811                 // we don't actually use NOWRAP.
   1812                 if (style->width().isFixed())
   1813                     style->setWhiteSpace(NORMAL);
   1814                 else
   1815                     style->setWhiteSpace(NOWRAP);
   1816             }
   1817         }
   1818 
   1819         // Tables never support the -webkit-* values for text-align and will reset back to the default.
   1820         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
   1821             style->setTextAlign(TAAUTO);
   1822 
   1823         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
   1824         // fix a crash where a site tries to position these objects.  They also never honor display.
   1825         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
   1826             style->setPosition(StaticPosition);
   1827             style->setDisplay(BLOCK);
   1828         }
   1829 
   1830         // Table headers with a text-align of auto will change the text-align to center.
   1831         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
   1832             style->setTextAlign(CENTER);
   1833 
   1834         if (e && e->hasTagName(legendTag))
   1835             style->setDisplay(BLOCK);
   1836 
   1837         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
   1838         // position or float an inline, compact, or run-in.  Cache the original display, since it
   1839         // may be needed for positioned elements that have to compute their static normal flow
   1840         // positions.  We also force inline-level roots to be block-level.
   1841         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
   1842             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
   1843              (e && e->document()->documentElement() == e))) {
   1844             if (style->display() == INLINE_TABLE)
   1845                 style->setDisplay(TABLE);
   1846             else if (style->display() == INLINE_BOX)
   1847                 style->setDisplay(BOX);
   1848             else if (style->display() == LIST_ITEM) {
   1849                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
   1850                 // but only in quirks mode.
   1851                 if (!m_checker.m_strictParsing && style->floating() != FNONE)
   1852                     style->setDisplay(BLOCK);
   1853             }
   1854             else
   1855                 style->setDisplay(BLOCK);
   1856         }
   1857 
   1858         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
   1859         // clear how that should work.
   1860         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
   1861             style->setDisplay(INLINE_BLOCK);
   1862 
   1863         // After performing the display mutation, check table rows.  We do not honor position:relative on
   1864         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
   1865         // on some sites).
   1866         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
   1867              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
   1868              style->position() == RelativePosition)
   1869             style->setPosition(StaticPosition);
   1870 
   1871         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
   1872         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
   1873         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
   1874             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
   1875             || style->display() == TABLE_CELL)
   1876             style->setWritingMode(parentStyle->writingMode());
   1877 
   1878         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
   1879         // of block-flow to anything other than TopToBottomWritingMode.
   1880         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
   1881         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
   1882             style->setWritingMode(TopToBottomWritingMode);
   1883     }
   1884 
   1885     // Make sure our z-index value is only applied if the object is positioned.
   1886     if (style->position() == StaticPosition)
   1887         style->setHasAutoZIndex();
   1888 
   1889     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
   1890     // cases where objects that should be blended as a single unit end up with a non-transparent
   1891     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
   1892     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f ||
   1893         style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect()))
   1894         style->setZIndex(0);
   1895 
   1896 #if ENABLE(WML)
   1897     if (e && (e->hasTagName(WMLNames::insertedLegendTag)
   1898               || e->hasTagName(WMLNames::inputTag))
   1899             && style->width().isAuto())
   1900         style->setWidth(Length(Intrinsic));
   1901 #endif
   1902 
   1903     // Textarea considers overflow visible as auto.
   1904     if (e && e->hasTagName(textareaTag)) {
   1905         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
   1906         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
   1907     }
   1908 
   1909     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
   1910     // tables, inline blocks, inline tables, run-ins, or shadow DOM.
   1911     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
   1912         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
   1913         style->setTextDecorationsInEffect(style->textDecoration());
   1914     else
   1915         style->addToTextDecorationsInEffect(style->textDecoration());
   1916 
   1917     // If either overflow value is not visible, change to auto.
   1918     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
   1919         style->setOverflowY(OMARQUEE);
   1920     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
   1921         style->setOverflowX(OMARQUEE);
   1922     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
   1923         style->setOverflowX(OAUTO);
   1924     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
   1925         style->setOverflowY(OAUTO);
   1926 
   1927     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
   1928     // FIXME: Eventually table sections will support auto and scroll.
   1929     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
   1930         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
   1931         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
   1932             style->setOverflowX(OVISIBLE);
   1933         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
   1934             style->setOverflowY(OVISIBLE);
   1935     }
   1936 
   1937     // Menulists should have visible overflow
   1938     if (style->appearance() == MenulistPart) {
   1939         style->setOverflowX(OVISIBLE);
   1940         style->setOverflowY(OVISIBLE);
   1941     }
   1942 
   1943     // Cull out any useless layers and also repeat patterns into additional layers.
   1944     style->adjustBackgroundLayers();
   1945     style->adjustMaskLayers();
   1946 
   1947     // Do the same for animations and transitions.
   1948     style->adjustAnimations();
   1949     style->adjustTransitions();
   1950 
   1951     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
   1952     // alter fonts and heights/widths.
   1953     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
   1954         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
   1955         // so we have to treat all image buttons as though they were explicitly sized.
   1956         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
   1957             addIntrinsicMargins(style);
   1958     }
   1959 
   1960     // Let the theme also have a crack at adjusting the style.
   1961     if (style->hasAppearance())
   1962         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
   1963 
   1964 #if ENABLE(SVG)
   1965     if (e && e->isSVGElement()) {
   1966         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
   1967         if (style->overflowY() == OSCROLL)
   1968             style->setOverflowY(OHIDDEN);
   1969         else if (style->overflowY() == OAUTO)
   1970             style->setOverflowY(OVISIBLE);
   1971 
   1972         if (style->overflowX() == OSCROLL)
   1973             style->setOverflowX(OHIDDEN);
   1974         else if (style->overflowX() == OAUTO)
   1975             style->setOverflowX(OVISIBLE);
   1976 
   1977         // Only the root <svg> element in an SVG document fragment tree honors css position
   1978         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
   1979             style->setPosition(RenderStyle::initialPosition());
   1980     }
   1981 #endif
   1982 }
   1983 
   1984 void CSSStyleSelector::updateFont()
   1985 {
   1986     checkForTextSizeAdjust();
   1987     checkForGenericFamilyChange(style(), m_parentStyle);
   1988     checkForZoomChange(style(), m_parentStyle);
   1989     m_style->font().update(m_fontSelector);
   1990     m_fontDirty = false;
   1991 }
   1992 
   1993 void CSSStyleSelector::cacheBorderAndBackground()
   1994 {
   1995     m_hasUAAppearance = m_style->hasAppearance();
   1996     if (m_hasUAAppearance) {
   1997         m_borderData = m_style->border();
   1998         m_backgroundData = *m_style->backgroundLayers();
   1999         m_backgroundColor = m_style->backgroundColor();
   2000     }
   2001 }
   2002 
   2003 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
   2004 {
   2005     return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly, includeEmptyRules, filter);
   2006 }
   2007 
   2008 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
   2009 {
   2010     if (!e || !e->document()->haveStylesheetsLoaded())
   2011         return 0;
   2012 
   2013     m_checker.m_collectRulesOnly = true;
   2014 
   2015     initElement(e);
   2016     initForStyleResolve(e, 0, pseudoId);
   2017 
   2018     if (!authorOnly) {
   2019         int firstUARule = -1, lastUARule = -1;
   2020         // First we match rules from the user agent sheet.
   2021         matchUARules(firstUARule, lastUARule);
   2022 
   2023         // Now we check user sheet rules.
   2024         if (m_matchAuthorAndUserStyles) {
   2025             int firstUserRule = -1, lastUserRule = -1;
   2026             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, includeEmptyRules);
   2027         }
   2028     }
   2029 
   2030     if (m_matchAuthorAndUserStyles) {
   2031         m_checker.m_sameOriginOnly = (filter == SameOriginCSSRulesOnly);
   2032 
   2033         // Check the rules in author sheets.
   2034         int firstAuthorRule = -1, lastAuthorRule = -1;
   2035         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, includeEmptyRules);
   2036 
   2037         m_checker.m_sameOriginOnly = false;
   2038     }
   2039 
   2040     m_checker.m_collectRulesOnly = false;
   2041 
   2042     return m_ruleList.release();
   2043 }
   2044 
   2045 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
   2046 {
   2047     m_dynamicPseudo = NOPSEUDO;
   2048 
   2049     // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
   2050     if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
   2051         // We know this selector does not include any pseudo selectors.
   2052         if (m_checker.m_pseudoStyle != NOPSEUDO)
   2053             return false;
   2054         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
   2055         // This is limited to HTML only so we don't need to check the namespace.
   2056         if (ruleData.hasTopSelectorMatchingHTMLBasedOnRuleHash() && !ruleData.hasMultipartSelector() && m_element->isHTMLElement())
   2057             return true;
   2058         return SelectorChecker::fastCheckSelector(ruleData.selector(), m_element);
   2059     }
   2060 
   2061     // Slow path.
   2062     SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
   2063     if (match != SelectorMatches)
   2064         return false;
   2065     if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
   2066         return false;
   2067     return true;
   2068 }
   2069 
   2070 static inline bool selectorTagMatches(const Element* element, const CSSSelector* selector)
   2071 {
   2072     if (!selector->hasTag())
   2073         return true;
   2074     const AtomicString& localName = selector->tag().localName();
   2075     if (localName != starAtom && localName != element->localName())
   2076         return false;
   2077     const AtomicString& namespaceURI = selector->tag().namespaceURI();
   2078     return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
   2079 }
   2080 
   2081 static inline bool isFastCheckableSelector(const CSSSelector* selector)
   2082 {
   2083     for (; selector; selector = selector->tagHistory()) {
   2084         if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
   2085             return false;
   2086         if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
   2087             return false;
   2088     }
   2089     return true;
   2090 }
   2091 
   2092 template <class ValueChecker>
   2093 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
   2094 {
   2095     AtomicStringImpl* value = selector->value().impl();
   2096     for (; element; element = element->parentElement()) {
   2097         if (ValueChecker::checkValue(element, value) && selectorTagMatches(element, selector)) {
   2098             if (selector->relation() == CSSSelector::Descendant)
   2099                 topChildOrSubselector = 0;
   2100             else if (!topChildOrSubselector) {
   2101                 ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
   2102                 topChildOrSubselector = selector;
   2103                 topChildOrSubselectorMatchElement = element;
   2104             }
   2105             if (selector->relation() != CSSSelector::SubSelector)
   2106                 element = element->parentElement();
   2107             selector = selector->tagHistory();
   2108             return true;
   2109         }
   2110         if (topChildOrSubselector) {
   2111             // Child or subselector check failed.
   2112             // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match
   2113             // the original element we were checking.
   2114             if (!topChildOrSubselectorMatchElement)
   2115                 return false;
   2116             // There may be other matches down the ancestor chain.
   2117             // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
   2118             selector = topChildOrSubselector;
   2119             element = topChildOrSubselectorMatchElement->parentElement();
   2120             topChildOrSubselector = 0;
   2121             return true;
   2122         }
   2123     }
   2124     return false;
   2125 }
   2126 
   2127 struct ClassCheck {
   2128     static bool checkValue(const Element* element, AtomicStringImpl* value)
   2129     {
   2130         return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value);
   2131     }
   2132 };
   2133 struct IdCheck {
   2134     static bool checkValue(const Element* element, AtomicStringImpl* value)
   2135     {
   2136         return element->hasID() && element->idForStyleResolution().impl() == value;
   2137     }
   2138 };
   2139 struct TagCheck {
   2140     static bool checkValue(const Element*, AtomicStringImpl*)
   2141     {
   2142         return true;
   2143     }
   2144 };
   2145 
   2146 bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element)
   2147 {
   2148     ASSERT(isFastCheckableSelector(selector));
   2149 
   2150     // The top selector requires tag check only as rule hashes have already handled id and class matches.
   2151     if (!selectorTagMatches(element, selector))
   2152         return false;
   2153 
   2154     const CSSSelector* topChildOrSubselector = 0;
   2155     const Element* topChildOrSubselectorMatchElement = 0;
   2156     if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
   2157         topChildOrSubselector = selector;
   2158 
   2159     if (selector->relation() != CSSSelector::SubSelector)
   2160         element = element->parentElement();
   2161 
   2162     selector = selector->tagHistory();
   2163 
   2164     // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
   2165     while (selector) {
   2166         switch (selector->m_match) {
   2167         case CSSSelector::Class:
   2168             if (!fastCheckSingleSelector<ClassCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
   2169                 return false;
   2170             break;
   2171         case CSSSelector::Id:
   2172             if (!fastCheckSingleSelector<IdCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
   2173                 return false;
   2174             break;
   2175         case CSSSelector::None:
   2176             if (!fastCheckSingleSelector<TagCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
   2177                 return false;
   2178             break;
   2179         default:
   2180             ASSERT_NOT_REACHED();
   2181         }
   2182     }
   2183     return true;
   2184 }
   2185 
   2186 // Recursive check of selectors and combinators
   2187 // It can return 3 different values:
   2188 // * SelectorMatches         - the selector matches the element e
   2189 // * SelectorFailsLocally    - the selector fails for the element e
   2190 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
   2191 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
   2192 {
   2193 #if ENABLE(SVG)
   2194     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
   2195     // because its contents are not part of the formal document structure.
   2196     if (e->isSVGElement() && e->isShadowRoot())
   2197         return SelectorFailsCompletely;
   2198 #endif
   2199 
   2200     // first selector has to match
   2201     if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle))
   2202         return SelectorFailsLocally;
   2203 
   2204     // The rest of the selectors has to match
   2205     CSSSelector::Relation relation = sel->relation();
   2206 
   2207     // Prepare next sel
   2208     sel = sel->tagHistory();
   2209     if (!sel)
   2210         return SelectorMatches;
   2211 
   2212     if (relation != CSSSelector::SubSelector)
   2213         // Bail-out if this selector is irrelevant for the pseudoStyle
   2214         if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
   2215             return SelectorFailsCompletely;
   2216 
   2217     // Check for nested links.
   2218     if (m_matchVisitedPseudoClass && !isSubSelector) {
   2219         RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
   2220         if (currentStyle && currentStyle->insideLink() && e->isLink()) {
   2221             if (encounteredLink)
   2222                 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching.
   2223             else
   2224                 encounteredLink = true;
   2225         }
   2226     }
   2227 
   2228     switch (relation) {
   2229         case CSSSelector::Descendant:
   2230             while (true) {
   2231                 ContainerNode* n = e->parentNode();
   2232                 if (!n || !n->isElementNode())
   2233                     return SelectorFailsCompletely;
   2234                 e = static_cast<Element*>(n);
   2235                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
   2236                 if (match != SelectorFailsLocally)
   2237                     return match;
   2238             }
   2239             break;
   2240         case CSSSelector::Child:
   2241         {
   2242             ContainerNode* n = e->parentNode();
   2243             if (!n || !n->isElementNode())
   2244                 return SelectorFailsCompletely;
   2245             e = static_cast<Element*>(n);
   2246             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
   2247         }
   2248         case CSSSelector::DirectAdjacent:
   2249         {
   2250             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
   2251                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
   2252                 if (parentStyle)
   2253                     parentStyle->setChildrenAffectedByDirectAdjacentRules();
   2254             }
   2255             Node* n = e->previousSibling();
   2256             while (n && !n->isElementNode())
   2257                 n = n->previousSibling();
   2258             if (!n)
   2259                 return SelectorFailsLocally;
   2260             e = static_cast<Element*>(n);
   2261             m_matchVisitedPseudoClass = false;
   2262             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
   2263         }
   2264         case CSSSelector::IndirectAdjacent:
   2265             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
   2266                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
   2267                 if (parentStyle)
   2268                     parentStyle->setChildrenAffectedByForwardPositionalRules();
   2269             }
   2270             while (true) {
   2271                 Node* n = e->previousSibling();
   2272                 while (n && !n->isElementNode())
   2273                     n = n->previousSibling();
   2274                 if (!n)
   2275                     return SelectorFailsLocally;
   2276                 e = static_cast<Element*>(n);
   2277                 m_matchVisitedPseudoClass = false;
   2278                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
   2279                 if (match != SelectorFailsLocally)
   2280                     return match;
   2281             };
   2282             break;
   2283         case CSSSelector::SubSelector:
   2284             // a selector is invalid if something follows a pseudo-element
   2285             // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
   2286             // to follow the pseudo elements.
   2287             if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
   2288                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
   2289                 return SelectorFailsCompletely;
   2290             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
   2291         case CSSSelector::ShadowDescendant:
   2292         {
   2293             Node* shadowHostNode = e->shadowAncestorNode();
   2294             if (shadowHostNode == e || !shadowHostNode->isElementNode())
   2295                 return SelectorFailsCompletely;
   2296             e = static_cast<Element*>(shadowHostNode);
   2297             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
   2298         }
   2299     }
   2300 
   2301     return SelectorFailsCompletely;
   2302 }
   2303 
   2304 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
   2305 {
   2306     set->add(qName.localName().impl());
   2307 }
   2308 
   2309 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
   2310 {
   2311     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
   2312     // Mozilla treats all other values as case-sensitive, thus so do we.
   2313     HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
   2314 
   2315     addLocalNameToSet(attrSet, accept_charsetAttr);
   2316     addLocalNameToSet(attrSet, acceptAttr);
   2317     addLocalNameToSet(attrSet, alignAttr);
   2318     addLocalNameToSet(attrSet, alinkAttr);
   2319     addLocalNameToSet(attrSet, axisAttr);
   2320     addLocalNameToSet(attrSet, bgcolorAttr);
   2321     addLocalNameToSet(attrSet, charsetAttr);
   2322     addLocalNameToSet(attrSet, checkedAttr);
   2323     addLocalNameToSet(attrSet, clearAttr);
   2324     addLocalNameToSet(attrSet, codetypeAttr);
   2325     addLocalNameToSet(attrSet, colorAttr);
   2326     addLocalNameToSet(attrSet, compactAttr);
   2327     addLocalNameToSet(attrSet, declareAttr);
   2328     addLocalNameToSet(attrSet, deferAttr);
   2329     addLocalNameToSet(attrSet, dirAttr);
   2330     addLocalNameToSet(attrSet, disabledAttr);
   2331     addLocalNameToSet(attrSet, enctypeAttr);
   2332     addLocalNameToSet(attrSet, faceAttr);
   2333     addLocalNameToSet(attrSet, frameAttr);
   2334     addLocalNameToSet(attrSet, hreflangAttr);
   2335     addLocalNameToSet(attrSet, http_equivAttr);
   2336     addLocalNameToSet(attrSet, langAttr);
   2337     addLocalNameToSet(attrSet, languageAttr);
   2338     addLocalNameToSet(attrSet, linkAttr);
   2339     addLocalNameToSet(attrSet, mediaAttr);
   2340     addLocalNameToSet(attrSet, methodAttr);
   2341     addLocalNameToSet(attrSet, multipleAttr);
   2342     addLocalNameToSet(attrSet, nohrefAttr);
   2343     addLocalNameToSet(attrSet, noresizeAttr);
   2344     addLocalNameToSet(attrSet, noshadeAttr);
   2345     addLocalNameToSet(attrSet, nowrapAttr);
   2346     addLocalNameToSet(attrSet, readonlyAttr);
   2347     addLocalNameToSet(attrSet, relAttr);
   2348     addLocalNameToSet(attrSet, revAttr);
   2349     addLocalNameToSet(attrSet, rulesAttr);
   2350     addLocalNameToSet(attrSet, scopeAttr);
   2351     addLocalNameToSet(attrSet, scrollingAttr);
   2352     addLocalNameToSet(attrSet, selectedAttr);
   2353     addLocalNameToSet(attrSet, shapeAttr);
   2354     addLocalNameToSet(attrSet, targetAttr);
   2355     addLocalNameToSet(attrSet, textAttr);
   2356     addLocalNameToSet(attrSet, typeAttr);
   2357     addLocalNameToSet(attrSet, valignAttr);
   2358     addLocalNameToSet(attrSet, valuetypeAttr);
   2359     addLocalNameToSet(attrSet, vlinkAttr);
   2360 
   2361     return attrSet;
   2362 }
   2363 
   2364 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
   2365 {
   2366     static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
   2367     bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
   2368     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
   2369 }
   2370 
   2371 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
   2372 {
   2373     ASSERT(e);
   2374     if (!e)
   2375         return false;
   2376 
   2377     if (!selectorTagMatches(e, sel))
   2378         return false;
   2379 
   2380     if (sel->hasAttribute()) {
   2381         if (sel->m_match == CSSSelector::Class)
   2382             return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value());
   2383 
   2384         if (sel->m_match == CSSSelector::Id)
   2385             return e->hasID() && e->idForStyleResolution() == sel->value();
   2386 
   2387         const QualifiedName& attr = sel->attribute();
   2388 
   2389         // FIXME: Handle the case were elementStyle is 0.
   2390         if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) {
   2391             elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
   2392             if (selectorAttrs)
   2393                 selectorAttrs->add(attr.localName().impl());
   2394         }
   2395 
   2396         const AtomicString& value = e->getAttribute(attr);
   2397         if (value.isNull())
   2398             return false; // attribute is not set
   2399 
   2400         bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
   2401 
   2402         switch (sel->m_match) {
   2403         case CSSSelector::Exact:
   2404             if (caseSensitive ? sel->value() != value : !equalIgnoringCase(sel->value(), value))
   2405                 return false;
   2406             break;
   2407         case CSSSelector::List:
   2408         {
   2409             // Ignore empty selectors or selectors containing spaces
   2410             if (sel->value().contains(' ') || sel->value().isEmpty())
   2411                 return false;
   2412 
   2413             unsigned startSearchAt = 0;
   2414             while (true) {
   2415                 size_t foundPos = value.find(sel->value(), startSearchAt, caseSensitive);
   2416                 if (foundPos == notFound)
   2417                     return false;
   2418                 if (foundPos == 0 || value[foundPos - 1] == ' ') {
   2419                     unsigned endStr = foundPos + sel->value().length();
   2420                     if (endStr == value.length() || value[endStr] == ' ')
   2421                         break; // We found a match.
   2422                 }
   2423 
   2424                 // No match. Keep looking.
   2425                 startSearchAt = foundPos + 1;
   2426             }
   2427             break;
   2428         }
   2429         case CSSSelector::Contain:
   2430             if (!value.contains(sel->value(), caseSensitive) || sel->value().isEmpty())
   2431                 return false;
   2432             break;
   2433         case CSSSelector::Begin:
   2434             if (!value.startsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
   2435                 return false;
   2436             break;
   2437         case CSSSelector::End:
   2438             if (!value.endsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
   2439                 return false;
   2440             break;
   2441         case CSSSelector::Hyphen:
   2442             if (value.length() < sel->value().length())
   2443                 return false;
   2444             if (!value.startsWith(sel->value(), caseSensitive))
   2445                 return false;
   2446             // It they start the same, check for exact match or following '-':
   2447             if (value.length() != sel->value().length() && value[sel->value().length()] != '-')
   2448                 return false;
   2449             break;
   2450         case CSSSelector::PseudoClass:
   2451         case CSSSelector::PseudoElement:
   2452         default:
   2453             break;
   2454         }
   2455     }
   2456 
   2457     if (sel->m_match == CSSSelector::PseudoClass) {
   2458         // Handle :not up front.
   2459         if (sel->pseudoType() == CSSSelector::PseudoNot) {
   2460             ASSERT(sel->selectorList());
   2461             for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) {
   2462                 // :not cannot nest. I don't really know why this is a
   2463                 // restriction in CSS3, but it is, so let's honor it.
   2464                 // the parser enforces that this never occurs
   2465                 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
   2466 
   2467                 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle))
   2468                     return true;
   2469             }
   2470         } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
   2471             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
   2472             // (since there are no elements involved).
   2473             return checkScrollbarPseudoClass(sel, dynamicPseudo);
   2474         } else if (dynamicPseudo == SELECTION) {
   2475             if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
   2476                 return !m_document->page()->focusController()->isActive();
   2477         }
   2478 
   2479         // Normal element pseudo class checking.
   2480         switch (sel->pseudoType()) {
   2481             // Pseudo classes:
   2482             case CSSSelector::PseudoNot:
   2483                 break; // Already handled up above.
   2484             case CSSSelector::PseudoEmpty: {
   2485                 bool result = true;
   2486                 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
   2487                     if (n->isElementNode()) {
   2488                         result = false;
   2489                         break;
   2490                     } else if (n->isTextNode()) {
   2491                         Text* textNode = static_cast<Text*>(n);
   2492                         if (!textNode->data().isEmpty()) {
   2493                             result = false;
   2494                             break;
   2495                         }
   2496                     }
   2497                 }
   2498                 if (!m_collectRulesOnly) {
   2499                     if (elementStyle)
   2500                         elementStyle->setEmptyState(result);
   2501                     else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
   2502                         e->renderStyle()->setEmptyState(result);
   2503                 }
   2504                 return result;
   2505             }
   2506             case CSSSelector::PseudoFirstChild: {
   2507                 // first-child matches the first child that is an element
   2508                 if (e->parentNode() && e->parentNode()->isElementNode()) {
   2509                     bool result = false;
   2510                     Node* n = e->previousSibling();
   2511                     while (n && !n->isElementNode())
   2512                         n = n->previousSibling();
   2513                     if (!n)
   2514                         result = true;
   2515                     if (!m_collectRulesOnly) {
   2516                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
   2517                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
   2518                         if (parentStyle)
   2519                             parentStyle->setChildrenAffectedByFirstChildRules();
   2520                         if (result && childStyle)
   2521                             childStyle->setFirstChildState();
   2522                     }
   2523                     return result;
   2524                 }
   2525                 break;
   2526             }
   2527             case CSSSelector::PseudoFirstOfType: {
   2528                 // first-of-type matches the first element of its type
   2529                 if (e->parentNode() && e->parentNode()->isElementNode()) {
   2530                     bool result = false;
   2531                     const QualifiedName& type = e->tagQName();
   2532                     Node* n = e->previousSibling();
   2533                     while (n) {
   2534                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2535                             break;
   2536                         n = n->previousSibling();
   2537                     }
   2538                     if (!n)
   2539                         result = true;
   2540                     if (!m_collectRulesOnly) {
   2541                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
   2542                         if (parentStyle)
   2543                             parentStyle->setChildrenAffectedByForwardPositionalRules();
   2544                     }
   2545                     return result;
   2546                 }
   2547                 break;
   2548             }
   2549             case CSSSelector::PseudoLastChild: {
   2550                 // last-child matches the last child that is an element
   2551                 if (Element* parentElement = e->parentElement()) {
   2552                     bool result = false;
   2553                     if (parentElement->isFinishedParsingChildren()) {
   2554                         Node* n = e->nextSibling();
   2555                         while (n && !n->isElementNode())
   2556                             n = n->nextSibling();
   2557                         if (!n)
   2558                             result = true;
   2559                     }
   2560                     if (!m_collectRulesOnly) {
   2561                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
   2562                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2563                         if (parentStyle)
   2564                             parentStyle->setChildrenAffectedByLastChildRules();
   2565                         if (result && childStyle)
   2566                             childStyle->setLastChildState();
   2567                     }
   2568                     return result;
   2569                 }
   2570                 break;
   2571             }
   2572             case CSSSelector::PseudoLastOfType: {
   2573                 // last-of-type matches the last element of its type
   2574                 if (Element* parentElement = e->parentElement()) {
   2575                     if (!m_collectRulesOnly) {
   2576                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2577                         if (parentStyle)
   2578                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
   2579                     }
   2580                     if (!parentElement->isFinishedParsingChildren())
   2581                         return false;
   2582                     bool result = false;
   2583                     const QualifiedName& type = e->tagQName();
   2584                     Node* n = e->nextSibling();
   2585                     while (n) {
   2586                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2587                             break;
   2588                         n = n->nextSibling();
   2589                     }
   2590                     if (!n)
   2591                         result = true;
   2592                     return result;
   2593                 }
   2594                 break;
   2595             }
   2596             case CSSSelector::PseudoOnlyChild: {
   2597                 if (Element* parentElement = e->parentElement()) {
   2598                     bool firstChild = false;
   2599                     bool lastChild = false;
   2600 
   2601                     Node* n = e->previousSibling();
   2602                     while (n && !n->isElementNode())
   2603                         n = n->previousSibling();
   2604                     if (!n)
   2605                         firstChild = true;
   2606                     if (firstChild && parentElement->isFinishedParsingChildren()) {
   2607                         n = e->nextSibling();
   2608                         while (n && !n->isElementNode())
   2609                             n = n->nextSibling();
   2610                         if (!n)
   2611                             lastChild = true;
   2612                     }
   2613                     if (!m_collectRulesOnly) {
   2614                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
   2615                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2616                         if (parentStyle) {
   2617                             parentStyle->setChildrenAffectedByFirstChildRules();
   2618                             parentStyle->setChildrenAffectedByLastChildRules();
   2619                         }
   2620                         if (firstChild && childStyle)
   2621                             childStyle->setFirstChildState();
   2622                         if (lastChild && childStyle)
   2623                             childStyle->setLastChildState();
   2624                     }
   2625                     return firstChild && lastChild;
   2626                 }
   2627                 break;
   2628             }
   2629             case CSSSelector::PseudoOnlyOfType: {
   2630                 // FIXME: This selector is very slow.
   2631                 if (Element* parentElement = e->parentElement()) {
   2632                     if (!m_collectRulesOnly) {
   2633                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2634                         if (parentStyle) {
   2635                             parentStyle->setChildrenAffectedByForwardPositionalRules();
   2636                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
   2637                         }
   2638                     }
   2639                     if (!parentElement->isFinishedParsingChildren())
   2640                         return false;
   2641                     bool firstChild = false;
   2642                     bool lastChild = false;
   2643                     const QualifiedName& type = e->tagQName();
   2644                     Node* n = e->previousSibling();
   2645                     while (n) {
   2646                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2647                             break;
   2648                         n = n->previousSibling();
   2649                     }
   2650                     if (!n)
   2651                         firstChild = true;
   2652                     if (firstChild) {
   2653                         n = e->nextSibling();
   2654                         while (n) {
   2655                             if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2656                                 break;
   2657                             n = n->nextSibling();
   2658                         }
   2659                         if (!n)
   2660                             lastChild = true;
   2661                     }
   2662                     return firstChild && lastChild;
   2663                 }
   2664                 break;
   2665             }
   2666             case CSSSelector::PseudoNthChild: {
   2667                 if (!sel->parseNth())
   2668                     break;
   2669                 if (Element* parentElement = e->parentElement()) {
   2670                     int count = 1;
   2671                     Node* n = e->previousSibling();
   2672                     while (n) {
   2673                         if (n->isElementNode()) {
   2674                             RenderStyle* s = n->renderStyle();
   2675                             unsigned index = s ? s->childIndex() : 0;
   2676                             if (index) {
   2677                                 count += index;
   2678                                 break;
   2679                             }
   2680                             count++;
   2681                         }
   2682                         n = n->previousSibling();
   2683                     }
   2684 
   2685                     if (!m_collectRulesOnly) {
   2686                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
   2687                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2688                         if (childStyle)
   2689                             childStyle->setChildIndex(count);
   2690                         if (parentStyle)
   2691                             parentStyle->setChildrenAffectedByForwardPositionalRules();
   2692                     }
   2693 
   2694                     if (sel->matchNth(count))
   2695                         return true;
   2696                 }
   2697                 break;
   2698             }
   2699             case CSSSelector::PseudoNthOfType: {
   2700                 if (!sel->parseNth())
   2701                     break;
   2702                 if (Element* parentElement = e->parentElement()) {
   2703                     int count = 1;
   2704                     const QualifiedName& type = e->tagQName();
   2705                     Node* n = e->previousSibling();
   2706                     while (n) {
   2707                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2708                             count++;
   2709                         n = n->previousSibling();
   2710                     }
   2711 
   2712                     if (!m_collectRulesOnly) {
   2713                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2714                         if (parentStyle)
   2715                             parentStyle->setChildrenAffectedByForwardPositionalRules();
   2716                     }
   2717 
   2718                     if (sel->matchNth(count))
   2719                         return true;
   2720                 }
   2721                 break;
   2722             }
   2723             case CSSSelector::PseudoNthLastChild: {
   2724                 if (!sel->parseNth())
   2725                     break;
   2726                 if (Element* parentElement = e->parentElement()) {
   2727                     if (!m_collectRulesOnly) {
   2728                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2729                         if (parentStyle)
   2730                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
   2731                     }
   2732                     if (!parentElement->isFinishedParsingChildren())
   2733                         return false;
   2734                     int count = 1;
   2735                     Node* n = e->nextSibling();
   2736                     while (n) {
   2737                         if (n->isElementNode())
   2738                             count++;
   2739                         n = n->nextSibling();
   2740                     }
   2741                     if (sel->matchNth(count))
   2742                         return true;
   2743                 }
   2744                 break;
   2745             }
   2746             case CSSSelector::PseudoNthLastOfType: {
   2747                 if (!sel->parseNth())
   2748                     break;
   2749                 if (Element* parentElement = e->parentElement()) {
   2750                     if (!m_collectRulesOnly) {
   2751                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
   2752                         if (parentStyle)
   2753                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
   2754                     }
   2755                     if (!parentElement->isFinishedParsingChildren())
   2756                         return false;
   2757                     int count = 1;
   2758                     const QualifiedName& type = e->tagQName();
   2759                     Node* n = e->nextSibling();
   2760                     while (n) {
   2761                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
   2762                             count++;
   2763                         n = n->nextSibling();
   2764                     }
   2765                     if (sel->matchNth(count))
   2766                         return true;
   2767                 }
   2768                 break;
   2769             }
   2770             case CSSSelector::PseudoTarget:
   2771                 if (e == e->document()->cssTarget())
   2772                     return true;
   2773                 break;
   2774             case CSSSelector::PseudoAny:
   2775                 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
   2776                     if (checkSelector(selector, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches)
   2777                         return true;
   2778                 }
   2779                 break;
   2780             case CSSSelector::PseudoAnyLink:
   2781                 if (e && e->isLink())
   2782                     return true;
   2783                 break;
   2784             case CSSSelector::PseudoAutofill: {
   2785                 if (!e || !e->isFormControlElement())
   2786                     break;
   2787                 if (InputElement* inputElement = e->toInputElement())
   2788                     return inputElement->isAutofilled();
   2789                 break;
   2790             }
   2791             case CSSSelector::PseudoLink:
   2792                 if (e && e->isLink())
   2793                     return !m_matchVisitedPseudoClass;
   2794                 break;
   2795             case CSSSelector::PseudoVisited:
   2796                 if (e && e->isLink())
   2797                     return m_matchVisitedPseudoClass;
   2798                 break;
   2799             case CSSSelector::PseudoDrag: {
   2800                 if (elementStyle)
   2801                     elementStyle->setAffectedByDragRules(true);
   2802                 else if (e->renderStyle())
   2803                     e->renderStyle()->setAffectedByDragRules(true);
   2804                 if (e->renderer() && e->renderer()->isDragging())
   2805                     return true;
   2806                 break;
   2807             }
   2808             case CSSSelector::PseudoFocus:
   2809                 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
   2810                     return true;
   2811                 break;
   2812             case CSSSelector::PseudoHover: {
   2813                 // If we're in quirks mode, then hover should never match anchors with no
   2814                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
   2815                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
   2816                     if (elementStyle)
   2817                         elementStyle->setAffectedByHoverRules(true);
   2818                     else if (e->renderStyle())
   2819                         e->renderStyle()->setAffectedByHoverRules(true);
   2820                     if (e->hovered())
   2821                         return true;
   2822                 }
   2823                 break;
   2824             }
   2825             case CSSSelector::PseudoActive:
   2826                 // If we're in quirks mode, then :active should never match anchors with no
   2827                 // href and *:active should not match anything.
   2828                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
   2829                     if (elementStyle)
   2830                         elementStyle->setAffectedByActiveRules(true);
   2831                     else if (e->renderStyle())
   2832                         e->renderStyle()->setAffectedByActiveRules(true);
   2833                     if (e->active())
   2834                         return true;
   2835                 }
   2836                 break;
   2837             case CSSSelector::PseudoEnabled:
   2838                 if (e && e->isFormControlElement())
   2839                     return e->isEnabledFormControl();
   2840                 break;
   2841             case CSSSelector::PseudoFullPageMedia:
   2842                 return e && e->document() && e->document()->isMediaDocument();
   2843                 break;
   2844             case CSSSelector::PseudoDefault:
   2845                 return e && e->isDefaultButtonForForm();
   2846             case CSSSelector::PseudoDisabled:
   2847                 if (e && e->isFormControlElement())
   2848                     return !e->isEnabledFormControl();
   2849                 break;
   2850             case CSSSelector::PseudoReadOnly: {
   2851                 if (!e || !e->isFormControlElement())
   2852                     return false;
   2853                 return e->isTextFormControl() && e->isReadOnlyFormControl();
   2854             }
   2855             case CSSSelector::PseudoReadWrite: {
   2856                 if (!e || !e->isFormControlElement())
   2857                     return false;
   2858                 return e->isTextFormControl() && !e->isReadOnlyFormControl();
   2859             }
   2860             case CSSSelector::PseudoOptional:
   2861                 return e && e->isOptionalFormControl();
   2862             case CSSSelector::PseudoRequired:
   2863                 return e && e->isRequiredFormControl();
   2864             case CSSSelector::PseudoValid: {
   2865                 if (!e)
   2866                     return false;
   2867                 e->document()->setContainsValidityStyleRules();
   2868                 return e->willValidate() && e->isValidFormControlElement();
   2869             } case CSSSelector::PseudoInvalid: {
   2870                 if (!e)
   2871                     return false;
   2872                 e->document()->setContainsValidityStyleRules();
   2873                 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
   2874             } case CSSSelector::PseudoChecked: {
   2875                 if (!e || !e->isFormControlElement())
   2876                     break;
   2877                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
   2878                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
   2879                 // obey the CSS spec here in the test for matching the pseudo.
   2880                 InputElement* inputElement = e->toInputElement();
   2881                 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate())
   2882                     return true;
   2883                 break;
   2884             }
   2885             case CSSSelector::PseudoIndeterminate: {
   2886                 if (!e || !e->isFormControlElement())
   2887                     break;
   2888                 InputElement* inputElement = e->toInputElement();
   2889                 if (inputElement && inputElement->isIndeterminate())
   2890                     return true;
   2891                 break;
   2892             }
   2893             case CSSSelector::PseudoRoot:
   2894                 if (e == e->document()->documentElement())
   2895                     return true;
   2896                 break;
   2897             case CSSSelector::PseudoLang: {
   2898                 AtomicString value = e->computeInheritedLanguage();
   2899                 const AtomicString& argument = sel->argument();
   2900                 if (value.isEmpty() || !value.startsWith(argument, false))
   2901                     break;
   2902                 if (value.length() != argument.length() && value[argument.length()] != '-')
   2903                     break;
   2904                 return true;
   2905             }
   2906 #if ENABLE(FULLSCREEN_API)
   2907             case CSSSelector::PseudoFullScreen:
   2908                 // While a Document is in the fullscreen state, and the document's current fullscreen
   2909                 // element is an element in the document, the 'full-screen' pseudoclass applies to
   2910                 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing
   2911                 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
   2912                 if (!e->document()->webkitIsFullScreen())
   2913                     return false;
   2914                 if (e != e->document()->webkitCurrentFullScreenElement())
   2915                     return false;
   2916                 return true;
   2917             case CSSSelector::PseudoFullScreenDocument:
   2918                 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
   2919                 // to all elements of that Document.
   2920                 if (!e->document()->webkitIsFullScreen())
   2921                     return false;
   2922                 return true;
   2923 #endif
   2924             case CSSSelector::PseudoInRange:
   2925                 if (!e)
   2926                     return false;
   2927                 e->document()->setContainsValidityStyleRules();
   2928                 return e->isInRange();
   2929             case CSSSelector::PseudoOutOfRange:
   2930                 if (!e)
   2931                     return false;
   2932                 e->document()->setContainsValidityStyleRules();
   2933                 return e->isOutOfRange();
   2934             case CSSSelector::PseudoUnknown:
   2935             case CSSSelector::PseudoNotParsed:
   2936             default:
   2937                 ASSERT_NOT_REACHED();
   2938                 break;
   2939         }
   2940         return false;
   2941     }
   2942     if (sel->m_match == CSSSelector::PseudoElement) {
   2943         if (!elementStyle && !m_collectRulesOnly)
   2944             return false;
   2945 
   2946         PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
   2947         if (pseudoId == FIRST_LETTER) {
   2948             if (Document* document = e->document())
   2949                 document->setUsesFirstLetterRules(true);
   2950         }
   2951         if (pseudoId != NOPSEUDO)
   2952             dynamicPseudo = pseudoId;
   2953     }
   2954     // ### add the rest of the checks...
   2955     return true;
   2956 }
   2957 
   2958 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
   2959 {
   2960     RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
   2961     ScrollbarPart part = RenderScrollbar::partForStyleResolve();
   2962 
   2963     // FIXME: This is a temporary hack for resizers and scrollbar corners.  Eventually :window-inactive should become a real
   2964     // pseudo class and just apply to everything.
   2965     if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
   2966         return !m_document->page()->focusController()->isActive();
   2967 
   2968     if (!scrollbar)
   2969         return false;
   2970 
   2971     ASSERT(sel->m_match == CSSSelector::PseudoClass);
   2972     switch (sel->pseudoType()) {
   2973         case CSSSelector::PseudoEnabled:
   2974             return scrollbar->enabled();
   2975         case CSSSelector::PseudoDisabled:
   2976             return !scrollbar->enabled();
   2977         case CSSSelector::PseudoHover: {
   2978             ScrollbarPart hoveredPart = scrollbar->hoveredPart();
   2979             if (part == ScrollbarBGPart)
   2980                 return hoveredPart != NoPart;
   2981             if (part == TrackBGPart)
   2982                 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
   2983             return part == hoveredPart;
   2984         }
   2985         case CSSSelector::PseudoActive: {
   2986             ScrollbarPart pressedPart = scrollbar->pressedPart();
   2987             if (part == ScrollbarBGPart)
   2988                 return pressedPart != NoPart;
   2989             if (part == TrackBGPart)
   2990                 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
   2991             return part == pressedPart;
   2992         }
   2993         case CSSSelector::PseudoHorizontal:
   2994             return scrollbar->orientation() == HorizontalScrollbar;
   2995         case CSSSelector::PseudoVertical:
   2996             return scrollbar->orientation() == VerticalScrollbar;
   2997         case CSSSelector::PseudoDecrement:
   2998             return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
   2999         case CSSSelector::PseudoIncrement:
   3000             return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
   3001         case CSSSelector::PseudoStart:
   3002             return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
   3003         case CSSSelector::PseudoEnd:
   3004             return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
   3005         case CSSSelector::PseudoDoubleButton: {
   3006             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
   3007             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
   3008                 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
   3009             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
   3010                 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
   3011             return false;
   3012         }
   3013         case CSSSelector::PseudoSingleButton: {
   3014             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
   3015             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
   3016                 return buttonsPlacement == ScrollbarButtonsSingle;
   3017             return false;
   3018         }
   3019         case CSSSelector::PseudoNoButton: {
   3020             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
   3021             if (part == BackTrackPart)
   3022                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
   3023             if (part == ForwardTrackPart)
   3024                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
   3025             return false;
   3026         }
   3027         case CSSSelector::PseudoCornerPresent:
   3028             return scrollbar->scrollableArea()->isScrollCornerVisible();
   3029         default:
   3030             return false;
   3031     }
   3032 }
   3033 
   3034 // -----------------------------------------------------------------
   3035 
   3036 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
   3037 {
   3038     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
   3039     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
   3040         return false;
   3041     if (selector->m_match == CSSSelector::None)
   3042         return true;
   3043     if (selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
   3044         return false;
   3045     return selector->tag() == starAtom;
   3046 }
   3047 
   3048 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
   3049     : m_rule(rule)
   3050     , m_selector(selector)
   3051     , m_specificity(selector->specificity())
   3052     , m_position(position)
   3053     , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
   3054     , m_hasMultipartSelector(selector->tagHistory())
   3055     , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
   3056 {
   3057     collectDescendantSelectorIdentifierHashes();
   3058 }
   3059 
   3060 inline void RuleData::collectIdentifierHashes(const CSSSelector* selector, unsigned& identifierCount)
   3061 {
   3062     if ((selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class) && !selector->value().isEmpty())
   3063         m_descendantSelectorIdentifierHashes[identifierCount++] = selector->value().impl()->existingHash();
   3064     if (identifierCount == maximumIdentifierCount)
   3065         return;
   3066     const AtomicString& localName = selector->tag().localName();
   3067     if (localName != starAtom)
   3068         m_descendantSelectorIdentifierHashes[identifierCount++] = localName.impl()->existingHash();
   3069 }
   3070 
   3071 inline void RuleData::collectDescendantSelectorIdentifierHashes()
   3072 {
   3073     unsigned identifierCount = 0;
   3074     CSSSelector::Relation relation = m_selector->relation();
   3075 
   3076     // Skip the topmost selector. It is handled quickly by the rule hashes.
   3077     bool skipOverSubselectors = true;
   3078     for (const CSSSelector* selector = m_selector->tagHistory(); selector; selector = selector->tagHistory()) {
   3079         // Only collect identifiers that match ancestors.
   3080         switch (relation) {
   3081         case CSSSelector::SubSelector:
   3082             if (!skipOverSubselectors)
   3083                 collectIdentifierHashes(selector, identifierCount);
   3084             break;
   3085         case CSSSelector::DirectAdjacent:
   3086         case CSSSelector::IndirectAdjacent:
   3087         case CSSSelector::ShadowDescendant:
   3088             skipOverSubselectors = true;
   3089             break;
   3090         case CSSSelector::Descendant:
   3091         case CSSSelector::Child:
   3092             skipOverSubselectors = false;
   3093             collectIdentifierHashes(selector, identifierCount);
   3094             break;
   3095         }
   3096         if (identifierCount == maximumIdentifierCount)
   3097             return;
   3098         relation = selector->relation();
   3099     }
   3100     m_descendantSelectorIdentifierHashes[identifierCount] = 0;
   3101 }
   3102 
   3103 RuleSet::RuleSet()
   3104     : m_ruleCount(0)
   3105     , m_autoShrinkToFitEnabled(true)
   3106 {
   3107 }
   3108 
   3109 RuleSet::~RuleSet()
   3110 {
   3111     deleteAllValues(m_idRules);
   3112     deleteAllValues(m_classRules);
   3113     deleteAllValues(m_pseudoRules);
   3114     deleteAllValues(m_tagRules);
   3115 }
   3116 
   3117 
   3118 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
   3119                               CSSStyleRule* rule, CSSSelector* sel)
   3120 {
   3121     if (!key) return;
   3122     Vector<RuleData>* rules = map.get(key);
   3123     if (!rules) {
   3124         rules = new Vector<RuleData>;
   3125         map.set(key, rules);
   3126     }
   3127     rules->append(RuleData(rule, sel, m_ruleCount++));
   3128 }
   3129 
   3130 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
   3131 {
   3132     if (sel->m_match == CSSSelector::Id) {
   3133         addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
   3134         return;
   3135     }
   3136     if (sel->m_match == CSSSelector::Class) {
   3137         addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
   3138         return;
   3139     }
   3140 
   3141     if (sel->isUnknownPseudoElement()) {
   3142         addToRuleSet(sel->value().impl(), m_pseudoRules, rule, sel);
   3143         return;
   3144     }
   3145 
   3146     const AtomicString& localName = sel->tag().localName();
   3147     if (localName != starAtom) {
   3148         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
   3149         return;
   3150     }
   3151 
   3152     m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
   3153 }
   3154 
   3155 void RuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
   3156 {
   3157     m_pageRules.append(RuleData(rule, sel, m_pageRules.size()));
   3158 }
   3159 
   3160 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
   3161 {
   3162     if (!sheet)
   3163         return;
   3164 
   3165     // No media implies "all", but if a media list exists it must
   3166     // contain our current medium
   3167     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
   3168         return; // the style sheet doesn't apply
   3169 
   3170     int len = sheet->length();
   3171 
   3172     for (int i = 0; i < len; i++) {
   3173         StyleBase* item = sheet->item(i);
   3174         if (item->isStyleRule())
   3175             addStyleRule(static_cast<CSSStyleRule*>(item));
   3176         else if (item->isImportRule()) {
   3177             CSSImportRule* import = static_cast<CSSImportRule*>(item);
   3178             if (!import->media() || medium.eval(import->media(), styleSelector))
   3179                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
   3180         }
   3181         else if (item->isMediaRule()) {
   3182             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
   3183             CSSRuleList* rules = r->cssRules();
   3184 
   3185             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
   3186                 // Traverse child elements of the @media rule.
   3187                 for (unsigned j = 0; j < rules->length(); j++) {
   3188                     CSSRule *childItem = rules->item(j);
   3189                     if (childItem->isStyleRule()) {
   3190                         // It is a StyleRule, so append it to our list
   3191                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
   3192                     } else if (childItem->isFontFaceRule() && styleSelector) {
   3193                         // Add this font face to our set.
   3194                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
   3195                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
   3196                     } else if (childItem->isKeyframesRule() && styleSelector) {
   3197                         // Add this keyframe rule to our set.
   3198                         styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
   3199                     }
   3200                 }   // for rules
   3201             }   // if rules
   3202         } else if (item->isFontFaceRule() && styleSelector) {
   3203             // Add this font face to our set.
   3204             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
   3205             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
   3206         } else if (item->isKeyframesRule())
   3207             styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item));
   3208     }
   3209     if (m_autoShrinkToFitEnabled)
   3210         shrinkToFit();
   3211 }
   3212 
   3213 void RuleSet::addStyleRule(CSSStyleRule* rule)
   3214 {
   3215     if (rule->isPageRule()) {
   3216         CSSPageRule* pageRule = static_cast<CSSPageRule*>(rule);
   3217         addPageRule(pageRule, pageRule->selectorList().first());
   3218     } else {
   3219         for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
   3220             addRule(rule, s);
   3221     }
   3222 }
   3223 
   3224 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
   3225 {
   3226     if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
   3227         features.idsInRules.add(selector->value().impl());
   3228     switch (selector->pseudoType()) {
   3229     case CSSSelector::PseudoFirstLine:
   3230         features.usesFirstLineRules = true;
   3231         break;
   3232     case CSSSelector::PseudoBefore:
   3233     case CSSSelector::PseudoAfter:
   3234         features.usesBeforeAfterRules = true;
   3235         break;
   3236     case CSSSelector::PseudoLink:
   3237     case CSSSelector::PseudoVisited:
   3238         features.usesLinkRules = true;
   3239         break;
   3240     default:
   3241         break;
   3242     }
   3243 }
   3244 
   3245 static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules)
   3246 {
   3247     unsigned size = rules.size();
   3248     for (unsigned i = 0; i < size; ++i) {
   3249         const RuleData& ruleData = rules[i];
   3250         bool foundSiblingSelector = false;
   3251         for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
   3252             collectFeaturesFromSelector(features, selector);
   3253 
   3254             if (CSSSelectorList* selectorList = selector->selectorList()) {
   3255                 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
   3256                     if (selector->isSiblingSelector())
   3257                         foundSiblingSelector = true;
   3258                     collectFeaturesFromSelector(features, subSelector);
   3259                 }
   3260             } else if (selector->isSiblingSelector())
   3261                 foundSiblingSelector = true;
   3262         }
   3263         if (foundSiblingSelector) {
   3264             if (!features.siblingRules)
   3265                 features.siblingRules = adoptPtr(new RuleSet);
   3266             features.siblingRules->addRule(ruleData.rule(), ruleData.selector());
   3267         }
   3268     }
   3269 }
   3270 
   3271 void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const
   3272 {
   3273     AtomRuleMap::const_iterator end = m_idRules.end();
   3274     for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
   3275         collectFeaturesFromList(features, *it->second);
   3276     end = m_classRules.end();
   3277     for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
   3278         collectFeaturesFromList(features, *it->second);
   3279     end = m_tagRules.end();
   3280     for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
   3281         collectFeaturesFromList(features, *it->second);
   3282     end = m_pseudoRules.end();
   3283     for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it)
   3284         collectFeaturesFromList(features, *it->second);
   3285     collectFeaturesFromList(features, m_universalRules);
   3286 }
   3287 
   3288 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
   3289 {
   3290     RuleSet::AtomRuleMap::iterator end = map.end();
   3291     for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
   3292         it->second->shrinkToFit();
   3293 }
   3294 
   3295 void RuleSet::shrinkToFit()
   3296 {
   3297     shrinkMapVectorsToFit(m_idRules);
   3298     shrinkMapVectorsToFit(m_classRules);
   3299     shrinkMapVectorsToFit(m_tagRules);
   3300     shrinkMapVectorsToFit(m_pseudoRules);
   3301     m_universalRules.shrinkToFit();
   3302     m_pageRules.shrinkToFit();
   3303 }
   3304 
   3305 // -------------------------------------------------------------------------------------
   3306 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
   3307 
   3308 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
   3309 {
   3310     // This function is tolerant of a null style value. The only place style is used is in
   3311     // length measurements, like 'ems' and 'px'. And in those cases style is only used
   3312     // when the units are EMS or EXS. So we will just fail in those cases.
   3313     Length l;
   3314     if (!primitiveValue) {
   3315         if (ok)
   3316             *ok = false;
   3317     } else {
   3318         int type = primitiveValue->primitiveType();
   3319 
   3320         if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
   3321             if (ok)
   3322                 *ok = false;
   3323         } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
   3324             if (toFloat)
   3325                 l = Length(primitiveValue->computeLengthDouble(style, rootStyle, multiplier), Fixed);
   3326             else
   3327                 l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed);
   3328         }
   3329         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   3330             l = Length(primitiveValue->getDoubleValue(), Percent);
   3331         else if (type == CSSPrimitiveValue::CSS_NUMBER)
   3332             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
   3333         else if (ok)
   3334             *ok = false;
   3335     }
   3336     return l;
   3337 }
   3338 
   3339 static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
   3340 {
   3341     return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
   3342 }
   3343 
   3344 static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
   3345 {
   3346     return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
   3347 }
   3348 
   3349 template <bool applyFirst>
   3350 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex)
   3351 {
   3352     if (startIndex == -1)
   3353         return;
   3354 
   3355     for (int i = startIndex; i <= endIndex; i++) {
   3356         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
   3357         CSSMutableStyleDeclaration::const_iterator end = decl->end();
   3358         for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {
   3359             const CSSProperty& current = *it;
   3360             if (isImportant == current.isImportant()) {
   3361                 int property = current.id();
   3362 
   3363                 if (applyFirst) {
   3364                     COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
   3365                     COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 14, CSS_zoom_is_end_of_first_prop_range);
   3366                     COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
   3367 
   3368                     // give special priority to font-xxx, color properties, etc
   3369                     if (property <= CSSPropertyLineHeight) {
   3370                         // we apply line-height later
   3371                         if (property == CSSPropertyLineHeight)
   3372                             m_lineHeightValue = current.value();
   3373                         else
   3374                             applyProperty(current.id(), current.value());
   3375                     }
   3376                 } else {
   3377                     if (property > CSSPropertyLineHeight)
   3378                         applyProperty(current.id(), current.value());
   3379                 }
   3380             }
   3381         }
   3382     }
   3383 }
   3384 
   3385 void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
   3386 {
   3387     m_matchedRules.clear();
   3388 
   3389     if (!rules)
   3390         return;
   3391 
   3392     matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName);
   3393 
   3394     // If we didn't match any rules, we're done.
   3395     if (m_matchedRules.isEmpty())
   3396         return;
   3397 
   3398     // Sort the set of matched rules.
   3399     sortMatchedRules();
   3400 
   3401     // Now transfer the set of matched rules over to our list of decls.
   3402     for (unsigned i = 0; i < m_matchedRules.size(); i++)
   3403         addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
   3404 }
   3405 
   3406 void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
   3407 {
   3408     if (!rules)
   3409         return;
   3410 
   3411     unsigned size = rules->size();
   3412     for (unsigned i = 0; i < size; ++i) {
   3413         const RuleData& ruleData = rules->at(i);
   3414         CSSStyleRule* rule = ruleData.rule();
   3415         const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
   3416         if (selectorLocalName != starAtom && selectorLocalName != pageName)
   3417             continue;
   3418         CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
   3419         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
   3420             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
   3421             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
   3422             continue;
   3423 
   3424         // If the rule has no properties to apply, then ignore it.
   3425         CSSMutableStyleDeclaration* decl = rule->declaration();
   3426         if (!decl || !decl->length())
   3427             continue;
   3428 
   3429         // Add this rule to our list of matched rules.
   3430         addMatchedRule(&ruleData);
   3431     }
   3432 }
   3433 
   3434 bool CSSStyleSelector::isLeftPage(int pageIndex) const
   3435 {
   3436     bool isFirstPageLeft = false;
   3437     if (!m_rootElementStyle->isLeftToRightDirection())
   3438         isFirstPageLeft = true;
   3439 
   3440     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
   3441 }
   3442 
   3443 bool CSSStyleSelector::isFirstPage(int pageIndex) const
   3444 {
   3445     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
   3446     return (!pageIndex);
   3447 }
   3448 
   3449 String CSSStyleSelector::pageName(int /* pageIndex */) const
   3450 {
   3451     // FIXME: Implement page index to page name mapping.
   3452     return "";
   3453 }
   3454 
   3455 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
   3456 {
   3457     CounterDirectiveMap& map = style->accessCounterDirectives();
   3458     typedef CounterDirectiveMap::iterator Iterator;
   3459 
   3460     Iterator end = map.end();
   3461     for (Iterator it = map.begin(); it != end; ++it)
   3462         if (isReset)
   3463             it->second.m_reset = false;
   3464         else
   3465             it->second.m_increment = false;
   3466 
   3467     int length = list ? list->length() : 0;
   3468     for (int i = 0; i < length; ++i) {
   3469         CSSValue* currValue = list->itemWithoutBoundsCheck(i);
   3470         if (!currValue->isPrimitiveValue())
   3471             continue;
   3472 
   3473         Pair* pair = static_cast<CSSPrimitiveValue*>(currValue)->getPairValue();
   3474         if (!pair || !pair->first() || !pair->second())
   3475             continue;
   3476 
   3477         AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
   3478         // FIXME: What about overflow?
   3479         int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
   3480         CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
   3481         if (isReset) {
   3482             directives.m_reset = true;
   3483             directives.m_resetValue = value;
   3484         } else {
   3485             if (directives.m_increment)
   3486                 directives.m_incrementValue += value;
   3487             else {
   3488                 directives.m_increment = true;
   3489                 directives.m_incrementValue = value;
   3490             }
   3491         }
   3492     }
   3493 }
   3494 
   3495 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style)
   3496 {
   3497     initElement(0);
   3498     initForStyleResolve(0, style);
   3499     m_style = style;
   3500     if (value)
   3501         applyProperty(id, value);
   3502 }
   3503 
   3504 inline bool isValidVisitedLinkProperty(int id)
   3505 {
   3506     switch(static_cast<CSSPropertyID>(id)) {
   3507         case CSSPropertyBackgroundColor:
   3508         case CSSPropertyBorderLeftColor:
   3509         case CSSPropertyBorderRightColor:
   3510         case CSSPropertyBorderTopColor:
   3511         case CSSPropertyBorderBottomColor:
   3512         case CSSPropertyColor:
   3513         case CSSPropertyOutlineColor:
   3514         case CSSPropertyWebkitColumnRuleColor:
   3515         case CSSPropertyWebkitTextEmphasisColor:
   3516         case CSSPropertyWebkitTextFillColor:
   3517         case CSSPropertyWebkitTextStrokeColor:
   3518         // Also allow shorthands so that inherit/initial still work.
   3519         case CSSPropertyBackground:
   3520         case CSSPropertyBorderLeft:
   3521         case CSSPropertyBorderRight:
   3522         case CSSPropertyBorderTop:
   3523         case CSSPropertyBorderBottom:
   3524         case CSSPropertyOutline:
   3525         case CSSPropertyWebkitColumnRule:
   3526 #if ENABLE(SVG)
   3527         case CSSPropertyFill:
   3528         case CSSPropertyStroke:
   3529 #endif
   3530             return true;
   3531         default:
   3532             break;
   3533     }
   3534 
   3535     return false;
   3536 }
   3537 
   3538 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
   3539 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
   3540 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
   3541 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
   3542 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
   3543 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
   3544 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
   3545 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
   3546 static inline bool useSVGZoomRules(const Element* e)
   3547 {
   3548     return e && e->isSVGElement();
   3549 }
   3550 
   3551 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
   3552 {
   3553     CSSPrimitiveValue* primitiveValue = 0;
   3554     if (value->isPrimitiveValue())
   3555         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   3556 
   3557     float zoomFactor = m_style->effectiveZoom();
   3558 
   3559     Length l;
   3560     bool apply = false;
   3561 
   3562     unsigned short valueType = value->cssValueType();
   3563 
   3564     bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
   3565     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
   3566 
   3567     id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
   3568 
   3569     if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) {
   3570         // Limit the properties that can be applied to only the ones honored by :visited.
   3571         return;
   3572     }
   3573 
   3574     CSSPropertyID property = static_cast<CSSPropertyID>(id);
   3575 
   3576     // check lookup table for implementations and use when available
   3577     if (m_applyProperty.implements(property)) {
   3578         if (isInherit)
   3579             m_applyProperty.applyInheritValue(property, this);
   3580         else if (isInitial)
   3581             m_applyProperty.applyInitialValue(property, this);
   3582         else
   3583             m_applyProperty.applyValue(property, this, value);
   3584         return;
   3585     }
   3586 
   3587     // What follows is a list that maps the CSS properties into their corresponding front-end
   3588     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
   3589     // are only hit when mapping "inherit" or "initial" into front-end values.
   3590     switch (property) {
   3591 // ident only properties
   3592     case CSSPropertyBorderCollapse:
   3593         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
   3594         if (!primitiveValue)
   3595             return;
   3596         switch (primitiveValue->getIdent()) {
   3597             case CSSValueCollapse:
   3598                 m_style->setBorderCollapse(true);
   3599                 break;
   3600             case CSSValueSeparate:
   3601                 m_style->setBorderCollapse(false);
   3602                 break;
   3603             default:
   3604                 return;
   3605         }
   3606         return;
   3607     case CSSPropertyOutlineStyle:
   3608         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
   3609         if (primitiveValue) {
   3610             if (primitiveValue->getIdent() == CSSValueAuto)
   3611                 m_style->setOutlineStyle(DOTTED, true);
   3612             else
   3613                 m_style->setOutlineStyle(*primitiveValue);
   3614         }
   3615         return;
   3616     case CSSPropertyCaptionSide:
   3617         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
   3618         return;
   3619     case CSSPropertyClear:
   3620         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
   3621         return;
   3622     case CSSPropertyDisplay:
   3623         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display)
   3624 #if ENABLE(WCSS)
   3625         if (primitiveValue) {
   3626             if (primitiveValue->getIdent() == CSSValueWapMarquee) {
   3627                 // Initialize WAP Marquee style
   3628                 m_style->setOverflowX(OMARQUEE);
   3629                 m_style->setOverflowY(OMARQUEE);
   3630                 m_style->setWhiteSpace(NOWRAP);
   3631                 m_style->setMarqueeDirection(MLEFT);
   3632                 m_style->setMarqueeSpeed(85); // Normal speed
   3633                 m_style->setMarqueeLoopCount(1);
   3634                 m_style->setMarqueeBehavior(MSCROLL);
   3635 
   3636                 if (m_parentStyle)
   3637                     m_style->setDisplay(m_parentStyle->display());
   3638                 else
   3639                     m_style->setDisplay(*primitiveValue);
   3640             } else
   3641                 m_style->setDisplay(*primitiveValue);
   3642         }
   3643 #endif
   3644         return;
   3645     case CSSPropertyEmptyCells:
   3646         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
   3647         return;
   3648     case CSSPropertyFloat:
   3649         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
   3650         return;
   3651     case CSSPropertyFontStyle:
   3652     {
   3653         FontDescription fontDescription = m_style->fontDescription();
   3654         if (isInherit)
   3655             fontDescription.setItalic(m_parentStyle->fontDescription().italic());
   3656         else if (isInitial)
   3657             fontDescription.setItalic(false);
   3658         else {
   3659             if (!primitiveValue)
   3660                 return;
   3661             switch (primitiveValue->getIdent()) {
   3662                 case CSSValueOblique:
   3663                 // FIXME: oblique is the same as italic for the moment...
   3664                 case CSSValueItalic:
   3665                     fontDescription.setItalic(true);
   3666                     break;
   3667                 case CSSValueNormal:
   3668                     fontDescription.setItalic(false);
   3669                     break;
   3670                 default:
   3671                     return;
   3672             }
   3673         }
   3674         if (m_style->setFontDescription(fontDescription))
   3675             m_fontDirty = true;
   3676         return;
   3677     }
   3678 
   3679     case CSSPropertyFontVariant:
   3680     {
   3681         FontDescription fontDescription = m_style->fontDescription();
   3682         if (isInherit)
   3683             fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps());
   3684         else if (isInitial)
   3685             fontDescription.setSmallCaps(false);
   3686         else {
   3687             if (!primitiveValue)
   3688                 return;
   3689             int id = primitiveValue->getIdent();
   3690             if (id == CSSValueNormal)
   3691                 fontDescription.setSmallCaps(false);
   3692             else if (id == CSSValueSmallCaps)
   3693                 fontDescription.setSmallCaps(true);
   3694             else
   3695                 return;
   3696         }
   3697         if (m_style->setFontDescription(fontDescription))
   3698             m_fontDirty = true;
   3699         return;
   3700     }
   3701 
   3702     case CSSPropertyFontWeight:
   3703     {
   3704         FontDescription fontDescription = m_style->fontDescription();
   3705         if (isInherit)
   3706             fontDescription.setWeight(m_parentStyle->fontDescription().weight());
   3707         else if (isInitial)
   3708             fontDescription.setWeight(FontWeightNormal);
   3709         else {
   3710             if (!primitiveValue)
   3711                 return;
   3712             if (primitiveValue->getIdent()) {
   3713                 switch (primitiveValue->getIdent()) {
   3714                     case CSSValueBolder:
   3715                         fontDescription.setWeight(fontDescription.bolderWeight());
   3716                         break;
   3717                     case CSSValueLighter:
   3718                         fontDescription.setWeight(fontDescription.lighterWeight());
   3719                         break;
   3720                     case CSSValueBold:
   3721                     case CSSValue700:
   3722                         fontDescription.setWeight(FontWeightBold);
   3723                         break;
   3724                     case CSSValueNormal:
   3725                     case CSSValue400:
   3726                         fontDescription.setWeight(FontWeightNormal);
   3727                         break;
   3728                     case CSSValue900:
   3729                         fontDescription.setWeight(FontWeight900);
   3730                         break;
   3731                     case CSSValue800:
   3732                         fontDescription.setWeight(FontWeight800);
   3733                         break;
   3734                     case CSSValue600:
   3735                         fontDescription.setWeight(FontWeight600);
   3736                         break;
   3737                     case CSSValue500:
   3738                         fontDescription.setWeight(FontWeight500);
   3739                         break;
   3740                     case CSSValue300:
   3741                         fontDescription.setWeight(FontWeight300);
   3742                         break;
   3743                     case CSSValue200:
   3744                         fontDescription.setWeight(FontWeight200);
   3745                         break;
   3746                     case CSSValue100:
   3747                         fontDescription.setWeight(FontWeight100);
   3748                         break;
   3749                     default:
   3750                         return;
   3751                 }
   3752             } else
   3753                 ASSERT_NOT_REACHED();
   3754         }
   3755         if (m_style->setFontDescription(fontDescription))
   3756             m_fontDirty = true;
   3757         return;
   3758     }
   3759 
   3760     case CSSPropertyListStylePosition:
   3761         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStylePosition, ListStylePosition)
   3762         return;
   3763     case CSSPropertyListStyleType:
   3764         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType)
   3765         return;
   3766     case CSSPropertyPageBreakBefore:
   3767         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
   3768         return;
   3769     case CSSPropertyPageBreakAfter:
   3770         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
   3771         return;
   3772     case CSSPropertyPageBreakInside: {
   3773         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
   3774         if (!primitiveValue)
   3775             return;
   3776         EPageBreak pageBreak = *primitiveValue;
   3777         if (pageBreak != PBALWAYS)
   3778             m_style->setPageBreakInside(pageBreak);
   3779         return;
   3780     }
   3781 
   3782     case CSSPropertyPosition:
   3783         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
   3784         return;
   3785     case CSSPropertyTableLayout: {
   3786         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
   3787 
   3788         ETableLayout l = *primitiveValue;
   3789         if (l == TAUTO)
   3790             l = RenderStyle::initialTableLayout();
   3791 
   3792         m_style->setTableLayout(l);
   3793         return;
   3794     }
   3795 
   3796     case CSSPropertyUnicodeBidi:
   3797         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
   3798         return;
   3799     case CSSPropertyTextTransform:
   3800         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
   3801         return;
   3802     case CSSPropertyVisibility:
   3803         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
   3804         return;
   3805     case CSSPropertyWhiteSpace:
   3806         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
   3807         return;
   3808     case CSSPropertyBorderSpacing: {
   3809         if (isInherit) {
   3810             m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing());
   3811             m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing());
   3812         }
   3813         else if (isInitial) {
   3814             m_style->setHorizontalBorderSpacing(0);
   3815             m_style->setVerticalBorderSpacing(0);
   3816         }
   3817         return;
   3818     }
   3819     case CSSPropertyWebkitBorderHorizontalSpacing: {
   3820         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
   3821         if (!primitiveValue)
   3822             return;
   3823         short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
   3824         m_style->setHorizontalBorderSpacing(spacing);
   3825         return;
   3826     }
   3827     case CSSPropertyWebkitBorderVerticalSpacing: {
   3828         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
   3829         if (!primitiveValue)
   3830             return;
   3831         short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
   3832         m_style->setVerticalBorderSpacing(spacing);
   3833         return;
   3834     }
   3835     case CSSPropertyCursor:
   3836         if (isInherit) {
   3837             m_style->setCursor(m_parentStyle->cursor());
   3838             m_style->setCursorList(m_parentStyle->cursors());
   3839             return;
   3840         }
   3841         m_style->clearCursorList();
   3842         if (isInitial) {
   3843             m_style->setCursor(RenderStyle::initialCursor());
   3844             return;
   3845         }
   3846         if (value->isValueList()) {
   3847             CSSValueList* list = static_cast<CSSValueList*>(value);
   3848             int len = list->length();
   3849             m_style->setCursor(CURSOR_AUTO);
   3850             for (int i = 0; i < len; i++) {
   3851                 CSSValue* item = list->itemWithoutBoundsCheck(i);
   3852                 if (!item->isPrimitiveValue())
   3853                     continue;
   3854                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
   3855                 int type = primitiveValue->primitiveType();
   3856                 if (type == CSSPrimitiveValue::CSS_URI) {
   3857                     if (primitiveValue->isCursorImageValue()) {
   3858                         CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
   3859                         if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style.
   3860                             m_style->setUnique();
   3861                         m_style->addCursor(cachedOrPendingFromValue(CSSPropertyCursor, image), image->hotSpot());
   3862                     }
   3863                 } else if (type == CSSPrimitiveValue::CSS_IDENT)
   3864                     m_style->setCursor(*primitiveValue);
   3865             }
   3866         } else if (primitiveValue) {
   3867             int type = primitiveValue->primitiveType();
   3868             if (type == CSSPrimitiveValue::CSS_IDENT && m_style->cursor() != ECursor(*primitiveValue))
   3869                 m_style->setCursor(*primitiveValue);
   3870         }
   3871         return;
   3872 
   3873 // uri || inherit
   3874     case CSSPropertyListStyleImage:
   3875     {
   3876         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
   3877         m_style->setListStyleImage(styleImage(CSSPropertyListStyleImage, value));
   3878         return;
   3879     }
   3880 
   3881 // length
   3882     case CSSPropertyBorderTopWidth:
   3883     case CSSPropertyBorderRightWidth:
   3884     case CSSPropertyBorderBottomWidth:
   3885     case CSSPropertyBorderLeftWidth:
   3886     case CSSPropertyOutlineWidth:
   3887     case CSSPropertyWebkitColumnRuleWidth:
   3888     {
   3889         if (isInherit) {
   3890             HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth)
   3891             HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth)
   3892             HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth)
   3893             HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth)
   3894             HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth)
   3895             HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth)
   3896             return;
   3897         }
   3898         else if (isInitial) {
   3899             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth)
   3900             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth)
   3901             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth)
   3902             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth)
   3903             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth)
   3904             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth)
   3905             return;
   3906         }
   3907 
   3908         if (!primitiveValue)
   3909             return;
   3910         short width = 3;
   3911         switch (primitiveValue->getIdent()) {
   3912         case CSSValueThin:
   3913             width = 1;
   3914             break;
   3915         case CSSValueMedium:
   3916             width = 3;
   3917             break;
   3918         case CSSValueThick:
   3919             width = 5;
   3920             break;
   3921         case CSSValueInvalid:
   3922             width = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
   3923             break;
   3924         default:
   3925             return;
   3926         }
   3927 
   3928         if (width < 0) return;
   3929         switch (id) {
   3930         case CSSPropertyBorderTopWidth:
   3931             m_style->setBorderTopWidth(width);
   3932             break;
   3933         case CSSPropertyBorderRightWidth:
   3934             m_style->setBorderRightWidth(width);
   3935             break;
   3936         case CSSPropertyBorderBottomWidth:
   3937             m_style->setBorderBottomWidth(width);
   3938             break;
   3939         case CSSPropertyBorderLeftWidth:
   3940             m_style->setBorderLeftWidth(width);
   3941             break;
   3942         case CSSPropertyOutlineWidth:
   3943             m_style->setOutlineWidth(width);
   3944             break;
   3945         case CSSPropertyWebkitColumnRuleWidth:
   3946             m_style->setColumnRuleWidth(width);
   3947             break;
   3948         default:
   3949             return;
   3950         }
   3951         return;
   3952     }
   3953 
   3954     case CSSPropertyWebkitFontSmoothing: {
   3955         FontDescription fontDescription = m_style->fontDescription();
   3956         if (isInherit)
   3957             fontDescription.setFontSmoothing(m_parentStyle->fontDescription().fontSmoothing());
   3958         else if (isInitial)
   3959             fontDescription.setFontSmoothing(AutoSmoothing);
   3960         else {
   3961             if (!primitiveValue)
   3962                 return;
   3963             int id = primitiveValue->getIdent();
   3964             FontSmoothingMode smoothing;
   3965             switch (id) {
   3966                 case CSSValueAuto:
   3967                     smoothing = AutoSmoothing;
   3968                     break;
   3969                 case CSSValueNone:
   3970                     smoothing = NoSmoothing;
   3971                     break;
   3972                 case CSSValueAntialiased:
   3973                     smoothing = Antialiased;
   3974                     break;
   3975                 case CSSValueSubpixelAntialiased:
   3976                     smoothing = SubpixelAntialiased;
   3977                     break;
   3978                 default:
   3979                     ASSERT_NOT_REACHED();
   3980                     smoothing = AutoSmoothing;
   3981             }
   3982             fontDescription.setFontSmoothing(smoothing);
   3983         }
   3984         if (m_style->setFontDescription(fontDescription))
   3985             m_fontDirty = true;
   3986         return;
   3987     }
   3988 
   3989     case CSSPropertyLetterSpacing:
   3990     case CSSPropertyWordSpacing:
   3991     {
   3992         if (isInherit) {
   3993             HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing)
   3994             HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing)
   3995             return;
   3996         }
   3997         else if (isInitial) {
   3998             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing)
   3999             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing)
   4000             return;
   4001         }
   4002 
   4003         int width = 0;
   4004         if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
   4005             width = 0;
   4006         } else {
   4007             if (!primitiveValue)
   4008                 return;
   4009             width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules(m_element) ? 1.0f : zoomFactor);
   4010         }
   4011         switch (id) {
   4012         case CSSPropertyLetterSpacing:
   4013             m_style->setLetterSpacing(width);
   4014             break;
   4015         case CSSPropertyWordSpacing:
   4016             m_style->setWordSpacing(width);
   4017             break;
   4018             // ### needs the definitions in renderstyle
   4019         default: break;
   4020         }
   4021         return;
   4022     }
   4023 
   4024     case CSSPropertyWordBreak:
   4025         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
   4026         return;
   4027     case CSSPropertyWordWrap:
   4028         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
   4029         return;
   4030     case CSSPropertyWebkitNbspMode:
   4031         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
   4032         return;
   4033     case CSSPropertyWebkitLineBreak:
   4034         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
   4035         return;
   4036     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
   4037         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
   4038         return;
   4039 
   4040     case CSSPropertyResize:
   4041     {
   4042         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
   4043 
   4044         if (!primitiveValue->getIdent())
   4045             return;
   4046 
   4047         EResize r = RESIZE_NONE;
   4048         if (primitiveValue->getIdent() == CSSValueAuto) {
   4049             if (Settings* settings = m_checker.m_document->settings())
   4050                 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
   4051         } else
   4052             r = *primitiveValue;
   4053 
   4054         m_style->setResize(r);
   4055         return;
   4056     }
   4057 
   4058     // length, percent
   4059     case CSSPropertyMaxWidth:
   4060         // +none +inherit
   4061         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
   4062             l = Length(undefinedLength, Fixed);
   4063             apply = true;
   4064         }
   4065     case CSSPropertyTop:
   4066     case CSSPropertyLeft:
   4067     case CSSPropertyRight:
   4068     case CSSPropertyBottom:
   4069     case CSSPropertyWidth:
   4070     case CSSPropertyMinWidth:
   4071     case CSSPropertyMarginTop:
   4072     case CSSPropertyMarginRight:
   4073     case CSSPropertyMarginBottom:
   4074     case CSSPropertyMarginLeft:
   4075         // +inherit +auto
   4076         if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) {
   4077             if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
   4078                 l = Length(Intrinsic);
   4079                 apply = true;
   4080             }
   4081             else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
   4082                 l = Length(MinIntrinsic);
   4083                 apply = true;
   4084             }
   4085         }
   4086         if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
   4087             apply = true;
   4088     case CSSPropertyPaddingTop:
   4089     case CSSPropertyPaddingRight:
   4090     case CSSPropertyPaddingBottom:
   4091     case CSSPropertyPaddingLeft:
   4092     case CSSPropertyTextIndent:
   4093         // +inherit
   4094     {
   4095         if (isInherit) {
   4096             HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth)
   4097             HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom)
   4098             HANDLE_INHERIT_COND(CSSPropertyTop, top, Top)
   4099             HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left)
   4100             HANDLE_INHERIT_COND(CSSPropertyRight, right, Right)
   4101             HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width)
   4102             HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth)
   4103             HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop)
   4104             HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight)
   4105             HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom)
   4106             HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft)
   4107             HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop)
   4108             HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight)
   4109             HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom)
   4110             HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft)
   4111             HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent)
   4112             return;
   4113         }
   4114         else if (isInitial) {
   4115             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize)
   4116             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset)
   4117             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset)
   4118             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset)
   4119             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset)
   4120             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size)
   4121             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize)
   4122             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding)
   4123             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding)
   4124             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding)
   4125             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding)
   4126             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin)
   4127             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin)
   4128             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin)
   4129             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin)
   4130             HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent)
   4131             return;
   4132         }
   4133 
   4134         if (primitiveValue && !apply) {
   4135             int type = primitiveValue->primitiveType();
   4136             if (CSSPrimitiveValue::isUnitTypeLength(type))
   4137                 // Handle our quirky margin units if we have them.
   4138                 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed,
   4139                            primitiveValue->isQuirkValue());
   4140             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   4141                 l = Length(primitiveValue->getDoubleValue(), Percent);
   4142             else
   4143                 return;
   4144             apply = true;
   4145         }
   4146         if (!apply) return;
   4147         switch (id) {
   4148             case CSSPropertyMaxWidth:
   4149                 m_style->setMaxWidth(l);
   4150                 break;
   4151             case CSSPropertyBottom:
   4152                 m_style->setBottom(l);
   4153                 break;
   4154             case CSSPropertyTop:
   4155                 m_style->setTop(l);
   4156                 break;
   4157             case CSSPropertyLeft:
   4158                 m_style->setLeft(l);
   4159                 break;
   4160             case CSSPropertyRight:
   4161                 m_style->setRight(l);
   4162                 break;
   4163             case CSSPropertyWidth:
   4164                 m_style->setWidth(l);
   4165                 break;
   4166             case CSSPropertyMinWidth:
   4167                 m_style->setMinWidth(l);
   4168                 break;
   4169             case CSSPropertyPaddingTop:
   4170                 m_style->setPaddingTop(l);
   4171                 break;
   4172             case CSSPropertyPaddingRight:
   4173                 m_style->setPaddingRight(l);
   4174                 break;
   4175             case CSSPropertyPaddingBottom:
   4176                 m_style->setPaddingBottom(l);
   4177                 break;
   4178             case CSSPropertyPaddingLeft:
   4179                 m_style->setPaddingLeft(l);
   4180                 break;
   4181             case CSSPropertyMarginTop:
   4182                 m_style->setMarginTop(l);
   4183                 break;
   4184             case CSSPropertyMarginRight:
   4185                 m_style->setMarginRight(l);
   4186                 break;
   4187             case CSSPropertyMarginBottom:
   4188                 m_style->setMarginBottom(l);
   4189                 break;
   4190             case CSSPropertyMarginLeft:
   4191                 m_style->setMarginLeft(l);
   4192                 break;
   4193             case CSSPropertyTextIndent:
   4194                 m_style->setTextIndent(l);
   4195                 break;
   4196             default:
   4197                 break;
   4198             }
   4199         return;
   4200     }
   4201 
   4202     case CSSPropertyMaxHeight:
   4203         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
   4204             l = Length(undefinedLength, Fixed);
   4205             apply = true;
   4206         }
   4207     case CSSPropertyHeight:
   4208     case CSSPropertyMinHeight:
   4209         if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
   4210             l = Length(Intrinsic);
   4211             apply = true;
   4212         } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
   4213             l = Length(MinIntrinsic);
   4214             apply = true;
   4215         } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
   4216             apply = true;
   4217         if (isInherit) {
   4218             HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight)
   4219             HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height)
   4220             HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight)
   4221             return;
   4222         }
   4223         if (isInitial) {
   4224             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize)
   4225             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size)
   4226             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize)
   4227             return;
   4228         }
   4229 
   4230         if (primitiveValue && !apply) {
   4231             unsigned short type = primitiveValue->primitiveType();
   4232             if (CSSPrimitiveValue::isUnitTypeLength(type))
   4233                 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   4234             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   4235                 l = Length(primitiveValue->getDoubleValue(), Percent);
   4236             else
   4237                 return;
   4238             apply = true;
   4239         }
   4240         if (apply)
   4241             switch (id) {
   4242                 case CSSPropertyMaxHeight:
   4243                     m_style->setMaxHeight(l);
   4244                     break;
   4245                 case CSSPropertyHeight:
   4246                     m_style->setHeight(l);
   4247                     break;
   4248                 case CSSPropertyMinHeight:
   4249                     m_style->setMinHeight(l);
   4250                     break;
   4251             }
   4252         return;
   4253 
   4254     case CSSPropertyVerticalAlign:
   4255         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
   4256         if (!primitiveValue)
   4257             return;
   4258         if (primitiveValue->getIdent()) {
   4259           EVerticalAlign align;
   4260 
   4261           switch (primitiveValue->getIdent()) {
   4262                 case CSSValueTop:
   4263                     align = TOP; break;
   4264                 case CSSValueBottom:
   4265                     align = BOTTOM; break;
   4266                 case CSSValueMiddle:
   4267                     align = MIDDLE; break;
   4268                 case CSSValueBaseline:
   4269                     align = BASELINE; break;
   4270                 case CSSValueTextBottom:
   4271                     align = TEXT_BOTTOM; break;
   4272                 case CSSValueTextTop:
   4273                     align = TEXT_TOP; break;
   4274                 case CSSValueSub:
   4275                     align = SUB; break;
   4276                 case CSSValueSuper:
   4277                     align = SUPER; break;
   4278                 case CSSValueWebkitBaselineMiddle:
   4279                     align = BASELINE_MIDDLE; break;
   4280                 default:
   4281                     return;
   4282             }
   4283           m_style->setVerticalAlign(align);
   4284           return;
   4285         } else {
   4286           int type = primitiveValue->primitiveType();
   4287           Length l;
   4288           if (CSSPrimitiveValue::isUnitTypeLength(type))
   4289             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   4290           else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   4291             l = Length(primitiveValue->getDoubleValue(), Percent);
   4292 
   4293           m_style->setVerticalAlign(LENGTH);
   4294           m_style->setVerticalAlignLength(l);
   4295         }
   4296         return;
   4297 
   4298     case CSSPropertyFontSize:
   4299     {
   4300         FontDescription fontDescription = m_style->fontDescription();
   4301         fontDescription.setKeywordSize(0);
   4302         float oldSize = 0;
   4303         float size = 0;
   4304 
   4305         bool parentIsAbsoluteSize = false;
   4306         if (m_parentNode) {
   4307             oldSize = m_parentStyle->fontDescription().specifiedSize();
   4308             parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
   4309         }
   4310 
   4311         if (isInherit) {
   4312             size = oldSize;
   4313             if (m_parentNode)
   4314                 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
   4315         } else if (isInitial) {
   4316             size = fontSizeForKeyword(m_checker.m_document, CSSValueMedium, fontDescription.useFixedDefaultSize());
   4317             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
   4318         } else if (primitiveValue->getIdent()) {
   4319             // Keywords are being used.
   4320             switch (primitiveValue->getIdent()) {
   4321                 case CSSValueXxSmall:
   4322                 case CSSValueXSmall:
   4323                 case CSSValueSmall:
   4324                 case CSSValueMedium:
   4325                 case CSSValueLarge:
   4326                 case CSSValueXLarge:
   4327                 case CSSValueXxLarge:
   4328                 case CSSValueWebkitXxxLarge:
   4329                     size = fontSizeForKeyword(m_checker.m_document, primitiveValue->getIdent(), fontDescription.useFixedDefaultSize());
   4330                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
   4331                     break;
   4332                 case CSSValueLarger:
   4333                     size = largerFontSize(oldSize, m_checker.m_document->inQuirksMode());
   4334                     break;
   4335                 case CSSValueSmaller:
   4336                     size = smallerFontSize(oldSize, m_checker.m_document->inQuirksMode());
   4337                     break;
   4338                 default:
   4339                     return;
   4340             }
   4341 
   4342             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
   4343                                               (primitiveValue->getIdent() == CSSValueLarger ||
   4344                                                primitiveValue->getIdent() == CSSValueSmaller));
   4345         } else {
   4346             int type = primitiveValue->primitiveType();
   4347             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
   4348                                               (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
   4349                                                type != CSSPrimitiveValue::CSS_EMS &&
   4350                                                type != CSSPrimitiveValue::CSS_EXS &&
   4351                                                type != CSSPrimitiveValue::CSS_REMS));
   4352             if (CSSPrimitiveValue::isUnitTypeLength(type))
   4353                 size = primitiveValue->computeLengthFloat(m_parentStyle, m_rootElementStyle, true);
   4354             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   4355                 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
   4356             else
   4357                 return;
   4358         }
   4359 
   4360         if (size < 0)
   4361             return;
   4362 
   4363         setFontSize(fontDescription, size);
   4364         if (m_style->setFontDescription(fontDescription))
   4365             m_fontDirty = true;
   4366         return;
   4367     }
   4368 
   4369     case CSSPropertyZIndex: {
   4370         if (isInherit) {
   4371             if (m_parentStyle->hasAutoZIndex())
   4372                 m_style->setHasAutoZIndex();
   4373             else
   4374                 m_style->setZIndex(m_parentStyle->zIndex());
   4375             return;
   4376         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
   4377             m_style->setHasAutoZIndex();
   4378             return;
   4379         }
   4380 
   4381         // FIXME: Should clamp all sorts of other integer properties too.
   4382         m_style->setZIndex(clampToInteger(primitiveValue->getDoubleValue()));
   4383         return;
   4384     }
   4385     case CSSPropertyWidows:
   4386     {
   4387         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
   4388         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   4389             return;
   4390         m_style->setWidows(primitiveValue->getIntValue());
   4391         return;
   4392     }
   4393 
   4394     case CSSPropertyOrphans:
   4395     {
   4396         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
   4397         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   4398             return;
   4399         m_style->setOrphans(primitiveValue->getIntValue());
   4400         return;
   4401     }
   4402 
   4403 // length, percent, number
   4404     case CSSPropertyLineHeight:
   4405     {
   4406         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
   4407         if (!primitiveValue)
   4408             return;
   4409         Length lineHeight;
   4410         int type = primitiveValue->primitiveType();
   4411         if (primitiveValue->getIdent() == CSSValueNormal)
   4412             lineHeight = Length(-100.0, Percent);
   4413         else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
   4414             double multiplier = zoomFactor;
   4415             if (m_style->textSizeAdjust()) {
   4416                 if (Frame* frame = m_checker.m_document->frame())
   4417                     multiplier *= frame->textZoomFactor();
   4418             }
   4419             lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle,  multiplier), Fixed);
   4420         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   4421             lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
   4422         else if (type == CSSPrimitiveValue::CSS_NUMBER)
   4423             lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
   4424         else
   4425             return;
   4426         m_style->setLineHeight(lineHeight);
   4427         return;
   4428     }
   4429 
   4430 // string
   4431     case CSSPropertyTextAlign:
   4432     {
   4433         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
   4434         if (!primitiveValue)
   4435             return;
   4436         if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) {
   4437             if (m_parentStyle->textAlign() == TASTART)
   4438                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT);
   4439             else if (m_parentStyle->textAlign() == TAEND)
   4440                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT);
   4441             else
   4442                 m_style->setTextAlign(m_parentStyle->textAlign());
   4443             return;
   4444         }
   4445         m_style->setTextAlign(*primitiveValue);
   4446         return;
   4447     }
   4448 
   4449 // rect
   4450     case CSSPropertyClip:
   4451     {
   4452         Length top;
   4453         Length right;
   4454         Length bottom;
   4455         Length left;
   4456         bool hasClip = true;
   4457         if (isInherit) {
   4458             if (m_parentStyle->hasClip()) {
   4459                 top = m_parentStyle->clipTop();
   4460                 right = m_parentStyle->clipRight();
   4461                 bottom = m_parentStyle->clipBottom();
   4462                 left = m_parentStyle->clipLeft();
   4463             } else {
   4464                 hasClip = false;
   4465                 top = right = bottom = left = Length();
   4466             }
   4467         } else if (isInitial) {
   4468             hasClip = false;
   4469             top = right = bottom = left = Length();
   4470         } else if (!primitiveValue) {
   4471             return;
   4472         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
   4473             Rect* rect = primitiveValue->getRectValue();
   4474             if (!rect)
   4475                 return;
   4476             top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
   4477             right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
   4478             bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
   4479             left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
   4480         } else if (primitiveValue->getIdent() != CSSValueAuto) {
   4481             return;
   4482         }
   4483         m_style->setClip(top, right, bottom, left);
   4484         m_style->setHasClip(hasClip);
   4485 
   4486         // rect, ident
   4487         return;
   4488     }
   4489 
   4490 // lists
   4491     case CSSPropertyContent:
   4492         // list of string, uri, counter, attr, i
   4493     {
   4494         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
   4495         // note is a reminder that eventually "inherit" needs to be supported.
   4496 
   4497         if (isInitial) {
   4498             m_style->clearContent();
   4499             return;
   4500         }
   4501 
   4502         if (!value->isValueList())
   4503             return;
   4504 
   4505         CSSValueList* list = static_cast<CSSValueList*>(value);
   4506         int len = list->length();
   4507 
   4508         bool didSet = false;
   4509         for (int i = 0; i < len; i++) {
   4510             CSSValue* item = list->itemWithoutBoundsCheck(i);
   4511             if (item->isImageGeneratorValue()) {
   4512                 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
   4513                 didSet = true;
   4514             }
   4515 
   4516             if (!item->isPrimitiveValue())
   4517                 continue;
   4518 
   4519             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
   4520             switch (contentValue->primitiveType()) {
   4521             case CSSPrimitiveValue::CSS_STRING:
   4522                 m_style->setContent(contentValue->getStringValue().impl(), didSet);
   4523                 didSet = true;
   4524                 break;
   4525             case CSSPrimitiveValue::CSS_ATTR: {
   4526                 // FIXME: Can a namespace be specified for an attr(foo)?
   4527                 if (m_style->styleType() == NOPSEUDO)
   4528                     m_style->setUnique();
   4529                 else
   4530                     m_parentStyle->setUnique();
   4531                 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
   4532                 m_style->setContent(m_element->getAttribute(attr).impl(), didSet);
   4533                 didSet = true;
   4534                 // register the fact that the attribute value affects the style
   4535                 m_selectorAttrs.add(attr.localName().impl());
   4536                 break;
   4537             }
   4538             case CSSPrimitiveValue::CSS_URI: {
   4539                 if (!contentValue->isImageValue())
   4540                     break;
   4541                 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
   4542                 didSet = true;
   4543                 break;
   4544             }
   4545             case CSSPrimitiveValue::CSS_COUNTER: {
   4546                 Counter* counterValue = contentValue->getCounterValue();
   4547                 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(),
   4548                     (EListStyleType)counterValue->listStyleNumber(), counterValue->separator()));
   4549                 m_style->setContent(counter.release(), didSet);
   4550                 didSet = true;
   4551                 break;
   4552             }
   4553             case CSSPrimitiveValue::CSS_IDENT:
   4554                 switch (contentValue->getIdent()) {
   4555                 case CSSValueOpenQuote:
   4556                     m_style->setContent(OPEN_QUOTE, didSet);
   4557                     didSet = true;
   4558                     break;
   4559                 case CSSValueCloseQuote:
   4560                     m_style->setContent(CLOSE_QUOTE, didSet);
   4561                     didSet = true;
   4562                     break;
   4563                 case CSSValueNoOpenQuote:
   4564                     m_style->setContent(NO_OPEN_QUOTE, didSet);
   4565                     didSet = true;
   4566                     break;
   4567                 case CSSValueNoCloseQuote:
   4568                     m_style->setContent(NO_CLOSE_QUOTE, didSet);
   4569                     didSet = true;
   4570                     break;
   4571                 default:
   4572                     // normal and none do not have any effect.
   4573                     {}
   4574                 }
   4575             }
   4576         }
   4577         if (!didSet)
   4578             m_style->clearContent();
   4579         return;
   4580     }
   4581     case CSSPropertyQuotes:
   4582         if (isInherit) {
   4583             if (m_parentStyle)
   4584                 m_style->setQuotes(m_parentStyle->quotes());
   4585             return;
   4586         }
   4587         if (isInitial) {
   4588             m_style->setQuotes(0);
   4589             return;
   4590         }
   4591         if (value->isValueList()) {
   4592             CSSValueList* list = static_cast<CSSValueList*>(value);
   4593             size_t length = list->length();
   4594             QuotesData* data = QuotesData::create(length);
   4595             if (!data)
   4596                 return; // Out of memory
   4597             String* quotes = data->data();
   4598             for (size_t i = 0; i < length; i++) {
   4599                 CSSValue* item = list->itemWithoutBoundsCheck(i);
   4600                 ASSERT(item->isPrimitiveValue());
   4601                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
   4602                 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
   4603                 quotes[i] = primitiveValue->getStringValue();
   4604             }
   4605             m_style->setQuotes(adoptRef(data));
   4606         } else if (primitiveValue) {
   4607             ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
   4608             if (primitiveValue->getIdent() == CSSValueNone)
   4609                 m_style->setQuotes(adoptRef(QuotesData::create(0)));
   4610         }
   4611         return;
   4612 
   4613     case CSSPropertyCounterIncrement:
   4614         applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false);
   4615         return;
   4616     case CSSPropertyCounterReset:
   4617         applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true);
   4618         return;
   4619 
   4620     case CSSPropertyFontFamily: {
   4621         // list of strings and ids
   4622         if (isInherit) {
   4623             FontDescription parentFontDescription = m_parentStyle->fontDescription();
   4624             FontDescription fontDescription = m_style->fontDescription();
   4625             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
   4626             fontDescription.setFamily(parentFontDescription.firstFamily());
   4627             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
   4628             if (m_style->setFontDescription(fontDescription))
   4629                 m_fontDirty = true;
   4630             return;
   4631         } else if (isInitial) {
   4632             FontDescription initialDesc = FontDescription();
   4633             FontDescription fontDescription = m_style->fontDescription();
   4634             // We need to adjust the size to account for the generic family change from monospace
   4635             // to non-monospace.
   4636             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
   4637                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
   4638             fontDescription.setGenericFamily(initialDesc.genericFamily());
   4639             if (!initialDesc.firstFamily().familyIsEmpty())
   4640                 fontDescription.setFamily(initialDesc.firstFamily());
   4641             if (m_style->setFontDescription(fontDescription))
   4642                 m_fontDirty = true;
   4643             return;
   4644         }
   4645 
   4646         if (!value->isValueList())
   4647             return;
   4648         FontDescription fontDescription = m_style->fontDescription();
   4649         CSSValueList* list = static_cast<CSSValueList*>(value);
   4650         int len = list->length();
   4651         FontFamily& firstFamily = fontDescription.firstFamily();
   4652         FontFamily* currFamily = 0;
   4653 
   4654         // Before mapping in a new font-family property, we should reset the generic family.
   4655         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
   4656         fontDescription.setGenericFamily(FontDescription::NoFamily);
   4657 
   4658         for (int i = 0; i < len; i++) {
   4659             CSSValue* item = list->itemWithoutBoundsCheck(i);
   4660             if (!item->isPrimitiveValue())
   4661                 continue;
   4662             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
   4663             AtomicString face;
   4664             Settings* settings = m_checker.m_document->settings();
   4665             if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
   4666                 if (contentValue->isFontFamilyValue())
   4667                     face = static_cast<FontFamilyValue*>(contentValue)->familyName();
   4668             } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
   4669                 switch (contentValue->getIdent()) {
   4670                     case CSSValueWebkitBody:
   4671                         face = settings->standardFontFamily();
   4672                         break;
   4673                     case CSSValueSerif:
   4674                         face = "-webkit-serif";
   4675                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
   4676                         break;
   4677                     case CSSValueSansSerif:
   4678                         face = "-webkit-sans-serif";
   4679                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
   4680                         break;
   4681                     case CSSValueCursive:
   4682                         face = "-webkit-cursive";
   4683                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
   4684                         break;
   4685                     case CSSValueFantasy:
   4686                         face = "-webkit-fantasy";
   4687                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
   4688                         break;
   4689                     case CSSValueMonospace:
   4690                         face = "-webkit-monospace";
   4691                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
   4692                         break;
   4693                 }
   4694             }
   4695 
   4696             if (!face.isEmpty()) {
   4697                 if (!currFamily) {
   4698                     // Filling in the first family.
   4699                     firstFamily.setFamily(face);
   4700                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
   4701                     currFamily = &firstFamily;
   4702                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
   4703                 } else {
   4704                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
   4705                     newFamily->setFamily(face);
   4706                     currFamily->appendFamily(newFamily);
   4707                     currFamily = newFamily.get();
   4708                 }
   4709             }
   4710         }
   4711 
   4712         // We can't call useFixedDefaultSize() until all new font families have been added
   4713         // If currFamily is non-zero then we set at least one family on this description.
   4714         if (currFamily) {
   4715             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
   4716                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
   4717 
   4718             if (m_style->setFontDescription(fontDescription))
   4719                 m_fontDirty = true;
   4720         }
   4721         return;
   4722     }
   4723     case CSSPropertyTextDecoration: {
   4724         // list of ident
   4725         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
   4726         int t = RenderStyle::initialTextDecoration();
   4727         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
   4728             // do nothing
   4729         } else {
   4730             if (!value->isValueList())
   4731                 return;
   4732             CSSValueList *list = static_cast<CSSValueList*>(value);
   4733             int len = list->length();
   4734             for (int i = 0; i < len; i++)
   4735             {
   4736                 CSSValue *item = list->itemWithoutBoundsCheck(i);
   4737                 if (!item->isPrimitiveValue())
   4738                     continue;
   4739                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
   4740                 switch (primitiveValue->getIdent()) {
   4741                     case CSSValueNone:
   4742                         t = TDNONE; break;
   4743                     case CSSValueUnderline:
   4744                         t |= UNDERLINE; break;
   4745                     case CSSValueOverline:
   4746                         t |= OVERLINE; break;
   4747                     case CSSValueLineThrough:
   4748                         t |= LINE_THROUGH; break;
   4749                     case CSSValueBlink:
   4750                         t |= BLINK; break;
   4751                     default:
   4752                         return;
   4753                 }
   4754             }
   4755         }
   4756 
   4757         m_style->setTextDecoration(t);
   4758         return;
   4759     }
   4760 
   4761     case CSSPropertyZoom:
   4762     {
   4763         // Reset the zoom in effect before we do anything.  This allows the setZoom method to accurately compute a new
   4764         // zoom in effect.
   4765         m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
   4766 
   4767         // Now we can handle inherit and initial.
   4768         HANDLE_INHERIT_AND_INITIAL(zoom, Zoom)
   4769 
   4770         // Handle normal/reset, numbers and percentages.
   4771         int type = primitiveValue->primitiveType();
   4772         if (primitiveValue->getIdent() == CSSValueNormal)
   4773             m_style->setZoom(RenderStyle::initialZoom());
   4774         else if (primitiveValue->getIdent() == CSSValueReset) {
   4775             m_style->setEffectiveZoom(RenderStyle::initialZoom());
   4776             m_style->setZoom(RenderStyle::initialZoom());
   4777         } else if (primitiveValue->getIdent() == CSSValueDocument) {
   4778             float docZoom = m_checker.m_document->renderer()->style()->zoom();
   4779             m_style->setEffectiveZoom(docZoom);
   4780             m_style->setZoom(docZoom);
   4781         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
   4782             if (primitiveValue->getFloatValue())
   4783                 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f);
   4784         } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
   4785             if (primitiveValue->getFloatValue())
   4786                 m_style->setZoom(primitiveValue->getFloatValue());
   4787         }
   4788 
   4789         m_fontDirty = true;
   4790         return;
   4791     }
   4792 // shorthand properties
   4793     case CSSPropertyBackground:
   4794         if (isInitial) {
   4795             m_style->clearBackgroundLayers();
   4796             m_style->setBackgroundColor(Color());
   4797         }
   4798         else if (isInherit) {
   4799             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
   4800             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
   4801         }
   4802         return;
   4803     case CSSPropertyWebkitMask:
   4804         if (isInitial)
   4805             m_style->clearMaskLayers();
   4806         else if (isInherit)
   4807             m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
   4808         return;
   4809 
   4810     case CSSPropertyBorder:
   4811     case CSSPropertyBorderStyle:
   4812     case CSSPropertyBorderWidth:
   4813     case CSSPropertyBorderColor:
   4814         if (id == CSSPropertyBorder || id == CSSPropertyBorderColor)
   4815         {
   4816             if (isInherit) {
   4817                 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
   4818                 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
   4819                 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
   4820                 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color());
   4821             }
   4822             else if (isInitial) {
   4823                 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
   4824                 m_style->setBorderBottomColor(Color());
   4825                 m_style->setBorderLeftColor(Color());
   4826                 m_style->setBorderRightColor(Color());
   4827             }
   4828         }
   4829         if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle)
   4830         {
   4831             if (isInherit) {
   4832                 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
   4833                 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
   4834                 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
   4835                 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
   4836             }
   4837             else if (isInitial) {
   4838                 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle());
   4839                 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
   4840                 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
   4841                 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle());
   4842             }
   4843         }
   4844         if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth)
   4845         {
   4846             if (isInherit) {
   4847                 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
   4848                 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
   4849                 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
   4850                 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
   4851             }
   4852             else if (isInitial) {
   4853                 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth());
   4854                 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
   4855                 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
   4856                 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth());
   4857             }
   4858         }
   4859         return;
   4860     case CSSPropertyBorderTop:
   4861         if (isInherit) {
   4862             m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
   4863             m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
   4864             m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
   4865         }
   4866         else if (isInitial)
   4867             m_style->resetBorderTop();
   4868         return;
   4869     case CSSPropertyBorderRight:
   4870         if (isInherit) {
   4871             m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color());
   4872             m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
   4873             m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
   4874         }
   4875         else if (isInitial)
   4876             m_style->resetBorderRight();
   4877         return;
   4878     case CSSPropertyBorderBottom:
   4879         if (isInherit) {
   4880             m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
   4881             m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
   4882             m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
   4883         }
   4884         else if (isInitial)
   4885             m_style->resetBorderBottom();
   4886         return;
   4887     case CSSPropertyBorderLeft:
   4888         if (isInherit) {
   4889             m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
   4890             m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
   4891             m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
   4892         }
   4893         else if (isInitial)
   4894             m_style->resetBorderLeft();
   4895         return;
   4896     case CSSPropertyMargin:
   4897         if (isInherit) {
   4898             m_style->setMarginTop(m_parentStyle->marginTop());
   4899             m_style->setMarginBottom(m_parentStyle->marginBottom());
   4900             m_style->setMarginLeft(m_parentStyle->marginLeft());
   4901             m_style->setMarginRight(m_parentStyle->marginRight());
   4902         }
   4903         else if (isInitial)
   4904             m_style->resetMargin();
   4905         return;
   4906     case CSSPropertyPadding:
   4907         if (isInherit) {
   4908             m_style->setPaddingTop(m_parentStyle->paddingTop());
   4909             m_style->setPaddingBottom(m_parentStyle->paddingBottom());
   4910             m_style->setPaddingLeft(m_parentStyle->paddingLeft());
   4911             m_style->setPaddingRight(m_parentStyle->paddingRight());
   4912         }
   4913         else if (isInitial)
   4914             m_style->resetPadding();
   4915         return;
   4916     case CSSPropertyFont:
   4917         if (isInherit) {
   4918             FontDescription fontDescription = m_parentStyle->fontDescription();
   4919             m_style->setLineHeight(m_parentStyle->lineHeight());
   4920             m_lineHeightValue = 0;
   4921             if (m_style->setFontDescription(fontDescription))
   4922                 m_fontDirty = true;
   4923         } else if (isInitial) {
   4924             Settings* settings = m_checker.m_document->settings();
   4925             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
   4926             if (!settings)
   4927                 return;
   4928             FontDescription fontDescription;
   4929             fontDescription.setGenericFamily(FontDescription::StandardFamily);
   4930             fontDescription.setRenderingMode(settings->fontRenderingMode());
   4931             fontDescription.setUsePrinterFont(m_checker.m_document->printing());
   4932             const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily();
   4933             if (!standardFontFamily.isEmpty()) {
   4934                 fontDescription.firstFamily().setFamily(standardFontFamily);
   4935                 fontDescription.firstFamily().appendFamily(0);
   4936             }
   4937             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
   4938             setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueMedium, false));
   4939             m_style->setLineHeight(RenderStyle::initialLineHeight());
   4940             m_lineHeightValue = 0;
   4941             if (m_style->setFontDescription(fontDescription))
   4942                 m_fontDirty = true;
   4943         } else if (primitiveValue) {
   4944             m_style->setLineHeight(RenderStyle::initialLineHeight());
   4945             m_lineHeightValue = 0;
   4946 
   4947             FontDescription fontDescription;
   4948             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
   4949 
   4950             // Double-check and see if the theme did anything.  If not, don't bother updating the font.
   4951             if (fontDescription.isAbsoluteSize()) {
   4952                 // Make sure the rendering mode and printer font settings are updated.
   4953                 Settings* settings = m_checker.m_document->settings();
   4954                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
   4955                 if (!settings)
   4956                     return;
   4957                 fontDescription.setRenderingMode(settings->fontRenderingMode());
   4958                 fontDescription.setUsePrinterFont(m_checker.m_document->printing());
   4959 
   4960                 // Handle the zoom factor.
   4961                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules(m_element)));
   4962                 if (m_style->setFontDescription(fontDescription))
   4963                     m_fontDirty = true;
   4964             }
   4965         } else if (value->isFontValue()) {
   4966             FontValue *font = static_cast<FontValue*>(value);
   4967             if (!font->style || !font->variant || !font->weight ||
   4968                  !font->size || !font->lineHeight || !font->family)
   4969                 return;
   4970             applyProperty(CSSPropertyFontStyle, font->style.get());
   4971             applyProperty(CSSPropertyFontVariant, font->variant.get());
   4972             applyProperty(CSSPropertyFontWeight, font->weight.get());
   4973             // The previous properties can dirty our font but they don't try to read the font's
   4974             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
   4975             // need query the dirtied font's x-height to get the computed size. To be safe in this
   4976             // case, let's just update the font now.
   4977             updateFont();
   4978             applyProperty(CSSPropertyFontSize, font->size.get());
   4979 
   4980             m_lineHeightValue = font->lineHeight.get();
   4981 
   4982             applyProperty(CSSPropertyFontFamily, font->family.get());
   4983         }
   4984         return;
   4985 
   4986     case CSSPropertyListStyle:
   4987         if (isInherit) {
   4988             m_style->setListStyleType(m_parentStyle->listStyleType());
   4989             m_style->setListStyleImage(m_parentStyle->listStyleImage());
   4990             m_style->setListStylePosition(m_parentStyle->listStylePosition());
   4991         }
   4992         else if (isInitial) {
   4993             m_style->setListStyleType(RenderStyle::initialListStyleType());
   4994             m_style->setListStyleImage(RenderStyle::initialListStyleImage());
   4995             m_style->setListStylePosition(RenderStyle::initialListStylePosition());
   4996         }
   4997         return;
   4998     case CSSPropertyOutline:
   4999         if (isInherit) {
   5000             m_style->setOutlineWidth(m_parentStyle->outlineWidth());
   5001             m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
   5002             m_style->setOutlineStyle(m_parentStyle->outlineStyle());
   5003         }
   5004         else if (isInitial)
   5005             m_style->resetOutline();
   5006         return;
   5007 
   5008     // CSS3 Properties
   5009     case CSSPropertyWebkitAppearance: {
   5010         HANDLE_INHERIT_AND_INITIAL(appearance, Appearance)
   5011         if (!primitiveValue)
   5012             return;
   5013         m_style->setAppearance(*primitiveValue);
   5014         return;
   5015     }
   5016 
   5017     case CSSPropertyWebkitBorderImage:
   5018     case CSSPropertyWebkitMaskBoxImage: {
   5019         if (isInherit) {
   5020             HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
   5021             HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
   5022             return;
   5023         } else if (isInitial) {
   5024             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
   5025             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
   5026             return;
   5027         }
   5028 
   5029         NinePieceImage image;
   5030         mapNinePieceImage(property, value, image);
   5031 
   5032         if (id == CSSPropertyWebkitBorderImage)
   5033             m_style->setBorderImage(image);
   5034         else
   5035             m_style->setMaskBoxImage(image);
   5036         return;
   5037     }
   5038 
   5039     case CSSPropertyBorderRadius:
   5040     case CSSPropertyWebkitBorderRadius:
   5041         if (isInherit) {
   5042             m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius());
   5043             m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius());
   5044             m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius());
   5045             m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius());
   5046             return;
   5047         }
   5048         if (isInitial) {
   5049             m_style->resetBorderRadius();
   5050             return;
   5051         }
   5052         // Fall through
   5053     case CSSPropertyBorderTopLeftRadius:
   5054     case CSSPropertyBorderTopRightRadius:
   5055     case CSSPropertyBorderBottomLeftRadius:
   5056     case CSSPropertyBorderBottomRightRadius: {
   5057         if (isInherit) {
   5058             HANDLE_INHERIT_COND(CSSPropertyBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius)
   5059             HANDLE_INHERIT_COND(CSSPropertyBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius)
   5060             HANDLE_INHERIT_COND(CSSPropertyBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius)
   5061             HANDLE_INHERIT_COND(CSSPropertyBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius)
   5062             return;
   5063         }
   5064 
   5065         if (isInitial) {
   5066             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius)
   5067             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopRightRadius, BorderTopRightRadius, BorderRadius)
   5068             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius)
   5069             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius)
   5070             return;
   5071         }
   5072 
   5073         if (!primitiveValue)
   5074             return;
   5075 
   5076         Pair* pair = primitiveValue->getPairValue();
   5077         if (!pair || !pair->first() || !pair->second())
   5078             return;
   5079 
   5080         Length radiusWidth;
   5081         Length radiusHeight;
   5082         if (pair->first()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   5083             radiusWidth = Length(pair->first()->getDoubleValue(), Percent);
   5084         else
   5085             radiusWidth = Length(max(intMinForLength, min(intMaxForLength, pair->first()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed);
   5086         if (pair->second()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   5087             radiusHeight = Length(pair->second()->getDoubleValue(), Percent);
   5088         else
   5089             radiusHeight = Length(max(intMinForLength, min(intMaxForLength, pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed);
   5090         int width = radiusWidth.value();
   5091         int height = radiusHeight.value();
   5092         if (width < 0 || height < 0)
   5093             return;
   5094         if (width == 0)
   5095             radiusHeight = radiusWidth; // Null out the other value.
   5096         else if (height == 0)
   5097             radiusWidth = radiusHeight; // Null out the other value.
   5098 
   5099         LengthSize size(radiusWidth, radiusHeight);
   5100         switch (id) {
   5101             case CSSPropertyBorderTopLeftRadius:
   5102                 m_style->setBorderTopLeftRadius(size);
   5103                 break;
   5104             case CSSPropertyBorderTopRightRadius:
   5105                 m_style->setBorderTopRightRadius(size);
   5106                 break;
   5107             case CSSPropertyBorderBottomLeftRadius:
   5108                 m_style->setBorderBottomLeftRadius(size);
   5109                 break;
   5110             case CSSPropertyBorderBottomRightRadius:
   5111                 m_style->setBorderBottomRightRadius(size);
   5112                 break;
   5113             default:
   5114                 m_style->setBorderRadius(size);
   5115                 break;
   5116         }
   5117         return;
   5118     }
   5119 
   5120     case CSSPropertyOutlineOffset:
   5121         HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
   5122         m_style->setOutlineOffset(primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor));
   5123         return;
   5124     case CSSPropertyTextRendering: {
   5125         FontDescription fontDescription = m_style->fontDescription();
   5126         if (isInherit)
   5127             fontDescription.setTextRenderingMode(m_parentStyle->fontDescription().textRenderingMode());
   5128         else if (isInitial)
   5129             fontDescription.setTextRenderingMode(AutoTextRendering);
   5130         else {
   5131             if (!primitiveValue)
   5132                 return;
   5133             fontDescription.setTextRenderingMode(*primitiveValue);
   5134         }
   5135         if (m_style->setFontDescription(fontDescription))
   5136             m_fontDirty = true;
   5137         return;
   5138     }
   5139     case CSSPropertyTextShadow:
   5140     case CSSPropertyBoxShadow:
   5141     case CSSPropertyWebkitBoxShadow: {
   5142         if (isInherit) {
   5143             if (id == CSSPropertyTextShadow)
   5144                 return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0);
   5145             return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0);
   5146         }
   5147         if (isInitial || primitiveValue) // initial | none
   5148             return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0);
   5149 
   5150         if (!value->isValueList())
   5151             return;
   5152 
   5153         CSSValueList *list = static_cast<CSSValueList*>(value);
   5154         int len = list->length();
   5155         for (int i = 0; i < len; i++) {
   5156             CSSValue* currValue = list->itemWithoutBoundsCheck(i);
   5157             if (!currValue->isShadowValue())
   5158                 continue;
   5159             ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i));
   5160             int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
   5161             int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
   5162             int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
   5163             int spread = item->spread ? item->spread->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
   5164             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
   5165             Color color;
   5166             if (item->color)
   5167                 color = getColorFromPrimitiveValue(item->color.get());
   5168             ShadowData* shadowData = new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent);
   5169             if (id == CSSPropertyTextShadow)
   5170                 m_style->setTextShadow(shadowData, i != 0);
   5171             else
   5172                 m_style->setBoxShadow(shadowData, i != 0);
   5173         }
   5174         return;
   5175     }
   5176     case CSSPropertyWebkitBoxReflect: {
   5177         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
   5178         if (primitiveValue) {
   5179             m_style->setBoxReflect(RenderStyle::initialBoxReflect());
   5180             return;
   5181         }
   5182 
   5183         if (!value->isReflectValue())
   5184             return;
   5185 
   5186         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
   5187         RefPtr<StyleReflection> reflection = StyleReflection::create();
   5188         reflection->setDirection(reflectValue->direction());
   5189         if (reflectValue->offset()) {
   5190             int type = reflectValue->offset()->primitiveType();
   5191             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5192                 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
   5193             else
   5194                 reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed));
   5195         }
   5196         NinePieceImage mask;
   5197         mapNinePieceImage(property, reflectValue->mask(), mask);
   5198         reflection->setMask(mask);
   5199 
   5200         m_style->setBoxReflect(reflection.release());
   5201         return;
   5202     }
   5203     case CSSPropertyOpacity:
   5204         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
   5205         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   5206             return; // Error case.
   5207         // Clamp opacity to the range 0-1
   5208         m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue())));
   5209         return;
   5210     case CSSPropertyWebkitBoxAlign:
   5211     {
   5212         HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign)
   5213         if (!primitiveValue)
   5214             return;
   5215         EBoxAlignment boxAlignment = *primitiveValue;
   5216         if (boxAlignment != BJUSTIFY)
   5217             m_style->setBoxAlign(boxAlignment);
   5218         return;
   5219     }
   5220     case CSSPropertySrc: // Only used in @font-face rules.
   5221         return;
   5222     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
   5223         return;
   5224     case CSSPropertyWebkitBackfaceVisibility:
   5225         HANDLE_INHERIT_AND_INITIAL(backfaceVisibility, BackfaceVisibility)
   5226         if (primitiveValue)
   5227             m_style->setBackfaceVisibility((primitiveValue->getIdent() == CSSValueVisible) ? BackfaceVisibilityVisible : BackfaceVisibilityHidden);
   5228         return;
   5229     case CSSPropertyWebkitBoxDirection:
   5230         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
   5231         return;
   5232     case CSSPropertyWebkitBoxLines:
   5233         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
   5234         return;
   5235     case CSSPropertyWebkitBoxOrient:
   5236         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
   5237         return;
   5238     case CSSPropertyWebkitBoxPack:
   5239     {
   5240         HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
   5241         if (!primitiveValue)
   5242             return;
   5243         EBoxAlignment boxPack = *primitiveValue;
   5244         if (boxPack != BSTRETCH && boxPack != BBASELINE)
   5245             m_style->setBoxPack(boxPack);
   5246         return;
   5247     }
   5248     case CSSPropertyWebkitBoxFlex:
   5249         HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex)
   5250         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   5251             return; // Error case.
   5252         m_style->setBoxFlex(primitiveValue->getFloatValue());
   5253         return;
   5254     case CSSPropertyWebkitBoxFlexGroup:
   5255         HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup)
   5256         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   5257             return; // Error case.
   5258         m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue()));
   5259         return;
   5260     case CSSPropertyWebkitBoxOrdinalGroup:
   5261         HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup)
   5262         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
   5263             return; // Error case.
   5264         m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue()));
   5265         return;
   5266     case CSSPropertyBoxSizing:
   5267         HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing)
   5268         if (!primitiveValue)
   5269             return;
   5270         if (primitiveValue->getIdent() == CSSValueContentBox)
   5271             m_style->setBoxSizing(CONTENT_BOX);
   5272         else
   5273             m_style->setBoxSizing(BORDER_BOX);
   5274         return;
   5275     case CSSPropertyWebkitColumnCount: {
   5276         if (isInherit) {
   5277             if (m_parentStyle->hasAutoColumnCount())
   5278                 m_style->setHasAutoColumnCount();
   5279             else
   5280                 m_style->setColumnCount(m_parentStyle->columnCount());
   5281             return;
   5282         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
   5283             m_style->setHasAutoColumnCount();
   5284             return;
   5285         }
   5286         m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue()));
   5287         return;
   5288     }
   5289     case CSSPropertyWebkitColumnGap: {
   5290         if (isInherit) {
   5291             if (m_parentStyle->hasNormalColumnGap())
   5292                 m_style->setHasNormalColumnGap();
   5293             else
   5294                 m_style->setColumnGap(m_parentStyle->columnGap());
   5295             return;
   5296         } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) {
   5297             m_style->setHasNormalColumnGap();
   5298             return;
   5299         }
   5300         m_style->setColumnGap(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
   5301         return;
   5302     }
   5303     case CSSPropertyWebkitColumnSpan: {
   5304         HANDLE_INHERIT_AND_INITIAL(columnSpan, ColumnSpan)
   5305         m_style->setColumnSpan(primitiveValue->getIdent() == CSSValueAll);
   5306         return;
   5307     }
   5308     case CSSPropertyWebkitColumnWidth: {
   5309         if (isInherit) {
   5310             if (m_parentStyle->hasAutoColumnWidth())
   5311                 m_style->setHasAutoColumnWidth();
   5312             else
   5313                 m_style->setColumnWidth(m_parentStyle->columnWidth());
   5314             return;
   5315         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
   5316             m_style->setHasAutoColumnWidth();
   5317             return;
   5318         }
   5319         m_style->setColumnWidth(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
   5320         return;
   5321     }
   5322     case CSSPropertyWebkitColumnRuleStyle:
   5323         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
   5324         return;
   5325     case CSSPropertyWebkitColumnBreakBefore:
   5326         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
   5327         return;
   5328     case CSSPropertyWebkitColumnBreakAfter:
   5329         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
   5330         return;
   5331     case CSSPropertyWebkitColumnBreakInside: {
   5332         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
   5333         EPageBreak pb = *primitiveValue;
   5334         if (pb != PBALWAYS)
   5335             m_style->setColumnBreakInside(pb);
   5336         return;
   5337     }
   5338      case CSSPropertyWebkitColumnRule:
   5339         if (isInherit) {
   5340             m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
   5341             m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
   5342             m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
   5343         }
   5344         else if (isInitial)
   5345             m_style->resetColumnRule();
   5346         return;
   5347     case CSSPropertyWebkitColumns:
   5348         if (isInherit) {
   5349             if (m_parentStyle->hasAutoColumnWidth())
   5350                 m_style->setHasAutoColumnWidth();
   5351             else
   5352                 m_style->setColumnWidth(m_parentStyle->columnWidth());
   5353             m_style->setColumnCount(m_parentStyle->columnCount());
   5354         } else if (isInitial) {
   5355             m_style->setHasAutoColumnWidth();
   5356             m_style->setColumnCount(RenderStyle::initialColumnCount());
   5357         }
   5358         return;
   5359     case CSSPropertyWebkitMarquee:
   5360         if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
   5361         m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
   5362         m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
   5363         m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
   5364         m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
   5365         m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
   5366         return;
   5367 #if ENABLE(WCSS)
   5368     case CSSPropertyWapMarqueeLoop:
   5369 #endif
   5370     case CSSPropertyWebkitMarqueeRepetition: {
   5371         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
   5372         if (!primitiveValue)
   5373             return;
   5374         if (primitiveValue->getIdent() == CSSValueInfinite)
   5375             m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
   5376         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
   5377             m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
   5378         return;
   5379     }
   5380 #if ENABLE(WCSS)
   5381     case CSSPropertyWapMarqueeSpeed:
   5382 #endif
   5383     case CSSPropertyWebkitMarqueeSpeed: {
   5384         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
   5385         if (!primitiveValue)
   5386             return;
   5387         if (primitiveValue->getIdent()) {
   5388             switch (primitiveValue->getIdent()) {
   5389                 case CSSValueSlow:
   5390                     m_style->setMarqueeSpeed(500); // 500 msec.
   5391                     break;
   5392                 case CSSValueNormal:
   5393                     m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
   5394                     break;
   5395                 case CSSValueFast:
   5396                     m_style->setMarqueeSpeed(10); // 10msec. Super fast.
   5397                     break;
   5398             }
   5399         }
   5400         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
   5401             m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
   5402         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
   5403             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
   5404         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
   5405             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
   5406         return;
   5407     }
   5408     case CSSPropertyWebkitMarqueeIncrement: {
   5409         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
   5410         if (!primitiveValue)
   5411             return;
   5412         if (primitiveValue->getIdent()) {
   5413             switch (primitiveValue->getIdent()) {
   5414                 case CSSValueSmall:
   5415                     m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
   5416                     break;
   5417                 case CSSValueNormal:
   5418                     m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
   5419                     break;
   5420                 case CSSValueLarge:
   5421                     m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
   5422                     break;
   5423             }
   5424         }
   5425         else {
   5426             bool ok = true;
   5427             Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
   5428             if (ok)
   5429                 m_style->setMarqueeIncrement(marqueeLength);
   5430         }
   5431         return;
   5432     }
   5433 #if ENABLE(WCSS)
   5434     case CSSPropertyWapMarqueeStyle:
   5435 #endif
   5436     case CSSPropertyWebkitMarqueeStyle:
   5437         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
   5438         return;
   5439 #if ENABLE(WCSS)
   5440     case CSSPropertyWapMarqueeDir:
   5441         HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
   5442         if (primitiveValue && primitiveValue->getIdent()) {
   5443             switch (primitiveValue->getIdent()) {
   5444             case CSSValueLtr:
   5445                 m_style->setMarqueeDirection(MRIGHT);
   5446                 break;
   5447             case CSSValueRtl:
   5448                 m_style->setMarqueeDirection(MLEFT);
   5449                 break;
   5450             default:
   5451                 m_style->setMarqueeDirection(*primitiveValue);
   5452                 break;
   5453             }
   5454         }
   5455         return;
   5456 #endif
   5457     case CSSPropertyWebkitMarqueeDirection:
   5458         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
   5459         return;
   5460     case CSSPropertyWebkitUserDrag:
   5461         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
   5462         return;
   5463     case CSSPropertyWebkitUserModify:
   5464         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
   5465         return;
   5466     case CSSPropertyWebkitUserSelect:
   5467         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
   5468         return;
   5469 
   5470     case CSSPropertyTextOverflow: {
   5471         // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
   5472         // work with WinIE-specific pages that use the property.
   5473         HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow)
   5474         if (!primitiveValue || !primitiveValue->getIdent())
   5475             return;
   5476         m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis);
   5477         return;
   5478     }
   5479     case CSSPropertyWebkitMarginCollapse: {
   5480         if (isInherit) {
   5481             m_style->setMarginBeforeCollapse(m_parentStyle->marginBeforeCollapse());
   5482             m_style->setMarginAfterCollapse(m_parentStyle->marginAfterCollapse());
   5483         }
   5484         else if (isInitial) {
   5485             m_style->setMarginBeforeCollapse(MCOLLAPSE);
   5486             m_style->setMarginAfterCollapse(MCOLLAPSE);
   5487         }
   5488         return;
   5489     }
   5490 
   5491     case CSSPropertyWebkitMarginBeforeCollapse:
   5492     case CSSPropertyWebkitMarginTopCollapse:
   5493         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginBeforeCollapse, MarginBeforeCollapse)
   5494         return;
   5495     case CSSPropertyWebkitMarginAfterCollapse:
   5496     case CSSPropertyWebkitMarginBottomCollapse:
   5497         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginAfterCollapse, MarginAfterCollapse)
   5498         return;
   5499     case CSSPropertyWebkitLineClamp: {
   5500         HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
   5501         if (!primitiveValue)
   5502             return;
   5503         int type = primitiveValue->primitiveType();
   5504         if (type == CSSPrimitiveValue::CSS_NUMBER)
   5505             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
   5506         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5507             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
   5508         return;
   5509     }
   5510     case CSSPropertyWebkitHighlight: {
   5511         HANDLE_INHERIT_AND_INITIAL(highlight, Highlight);
   5512         if (primitiveValue->getIdent() == CSSValueNone)
   5513             m_style->setHighlight(nullAtom);
   5514         else
   5515             m_style->setHighlight(primitiveValue->getStringValue());
   5516         return;
   5517     }
   5518     case CSSPropertyWebkitHyphens: {
   5519         HANDLE_INHERIT_AND_INITIAL(hyphens, Hyphens);
   5520         m_style->setHyphens(*primitiveValue);
   5521         return;
   5522     }
   5523     case CSSPropertyWebkitHyphenateCharacter: {
   5524         HANDLE_INHERIT_AND_INITIAL(hyphenationString, HyphenationString);
   5525         if (primitiveValue->getIdent() == CSSValueAuto)
   5526             m_style->setHyphenationString(nullAtom);
   5527         else
   5528             m_style->setHyphenationString(primitiveValue->getStringValue());
   5529         return;
   5530     }
   5531     case CSSPropertyWebkitHyphenateLimitAfter: {
   5532         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter);
   5533         if (primitiveValue->getIdent() == CSSValueAuto)
   5534             m_style->setHyphenationLimitAfter(-1);
   5535         else
   5536             m_style->setHyphenationLimitAfter(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max())));
   5537         return;
   5538     }
   5539     case CSSPropertyWebkitHyphenateLimitBefore: {
   5540         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore);
   5541         if (primitiveValue->getIdent() == CSSValueAuto)
   5542             m_style->setHyphenationLimitBefore(-1);
   5543         else
   5544             m_style->setHyphenationLimitBefore(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max())));
   5545         return;
   5546     }
   5547     case CSSPropertyWebkitLocale: {
   5548         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
   5549         if (primitiveValue->getIdent() == CSSValueAuto)
   5550             m_style->setLocale(nullAtom);
   5551         else
   5552             m_style->setLocale(primitiveValue->getStringValue());
   5553         return;
   5554     }
   5555     case CSSPropertyWebkitBorderFit: {
   5556         HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit);
   5557         if (primitiveValue->getIdent() == CSSValueBorder)
   5558             m_style->setBorderFit(BorderFitBorder);
   5559         else
   5560             m_style->setBorderFit(BorderFitLines);
   5561         return;
   5562     }
   5563     case CSSPropertyWebkitTextSizeAdjust: {
   5564         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
   5565         if (!primitiveValue || !primitiveValue->getIdent()) return;
   5566         m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
   5567         m_fontDirty = true;
   5568         return;
   5569     }
   5570     case CSSPropertyWebkitTextSecurity:
   5571         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
   5572         return;
   5573 
   5574 #if ENABLE(DASHBOARD_SUPPORT)
   5575     case CSSPropertyWebkitDashboardRegion: {
   5576         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
   5577         if (!primitiveValue)
   5578             return;
   5579 
   5580         if (primitiveValue->getIdent() == CSSValueNone) {
   5581             m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
   5582             return;
   5583         }
   5584 
   5585         DashboardRegion *region = primitiveValue->getDashboardRegionValue();
   5586         if (!region)
   5587             return;
   5588 
   5589         DashboardRegion *first = region;
   5590         while (region) {
   5591             Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
   5592             Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
   5593             Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
   5594             Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
   5595             if (region->m_isCircle)
   5596                 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
   5597             else if (region->m_isRectangle)
   5598                 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
   5599             region = region->m_next.get();
   5600         }
   5601 
   5602         m_element->document()->setHasDashboardRegions(true);
   5603 
   5604         return;
   5605     }
   5606 #endif
   5607     case CSSPropertyWebkitRtlOrdering:
   5608         HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered)
   5609         if (!primitiveValue || !primitiveValue->getIdent())
   5610             return;
   5611         m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual);
   5612         return;
   5613     case CSSPropertyWebkitTextStrokeWidth: {
   5614         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
   5615         float width = 0;
   5616         switch (primitiveValue->getIdent()) {
   5617             case CSSValueThin:
   5618             case CSSValueMedium:
   5619             case CSSValueThick: {
   5620                 double result = 1.0 / 48;
   5621                 if (primitiveValue->getIdent() == CSSValueMedium)
   5622                     result *= 3;
   5623                 else if (primitiveValue->getIdent() == CSSValueThick)
   5624                     result *= 5;
   5625                 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
   5626                 break;
   5627             }
   5628             default:
   5629                 width = primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
   5630                 break;
   5631         }
   5632         m_style->setTextStrokeWidth(width);
   5633         return;
   5634     }
   5635     case CSSPropertyWebkitTransform: {
   5636         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
   5637         TransformOperations operations;
   5638         createTransformOperations(value, style(), m_rootElementStyle, operations);
   5639         m_style->setTransform(operations);
   5640         return;
   5641     }
   5642     case CSSPropertyWebkitTransformOrigin:
   5643         HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
   5644         HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
   5645         HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
   5646         return;
   5647     case CSSPropertyWebkitTransformOriginX: {
   5648         HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
   5649         if (!primitiveValue)
   5650             return;
   5651         Length l;
   5652         int type = primitiveValue->primitiveType();
   5653         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5654             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   5655         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5656             l = Length(primitiveValue->getDoubleValue(), Percent);
   5657         else
   5658             return;
   5659         m_style->setTransformOriginX(l);
   5660         break;
   5661     }
   5662     case CSSPropertyWebkitTransformOriginY: {
   5663         HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
   5664         if (!primitiveValue)
   5665             return;
   5666         Length l;
   5667         int type = primitiveValue->primitiveType();
   5668         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5669             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   5670         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5671             l = Length(primitiveValue->getDoubleValue(), Percent);
   5672         else
   5673             return;
   5674         m_style->setTransformOriginY(l);
   5675         break;
   5676     }
   5677     case CSSPropertyWebkitTransformOriginZ: {
   5678         HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
   5679         if (!primitiveValue)
   5680             return;
   5681         float f;
   5682         int type = primitiveValue->primitiveType();
   5683         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5684             f = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle));
   5685         else
   5686             return;
   5687         m_style->setTransformOriginZ(f);
   5688         break;
   5689     }
   5690     case CSSPropertyWebkitTransformStyle:
   5691         HANDLE_INHERIT_AND_INITIAL(transformStyle3D, TransformStyle3D)
   5692         if (primitiveValue)
   5693             m_style->setTransformStyle3D((primitiveValue->getIdent() == CSSValuePreserve3d) ? TransformStyle3DPreserve3D : TransformStyle3DFlat);
   5694         return;
   5695     case CSSPropertyWebkitPerspective: {
   5696         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
   5697         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
   5698             m_style->setPerspective(0);
   5699             return;
   5700         }
   5701 
   5702         float perspectiveValue;
   5703         int type = primitiveValue->primitiveType();
   5704         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5705             perspectiveValue = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor));
   5706         else if (type == CSSPrimitiveValue::CSS_NUMBER) {
   5707             // For backward compatibility, treat valueless numbers as px.
   5708             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
   5709         } else
   5710             return;
   5711 
   5712         if (perspectiveValue >= 0.0f)
   5713             m_style->setPerspective(perspectiveValue);
   5714         return;
   5715     }
   5716     case CSSPropertyWebkitPerspectiveOrigin:
   5717         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
   5718         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
   5719         return;
   5720     case CSSPropertyWebkitPerspectiveOriginX: {
   5721         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
   5722         if (!primitiveValue)
   5723             return;
   5724         Length l;
   5725         int type = primitiveValue->primitiveType();
   5726         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5727             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   5728         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5729             l = Length(primitiveValue->getDoubleValue(), Percent);
   5730         else
   5731             return;
   5732         m_style->setPerspectiveOriginX(l);
   5733         return;
   5734     }
   5735     case CSSPropertyWebkitPerspectiveOriginY: {
   5736         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
   5737         if (!primitiveValue)
   5738             return;
   5739         Length l;
   5740         int type = primitiveValue->primitiveType();
   5741         if (CSSPrimitiveValue::isUnitTypeLength(type))
   5742             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   5743         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   5744             l = Length(primitiveValue->getDoubleValue(), Percent);
   5745         else
   5746             return;
   5747         m_style->setPerspectiveOriginY(l);
   5748         return;
   5749     }
   5750     case CSSPropertyWebkitAnimation:
   5751         if (isInitial)
   5752             m_style->clearAnimations();
   5753         else if (isInherit)
   5754             m_style->inheritAnimations(m_parentStyle->animations());
   5755         return;
   5756     case CSSPropertyWebkitAnimationDelay:
   5757         HANDLE_ANIMATION_VALUE(delay, Delay, value)
   5758         return;
   5759     case CSSPropertyWebkitAnimationDirection:
   5760         HANDLE_ANIMATION_VALUE(direction, Direction, value)
   5761         return;
   5762     case CSSPropertyWebkitAnimationDuration:
   5763         HANDLE_ANIMATION_VALUE(duration, Duration, value)
   5764         return;
   5765     case CSSPropertyWebkitAnimationFillMode:
   5766         HANDLE_ANIMATION_VALUE(fillMode, FillMode, value)
   5767         return;
   5768     case CSSPropertyWebkitAnimationIterationCount:
   5769         HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value)
   5770         return;
   5771     case CSSPropertyWebkitAnimationName:
   5772         HANDLE_ANIMATION_VALUE(name, Name, value)
   5773         return;
   5774     case CSSPropertyWebkitAnimationPlayState:
   5775         HANDLE_ANIMATION_VALUE(playState, PlayState, value)
   5776         return;
   5777     case CSSPropertyWebkitAnimationTimingFunction:
   5778         HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value)
   5779         return;
   5780     case CSSPropertyWebkitTransition:
   5781         if (isInitial)
   5782             m_style->clearTransitions();
   5783         else if (isInherit)
   5784             m_style->inheritTransitions(m_parentStyle->transitions());
   5785         return;
   5786     case CSSPropertyWebkitTransitionDelay:
   5787         HANDLE_TRANSITION_VALUE(delay, Delay, value)
   5788         return;
   5789     case CSSPropertyWebkitTransitionDuration:
   5790         HANDLE_TRANSITION_VALUE(duration, Duration, value)
   5791         return;
   5792     case CSSPropertyWebkitTransitionProperty:
   5793         HANDLE_TRANSITION_VALUE(property, Property, value)
   5794         return;
   5795     case CSSPropertyWebkitTransitionTimingFunction:
   5796         HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value)
   5797         return;
   5798     case CSSPropertyPointerEvents:
   5799     {
   5800 #if ENABLE(DASHBOARD_SUPPORT)
   5801         // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
   5802         // pointer-events property by not applying it in Dashboard.
   5803         Settings* settings = m_checker.m_document->settings();
   5804         if (settings && settings->usesDashboardBackwardCompatibilityMode())
   5805             return;
   5806 #endif
   5807         HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents)
   5808         if (!primitiveValue)
   5809             return;
   5810         m_style->setPointerEvents(*primitiveValue);
   5811         return;
   5812     }
   5813     case CSSPropertyWebkitColorCorrection:
   5814         if (isInherit)
   5815             m_style->setColorSpace(m_parentStyle->colorSpace());
   5816         else if (isInitial)
   5817             m_style->setColorSpace(ColorSpaceDeviceRGB);
   5818         else {
   5819             if (!primitiveValue)
   5820                 return;
   5821             m_style->setColorSpace(*primitiveValue);
   5822         }
   5823         return;
   5824     case CSSPropertySize:
   5825         applyPageSizeProperty(value);
   5826         return;
   5827 
   5828     case CSSPropertySpeak:
   5829         HANDLE_INHERIT_AND_INITIAL(speak, Speak);
   5830         if (!primitiveValue)
   5831             return;
   5832         m_style->setSpeak(*primitiveValue);
   5833         return;
   5834 
   5835     case CSSPropertyInvalid:
   5836         return;
   5837 
   5838     // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
   5839     case CSSPropertyWebkitBorderEnd:
   5840     case CSSPropertyWebkitBorderEndColor:
   5841     case CSSPropertyWebkitBorderEndStyle:
   5842     case CSSPropertyWebkitBorderEndWidth:
   5843     case CSSPropertyWebkitBorderStart:
   5844     case CSSPropertyWebkitBorderStartColor:
   5845     case CSSPropertyWebkitBorderStartStyle:
   5846     case CSSPropertyWebkitBorderStartWidth:
   5847     case CSSPropertyWebkitBorderBefore:
   5848     case CSSPropertyWebkitBorderBeforeColor:
   5849     case CSSPropertyWebkitBorderBeforeStyle:
   5850     case CSSPropertyWebkitBorderBeforeWidth:
   5851     case CSSPropertyWebkitBorderAfter:
   5852     case CSSPropertyWebkitBorderAfterColor:
   5853     case CSSPropertyWebkitBorderAfterStyle:
   5854     case CSSPropertyWebkitBorderAfterWidth:
   5855     case CSSPropertyWebkitMarginEnd:
   5856     case CSSPropertyWebkitMarginStart:
   5857     case CSSPropertyWebkitMarginBefore:
   5858     case CSSPropertyWebkitMarginAfter:
   5859     case CSSPropertyWebkitPaddingEnd:
   5860     case CSSPropertyWebkitPaddingStart:
   5861     case CSSPropertyWebkitPaddingBefore:
   5862     case CSSPropertyWebkitPaddingAfter:
   5863     case CSSPropertyWebkitLogicalWidth:
   5864     case CSSPropertyWebkitLogicalHeight:
   5865     case CSSPropertyWebkitMinLogicalWidth:
   5866     case CSSPropertyWebkitMinLogicalHeight:
   5867     case CSSPropertyWebkitMaxLogicalWidth:
   5868     case CSSPropertyWebkitMaxLogicalHeight:
   5869         ASSERT_NOT_REACHED();
   5870         break;
   5871 
   5872     case CSSPropertyFontStretch:
   5873     case CSSPropertyPage:
   5874     case CSSPropertyTextLineThrough:
   5875     case CSSPropertyTextLineThroughColor:
   5876     case CSSPropertyTextLineThroughMode:
   5877     case CSSPropertyTextLineThroughStyle:
   5878     case CSSPropertyTextLineThroughWidth:
   5879     case CSSPropertyTextOverline:
   5880     case CSSPropertyTextOverlineColor:
   5881     case CSSPropertyTextOverlineMode:
   5882     case CSSPropertyTextOverlineStyle:
   5883     case CSSPropertyTextOverlineWidth:
   5884     case CSSPropertyTextUnderline:
   5885     case CSSPropertyTextUnderlineColor:
   5886     case CSSPropertyTextUnderlineMode:
   5887     case CSSPropertyTextUnderlineStyle:
   5888     case CSSPropertyTextUnderlineWidth:
   5889     case CSSPropertyWebkitFontSizeDelta:
   5890     case CSSPropertyWebkitTextDecorationsInEffect:
   5891     case CSSPropertyWebkitTextStroke:
   5892     case CSSPropertyWebkitTextEmphasis:
   5893         return;
   5894 #if ENABLE(WCSS)
   5895     case CSSPropertyWapInputFormat:
   5896         if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) {
   5897             String mask = primitiveValue->getStringValue();
   5898             static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask);
   5899         }
   5900         return;
   5901 
   5902     case CSSPropertyWapInputRequired:
   5903         if (primitiveValue && m_element->isFormControlElement()) {
   5904             HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element);
   5905             bool required = primitiveValue->getStringValue() == "true";
   5906             element->setRequired(required);
   5907         }
   5908         return;
   5909 #endif
   5910 
   5911     // CSS Text Layout Module Level 3: Vertical writing support
   5912     case CSSPropertyWebkitWritingMode: {
   5913         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
   5914         if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
   5915             m_element->document()->setWritingModeSetOnDocumentElement(true);
   5916         FontDescription fontDescription = m_style->fontDescription();
   5917         fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
   5918         if (m_style->setFontDescription(fontDescription))
   5919             m_fontDirty = true;
   5920         return;
   5921     }
   5922 
   5923     case CSSPropertyWebkitTextCombine:
   5924         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine)
   5925         return;
   5926 
   5927     case CSSPropertyWebkitTextEmphasisPosition:
   5928         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textEmphasisPosition, TextEmphasisPosition)
   5929         return;
   5930 
   5931     case CSSPropertyWebkitTextEmphasisStyle:
   5932         HANDLE_INHERIT_AND_INITIAL(textEmphasisFill, TextEmphasisFill)
   5933         HANDLE_INHERIT_AND_INITIAL(textEmphasisMark, TextEmphasisMark)
   5934         HANDLE_INHERIT_AND_INITIAL(textEmphasisCustomMark, TextEmphasisCustomMark)
   5935         if (isInherit || isInitial)
   5936             return;
   5937 
   5938         if (value->isValueList()) {
   5939             CSSValueList* list = static_cast<CSSValueList*>(value);
   5940             ASSERT(list->length() == 2);
   5941             if (list->length() != 2)
   5942                 return;
   5943             for (unsigned i = 0; i < 2; ++i) {
   5944                 CSSValue* item = list->itemWithoutBoundsCheck(i);
   5945                 if (!item->isPrimitiveValue())
   5946                     continue;
   5947 
   5948                 CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(item);
   5949                 if (value->getIdent() == CSSValueFilled || value->getIdent() == CSSValueOpen)
   5950                     m_style->setTextEmphasisFill(*value);
   5951                 else
   5952                     m_style->setTextEmphasisMark(*value);
   5953             }
   5954             m_style->setTextEmphasisCustomMark(nullAtom);
   5955             return;
   5956         }
   5957 
   5958         if (!primitiveValue)
   5959             return;
   5960 
   5961         if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
   5962             m_style->setTextEmphasisFill(TextEmphasisFillFilled);
   5963             m_style->setTextEmphasisMark(TextEmphasisMarkCustom);
   5964             m_style->setTextEmphasisCustomMark(primitiveValue->getStringValue());
   5965             return;
   5966         }
   5967 
   5968         m_style->setTextEmphasisCustomMark(nullAtom);
   5969 
   5970         if (primitiveValue->getIdent() == CSSValueFilled || primitiveValue->getIdent() == CSSValueOpen) {
   5971             m_style->setTextEmphasisFill(*primitiveValue);
   5972             m_style->setTextEmphasisMark(TextEmphasisMarkAuto);
   5973         } else {
   5974             m_style->setTextEmphasisFill(TextEmphasisFillFilled);
   5975             m_style->setTextEmphasisMark(*primitiveValue);
   5976         }
   5977 
   5978         return;
   5979 
   5980     case CSSPropertyWebkitTextOrientation: {
   5981         if (!isInherit && !isInitial && !primitiveValue)
   5982             return;
   5983 
   5984         TextOrientation result;
   5985         if (isInherit)
   5986             result = m_parentStyle->fontDescription().textOrientation();
   5987         else if (isInitial)
   5988             result = RenderStyle::initialTextOrientation();
   5989         else
   5990             result = *primitiveValue;
   5991 
   5992         FontDescription fontDescription = m_style->fontDescription();
   5993         if (fontDescription.textOrientation() != result) {
   5994             fontDescription.setTextOrientation(result);
   5995             if (m_style->setFontDescription(fontDescription))
   5996                 m_fontDirty = true;
   5997         }
   5998         return;
   5999     }
   6000 
   6001     case CSSPropertyWebkitLineBoxContain: {
   6002         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
   6003         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
   6004             m_style->setLineBoxContain(LineBoxContainNone);
   6005             return;
   6006         }
   6007 
   6008         if (!value->isCSSLineBoxContainValue())
   6009             return;
   6010 
   6011         CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
   6012         m_style->setLineBoxContain(lineBoxContainValue->value());
   6013         return;
   6014     }
   6015 
   6016     // These properties are implemented in the CSSStyleApplyProperty lookup table.
   6017     case CSSPropertyColor:
   6018     case CSSPropertyDirection:
   6019     case CSSPropertyBackgroundAttachment:
   6020     case CSSPropertyBackgroundClip:
   6021     case CSSPropertyWebkitBackgroundClip:
   6022     case CSSPropertyWebkitBackgroundComposite:
   6023     case CSSPropertyBackgroundOrigin:
   6024     case CSSPropertyWebkitBackgroundOrigin:
   6025     case CSSPropertyBackgroundImage:
   6026     case CSSPropertyBackgroundSize:
   6027     case CSSPropertyWebkitBackgroundSize:
   6028     case CSSPropertyWebkitMaskAttachment:
   6029     case CSSPropertyWebkitMaskClip:
   6030     case CSSPropertyWebkitMaskComposite:
   6031     case CSSPropertyWebkitMaskOrigin:
   6032     case CSSPropertyWebkitMaskImage:
   6033     case CSSPropertyWebkitMaskSize:
   6034     case CSSPropertyBackgroundColor:
   6035     case CSSPropertyBorderBottomColor:
   6036     case CSSPropertyBorderLeftColor:
   6037     case CSSPropertyBorderRightColor:
   6038     case CSSPropertyBorderTopColor:
   6039     case CSSPropertyBorderTopStyle:
   6040     case CSSPropertyBorderRightStyle:
   6041     case CSSPropertyBorderBottomStyle:
   6042     case CSSPropertyBorderLeftStyle:
   6043     case CSSPropertyOutlineColor:
   6044     case CSSPropertyWebkitColumnRuleColor:
   6045     case CSSPropertyWebkitTextEmphasisColor:
   6046     case CSSPropertyWebkitTextFillColor:
   6047     case CSSPropertyWebkitTextStrokeColor:
   6048     case CSSPropertyBackgroundPosition:
   6049     case CSSPropertyBackgroundPositionX:
   6050     case CSSPropertyBackgroundPositionY:
   6051     case CSSPropertyWebkitMaskPosition:
   6052     case CSSPropertyWebkitMaskPositionX:
   6053     case CSSPropertyWebkitMaskPositionY:
   6054     case CSSPropertyBackgroundRepeat:
   6055     case CSSPropertyBackgroundRepeatX:
   6056     case CSSPropertyBackgroundRepeatY:
   6057     case CSSPropertyWebkitMaskRepeat:
   6058     case CSSPropertyWebkitMaskRepeatX:
   6059     case CSSPropertyWebkitMaskRepeatY:
   6060     case CSSPropertyOverflow:
   6061     case CSSPropertyOverflowX:
   6062     case CSSPropertyOverflowY:
   6063         ASSERT_NOT_REACHED();
   6064         return;
   6065 
   6066 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
   6067     case CSSPropertyWebkitTapHighlightColor: {
   6068         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
   6069         if (!primitiveValue)
   6070             break;
   6071 
   6072         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
   6073         m_style->setTapHighlightColor(col);
   6074         return;
   6075     }
   6076 #endif
   6077 
   6078 #if ENABLE(SVG)
   6079     default:
   6080         // Try the SVG properties
   6081         applySVGProperty(id, value);
   6082         return;
   6083 #endif
   6084     }
   6085 }
   6086 
   6087 void CSSStyleSelector::applyPageSizeProperty(CSSValue* value)
   6088 {
   6089     m_style->resetPageSizeType();
   6090     if (!value->isValueList())
   6091         return;
   6092     CSSValueList* valueList = static_cast<CSSValueList*>(value);
   6093     Length width;
   6094     Length height;
   6095     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
   6096     switch (valueList->length()) {
   6097     case 2: {
   6098         // <length>{2} | <page-size> <orientation>
   6099         pageSizeType = PAGE_SIZE_RESOLVED;
   6100         if (!valueList->item(0)->isPrimitiveValue() || !valueList->item(1)->isPrimitiveValue())
   6101             return;
   6102         CSSPrimitiveValue* primitiveValue0 = static_cast<CSSPrimitiveValue*>(valueList->item(0));
   6103         CSSPrimitiveValue* primitiveValue1 = static_cast<CSSPrimitiveValue*>(valueList->item(1));
   6104         int type0 = primitiveValue0->primitiveType();
   6105         int type1 = primitiveValue1->primitiveType();
   6106         if (CSSPrimitiveValue::isUnitTypeLength(type0)) {
   6107             // <length>{2}
   6108             if (!CSSPrimitiveValue::isUnitTypeLength(type1))
   6109                 return;
   6110             width = Length(primitiveValue0->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
   6111             height = Length(primitiveValue1->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
   6112         } else {
   6113             // <page-size> <orientation>
   6114             // The value order is guaranteed. See CSSParser::parseSizeParameter.
   6115             if (!pageSizeFromName(primitiveValue0, primitiveValue1, width, height))
   6116                 return;
   6117         }
   6118         break;
   6119     }
   6120     case 1: {
   6121         // <length> | auto | <page-size> | [ portrait | landscape]
   6122         if (!valueList->item(0)->isPrimitiveValue())
   6123             return;
   6124         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valueList->item(0));
   6125         int type = primitiveValue->primitiveType();
   6126         if (CSSPrimitiveValue::isUnitTypeLength(type)) {
   6127             // <length>
   6128             pageSizeType = PAGE_SIZE_RESOLVED;
   6129             width = height = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
   6130         } else {
   6131             if (type != CSSPrimitiveValue::CSS_IDENT)
   6132                 return;
   6133             switch (primitiveValue->getIdent()) {
   6134             case CSSValueAuto:
   6135                 pageSizeType = PAGE_SIZE_AUTO;
   6136                 break;
   6137             case CSSValuePortrait:
   6138                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
   6139                 break;
   6140             case CSSValueLandscape:
   6141                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
   6142                 break;
   6143             default:
   6144                 // <page-size>
   6145                 pageSizeType = PAGE_SIZE_RESOLVED;
   6146                 if (!pageSizeFromName(primitiveValue, 0, width, height))
   6147                     return;
   6148             }
   6149         }
   6150         break;
   6151     }
   6152     default:
   6153         return;
   6154     }
   6155     m_style->setPageSizeType(pageSizeType);
   6156     m_style->setPageSize(LengthSize(width, height));
   6157     return;
   6158 }
   6159 
   6160 bool CSSStyleSelector::pageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
   6161 {
   6162     static const Length a5Width = mmLength(148), a5Height = mmLength(210);
   6163     static const Length a4Width = mmLength(210), a4Height = mmLength(297);
   6164     static const Length a3Width = mmLength(297), a3Height = mmLength(420);
   6165     static const Length b5Width = mmLength(176), b5Height = mmLength(250);
   6166     static const Length b4Width = mmLength(250), b4Height = mmLength(353);
   6167     static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11);
   6168     static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14);
   6169     static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17);
   6170 
   6171     if (!pageSizeName || pageSizeName->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
   6172         return false;
   6173 
   6174     switch (pageSizeName->getIdent()) {
   6175     case CSSValueA5:
   6176         width = a5Width;
   6177         height = a5Height;
   6178         break;
   6179     case CSSValueA4:
   6180         width = a4Width;
   6181         height = a4Height;
   6182         break;
   6183     case CSSValueA3:
   6184         width = a3Width;
   6185         height = a3Height;
   6186         break;
   6187     case CSSValueB5:
   6188         width = b5Width;
   6189         height = b5Height;
   6190         break;
   6191     case CSSValueB4:
   6192         width = b4Width;
   6193         height = b4Height;
   6194         break;
   6195     case CSSValueLetter:
   6196         width = letterWidth;
   6197         height = letterHeight;
   6198         break;
   6199     case CSSValueLegal:
   6200         width = legalWidth;
   6201         height = legalHeight;
   6202         break;
   6203     case CSSValueLedger:
   6204         width = ledgerWidth;
   6205         height = ledgerHeight;
   6206         break;
   6207     default:
   6208         return false;
   6209     }
   6210 
   6211     if (pageOrientation) {
   6212         if (pageOrientation->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
   6213             return false;
   6214         switch (pageOrientation->getIdent()) {
   6215         case CSSValueLandscape:
   6216             std::swap(width, height);
   6217             break;
   6218         case CSSValuePortrait:
   6219             // Nothing to do.
   6220             break;
   6221         default:
   6222             return false;
   6223         }
   6224     }
   6225     return true;
   6226 }
   6227 
   6228 Length CSSStyleSelector::mmLength(double mm) const
   6229 {
   6230     return Length(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
   6231 }
   6232 
   6233 Length CSSStyleSelector::inchLength(double inch) const
   6234 {
   6235     return Length(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
   6236 }
   6237 
   6238 void CSSStyleSelector::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6239 {
   6240     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6241         layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
   6242         return;
   6243     }
   6244 
   6245     if (!value->isPrimitiveValue())
   6246         return;
   6247 
   6248     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6249     switch (primitiveValue->getIdent()) {
   6250         case CSSValueFixed:
   6251             layer->setAttachment(FixedBackgroundAttachment);
   6252             break;
   6253         case CSSValueScroll:
   6254             layer->setAttachment(ScrollBackgroundAttachment);
   6255             break;
   6256         case CSSValueLocal:
   6257             layer->setAttachment(LocalBackgroundAttachment);
   6258             break;
   6259         default:
   6260             return;
   6261     }
   6262 }
   6263 
   6264 void CSSStyleSelector::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6265 {
   6266     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6267         layer->setClip(FillLayer::initialFillClip(layer->type()));
   6268         return;
   6269     }
   6270 
   6271     if (!value->isPrimitiveValue())
   6272         return;
   6273 
   6274     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6275     layer->setClip(*primitiveValue);
   6276 }
   6277 
   6278 void CSSStyleSelector::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6279 {
   6280     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6281         layer->setComposite(FillLayer::initialFillComposite(layer->type()));
   6282         return;
   6283     }
   6284 
   6285     if (!value->isPrimitiveValue())
   6286         return;
   6287 
   6288     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6289     layer->setComposite(*primitiveValue);
   6290 }
   6291 
   6292 void CSSStyleSelector::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6293 {
   6294     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6295         layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
   6296         return;
   6297     }
   6298 
   6299     if (!value->isPrimitiveValue())
   6300         return;
   6301 
   6302     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6303     layer->setOrigin(*primitiveValue);
   6304 }
   6305 
   6306 StyleImage* CSSStyleSelector::styleImage(CSSPropertyID property, CSSValue* value)
   6307 {
   6308     if (value->isImageValue())
   6309         return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value));
   6310 
   6311     if (value->isImageGeneratorValue())
   6312         return static_cast<CSSImageGeneratorValue*>(value)->generatedImage();
   6313 
   6314     return 0;
   6315 }
   6316 
   6317 StyleImage* CSSStyleSelector::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
   6318 {
   6319     StyleImage* image = value->cachedOrPendingImage();
   6320     if (image && image->isPendingImage())
   6321         m_pendingImageProperties.add(property);
   6322     return image;
   6323 }
   6324 
   6325 void CSSStyleSelector::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
   6326 {
   6327     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6328         layer->setImage(FillLayer::initialFillImage(layer->type()));
   6329         return;
   6330     }
   6331 
   6332     layer->setImage(styleImage(property, value));
   6333 }
   6334 
   6335 void CSSStyleSelector::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6336 {
   6337     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6338         layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
   6339         return;
   6340     }
   6341 
   6342     if (!value->isPrimitiveValue())
   6343         return;
   6344 
   6345     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6346     layer->setRepeatX(*primitiveValue);
   6347 }
   6348 
   6349 void CSSStyleSelector::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6350 {
   6351     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6352         layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
   6353         return;
   6354     }
   6355 
   6356     if (!value->isPrimitiveValue())
   6357         return;
   6358 
   6359     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6360     layer->setRepeatY(*primitiveValue);
   6361 }
   6362 
   6363 void CSSStyleSelector::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6364 {
   6365     if (!value->isPrimitiveValue()) {
   6366         layer->setSizeType(SizeNone);
   6367         return;
   6368     }
   6369 
   6370     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6371     if (primitiveValue->getIdent() == CSSValueContain)
   6372         layer->setSizeType(Contain);
   6373     else if (primitiveValue->getIdent() == CSSValueCover)
   6374         layer->setSizeType(Cover);
   6375     else
   6376         layer->setSizeType(SizeLength);
   6377 
   6378     LengthSize b = FillLayer::initialFillSizeLength(layer->type());
   6379 
   6380     if (value->cssValueType() == CSSValue::CSS_INITIAL || primitiveValue->getIdent() == CSSValueContain
   6381         || primitiveValue->getIdent() == CSSValueCover) {
   6382         layer->setSizeLength(b);
   6383         return;
   6384     }
   6385 
   6386     Pair* pair = primitiveValue->getPairValue();
   6387     if (!pair || !pair->first() || !pair->second())
   6388         return;
   6389 
   6390     CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first());
   6391     CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second());
   6392 
   6393     Length firstLength, secondLength;
   6394     int firstType = first->primitiveType();
   6395     int secondType = second->primitiveType();
   6396 
   6397     float zoomFactor = m_style->effectiveZoom();
   6398 
   6399     if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
   6400         firstLength = Length(Auto);
   6401     else if (CSSPrimitiveValue::isUnitTypeLength(firstType))
   6402         firstLength = Length(first->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   6403     else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
   6404         firstLength = Length(first->getDoubleValue(), Percent);
   6405     else
   6406         return;
   6407 
   6408     if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
   6409         secondLength = Length(Auto);
   6410     else if (CSSPrimitiveValue::isUnitTypeLength(secondType))
   6411         secondLength = Length(second->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   6412     else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
   6413         secondLength = Length(second->getDoubleValue(), Percent);
   6414     else
   6415         return;
   6416 
   6417     b.setWidth(firstLength);
   6418     b.setHeight(secondLength);
   6419     layer->setSizeLength(b);
   6420 }
   6421 
   6422 void CSSStyleSelector::mapFillXPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6423 {
   6424     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6425         layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
   6426         return;
   6427     }
   6428 
   6429     if (!value->isPrimitiveValue())
   6430         return;
   6431 
   6432     float zoomFactor = m_style->effectiveZoom();
   6433 
   6434     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6435     Length l;
   6436     int type = primitiveValue->primitiveType();
   6437     if (CSSPrimitiveValue::isUnitTypeLength(type))
   6438         l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   6439     else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   6440         l = Length(primitiveValue->getDoubleValue(), Percent);
   6441     else
   6442         return;
   6443     layer->setXPosition(l);
   6444 }
   6445 
   6446 void CSSStyleSelector::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
   6447 {
   6448     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6449         layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
   6450         return;
   6451     }
   6452 
   6453     if (!value->isPrimitiveValue())
   6454         return;
   6455 
   6456     float zoomFactor = m_style->effectiveZoom();
   6457 
   6458     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6459     Length l;
   6460     int type = primitiveValue->primitiveType();
   6461     if (CSSPrimitiveValue::isUnitTypeLength(type))
   6462         l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
   6463     else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
   6464         l = Length(primitiveValue->getDoubleValue(), Percent);
   6465     else
   6466         return;
   6467     layer->setYPosition(l);
   6468 }
   6469 
   6470 void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value)
   6471 {
   6472     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6473         animation->setDelay(Animation::initialAnimationDelay());
   6474         return;
   6475     }
   6476 
   6477     if (!value->isPrimitiveValue())
   6478         return;
   6479 
   6480     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6481     if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
   6482         animation->setDelay(primitiveValue->getFloatValue());
   6483     else
   6484         animation->setDelay(primitiveValue->getFloatValue()/1000.0f);
   6485 }
   6486 
   6487 void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value)
   6488 {
   6489     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6490         layer->setDirection(Animation::initialAnimationDirection());
   6491         return;
   6492     }
   6493 
   6494     if (!value->isPrimitiveValue())
   6495         return;
   6496 
   6497     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6498     layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal);
   6499 }
   6500 
   6501 void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
   6502 {
   6503     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6504         animation->setDuration(Animation::initialAnimationDuration());
   6505         return;
   6506     }
   6507 
   6508     if (!value->isPrimitiveValue())
   6509         return;
   6510 
   6511     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6512     if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
   6513         animation->setDuration(primitiveValue->getFloatValue());
   6514     else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
   6515         animation->setDuration(primitiveValue->getFloatValue()/1000.0f);
   6516 }
   6517 
   6518 void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value)
   6519 {
   6520     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6521         layer->setFillMode(Animation::initialAnimationFillMode());
   6522         return;
   6523     }
   6524 
   6525     if (!value->isPrimitiveValue())
   6526         return;
   6527 
   6528     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6529     switch (primitiveValue->getIdent()) {
   6530     case CSSValueNone:
   6531         layer->setFillMode(AnimationFillModeNone);
   6532         break;
   6533     case CSSValueForwards:
   6534         layer->setFillMode(AnimationFillModeForwards);
   6535         break;
   6536     case CSSValueBackwards:
   6537         layer->setFillMode(AnimationFillModeBackwards);
   6538         break;
   6539     case CSSValueBoth:
   6540         layer->setFillMode(AnimationFillModeBoth);
   6541         break;
   6542     }
   6543 }
   6544 
   6545 void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value)
   6546 {
   6547     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6548         animation->setIterationCount(Animation::initialAnimationIterationCount());
   6549         return;
   6550     }
   6551 
   6552     if (!value->isPrimitiveValue())
   6553         return;
   6554 
   6555     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6556     if (primitiveValue->getIdent() == CSSValueInfinite)
   6557         animation->setIterationCount(-1);
   6558     else
   6559         animation->setIterationCount(int(primitiveValue->getFloatValue()));
   6560 }
   6561 
   6562 void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value)
   6563 {
   6564     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6565         layer->setName(Animation::initialAnimationName());
   6566         return;
   6567     }
   6568 
   6569     if (!value->isPrimitiveValue())
   6570         return;
   6571 
   6572     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6573     if (primitiveValue->getIdent() == CSSValueNone)
   6574         layer->setIsNoneAnimation(true);
   6575     else
   6576         layer->setName(primitiveValue->getStringValue());
   6577 }
   6578 
   6579 void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value)
   6580 {
   6581     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6582         layer->setPlayState(Animation::initialAnimationPlayState());
   6583         return;
   6584     }
   6585 
   6586     if (!value->isPrimitiveValue())
   6587         return;
   6588 
   6589     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6590     EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
   6591     layer->setPlayState(playState);
   6592 }
   6593 
   6594 void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value)
   6595 {
   6596     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6597         animation->setProperty(Animation::initialAnimationProperty());
   6598         return;
   6599     }
   6600 
   6601     if (!value->isPrimitiveValue())
   6602         return;
   6603 
   6604     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6605     if (primitiveValue->getIdent() == CSSValueAll)
   6606         animation->setProperty(cAnimateAll);
   6607     else if (primitiveValue->getIdent() == CSSValueNone)
   6608         animation->setProperty(cAnimateNone);
   6609     else
   6610         animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
   6611 }
   6612 
   6613 void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
   6614 {
   6615     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
   6616         animation->setTimingFunction(Animation::initialAnimationTimingFunction());
   6617         return;
   6618     }
   6619 
   6620     if (value->isPrimitiveValue()) {
   6621         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
   6622         switch (primitiveValue->getIdent()) {
   6623             case CSSValueLinear:
   6624                 animation->setTimingFunction(LinearTimingFunction::create());
   6625                 break;
   6626             case CSSValueEase:
   6627                 animation->setTimingFunction(CubicBezierTimingFunction::create());
   6628                 break;
   6629             case CSSValueEaseIn:
   6630                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 1.0, 1.0));
   6631                 break;
   6632             case CSSValueEaseOut:
   6633                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.0, 0.0, 0.58, 1.0));
   6634                 break;
   6635             case CSSValueEaseInOut:
   6636                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 0.58, 1.0));
   6637                 break;
   6638             case CSSValueStepStart:
   6639                 animation->setTimingFunction(StepsTimingFunction::create(1, true));
   6640                 break;
   6641             case CSSValueStepEnd:
   6642                 animation->setTimingFunction(StepsTimingFunction::create(1, false));
   6643                 break;
   6644         }
   6645         return;
   6646     }
   6647 
   6648     if (value->isTimingFunctionValue()) {
   6649         CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
   6650         if (timingFunction->isCubicBezierTimingFunctionValue()) {
   6651             CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value);
   6652             animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()));
   6653         } else if (timingFunction->isStepsTimingFunctionValue()) {
   6654             CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value);
   6655             animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()));
   6656         } else
   6657             animation->setTimingFunction(LinearTimingFunction::create());
   6658     }
   6659 }
   6660 
   6661 void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
   6662 {
   6663     // If we're a primitive value, then we are "none" and don't need to alter the empty image at all.
   6664     if (!value || value->isPrimitiveValue() || !value->isBorderImageValue())
   6665         return;
   6666 
   6667     // Retrieve the border image value.
   6668     CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
   6669 
   6670     // Set the image (this kicks off the load).
   6671     image.setImage(styleImage(property, borderImage->imageValue()));
   6672 
   6673     // Set up a length box to represent our image slices.
   6674     LengthBox l;
   6675     Rect* r = borderImage->m_imageSliceRect.get();
   6676     if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   6677         l.m_top = Length(r->top()->getDoubleValue(), Percent);
   6678     else
   6679         l.m_top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
   6680     if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   6681         l.m_bottom = Length(r->bottom()->getDoubleValue(), Percent);
   6682     else
   6683         l.m_bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
   6684     if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   6685         l.m_left = Length(r->left()->getDoubleValue(), Percent);
   6686     else
   6687         l.m_left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
   6688     if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
   6689         l.m_right = Length(r->right()->getDoubleValue(), Percent);
   6690     else
   6691         l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
   6692     image.setSlices(l);
   6693 
   6694     // Set the appropriate rules for stretch/round/repeat of the slices
   6695     ENinePieceImageRule horizontalRule;
   6696     switch (borderImage->m_horizontalSizeRule) {
   6697         case CSSValueStretch:
   6698             horizontalRule = StretchImageRule;
   6699             break;
   6700         case CSSValueRound:
   6701             horizontalRule = RoundImageRule;
   6702             break;
   6703         default: // CSSValueRepeat
   6704             horizontalRule = RepeatImageRule;
   6705             break;
   6706     }
   6707     image.setHorizontalRule(horizontalRule);
   6708 
   6709     ENinePieceImageRule verticalRule;
   6710     switch (borderImage->m_verticalSizeRule) {
   6711         case CSSValueStretch:
   6712             verticalRule = StretchImageRule;
   6713             break;
   6714         case CSSValueRound:
   6715             verticalRule = RoundImageRule;
   6716             break;
   6717         default: // CSSValueRepeat
   6718             verticalRule = RepeatImageRule;
   6719             break;
   6720     }
   6721     image.setVerticalRule(verticalRule);
   6722 }
   6723 
   6724 void CSSStyleSelector::checkForTextSizeAdjust()
   6725 {
   6726     if (m_style->textSizeAdjust())
   6727         return;
   6728 
   6729     /* TODO: Remove this when a fix for webkit bug 56543 is submitted and can
   6730      * be cherry picked.
   6731      * This is a quick fix for Android to prevent sites from using
   6732      * -webkit-text-size-adjust: none; which breaks font size accessibility
   6733      * options on all platforms. The purpose of the property is to prevent
   6734      * the automatic font size changes done by platforms like iOS when the
   6735      * rotation changes. Since Android doesn't do this, we can safely ignore
   6736      * the 'none' option.
   6737      */
   6738 #if PLATFORM(ANDROID)
   6739     return;
   6740 #endif
   6741 
   6742     FontDescription newFontDescription(m_style->fontDescription());
   6743     newFontDescription.setComputedSize(newFontDescription.specifiedSize());
   6744     m_style->setFontDescription(newFontDescription);
   6745 }
   6746 
   6747 void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
   6748 {
   6749     if (style->effectiveZoom() == parentStyle->effectiveZoom())
   6750         return;
   6751 
   6752     const FontDescription& childFont = style->fontDescription();
   6753     FontDescription newFontDescription(childFont);
   6754     setFontSize(newFontDescription, childFont.specifiedSize());
   6755     style->setFontDescription(newFontDescription);
   6756 }
   6757 
   6758 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
   6759 {
   6760     const FontDescription& childFont = style->fontDescription();
   6761 
   6762     if (childFont.isAbsoluteSize() || !parentStyle)
   6763         return;
   6764 
   6765     const FontDescription& parentFont = parentStyle->fontDescription();
   6766     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
   6767         return;
   6768 
   6769     // For now, lump all families but monospace together.
   6770     if (childFont.genericFamily() != FontDescription::MonospaceFamily &&
   6771         parentFont.genericFamily() != FontDescription::MonospaceFamily)
   6772         return;
   6773 
   6774     // We know the parent is monospace or the child is monospace, and that font
   6775     // size was unspecified.  We want to scale our font size as appropriate.
   6776     // If the font uses a keyword size, then we refetch from the table rather than
   6777     // multiplying by our scale factor.
   6778     float size;
   6779     if (childFont.keywordSize())
   6780         size = fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize());
   6781     else {
   6782         Settings* settings = m_checker.m_document->settings();
   6783         float fixedScaleFactor = settings
   6784             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
   6785             : 1;
   6786         size = parentFont.useFixedDefaultSize() ?
   6787                 childFont.specifiedSize() / fixedScaleFactor :
   6788                 childFont.specifiedSize() * fixedScaleFactor;
   6789     }
   6790 
   6791     FontDescription newFontDescription(childFont);
   6792     setFontSize(newFontDescription, size);
   6793     style->setFontDescription(newFontDescription);
   6794 }
   6795 
   6796 void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size)
   6797 {
   6798     fontDescription.setSpecifiedSize(size);
   6799 
   6800     bool useSVGZoomRules = m_element && m_element->isSVGElement();
   6801     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
   6802 }
   6803 
   6804 float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules)
   6805 {
   6806     // Text with a 0px font size should not be visible and therefore needs to be
   6807     // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
   6808     // rendering. This is also compatible with other browsers that have minimum
   6809     // font size settings (e.g. Firefox).
   6810     if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon())
   6811         return 0.0f;
   6812 
   6813     float zoomFactor = 1.0f;
   6814     if (!useSVGZoomRules) {
   6815         zoomFactor = style->effectiveZoom();
   6816         if (Frame* frame = document->frame())
   6817             zoomFactor *= frame->textZoomFactor();
   6818     }
   6819 
   6820     // We support two types of minimum font size.  The first is a hard override that applies to
   6821     // all fonts.  This is "minSize."  The second type of minimum font size is a "smart minimum"
   6822     // that is applied only when the Web page can't know what size it really asked for, e.g.,
   6823     // when it uses logical sizes like "small" or expresses the font-size as a percentage of
   6824     // the user's default font setting.
   6825 
   6826     // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
   6827     // However we always allow the page to set an explicit pixel size that is smaller,
   6828     // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
   6829 
   6830     Settings* settings = document->settings();
   6831     if (!settings)
   6832         return 1.0f;
   6833 
   6834     int minSize = settings->minimumFontSize();
   6835     int minLogicalSize = settings->minimumLogicalFontSize();
   6836     float zoomedSize = specifiedSize * zoomFactor;
   6837 
   6838     // Apply the hard minimum first.  We only apply the hard minimum if after zooming we're still too small.
   6839     if (zoomedSize < minSize)
   6840         zoomedSize = minSize;
   6841 
   6842     // Now apply the "smart minimum."  This minimum is also only applied if we're still too small
   6843     // after zooming.  The font size must either be relative to the user default or the original size
   6844     // must have been acceptable.  In other words, we only apply the smart minimum whenever we're positive
   6845     // doing so won't disrupt the layout.
   6846     if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
   6847         zoomedSize = minLogicalSize;
   6848 
   6849     // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
   6850     // platforms (I'm looking at you, Windows.)
   6851     return min(1000000.0f, zoomedSize);
   6852 }
   6853 
   6854 const int fontSizeTableMax = 16;
   6855 const int fontSizeTableMin = 9;
   6856 const int totalKeywords = 8;
   6857 
   6858 // WinIE/Nav4 table for font sizes.  Designed to match the legacy font mapping system of HTML.
   6859 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
   6860 {
   6861       { 9,    9,     9,     9,    11,    14,    18,    28 },
   6862       { 9,    9,     9,    10,    12,    15,    20,    31 },
   6863       { 9,    9,     9,    11,    13,    17,    22,    34 },
   6864       { 9,    9,    10,    12,    14,    18,    24,    37 },
   6865       { 9,    9,    10,    13,    16,    20,    26,    40 }, // fixed font default (13)
   6866       { 9,    9,    11,    14,    17,    21,    28,    42 },
   6867       { 9,   10,    12,    15,    17,    23,    30,    45 },
   6868       { 9,   10,    13,    16,    18,    24,    32,    48 }  // proportional font default (16)
   6869 };
   6870 // HTML       1      2      3      4      5      6      7
   6871 // CSS  xxs   xs     s      m      l     xl     xxl
   6872 //                          |
   6873 //                      user pref
   6874 
   6875 // Strict mode table matches MacIE and Mozilla's settings exactly.
   6876 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
   6877 {
   6878       { 9,    9,     9,     9,    11,    14,    18,    27 },
   6879       { 9,    9,     9,    10,    12,    15,    20,    30 },
   6880       { 9,    9,    10,    11,    13,    17,    22,    33 },
   6881       { 9,    9,    10,    12,    14,    18,    24,    36 },
   6882       { 9,   10,    12,    13,    16,    20,    26,    39 }, // fixed font default (13)
   6883       { 9,   10,    12,    14,    17,    21,    28,    42 },
   6884       { 9,   10,    13,    15,    18,    23,    30,    45 },
   6885       { 9,   10,    13,    16,    18,    24,    32,    48 }  // proportional font default (16)
   6886 };
   6887 // HTML       1      2      3      4      5      6      7
   6888 // CSS  xxs   xs     s      m      l     xl     xxl
   6889 //                          |
   6890 //                      user pref
   6891 
   6892 // For values outside the range of the table, we use Todd Fahrner's suggested scale
   6893 // factors for each keyword value.
   6894 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
   6895 
   6896 float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool shouldUseFixedDefaultSize)
   6897 {
   6898     Settings* settings = document->settings();
   6899     if (!settings)
   6900         return 1.0f;
   6901 
   6902     bool quirksMode = document->inQuirksMode();
   6903     int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
   6904     if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
   6905         // Look up the entry in the table.
   6906         int row = mediumSize - fontSizeTableMin;
   6907         int col = (keyword - CSSValueXxSmall);
   6908         return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
   6909     }
   6910 
   6911     // Value is outside the range of the table. Apply the scale factor instead.
   6912     float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
   6913     return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
   6914 }
   6915 
   6916 template<typename T>
   6917 static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier)
   6918 {
   6919     // Ignore table[0] because xx-small does not correspond to any legacy font size.
   6920     for (int i = 1; i < totalKeywords - 1; i++) {
   6921         if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier)
   6922             return i;
   6923     }
   6924     return totalKeywords - 1;
   6925 }
   6926 
   6927 int CSSStyleSelector::legacyFontSize(Document* document, int pixelFontSize, bool shouldUseFixedDefaultSize)
   6928 {
   6929     Settings* settings = document->settings();
   6930     if (!settings)
   6931         return 1;
   6932 
   6933     bool quirksMode = document->inQuirksMode();
   6934     int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
   6935     if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
   6936         int row = mediumSize - fontSizeTableMin;
   6937         return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1);
   6938     }
   6939 
   6940     return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize);
   6941 }
   6942 
   6943 float CSSStyleSelector::largerFontSize(float size, bool) const
   6944 {
   6945     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
   6946     // the next size level.
   6947     return size * 1.2f;
   6948 }
   6949 
   6950 float CSSStyleSelector::smallerFontSize(float size, bool) const
   6951 {
   6952     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
   6953     // the next size level.
   6954     return size / 1.2f;
   6955 }
   6956 
   6957 static Color colorForCSSValue(int cssValueId)
   6958 {
   6959     struct ColorValue {
   6960         int cssValueId;
   6961         RGBA32 color;
   6962     };
   6963 
   6964     static const ColorValue colorValues[] = {
   6965         { CSSValueAqua, 0xFF00FFFF },
   6966         { CSSValueBlack, 0xFF000000 },
   6967         { CSSValueBlue, 0xFF0000FF },
   6968         { CSSValueFuchsia, 0xFFFF00FF },
   6969         { CSSValueGray, 0xFF808080 },
   6970         { CSSValueGreen, 0xFF008000  },
   6971         { CSSValueGrey, 0xFF808080 },
   6972         { CSSValueLime, 0xFF00FF00 },
   6973         { CSSValueMaroon, 0xFF800000 },
   6974         { CSSValueNavy, 0xFF000080 },
   6975         { CSSValueOlive, 0xFF808000  },
   6976         { CSSValueOrange, 0xFFFFA500 },
   6977         { CSSValuePurple, 0xFF800080 },
   6978         { CSSValueRed, 0xFFFF0000 },
   6979         { CSSValueSilver, 0xFFC0C0C0 },
   6980         { CSSValueTeal, 0xFF008080  },
   6981         { CSSValueTransparent, 0x00000000 },
   6982         { CSSValueWhite, 0xFFFFFFFF },
   6983         { CSSValueYellow, 0xFFFFFF00 },
   6984         { 0, 0 }
   6985     };
   6986 
   6987     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
   6988         if (col->cssValueId == cssValueId)
   6989             return col->color;
   6990     }
   6991     return RenderTheme::defaultTheme()->systemColor(cssValueId);
   6992 }
   6993 
   6994 Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) const
   6995 {
   6996     Color col;
   6997     int ident = primitiveValue->getIdent();
   6998     if (ident) {
   6999         if (ident == CSSValueWebkitText)
   7000             col = m_element->document()->textColor();
   7001         else if (ident == CSSValueWebkitLink)
   7002             col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor();
   7003         else if (ident == CSSValueWebkitActivelink)
   7004             col = m_element->document()->activeLinkColor();
   7005         else if (ident == CSSValueWebkitFocusRingColor)
   7006             col = RenderTheme::focusRingColor();
   7007         else if (ident == CSSValueCurrentcolor)
   7008             col = m_style->color();
   7009         else
   7010             col = colorForCSSValue(ident);
   7011     } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
   7012         col.setRGB(primitiveValue->getRGBA32Value());
   7013     return col;
   7014 }
   7015 
   7016 bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) const
   7017 {
   7018     return m_selectorAttrs.contains(attrname.impl());
   7019 }
   7020 
   7021 void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
   7022 {
   7023     m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
   7024 }
   7025 
   7026 bool CSSStyleSelector::affectedByViewportChange() const
   7027 {
   7028     unsigned s = m_viewportDependentMediaQueryResults.size();
   7029     for (unsigned i = 0; i < s; i++) {
   7030         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
   7031             return true;
   7032     }
   7033     return false;
   7034 }
   7035 
   7036 void CSSStyleSelector::SelectorChecker::allVisitedStateChanged()
   7037 {
   7038     if (m_linksCheckedForVisitedState.isEmpty())
   7039         return;
   7040     for (Node* node = m_document; node; node = node->traverseNextNode()) {
   7041         if (node->isLink())
   7042             node->setNeedsStyleRecalc();
   7043     }
   7044 }
   7045 
   7046 void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash)
   7047 {
   7048     if (!m_linksCheckedForVisitedState.contains(visitedHash))
   7049         return;
   7050     for (Node* node = m_document; node; node = node->traverseNextNode()) {
   7051         const AtomicString* attr = linkAttribute(node);
   7052         if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash)
   7053             node->setNeedsStyleRecalc();
   7054     }
   7055 }
   7056 
   7057 static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type)
   7058 {
   7059     switch (type) {
   7060         case WebKitCSSTransformValue::ScaleTransformOperation:          return TransformOperation::SCALE;
   7061         case WebKitCSSTransformValue::ScaleXTransformOperation:         return TransformOperation::SCALE_X;
   7062         case WebKitCSSTransformValue::ScaleYTransformOperation:         return TransformOperation::SCALE_Y;
   7063         case WebKitCSSTransformValue::ScaleZTransformOperation:         return TransformOperation::SCALE_Z;
   7064         case WebKitCSSTransformValue::Scale3DTransformOperation:        return TransformOperation::SCALE_3D;
   7065         case WebKitCSSTransformValue::TranslateTransformOperation:      return TransformOperation::TRANSLATE;
   7066         case WebKitCSSTransformValue::TranslateXTransformOperation:     return TransformOperation::TRANSLATE_X;
   7067         case WebKitCSSTransformValue::TranslateYTransformOperation:     return TransformOperation::TRANSLATE_Y;
   7068         case WebKitCSSTransformValue::TranslateZTransformOperation:     return TransformOperation::TRANSLATE_Z;
   7069         case WebKitCSSTransformValue::Translate3DTransformOperation:    return TransformOperation::TRANSLATE_3D;
   7070         case WebKitCSSTransformValue::RotateTransformOperation:         return TransformOperation::ROTATE;
   7071         case WebKitCSSTransformValue::RotateXTransformOperation:        return TransformOperation::ROTATE_X;
   7072         case WebKitCSSTransformValue::RotateYTransformOperation:        return TransformOperation::ROTATE_Y;
   7073         case WebKitCSSTransformValue::RotateZTransformOperation:        return TransformOperation::ROTATE_Z;
   7074         case WebKitCSSTransformValue::Rotate3DTransformOperation:       return TransformOperation::ROTATE_3D;
   7075         case WebKitCSSTransformValue::SkewTransformOperation:           return TransformOperation::SKEW;
   7076         case WebKitCSSTransformValue::SkewXTransformOperation:          return TransformOperation::SKEW_X;
   7077         case WebKitCSSTransformValue::SkewYTransformOperation:          return TransformOperation::SKEW_Y;
   7078         case WebKitCSSTransformValue::MatrixTransformOperation:         return TransformOperation::MATRIX;
   7079         case WebKitCSSTransformValue::Matrix3DTransformOperation:       return TransformOperation::MATRIX_3D;
   7080         case WebKitCSSTransformValue::PerspectiveTransformOperation:    return TransformOperation::PERSPECTIVE;
   7081         case WebKitCSSTransformValue::UnknownTransformOperation:        return TransformOperation::NONE;
   7082     }
   7083     return TransformOperation::NONE;
   7084 }
   7085 
   7086 bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations)
   7087 {
   7088     if (!inValue || !inValue->isValueList()) {
   7089         outOperations.clear();
   7090         return false;
   7091     }
   7092 
   7093     float zoomFactor = style ? style->effectiveZoom() : 1;
   7094     TransformOperations operations;
   7095     CSSValueList* list = static_cast<CSSValueList*>(inValue);
   7096     unsigned size = list->length();
   7097     for (unsigned i = 0; i < size; i++) {
   7098         CSSValue* currValue = list->itemWithoutBoundsCheck(i);
   7099         if (!currValue->isWebKitCSSTransformValue())
   7100             continue;
   7101 
   7102         WebKitCSSTransformValue* transformValue = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i));
   7103         if (!transformValue->length())
   7104             continue;
   7105 
   7106         bool haveNonPrimitiveValue = false;
   7107         for (unsigned j = 0; j < transformValue->length(); ++j) {
   7108             if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
   7109                 haveNonPrimitiveValue = true;
   7110                 break;
   7111             }
   7112         }
   7113         if (haveNonPrimitiveValue)
   7114             continue;
   7115 
   7116         CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0));
   7117 
   7118         switch (transformValue->operationType()) {
   7119             case WebKitCSSTransformValue::ScaleTransformOperation:
   7120             case WebKitCSSTransformValue::ScaleXTransformOperation:
   7121             case WebKitCSSTransformValue::ScaleYTransformOperation: {
   7122                 double sx = 1.0;
   7123                 double sy = 1.0;
   7124                 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
   7125                     sy = firstValue->getDoubleValue();
   7126                 else {
   7127                     sx = firstValue->getDoubleValue();
   7128                     if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
   7129                         if (transformValue->length() > 1) {
   7130                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7131                             sy = secondValue->getDoubleValue();
   7132                         } else
   7133                             sy = sx;
   7134                     }
   7135                 }
   7136                 operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType())));
   7137                 break;
   7138             }
   7139             case WebKitCSSTransformValue::ScaleZTransformOperation:
   7140             case WebKitCSSTransformValue::Scale3DTransformOperation: {
   7141                 double sx = 1.0;
   7142                 double sy = 1.0;
   7143                 double sz = 1.0;
   7144                 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation)
   7145                     sz = firstValue->getDoubleValue();
   7146                 else if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
   7147                     sy = firstValue->getDoubleValue();
   7148                 else {
   7149                     sx = firstValue->getDoubleValue();
   7150                     if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
   7151                         if (transformValue->length() > 2) {
   7152                             CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
   7153                             sz = thirdValue->getDoubleValue();
   7154                         }
   7155                         if (transformValue->length() > 1) {
   7156                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7157                             sy = secondValue->getDoubleValue();
   7158                         } else
   7159                             sy = sx;
   7160                     }
   7161                 }
   7162                 operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType())));
   7163                 break;
   7164             }
   7165             case WebKitCSSTransformValue::TranslateTransformOperation:
   7166             case WebKitCSSTransformValue::TranslateXTransformOperation:
   7167             case WebKitCSSTransformValue::TranslateYTransformOperation: {
   7168                 bool ok = true;
   7169                 Length tx = Length(0, Fixed);
   7170                 Length ty = Length(0, Fixed);
   7171                 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
   7172                     ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7173                 else {
   7174                     tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7175                     if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
   7176                         if (transformValue->length() > 1) {
   7177                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7178                             ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
   7179                         }
   7180                     }
   7181                 }
   7182 
   7183                 if (!ok)
   7184                     return false;
   7185 
   7186                 operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType())));
   7187                 break;
   7188             }
   7189             case WebKitCSSTransformValue::TranslateZTransformOperation:
   7190             case WebKitCSSTransformValue::Translate3DTransformOperation: {
   7191                 bool ok = true;
   7192                 Length tx = Length(0, Fixed);
   7193                 Length ty = Length(0, Fixed);
   7194                 Length tz = Length(0, Fixed);
   7195                 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation)
   7196                     tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7197                 else if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
   7198                     ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7199                 else {
   7200                     tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7201                     if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
   7202                         if (transformValue->length() > 2) {
   7203                             CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
   7204                             tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor, &ok);
   7205                         }
   7206                         if (transformValue->length() > 1) {
   7207                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7208                             ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
   7209                         }
   7210                     }
   7211                 }
   7212 
   7213                 if (!ok)
   7214                     return false;
   7215 
   7216                 operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType())));
   7217                 break;
   7218             }
   7219             case WebKitCSSTransformValue::RotateTransformOperation: {
   7220                 double angle = firstValue->getDoubleValue();
   7221                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
   7222                     angle = rad2deg(angle);
   7223                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
   7224                     angle = grad2deg(angle);
   7225                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
   7226                     angle = turn2deg(angle);
   7227 
   7228                 operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType())));
   7229                 break;
   7230             }
   7231             case WebKitCSSTransformValue::RotateXTransformOperation:
   7232             case WebKitCSSTransformValue::RotateYTransformOperation:
   7233             case WebKitCSSTransformValue::RotateZTransformOperation: {
   7234                 double x = 0;
   7235                 double y = 0;
   7236                 double z = 0;
   7237                 double angle = firstValue->getDoubleValue();
   7238                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
   7239                     angle = rad2deg(angle);
   7240                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
   7241                     angle = grad2deg(angle);
   7242 
   7243                 if (transformValue->operationType() == WebKitCSSTransformValue::RotateXTransformOperation)
   7244                     x = 1;
   7245                 else if (transformValue->operationType() == WebKitCSSTransformValue::RotateYTransformOperation)
   7246                     y = 1;
   7247                 else
   7248                     z = 1;
   7249                 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
   7250                 break;
   7251             }
   7252             case WebKitCSSTransformValue::Rotate3DTransformOperation: {
   7253                 if (transformValue->length() < 4)
   7254                     break;
   7255                 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7256                 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
   7257                 CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3));
   7258                 double x = firstValue->getDoubleValue();
   7259                 double y = secondValue->getDoubleValue();
   7260                 double z = thirdValue->getDoubleValue();
   7261                 double angle = fourthValue->getDoubleValue();
   7262                 if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
   7263                     angle = rad2deg(angle);
   7264                 else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
   7265                     angle = grad2deg(angle);
   7266                 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
   7267                 break;
   7268             }
   7269             case WebKitCSSTransformValue::SkewTransformOperation:
   7270             case WebKitCSSTransformValue::SkewXTransformOperation:
   7271             case WebKitCSSTransformValue::SkewYTransformOperation: {
   7272                 double angleX = 0;
   7273                 double angleY = 0;
   7274                 double angle = firstValue->getDoubleValue();
   7275                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
   7276                     angle = rad2deg(angle);
   7277                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
   7278                     angle = grad2deg(angle);
   7279                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
   7280                     angle = turn2deg(angle);
   7281                 if (transformValue->operationType() == WebKitCSSTransformValue::SkewYTransformOperation)
   7282                     angleY = angle;
   7283                 else {
   7284                     angleX = angle;
   7285                     if (transformValue->operationType() == WebKitCSSTransformValue::SkewTransformOperation) {
   7286                         if (transformValue->length() > 1) {
   7287                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
   7288                             angleY = secondValue->getDoubleValue();
   7289                             if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
   7290                                 angleY = rad2deg(angleY);
   7291                             else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
   7292                                 angleY = grad2deg(angleY);
   7293                             else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
   7294                                 angleY = turn2deg(angleY);
   7295                         }
   7296                     }
   7297                 }
   7298                 operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType())));
   7299                 break;
   7300             }
   7301             case WebKitCSSTransformValue::MatrixTransformOperation: {
   7302                 if (transformValue->length() < 6)
   7303                     break;
   7304                 double a = firstValue->getDoubleValue();
   7305                 double b = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue();
   7306                 double c = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue();
   7307                 double d = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue();
   7308                 double e = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue();
   7309                 double f = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue();
   7310                 operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f));
   7311                 break;
   7312             }
   7313             case WebKitCSSTransformValue::Matrix3DTransformOperation: {
   7314                 if (transformValue->length() < 16)
   7315                     break;
   7316                 TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(),
   7317                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(),
   7318                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(),
   7319                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(),
   7320                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(),
   7321                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(),
   7322                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(),
   7323                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(),
   7324                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(),
   7325                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(),
   7326                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(),
   7327                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(),
   7328                                    zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(),
   7329                                    zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(),
   7330                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(),
   7331                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue());
   7332                 operations.operations().append(Matrix3DTransformOperation::create(matrix));
   7333                 break;
   7334             }
   7335             case WebKitCSSTransformValue::PerspectiveTransformOperation: {
   7336                 bool ok = true;
   7337                 Length p = Length(0, Fixed);
   7338                 if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType()))
   7339                     p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
   7340                 else {
   7341                     // This is a quirk that should go away when 3d transforms are finalized.
   7342                     double val = firstValue->getDoubleValue();
   7343                     ok = val >= 0;
   7344                     val = clampToPositiveInteger(val);
   7345                     p = Length(static_cast<int>(val), Fixed);
   7346                 }
   7347 
   7348                 if (!ok)
   7349                     return false;
   7350 
   7351                 operations.operations().append(PerspectiveTransformOperation::create(p));
   7352                 break;
   7353             }
   7354             case WebKitCSSTransformValue::UnknownTransformOperation:
   7355                 ASSERT_NOT_REACHED();
   7356                 break;
   7357         }
   7358     }
   7359 
   7360     outOperations = operations;
   7361     return true;
   7362 }
   7363 
   7364 void CSSStyleSelector::loadPendingImages()
   7365 {
   7366     if (m_pendingImageProperties.isEmpty())
   7367         return;
   7368 
   7369     HashSet<int>::const_iterator end = m_pendingImageProperties.end();
   7370     for (HashSet<int>::const_iterator it = m_pendingImageProperties.begin(); it != end; ++it) {
   7371         CSSPropertyID currentProperty = static_cast<CSSPropertyID>(*it);
   7372 
   7373         CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
   7374 
   7375         switch (currentProperty) {
   7376             case CSSPropertyBackgroundImage: {
   7377                 for (FillLayer* backgroundLayer = m_style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
   7378                     if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage()) {
   7379                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(backgroundLayer->image())->cssImageValue();
   7380                         backgroundLayer->setImage(imageValue->cachedImage(cachedResourceLoader));
   7381                     }
   7382                 }
   7383                 break;
   7384             }
   7385 
   7386             case CSSPropertyContent: {
   7387                 for (ContentData* contentData = const_cast<ContentData*>(m_style->contentData()); contentData; contentData = contentData->next()) {
   7388                     if (contentData->isImage() && contentData->image()->isPendingImage()) {
   7389                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(contentData->image())->cssImageValue();
   7390                         if (StyleCachedImage* cachedImage = imageValue->cachedImage(cachedResourceLoader))
   7391                             contentData->setImage(cachedImage);
   7392                     }
   7393                 }
   7394                 break;
   7395             }
   7396 
   7397             case CSSPropertyCursor: {
   7398                 if (CursorList* cursorList = m_style->cursors()) {
   7399                     for (size_t i = 0; i < cursorList->size(); ++i) {
   7400                         CursorData& currentCursor = cursorList->at(i);
   7401                         if (StyleImage* image = currentCursor.image()) {
   7402                             if (image->isPendingImage()) {
   7403                                 CSSImageValue* imageValue = static_cast<StylePendingImage*>(image)->cssImageValue();
   7404                                 currentCursor.setImage(imageValue->cachedImage(cachedResourceLoader));
   7405                             }
   7406                         }
   7407                     }
   7408                 }
   7409                 break;
   7410             }
   7411 
   7412             case CSSPropertyListStyleImage: {
   7413                 if (m_style->listStyleImage() && m_style->listStyleImage()->isPendingImage()) {
   7414                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(m_style->listStyleImage())->cssImageValue();
   7415                     m_style->setListStyleImage(imageValue->cachedImage(cachedResourceLoader));
   7416                 }
   7417                 break;
   7418             }
   7419 
   7420             case CSSPropertyWebkitBorderImage: {
   7421                 const NinePieceImage& borderImage = m_style->borderImage();
   7422                 if (borderImage.image() && borderImage.image()->isPendingImage()) {
   7423                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(borderImage.image())->cssImageValue();
   7424                     m_style->setBorderImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), borderImage.slices(), borderImage.horizontalRule(), borderImage.verticalRule()));
   7425                 }
   7426                 break;
   7427             }
   7428 
   7429             case CSSPropertyWebkitBoxReflect: {
   7430                 if (StyleReflection* reflection = m_style->boxReflect()) {
   7431                     const NinePieceImage& maskImage = reflection->mask();
   7432                     if (maskImage.image() && maskImage.image()->isPendingImage()) {
   7433                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskImage.image())->cssImageValue();
   7434                         reflection->setMask(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskImage.slices(), maskImage.horizontalRule(), maskImage.verticalRule()));
   7435                     }
   7436                 }
   7437                 break;
   7438             }
   7439 
   7440             case CSSPropertyWebkitMaskBoxImage: {
   7441                 const NinePieceImage& maskBoxImage = m_style->maskBoxImage();
   7442                 if (maskBoxImage.image() && maskBoxImage.image()->isPendingImage()) {
   7443                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskBoxImage.image())->cssImageValue();
   7444                     m_style->setMaskBoxImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskBoxImage.slices(), maskBoxImage.horizontalRule(), maskBoxImage.verticalRule()));
   7445                 }
   7446                 break;
   7447             }
   7448 
   7449             case CSSPropertyWebkitMaskImage: {
   7450                 for (FillLayer* maskLayer = m_style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
   7451                     if (maskLayer->image() && maskLayer->image()->isPendingImage()) {
   7452                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskLayer->image())->cssImageValue();
   7453                         maskLayer->setImage(imageValue->cachedImage(cachedResourceLoader));
   7454                     }
   7455                 }
   7456                 break;
   7457             }
   7458             default:
   7459                 ASSERT_NOT_REACHED();
   7460         }
   7461     }
   7462 
   7463     m_pendingImageProperties.clear();
   7464 }
   7465 
   7466 } // namespace WebCore
   7467