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