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