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