Implement form validation message UI
[WebKit-https.git] / Source / WebCore / css / CSSStyleSelector.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 "Attribute.h"
30 #include "CSSBorderImageValue.h"
31 #include "CSSCursorImageValue.h"
32 #include "CSSFontFaceRule.h"
33 #include "CSSImportRule.h"
34 #include "CSSMediaRule.h"
35 #include "CSSPageRule.h"
36 #include "CSSParser.h"
37 #include "CSSPrimitiveValueMappings.h"
38 #include "CSSPropertyNames.h"
39 #include "CSSReflectValue.h"
40 #include "CSSRuleList.h"
41 #include "CSSSelector.h"
42 #include "CSSSelectorList.h"
43 #include "CSSStyleRule.h"
44 #include "CSSStyleSheet.h"
45 #include "CSSTimingFunctionValue.h"
46 #include "CSSValueList.h"
47 #include "CachedImage.h"
48 #include "Counter.h"
49 #include "FocusController.h"
50 #include "FontFamilyValue.h"
51 #include "FontValue.h"
52 #include "Frame.h"
53 #include "FrameView.h"
54 #include "HTMLDocument.h"
55 #include "HTMLElement.h"
56 #include "HTMLInputElement.h"
57 #include "HTMLNames.h"
58 #include "HTMLTextAreaElement.h"
59 #include "KeyframeList.h"
60 #include "LinkHash.h"
61 #include "Matrix3DTransformOperation.h"
62 #include "MatrixTransformOperation.h"
63 #include "MediaList.h"
64 #include "MediaQueryEvaluator.h"
65 #include "NodeRenderStyle.h"
66 #include "Page.h"
67 #include "PageGroup.h"
68 #include "Pair.h"
69 #include "PerspectiveTransformOperation.h"
70 #include "Rect.h"
71 #include "RenderScrollbar.h"
72 #include "RenderScrollbarTheme.h"
73 #include "RenderStyleConstants.h"
74 #include "RenderTheme.h"
75 #include "RotateTransformOperation.h"
76 #include "ScaleTransformOperation.h"
77 #include "SelectionController.h"
78 #include "Settings.h"
79 #include "ShadowValue.h"
80 #include "SkewTransformOperation.h"
81 #include "StyleCachedImage.h"
82 #include "StylePendingImage.h"
83 #include "StyleGeneratedImage.h"
84 #include "StyleSheetList.h"
85 #include "Text.h"
86 #include "TransformationMatrix.h"
87 #include "TranslateTransformOperation.h"
88 #include "UserAgentStyleSheets.h"
89 #include "WebKitCSSKeyframeRule.h"
90 #include "WebKitCSSKeyframesRule.h"
91 #include "WebKitCSSTransformValue.h"
92 #include "XMLNames.h"
93 #include <wtf/StdLibExtras.h>
94 #include <wtf/Vector.h>
95
96 #if USE(PLATFORM_STRATEGIES)
97 #include "PlatformStrategies.h"
98 #include "VisitedLinkStrategy.h"
99 #endif
100
101 #if ENABLE(DASHBOARD_SUPPORT)
102 #include "DashboardRegion.h"
103 #endif
104
105 #if ENABLE(SVG)
106 #include "XLinkNames.h"
107 #include "SVGNames.h"
108 #endif
109
110 #if ENABLE(WML)
111 #include "WMLNames.h"
112 #endif
113
114 #if PLATFORM(QT)
115 #include <qwebhistoryinterface.h>
116 #endif
117
118 using namespace std;
119
120 namespace WebCore {
121
122 using namespace HTMLNames;
123
124 #define HANDLE_INHERIT(prop, Prop) \
125 if (isInherit) { \
126     m_style->set##Prop(m_parentStyle->prop()); \
127     return; \
128 }
129
130 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
131 HANDLE_INHERIT(prop, Prop) \
132 if (isInitial) { \
133     m_style->set##Prop(RenderStyle::initial##Prop()); \
134     return; \
135 }
136
137 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
138 HANDLE_INHERIT(prop, Prop) \
139 if (isInitial) { \
140     m_style->set##Prop(RenderStyle::initial##Value());\
141     return;\
142 }
143
144 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
145 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
146 if (primitiveValue) \
147     m_style->set##Prop(*primitiveValue);
148
149 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
150 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
151 if (primitiveValue) \
152     m_style->set##Prop(*primitiveValue);
153
154 #define HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
155 if (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) { \
184 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
185 if (isInherit || isInitial) \
186     return; \
187 FillLayer* currChild = m_style->access##LayerType##Layers(); \
188 FillLayer* prevChild = 0; \
189 if (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(property, currChild, valueList->itemWithoutBoundsCheck(i)); \
199         prevChild = currChild; \
200         currChild = currChild->next(); \
201     } \
202 } else { \
203     mapFill##Prop(property, currChild, value); \
204     currChild = currChild->next(); \
205 } \
206 while (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) \
213 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(background, Background, prop, Prop)
214
215 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \
216 HANDLE_FILL_LAYER_VALUE(background, Background, prop, Prop, value)
217
218 #define HANDLE_MASK_INHERIT_AND_INITIAL(prop, Prop) \
219 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(mask, Mask, prop, Prop)
220
221 #define HANDLE_MASK_VALUE(prop, Prop, value) \
222 HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value)
223
224 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
225 if (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) { \
248 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
249 if (isInherit || isInitial) \
250     return; \
251 AnimationList* list = m_style->accessAnimations(); \
252 size_t childIndex = 0; \
253 if (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 } \
268 for ( ; 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) \
275 if (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) { \
298 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
299 if (isInherit || isInitial) \
300     return; \
301 AnimationList* list = m_style->accessTransitions(); \
302 size_t childIndex = 0; \
303 if (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 } \
318 for ( ; 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) \
325 if (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) \
331 if (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) \
340 if (id == propID) { \
341     m_style->set##Prop(RenderStyle::initial##Prop()); \
342     return; \
343 }
344
345 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
346 if (id == propID) { \
347     m_style->set##Prop(RenderStyle::initial##Value()); \
348     return; \
349 }
350
351 class CSSRuleData : public Noncopyable {
352 public:
353     CSSRuleData(unsigned pos, CSSStyleRule* r, CSSSelector* sel, CSSRuleData* prev = 0)
354         : m_position(pos)
355         , m_rule(r)
356         , m_selector(sel)
357         , m_next(0)
358     {
359         if (prev)
360             prev->m_next = this;
361     }
362
363     ~CSSRuleData()
364     {
365     }
366
367     unsigned position() { return m_position; }
368     CSSStyleRule* rule() { return m_rule; }
369     CSSSelector* selector() { return m_selector; }
370     CSSRuleData* next() { return m_next; }
371
372 private:
373     unsigned m_position;
374     CSSStyleRule* m_rule;
375     CSSSelector* m_selector;
376     CSSRuleData* m_next;
377 };
378
379 class CSSRuleDataList : public Noncopyable {
380 public:
381     CSSRuleDataList(unsigned pos, CSSStyleRule* rule, CSSSelector* sel)
382         : m_first(new CSSRuleData(pos, rule, sel))
383         , m_last(m_first)
384     {
385     }
386
387     ~CSSRuleDataList()
388     {
389         CSSRuleData* ptr;
390         CSSRuleData* next;
391         ptr = m_first;
392         while (ptr) {
393             next = ptr->next();
394             delete ptr;
395             ptr = next;
396         }
397     }
398
399     CSSRuleData* first() { return m_first; }
400     CSSRuleData* last() { return m_last; }
401
402     void append(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) { m_last = new CSSRuleData(pos, rule, sel, m_last); }
403
404 private:
405     CSSRuleData* m_first;
406     CSSRuleData* m_last;
407 };
408
409 class CSSRuleSet : public Noncopyable {
410 public:
411     CSSRuleSet();
412     ~CSSRuleSet();
413     
414     typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
415     
416     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
417
418     void addStyleRule(CSSStyleRule* item);
419     void addRule(CSSStyleRule* rule, CSSSelector* sel);
420     void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
421     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
422                       CSSStyleRule* rule, CSSSelector* sel);
423     
424     CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
425     CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
426     CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
427     CSSRuleDataList* getPseudoRules(AtomicStringImpl* key) { return m_pseudoRules.get(key); }
428     CSSRuleDataList* getUniversalRules() { return m_universalRules.get(); }
429     CSSRuleDataList* getPageRules() { return m_pageRules.get(); }
430     
431 public:
432     AtomRuleMap m_idRules;
433     AtomRuleMap m_classRules;
434     AtomRuleMap m_tagRules;
435     AtomRuleMap m_pseudoRules;
436     OwnPtr<CSSRuleDataList> m_universalRules;
437     OwnPtr<CSSRuleDataList> m_pageRules;
438     unsigned m_ruleCount;
439     unsigned m_pageRuleCount;
440 };
441
442 static CSSRuleSet* defaultStyle;
443 static CSSRuleSet* defaultQuirksStyle;
444 static CSSRuleSet* defaultPrintStyle;
445 static CSSRuleSet* defaultViewSourceStyle;
446 static CSSStyleSheet* simpleDefaultStyleSheet;
447
448 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
449
450 static void loadFullDefaultStyle();
451 #if ENABLE(FULLSCREEN_API)
452 static void loadFullScreenRulesIfNeeded(Document*);
453 #endif
454 static void loadSimpleDefaultStyle();
455 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
456 static 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}";
457
458 static bool elementCanUseSimpleDefaultStyle(Element* e)
459 {
460     return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
461 }
462
463 static const MediaQueryEvaluator& screenEval()
464 {
465     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
466     return staticScreenEval;
467 }
468
469 static const MediaQueryEvaluator& printEval()
470 {
471     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
472     return staticPrintEval;
473 }
474
475 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
476                                    CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
477                                    bool strictParsing, bool matchAuthorAndUserStyles)
478     : m_backgroundData(BackgroundFillLayer)
479     , m_checker(document, strictParsing)
480     , m_element(0)
481     , m_styledElement(0)
482     , m_elementLinkState(NotInsideLink)
483     , m_fontSelector(CSSFontSelector::create(document))
484 {
485     m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
486     
487     Element* root = document->documentElement();
488
489     if (!defaultStyle) {
490         if (!root || elementCanUseSimpleDefaultStyle(root))
491             loadSimpleDefaultStyle();
492         else {
493             loadFullDefaultStyle();
494 #if ENABLE(FULLSCREEN_API)
495             loadFullScreenRulesIfNeeded(document);
496 #endif
497         }
498     }
499
500     // construct document root element default style. this is needed
501     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
502     // This is here instead of constructor, because when constructor is run,
503     // document doesn't have documentElement
504     // NOTE: this assumes that element that gets passed to styleForElement -call
505     // is always from the document that owns the style selector
506     FrameView* view = document->view();
507     if (view)
508         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
509     else
510         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
511
512     if (root)
513         m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
514
515     if (m_rootDefaultStyle && view)
516         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
517
518     m_authorStyle = adoptPtr(new CSSRuleSet);
519
520     // FIXME: This sucks! The user sheet is reparsed every time!
521     OwnPtr<CSSRuleSet> tempUserStyle = adoptPtr(new CSSRuleSet);
522     if (pageUserSheet)
523         tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
524     if (pageGroupUserSheets) {
525         unsigned length = pageGroupUserSheets->size();
526         for (unsigned i = 0; i < length; i++) {
527             if (pageGroupUserSheets->at(i)->isUserStyleSheet())
528                 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
529             else
530                 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
531         }
532     }
533
534     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRuleCount > 0)
535         m_userStyle = tempUserStyle.release();
536
537     // Add rules from elements like SVG's <font-face>
538     if (mappedElementSheet)
539         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
540
541     // add stylesheets from document
542     unsigned length = styleSheets->length();
543     for (unsigned i = 0; i < length; i++) {
544         StyleSheet* sheet = styleSheets->item(i);
545         if (sheet->isCSSStyleSheet() && !sheet->disabled())
546             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
547     }
548
549     if (document->renderer() && document->renderer()->style())
550         document->renderer()->style()->font().update(fontSelector());
551 }
552
553 // This is a simplified style setting function for keyframe styles
554 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
555 {
556     AtomicString s(rule->name());
557     m_keyframesRuleMap.add(s.impl(), rule);
558 }
559
560 CSSStyleSelector::~CSSStyleSelector()
561 {
562     m_fontSelector->clearDocument();
563     deleteAllValues(m_viewportDependentMediaQueryResults);
564 }
565
566 static CSSStyleSheet* parseUASheet(const String& str)
567 {
568     CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
569     sheet->parseString(str);
570     return sheet;
571 }
572
573 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
574 {
575     return parseUASheet(String(characters, size));
576 }
577
578 static void loadFullDefaultStyle()
579 {
580     if (simpleDefaultStyleSheet) {
581         ASSERT(defaultStyle);
582         delete defaultStyle;
583         simpleDefaultStyleSheet->deref();
584         defaultStyle = new CSSRuleSet;
585         simpleDefaultStyleSheet = 0;
586     } else {
587         ASSERT(!defaultStyle);
588         defaultStyle = new CSSRuleSet;
589         defaultPrintStyle = new CSSRuleSet;
590         defaultQuirksStyle = new CSSRuleSet;
591     }
592
593     // Strict-mode rules.
594     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
595     CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
596     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
597     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
598
599     // Quirks-mode rules.
600     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
601     CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
602     defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
603 }
604
605 #if ENABLE(FULLSCREEN_API)
606 static void loadFullScreenRulesIfNeeded(Document* document)
607 {
608     if (!document->webkitIsFullScreen())
609         return;
610     // Full-screen rules.
611     String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
612     CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
613     defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
614     defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
615 }
616 #endif
617
618 static void loadSimpleDefaultStyle()
619 {
620     ASSERT(!defaultStyle);
621     ASSERT(!simpleDefaultStyleSheet);
622     
623     defaultStyle = new CSSRuleSet;
624     defaultPrintStyle = new CSSRuleSet;
625     defaultQuirksStyle = new CSSRuleSet;
626
627     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
628     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
629     
630     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
631 }
632     
633 static void loadViewSourceStyle()
634 {
635     ASSERT(!defaultViewSourceStyle);
636     defaultViewSourceStyle = new CSSRuleSet;
637     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
638 }
639
640 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
641 {
642     m_matchedDecls.append(decl);
643 }
644
645 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
646 {
647     m_matchedRules.clear();
648
649     if (!rules || !m_element)
650         return;
651     
652     // We need to collect the rules for id, class, tag, and everything else into a buffer and
653     // then sort the buffer.
654     if (m_element->hasID())
655         matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
656     if (m_element->hasClass()) {
657         ASSERT(m_styledElement);
658         const SpaceSplitString& classNames = m_styledElement->classNames();
659         size_t size = classNames.size();
660         for (size_t i = 0; i < size; ++i)
661             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
662     }
663     if (!m_element->shadowPseudoId().isEmpty()) {
664         ASSERT(m_styledElement);
665         matchRulesForList(rules->getPseudoRules(m_element->shadowPseudoId().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
666     }
667     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
668     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
669     
670     // If we didn't match any rules, we're done.
671     if (m_matchedRules.isEmpty())
672         return;
673     
674     // Sort the set of matched rules.
675     sortMatchedRules(0, m_matchedRules.size());
676     
677     // Now transfer the set of matched rules over to our list of decls.
678     if (!m_checker.m_collectRulesOnly) {
679         for (unsigned i = 0; i < m_matchedRules.size(); i++)
680             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
681     } else {
682         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
683             if (!m_ruleList)
684                 m_ruleList = CSSRuleList::create();
685             m_ruleList->append(m_matchedRules[i]->rule());
686         }
687     }
688 }
689
690 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
691 {
692     if (!rules)
693         return;
694
695     for (CSSRuleData* d = rules->first(); d; d = d->next()) {
696         CSSStyleRule* rule = d->rule();
697         if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
698             continue; 
699         if (checkSelector(d->selector())) {
700             // If the rule has no properties to apply, then ignore it in the non-debug mode.
701             CSSMutableStyleDeclaration* decl = rule->declaration();
702             if (!decl || (!decl->length() && !includeEmptyRules))
703                 continue;
704             
705             // If we're matching normal rules, set a pseudo bit if 
706             // we really just matched a pseudo-element.
707             if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) {
708                 if (m_checker.m_collectRulesOnly)
709                     continue;
710                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
711                     m_style->setHasPseudoStyle(m_dynamicPseudo);
712             } else {
713                 // Update our first/last rule indices in the matched rules array.
714                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
715                 if (firstRuleIndex == -1)
716                     firstRuleIndex = lastRuleIndex;
717
718                 // Add this rule to our list of matched rules.
719                 addMatchedRule(d);
720             }
721         }
722     }
723 }
724
725 static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
726 {
727     int spec1 = r1.selector()->specificity();
728     int spec2 = r2.selector()->specificity();
729     return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; 
730 }
731     
732 static bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
733 {
734     return !(r1 > r2);
735 }
736
737 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
738 {
739     if (start >= end || (end - start == 1))
740         return; // Sanity check.
741
742     if (end - start <= 6) {
743         // Apply a bubble sort for smaller lists.
744         for (unsigned i = end - 1; i > start; i--) {
745             bool sorted = true;
746             for (unsigned j = start; j < i; j++) {
747                 CSSRuleData* elt = m_matchedRules[j];
748                 CSSRuleData* elt2 = m_matchedRules[j + 1];
749                 if (*elt > *elt2) {
750                     sorted = false;
751                     m_matchedRules[j] = elt2;
752                     m_matchedRules[j + 1] = elt;
753                 }
754             }
755             if (sorted)
756                 return;
757         }
758         return;
759     }
760
761     // Perform a merge sort for larger lists.
762     unsigned mid = (start + end) / 2;
763     sortMatchedRules(start, mid);
764     sortMatchedRules(mid, end);
765     
766     CSSRuleData* elt = m_matchedRules[mid - 1];
767     CSSRuleData* elt2 = m_matchedRules[mid];
768     
769     // Handle the fast common case (of equal specificity).  The list may already
770     // be completely sorted.
771     if (*elt <= *elt2)
772         return;
773     
774     // We have to merge sort.  Ensure our merge buffer is big enough to hold
775     // all the items.
776     Vector<CSSRuleData*> rulesMergeBuffer;
777     rulesMergeBuffer.reserveInitialCapacity(end - start); 
778
779     unsigned i1 = start;
780     unsigned i2 = mid;
781     
782     elt = m_matchedRules[i1];
783     elt2 = m_matchedRules[i2];
784     
785     while (i1 < mid || i2 < end) {
786         if (i1 < mid && (i2 == end || *elt <= *elt2)) {
787             rulesMergeBuffer.append(elt);
788             if (++i1 < mid)
789                 elt = m_matchedRules[i1];
790         } else {
791             rulesMergeBuffer.append(elt2);
792             if (++i2 < end)
793                 elt2 = m_matchedRules[i2];
794         }
795     }
796     
797     for (unsigned i = start; i < end; i++)
798         m_matchedRules[i] = rulesMergeBuffer[i - start];
799 }
800
801 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const
802 {
803     if (!element || !element->isLink())
804         return NotInsideLink;
805     return determineLinkStateSlowCase(element);
806 }
807     
808 inline void CSSStyleSelector::initElement(Element* e)
809 {
810     if (m_element != e) {
811         m_element = e;
812         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
813         m_elementLinkState = m_checker.determineLinkState(m_element);
814         if (e && e == e->document()->documentElement()) {
815             e->document()->setDirectionSetOnDocumentElement(false);
816             e->document()->setWritingModeSetOnDocumentElement(false);
817         }
818     }
819 }
820
821 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
822 {
823     m_checker.m_pseudoStyle = pseudoID;
824
825     m_parentNode = e ? e->parentOrHostNode() : 0;
826
827     if (parentStyle)
828         m_parentStyle = parentStyle;
829     else
830         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
831
832     Node* docElement = e ? e->document()->documentElement() : 0;
833     RenderStyle* docStyle = m_checker.m_document->renderStyle();
834     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
835
836     m_style = 0;
837
838     m_matchedDecls.clear();
839
840     m_pendingImageProperties.clear();
841
842     m_ruleList = 0;
843
844     m_fontDirty = false;
845 }
846
847 static inline const AtomicString* linkAttribute(Node* node)
848 {
849     if (!node->isLink())
850         return 0;
851
852     ASSERT(node->isElementNode());
853     Element* element = static_cast<Element*>(node);
854     if (element->isHTMLElement())
855         return &element->fastGetAttribute(hrefAttr);
856
857 #if ENABLE(WML)
858     if (element->isWMLElement()) {
859         // <anchor> elements don't have href attributes, but we still want to
860         // appear as link, so linkAttribute() has to return a non-null value!
861         if (element->hasTagName(WMLNames::anchorTag))
862             return &emptyAtom;
863
864         return &element->fastGetAttribute(hrefAttr);
865     }
866 #endif
867
868 #if ENABLE(SVG)
869     if (element->isSVGElement())
870         return &element->fastGetAttribute(XLinkNames::hrefAttr);
871 #endif
872
873     return 0;
874 }
875
876 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
877     : m_document(document)
878     , m_strictParsing(strictParsing)
879     , m_collectRulesOnly(false)
880     , m_sameOriginOnly(false)
881     , m_pseudoStyle(NOPSEUDO)
882     , m_documentIsHTML(document->isHTMLDocument())
883     , m_matchVisitedPseudoClass(false)
884 {
885 }
886
887 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const
888 {
889     ASSERT(element->isLink());
890     
891     const AtomicString* attr = linkAttribute(element);
892     if (!attr || attr->isNull())
893         return NotInsideLink;
894
895 #if PLATFORM(QT)
896     Vector<UChar, 512> url;
897     visitedURL(m_document->baseURL(), *attr, url);
898     if (url.isEmpty())
899         return InsideUnvisitedLink;
900
901     // If the Qt4.4 interface for the history is used, we will have to fallback
902     // to the old global history.
903     QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface();
904     if (iface)
905         return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink;
906
907     LinkHash hash = visitedLinkHash(url.data(), url.size());
908     if (!hash)
909         return InsideUnvisitedLink;
910 #else
911     LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr);
912     if (!hash)
913         return InsideUnvisitedLink;
914 #endif
915
916     Frame* frame = m_document->frame();
917     if (!frame)
918         return InsideUnvisitedLink;
919
920     Page* page = frame->page();
921     if (!page)
922         return InsideUnvisitedLink;
923
924     m_linksCheckedForVisitedState.add(hash);
925
926 #if USE(PLATFORM_STRATEGIES)
927     return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink;
928 #else
929     return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
930 #endif
931 }
932
933 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
934 {
935     PseudoId dynamicPseudo = NOPSEUDO;
936     return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches;
937 }
938
939 static const unsigned cStyleSearchThreshold = 10;
940
941 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) const
942 {
943     if (parent && parent->isStyledElement()) {
944         StyledElement* p = static_cast<StyledElement*>(parent);
945         if (!p->inlineStyleDecl() && !p->hasID()) {
946             Node* r = p->previousSibling();
947             unsigned subcount = 0;
948             RenderStyle* st = p->renderStyle();
949             while (r) {
950                 if (r->renderStyle() == st)
951                     return r->lastChild();
952                 if (subcount++ == cStyleSearchThreshold)
953                     return 0;
954                 r = r->previousSibling();
955             }
956             if (!r && depth < cStyleSearchThreshold)
957                 r = locateCousinList(parent->parentElement(), depth + 1);
958             while (r) {
959                 if (r->renderStyle() == st)
960                     return r->lastChild();
961                 if (subcount++ == cStyleSearchThreshold)
962                     return 0;
963                 r = r->previousSibling();
964             }
965         }
966     }
967     return 0;
968 }
969
970 bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
971 {
972     if (n->isStyledElement()) {
973         StyledElement* s = static_cast<StyledElement*>(n);
974         RenderStyle* style = s->renderStyle();
975         if (style && !style->unique() &&
976             (s->tagQName() == m_element->tagQName()) && !s->hasID() &&
977             (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
978             (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
979             (s->isLink() == m_element->isLink()) && 
980             !style->affectedByAttributeSelectors() &&
981             (s->hovered() == m_element->hovered()) &&
982             (s->active() == m_element->active()) &&
983             (s->focused() == m_element->focused()) &&
984             (s->shadowPseudoId() == m_element->shadowPseudoId()) &&
985             (s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) &&
986             (s->fastGetAttribute(typeAttr) == m_element->fastGetAttribute(typeAttr)) &&
987             (s->fastGetAttribute(XMLNames::langAttr) == m_element->fastGetAttribute(XMLNames::langAttr)) &&
988             (s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) &&
989             (s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) &&
990             (s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) {
991             bool isControl = s->isFormControlElement();
992             if (isControl != m_element->isFormControlElement())
993                 return false;
994             if (isControl) {
995                 InputElement* thisInputElement = toInputElement(s);
996                 InputElement* otherInputElement = toInputElement(m_element);
997                 if (thisInputElement && otherInputElement) {
998                     if ((thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) ||
999                         (thisInputElement->isChecked() != otherInputElement->isChecked()) ||
1000                         (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate()))
1001                     return false;
1002                 } else
1003                     return false;
1004
1005                 if (s->isEnabledFormControl() != m_element->isEnabledFormControl())
1006                     return false;
1007
1008                 if (s->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1009                     return false;
1010                 
1011                 if (!m_element->document()->containsValidityStyleRules())
1012                     return false;
1013                 
1014                 bool willValidate = s->willValidate();
1015                 if (willValidate != m_element->willValidate())
1016                     return false;
1017                 
1018                 if (willValidate && (s->isValidFormControlElement() != m_element->isValidFormControlElement()))
1019                     return false;
1020
1021                 if (s->isInRange() != m_element->isInRange())
1022                     return false;
1023
1024                 if (s->isOutOfRange() != m_element->isOutOfRange())
1025                     return false;
1026             }
1027
1028             if (style->transitions() || style->animations())
1029                 return false;
1030
1031 #if USE(ACCELERATED_COMPOSITING)
1032             // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1033             // See comments in RenderObject::setStyle().
1034             if (s->hasTagName(iframeTag) || s->hasTagName(embedTag) || s->hasTagName(objectTag) || s->hasTagName(appletTag))
1035                 return false;
1036 #endif
1037
1038             bool classesMatch = true;
1039             if (s->hasClass()) {
1040                 const AtomicString& class1 = m_element->fastGetAttribute(classAttr);
1041                 const AtomicString& class2 = s->fastGetAttribute(classAttr);
1042                 classesMatch = (class1 == class2);
1043             }
1044             
1045             if (classesMatch) {
1046                 bool mappedAttrsMatch = true;
1047                 if (s->hasMappedAttributes())
1048                     mappedAttrsMatch = s->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap());
1049                 if (mappedAttrsMatch) {
1050                     if (s->isLink()) {
1051                         if (m_elementLinkState != style->insideLink())
1052                             return false;
1053                     }
1054                     return true;
1055                 }
1056             }
1057         }
1058     }
1059     return false;
1060 }
1061
1062 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() const
1063 {
1064     if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
1065         // Check previous siblings.
1066         unsigned count = 0;
1067         Node* n;
1068         for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1069         while (n) {
1070             if (canShareStyleWithElement(n))
1071                 return n->renderStyle();
1072             if (count++ == cStyleSearchThreshold)
1073                 return 0;
1074             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1075         }
1076         if (!n) 
1077             n = locateCousinList(m_element->parentElement());
1078         while (n) {
1079             if (canShareStyleWithElement(n))
1080                 return n->renderStyle();
1081             if (count++ == cStyleSearchThreshold)
1082                 return 0;
1083             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1084         }        
1085     }
1086     return 0;
1087 }
1088
1089 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
1090 {
1091     // First we match rules from the user agent sheet.
1092     CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1093         ? defaultPrintStyle : defaultStyle;
1094     matchRules(userAgentStyleSheet, firstUARule, lastUARule, false);
1095
1096     // In quirks mode, we match rules from the quirks user agent sheet.
1097     if (!m_checker.m_strictParsing)
1098         matchRules(defaultQuirksStyle, firstUARule, lastUARule, false);
1099         
1100     // If we're in view source mode, then we match rules from the view source style sheet.
1101     if (m_checker.m_document->frame() && m_checker.m_document->frame()->inViewSourceMode()) {
1102         if (!defaultViewSourceStyle)
1103             loadViewSourceStyle();
1104         matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false);
1105     }
1106 }
1107
1108 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1109 {
1110     Frame* frame = document->frame();
1111
1112     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1113     documentStyle->setDisplay(BLOCK);
1114     documentStyle->setVisuallyOrdered(document->visuallyOrdered());
1115     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1116     documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1);
1117     
1118     Element* docElement = document->documentElement();
1119     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1120     if (docElementRenderer) {
1121         // Use the direction and writing-mode of the body to set the
1122         // viewport's direction and writing-mode unless the property is set on the document element.
1123         // If there is no body, then use the document element.
1124         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1125         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1126             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1127         else
1128             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1129         if (bodyRenderer && !document->directionSetOnDocumentElement())
1130             documentStyle->setDirection(bodyRenderer->style()->direction());
1131         else
1132             documentStyle->setDirection(docElementRenderer->style()->direction());
1133     }
1134
1135     FontDescription fontDescription;
1136     fontDescription.setUsePrinterFont(document->printing());
1137     if (Settings* settings = document->settings()) {
1138         fontDescription.setRenderingMode(settings->fontRenderingMode());
1139         if (document->printing() && !settings->shouldPrintBackgrounds())
1140             documentStyle->setForceBackgroundsToWhite(true);
1141         const AtomicString& stdfont = settings->standardFontFamily();
1142         if (!stdfont.isEmpty()) {
1143             fontDescription.firstFamily().setFamily(stdfont);
1144             fontDescription.firstFamily().appendFamily(0);
1145         }
1146         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1147         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1148         fontDescription.setSpecifiedSize(size);
1149         bool useSVGZoomRules = document->isSVGDocument();
1150         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1151     }
1152
1153     documentStyle->setFontDescription(fontDescription);
1154     documentStyle->font().update(0);
1155         
1156     return documentStyle.release();
1157 }
1158
1159 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1160 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1161
1162 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass)
1163 {
1164     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1165     // will vanish if a style recalc happens during loading.
1166     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
1167         if (!s_styleNotYetAvailable) {
1168             s_styleNotYetAvailable = RenderStyle::create().releaseRef();
1169             s_styleNotYetAvailable->ref();
1170             s_styleNotYetAvailable->setDisplay(NONE);
1171             s_styleNotYetAvailable->font().update(m_fontSelector);
1172         }
1173         s_styleNotYetAvailable->ref();
1174         e->document()->setHasNodesWithPlaceholderStyle();
1175         return s_styleNotYetAvailable;
1176     }
1177
1178     initElement(e);
1179     if (allowSharing) {
1180         RenderStyle* sharedStyle = locateSharedStyle();
1181         if (sharedStyle)
1182             return sharedStyle;
1183     }
1184     initForStyleResolve(e, defaultParent);
1185
1186     // Compute our style allowing :visited to match first.
1187     RefPtr<RenderStyle> visitedStyle;
1188     if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) {
1189         // Fetch our parent style.
1190         RenderStyle* parentStyle = m_parentStyle;
1191         if (!e->isLink()) {
1192             // Use the parent's visited style if one exists.
1193             RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK);
1194             if (parentVisitedStyle)
1195                 parentStyle = parentVisitedStyle;
1196         }
1197         visitedStyle = styleForElement(e, parentStyle, false, false, true);
1198         if (visitedStyle) {
1199             if (m_elementLinkState == InsideUnvisitedLink)
1200                 visitedStyle = 0;  // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it.
1201             else
1202                 visitedStyle->setStyleType(VISITED_LINK);
1203         }
1204         initForStyleResolve(e, defaultParent);
1205     }
1206
1207     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1208
1209     m_style = RenderStyle::create();
1210
1211     if (m_parentStyle)
1212         m_style->inheritFrom(m_parentStyle);
1213     else
1214         m_parentStyle = style();
1215
1216     if (e->isLink()) {
1217         m_style->setIsLink(true);
1218         m_style->setInsideLink(m_elementLinkState);
1219     }
1220     
1221     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) {
1222         loadFullDefaultStyle();
1223 #if ENABLE(FULLSCREEN_API)
1224         loadFullScreenRulesIfNeeded(e->document());
1225 #endif
1226     }
1227
1228 #if ENABLE(SVG)
1229     static bool loadedSVGUserAgentSheet;
1230     if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
1231         // SVG rules.
1232         loadedSVGUserAgentSheet = true;
1233         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
1234         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
1235         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
1236     }
1237 #endif
1238
1239 #if ENABLE(MATHML)
1240     static bool loadedMathMLUserAgentSheet;
1241     if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) {
1242         // MathML rules.
1243         loadedMathMLUserAgentSheet = true;
1244         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
1245         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
1246         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
1247     }
1248 #endif
1249
1250 #if ENABLE(WML)
1251     static bool loadedWMLUserAgentSheet;
1252     if (e->isWMLElement() && !loadedWMLUserAgentSheet) {
1253         // WML rules.
1254         loadedWMLUserAgentSheet = true;
1255         CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
1256         defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
1257         defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
1258     }
1259 #endif
1260
1261 #if ENABLE(VIDEO)
1262     static bool loadedMediaStyleSheet;
1263     if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) {
1264         loadedMediaStyleSheet = true;
1265         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(e->document()->page())->extraMediaControlsStyleSheet();
1266         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
1267         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
1268         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
1269     }
1270 #endif
1271
1272     int firstUARule = -1, lastUARule = -1;
1273     int firstUserRule = -1, lastUserRule = -1;
1274     int firstAuthorRule = -1, lastAuthorRule = -1;
1275     matchUARules(firstUARule, lastUARule);
1276
1277     if (!resolveForRootDefault) {
1278         // 4. Now we check user sheet rules.
1279         if (m_matchAuthorAndUserStyles)
1280             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1281
1282         // 5. Now check author rules, beginning first with presentational attributes
1283         // mapped from HTML.
1284         if (m_styledElement) {
1285             // Ask if the HTML element has mapped attributes.
1286             if (m_styledElement->hasMappedAttributes()) {
1287                 // Walk our attribute list and add in each decl.
1288                 const NamedNodeMap* map = m_styledElement->attributeMap();
1289                 for (unsigned i = 0; i < map->length(); i++) {
1290                     Attribute* attr = map->attributeItem(i);
1291                     if (attr->isMappedAttribute() && attr->decl()) {
1292                         lastAuthorRule = m_matchedDecls.size();
1293                         if (firstAuthorRule == -1)
1294                             firstAuthorRule = lastAuthorRule;
1295                         addMatchedDeclaration(attr->decl());
1296                     }
1297                 }
1298             }
1299
1300             // Now we check additional mapped declarations.
1301             // Tables and table cells share an additional mapped rule that must be applied
1302             // after all attributes, since their mapped style depends on the values of multiple attributes.
1303             if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
1304                 m_additionalAttributeStyleDecls.clear();
1305                 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
1306                 if (!m_additionalAttributeStyleDecls.isEmpty()) {
1307                     unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
1308                     if (firstAuthorRule == -1)
1309                         firstAuthorRule = m_matchedDecls.size();
1310                     lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
1311                     for (unsigned i = 0; i < additionalDeclsSize; i++)
1312                         addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
1313                 }
1314             }
1315         }
1316     
1317         // 6. Check the rules in author sheets next.
1318         if (m_matchAuthorAndUserStyles)
1319             matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1320
1321         // 7. Now check our inline style attribute.
1322         if (m_matchAuthorAndUserStyles && m_styledElement) {
1323             CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
1324             if (inlineDecl) {
1325                 lastAuthorRule = m_matchedDecls.size();
1326                 if (firstAuthorRule == -1)
1327                     firstAuthorRule = lastAuthorRule;
1328                 addMatchedDeclaration(inlineDecl);
1329             }
1330         }
1331     }
1332
1333     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1334     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1335     
1336     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
1337     // high-priority properties first, i.e., those properties that other properties depend on.
1338     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1339     // and (4) normal important.
1340     m_lineHeightValue = 0;
1341     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1342     if (!resolveForRootDefault) {
1343         applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1344         applyDeclarations<true>(true, firstUserRule, lastUserRule);
1345     }
1346     applyDeclarations<true>(true, firstUARule, lastUARule);
1347     
1348     // If our font got dirtied, go ahead and update it now.
1349     if (m_fontDirty)
1350         updateFont();
1351
1352     // Line-height is set when we are sure we decided on the font-size
1353     if (m_lineHeightValue)
1354         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1355
1356     // Now do the normal priority UA properties.
1357     applyDeclarations<false>(false, firstUARule, lastUARule);
1358     
1359     // Cache our border and background so that we can examine them later.
1360     cacheBorderAndBackground();
1361     
1362     // Now do the author and user normal priority properties and all the !important properties.
1363     if (!resolveForRootDefault) {
1364         applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1365         applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1366         applyDeclarations<false>(true, firstUserRule, lastUserRule);
1367     }
1368     applyDeclarations<false>(true, firstUARule, lastUARule);
1369
1370     ASSERT(!m_fontDirty);
1371     // If our font got dirtied by one of the non-essential font props, 
1372     // go ahead and update it a second time.
1373     if (m_fontDirty)
1374         updateFont();
1375     
1376     // Clean up our style object's display and text decorations (among other fixups).
1377     adjustRenderStyle(style(), m_parentStyle, e);
1378
1379     // Start loading images referenced by this style.
1380     loadPendingImages();
1381
1382     // If we have first-letter pseudo style, do not share this style
1383     if (m_style->hasPseudoStyle(FIRST_LETTER))
1384         m_style->setUnique();
1385
1386     if (visitedStyle) {
1387         // Copy any pseudo bits that the visited style has to the primary style so that
1388         // pseudo element styles will continue to work for pseudo elements inside :visited
1389         // links.
1390         for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) {
1391             if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo)))
1392                 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo));
1393         }
1394         
1395         // Add the visited style off the main style.
1396         m_style->addCachedPseudoStyle(visitedStyle.release());
1397     }
1398
1399     if (!matchVisitedPseudoClass)
1400         initElement(0); // Clear out for the next resolve.
1401
1402     // Now return the style.
1403     return m_style.release();
1404 }
1405
1406 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1407 {
1408     if (keyframeRule->style())
1409         addMatchedDeclaration(keyframeRule->style());
1410
1411     ASSERT(!m_style);
1412
1413     // Create the style
1414     m_style = RenderStyle::clone(elementStyle);
1415
1416     m_lineHeightValue = 0;
1417
1418     // We don't need to bother with !important. Since there is only ever one
1419     // decl, there's nothing to override. So just add the first properties.
1420     if (keyframeRule->style())
1421         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1422
1423     // If our font got dirtied, go ahead and update it now.
1424     if (m_fontDirty)
1425         updateFont();
1426
1427     // Line-height is set when we are sure we decided on the font-size
1428     if (m_lineHeightValue)
1429         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1430
1431     // Now do rest of the properties.
1432     if (keyframeRule->style())
1433         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1434
1435     // If our font got dirtied by one of the non-essential font props,
1436     // go ahead and update it a second time.
1437     if (m_fontDirty)
1438         updateFont();
1439
1440     // Start loading images referenced by this style.
1441     loadPendingImages();
1442
1443     // Add all the animating properties to the keyframe.
1444     if (keyframeRule->style()) {
1445         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1446         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1447             int property = (*it).id();
1448             // Timing-function within keyframes is special, because it is not animated; it just
1449             // describes the timing function between this keyframe and the next.
1450             if (property != CSSPropertyWebkitAnimationTimingFunction)
1451                 keyframe.addProperty(property);
1452         }
1453     }
1454
1455     return m_style.release();
1456 }
1457
1458 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1459 {
1460     list.clear();
1461     
1462     // Get the keyframesRule for this name
1463     if (!e || list.animationName().isEmpty())
1464         return;
1465
1466     m_keyframesRuleMap.checkConsistency();
1467    
1468     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1469         return;
1470         
1471     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1472     
1473     // Construct and populate the style for each keyframe
1474     for (unsigned i = 0; i < rule->length(); ++i) {
1475         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1476         initElement(e);
1477         initForStyleResolve(e);
1478         
1479         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1480
1481         KeyframeValue keyframe(0, 0);
1482         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1483
1484         // Add this keyframe style to all the indicated key times
1485         Vector<float> keys;
1486         keyframeRule->getKeys(keys);
1487         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1488             keyframe.setKey(keys[keyIndex]);
1489             list.insert(keyframe);
1490         }
1491     }
1492     
1493     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1494     int initialListSize = list.size();
1495     if (initialListSize > 0 && list[0].key() != 0) {
1496         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1497         keyframeRule->setKeyText("0%");
1498         KeyframeValue keyframe(0, 0);
1499         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1500         list.insert(keyframe);
1501     }
1502
1503     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1504     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1505         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1506         keyframeRule->setKeyText("100%");
1507         KeyframeValue keyframe(1, 0);
1508         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1509         list.insert(keyframe);
1510     }
1511 }
1512
1513 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass)
1514 {
1515     if (!e)
1516         return 0;
1517
1518     initElement(e);
1519
1520     // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it
1521     // off of.
1522     RefPtr<RenderStyle> visitedStyle;
1523     if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) {
1524         // Fetch our parent style with :visited in effect.
1525         RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK);
1526         visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true);
1527         if (visitedStyle) {
1528             if (m_elementLinkState == InsideUnvisitedLink)
1529                 visitedStyle = 0;  // We made the style to avoid timing attacks. Just throw it away now that we did that.
1530             else
1531                 visitedStyle->setStyleType(VISITED_LINK);
1532         }
1533     }
1534
1535     initForStyleResolve(e, parentStyle, pseudo);
1536     m_style = RenderStyle::create();
1537     if (parentStyle)
1538         m_style->inheritFrom(parentStyle);
1539
1540     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1541
1542     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1543     // those rules.
1544     
1545     // Check UA, user and author rules.
1546     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
1547     matchUARules(firstUARule, lastUARule);
1548
1549     if (m_matchAuthorAndUserStyles) {
1550         matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1551         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1552     }
1553
1554     if (m_matchedDecls.isEmpty() && !visitedStyle)
1555         return 0;
1556
1557     m_style->setStyleType(pseudo);
1558     
1559     m_lineHeightValue = 0;
1560     
1561     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1562     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1563
1564     // High-priority properties.
1565     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1566     applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1567     applyDeclarations<true>(true, firstUserRule, lastUserRule);
1568     applyDeclarations<true>(true, firstUARule, lastUARule);
1569     
1570     // If our font got dirtied, go ahead and update it now.
1571     if (m_fontDirty)
1572         updateFont();
1573
1574     // Line-height is set when we are sure we decided on the font-size
1575     if (m_lineHeightValue)
1576         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1577     
1578     // Now do the normal priority properties.
1579     applyDeclarations<false>(false, firstUARule, lastUARule);
1580     
1581     // Cache our border and background so that we can examine them later.
1582     cacheBorderAndBackground();
1583     
1584     applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1585     applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1586     applyDeclarations<false>(true, firstUserRule, lastUserRule);
1587     applyDeclarations<false>(true, firstUARule, lastUARule);
1588     
1589     // If our font got dirtied by one of the non-essential font props, 
1590     // go ahead and update it a second time.
1591     if (m_fontDirty)
1592         updateFont();
1593
1594     // Clean up our style object's display and text decorations (among other fixups).
1595     adjustRenderStyle(style(), parentStyle, 0);
1596
1597     // Start loading images referenced by this style.
1598     loadPendingImages();
1599
1600     // Hang our visited style off m_style.
1601     if (visitedStyle)
1602         m_style->addCachedPseudoStyle(visitedStyle.release());
1603         
1604     // Now return the style.
1605     return m_style.release();
1606 }
1607
1608 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1609 {
1610     initForStyleResolve(m_checker.m_document->documentElement()); // m_rootElementStyle will be set to the document style.
1611
1612     m_style = RenderStyle::create();
1613     m_style->inheritFrom(m_rootElementStyle);
1614
1615     const bool isLeft = isLeftPage(pageIndex);
1616     const bool isFirst = isFirstPage(pageIndex);
1617     const String page = pageName(pageIndex);
1618     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1619     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1620     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1621     m_lineHeightValue = 0;
1622     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1623
1624     // If our font got dirtied, go ahead and update it now.
1625     if (m_fontDirty)
1626         updateFont();
1627
1628     // Line-height is set when we are sure we decided on the font-size
1629     if (m_lineHeightValue)
1630         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1631
1632     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1633
1634     // Start loading images referenced by this style.
1635     loadPendingImages();
1636
1637     // Now return the style.
1638     return m_style.release();
1639 }
1640
1641 #if ENABLE(DATAGRID)
1642
1643 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*)
1644 {
1645     // FIXME: Implement
1646     return 0;
1647 }
1648
1649 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*)
1650 {
1651     // FIXME: Implement
1652     return 0;
1653 }
1654
1655 #endif
1656
1657 static void addIntrinsicMargins(RenderStyle* style)
1658 {
1659     // Intrinsic margin value.
1660     const int intrinsicMargin = 2 * style->effectiveZoom();
1661     
1662     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1663     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1664     if (style->width().isIntrinsicOrAuto()) {
1665         if (style->marginLeft().quirk())
1666             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1667         if (style->marginRight().quirk())
1668             style->setMarginRight(Length(intrinsicMargin, Fixed));
1669     }
1670
1671     if (style->height().isAuto()) {
1672         if (style->marginTop().quirk())
1673             style->setMarginTop(Length(intrinsicMargin, Fixed));
1674         if (style->marginBottom().quirk())
1675             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1676     }
1677 }
1678
1679 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1680 {
1681     // Cache our original display.
1682     style->setOriginalDisplay(style->display());
1683
1684     if (style->display() != NONE) {
1685         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1686         // property.
1687         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1688         // these tags to retain their display types.
1689         if (!m_checker.m_strictParsing && e) {
1690             if (e->hasTagName(tdTag)) {
1691                 style->setDisplay(TABLE_CELL);
1692                 style->setFloating(FNONE);
1693             }
1694             else if (e->hasTagName(tableTag))
1695                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1696         }
1697
1698         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1699             if (style->whiteSpace() == KHTML_NOWRAP) {
1700                 // Figure out if we are really nowrapping or if we should just
1701                 // use normal instead.  If the width of the cell is fixed, then
1702                 // we don't actually use NOWRAP.
1703                 if (style->width().isFixed())
1704                     style->setWhiteSpace(NORMAL);
1705                 else
1706                     style->setWhiteSpace(NOWRAP);
1707             }
1708         }
1709
1710         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1711         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1712             style->setTextAlign(TAAUTO);
1713
1714         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1715         // fix a crash where a site tries to position these objects.  They also never honor display.
1716         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1717             style->setPosition(StaticPosition);
1718             style->setDisplay(BLOCK);
1719         }
1720
1721         // Table headers with a text-align of auto will change the text-align to center.
1722         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1723             style->setTextAlign(CENTER);
1724
1725         if (e && e->hasTagName(legendTag))
1726             style->setDisplay(BLOCK);
1727
1728         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1729         // position or float an inline, compact, or run-in.  Cache the original display, since it
1730         // may be needed for positioned elements that have to compute their static normal flow
1731         // positions.  We also force inline-level roots to be block-level.
1732         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1733             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1734              (e && e->document()->documentElement() == e))) {
1735             if (style->display() == INLINE_TABLE)
1736                 style->setDisplay(TABLE);
1737             else if (style->display() == INLINE_BOX)
1738                 style->setDisplay(BOX);
1739             else if (style->display() == LIST_ITEM) {
1740                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1741                 // but only in quirks mode.
1742                 if (!m_checker.m_strictParsing && style->floating() != FNONE)
1743                     style->setDisplay(BLOCK);
1744             }
1745             else
1746                 style->setDisplay(BLOCK);
1747         }
1748         
1749         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1750         // clear how that should work.
1751         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1752             style->setDisplay(INLINE_BLOCK);
1753         
1754         // After performing the display mutation, check table rows.  We do not honor position:relative on
1755         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1756         // on some sites).
1757         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1758              style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1759              style->position() == RelativePosition)
1760             style->setPosition(StaticPosition);
1761
1762         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1763         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1764         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1765             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1766             || style->display() == TABLE_CELL)
1767             style->setWritingMode(parentStyle->writingMode());
1768
1769         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1770         // of block-flow to anything other than TopToBottomWritingMode.
1771         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1772         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1773             style->setWritingMode(TopToBottomWritingMode);
1774     }
1775
1776     // Make sure our z-index value is only applied if the object is positioned.
1777     if (style->position() == StaticPosition)
1778         style->setHasAutoZIndex();
1779
1780     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1781     // cases where objects that should be blended as a single unit end up with a non-transparent
1782     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1783     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || 
1784         style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect()))
1785         style->setZIndex(0);
1786     
1787 #if ENABLE(WML)
1788     if (e && (e->hasTagName(WMLNames::insertedLegendTag)
1789               || e->hasTagName(WMLNames::inputTag))
1790             && style->width().isAuto())
1791         style->setWidth(Length(Intrinsic));
1792 #endif
1793
1794     // Textarea considers overflow visible as auto.
1795     if (e && e->hasTagName(textareaTag)) {
1796         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1797         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1798     }
1799
1800     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1801     // tables, inline blocks, inline tables, or run-ins.
1802     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1803         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1804         style->setTextDecorationsInEffect(style->textDecoration());
1805     else
1806         style->addToTextDecorationsInEffect(style->textDecoration());
1807     
1808     // If either overflow value is not visible, change to auto.
1809     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1810         style->setOverflowY(OMARQUEE);
1811     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1812         style->setOverflowX(OMARQUEE);
1813     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1814         style->setOverflowX(OAUTO);
1815     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1816         style->setOverflowY(OAUTO);
1817
1818     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1819     // FIXME: Eventually table sections will support auto and scroll.
1820     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1821         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1822         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) 
1823             style->setOverflowX(OVISIBLE);
1824         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) 
1825             style->setOverflowY(OVISIBLE);
1826     }
1827
1828     // Menulists should have visible overflow
1829     if (style->appearance() == MenulistPart) {
1830         style->setOverflowX(OVISIBLE);
1831         style->setOverflowY(OVISIBLE);
1832     }
1833
1834     // Cull out any useless layers and also repeat patterns into additional layers.
1835     style->adjustBackgroundLayers();
1836     style->adjustMaskLayers();
1837
1838     // Do the same for animations and transitions.
1839     style->adjustAnimations();
1840     style->adjustTransitions();
1841
1842     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1843     // alter fonts and heights/widths.
1844     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1845         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1846         // so we have to treat all image buttons as though they were explicitly sized.
1847         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1848             addIntrinsicMargins(style);
1849     }
1850
1851     // Let the theme also have a crack at adjusting the style.
1852     if (style->hasAppearance())
1853         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1854
1855 #if ENABLE(SVG)
1856     if (e && e->isSVGElement()) {
1857         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1858         if (style->overflowY() == OSCROLL)
1859             style->setOverflowY(OHIDDEN);
1860         else if (style->overflowY() == OAUTO)
1861             style->setOverflowY(OVISIBLE);
1862
1863         if (style->overflowX() == OSCROLL)
1864             style->setOverflowX(OHIDDEN);
1865         else if (style->overflowX() == OAUTO)
1866             style->setOverflowX(OVISIBLE);
1867
1868         // Only the root <svg> element in an SVG document fragment tree honors css position
1869         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1870             style->setPosition(RenderStyle::initialPosition());
1871     }
1872 #endif
1873 }
1874
1875 void CSSStyleSelector::updateFont()
1876 {
1877     checkForTextSizeAdjust();
1878     checkForGenericFamilyChange(style(), m_parentStyle);
1879     checkForZoomChange(style(), m_parentStyle);
1880     m_style->font().update(m_fontSelector);
1881     m_fontDirty = false;
1882 }
1883
1884 void CSSStyleSelector::cacheBorderAndBackground()
1885 {
1886     m_hasUAAppearance = m_style->hasAppearance();
1887     if (m_hasUAAppearance) {
1888         m_borderData = m_style->border();
1889         m_backgroundData = *m_style->backgroundLayers();
1890         m_backgroundColor = m_style->backgroundColor();
1891     }
1892 }
1893
1894 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
1895 {
1896     return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly, includeEmptyRules, filter);
1897 }
1898
1899 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
1900 {
1901     if (!e || !e->document()->haveStylesheetsLoaded())
1902         return 0;
1903
1904     m_checker.m_collectRulesOnly = true;
1905
1906     initElement(e);
1907     initForStyleResolve(e, 0, pseudoId);
1908
1909     if (!authorOnly) {
1910         int firstUARule = -1, lastUARule = -1;
1911         // First we match rules from the user agent sheet.
1912         matchUARules(firstUARule, lastUARule);
1913
1914         // Now we check user sheet rules.
1915         if (m_matchAuthorAndUserStyles) {
1916             int firstUserRule = -1, lastUserRule = -1;
1917             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, includeEmptyRules);
1918         }
1919     }
1920
1921     if (m_matchAuthorAndUserStyles) {
1922         m_checker.m_sameOriginOnly = (filter == SameOriginCSSRulesOnly);
1923
1924         // Check the rules in author sheets.
1925         int firstAuthorRule = -1, lastAuthorRule = -1;
1926         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, includeEmptyRules);
1927
1928         m_checker.m_sameOriginOnly = false;
1929     }
1930
1931     m_checker.m_collectRulesOnly = false;
1932    
1933     return m_ruleList.release();
1934 }
1935
1936 bool CSSStyleSelector::checkSelector(CSSSelector* sel)
1937 {
1938     m_dynamicPseudo = NOPSEUDO;
1939
1940     // Check the selector
1941     SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
1942     if (match != SelectorMatches)
1943         return false;
1944
1945     if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
1946         return false;
1947
1948     return true;
1949 }
1950
1951 // Recursive check of selectors and combinators
1952 // It can return 3 different values:
1953 // * SelectorMatches         - the selector matches the element e
1954 // * SelectorFailsLocally    - the selector fails for the element e
1955 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
1956 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
1957 {
1958 #if ENABLE(SVG)
1959     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
1960     // because its contents are not part of the formal document structure.
1961     if (e->isSVGElement() && e->isShadowRoot())
1962         return SelectorFailsCompletely;
1963 #endif
1964
1965     // first selector has to match
1966     if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, elementStyle, elementParentStyle))
1967         return SelectorFailsLocally;
1968
1969     // The rest of the selectors has to match
1970     CSSSelector::Relation relation = sel->relation();
1971
1972     // Prepare next sel
1973     sel = sel->tagHistory();
1974     if (!sel)
1975         return SelectorMatches;
1976
1977     if (relation != CSSSelector::SubSelector)
1978         // Bail-out if this selector is irrelevant for the pseudoStyle
1979         if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
1980             return SelectorFailsCompletely;
1981
1982     // Check for nested links.
1983     if (m_matchVisitedPseudoClass && !isSubSelector) {
1984         RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
1985         if (currentStyle && currentStyle->insideLink() && e->isLink()) {
1986             if (encounteredLink)
1987                 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching.
1988             else
1989                 encounteredLink = true;
1990         }
1991     }
1992
1993     switch (relation) {
1994         case CSSSelector::Descendant:
1995             while (true) {
1996                 ContainerNode* n = e->parentNode();
1997                 if (!n || !n->isElementNode())
1998                     return SelectorFailsCompletely;
1999                 e = static_cast<Element*>(n);
2000                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2001                 if (match != SelectorFailsLocally)
2002                     return match;
2003             }
2004             break;
2005         case CSSSelector::Child:
2006         {
2007             ContainerNode* n = e->parentNode();
2008             if (!n || !n->isElementNode())
2009                 return SelectorFailsCompletely;
2010             e = static_cast<Element*>(n);
2011             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2012         }
2013         case CSSSelector::DirectAdjacent:
2014         {
2015             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2016                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2017                 if (parentStyle)
2018                     parentStyle->setChildrenAffectedByDirectAdjacentRules();
2019             }
2020             Node* n = e->previousSibling();
2021             while (n && !n->isElementNode())
2022                 n = n->previousSibling();
2023             if (!n)
2024                 return SelectorFailsLocally;
2025             e = static_cast<Element*>(n);
2026             m_matchVisitedPseudoClass = false;
2027             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 
2028         }
2029         case CSSSelector::IndirectAdjacent:
2030             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2031                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2032                 if (parentStyle)
2033                     parentStyle->setChildrenAffectedByForwardPositionalRules();
2034             }
2035             while (true) {
2036                 Node* n = e->previousSibling();
2037                 while (n && !n->isElementNode())
2038                     n = n->previousSibling();
2039                 if (!n)
2040                     return SelectorFailsLocally;
2041                 e = static_cast<Element*>(n);
2042                 m_matchVisitedPseudoClass = false;
2043                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2044                 if (match != SelectorFailsLocally)
2045                     return match;
2046             };
2047             break;
2048         case CSSSelector::SubSelector:
2049             // a selector is invalid if something follows a pseudo-element
2050             // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
2051             // to follow the pseudo elements.
2052             if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
2053                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
2054                 return SelectorFailsCompletely;
2055             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
2056         case CSSSelector::ShadowDescendant:
2057         {
2058             Node* shadowHostNode = e->shadowAncestorNode();
2059             if (shadowHostNode == e || !shadowHostNode->isElementNode())
2060                 return SelectorFailsCompletely;
2061             e = static_cast<Element*>(shadowHostNode);
2062             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2063         }
2064     }
2065
2066     return SelectorFailsCompletely;
2067 }
2068
2069 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
2070 {
2071     set->add(qName.localName().impl());
2072 }
2073
2074 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
2075 {
2076     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
2077     // Mozilla treats all other values as case-sensitive, thus so do we.
2078     HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
2079
2080     addLocalNameToSet(attrSet, accept_charsetAttr);
2081     addLocalNameToSet(attrSet, acceptAttr);
2082     addLocalNameToSet(attrSet, alignAttr);
2083     addLocalNameToSet(attrSet, alinkAttr);
2084     addLocalNameToSet(attrSet, axisAttr);
2085     addLocalNameToSet(attrSet, bgcolorAttr);
2086     addLocalNameToSet(attrSet, charsetAttr);
2087     addLocalNameToSet(attrSet, checkedAttr);
2088     addLocalNameToSet(attrSet, clearAttr);
2089     addLocalNameToSet(attrSet, codetypeAttr);
2090     addLocalNameToSet(attrSet, colorAttr);
2091     addLocalNameToSet(attrSet, compactAttr);
2092     addLocalNameToSet(attrSet, declareAttr);
2093     addLocalNameToSet(attrSet, deferAttr);
2094     addLocalNameToSet(attrSet, dirAttr);
2095     addLocalNameToSet(attrSet, disabledAttr);
2096     addLocalNameToSet(attrSet, enctypeAttr);
2097     addLocalNameToSet(attrSet, faceAttr);
2098     addLocalNameToSet(attrSet, frameAttr);
2099     addLocalNameToSet(attrSet, hreflangAttr);
2100     addLocalNameToSet(attrSet, http_equivAttr);
2101     addLocalNameToSet(attrSet, langAttr);
2102     addLocalNameToSet(attrSet, languageAttr);
2103     addLocalNameToSet(attrSet, linkAttr);
2104     addLocalNameToSet(attrSet, mediaAttr);
2105     addLocalNameToSet(attrSet, methodAttr);
2106     addLocalNameToSet(attrSet, multipleAttr);
2107     addLocalNameToSet(attrSet, nohrefAttr);
2108     addLocalNameToSet(attrSet, noresizeAttr);
2109     addLocalNameToSet(attrSet, noshadeAttr);
2110     addLocalNameToSet(attrSet, nowrapAttr);
2111     addLocalNameToSet(attrSet, readonlyAttr);
2112     addLocalNameToSet(attrSet, relAttr);
2113     addLocalNameToSet(attrSet, revAttr);
2114     addLocalNameToSet(attrSet, rulesAttr);
2115     addLocalNameToSet(attrSet, scopeAttr);
2116     addLocalNameToSet(attrSet, scrollingAttr);
2117     addLocalNameToSet(attrSet, selectedAttr);
2118     addLocalNameToSet(attrSet, shapeAttr);
2119     addLocalNameToSet(attrSet, targetAttr);
2120     addLocalNameToSet(attrSet, textAttr);
2121     addLocalNameToSet(attrSet, typeAttr);
2122     addLocalNameToSet(attrSet, valignAttr);
2123     addLocalNameToSet(attrSet, valuetypeAttr);
2124     addLocalNameToSet(attrSet, vlinkAttr);
2125
2126     return attrSet;
2127 }
2128
2129 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
2130 {
2131     static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
2132     bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
2133     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
2134 }
2135
2136 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2137 {
2138     ASSERT(e);
2139     if (!e)
2140         return false;
2141
2142     if (sel->hasTag()) {
2143         const AtomicString& selLocalName = sel->m_tag.localName();
2144         if (selLocalName != starAtom && selLocalName != e->localName())
2145             return false;
2146         const AtomicString& selNS = sel->m_tag.namespaceURI();
2147         if (selNS != starAtom && selNS != e->namespaceURI())
2148             return false;
2149     }
2150
2151     if (sel->hasAttribute()) {
2152         if (sel->m_match == CSSSelector::Class)
2153             return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value);
2154
2155         if (sel->m_match == CSSSelector::Id)
2156             return e->hasID() && e->idForStyleResolution() == sel->m_value;
2157         
2158         const QualifiedName& attr = sel->attribute();
2159
2160         // FIXME: Handle the case were elementStyle is 0.
2161         if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) {
2162             elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
2163             if (selectorAttrs)
2164                 selectorAttrs->add(attr.localName().impl());
2165         }
2166
2167         const AtomicString& value = e->getAttribute(attr);
2168         if (value.isNull())
2169             return false; // attribute is not set
2170
2171         bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
2172
2173         switch (sel->m_match) {
2174         case CSSSelector::Exact:
2175             if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
2176                 return false;
2177             break;
2178         case CSSSelector::List:
2179         {
2180             // Ignore empty selectors or selectors containing spaces
2181             if (sel->m_value.contains(' ') || sel->m_value.isEmpty())
2182                 return false;
2183
2184             unsigned startSearchAt = 0;
2185             while (true) {
2186                 size_t foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
2187                 if (foundPos == notFound)
2188                     return false;
2189                 if (foundPos == 0 || value[foundPos - 1] == ' ') {
2190                     unsigned endStr = foundPos + sel->m_value.length();
2191                     if (endStr == value.length() || value[endStr] == ' ')
2192                         break; // We found a match.
2193                 }
2194                 
2195                 // No match. Keep looking.
2196                 startSearchAt = foundPos + 1;
2197             }
2198             break;
2199         }
2200         case CSSSelector::Contain:
2201             if (!value.contains(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2202                 return false;
2203             break;
2204         case CSSSelector::Begin:
2205             if (!value.startsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2206                 return false;
2207             break;
2208         case CSSSelector::End:
2209             if (!value.endsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2210                 return false;
2211             break;
2212         case CSSSelector::Hyphen:
2213             if (value.length() < sel->m_value.length())
2214                 return false;
2215             if (!value.startsWith(sel->m_value, caseSensitive))
2216                 return false;
2217             // It they start the same, check for exact match or following '-':
2218             if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
2219                 return false;
2220             break;
2221         case CSSSelector::PseudoClass:
2222         case CSSSelector::PseudoElement:
2223         default:
2224             break;
2225         }
2226     }
2227     
2228     if (sel->m_match == CSSSelector::PseudoClass) {
2229         // Handle :not up front.
2230         if (sel->pseudoType() == CSSSelector::PseudoNot) {
2231             // check the simple selector
2232             for (CSSSelector* subSel = sel->simpleSelector(); subSel; subSel = subSel->tagHistory()) {
2233                 // :not cannot nest. I don't really know why this is a
2234                 // restriction in CSS3, but it is, so let's honor it.
2235                 // the parser enforces that this never occurs
2236                 ASSERT(!subSel->simpleSelector());
2237
2238                 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, elementStyle, elementParentStyle))
2239                     return true;
2240             }
2241         } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
2242             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
2243             // (since there are no elements involved).
2244             return checkScrollbarPseudoClass(sel, dynamicPseudo);
2245         } else if (dynamicPseudo == SELECTION) {
2246             if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2247                 return !m_document->page()->focusController()->isActive();
2248         }
2249         
2250         // Normal element pseudo class checking.
2251         switch (sel->pseudoType()) {
2252             // Pseudo classes:
2253             case CSSSelector::PseudoNot:
2254                 break; // Already handled up above.
2255             case CSSSelector::PseudoEmpty: {
2256                 bool result = true;
2257                 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
2258                     if (n->isElementNode()) {
2259                         result = false;
2260                         break;
2261                     } else if (n->isTextNode()) {
2262                         Text* textNode = static_cast<Text*>(n);
2263                         if (!textNode->data().isEmpty()) {
2264                             result = false;
2265                             break;
2266                         }
2267                     }
2268                 }
2269                 if (!m_collectRulesOnly) {
2270                     if (elementStyle)
2271                         elementStyle->setEmptyState(result);
2272                     else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
2273                         e->renderStyle()->setEmptyState(result);
2274                 }
2275                 return result;
2276             }
2277             case CSSSelector::PseudoFirstChild: {
2278                 // first-child matches the first child that is an element
2279                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2280                     bool result = false;
2281                     Node* n = e->previousSibling();
2282                     while (n && !n->isElementNode())
2283                         n = n->previousSibling();
2284                     if (!n)
2285                         result = true;
2286                     if (!m_collectRulesOnly) {
2287                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2288                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2289                         if (parentStyle)
2290                             parentStyle->setChildrenAffectedByFirstChildRules();
2291                         if (result && childStyle)
2292                             childStyle->setFirstChildState();
2293                     }
2294                     return result;
2295                 }
2296                 break;
2297             }
2298             case CSSSelector::PseudoFirstOfType: {
2299                 // first-of-type matches the first element of its type
2300                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2301                     bool result = false;
2302                     const QualifiedName& type = e->tagQName();
2303                     Node* n = e->previousSibling();
2304                     while (n) {
2305                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2306                             break;
2307                         n = n->previousSibling();
2308                     }
2309                     if (!n)
2310                         result = true;
2311                     if (!m_collectRulesOnly) {
2312                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2313                         if (parentStyle)
2314                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2315                     }
2316                     return result;
2317                 }
2318                 break;
2319             }
2320             case CSSSelector::PseudoLastChild: {
2321                 // last-child matches the last child that is an element
2322                 if (Element* parentElement = e->parentElement()) {
2323                     bool result = false;
2324                     if (parentElement->isFinishedParsingChildren()) {
2325                         Node* n = e->nextSibling();
2326                         while (n && !n->isElementNode())
2327                             n = n->nextSibling();
2328                         if (!n)
2329                             result = true;
2330                     }
2331                     if (!m_collectRulesOnly) {
2332                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2333                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2334                         if (parentStyle)
2335                             parentStyle->setChildrenAffectedByLastChildRules();
2336                         if (result && childStyle)
2337                             childStyle->setLastChildState();
2338                     }
2339                     return result;
2340                 }
2341                 break;
2342             }
2343             case CSSSelector::PseudoLastOfType: {
2344                 // last-of-type matches the last element of its type
2345                 if (Element* parentElement = e->parentElement()) {
2346                     if (!m_collectRulesOnly) {
2347                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2348                         if (parentStyle)
2349                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2350                     }
2351                     if (!parentElement->isFinishedParsingChildren())
2352                         return false;
2353                     bool result = false;
2354                     const QualifiedName& type = e->tagQName();
2355                     Node* n = e->nextSibling();
2356                     while (n) {
2357                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2358                             break;
2359                         n = n->nextSibling();
2360                     }
2361                     if (!n)
2362                         result = true;
2363                     return result;
2364                 }
2365                 break;
2366             }
2367             case CSSSelector::PseudoOnlyChild: {
2368                 if (Element* parentElement = e->parentElement()) {
2369                     bool firstChild = false;
2370                     bool lastChild = false;
2371                     
2372                     Node* n = e->previousSibling();
2373                     while (n && !n->isElementNode())
2374                         n = n->previousSibling();
2375                     if (!n)
2376                         firstChild = true;
2377                     if (firstChild && parentElement->isFinishedParsingChildren()) {
2378                         n = e->nextSibling();
2379                         while (n && !n->isElementNode())
2380                             n = n->nextSibling();
2381                         if (!n)
2382                             lastChild = true;
2383                     }
2384                     if (!m_collectRulesOnly) {
2385                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2386                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2387                         if (parentStyle) {
2388                             parentStyle->setChildrenAffectedByFirstChildRules();
2389                             parentStyle->setChildrenAffectedByLastChildRules();
2390                         }
2391                         if (firstChild && childStyle)
2392                             childStyle->setFirstChildState();
2393                         if (lastChild && childStyle)
2394                             childStyle->setLastChildState();
2395                     }
2396                     return firstChild && lastChild;
2397                 }
2398                 break;
2399             }
2400             case CSSSelector::PseudoOnlyOfType: {
2401                 // FIXME: This selector is very slow.
2402                 if (Element* parentElement = e->parentElement()) {
2403                     if (!m_collectRulesOnly) {
2404                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2405                         if (parentStyle) {
2406                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2407                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2408                         }
2409                     }
2410                     if (!parentElement->isFinishedParsingChildren())
2411                         return false;
2412                     bool firstChild = false;
2413                     bool lastChild = false;
2414                     const QualifiedName& type = e->tagQName();
2415                     Node* n = e->previousSibling();
2416                     while (n) {
2417                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2418                             break;
2419                         n = n->previousSibling();
2420                     }
2421                     if (!n)
2422                         firstChild = true;
2423                     if (firstChild) {
2424                         n = e->nextSibling();
2425                         while (n) {
2426                             if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2427                                 break;
2428                             n = n->nextSibling();
2429                         }
2430                         if (!n)
2431                             lastChild = true;
2432                     }
2433                     return firstChild && lastChild;
2434                 }
2435                 break;
2436             }
2437             case CSSSelector::PseudoNthChild: {
2438                 if (!sel->parseNth())
2439                     break;
2440                 if (Element* parentElement = e->parentElement()) {
2441                     int count = 1;
2442                     Node* n = e->previousSibling();
2443                     while (n) {
2444                         if (n->isElementNode()) {
2445                             RenderStyle* s = n->renderStyle();
2446                             unsigned index = s ? s->childIndex() : 0;
2447                             if (index) {
2448                                 count += index;
2449                                 break;
2450                             }
2451                             count++;
2452                         }
2453                         n = n->previousSibling();
2454                     }
2455                     
2456                     if (!m_collectRulesOnly) {
2457                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2458                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2459                         if (childStyle)
2460                             childStyle->setChildIndex(count);
2461                         if (parentStyle)
2462                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2463                     }
2464                     
2465                     if (sel->matchNth(count))
2466                         return true;
2467                 }
2468                 break;
2469             }
2470             case CSSSelector::PseudoNthOfType: {
2471                 if (!sel->parseNth())
2472                     break;
2473                 if (Element* parentElement = e->parentElement()) {
2474                     int count = 1;
2475                     const QualifiedName& type = e->tagQName();
2476                     Node* n = e->previousSibling();
2477                     while (n) {
2478                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2479                             count++;
2480                         n = n->previousSibling();
2481                     }
2482                     
2483                     if (!m_collectRulesOnly) {
2484                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2485                         if (parentStyle)
2486                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2487                     }
2488
2489                     if (sel->matchNth(count))
2490                         return true;
2491                 }
2492                 break;
2493             }
2494             case CSSSelector::PseudoNthLastChild: {
2495                 if (!sel->parseNth())
2496                     break;
2497                 if (Element* parentElement = e->parentElement()) {
2498                     if (!m_collectRulesOnly) {
2499                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2500                         if (parentStyle)
2501                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2502                     }
2503                     if (!parentElement->isFinishedParsingChildren())
2504                         return false;
2505                     int count = 1;
2506                     Node* n = e->nextSibling();
2507                     while (n) {
2508                         if (n->isElementNode())
2509                             count++;
2510                         n = n->nextSibling();
2511                     }
2512                     if (sel->matchNth(count))
2513                         return true;
2514                 }
2515                 break;
2516             }
2517             case CSSSelector::PseudoNthLastOfType: {
2518                 if (!sel->parseNth())
2519                     break;
2520                 if (Element* parentElement = e->parentElement()) {
2521                     if (!m_collectRulesOnly) {
2522                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2523                         if (parentStyle)
2524                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2525                     }
2526                     if (!parentElement->isFinishedParsingChildren())
2527                         return false;
2528                     int count = 1;
2529                     const QualifiedName& type = e->tagQName();
2530                     Node* n = e->nextSibling();
2531                     while (n) {
2532                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2533                             count++;
2534                         n = n->nextSibling();
2535                     }
2536                     if (sel->matchNth(count))
2537                         return true;
2538                 }
2539                 break;
2540             }
2541             case CSSSelector::PseudoTarget:
2542                 if (e == e->document()->cssTarget())
2543                     return true;
2544                 break;
2545             case CSSSelector::PseudoAnyLink:
2546                 if (e && e->isLink())
2547                     return true;
2548                 break;
2549             case CSSSelector::PseudoAutofill: {
2550                 if (!e || !e->isFormControlElement())
2551                     break;
2552                 if (InputElement* inputElement = toInputElement(e))
2553                     return inputElement->isAutofilled();
2554                 break;
2555             }
2556             case CSSSelector::PseudoLink:
2557                 if (e && e->isLink())
2558                     return !m_matchVisitedPseudoClass;
2559                 break;
2560             case CSSSelector::PseudoVisited:
2561                 if (e && e->isLink())
2562                     return m_matchVisitedPseudoClass;
2563                 break;
2564             case CSSSelector::PseudoDrag: {
2565                 if (elementStyle)
2566                     elementStyle->setAffectedByDragRules(true);
2567                 else if (e->renderStyle())
2568                     e->renderStyle()->setAffectedByDragRules(true);
2569                 if (e->renderer() && e->renderer()->isDragging())
2570                     return true;
2571                 break;
2572             }
2573             case CSSSelector::PseudoFocus:
2574                 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
2575                     return true;
2576                 break;
2577             case CSSSelector::PseudoHover: {
2578                 // If we're in quirks mode, then hover should never match anchors with no
2579                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
2580                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2581                     if (elementStyle)
2582                         elementStyle->setAffectedByHoverRules(true);
2583                     else if (e->renderStyle())
2584                         e->renderStyle()->setAffectedByHoverRules(true);
2585                     if (e->hovered())
2586                         return true;
2587                 }
2588                 break;
2589             }
2590             case CSSSelector::PseudoActive:
2591                 // If we're in quirks mode, then :active should never match anchors with no
2592                 // href and *:active should not match anything. 
2593                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2594                     if (elementStyle)
2595                         elementStyle->setAffectedByActiveRules(true);
2596                     else if (e->renderStyle())
2597                         e->renderStyle()->setAffectedByActiveRules(true);
2598                     if (e->active())
2599                         return true;
2600                 }
2601                 break;
2602             case CSSSelector::PseudoEnabled:
2603                 if (e && e->isFormControlElement())
2604                     return e->isEnabledFormControl();
2605                 break;
2606             case CSSSelector::PseudoFullPageMedia:
2607                 return e && e->document() && e->document()->isMediaDocument();
2608                 break;
2609             case CSSSelector::PseudoDefault:
2610                 return e && e->isDefaultButtonForForm();
2611             case CSSSelector::PseudoDisabled:
2612                 if (e && e->isFormControlElement())
2613                     return !e->isEnabledFormControl();
2614                 break;
2615             case CSSSelector::PseudoReadOnly: {
2616                 if (!e || !e->isFormControlElement())
2617                     return false;
2618                 return e->isTextFormControl() && e->isReadOnlyFormControl();
2619             }
2620             case CSSSelector::PseudoReadWrite: {
2621                 if (!e || !e->isFormControlElement())
2622                     return false;
2623                 return e->isTextFormControl() && !e->isReadOnlyFormControl();
2624             }
2625             case CSSSelector::PseudoOptional:
2626                 return e && e->isOptionalFormControl();
2627             case CSSSelector::PseudoRequired:
2628                 return e && e->isRequiredFormControl();
2629             case CSSSelector::PseudoValid: {
2630                 if (!e)
2631                     return false;
2632                 e->document()->setContainsValidityStyleRules();
2633                 return e->willValidate() && e->isValidFormControlElement();
2634             } case CSSSelector::PseudoInvalid: {
2635                 if (!e)
2636                     return false;
2637                 e->document()->setContainsValidityStyleRules();
2638                 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
2639             } case CSSSelector::PseudoChecked: {
2640                 if (!e || !e->isFormControlElement())
2641                     break;
2642                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
2643                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
2644                 // obey the CSS spec here in the test for matching the pseudo.
2645                 InputElement* inputElement = toInputElement(e);
2646                 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate())
2647                     return true;
2648                 break;
2649             }
2650             case CSSSelector::PseudoIndeterminate: {
2651                 if (!e || !e->isFormControlElement())
2652                     break;
2653                 InputElement* inputElement = toInputElement(e);
2654                 if (inputElement && inputElement->isIndeterminate())
2655                     return true;
2656                 break;
2657             }
2658             case CSSSelector::PseudoRoot:
2659                 if (e == e->document()->documentElement())
2660                     return true;
2661                 break;
2662             case CSSSelector::PseudoLang: {
2663                 AtomicString value = e->computeInheritedLanguage();
2664                 const AtomicString& argument = sel->argument();
2665                 if (value.isEmpty() || !value.startsWith(argument, false))
2666                     break;
2667                 if (value.length() != argument.length() && value[argument.length()] != '-')
2668                     break;
2669                 return true;
2670             }
2671 #if ENABLE(FULLSCREEN_API)
2672             case CSSSelector::PseudoFullScreen:
2673                 // While a Document is in the fullscreen state, and the document's current fullscreen 
2674                 // element is an element in the document, the 'full-screen' pseudoclass applies to 
2675                 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing 
2676                 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
2677                 if (!e->document()->webkitIsFullScreen())
2678                     return false;
2679                 if (e != e->document()->webkitCurrentFullScreenElement())
2680                     return false;
2681                 return true;
2682             case CSSSelector::PseudoFullScreenDocument:
2683                 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies 
2684                 // to all elements of that Document.
2685                 if (!e->document()->webkitIsFullScreen())
2686                     return false;
2687                 return true;
2688 #endif
2689             case CSSSelector::PseudoInRange:
2690                 if (!e)
2691                     return false;
2692                 e->document()->setContainsValidityStyleRules();
2693                 return e->isInRange();
2694             case CSSSelector::PseudoOutOfRange:
2695                 if (!e)
2696                     return false;
2697                 e->document()->setContainsValidityStyleRules();
2698                 return e->isOutOfRange();
2699             case CSSSelector::PseudoUnknown:
2700             case CSSSelector::PseudoNotParsed:
2701             default:
2702                 ASSERT_NOT_REACHED();
2703                 break;
2704         }
2705         return false;
2706     }
2707     if (sel->m_match == CSSSelector::PseudoElement) {
2708         if (!elementStyle && !m_collectRulesOnly)
2709             return false;
2710
2711         PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
2712         if (pseudoId == FIRST_LETTER) {
2713             if (Document* document = e->document())
2714                 document->setUsesFirstLetterRules(true);
2715         }
2716         if (pseudoId != NOPSEUDO)
2717             dynamicPseudo = pseudoId;
2718     }
2719     // ### add the rest of the checks...
2720     return true;
2721 }
2722
2723 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
2724 {
2725     RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
2726     ScrollbarPart part = RenderScrollbar::partForStyleResolve();
2727
2728     // FIXME: This is a temporary hack for resizers and scrollbar corners.  Eventually :window-inactive should become a real
2729     // pseudo class and just apply to everything.
2730     if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2731         return !m_document->page()->focusController()->isActive();
2732     
2733     if (!scrollbar)
2734         return false;
2735         
2736     ASSERT(sel->m_match == CSSSelector::PseudoClass);
2737     switch (sel->pseudoType()) {
2738         case CSSSelector::PseudoEnabled:
2739             return scrollbar->enabled();
2740         case CSSSelector::PseudoDisabled:
2741             return !scrollbar->enabled();
2742         case CSSSelector::PseudoHover: {
2743             ScrollbarPart hoveredPart = scrollbar->hoveredPart();
2744             if (part == ScrollbarBGPart)
2745                 return hoveredPart != NoPart;
2746             if (part == TrackBGPart)
2747                 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
2748             return part == hoveredPart;
2749         }
2750         case CSSSelector::PseudoActive: {
2751             ScrollbarPart pressedPart = scrollbar->pressedPart();
2752             if (part == ScrollbarBGPart)
2753                 return pressedPart != NoPart;
2754             if (part == TrackBGPart)
2755                 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
2756             return part == pressedPart;
2757         }
2758         case CSSSelector::PseudoHorizontal:
2759             return scrollbar->orientation() == HorizontalScrollbar;
2760         case CSSSelector::PseudoVertical:
2761             return scrollbar->orientation() == VerticalScrollbar;
2762         case CSSSelector::PseudoDecrement:
2763             return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
2764         case CSSSelector::PseudoIncrement:
2765             return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
2766         case CSSSelector::PseudoStart:
2767             return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
2768         case CSSSelector::PseudoEnd:
2769             return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
2770         case CSSSelector::PseudoDoubleButton: {
2771             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2772             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
2773                 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
2774             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
2775                 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
2776             return false;
2777         } 
2778         case CSSSelector::PseudoSingleButton: {
2779             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2780             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
2781                 return buttonsPlacement == ScrollbarButtonsSingle;
2782             return false;
2783         }
2784         case CSSSelector::PseudoNoButton: {
2785             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2786             if (part == BackTrackPart)
2787                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
2788             if (part == ForwardTrackPart)
2789                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
2790             return false;
2791         }
2792         case CSSSelector::PseudoCornerPresent:
2793             return scrollbar->client()->scrollbarCornerPresent();
2794         default:
2795             return false;
2796     }
2797 }
2798
2799 // -----------------------------------------------------------------
2800
2801 CSSRuleSet::CSSRuleSet()
2802     : m_ruleCount(0)
2803     , m_pageRuleCount(0)
2804 {
2805 }
2806
2807 CSSRuleSet::~CSSRuleSet()
2808
2809     deleteAllValues(m_idRules);
2810     deleteAllValues(m_classRules);
2811     deleteAllValues(m_tagRules);
2812 }
2813
2814
2815 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
2816                               CSSStyleRule* rule, CSSSelector* sel)
2817 {
2818     if (!key) return;
2819     CSSRuleDataList* rules = map.get(key);
2820     if (!rules) {
2821         rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
2822         map.set(key, rules);
2823     } else
2824         rules->append(m_ruleCount++, rule, sel);
2825 }
2826
2827 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
2828 {
2829     if (sel->m_match == CSSSelector::Id) {
2830         addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel);
2831         return;
2832     }
2833     if (sel->m_match == CSSSelector::Class) {
2834         addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel);
2835         return;
2836     }
2837      
2838     if (sel->isUnknownPseudoElement()) {
2839         addToRuleSet(sel->m_value.impl(), m_pseudoRules, rule, sel);
2840         return;
2841     }
2842
2843     const AtomicString& localName = sel->m_tag.localName();
2844     if (localName != starAtom) {
2845         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
2846         return;
2847     }
2848
2849     // Just put it in the universal rule set.
2850     if (!m_universalRules)
2851         m_universalRules = adoptPtr(new CSSRuleDataList(m_ruleCount++, rule, sel));
2852     else
2853         m_universalRules->append(m_ruleCount++, rule, sel);
2854 }
2855
2856 void CSSRuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
2857 {
2858     if (!m_pageRules)
2859         m_pageRules = adoptPtr(new CSSRuleDataList(m_pageRuleCount++, rule, sel));
2860     else
2861         m_pageRules->append(m_pageRuleCount++, rule, sel);
2862 }
2863
2864 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
2865 {
2866     if (!sheet)
2867         return;
2868
2869     // No media implies "all", but if a media list exists it must
2870     // contain our current medium
2871     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
2872         return; // the style sheet doesn't apply
2873
2874     int len = sheet->length();
2875
2876     for (int i = 0; i < len; i++) {
2877         StyleBase* item = sheet->item(i);
2878         if (item->isStyleRule())
2879             addStyleRule(static_cast<CSSStyleRule*>(item));
2880         else if (item->isImportRule()) {
2881             CSSImportRule* import = static_cast<CSSImportRule*>(item);
2882             if (!import->media() || medium.eval(import->media(), styleSelector))
2883                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
2884         }
2885         else if (item->isMediaRule()) {
2886             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
2887             CSSRuleList* rules = r->cssRules();
2888
2889             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
2890                 // Traverse child elements of the @media rule.
2891                 for (unsigned j = 0; j < rules->length(); j++) {
2892                     CSSRule *childItem = rules->item(j);
2893                     if (childItem->isStyleRule()) {
2894                         // It is a StyleRule, so append it to our list
2895                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
2896                     } else if (childItem->isFontFaceRule() && styleSelector) {
2897                         // Add this font face to our set.
2898                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
2899                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2900                     } else if (childItem->isKeyframesRule() && styleSelector) {
2901                         // Add this keyframe rule to our set.
2902                         styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
2903                     }
2904                 }   // for rules
2905             }   // if rules
2906         } else if (item->isFontFaceRule() && styleSelector) {
2907             // Add this font face to our set.
2908             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
2909             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2910         } else if (item->isKeyframesRule())
2911             styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item));
2912     }
2913 }
2914
2915 void CSSRuleSet::addStyleRule(CSSStyleRule* rule)
2916 {
2917     if (rule->isPageRule()) {
2918         CSSPageRule* pageRule = static_cast<CSSPageRule*>(rule);
2919         addPageRule(pageRule, pageRule->selectorList().first());
2920     } else {
2921         for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2922             addRule(rule, s);
2923     }
2924 }
2925
2926 // -------------------------------------------------------------------------------------
2927 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2928
2929 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2930 {
2931     // This function is tolerant of a null style value. The only place style is used is in
2932     // length measurements, like 'ems' and 'px'. And in those cases style is only used
2933     // when the units are EMS or EXS. So we will just fail in those cases.
2934     Length l;
2935     if (!primitiveValue) {
2936         if (ok)
2937             *ok = false;
2938     } else {
2939         int type = primitiveValue->primitiveType();
2940         
2941         if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
2942             if (ok)
2943                 *ok = false;
2944         } else if (CSSPrimitiveValue::isUnitTypeLength(type))
2945             l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed);
2946         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2947             l = Length(primitiveValue->getDoubleValue(), Percent);
2948         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2949             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2950         else if (ok)
2951             *ok = false;
2952     }
2953     return l;
2954 }
2955
2956 template <bool applyFirst>
2957 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex)
2958 {
2959     if (startIndex == -1)
2960         return;
2961
2962     for (int i = startIndex; i <= endIndex; i++) {
2963         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
2964         CSSMutableStyleDeclaration::const_iterator end = decl->end();
2965         for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {
2966             const CSSProperty& current = *it;
2967             if (isImportant == current.isImportant()) {
2968                 int property = current.id();
2969
2970                 if (applyFirst) {
2971                     COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2972                     COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 13, CSS_zoom_is_end_of_first_prop_range);
2973                     COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2974
2975                     // give special priority to font-xxx, color properties, etc
2976                     if (property <= CSSPropertyLineHeight) {
2977                         // we apply line-height later
2978                         if (property == CSSPropertyLineHeight)
2979                             m_lineHeightValue = current.value(); 
2980                         else 
2981                             applyProperty(current.id(), current.value());
2982                     }
2983                 } else {
2984                     if (property > CSSPropertyLineHeight)
2985                         applyProperty(current.id(), current.value());
2986                 }
2987             }
2988         }
2989     }
2990 }
2991
2992 void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2993 {
2994     m_matchedRules.clear();
2995
2996     if (!rules)
2997         return;
2998
2999     matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName);
3000
3001     // If we didn't match any rules, we're done.
3002     if (m_matchedRules.isEmpty())
3003         return;
3004
3005     // Sort the set of matched rules.
3006     sortMatchedRules(0, m_matchedRules.size());
3007
3008     // Now transfer the set of matched rules over to our list of decls.
3009     for (unsigned i = 0; i < m_matchedRules.size(); i++)
3010         addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
3011 }
3012
3013 void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
3014 {
3015     if (!rules)
3016         return;
3017
3018     for (CSSRuleData* d = rules->first(); d; d = d->next()) {
3019         CSSStyleRule* rule = d->rule();
3020         const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
3021         if (selectorLocalName != starAtom && selectorLocalName != pageName)
3022             continue;
3023         CSSSelector::PseudoType pseudoType = d->selector()->pseudoType();
3024         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
3025             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
3026             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
3027             continue;
3028
3029         // If the rule has no properties to apply, then ignore it.
3030         CSSMutableStyleDeclaration* decl = rule->declaration();
3031         if (!decl || !decl->length())
3032             continue;
3033
3034         // Add this rule to our list of matched rules.
3035         addMatchedRule(d);
3036     }
3037 }
3038
3039 bool CSSStyleSelector::isLeftPage(int pageIndex) const
3040 {
3041     bool isFirstPageLeft = false;
3042     if (!m_rootElementStyle->isLeftToRightDirection())
3043         isFirstPageLeft = true;
3044
3045     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
3046 }
3047
3048 bool CSSStyleSelector::isFirstPage(int pageIndex) const
3049 {
3050     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
3051     return (!pageIndex);
3052 }
3053
3054 String CSSStyleSelector::pageName(int /* pageIndex */) const
3055 {
3056     // FIXME: Implement page index to page name mapping.
3057     return "";
3058 }
3059
3060 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
3061 {
3062     CounterDirectiveMap& map = style->accessCounterDirectives();
3063     typedef CounterDirectiveMap::iterator Iterator;
3064
3065     Iterator end = map.end();
3066     for (Iterator it = map.begin(); it != end; ++it)
3067         if (isReset)
3068             it->second.m_reset = false;
3069         else
3070             it->second.m_increment = false;
3071
3072     int length = list ? list->length() : 0;
3073     for (int i = 0; i < length; ++i) {
3074         CSSValue* currValue = list->itemWithoutBoundsCheck(i);
3075         if (!currValue->isPrimitiveValue())
3076             continue;
3077
3078         Pair* pair = static_cast<CSSPrimitiveValue*>(currValue)->getPairValue();
3079         if (!pair || !pair->first() || !pair->second())
3080             continue;
3081
3082         AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
3083         // FIXME: What about overflow?
3084         int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
3085         CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
3086         if (isReset) {
3087             directives.m_reset = true;
3088             directives.m_resetValue = value;
3089         } else {
3090             if (directives.m_increment)
3091                 directives.m_incrementValue += value;
3092             else {
3093                 directives.m_increment = true;
3094                 directives.m_incrementValue = value;
3095             }
3096         }
3097     }
3098 }
3099
3100 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style)
3101 {
3102     initElement(0);
3103     initForStyleResolve(0, style);
3104     m_style = style;
3105     if (value)
3106         applyProperty(id, value);
3107 }
3108
3109 inline bool isValidVisitedLinkProperty(int id)
3110 {
3111     switch(static_cast<CSSPropertyID>(id)) {
3112         case CSSPropertyBackgroundColor:
3113         case CSSPropertyBorderLeftColor:
3114         case CSSPropertyBorderRightColor:
3115         case CSSPropertyBorderTopColor:
3116         case CSSPropertyBorderBottomColor:
3117         case CSSPropertyColor:
3118         case CSSPropertyOutlineColor:
3119         case CSSPropertyWebkitColumnRuleColor:
3120         case CSSPropertyWebkitTextEmphasisColor:
3121         case CSSPropertyWebkitTextFillColor:
3122         case CSSPropertyWebkitTextStrokeColor:
3123         // Also allow shorthands so that inherit/initial still work.
3124         case CSSPropertyBackground:
3125         case CSSPropertyBorderLeft:
3126         case CSSPropertyBorderRight:
3127         case CSSPropertyBorderTop:
3128         case CSSPropertyBorderBottom:
3129         case CSSPropertyOutline:
3130         case CSSPropertyWebkitColumnRule:
3131 #if ENABLE(SVG)
3132         case CSSPropertyFill:
3133         case CSSPropertyStroke:
3134 #endif
3135             return true;
3136         default:
3137             break;
3138     }
3139
3140     return false;
3141 }
3142
3143 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
3144 {
3145     CSSPrimitiveValue* primitiveValue = 0;
3146     if (value->isPrimitiveValue())
3147         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3148
3149     float zoomFactor = m_style->effectiveZoom();
3150
3151     // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
3152     // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
3153     // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
3154     // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
3155     // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
3156     // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
3157     // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
3158     // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
3159     bool useSVGZoomRules = m_element && m_element->isSVGElement();
3160
3161     Length l;
3162     bool apply = false;
3163
3164     unsigned short valueType = value->cssValueType();
3165
3166     bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
3167     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
3168     
3169     id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3170
3171     if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) {
3172         // Limit the properties that can be applied to only the ones honored by :visited.
3173         return;
3174     }
3175     
3176     // What follows is a list that maps the CSS properties into their corresponding front-end
3177     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
3178     // are only hit when mapping "inherit" or "initial" into front-end values.
3179     CSSPropertyID property = static_cast<CSSPropertyID>(id);
3180     switch (property) {
3181 // ident only properties
3182     case CSSPropertyBackgroundAttachment:
3183         HANDLE_BACKGROUND_VALUE(attachment, Attachment, value)
3184         return;
3185     case CSSPropertyBackgroundClip:
3186     case CSSPropertyWebkitBackgroundClip:
3187         HANDLE_BACKGROUND_VALUE(clip, Clip, value)
3188         return;
3189     case CSSPropertyWebkitBackgroundComposite:
3190         HANDLE_BACKGROUND_VALUE(composite, Composite, value)
3191         return;
3192     case CSSPropertyBackgroundOrigin:
3193     case CSSPropertyWebkitBackgroundOrigin:
3194         HANDLE_BACKGROUND_VALUE(origin, Origin, value)
3195         return;
3196     case CSSPropertyBackgroundSize:
3197     case CSSPropertyWebkitBackgroundSize:
3198         HANDLE_BACKGROUND_VALUE(size, Size, value)
3199         return;
3200     case CSSPropertyWebkitMaskAttachment:
3201         HANDLE_MASK_VALUE(attachment, Attachment, value)
3202         return;
3203     case CSSPropertyWebkitMaskClip:
3204         HANDLE_MASK_VALUE(clip, Clip, value)
3205         return;
3206     case CSSPropertyWebkitMaskComposite:
3207         HANDLE_MASK_VALUE(composite, Composite, value)
3208         return;
3209     case CSSPropertyWebkitMaskOrigin:
3210    &