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