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