• 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, 2010, 2011 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  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 
27 #include "config.h"
28 #include "CSSStyleSelector.h"
29 
30 #include "Attribute.h"
31 #include "ContentData.h"
32 #include "CounterContent.h"
33 #include "CursorList.h"
34 #include "CSSBorderImageValue.h"
35 #include "CSSCursorImageValue.h"
36 #include "CSSFontFaceRule.h"
37 #include "CSSImportRule.h"
38 #include "CSSLineBoxContainValue.h"
39 #include "CSSMediaRule.h"
40 #include "CSSPageRule.h"
41 #include "CSSParser.h"
42 #include "CSSPrimitiveValueMappings.h"
43 #include "CSSPropertyNames.h"
44 #include "CSSReflectValue.h"
45 #include "CSSRuleList.h"
46 #include "CSSSelector.h"
47 #include "CSSSelectorList.h"
48 #include "CSSStyleApplyProperty.h"
49 #include "CSSStyleRule.h"
50 #include "CSSStyleSheet.h"
51 #include "CSSTimingFunctionValue.h"
52 #include "CSSValueList.h"
53 #include "CachedImage.h"
54 #include "Counter.h"
55 #include "FocusController.h"
56 #include "FontFamilyValue.h"
57 #include "FontValue.h"
58 #include "Frame.h"
59 #include "FrameView.h"
60 #include "HTMLDocument.h"
61 #include "HTMLElement.h"
62 #include "HTMLInputElement.h"
63 #include "HTMLNames.h"
64 #include "HTMLTextAreaElement.h"
65 #include "KeyframeList.h"
66 #include "LinkHash.h"
67 #include "Matrix3DTransformOperation.h"
68 #include "MatrixTransformOperation.h"
69 #include "MediaList.h"
70 #include "MediaQueryEvaluator.h"
71 #include "NodeRenderStyle.h"
72 #include "Page.h"
73 #include "PageGroup.h"
74 #include "Pair.h"
75 #include "PerspectiveTransformOperation.h"
76 #include "QuotesData.h"
77 #include "Rect.h"
78 #include "RenderScrollbar.h"
79 #include "RenderScrollbarTheme.h"
80 #include "RenderStyleConstants.h"
81 #include "RenderTheme.h"
82 #include "RotateTransformOperation.h"
83 #include "ScaleTransformOperation.h"
84 #include "SelectionController.h"
85 #include "Settings.h"
86 #include "ShadowData.h"
87 #include "ShadowValue.h"
88 #include "SkewTransformOperation.h"
89 #include "StyleCachedImage.h"
90 #include "StylePendingImage.h"
91 #include "StyleGeneratedImage.h"
92 #include "StyleSheetList.h"
93 #include "Text.h"
94 #include "TransformationMatrix.h"
95 #include "TranslateTransformOperation.h"
96 #include "UserAgentStyleSheets.h"
97 #include "WebKitCSSKeyframeRule.h"
98 #include "WebKitCSSKeyframesRule.h"
99 #include "WebKitCSSTransformValue.h"
100 #include "XMLNames.h"
101 #include <wtf/StdLibExtras.h>
102 #include <wtf/Vector.h>
103 
104 #if USE(PLATFORM_STRATEGIES)
105 #include "PlatformStrategies.h"
106 #include "VisitedLinkStrategy.h"
107 #endif
108 
109 #if ENABLE(DASHBOARD_SUPPORT)
110 #include "DashboardRegion.h"
111 #endif
112 
113 #if ENABLE(SVG)
114 #include "XLinkNames.h"
115 #include "SVGNames.h"
116 #endif
117 
118 #if ENABLE(WML)
119 #include "WMLNames.h"
120 #endif
121 
122 #if PLATFORM(QT)
123 #include <qwebhistoryinterface.h>
124 #endif
125 
126 using namespace std;
127 
128 namespace WebCore {
129 
130 using namespace HTMLNames;
131 
132 #define HANDLE_INHERIT(prop, Prop) \
133 if (isInherit) { \
134     m_style->set##Prop(m_parentStyle->prop()); \
135     return; \
136 }
137 
138 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
139 HANDLE_INHERIT(prop, Prop) \
140 if (isInitial) { \
141     m_style->set##Prop(RenderStyle::initial##Prop()); \
142     return; \
143 }
144 
145 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
146 HANDLE_INHERIT(prop, Prop) \
147 if (isInitial) { \
148     m_style->set##Prop(RenderStyle::initial##Value());\
149     return;\
150 }
151 
152 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
153 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
154 if (primitiveValue) \
155     m_style->set##Prop(*primitiveValue);
156 
157 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
158 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
159 if (primitiveValue) \
160     m_style->set##Prop(*primitiveValue);
161 
162 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
163 if (isInherit) { \
164     AnimationList* list = m_style->accessAnimations(); \
165     const AnimationList* parentList = m_parentStyle->animations(); \
166     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
167     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
168         if (list->size() <= i) \
169             list->append(Animation::create()); \
170         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
171     } \
172     \
173     /* Reset any remaining animations to not have the property set. */ \
174     for ( ; i < list->size(); ++i) \
175         list->animation(i)->clear##Prop(); \
176 } else if (isInitial) { \
177     AnimationList* list = m_style->accessAnimations(); \
178     if (list->isEmpty()) \
179         list->append(Animation::create()); \
180     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
181     for (size_t i = 1; i < list->size(); ++i) \
182         list->animation(0)->clear##Prop(); \
183 }
184 
185 #define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \
186 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
187 if (isInherit || isInitial) \
188     return; \
189 AnimationList* list = m_style->accessAnimations(); \
190 size_t childIndex = 0; \
191 if (value->isValueList()) { \
192     /* Walk each value and put it into an animation, creating new animations as needed. */ \
193     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
194     for (unsigned int i = 0; i < valueList->length(); i++) { \
195         if (childIndex <= list->size()) \
196             list->append(Animation::create()); \
197         mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
198         ++childIndex; \
199     } \
200 } else { \
201     if (list->isEmpty()) \
202         list->append(Animation::create()); \
203     mapAnimation##Prop(list->animation(childIndex), value); \
204     childIndex = 1; \
205 } \
206 for ( ; childIndex < list->size(); ++childIndex) { \
207     /* Reset all remaining animations to not have the property set. */ \
208     list->animation(childIndex)->clear##Prop(); \
209 } \
210 }
211 
212 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
213 if (isInherit) { \
214     AnimationList* list = m_style->accessTransitions(); \
215     const AnimationList* parentList = m_parentStyle->transitions(); \
216     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
217     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
218         if (list->size() <= i) \
219             list->append(Animation::create()); \
220         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
221     } \
222     \
223     /* Reset any remaining transitions to not have the property set. */ \
224     for ( ; i < list->size(); ++i) \
225         list->animation(i)->clear##Prop(); \
226 } else if (isInitial) { \
227     AnimationList* list = m_style->accessTransitions(); \
228     if (list->isEmpty()) \
229         list->append(Animation::create()); \
230     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
231     for (size_t i = 1; i < list->size(); ++i) \
232         list->animation(0)->clear##Prop(); \
233 }
234 
235 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
236 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
237 if (isInherit || isInitial) \
238     return; \
239 AnimationList* list = m_style->accessTransitions(); \
240 size_t childIndex = 0; \
241 if (value->isValueList()) { \
242     /* Walk each value and put it into a transition, creating new animations as needed. */ \
243     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
244     for (unsigned int i = 0; i < valueList->length(); i++) { \
245         if (childIndex <= list->size()) \
246             list->append(Animation::create()); \
247         mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
248         ++childIndex; \
249     } \
250 } else { \
251     if (list->isEmpty()) \
252         list->append(Animation::create()); \
253     mapAnimation##Prop(list->animation(childIndex), value); \
254     childIndex = 1; \
255 } \
256 for ( ; childIndex < list->size(); ++childIndex) { \
257     /* Reset all remaining transitions to not have the property set. */ \
258     list->animation(childIndex)->clear##Prop(); \
259 } \
260 }
261 
262 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
263 if (id == propID) { \
264     m_style->set##Prop(m_parentStyle->prop()); \
265     return; \
266 }
267 
268 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
269 if (id == propID) { \
270     if (m_parentStyle->prop().isValid()) \
271         m_style->set##Prop(m_parentStyle->prop()); \
272     else \
273         m_style->set##Prop(m_parentStyle->propAlt()); \
274     return; \
275 }
276 
277 #define HANDLE_INITIAL_COND(propID, Prop) \
278 if (id == propID) { \
279     m_style->set##Prop(RenderStyle::initial##Prop()); \
280     return; \
281 }
282 
283 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
284 if (id == propID) { \
285     m_style->set##Prop(RenderStyle::initial##Value()); \
286     return; \
287 }
288 
289 class RuleData {
290 public:
291     RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
292 
position() const293     unsigned position() const { return m_position; }
rule() const294     CSSStyleRule* rule() const { return m_rule; }
selector() const295     CSSSelector* selector() const { return m_selector; }
296 
hasFastCheckableSelector() const297     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
hasMultipartSelector() const298     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
hasTopSelectorMatchingHTMLBasedOnRuleHash() const299     bool hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; }
specificity() const300     unsigned specificity() const { return m_specificity; }
301 
302     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
303     static const unsigned maximumIdentifierCount = 4;
descendantSelectorIdentifierHashes() const304     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
305 
306 private:
307     void collectDescendantSelectorIdentifierHashes();
308     void collectIdentifierHashes(const CSSSelector*, unsigned& identifierCount);
309 
310     CSSStyleRule* m_rule;
311     CSSSelector* m_selector;
312     unsigned m_specificity;
313     unsigned m_position : 29;
314     bool m_hasFastCheckableSelector : 1;
315     bool m_hasMultipartSelector : 1;
316     bool m_hasTopSelectorMatchingHTMLBasedOnRuleHash : 1;
317     // Use plain array instead of a Vector to minimize memory overhead.
318     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
319 };
320 
321 class RuleSet {
322     WTF_MAKE_NONCOPYABLE(RuleSet);
323 public:
324     RuleSet();
325     ~RuleSet();
326 
327     typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap;
328 
329     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
330 
331     void addStyleRule(CSSStyleRule* item);
332     void addRule(CSSStyleRule* rule, CSSSelector* sel);
333     void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
334     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
335                       CSSStyleRule* rule, CSSSelector* sel);
336     void shrinkToFit();
disableAutoShrinkToFit()337     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
338 
339     void collectFeatures(CSSStyleSelector::Features&) const;
340 
getIDRules(AtomicStringImpl * key) const341     const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
getClassRules(AtomicStringImpl * key) const342     const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
getTagRules(AtomicStringImpl * key) const343     const Vector<RuleData>* getTagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
getPseudoRules(AtomicStringImpl * key) const344     const Vector<RuleData>* getPseudoRules(AtomicStringImpl* key) const { return m_pseudoRules.get(key); }
getUniversalRules() const345     const Vector<RuleData>* getUniversalRules() const { return &m_universalRules; }
getPageRules() const346     const Vector<RuleData>* getPageRules() const { return &m_pageRules; }
347 
348 public:
349     AtomRuleMap m_idRules;
350     AtomRuleMap m_classRules;
351     AtomRuleMap m_tagRules;
352     AtomRuleMap m_pseudoRules;
353     Vector<RuleData> m_universalRules;
354     Vector<RuleData> m_pageRules;
355     unsigned m_ruleCount;
356     bool m_autoShrinkToFitEnabled;
357 };
358 
359 static RuleSet* defaultStyle;
360 static RuleSet* defaultQuirksStyle;
361 static RuleSet* defaultPrintStyle;
362 static RuleSet* defaultViewSourceStyle;
363 static CSSStyleSheet* simpleDefaultStyleSheet;
364 
365 static RuleSet* siblingRulesInDefaultStyle;
366 
367 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
368 
369 static void loadFullDefaultStyle();
370 static void loadSimpleDefaultStyle();
371 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
372 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}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}";
373 
elementCanUseSimpleDefaultStyle(Element * e)374 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
375 {
376     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
377 }
378 
collectSiblingRulesInDefaultStyle()379 static inline void collectSiblingRulesInDefaultStyle()
380 {
381     CSSStyleSelector::Features features;
382     defaultStyle->collectFeatures(features);
383     ASSERT(features.idsInRules.isEmpty());
384     delete siblingRulesInDefaultStyle;
385     siblingRulesInDefaultStyle = features.siblingRules.leakPtr();
386 }
387 
assertNoSiblingRulesInDefaultStyle()388 static inline void assertNoSiblingRulesInDefaultStyle()
389 {
390 #ifndef NDEBUG
391     if (siblingRulesInDefaultStyle)
392         return;
393     collectSiblingRulesInDefaultStyle();
394     ASSERT(!siblingRulesInDefaultStyle);
395 #endif
396 }
397 
screenEval()398 static const MediaQueryEvaluator& screenEval()
399 {
400     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
401     return staticScreenEval;
402 }
403 
printEval()404 static const MediaQueryEvaluator& printEval()
405 {
406     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
407     return staticPrintEval;
408 }
409 
leftToRightDeclaration()410 static CSSMutableStyleDeclaration* leftToRightDeclaration()
411 {
412     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
413     if (!leftToRightDecl->length()) {
414         leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false);
415         leftToRightDecl->setStrictParsing(false);
416     }
417     return leftToRightDecl.get();
418 }
419 
rightToLeftDeclaration()420 static CSSMutableStyleDeclaration* rightToLeftDeclaration()
421 {
422     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create()));
423     if (!rightToLeftDecl->length()) {
424         rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false);
425         rightToLeftDecl->setStrictParsing(false);
426     }
427     return rightToLeftDecl.get();
428 }
429 
CSSStyleSelector(Document * document,StyleSheetList * styleSheets,CSSStyleSheet * mappedElementSheet,CSSStyleSheet * pageUserSheet,const Vector<RefPtr<CSSStyleSheet>> * pageGroupUserSheets,bool strictParsing,bool matchAuthorAndUserStyles)430 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
431                                    CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
432                                    bool strictParsing, bool matchAuthorAndUserStyles)
433     : m_backgroundData(BackgroundFillLayer)
434     , m_checker(document, strictParsing)
435     , m_element(0)
436     , m_styledElement(0)
437     , m_elementLinkState(NotInsideLink)
438     , m_fontSelector(CSSFontSelector::create(document))
439     , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
440 {
441     m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
442 
443     Element* root = document->documentElement();
444 
445     if (!defaultStyle) {
446         if (!root || elementCanUseSimpleDefaultStyle(root))
447             loadSimpleDefaultStyle();
448         else {
449             loadFullDefaultStyle();
450         }
451     }
452 
453     // construct document root element default style. this is needed
454     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
455     // This is here instead of constructor, because when constructor is run,
456     // document doesn't have documentElement
457     // NOTE: this assumes that element that gets passed to styleForElement -call
458     // is always from the document that owns the style selector
459     FrameView* view = document->view();
460     if (view)
461         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
462     else
463         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
464 
465     if (root)
466         m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
467 
468     if (m_rootDefaultStyle && view)
469         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
470 
471     m_authorStyle = adoptPtr(new RuleSet);
472     // Adding rules from multiple sheets, shrink at the end.
473     m_authorStyle->disableAutoShrinkToFit();
474 
475     // FIXME: This sucks! The user sheet is reparsed every time!
476     OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
477     if (pageUserSheet)
478         tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
479     if (pageGroupUserSheets) {
480         unsigned length = pageGroupUserSheets->size();
481         for (unsigned i = 0; i < length; i++) {
482             if (pageGroupUserSheets->at(i)->isUserStyleSheet())
483                 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
484             else
485                 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
486         }
487     }
488 
489     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
490         m_userStyle = tempUserStyle.release();
491 
492     // Add rules from elements like SVG's <font-face>
493     if (mappedElementSheet)
494         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
495 
496     // add stylesheets from document
497     unsigned length = styleSheets->length();
498     for (unsigned i = 0; i < length; i++) {
499         StyleSheet* sheet = styleSheets->item(i);
500         if (sheet->isCSSStyleSheet() && !sheet->disabled())
501             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
502     }
503     // Collect all ids and rules using sibling selectors (:first-child and similar)
504     // in the current set of stylesheets. Style sharing code uses this information to reject
505     // sharing candidates.
506     // Usually there are no sibling rules in the default style but the MathML sheet has some.
507     if (siblingRulesInDefaultStyle)
508         siblingRulesInDefaultStyle->collectFeatures(m_features);
509     m_authorStyle->collectFeatures(m_features);
510     if (m_userStyle)
511         m_userStyle->collectFeatures(m_features);
512 
513     m_authorStyle->shrinkToFit();
514     if (m_features.siblingRules)
515         m_features.siblingRules->shrinkToFit();
516 
517     if (document->renderer() && document->renderer()->style())
518         document->renderer()->style()->font().update(fontSelector());
519 }
520 
521 // This is a simplified style setting function for keyframe styles
addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)522 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
523 {
524     AtomicString s(rule->name());
525     m_keyframesRuleMap.add(s.impl(), rule);
526 }
527 
~CSSStyleSelector()528 CSSStyleSelector::~CSSStyleSelector()
529 {
530     m_fontSelector->clearDocument();
531     deleteAllValues(m_viewportDependentMediaQueryResults);
532 }
533 
Features()534 CSSStyleSelector::Features::Features()
535     : usesFirstLineRules(false)
536     , usesBeforeAfterRules(false)
537     , usesLinkRules(false)
538 {
539 }
540 
~Features()541 CSSStyleSelector::Features::~Features()
542 {
543 }
544 
parseUASheet(const String & str)545 static CSSStyleSheet* parseUASheet(const String& str)
546 {
547     CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
548     sheet->parseString(str);
549     return sheet;
550 }
551 
parseUASheet(const char * characters,unsigned size)552 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
553 {
554     return parseUASheet(String(characters, size));
555 }
556 
loadFullDefaultStyle()557 static void loadFullDefaultStyle()
558 {
559     if (simpleDefaultStyleSheet) {
560         ASSERT(defaultStyle);
561         delete defaultStyle;
562         simpleDefaultStyleSheet->deref();
563         defaultStyle = new RuleSet;
564         simpleDefaultStyleSheet = 0;
565     } else {
566         ASSERT(!defaultStyle);
567         defaultStyle = new RuleSet;
568         defaultPrintStyle = new RuleSet;
569         defaultQuirksStyle = new RuleSet;
570     }
571 
572     // Strict-mode rules.
573     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
574     CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
575     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
576     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
577 
578     // Quirks-mode rules.
579     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
580     CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
581     defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
582 }
583 
loadSimpleDefaultStyle()584 static void loadSimpleDefaultStyle()
585 {
586     ASSERT(!defaultStyle);
587     ASSERT(!simpleDefaultStyleSheet);
588 
589     defaultStyle = new RuleSet;
590     defaultPrintStyle = new RuleSet;
591     defaultQuirksStyle = new RuleSet;
592 
593     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
594     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
595 
596     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
597 }
598 
loadViewSourceStyle()599 static void loadViewSourceStyle()
600 {
601     ASSERT(!defaultViewSourceStyle);
602     defaultViewSourceStyle = new RuleSet;
603     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
604 }
605 
collectElementIdentifierHashes(const Element * element,Vector<unsigned,4> & identifierHashes)606 static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
607 {
608     identifierHashes.append(element->localName().impl()->existingHash());
609     if (element->hasID())
610         identifierHashes.append(element->idForStyleResolution().impl()->existingHash());
611     const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0;
612     if (styledElement && styledElement->hasClass()) {
613         const SpaceSplitString& classNames = styledElement->classNames();
614         size_t count = classNames.size();
615         for (size_t i = 0; i < count; ++i)
616             identifierHashes.append(classNames[i].impl()->existingHash());
617     }
618 }
619 
pushParentStackFrame(Element * parent)620 void CSSStyleSelector::pushParentStackFrame(Element* parent)
621 {
622     ASSERT(m_ancestorIdentifierFilter);
623     ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentElement());
624     ASSERT(!m_parentStack.isEmpty() || !parent->parentElement());
625     m_parentStack.append(ParentStackFrame(parent));
626     ParentStackFrame& parentFrame = m_parentStack.last();
627     // Mix tags, class names and ids into some sort of weird bouillabaisse.
628     // The filter is used for fast rejection of child and descendant selectors.
629     collectElementIdentifierHashes(parent, parentFrame.identifierHashes);
630     size_t count = parentFrame.identifierHashes.size();
631     for (size_t i = 0; i < count; ++i)
632         m_ancestorIdentifierFilter->add(parentFrame.identifierHashes[i]);
633 }
634 
popParentStackFrame()635 void CSSStyleSelector::popParentStackFrame()
636 {
637     ASSERT(!m_parentStack.isEmpty());
638     ASSERT(m_ancestorIdentifierFilter);
639     const ParentStackFrame& parentFrame = m_parentStack.last();
640     size_t count = parentFrame.identifierHashes.size();
641     for (size_t i = 0; i < count; ++i)
642         m_ancestorIdentifierFilter->remove(parentFrame.identifierHashes[i]);
643     m_parentStack.removeLast();
644     if (m_parentStack.isEmpty()) {
645         ASSERT(m_ancestorIdentifierFilter->likelyEmpty());
646         m_ancestorIdentifierFilter.clear();
647     }
648 }
649 
pushParent(Element * parent)650 void CSSStyleSelector::pushParent(Element* parent)
651 {
652     if (m_parentStack.isEmpty()) {
653         ASSERT(!m_ancestorIdentifierFilter);
654         m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>);
655         // If the element is not the root itself, build the stack starting from the root.
656         if (parent->parentElement()) {
657             Vector<Element*, 30> ancestors;
658             for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentElement())
659                 ancestors.append(ancestor);
660             int count = ancestors.size();
661             for (int n = count - 1; n >= 0; --n)
662                 pushParentStackFrame(ancestors[n]);
663             return;
664         }
665     } else if (!parent->parentElement()) {
666         // We are not always invoked consistently. For example, script execution can cause us to enter
667         // style recalc in the middle of tree building. Reset the stack if we see a new root element.
668         ASSERT(m_ancestorIdentifierFilter);
669         m_ancestorIdentifierFilter->clear();
670         m_parentStack.resize(0);
671     } else {
672         ASSERT(m_ancestorIdentifierFilter);
673         // We may get invoked for some random elements in some wacky cases during style resolve.
674         // Pause maintaining the stack in this case.
675         if (m_parentStack.last().element != parent->parentElement())
676             return;
677     }
678     pushParentStackFrame(parent);
679 }
680 
popParent(Element * parent)681 void CSSStyleSelector::popParent(Element* parent)
682 {
683     if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)
684         return;
685     popParentStackFrame();
686 }
687 
addMatchedDeclaration(CSSMutableStyleDeclaration * decl)688 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
689 {
690     m_matchedDecls.append(decl);
691 }
692 
matchRules(RuleSet * rules,int & firstRuleIndex,int & lastRuleIndex,bool includeEmptyRules)693 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
694 {
695     m_matchedRules.clear();
696 
697     if (!rules || !m_element)
698         return;
699 
700     // We need to collect the rules for id, class, tag, and everything else into a buffer and
701     // then sort the buffer.
702     if (m_element->hasID())
703         matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
704     if (m_element->hasClass()) {
705         ASSERT(m_styledElement);
706         const SpaceSplitString& classNames = m_styledElement->classNames();
707         size_t size = classNames.size();
708         for (size_t i = 0; i < size; ++i)
709             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
710     }
711     if (!m_element->shadowPseudoId().isEmpty()) {
712         ASSERT(m_styledElement);
713         matchRulesForList(rules->getPseudoRules(m_element->shadowPseudoId().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
714     }
715     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
716     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
717 
718     // If we didn't match any rules, we're done.
719     if (m_matchedRules.isEmpty())
720         return;
721 
722     // Sort the set of matched rules.
723     sortMatchedRules();
724 
725     // Now transfer the set of matched rules over to our list of decls.
726     if (!m_checker.m_collectRulesOnly) {
727         for (unsigned i = 0; i < m_matchedRules.size(); i++)
728             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
729     } else {
730         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
731             if (!m_ruleList)
732                 m_ruleList = CSSRuleList::create();
733             m_ruleList->append(m_matchedRules[i]->rule());
734         }
735     }
736 }
737 
fastRejectSelector(const RuleData & ruleData) const738 inline bool CSSStyleSelector::fastRejectSelector(const RuleData& ruleData) const
739 {
740     ASSERT(m_ancestorIdentifierFilter);
741     const unsigned* descendantSelectorIdentifierHashes = ruleData.descendantSelectorIdentifierHashes();
742     for (unsigned n = 0; n < RuleData::maximumIdentifierCount && descendantSelectorIdentifierHashes[n]; ++n) {
743         if (!m_ancestorIdentifierFilter->mayContain(descendantSelectorIdentifierHashes[n]))
744             return true;
745     }
746     return false;
747 }
748 
matchRulesForList(const Vector<RuleData> * rules,int & firstRuleIndex,int & lastRuleIndex,bool includeEmptyRules)749 void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
750 {
751     if (!rules)
752         return;
753     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
754     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
755     bool canUseFastReject = !m_parentStack.isEmpty() && m_parentStack.last().element == m_parentNode;
756 
757     unsigned size = rules->size();
758     for (unsigned i = 0; i < size; ++i) {
759         const RuleData& ruleData = rules->at(i);
760         if (canUseFastReject && fastRejectSelector(ruleData))
761             continue;
762         if (checkSelector(ruleData)) {
763             // If the rule has no properties to apply, then ignore it in the non-debug mode.
764             CSSStyleRule* rule = ruleData.rule();
765             CSSMutableStyleDeclaration* decl = rule->declaration();
766             if (!decl || (!decl->length() && !includeEmptyRules))
767                 continue;
768             if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
769                 continue;
770             // If we're matching normal rules, set a pseudo bit if
771             // we really just matched a pseudo-element.
772             if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) {
773                 if (m_checker.m_collectRulesOnly)
774                     continue;
775                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
776                     m_style->setHasPseudoStyle(m_dynamicPseudo);
777             } else {
778                 // Update our first/last rule indices in the matched rules array.
779                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
780                 if (firstRuleIndex == -1)
781                     firstRuleIndex = lastRuleIndex;
782 
783                 // Add this rule to our list of matched rules.
784                 addMatchedRule(&ruleData);
785             }
786         }
787     }
788 }
789 
compareRules(const RuleData * r1,const RuleData * r2)790 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
791 {
792     unsigned specificity1 = r1->specificity();
793     unsigned specificity2 = r2->specificity();
794     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
795 }
796 
sortMatchedRules()797 void CSSStyleSelector::sortMatchedRules()
798 {
799     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
800 }
801 
determineLinkState(Element * element) const802 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const
803 {
804     if (!element || !element->isLink())
805         return NotInsideLink;
806     return determineLinkStateSlowCase(element);
807 }
808 
initElement(Element * e)809 inline void CSSStyleSelector::initElement(Element* e)
810 {
811     if (m_element != e) {
812         m_element = e;
813         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
814         m_elementLinkState = m_checker.determineLinkState(m_element);
815         if (e && e == e->document()->documentElement()) {
816             e->document()->setDirectionSetOnDocumentElement(false);
817             e->document()->setWritingModeSetOnDocumentElement(false);
818         }
819     }
820 }
821 
initForStyleResolve(Element * e,RenderStyle * parentStyle,PseudoId pseudoID)822 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
823 {
824     m_checker.m_pseudoStyle = pseudoID;
825 
826     m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
827 
828     if (parentStyle)
829         m_parentStyle = parentStyle;
830     else
831         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
832 
833     Node* docElement = e ? e->document()->documentElement() : 0;
834     RenderStyle* docStyle = m_checker.m_document->renderStyle();
835     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
836 
837     m_style = 0;
838 
839     m_matchedDecls.clear();
840 
841     m_pendingImageProperties.clear();
842 
843     m_ruleList = 0;
844 
845     m_fontDirty = false;
846 }
847 
linkAttribute(Node * node)848 static inline const AtomicString* linkAttribute(Node* node)
849 {
850     if (!node->isLink())
851         return 0;
852 
853     ASSERT(node->isElementNode());
854     Element* element = static_cast<Element*>(node);
855     if (element->isHTMLElement())
856         return &element->fastGetAttribute(hrefAttr);
857 
858 #if ENABLE(WML)
859     if (element->isWMLElement()) {
860         // <anchor> elements don't have href attributes, but we still want to
861         // appear as link, so linkAttribute() has to return a non-null value!
862         if (element->hasTagName(WMLNames::anchorTag))
863             return &emptyAtom;
864 
865         return &element->fastGetAttribute(hrefAttr);
866     }
867 #endif
868 
869 #if ENABLE(SVG)
870     if (element->isSVGElement())
871         return &element->fastGetAttribute(XLinkNames::hrefAttr);
872 #endif
873 
874     return 0;
875 }
876 
SelectorChecker(Document * document,bool strictParsing)877 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
878     : m_document(document)
879     , m_strictParsing(strictParsing)
880     , m_collectRulesOnly(false)
881     , m_sameOriginOnly(false)
882     , m_pseudoStyle(NOPSEUDO)
883     , m_documentIsHTML(document->isHTMLDocument())
884     , m_matchVisitedPseudoClass(false)
885 {
886 }
887 
determineLinkStateSlowCase(Element * element) const888 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const
889 {
890     ASSERT(element->isLink());
891 
892     const AtomicString* attr = linkAttribute(element);
893     if (!attr || attr->isNull())
894         return NotInsideLink;
895 
896 #if PLATFORM(QT)
897     Vector<UChar, 512> url;
898     visitedURL(m_document->baseURL(), *attr, url);
899     if (url.isEmpty())
900         return InsideUnvisitedLink;
901 
902     // If the Qt4.4 interface for the history is used, we will have to fallback
903     // to the old global history.
904     QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface();
905     if (iface)
906         return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink;
907 
908     LinkHash hash = visitedLinkHash(url.data(), url.size());
909     if (!hash)
910         return InsideUnvisitedLink;
911 #else
912     LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr);
913     if (!hash)
914         return InsideUnvisitedLink;
915 #endif
916 
917     Frame* frame = m_document->frame();
918     if (!frame)
919         return InsideUnvisitedLink;
920 
921     Page* page = frame->page();
922     if (!page)
923         return InsideUnvisitedLink;
924 
925     m_linksCheckedForVisitedState.add(hash);
926 
927 #if USE(PLATFORM_STRATEGIES)
928     return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink;
929 #else
930     return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
931 #endif
932 }
933 
checkSelector(CSSSelector * sel,Element * element) const934 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
935 {
936     PseudoId dynamicPseudo = NOPSEUDO;
937     return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches;
938 }
939 
940 static const unsigned cStyleSearchThreshold = 10;
941 static const unsigned cStyleSearchLevelThreshold = 10;
942 
locateCousinList(Element * parent,unsigned & visitedNodeCount) const943 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
944 {
945     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
946         return 0;
947     if (!parent || !parent->isStyledElement())
948         return 0;
949     StyledElement* p = static_cast<StyledElement*>(parent);
950     if (p->inlineStyleDecl())
951         return 0;
952     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
953         return 0;
954 
955     RenderStyle* parentStyle = p->renderStyle();
956     unsigned subcount = 0;
957     Node* thisCousin = p;
958     Node* currentNode = p->previousSibling();
959 
960     // Reserve the tries for this level. This effectively makes sure that the algorithm
961     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
962     visitedNodeCount += cStyleSearchThreshold;
963     while (thisCousin) {
964         while (currentNode) {
965             ++subcount;
966             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
967                 // Adjust for unused reserved tries.
968                 visitedNodeCount -= cStyleSearchThreshold - subcount;
969                 return currentNode->lastChild();
970             }
971             if (subcount >= cStyleSearchThreshold)
972                 return 0;
973             currentNode = currentNode->previousSibling();
974         }
975         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
976         thisCousin = currentNode;
977     }
978 
979     return 0;
980 }
981 
matchesSiblingRules()982 bool CSSStyleSelector::matchesSiblingRules()
983 {
984     int firstSiblingRule = -1, lastSiblingRule = -1;
985     matchRules(m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false);
986     if (m_matchedDecls.isEmpty())
987         return false;
988     m_matchedDecls.clear();
989     return true;
990 }
991 
canShareStyleWithElement(Node * node) const992 bool CSSStyleSelector::canShareStyleWithElement(Node* node) const
993 {
994     if (!node->isStyledElement())
995         return false;
996 
997     StyledElement* element = static_cast<StyledElement*>(node);
998     RenderStyle* style = element->renderStyle();
999 
1000     if (!style)
1001         return false;
1002     if (style->unique())
1003         return false;
1004     if (element->tagQName() != m_element->tagQName())
1005         return false;
1006     if (element->hasClass() != m_element->hasClass())
1007         return false;
1008     if (element->inlineStyleDecl())
1009         return false;
1010     if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
1011         return false;
1012     if (element->isLink() != m_element->isLink())
1013         return false;
1014     if (style->affectedByAttributeSelectors())
1015         return false;
1016     if (element->hovered() != m_element->hovered())
1017         return false;
1018     if (element->active() != m_element->active())
1019         return false;
1020     if (element->focused() != m_element->focused())
1021         return false;
1022     if (element->shadowPseudoId() != m_element->shadowPseudoId())
1023         return false;
1024     if (element == element->document()->cssTarget())
1025         return false;
1026     if (m_element == m_element->document()->cssTarget())
1027         return false;
1028     if (element->fastGetAttribute(typeAttr) != m_element->fastGetAttribute(typeAttr))
1029         return false;
1030     if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1031         return false;
1032     if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1033         return false;
1034     if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1035         return false;
1036     if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1037         return false;
1038 
1039     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1040         return false;
1041 
1042     bool isControl = element->isFormControlElement();
1043 
1044     if (isControl != m_element->isFormControlElement())
1045         return false;
1046 
1047     if (isControl) {
1048         InputElement* thisInputElement = element->toInputElement();
1049         InputElement* otherInputElement = m_element->toInputElement();
1050 
1051         if (!thisInputElement || !otherInputElement)
1052             return false;
1053 
1054         if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1055             return false;
1056         if (thisInputElement->isChecked() != otherInputElement->isChecked())
1057             return false;
1058         if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1059             return false;
1060 
1061         if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1062             return false;
1063 
1064         if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1065             return false;
1066 
1067         if (!m_element->document()->containsValidityStyleRules())
1068             return false;
1069 
1070         bool willValidate = element->willValidate();
1071 
1072         if (willValidate != m_element->willValidate())
1073             return false;
1074 
1075         if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1076             return false;
1077 
1078         if (element->isInRange() != m_element->isInRange())
1079             return false;
1080 
1081         if (element->isOutOfRange() != m_element->isOutOfRange())
1082             return false;
1083     }
1084 
1085     if (style->transitions() || style->animations())
1086         return false;
1087 
1088 #if USE(ACCELERATED_COMPOSITING)
1089     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1090     // See comments in RenderObject::setStyle().
1091     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag))
1092         return false;
1093 #endif
1094 
1095     if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
1096         return false;
1097 
1098     if (element->hasClass() && m_element->fastGetAttribute(classAttr) != element->fastGetAttribute(classAttr))
1099         return false;
1100 
1101     if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
1102         return false;
1103 
1104     if (element->isLink() && m_elementLinkState != style->insideLink())
1105         return false;
1106 
1107     return true;
1108 }
1109 
findSiblingForStyleSharing(Node * node,unsigned & count) const1110 inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
1111 {
1112     for (; node; node = node->previousSibling()) {
1113         if (!node->isElementNode())
1114             continue;
1115         if (canShareStyleWithElement(node))
1116             break;
1117         if (count++ == cStyleSearchThreshold)
1118             return 0;
1119     }
1120     return node;
1121 }
1122 
parentStylePreventsSharing(const RenderStyle * parentStyle)1123 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1124 {
1125     return parentStyle->childrenAffectedByPositionalRules()
1126         || parentStyle->childrenAffectedByFirstChildRules()
1127         || parentStyle->childrenAffectedByLastChildRules()
1128         || parentStyle->childrenAffectedByDirectAdjacentRules();
1129 }
1130 
locateSharedStyle()1131 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
1132 {
1133     if (!m_styledElement || !m_parentStyle)
1134         return 0;
1135     // If the element has inline style it is probably unique.
1136     if (m_styledElement->inlineStyleDecl())
1137         return 0;
1138     // Ids stop style sharing if they show up in the stylesheets.
1139     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1140         return 0;
1141     if (parentStylePreventsSharing(m_parentStyle))
1142         return 0;
1143 
1144     // Check previous siblings and their cousins.
1145     unsigned count = 0;
1146     unsigned visitedNodeCount = 0;
1147     Node* shareNode = 0;
1148     Node* cousinList = m_styledElement->previousSibling();
1149     while (cousinList) {
1150         shareNode = findSiblingForStyleSharing(cousinList, count);
1151         if (shareNode)
1152             break;
1153         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1154     }
1155 
1156     // If we have exhausted all our budget or our cousins.
1157     if (!shareNode)
1158         return 0;
1159 
1160     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1161     if (matchesSiblingRules())
1162         return 0;
1163     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1164     if (parentStylePreventsSharing(m_parentStyle))
1165         return 0;
1166     return shareNode->renderStyle();
1167 }
1168 
matchUARules(int & firstUARule,int & lastUARule)1169 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
1170 {
1171     // First we match rules from the user agent sheet.
1172     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1173         ? defaultPrintStyle : defaultStyle;
1174     matchRules(userAgentStyleSheet, firstUARule, lastUARule, false);
1175 
1176     // In quirks mode, we match rules from the quirks user agent sheet.
1177     if (!m_checker.m_strictParsing)
1178         matchRules(defaultQuirksStyle, firstUARule, lastUARule, false);
1179 
1180     // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
1181     if (m_checker.m_document->usesViewSourceStyles()) {
1182         if (!defaultViewSourceStyle)
1183             loadViewSourceStyle();
1184         matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false);
1185     }
1186 }
1187 
styleForDocument(Document * document)1188 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1189 {
1190     Frame* frame = document->frame();
1191 
1192     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1193     documentStyle->setDisplay(BLOCK);
1194     documentStyle->setVisuallyOrdered(document->visuallyOrdered());
1195     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1196     documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1);
1197 
1198     Element* docElement = document->documentElement();
1199     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1200     if (docElementRenderer) {
1201         // Use the direction and writing-mode of the body to set the
1202         // viewport's direction and writing-mode unless the property is set on the document element.
1203         // If there is no body, then use the document element.
1204         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1205         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1206             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1207         else
1208             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1209         if (bodyRenderer && !document->directionSetOnDocumentElement())
1210             documentStyle->setDirection(bodyRenderer->style()->direction());
1211         else
1212             documentStyle->setDirection(docElementRenderer->style()->direction());
1213     }
1214 
1215     FontDescription fontDescription;
1216     fontDescription.setUsePrinterFont(document->printing());
1217     if (Settings* settings = document->settings()) {
1218         fontDescription.setRenderingMode(settings->fontRenderingMode());
1219         if (document->printing() && !settings->shouldPrintBackgrounds())
1220             documentStyle->setForceBackgroundsToWhite(true);
1221         const AtomicString& stdfont = settings->standardFontFamily();
1222         if (!stdfont.isEmpty()) {
1223             fontDescription.firstFamily().setFamily(stdfont);
1224             fontDescription.firstFamily().appendFamily(0);
1225         }
1226         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1227         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1228         fontDescription.setSpecifiedSize(size);
1229         bool useSVGZoomRules = document->isSVGDocument();
1230         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1231     }
1232 
1233     documentStyle->setFontDescription(fontDescription);
1234     documentStyle->font().update(0);
1235 
1236     return documentStyle.release();
1237 }
1238 
1239 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1240 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1241 
styleForElement(Element * e,RenderStyle * defaultParent,bool allowSharing,bool resolveForRootDefault,bool matchVisitedPseudoClass)1242 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass)
1243 {
1244     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1245     // will vanish if a style recalc happens during loading.
1246     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
1247         if (!s_styleNotYetAvailable) {
1248             s_styleNotYetAvailable = RenderStyle::create().releaseRef();
1249             s_styleNotYetAvailable->ref();
1250             s_styleNotYetAvailable->setDisplay(NONE);
1251             s_styleNotYetAvailable->font().update(m_fontSelector);
1252         }
1253         s_styleNotYetAvailable->ref();
1254         e->document()->setHasNodesWithPlaceholderStyle();
1255         return s_styleNotYetAvailable;
1256     }
1257 
1258     initElement(e);
1259     initForStyleResolve(e, defaultParent);
1260     if (allowSharing) {
1261         RenderStyle* sharedStyle = locateSharedStyle();
1262         if (sharedStyle)
1263             return sharedStyle;
1264     }
1265 
1266     // Compute our style allowing :visited to match first.
1267     RefPtr<RenderStyle> visitedStyle;
1268     if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) {
1269         // Fetch our parent style.
1270         RenderStyle* parentStyle = m_parentStyle;
1271         if (!e->isLink()) {
1272             // Use the parent's visited style if one exists.
1273             RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK);
1274             if (parentVisitedStyle)
1275                 parentStyle = parentVisitedStyle;
1276         }
1277         visitedStyle = styleForElement(e, parentStyle, false, false, true);
1278         initForStyleResolve(e, defaultParent);
1279     }
1280 
1281     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1282 
1283     m_style = RenderStyle::create();
1284 
1285     if (m_parentStyle)
1286         m_style->inheritFrom(m_parentStyle);
1287     else
1288         m_parentStyle = style();
1289 
1290     if (e->isLink()) {
1291         m_style->setIsLink(true);
1292         m_style->setInsideLink(m_elementLinkState);
1293     }
1294 
1295     if (visitedStyle) {
1296         // Copy any pseudo bits that the visited style has to the primary style so that
1297         // pseudo element styles will continue to work for pseudo elements inside :visited
1298         // links.
1299         for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) {
1300             if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo)))
1301                 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo));
1302         }
1303         if (m_elementLinkState == InsideUnvisitedLink)
1304             visitedStyle = 0;  // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it.
1305         else
1306             visitedStyle->setStyleType(VISITED_LINK);
1307     }
1308 
1309     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) {
1310         loadFullDefaultStyle();
1311         assertNoSiblingRulesInDefaultStyle();
1312     }
1313 
1314 #if ENABLE(SVG)
1315     static bool loadedSVGUserAgentSheet;
1316     if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
1317         // SVG rules.
1318         loadedSVGUserAgentSheet = true;
1319         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
1320         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
1321         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
1322         assertNoSiblingRulesInDefaultStyle();
1323     }
1324 #endif
1325 
1326 #if ENABLE(MATHML)
1327     static bool loadedMathMLUserAgentSheet;
1328     if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) {
1329         // MathML rules.
1330         loadedMathMLUserAgentSheet = true;
1331         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
1332         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
1333         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
1334         // There are some sibling rules here.
1335         collectSiblingRulesInDefaultStyle();
1336     }
1337 #endif
1338 
1339 #if ENABLE(WML)
1340     static bool loadedWMLUserAgentSheet;
1341     if (e->isWMLElement() && !loadedWMLUserAgentSheet) {
1342         // WML rules.
1343         loadedWMLUserAgentSheet = true;
1344         CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
1345         defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
1346         defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
1347         assertNoSiblingRulesInDefaultStyle();
1348     }
1349 #endif
1350 
1351 #if ENABLE(VIDEO)
1352     static bool loadedMediaStyleSheet;
1353     if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) {
1354         loadedMediaStyleSheet = true;
1355         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(e->document()->page())->extraMediaControlsStyleSheet();
1356         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
1357         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
1358         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
1359         assertNoSiblingRulesInDefaultStyle();
1360     }
1361 #endif
1362 
1363 #if ENABLE(FULLSCREEN_API)
1364     static bool loadedFullScreenStyleSheet;
1365     if (!loadedFullScreenStyleSheet && e->document()->webkitIsFullScreen()) {
1366         loadedFullScreenStyleSheet = true;
1367         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
1368         CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
1369         defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
1370         defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
1371     }
1372 #endif
1373 
1374     int firstUARule = -1, lastUARule = -1;
1375     int firstUserRule = -1, lastUserRule = -1;
1376     int firstAuthorRule = -1, lastAuthorRule = -1;
1377     matchUARules(firstUARule, lastUARule);
1378 
1379     if (!resolveForRootDefault) {
1380         // 4. Now we check user sheet rules.
1381         if (m_matchAuthorAndUserStyles)
1382             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1383 
1384         // 5. Now check author rules, beginning first with presentational attributes
1385         // mapped from HTML.
1386         if (m_styledElement) {
1387             // Ask if the HTML element has mapped attributes.
1388             if (m_styledElement->hasMappedAttributes()) {
1389                 // Walk our attribute list and add in each decl.
1390                 const NamedNodeMap* map = m_styledElement->attributeMap();
1391                 for (unsigned i = 0; i < map->length(); i++) {
1392                     Attribute* attr = map->attributeItem(i);
1393                     if (attr->isMappedAttribute() && attr->decl()) {
1394                         lastAuthorRule = m_matchedDecls.size();
1395                         if (firstAuthorRule == -1)
1396                             firstAuthorRule = lastAuthorRule;
1397                         addMatchedDeclaration(attr->decl());
1398                     }
1399                 }
1400             }
1401 
1402             // Now we check additional mapped declarations.
1403             // Tables and table cells share an additional mapped rule that must be applied
1404             // after all attributes, since their mapped style depends on the values of multiple attributes.
1405             if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
1406                 m_additionalAttributeStyleDecls.clear();
1407                 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
1408                 if (!m_additionalAttributeStyleDecls.isEmpty()) {
1409                     unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
1410                     if (firstAuthorRule == -1)
1411                         firstAuthorRule = m_matchedDecls.size();
1412                     lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
1413                     for (unsigned i = 0; i < additionalDeclsSize; i++)
1414                         addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
1415                 }
1416             }
1417             if (m_styledElement->isHTMLElement()) {
1418                 bool isAuto;
1419                 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
1420                 if (isAuto)
1421                     addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
1422             }
1423         }
1424 
1425         // 6. Check the rules in author sheets next.
1426         if (m_matchAuthorAndUserStyles)
1427             matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1428 
1429         // 7. Now check our inline style attribute.
1430         if (m_matchAuthorAndUserStyles && m_styledElement) {
1431             CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
1432             if (inlineDecl) {
1433                 lastAuthorRule = m_matchedDecls.size();
1434                 if (firstAuthorRule == -1)
1435                     firstAuthorRule = lastAuthorRule;
1436                 addMatchedDeclaration(inlineDecl);
1437             }
1438         }
1439     }
1440 
1441     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1442     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1443 
1444     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
1445     // high-priority properties first, i.e., those properties that other properties depend on.
1446     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1447     // and (4) normal important.
1448     m_lineHeightValue = 0;
1449     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1450     if (!resolveForRootDefault) {
1451         applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1452         applyDeclarations<true>(true, firstUserRule, lastUserRule);
1453     }
1454     applyDeclarations<true>(true, firstUARule, lastUARule);
1455 
1456     // If our font got dirtied, go ahead and update it now.
1457     if (m_fontDirty)
1458         updateFont();
1459 
1460     // Line-height is set when we are sure we decided on the font-size
1461     if (m_lineHeightValue)
1462         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1463 
1464     // Now do the normal priority UA properties.
1465     applyDeclarations<false>(false, firstUARule, lastUARule);
1466 
1467     // Cache our border and background so that we can examine them later.
1468     cacheBorderAndBackground();
1469 
1470     // Now do the author and user normal priority properties and all the !important properties.
1471     if (!resolveForRootDefault) {
1472         applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1473         applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1474         applyDeclarations<false>(true, firstUserRule, lastUserRule);
1475     }
1476     applyDeclarations<false>(true, firstUARule, lastUARule);
1477 
1478     ASSERT(!m_fontDirty);
1479     // If our font got dirtied by one of the non-essential font props,
1480     // go ahead and update it a second time.
1481     if (m_fontDirty)
1482         updateFont();
1483 
1484     // Clean up our style object's display and text decorations (among other fixups).
1485     adjustRenderStyle(style(), m_parentStyle, e);
1486 
1487     // Start loading images referenced by this style.
1488     loadPendingImages();
1489 
1490     // If we have first-letter pseudo style, do not share this style
1491     if (m_style->hasPseudoStyle(FIRST_LETTER))
1492         m_style->setUnique();
1493 
1494     if (visitedStyle) {
1495         // Add the visited style off the main style.
1496         m_style->addCachedPseudoStyle(visitedStyle.release());
1497     }
1498 
1499     if (!matchVisitedPseudoClass)
1500         initElement(0); // Clear out for the next resolve.
1501 
1502     // Now return the style.
1503     return m_style.release();
1504 }
1505 
styleForKeyframe(const RenderStyle * elementStyle,const WebKitCSSKeyframeRule * keyframeRule,KeyframeValue & keyframe)1506 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1507 {
1508     if (keyframeRule->style())
1509         addMatchedDeclaration(keyframeRule->style());
1510 
1511     ASSERT(!m_style);
1512 
1513     // Create the style
1514     m_style = RenderStyle::clone(elementStyle);
1515 
1516     m_lineHeightValue = 0;
1517 
1518     // We don't need to bother with !important. Since there is only ever one
1519     // decl, there's nothing to override. So just add the first properties.
1520     if (keyframeRule->style())
1521         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1522 
1523     // If our font got dirtied, go ahead and update it now.
1524     if (m_fontDirty)
1525         updateFont();
1526 
1527     // Line-height is set when we are sure we decided on the font-size
1528     if (m_lineHeightValue)
1529         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1530 
1531     // Now do rest of the properties.
1532     if (keyframeRule->style())
1533         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1534 
1535     // If our font got dirtied by one of the non-essential font props,
1536     // go ahead and update it a second time.
1537     if (m_fontDirty)
1538         updateFont();
1539 
1540     // Start loading images referenced by this style.
1541     loadPendingImages();
1542 
1543     // Add all the animating properties to the keyframe.
1544     if (keyframeRule->style()) {
1545         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1546         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1547             int property = (*it).id();
1548             // Timing-function within keyframes is special, because it is not animated; it just
1549             // describes the timing function between this keyframe and the next.
1550             if (property != CSSPropertyWebkitAnimationTimingFunction)
1551                 keyframe.addProperty(property);
1552         }
1553     }
1554 
1555     return m_style.release();
1556 }
1557 
keyframeStylesForAnimation(Element * e,const RenderStyle * elementStyle,KeyframeList & list)1558 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1559 {
1560     list.clear();
1561 
1562     // Get the keyframesRule for this name
1563     if (!e || list.animationName().isEmpty())
1564         return;
1565 
1566     m_keyframesRuleMap.checkConsistency();
1567 
1568     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1569         return;
1570 
1571     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1572 
1573     // Construct and populate the style for each keyframe
1574     for (unsigned i = 0; i < rule->length(); ++i) {
1575         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1576         initElement(e);
1577         initForStyleResolve(e);
1578 
1579         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1580 
1581         KeyframeValue keyframe(0, 0);
1582         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1583 
1584         // Add this keyframe style to all the indicated key times
1585         Vector<float> keys;
1586         keyframeRule->getKeys(keys);
1587         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1588             keyframe.setKey(keys[keyIndex]);
1589             list.insert(keyframe);
1590         }
1591     }
1592 
1593     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1594     int initialListSize = list.size();
1595     if (initialListSize > 0 && list[0].key() != 0) {
1596         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1597         keyframeRule->setKeyText("0%");
1598         KeyframeValue keyframe(0, 0);
1599         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1600         list.insert(keyframe);
1601     }
1602 
1603     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1604     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1605         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1606         keyframeRule->setKeyText("100%");
1607         KeyframeValue keyframe(1, 0);
1608         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1609         list.insert(keyframe);
1610     }
1611 }
1612 
pseudoStyleForElement(PseudoId pseudo,Element * e,RenderStyle * parentStyle,bool matchVisitedPseudoClass)1613 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass)
1614 {
1615     if (!e)
1616         return 0;
1617 
1618     initElement(e);
1619 
1620     // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it
1621     // off of.
1622     RefPtr<RenderStyle> visitedStyle;
1623     if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) {
1624         // Fetch our parent style with :visited in effect.
1625         RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK);
1626         visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true);
1627         if (visitedStyle)
1628             visitedStyle->setStyleType(VISITED_LINK);
1629     }
1630 
1631     initForStyleResolve(e, parentStyle, pseudo);
1632     m_style = RenderStyle::create();
1633     if (parentStyle)
1634         m_style->inheritFrom(parentStyle);
1635 
1636     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1637 
1638     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1639     // those rules.
1640 
1641     // Check UA, user and author rules.
1642     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
1643     matchUARules(firstUARule, lastUARule);
1644 
1645     if (m_matchAuthorAndUserStyles) {
1646         matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1647         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1648     }
1649 
1650     if (m_matchedDecls.isEmpty() && !visitedStyle)
1651         return 0;
1652 
1653     m_style->setStyleType(pseudo);
1654 
1655     m_lineHeightValue = 0;
1656 
1657     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1658     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1659 
1660     // High-priority properties.
1661     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1662     applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1663     applyDeclarations<true>(true, firstUserRule, lastUserRule);
1664     applyDeclarations<true>(true, firstUARule, lastUARule);
1665 
1666     // If our font got dirtied, go ahead and update it now.
1667     if (m_fontDirty)
1668         updateFont();
1669 
1670     // Line-height is set when we are sure we decided on the font-size
1671     if (m_lineHeightValue)
1672         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1673 
1674     // Now do the normal priority properties.
1675     applyDeclarations<false>(false, firstUARule, lastUARule);
1676 
1677     // Cache our border and background so that we can examine them later.
1678     cacheBorderAndBackground();
1679 
1680     applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1681     applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1682     applyDeclarations<false>(true, firstUserRule, lastUserRule);
1683     applyDeclarations<false>(true, firstUARule, lastUARule);
1684 
1685     // If our font got dirtied by one of the non-essential font props,
1686     // go ahead and update it a second time.
1687     if (m_fontDirty)
1688         updateFont();
1689 
1690     // Clean up our style object's display and text decorations (among other fixups).
1691     adjustRenderStyle(style(), parentStyle, 0);
1692 
1693     // Start loading images referenced by this style.
1694     loadPendingImages();
1695 
1696     // Hang our visited style off m_style.
1697     if (visitedStyle)
1698         m_style->addCachedPseudoStyle(visitedStyle.release());
1699 
1700     // Now return the style.
1701     return m_style.release();
1702 }
1703 
styleForPage(int pageIndex)1704 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1705 {
1706     initForStyleResolve(m_checker.m_document->documentElement()); // m_rootElementStyle will be set to the document style.
1707 
1708     m_style = RenderStyle::create();
1709     m_style->inheritFrom(m_rootElementStyle);
1710 
1711     const bool isLeft = isLeftPage(pageIndex);
1712     const bool isFirst = isFirstPage(pageIndex);
1713     const String page = pageName(pageIndex);
1714     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1715     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1716     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1717     m_lineHeightValue = 0;
1718     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1719 
1720     // If our font got dirtied, go ahead and update it now.
1721     if (m_fontDirty)
1722         updateFont();
1723 
1724     // Line-height is set when we are sure we decided on the font-size
1725     if (m_lineHeightValue)
1726         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1727 
1728     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1729 
1730     // Start loading images referenced by this style.
1731     loadPendingImages();
1732 
1733     // Now return the style.
1734     return m_style.release();
1735 }
1736 
1737 #if ENABLE(DATAGRID)
1738 
pseudoStyleForDataGridColumn(DataGridColumn *,RenderStyle *)1739 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*)
1740 {
1741     // FIXME: Implement
1742     return 0;
1743 }
1744 
pseudoStyleForDataGridColumnHeader(DataGridColumn *,RenderStyle *)1745 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*)
1746 {
1747     // FIXME: Implement
1748     return 0;
1749 }
1750 
1751 #endif
1752 
addIntrinsicMargins(RenderStyle * style)1753 static void addIntrinsicMargins(RenderStyle* style)
1754 {
1755     // Intrinsic margin value.
1756     const int intrinsicMargin = 2 * style->effectiveZoom();
1757 
1758     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1759     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1760     if (style->width().isIntrinsicOrAuto()) {
1761         if (style->marginLeft().quirk())
1762             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1763         if (style->marginRight().quirk())
1764             style->setMarginRight(Length(intrinsicMargin, Fixed));
1765     }
1766 
1767     if (style->height().isAuto()) {
1768         if (style->marginTop().quirk())
1769             style->setMarginTop(Length(intrinsicMargin, Fixed));
1770         if (style->marginBottom().quirk())
1771             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1772     }
1773 }
1774 
isAtShadowBoundary(Element * element)1775 static inline bool isAtShadowBoundary(Element* element)
1776 {
1777     if (!element)
1778         return false;
1779 
1780     ContainerNode* parentNode = element->parentNode();
1781     return parentNode && parentNode->isShadowBoundary();
1782 }
1783 
adjustRenderStyle(RenderStyle * style,RenderStyle * parentStyle,Element * e)1784 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1785 {
1786     // Cache our original display.
1787     style->setOriginalDisplay(style->display());
1788 
1789     if (style->display() != NONE) {
1790         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1791         // property.
1792         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1793         // these tags to retain their display types.
1794         if (!m_checker.m_strictParsing && e) {
1795             if (e->hasTagName(tdTag)) {
1796                 style->setDisplay(TABLE_CELL);
1797                 style->setFloating(FNONE);
1798             }
1799             else if (e->hasTagName(tableTag))
1800                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1801         }
1802 
1803         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1804             if (style->whiteSpace() == KHTML_NOWRAP) {
1805                 // Figure out if we are really nowrapping or if we should just
1806                 // use normal instead.  If the width of the cell is fixed, then
1807                 // we don't actually use NOWRAP.
1808                 if (style->width().isFixed())
1809                     style->setWhiteSpace(NORMAL);
1810                 else
1811                     style->setWhiteSpace(NOWRAP);
1812             }
1813         }
1814 
1815         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1816         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1817             style->setTextAlign(TAAUTO);
1818 
1819         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1820         // fix a crash where a site tries to position these objects.  They also never honor display.
1821         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1822             style->setPosition(StaticPosition);
1823             style->setDisplay(BLOCK);
1824         }
1825 
1826         // Table headers with a text-align of auto will change the text-align to center.
1827         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1828             style->setTextAlign(CENTER);
1829 
1830         if (e && e->hasTagName(legendTag))
1831             style->setDisplay(BLOCK);
1832 
1833         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1834         // position or float an inline, compact, or run-in.  Cache the original display, since it
1835         // may be needed for positioned elements that have to compute their static normal flow
1836         // positions.  We also force inline-level roots to be block-level.
1837         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1838             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1839              (e && e->document()->documentElement() == e))) {
1840             if (style->display() == INLINE_TABLE)
1841                 style->setDisplay(TABLE);
1842             else if (style->display() == INLINE_BOX)
1843                 style->setDisplay(BOX);
1844             else if (style->display() == LIST_ITEM) {
1845                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1846                 // but only in quirks mode.
1847                 if (!m_checker.m_strictParsing && style->floating() != FNONE)
1848                     style->setDisplay(BLOCK);
1849             }
1850             else
1851                 style->setDisplay(BLOCK);
1852         }
1853 
1854         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1855         // clear how that should work.
1856         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1857             style->setDisplay(INLINE_BLOCK);
1858 
1859         // After performing the display mutation, check table rows.  We do not honor position:relative on
1860         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1861         // on some sites).
1862         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1863              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1864              style->position() == RelativePosition)
1865             style->setPosition(StaticPosition);
1866 
1867         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1868         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1869         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1870             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1871             || style->display() == TABLE_CELL)
1872             style->setWritingMode(parentStyle->writingMode());
1873 
1874         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1875         // of block-flow to anything other than TopToBottomWritingMode.
1876         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1877         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1878             style->setWritingMode(TopToBottomWritingMode);
1879     }
1880 
1881     // Make sure our z-index value is only applied if the object is positioned.
1882     if (style->position() == StaticPosition)
1883         style->setHasAutoZIndex();
1884 
1885     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1886     // cases where objects that should be blended as a single unit end up with a non-transparent
1887     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1888     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f ||
1889         style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect()))
1890         style->setZIndex(0);
1891 
1892 #if ENABLE(WML)
1893     if (e && (e->hasTagName(WMLNames::insertedLegendTag)
1894               || e->hasTagName(WMLNames::inputTag))
1895             && style->width().isAuto())
1896         style->setWidth(Length(Intrinsic));
1897 #endif
1898 
1899     // Textarea considers overflow visible as auto.
1900     if (e && e->hasTagName(textareaTag)) {
1901         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1902         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1903     }
1904 
1905     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1906     // tables, inline blocks, inline tables, run-ins, or shadow DOM.
1907     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1908         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
1909         style->setTextDecorationsInEffect(style->textDecoration());
1910     else
1911         style->addToTextDecorationsInEffect(style->textDecoration());
1912 
1913     // If either overflow value is not visible, change to auto.
1914     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1915         style->setOverflowY(OMARQUEE);
1916     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1917         style->setOverflowX(OMARQUEE);
1918     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1919         style->setOverflowX(OAUTO);
1920     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1921         style->setOverflowY(OAUTO);
1922 
1923     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1924     // FIXME: Eventually table sections will support auto and scroll.
1925     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1926         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1927         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1928             style->setOverflowX(OVISIBLE);
1929         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1930             style->setOverflowY(OVISIBLE);
1931     }
1932 
1933     // Menulists should have visible overflow
1934     if (style->appearance() == MenulistPart) {
1935         style->setOverflowX(OVISIBLE);
1936         style->setOverflowY(OVISIBLE);
1937     }
1938 
1939     // Cull out any useless layers and also repeat patterns into additional layers.
1940     style->adjustBackgroundLayers();
1941     style->adjustMaskLayers();
1942 
1943     // Do the same for animations and transitions.
1944     style->adjustAnimations();
1945     style->adjustTransitions();
1946 
1947     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1948     // alter fonts and heights/widths.
1949     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1950         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1951         // so we have to treat all image buttons as though they were explicitly sized.
1952         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1953             addIntrinsicMargins(style);
1954     }
1955 
1956     // Let the theme also have a crack at adjusting the style.
1957     if (style->hasAppearance())
1958         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1959 
1960 #if ENABLE(SVG)
1961     if (e && e->isSVGElement()) {
1962         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1963         if (style->overflowY() == OSCROLL)
1964             style->setOverflowY(OHIDDEN);
1965         else if (style->overflowY() == OAUTO)
1966             style->setOverflowY(OVISIBLE);
1967 
1968         if (style->overflowX() == OSCROLL)
1969             style->setOverflowX(OHIDDEN);
1970         else if (style->overflowX() == OAUTO)
1971             style->setOverflowX(OVISIBLE);
1972 
1973         // Only the root <svg> element in an SVG document fragment tree honors css position
1974         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1975             style->setPosition(RenderStyle::initialPosition());
1976     }
1977 #endif
1978 }
1979 
updateFont()1980 void CSSStyleSelector::updateFont()
1981 {
1982     checkForTextSizeAdjust();
1983     checkForGenericFamilyChange(style(), m_parentStyle);
1984     checkForZoomChange(style(), m_parentStyle);
1985     m_style->font().update(m_fontSelector);
1986     m_fontDirty = false;
1987 }
1988 
cacheBorderAndBackground()1989 void CSSStyleSelector::cacheBorderAndBackground()
1990 {
1991     m_hasUAAppearance = m_style->hasAppearance();
1992     if (m_hasUAAppearance) {
1993         m_borderData = m_style->border();
1994         m_backgroundData = *m_style->backgroundLayers();
1995         m_backgroundColor = m_style->backgroundColor();
1996     }
1997 }
1998 
styleRulesForElement(Element * e,bool authorOnly,bool includeEmptyRules,CSSRuleFilter filter)1999 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
2000 {
2001     return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly, includeEmptyRules, filter);
2002 }
2003 
pseudoStyleRulesForElement(Element * e,PseudoId pseudoId,bool authorOnly,bool includeEmptyRules,CSSRuleFilter filter)2004 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter)
2005 {
2006     if (!e || !e->document()->haveStylesheetsLoaded())
2007         return 0;
2008 
2009     m_checker.m_collectRulesOnly = true;
2010 
2011     initElement(e);
2012     initForStyleResolve(e, 0, pseudoId);
2013 
2014     if (!authorOnly) {
2015         int firstUARule = -1, lastUARule = -1;
2016         // First we match rules from the user agent sheet.
2017         matchUARules(firstUARule, lastUARule);
2018 
2019         // Now we check user sheet rules.
2020         if (m_matchAuthorAndUserStyles) {
2021             int firstUserRule = -1, lastUserRule = -1;
2022             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, includeEmptyRules);
2023         }
2024     }
2025 
2026     if (m_matchAuthorAndUserStyles) {
2027         m_checker.m_sameOriginOnly = (filter == SameOriginCSSRulesOnly);
2028 
2029         // Check the rules in author sheets.
2030         int firstAuthorRule = -1, lastAuthorRule = -1;
2031         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, includeEmptyRules);
2032 
2033         m_checker.m_sameOriginOnly = false;
2034     }
2035 
2036     m_checker.m_collectRulesOnly = false;
2037 
2038     return m_ruleList.release();
2039 }
2040 
checkSelector(const RuleData & ruleData)2041 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
2042 {
2043     m_dynamicPseudo = NOPSEUDO;
2044 
2045     // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
2046     if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
2047         // We know this selector does not include any pseudo selectors.
2048         if (m_checker.m_pseudoStyle != NOPSEUDO)
2049             return false;
2050         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
2051         // This is limited to HTML only so we don't need to check the namespace.
2052         if (ruleData.hasTopSelectorMatchingHTMLBasedOnRuleHash() && !ruleData.hasMultipartSelector() && m_element->isHTMLElement())
2053             return true;
2054         return SelectorChecker::fastCheckSelector(ruleData.selector(), m_element);
2055     }
2056 
2057     // Slow path.
2058     SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
2059     if (match != SelectorMatches)
2060         return false;
2061     if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
2062         return false;
2063     return true;
2064 }
2065 
selectorTagMatches(const Element * element,const CSSSelector * selector)2066 static inline bool selectorTagMatches(const Element* element, const CSSSelector* selector)
2067 {
2068     if (!selector->hasTag())
2069         return true;
2070     const AtomicString& localName = selector->tag().localName();
2071     if (localName != starAtom && localName != element->localName())
2072         return false;
2073     const AtomicString& namespaceURI = selector->tag().namespaceURI();
2074     return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
2075 }
2076 
isFastCheckableSelector(const CSSSelector * selector)2077 static inline bool isFastCheckableSelector(const CSSSelector* selector)
2078 {
2079     for (; selector; selector = selector->tagHistory()) {
2080         if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
2081             return false;
2082         if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
2083             return false;
2084     }
2085     return true;
2086 }
2087 
2088 template <class ValueChecker>
fastCheckSingleSelector(const CSSSelector * & selector,const Element * & element,const CSSSelector * & topChildOrSubselector,const Element * & topChildOrSubselectorMatchElement)2089 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
2090 {
2091     AtomicStringImpl* value = selector->value().impl();
2092     for (; element; element = element->parentElement()) {
2093         if (ValueChecker::checkValue(element, value) && selectorTagMatches(element, selector)) {
2094             if (selector->relation() == CSSSelector::Descendant)
2095                 topChildOrSubselector = 0;
2096             else if (!topChildOrSubselector) {
2097                 ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
2098                 topChildOrSubselector = selector;
2099                 topChildOrSubselectorMatchElement = element;
2100             }
2101             if (selector->relation() != CSSSelector::SubSelector)
2102                 element = element->parentElement();
2103             selector = selector->tagHistory();
2104             return true;
2105         }
2106         if (topChildOrSubselector) {
2107             // Child or subselector check failed.
2108             // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match
2109             // the original element we were checking.
2110             if (!topChildOrSubselectorMatchElement)
2111                 return false;
2112             // There may be other matches down the ancestor chain.
2113             // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
2114             selector = topChildOrSubselector;
2115             element = topChildOrSubselectorMatchElement->parentElement();
2116             topChildOrSubselector = 0;
2117             return true;
2118         }
2119     }
2120     return false;
2121 }
2122 
2123 struct ClassCheck {
checkValueWebCore::ClassCheck2124     static bool checkValue(const Element* element, AtomicStringImpl* value)
2125     {
2126         return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value);
2127     }
2128 };
2129 struct IdCheck {
checkValueWebCore::IdCheck2130     static bool checkValue(const Element* element, AtomicStringImpl* value)
2131     {
2132         return element->hasID() && element->idForStyleResolution().impl() == value;
2133     }
2134 };
2135 struct TagCheck {
checkValueWebCore::TagCheck2136     static bool checkValue(const Element*, AtomicStringImpl*)
2137     {
2138         return true;
2139     }
2140 };
2141 
fastCheckSelector(const CSSSelector * selector,const Element * element)2142 bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element)
2143 {
2144     ASSERT(isFastCheckableSelector(selector));
2145 
2146     // The top selector requires tag check only as rule hashes have already handled id and class matches.
2147     if (!selectorTagMatches(element, selector))
2148         return false;
2149 
2150     const CSSSelector* topChildOrSubselector = 0;
2151     const Element* topChildOrSubselectorMatchElement = 0;
2152     if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
2153         topChildOrSubselector = selector;
2154 
2155     if (selector->relation() != CSSSelector::SubSelector)
2156         element = element->parentElement();
2157 
2158     selector = selector->tagHistory();
2159 
2160     // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
2161     while (selector) {
2162         switch (selector->m_match) {
2163         case CSSSelector::Class:
2164             if (!fastCheckSingleSelector<ClassCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2165                 return false;
2166             break;
2167         case CSSSelector::Id:
2168             if (!fastCheckSingleSelector<IdCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2169                 return false;
2170             break;
2171         case CSSSelector::None:
2172             if (!fastCheckSingleSelector<TagCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2173                 return false;
2174             break;
2175         default:
2176             ASSERT_NOT_REACHED();
2177         }
2178     }
2179     return true;
2180 }
2181 
2182 // Recursive check of selectors and combinators
2183 // It can return 3 different values:
2184 // * SelectorMatches         - the selector matches the element e
2185 // * SelectorFailsLocally    - the selector fails for the element e
2186 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
checkSelector(CSSSelector * sel,Element * e,HashSet<AtomicStringImpl * > * selectorAttrs,PseudoId & dynamicPseudo,bool isSubSelector,bool encounteredLink,RenderStyle * elementStyle,RenderStyle * elementParentStyle) const2187 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2188 {
2189 #if ENABLE(SVG)
2190     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
2191     // because its contents are not part of the formal document structure.
2192     if (e->isSVGElement() && e->isShadowRoot())
2193         return SelectorFailsCompletely;
2194 #endif
2195 
2196     // first selector has to match
2197     if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle))
2198         return SelectorFailsLocally;
2199 
2200     // The rest of the selectors has to match
2201     CSSSelector::Relation relation = sel->relation();
2202 
2203     // Prepare next sel
2204     sel = sel->tagHistory();
2205     if (!sel)
2206         return SelectorMatches;
2207 
2208     if (relation != CSSSelector::SubSelector)
2209         // Bail-out if this selector is irrelevant for the pseudoStyle
2210         if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
2211             return SelectorFailsCompletely;
2212 
2213     // Check for nested links.
2214     if (m_matchVisitedPseudoClass && !isSubSelector) {
2215         RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
2216         if (currentStyle && currentStyle->insideLink() && e->isLink()) {
2217             if (encounteredLink)
2218                 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching.
2219             else
2220                 encounteredLink = true;
2221         }
2222     }
2223 
2224     switch (relation) {
2225         case CSSSelector::Descendant:
2226             while (true) {
2227                 ContainerNode* n = e->parentNode();
2228                 if (!n || !n->isElementNode())
2229                     return SelectorFailsCompletely;
2230                 e = static_cast<Element*>(n);
2231                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2232                 if (match != SelectorFailsLocally)
2233                     return match;
2234             }
2235             break;
2236         case CSSSelector::Child:
2237         {
2238             ContainerNode* n = e->parentNode();
2239             if (!n || !n->isElementNode())
2240                 return SelectorFailsCompletely;
2241             e = static_cast<Element*>(n);
2242             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2243         }
2244         case CSSSelector::DirectAdjacent:
2245         {
2246             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2247                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2248                 if (parentStyle)
2249                     parentStyle->setChildrenAffectedByDirectAdjacentRules();
2250             }
2251             Node* n = e->previousSibling();
2252             while (n && !n->isElementNode())
2253                 n = n->previousSibling();
2254             if (!n)
2255                 return SelectorFailsLocally;
2256             e = static_cast<Element*>(n);
2257             m_matchVisitedPseudoClass = false;
2258             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2259         }
2260         case CSSSelector::IndirectAdjacent:
2261             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2262                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2263                 if (parentStyle)
2264                     parentStyle->setChildrenAffectedByForwardPositionalRules();
2265             }
2266             while (true) {
2267                 Node* n = e->previousSibling();
2268                 while (n && !n->isElementNode())
2269                     n = n->previousSibling();
2270                 if (!n)
2271                     return SelectorFailsLocally;
2272                 e = static_cast<Element*>(n);
2273                 m_matchVisitedPseudoClass = false;
2274                 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2275                 if (match != SelectorFailsLocally)
2276                     return match;
2277             };
2278             break;
2279         case CSSSelector::SubSelector:
2280             // a selector is invalid if something follows a pseudo-element
2281             // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
2282             // to follow the pseudo elements.
2283             if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
2284                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
2285                 return SelectorFailsCompletely;
2286             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
2287         case CSSSelector::ShadowDescendant:
2288         {
2289             Node* shadowHostNode = e->shadowAncestorNode();
2290             if (shadowHostNode == e || !shadowHostNode->isElementNode())
2291                 return SelectorFailsCompletely;
2292             e = static_cast<Element*>(shadowHostNode);
2293             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
2294         }
2295     }
2296 
2297     return SelectorFailsCompletely;
2298 }
2299 
addLocalNameToSet(HashSet<AtomicStringImpl * > * set,const QualifiedName & qName)2300 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
2301 {
2302     set->add(qName.localName().impl());
2303 }
2304 
createHtmlCaseInsensitiveAttributesSet()2305 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
2306 {
2307     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
2308     // Mozilla treats all other values as case-sensitive, thus so do we.
2309     HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
2310 
2311     addLocalNameToSet(attrSet, accept_charsetAttr);
2312     addLocalNameToSet(attrSet, acceptAttr);
2313     addLocalNameToSet(attrSet, alignAttr);
2314     addLocalNameToSet(attrSet, alinkAttr);
2315     addLocalNameToSet(attrSet, axisAttr);
2316     addLocalNameToSet(attrSet, bgcolorAttr);
2317     addLocalNameToSet(attrSet, charsetAttr);
2318     addLocalNameToSet(attrSet, checkedAttr);
2319     addLocalNameToSet(attrSet, clearAttr);
2320     addLocalNameToSet(attrSet, codetypeAttr);
2321     addLocalNameToSet(attrSet, colorAttr);
2322     addLocalNameToSet(attrSet, compactAttr);
2323     addLocalNameToSet(attrSet, declareAttr);
2324     addLocalNameToSet(attrSet, deferAttr);
2325     addLocalNameToSet(attrSet, dirAttr);
2326     addLocalNameToSet(attrSet, disabledAttr);
2327     addLocalNameToSet(attrSet, enctypeAttr);
2328     addLocalNameToSet(attrSet, faceAttr);
2329     addLocalNameToSet(attrSet, frameAttr);
2330     addLocalNameToSet(attrSet, hreflangAttr);
2331     addLocalNameToSet(attrSet, http_equivAttr);
2332     addLocalNameToSet(attrSet, langAttr);
2333     addLocalNameToSet(attrSet, languageAttr);
2334     addLocalNameToSet(attrSet, linkAttr);
2335     addLocalNameToSet(attrSet, mediaAttr);
2336     addLocalNameToSet(attrSet, methodAttr);
2337     addLocalNameToSet(attrSet, multipleAttr);
2338     addLocalNameToSet(attrSet, nohrefAttr);
2339     addLocalNameToSet(attrSet, noresizeAttr);
2340     addLocalNameToSet(attrSet, noshadeAttr);
2341     addLocalNameToSet(attrSet, nowrapAttr);
2342     addLocalNameToSet(attrSet, readonlyAttr);
2343     addLocalNameToSet(attrSet, relAttr);
2344     addLocalNameToSet(attrSet, revAttr);
2345     addLocalNameToSet(attrSet, rulesAttr);
2346     addLocalNameToSet(attrSet, scopeAttr);
2347     addLocalNameToSet(attrSet, scrollingAttr);
2348     addLocalNameToSet(attrSet, selectedAttr);
2349     addLocalNameToSet(attrSet, shapeAttr);
2350     addLocalNameToSet(attrSet, targetAttr);
2351     addLocalNameToSet(attrSet, textAttr);
2352     addLocalNameToSet(attrSet, typeAttr);
2353     addLocalNameToSet(attrSet, valignAttr);
2354     addLocalNameToSet(attrSet, valuetypeAttr);
2355     addLocalNameToSet(attrSet, vlinkAttr);
2356 
2357     return attrSet;
2358 }
2359 
htmlAttributeHasCaseInsensitiveValue(const QualifiedName & attr)2360 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
2361 {
2362     static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
2363     bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
2364     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
2365 }
2366 
checkOneSelector(CSSSelector * sel,Element * e,HashSet<AtomicStringImpl * > * selectorAttrs,PseudoId & dynamicPseudo,bool isSubSelector,bool encounteredLink,RenderStyle * elementStyle,RenderStyle * elementParentStyle) const2367 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2368 {
2369     ASSERT(e);
2370     if (!e)
2371         return false;
2372 
2373     if (!selectorTagMatches(e, sel))
2374         return false;
2375 
2376     if (sel->hasAttribute()) {
2377         if (sel->m_match == CSSSelector::Class)
2378             return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value());
2379 
2380         if (sel->m_match == CSSSelector::Id)
2381             return e->hasID() && e->idForStyleResolution() == sel->value();
2382 
2383         const QualifiedName& attr = sel->attribute();
2384 
2385         // FIXME: Handle the case were elementStyle is 0.
2386         if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) {
2387             elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
2388             if (selectorAttrs)
2389                 selectorAttrs->add(attr.localName().impl());
2390         }
2391 
2392         const AtomicString& value = e->getAttribute(attr);
2393         if (value.isNull())
2394             return false; // attribute is not set
2395 
2396         bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
2397 
2398         switch (sel->m_match) {
2399         case CSSSelector::Exact:
2400             if (caseSensitive ? sel->value() != value : !equalIgnoringCase(sel->value(), value))
2401                 return false;
2402             break;
2403         case CSSSelector::List:
2404         {
2405             // Ignore empty selectors or selectors containing spaces
2406             if (sel->value().contains(' ') || sel->value().isEmpty())
2407                 return false;
2408 
2409             unsigned startSearchAt = 0;
2410             while (true) {
2411                 size_t foundPos = value.find(sel->value(), startSearchAt, caseSensitive);
2412                 if (foundPos == notFound)
2413                     return false;
2414                 if (foundPos == 0 || value[foundPos - 1] == ' ') {
2415                     unsigned endStr = foundPos + sel->value().length();
2416                     if (endStr == value.length() || value[endStr] == ' ')
2417                         break; // We found a match.
2418                 }
2419 
2420                 // No match. Keep looking.
2421                 startSearchAt = foundPos + 1;
2422             }
2423             break;
2424         }
2425         case CSSSelector::Contain:
2426             if (!value.contains(sel->value(), caseSensitive) || sel->value().isEmpty())
2427                 return false;
2428             break;
2429         case CSSSelector::Begin:
2430             if (!value.startsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
2431                 return false;
2432             break;
2433         case CSSSelector::End:
2434             if (!value.endsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
2435                 return false;
2436             break;
2437         case CSSSelector::Hyphen:
2438             if (value.length() < sel->value().length())
2439                 return false;
2440             if (!value.startsWith(sel->value(), caseSensitive))
2441                 return false;
2442             // It they start the same, check for exact match or following '-':
2443             if (value.length() != sel->value().length() && value[sel->value().length()] != '-')
2444                 return false;
2445             break;
2446         case CSSSelector::PseudoClass:
2447         case CSSSelector::PseudoElement:
2448         default:
2449             break;
2450         }
2451     }
2452 
2453     if (sel->m_match == CSSSelector::PseudoClass) {
2454         // Handle :not up front.
2455         if (sel->pseudoType() == CSSSelector::PseudoNot) {
2456             ASSERT(sel->selectorList());
2457             for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) {
2458                 // :not cannot nest. I don't really know why this is a
2459                 // restriction in CSS3, but it is, so let's honor it.
2460                 // the parser enforces that this never occurs
2461                 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
2462 
2463                 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle))
2464                     return true;
2465             }
2466         } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
2467             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
2468             // (since there are no elements involved).
2469             return checkScrollbarPseudoClass(sel, dynamicPseudo);
2470         } else if (dynamicPseudo == SELECTION) {
2471             if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2472                 return !m_document->page()->focusController()->isActive();
2473         }
2474 
2475         // Normal element pseudo class checking.
2476         switch (sel->pseudoType()) {
2477             // Pseudo classes:
2478             case CSSSelector::PseudoNot:
2479                 break; // Already handled up above.
2480             case CSSSelector::PseudoEmpty: {
2481                 bool result = true;
2482                 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
2483                     if (n->isElementNode()) {
2484                         result = false;
2485                         break;
2486                     } else if (n->isTextNode()) {
2487                         Text* textNode = static_cast<Text*>(n);
2488                         if (!textNode->data().isEmpty()) {
2489                             result = false;
2490                             break;
2491                         }
2492                     }
2493                 }
2494                 if (!m_collectRulesOnly) {
2495                     if (elementStyle)
2496                         elementStyle->setEmptyState(result);
2497                     else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
2498                         e->renderStyle()->setEmptyState(result);
2499                 }
2500                 return result;
2501             }
2502             case CSSSelector::PseudoFirstChild: {
2503                 // first-child matches the first child that is an element
2504                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2505                     bool result = false;
2506                     Node* n = e->previousSibling();
2507                     while (n && !n->isElementNode())
2508                         n = n->previousSibling();
2509                     if (!n)
2510                         result = true;
2511                     if (!m_collectRulesOnly) {
2512                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2513                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2514                         if (parentStyle)
2515                             parentStyle->setChildrenAffectedByFirstChildRules();
2516                         if (result && childStyle)
2517                             childStyle->setFirstChildState();
2518                     }
2519                     return result;
2520                 }
2521                 break;
2522             }
2523             case CSSSelector::PseudoFirstOfType: {
2524                 // first-of-type matches the first element of its type
2525                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2526                     bool result = false;
2527                     const QualifiedName& type = e->tagQName();
2528                     Node* n = e->previousSibling();
2529                     while (n) {
2530                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2531                             break;
2532                         n = n->previousSibling();
2533                     }
2534                     if (!n)
2535                         result = true;
2536                     if (!m_collectRulesOnly) {
2537                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2538                         if (parentStyle)
2539                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2540                     }
2541                     return result;
2542                 }
2543                 break;
2544             }
2545             case CSSSelector::PseudoLastChild: {
2546                 // last-child matches the last child that is an element
2547                 if (Element* parentElement = e->parentElement()) {
2548                     bool result = false;
2549                     if (parentElement->isFinishedParsingChildren()) {
2550                         Node* n = e->nextSibling();
2551                         while (n && !n->isElementNode())
2552                             n = n->nextSibling();
2553                         if (!n)
2554                             result = true;
2555                     }
2556                     if (!m_collectRulesOnly) {
2557                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2558                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2559                         if (parentStyle)
2560                             parentStyle->setChildrenAffectedByLastChildRules();
2561                         if (result && childStyle)
2562                             childStyle->setLastChildState();
2563                     }
2564                     return result;
2565                 }
2566                 break;
2567             }
2568             case CSSSelector::PseudoLastOfType: {
2569                 // last-of-type matches the last element of its type
2570                 if (Element* parentElement = e->parentElement()) {
2571                     if (!m_collectRulesOnly) {
2572                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2573                         if (parentStyle)
2574                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2575                     }
2576                     if (!parentElement->isFinishedParsingChildren())
2577                         return false;
2578                     bool result = false;
2579                     const QualifiedName& type = e->tagQName();
2580                     Node* n = e->nextSibling();
2581                     while (n) {
2582                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2583                             break;
2584                         n = n->nextSibling();
2585                     }
2586                     if (!n)
2587                         result = true;
2588                     return result;
2589                 }
2590                 break;
2591             }
2592             case CSSSelector::PseudoOnlyChild: {
2593                 if (Element* parentElement = e->parentElement()) {
2594                     bool firstChild = false;
2595                     bool lastChild = false;
2596 
2597                     Node* n = e->previousSibling();
2598                     while (n && !n->isElementNode())
2599                         n = n->previousSibling();
2600                     if (!n)
2601                         firstChild = true;
2602                     if (firstChild && parentElement->isFinishedParsingChildren()) {
2603                         n = e->nextSibling();
2604                         while (n && !n->isElementNode())
2605                             n = n->nextSibling();
2606                         if (!n)
2607                             lastChild = true;
2608                     }
2609                     if (!m_collectRulesOnly) {
2610                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2611                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2612                         if (parentStyle) {
2613                             parentStyle->setChildrenAffectedByFirstChildRules();
2614                             parentStyle->setChildrenAffectedByLastChildRules();
2615                         }
2616                         if (firstChild && childStyle)
2617                             childStyle->setFirstChildState();
2618                         if (lastChild && childStyle)
2619                             childStyle->setLastChildState();
2620                     }
2621                     return firstChild && lastChild;
2622                 }
2623                 break;
2624             }
2625             case CSSSelector::PseudoOnlyOfType: {
2626                 // FIXME: This selector is very slow.
2627                 if (Element* parentElement = e->parentElement()) {
2628                     if (!m_collectRulesOnly) {
2629                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2630                         if (parentStyle) {
2631                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2632                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2633                         }
2634                     }
2635                     if (!parentElement->isFinishedParsingChildren())
2636                         return false;
2637                     bool firstChild = false;
2638                     bool lastChild = false;
2639                     const QualifiedName& type = e->tagQName();
2640                     Node* n = e->previousSibling();
2641                     while (n) {
2642                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2643                             break;
2644                         n = n->previousSibling();
2645                     }
2646                     if (!n)
2647                         firstChild = true;
2648                     if (firstChild) {
2649                         n = e->nextSibling();
2650                         while (n) {
2651                             if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2652                                 break;
2653                             n = n->nextSibling();
2654                         }
2655                         if (!n)
2656                             lastChild = true;
2657                     }
2658                     return firstChild && lastChild;
2659                 }
2660                 break;
2661             }
2662             case CSSSelector::PseudoNthChild: {
2663                 if (!sel->parseNth())
2664                     break;
2665                 if (Element* parentElement = e->parentElement()) {
2666                     int count = 1;
2667                     Node* n = e->previousSibling();
2668                     while (n) {
2669                         if (n->isElementNode()) {
2670                             RenderStyle* s = n->renderStyle();
2671                             unsigned index = s ? s->childIndex() : 0;
2672                             if (index) {
2673                                 count += index;
2674                                 break;
2675                             }
2676                             count++;
2677                         }
2678                         n = n->previousSibling();
2679                     }
2680 
2681                     if (!m_collectRulesOnly) {
2682                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2683                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2684                         if (childStyle)
2685                             childStyle->setChildIndex(count);
2686                         if (parentStyle)
2687                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2688                     }
2689 
2690                     if (sel->matchNth(count))
2691                         return true;
2692                 }
2693                 break;
2694             }
2695             case CSSSelector::PseudoNthOfType: {
2696                 if (!sel->parseNth())
2697                     break;
2698                 if (Element* parentElement = e->parentElement()) {
2699                     int count = 1;
2700                     const QualifiedName& type = e->tagQName();
2701                     Node* n = e->previousSibling();
2702                     while (n) {
2703                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2704                             count++;
2705                         n = n->previousSibling();
2706                     }
2707 
2708                     if (!m_collectRulesOnly) {
2709                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2710                         if (parentStyle)
2711                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2712                     }
2713 
2714                     if (sel->matchNth(count))
2715                         return true;
2716                 }
2717                 break;
2718             }
2719             case CSSSelector::PseudoNthLastChild: {
2720                 if (!sel->parseNth())
2721                     break;
2722                 if (Element* parentElement = e->parentElement()) {
2723                     if (!m_collectRulesOnly) {
2724                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2725                         if (parentStyle)
2726                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2727                     }
2728                     if (!parentElement->isFinishedParsingChildren())
2729                         return false;
2730                     int count = 1;
2731                     Node* n = e->nextSibling();
2732                     while (n) {
2733                         if (n->isElementNode())
2734                             count++;
2735                         n = n->nextSibling();
2736                     }
2737                     if (sel->matchNth(count))
2738                         return true;
2739                 }
2740                 break;
2741             }
2742             case CSSSelector::PseudoNthLastOfType: {
2743                 if (!sel->parseNth())
2744                     break;
2745                 if (Element* parentElement = e->parentElement()) {
2746                     if (!m_collectRulesOnly) {
2747                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2748                         if (parentStyle)
2749                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2750                     }
2751                     if (!parentElement->isFinishedParsingChildren())
2752                         return false;
2753                     int count = 1;
2754                     const QualifiedName& type = e->tagQName();
2755                     Node* n = e->nextSibling();
2756                     while (n) {
2757                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2758                             count++;
2759                         n = n->nextSibling();
2760                     }
2761                     if (sel->matchNth(count))
2762                         return true;
2763                 }
2764                 break;
2765             }
2766             case CSSSelector::PseudoTarget:
2767                 if (e == e->document()->cssTarget())
2768                     return true;
2769                 break;
2770             case CSSSelector::PseudoAny:
2771                 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
2772                     if (checkSelector(selector, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches)
2773                         return true;
2774                 }
2775                 break;
2776             case CSSSelector::PseudoAnyLink:
2777                 if (e && e->isLink())
2778                     return true;
2779                 break;
2780             case CSSSelector::PseudoAutofill: {
2781                 if (!e || !e->isFormControlElement())
2782                     break;
2783                 if (InputElement* inputElement = e->toInputElement())
2784                     return inputElement->isAutofilled();
2785                 break;
2786             }
2787             case CSSSelector::PseudoLink:
2788                 if (e && e->isLink())
2789                     return !m_matchVisitedPseudoClass;
2790                 break;
2791             case CSSSelector::PseudoVisited:
2792                 if (e && e->isLink())
2793                     return m_matchVisitedPseudoClass;
2794                 break;
2795             case CSSSelector::PseudoDrag: {
2796                 if (elementStyle)
2797                     elementStyle->setAffectedByDragRules(true);
2798                 else if (e->renderStyle())
2799                     e->renderStyle()->setAffectedByDragRules(true);
2800                 if (e->renderer() && e->renderer()->isDragging())
2801                     return true;
2802                 break;
2803             }
2804             case CSSSelector::PseudoFocus:
2805                 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
2806                     return true;
2807                 break;
2808             case CSSSelector::PseudoHover: {
2809                 // If we're in quirks mode, then hover should never match anchors with no
2810                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
2811                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2812                     if (elementStyle)
2813                         elementStyle->setAffectedByHoverRules(true);
2814                     else if (e->renderStyle())
2815                         e->renderStyle()->setAffectedByHoverRules(true);
2816                     if (e->hovered())
2817                         return true;
2818                 }
2819                 break;
2820             }
2821             case CSSSelector::PseudoActive:
2822                 // If we're in quirks mode, then :active should never match anchors with no
2823                 // href and *:active should not match anything.
2824                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2825                     if (elementStyle)
2826                         elementStyle->setAffectedByActiveRules(true);
2827                     else if (e->renderStyle())
2828                         e->renderStyle()->setAffectedByActiveRules(true);
2829                     if (e->active())
2830                         return true;
2831                 }
2832                 break;
2833             case CSSSelector::PseudoEnabled:
2834                 if (e && e->isFormControlElement())
2835                     return e->isEnabledFormControl();
2836                 break;
2837             case CSSSelector::PseudoFullPageMedia:
2838                 return e && e->document() && e->document()->isMediaDocument();
2839                 break;
2840             case CSSSelector::PseudoDefault:
2841                 return e && e->isDefaultButtonForForm();
2842             case CSSSelector::PseudoDisabled:
2843                 if (e && e->isFormControlElement())
2844                     return !e->isEnabledFormControl();
2845                 break;
2846             case CSSSelector::PseudoReadOnly: {
2847                 if (!e || !e->isFormControlElement())
2848                     return false;
2849                 return e->isTextFormControl() && e->isReadOnlyFormControl();
2850             }
2851             case CSSSelector::PseudoReadWrite: {
2852                 if (!e || !e->isFormControlElement())
2853                     return false;
2854                 return e->isTextFormControl() && !e->isReadOnlyFormControl();
2855             }
2856             case CSSSelector::PseudoOptional:
2857                 return e && e->isOptionalFormControl();
2858             case CSSSelector::PseudoRequired:
2859                 return e && e->isRequiredFormControl();
2860             case CSSSelector::PseudoValid: {
2861                 if (!e)
2862                     return false;
2863                 e->document()->setContainsValidityStyleRules();
2864                 return e->willValidate() && e->isValidFormControlElement();
2865             } case CSSSelector::PseudoInvalid: {
2866                 if (!e)
2867                     return false;
2868                 e->document()->setContainsValidityStyleRules();
2869                 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
2870             } case CSSSelector::PseudoChecked: {
2871                 if (!e || !e->isFormControlElement())
2872                     break;
2873                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
2874                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
2875                 // obey the CSS spec here in the test for matching the pseudo.
2876                 InputElement* inputElement = e->toInputElement();
2877                 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate())
2878                     return true;
2879                 break;
2880             }
2881             case CSSSelector::PseudoIndeterminate: {
2882                 if (!e || !e->isFormControlElement())
2883                     break;
2884                 InputElement* inputElement = e->toInputElement();
2885                 if (inputElement && inputElement->isIndeterminate())
2886                     return true;
2887                 break;
2888             }
2889             case CSSSelector::PseudoRoot:
2890                 if (e == e->document()->documentElement())
2891                     return true;
2892                 break;
2893             case CSSSelector::PseudoLang: {
2894                 AtomicString value = e->computeInheritedLanguage();
2895                 const AtomicString& argument = sel->argument();
2896                 if (value.isEmpty() || !value.startsWith(argument, false))
2897                     break;
2898                 if (value.length() != argument.length() && value[argument.length()] != '-')
2899                     break;
2900                 return true;
2901             }
2902 #if ENABLE(FULLSCREEN_API)
2903             case CSSSelector::PseudoFullScreen:
2904                 // While a Document is in the fullscreen state, and the document's current fullscreen
2905                 // element is an element in the document, the 'full-screen' pseudoclass applies to
2906                 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing
2907                 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
2908                 if (!e->document()->webkitIsFullScreen())
2909                     return false;
2910                 if (e != e->document()->webkitCurrentFullScreenElement())
2911                     return false;
2912                 return true;
2913             case CSSSelector::PseudoFullScreenDocument:
2914                 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
2915                 // to all elements of that Document.
2916                 if (!e->document()->webkitIsFullScreen())
2917                     return false;
2918                 return true;
2919 #endif
2920             case CSSSelector::PseudoInRange:
2921                 if (!e)
2922                     return false;
2923                 e->document()->setContainsValidityStyleRules();
2924                 return e->isInRange();
2925             case CSSSelector::PseudoOutOfRange:
2926                 if (!e)
2927                     return false;
2928                 e->document()->setContainsValidityStyleRules();
2929                 return e->isOutOfRange();
2930             case CSSSelector::PseudoUnknown:
2931             case CSSSelector::PseudoNotParsed:
2932             default:
2933                 ASSERT_NOT_REACHED();
2934                 break;
2935         }
2936         return false;
2937     }
2938     if (sel->m_match == CSSSelector::PseudoElement) {
2939         if (!elementStyle && !m_collectRulesOnly)
2940             return false;
2941 
2942         PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
2943         if (pseudoId == FIRST_LETTER) {
2944             if (Document* document = e->document())
2945                 document->setUsesFirstLetterRules(true);
2946         }
2947         if (pseudoId != NOPSEUDO)
2948             dynamicPseudo = pseudoId;
2949     }
2950     // ### add the rest of the checks...
2951     return true;
2952 }
2953 
checkScrollbarPseudoClass(CSSSelector * sel,PseudoId &) const2954 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
2955 {
2956     RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
2957     ScrollbarPart part = RenderScrollbar::partForStyleResolve();
2958 
2959     // FIXME: This is a temporary hack for resizers and scrollbar corners.  Eventually :window-inactive should become a real
2960     // pseudo class and just apply to everything.
2961     if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2962         return !m_document->page()->focusController()->isActive();
2963 
2964     if (!scrollbar)
2965         return false;
2966 
2967     ASSERT(sel->m_match == CSSSelector::PseudoClass);
2968     switch (sel->pseudoType()) {
2969         case CSSSelector::PseudoEnabled:
2970             return scrollbar->enabled();
2971         case CSSSelector::PseudoDisabled:
2972             return !scrollbar->enabled();
2973         case CSSSelector::PseudoHover: {
2974             ScrollbarPart hoveredPart = scrollbar->hoveredPart();
2975             if (part == ScrollbarBGPart)
2976                 return hoveredPart != NoPart;
2977             if (part == TrackBGPart)
2978                 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
2979             return part == hoveredPart;
2980         }
2981         case CSSSelector::PseudoActive: {
2982             ScrollbarPart pressedPart = scrollbar->pressedPart();
2983             if (part == ScrollbarBGPart)
2984                 return pressedPart != NoPart;
2985             if (part == TrackBGPart)
2986                 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
2987             return part == pressedPart;
2988         }
2989         case CSSSelector::PseudoHorizontal:
2990             return scrollbar->orientation() == HorizontalScrollbar;
2991         case CSSSelector::PseudoVertical:
2992             return scrollbar->orientation() == VerticalScrollbar;
2993         case CSSSelector::PseudoDecrement:
2994             return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
2995         case CSSSelector::PseudoIncrement:
2996             return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
2997         case CSSSelector::PseudoStart:
2998             return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
2999         case CSSSelector::PseudoEnd:
3000             return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
3001         case CSSSelector::PseudoDoubleButton: {
3002             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3003             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
3004                 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
3005             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
3006                 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
3007             return false;
3008         }
3009         case CSSSelector::PseudoSingleButton: {
3010             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3011             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
3012                 return buttonsPlacement == ScrollbarButtonsSingle;
3013             return false;
3014         }
3015         case CSSSelector::PseudoNoButton: {
3016             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3017             if (part == BackTrackPart)
3018                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
3019             if (part == ForwardTrackPart)
3020                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
3021             return false;
3022         }
3023         case CSSSelector::PseudoCornerPresent:
3024             return scrollbar->scrollableArea()->isScrollCornerVisible();
3025         default:
3026             return false;
3027     }
3028 }
3029 
3030 // -----------------------------------------------------------------
3031 
isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector * selector)3032 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
3033 {
3034     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
3035     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
3036         return false;
3037     if (selector->m_match == CSSSelector::None)
3038         return true;
3039     if (selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
3040         return false;
3041     return selector->tag() == starAtom;
3042 }
3043 
RuleData(CSSStyleRule * rule,CSSSelector * selector,unsigned position)3044 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
3045     : m_rule(rule)
3046     , m_selector(selector)
3047     , m_specificity(selector->specificity())
3048     , m_position(position)
3049     , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
3050     , m_hasMultipartSelector(selector->tagHistory())
3051     , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
3052 {
3053     collectDescendantSelectorIdentifierHashes();
3054 }
3055 
collectIdentifierHashes(const CSSSelector * selector,unsigned & identifierCount)3056 inline void RuleData::collectIdentifierHashes(const CSSSelector* selector, unsigned& identifierCount)
3057 {
3058     if ((selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class) && !selector->value().isEmpty())
3059         m_descendantSelectorIdentifierHashes[identifierCount++] = selector->value().impl()->existingHash();
3060     if (identifierCount == maximumIdentifierCount)
3061         return;
3062     const AtomicString& localName = selector->tag().localName();
3063     if (localName != starAtom)
3064         m_descendantSelectorIdentifierHashes[identifierCount++] = localName.impl()->existingHash();
3065 }
3066 
collectDescendantSelectorIdentifierHashes()3067 inline void RuleData::collectDescendantSelectorIdentifierHashes()
3068 {
3069     unsigned identifierCount = 0;
3070     CSSSelector::Relation relation = m_selector->relation();
3071 
3072     // Skip the topmost selector. It is handled quickly by the rule hashes.
3073     bool skipOverSubselectors = true;
3074     for (const CSSSelector* selector = m_selector->tagHistory(); selector; selector = selector->tagHistory()) {
3075         // Only collect identifiers that match ancestors.
3076         switch (relation) {
3077         case CSSSelector::SubSelector:
3078             if (!skipOverSubselectors)
3079                 collectIdentifierHashes(selector, identifierCount);
3080             break;
3081         case CSSSelector::DirectAdjacent:
3082         case CSSSelector::IndirectAdjacent:
3083         case CSSSelector::ShadowDescendant:
3084             skipOverSubselectors = true;
3085             break;
3086         case CSSSelector::Descendant:
3087         case CSSSelector::Child:
3088             skipOverSubselectors = false;
3089             collectIdentifierHashes(selector, identifierCount);
3090             break;
3091         }
3092         if (identifierCount == maximumIdentifierCount)
3093             return;
3094         relation = selector->relation();
3095     }
3096     m_descendantSelectorIdentifierHashes[identifierCount] = 0;
3097 }
3098 
RuleSet()3099 RuleSet::RuleSet()
3100     : m_ruleCount(0)
3101     , m_autoShrinkToFitEnabled(true)
3102 {
3103 }
3104 
~RuleSet()3105 RuleSet::~RuleSet()
3106 {
3107     deleteAllValues(m_idRules);
3108     deleteAllValues(m_classRules);
3109     deleteAllValues(m_pseudoRules);
3110     deleteAllValues(m_tagRules);
3111 }
3112 
3113 
addToRuleSet(AtomicStringImpl * key,AtomRuleMap & map,CSSStyleRule * rule,CSSSelector * sel)3114 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
3115                               CSSStyleRule* rule, CSSSelector* sel)
3116 {
3117     if (!key) return;
3118     Vector<RuleData>* rules = map.get(key);
3119     if (!rules) {
3120         rules = new Vector<RuleData>;
3121         map.set(key, rules);
3122     }
3123     rules->append(RuleData(rule, sel, m_ruleCount++));
3124 }
3125 
addRule(CSSStyleRule * rule,CSSSelector * sel)3126 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
3127 {
3128     if (sel->m_match == CSSSelector::Id) {
3129         addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
3130         return;
3131     }
3132     if (sel->m_match == CSSSelector::Class) {
3133         addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
3134         return;
3135     }
3136 
3137     if (sel->isUnknownPseudoElement()) {
3138         addToRuleSet(sel->value().impl(), m_pseudoRules, rule, sel);
3139         return;
3140     }
3141 
3142     const AtomicString& localName = sel->tag().localName();
3143     if (localName != starAtom) {
3144         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
3145         return;
3146     }
3147 
3148     m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
3149 }
3150 
addPageRule(CSSStyleRule * rule,CSSSelector * sel)3151 void RuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
3152 {
3153     m_pageRules.append(RuleData(rule, sel, m_pageRules.size()));
3154 }
3155 
addRulesFromSheet(CSSStyleSheet * sheet,const MediaQueryEvaluator & medium,CSSStyleSelector * styleSelector)3156 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
3157 {
3158     if (!sheet)
3159         return;
3160 
3161     // No media implies "all", but if a media list exists it must
3162     // contain our current medium
3163     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
3164         return; // the style sheet doesn't apply
3165 
3166     int len = sheet->length();
3167 
3168     for (int i = 0; i < len; i++) {
3169         StyleBase* item = sheet->item(i);
3170         if (item->isStyleRule())
3171             addStyleRule(static_cast<CSSStyleRule*>(item));
3172         else if (item->isImportRule()) {
3173             CSSImportRule* import = static_cast<CSSImportRule*>(item);
3174             if (!import->media() || medium.eval(import->media(), styleSelector))
3175                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
3176         }
3177         else if (item->isMediaRule()) {
3178             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
3179             CSSRuleList* rules = r->cssRules();
3180 
3181             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
3182                 // Traverse child elements of the @media rule.
3183                 for (unsigned j = 0; j < rules->length(); j++) {
3184                     CSSRule *childItem = rules->item(j);
3185                     if (childItem->isStyleRule()) {
3186                         // It is a StyleRule, so append it to our list
3187                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
3188                     } else if (childItem->isFontFaceRule() && styleSelector) {
3189                         // Add this font face to our set.
3190                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
3191                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
3192                     } else if (childItem->isKeyframesRule() && styleSelector) {
3193                         // Add this keyframe rule to our set.
3194                         styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
3195                     }
3196                 }   // for rules
3197             }   // if rules
3198         } else if (item->isFontFaceRule() && styleSelector) {
3199             // Add this font face to our set.
3200             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
3201             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
3202         } else if (item->isKeyframesRule())
3203             styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item));
3204     }
3205     if (m_autoShrinkToFitEnabled)
3206         shrinkToFit();
3207 }
3208 
addStyleRule(CSSStyleRule * rule)3209 void RuleSet::addStyleRule(CSSStyleRule* rule)
3210 {
3211     if (rule->isPageRule()) {
3212         CSSPageRule* pageRule = static_cast<CSSPageRule*>(rule);
3213         addPageRule(pageRule, pageRule->selectorList().first());
3214     } else {
3215         for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
3216             addRule(rule, s);
3217     }
3218 }
3219 
collectFeaturesFromSelector(CSSStyleSelector::Features & features,const CSSSelector * selector)3220 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
3221 {
3222     if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
3223         features.idsInRules.add(selector->value().impl());
3224     switch (selector->pseudoType()) {
3225     case CSSSelector::PseudoFirstLine:
3226         features.usesFirstLineRules = true;
3227         break;
3228     case CSSSelector::PseudoBefore:
3229     case CSSSelector::PseudoAfter:
3230         features.usesBeforeAfterRules = true;
3231         break;
3232     case CSSSelector::PseudoLink:
3233     case CSSSelector::PseudoVisited:
3234         features.usesLinkRules = true;
3235         break;
3236     default:
3237         break;
3238     }
3239 }
3240 
collectFeaturesFromList(CSSStyleSelector::Features & features,const Vector<RuleData> & rules)3241 static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules)
3242 {
3243     unsigned size = rules.size();
3244     for (unsigned i = 0; i < size; ++i) {
3245         const RuleData& ruleData = rules[i];
3246         bool foundSiblingSelector = false;
3247         for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
3248             collectFeaturesFromSelector(features, selector);
3249 
3250             if (CSSSelectorList* selectorList = selector->selectorList()) {
3251                 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
3252                     if (selector->isSiblingSelector())
3253                         foundSiblingSelector = true;
3254                     collectFeaturesFromSelector(features, subSelector);
3255                 }
3256             } else if (selector->isSiblingSelector())
3257                 foundSiblingSelector = true;
3258         }
3259         if (foundSiblingSelector) {
3260             if (!features.siblingRules)
3261                 features.siblingRules = adoptPtr(new RuleSet);
3262             features.siblingRules->addRule(ruleData.rule(), ruleData.selector());
3263         }
3264     }
3265 }
3266 
collectFeatures(CSSStyleSelector::Features & features) const3267 void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const
3268 {
3269     AtomRuleMap::const_iterator end = m_idRules.end();
3270     for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
3271         collectFeaturesFromList(features, *it->second);
3272     end = m_classRules.end();
3273     for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
3274         collectFeaturesFromList(features, *it->second);
3275     end = m_tagRules.end();
3276     for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
3277         collectFeaturesFromList(features, *it->second);
3278     end = m_pseudoRules.end();
3279     for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it)
3280         collectFeaturesFromList(features, *it->second);
3281     collectFeaturesFromList(features, m_universalRules);
3282 }
3283 
shrinkMapVectorsToFit(RuleSet::AtomRuleMap & map)3284 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
3285 {
3286     RuleSet::AtomRuleMap::iterator end = map.end();
3287     for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
3288         it->second->shrinkToFit();
3289 }
3290 
shrinkToFit()3291 void RuleSet::shrinkToFit()
3292 {
3293     shrinkMapVectorsToFit(m_idRules);
3294     shrinkMapVectorsToFit(m_classRules);
3295     shrinkMapVectorsToFit(m_tagRules);
3296     shrinkMapVectorsToFit(m_pseudoRules);
3297     m_universalRules.shrinkToFit();
3298     m_pageRules.shrinkToFit();
3299 }
3300 
3301 // -------------------------------------------------------------------------------------
3302 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
3303 
convertToLength(CSSPrimitiveValue * primitiveValue,RenderStyle * style,RenderStyle * rootStyle,bool toFloat,double multiplier=1,bool * ok=0)3304 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
3305 {
3306     // This function is tolerant of a null style value. The only place style is used is in
3307     // length measurements, like 'ems' and 'px'. And in those cases style is only used
3308     // when the units are EMS or EXS. So we will just fail in those cases.
3309     Length l;
3310     if (!primitiveValue) {
3311         if (ok)
3312             *ok = false;
3313     } else {
3314         int type = primitiveValue->primitiveType();
3315 
3316         if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
3317             if (ok)
3318                 *ok = false;
3319         } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
3320             if (toFloat)
3321                 l = Length(primitiveValue->computeLengthDouble(style, rootStyle, multiplier), Fixed);
3322             else
3323                 l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed);
3324         }
3325         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3326             l = Length(primitiveValue->getDoubleValue(), Percent);
3327         else if (type == CSSPrimitiveValue::CSS_NUMBER)
3328             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
3329         else if (ok)
3330             *ok = false;
3331     }
3332     return l;
3333 }
3334 
convertToIntLength(CSSPrimitiveValue * primitiveValue,RenderStyle * style,RenderStyle * rootStyle,double multiplier=1,bool * ok=0)3335 static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
3336 {
3337     return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
3338 }
3339 
convertToFloatLength(CSSPrimitiveValue * primitiveValue,RenderStyle * style,RenderStyle * rootStyle,double multiplier=1,bool * ok=0)3340 static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
3341 {
3342     return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
3343 }
3344 
3345 template <bool applyFirst>
applyDeclarations(bool isImportant,int startIndex,int endIndex)3346 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex)
3347 {
3348     if (startIndex == -1)
3349         return;
3350 
3351     for (int i = startIndex; i <= endIndex; i++) {
3352         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
3353         CSSMutableStyleDeclaration::const_iterator end = decl->end();
3354         for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {
3355             const CSSProperty& current = *it;
3356             if (isImportant == current.isImportant()) {
3357                 int property = current.id();
3358 
3359                 if (applyFirst) {
3360                     COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
3361                     COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 14, CSS_zoom_is_end_of_first_prop_range);
3362                     COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
3363 
3364                     // give special priority to font-xxx, color properties, etc
3365                     if (property <= CSSPropertyLineHeight) {
3366                         // we apply line-height later
3367                         if (property == CSSPropertyLineHeight)
3368                             m_lineHeightValue = current.value();
3369                         else
3370                             applyProperty(current.id(), current.value());
3371                     }
3372                 } else {
3373                     if (property > CSSPropertyLineHeight)
3374                         applyProperty(current.id(), current.value());
3375                 }
3376             }
3377         }
3378     }
3379 }
3380 
matchPageRules(RuleSet * rules,bool isLeftPage,bool isFirstPage,const String & pageName)3381 void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
3382 {
3383     m_matchedRules.clear();
3384 
3385     if (!rules)
3386         return;
3387 
3388     matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName);
3389 
3390     // If we didn't match any rules, we're done.
3391     if (m_matchedRules.isEmpty())
3392         return;
3393 
3394     // Sort the set of matched rules.
3395     sortMatchedRules();
3396 
3397     // Now transfer the set of matched rules over to our list of decls.
3398     for (unsigned i = 0; i < m_matchedRules.size(); i++)
3399         addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
3400 }
3401 
matchPageRulesForList(const Vector<RuleData> * rules,bool isLeftPage,bool isFirstPage,const String & pageName)3402 void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
3403 {
3404     if (!rules)
3405         return;
3406 
3407     unsigned size = rules->size();
3408     for (unsigned i = 0; i < size; ++i) {
3409         const RuleData& ruleData = rules->at(i);
3410         CSSStyleRule* rule = ruleData.rule();
3411         const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
3412         if (selectorLocalName != starAtom && selectorLocalName != pageName)
3413             continue;
3414         CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
3415         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
3416             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
3417             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
3418             continue;
3419 
3420         // If the rule has no properties to apply, then ignore it.
3421         CSSMutableStyleDeclaration* decl = rule->declaration();
3422         if (!decl || !decl->length())
3423             continue;
3424 
3425         // Add this rule to our list of matched rules.
3426         addMatchedRule(&ruleData);
3427     }
3428 }
3429 
isLeftPage(int pageIndex) const3430 bool CSSStyleSelector::isLeftPage(int pageIndex) const
3431 {
3432     bool isFirstPageLeft = false;
3433     if (!m_rootElementStyle->isLeftToRightDirection())
3434         isFirstPageLeft = true;
3435 
3436     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
3437 }
3438 
isFirstPage(int pageIndex) const3439 bool CSSStyleSelector::isFirstPage(int pageIndex) const
3440 {
3441     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
3442     return (!pageIndex);
3443 }
3444 
pageName(int) const3445 String CSSStyleSelector::pageName(int /* pageIndex */) const
3446 {
3447     // FIXME: Implement page index to page name mapping.
3448     return "";
3449 }
3450 
applyCounterList(RenderStyle * style,CSSValueList * list,bool isReset)3451 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
3452 {
3453     CounterDirectiveMap& map = style->accessCounterDirectives();
3454     typedef CounterDirectiveMap::iterator Iterator;
3455 
3456     Iterator end = map.end();
3457     for (Iterator it = map.begin(); it != end; ++it)
3458         if (isReset)
3459             it->second.m_reset = false;
3460         else
3461             it->second.m_increment = false;
3462 
3463     int length = list ? list->length() : 0;
3464     for (int i = 0; i < length; ++i) {
3465         CSSValue* currValue = list->itemWithoutBoundsCheck(i);
3466         if (!currValue->isPrimitiveValue())
3467             continue;
3468 
3469         Pair* pair = static_cast<CSSPrimitiveValue*>(currValue)->getPairValue();
3470         if (!pair || !pair->first() || !pair->second())
3471             continue;
3472 
3473         AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
3474         // FIXME: What about overflow?
3475         int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
3476         CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
3477         if (isReset) {
3478             directives.m_reset = true;
3479             directives.m_resetValue = value;
3480         } else {
3481             if (directives.m_increment)
3482                 directives.m_incrementValue += value;
3483             else {
3484                 directives.m_increment = true;
3485                 directives.m_incrementValue = value;
3486             }
3487         }
3488     }
3489 }
3490 
applyPropertyToStyle(int id,CSSValue * value,RenderStyle * style)3491 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style)
3492 {
3493     initElement(0);
3494     initForStyleResolve(0, style);
3495     m_style = style;
3496     if (value)
3497         applyProperty(id, value);
3498 }
3499 
isValidVisitedLinkProperty(int id)3500 inline bool isValidVisitedLinkProperty(int id)
3501 {
3502     switch(static_cast<CSSPropertyID>(id)) {
3503         case CSSPropertyBackgroundColor:
3504         case CSSPropertyBorderLeftColor:
3505         case CSSPropertyBorderRightColor:
3506         case CSSPropertyBorderTopColor:
3507         case CSSPropertyBorderBottomColor:
3508         case CSSPropertyColor:
3509         case CSSPropertyOutlineColor:
3510         case CSSPropertyWebkitColumnRuleColor:
3511         case CSSPropertyWebkitTextEmphasisColor:
3512         case CSSPropertyWebkitTextFillColor:
3513         case CSSPropertyWebkitTextStrokeColor:
3514         // Also allow shorthands so that inherit/initial still work.
3515         case CSSPropertyBackground:
3516         case CSSPropertyBorderLeft:
3517         case CSSPropertyBorderRight:
3518         case CSSPropertyBorderTop:
3519         case CSSPropertyBorderBottom:
3520         case CSSPropertyOutline:
3521         case CSSPropertyWebkitColumnRule:
3522 #if ENABLE(SVG)
3523         case CSSPropertyFill:
3524         case CSSPropertyStroke:
3525 #endif
3526             return true;
3527         default:
3528             break;
3529     }
3530 
3531     return false;
3532 }
3533 
3534 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
3535 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
3536 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
3537 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
3538 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
3539 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
3540 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
3541 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
useSVGZoomRules(const Element * e)3542 static inline bool useSVGZoomRules(const Element* e)
3543 {
3544     return e && e->isSVGElement();
3545 }
3546 
applyProperty(int id,CSSValue * value)3547 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
3548 {
3549     CSSPrimitiveValue* primitiveValue = 0;
3550     if (value->isPrimitiveValue())
3551         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3552 
3553     float zoomFactor = m_style->effectiveZoom();
3554 
3555     Length l;
3556     bool apply = false;
3557 
3558     unsigned short valueType = value->cssValueType();
3559 
3560     bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
3561     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
3562 
3563     id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3564 
3565     if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) {
3566         // Limit the properties that can be applied to only the ones honored by :visited.
3567         return;
3568     }
3569 
3570     CSSPropertyID property = static_cast<CSSPropertyID>(id);
3571 
3572     // check lookup table for implementations and use when available
3573     if (m_applyProperty.implements(property)) {
3574         if (isInherit)
3575             m_applyProperty.applyInheritValue(property, this);
3576         else if (isInitial)
3577             m_applyProperty.applyInitialValue(property, this);
3578         else
3579             m_applyProperty.applyValue(property, this, value);
3580         return;
3581     }
3582 
3583     // What follows is a list that maps the CSS properties into their corresponding front-end
3584     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
3585     // are only hit when mapping "inherit" or "initial" into front-end values.
3586     switch (property) {
3587 // ident only properties
3588     case CSSPropertyBorderCollapse:
3589         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
3590         if (!primitiveValue)
3591             return;
3592         switch (primitiveValue->getIdent()) {
3593             case CSSValueCollapse:
3594                 m_style->setBorderCollapse(true);
3595                 break;
3596             case CSSValueSeparate:
3597                 m_style->setBorderCollapse(false);
3598                 break;
3599             default:
3600                 return;
3601         }
3602         return;
3603     case CSSPropertyOutlineStyle:
3604         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
3605         if (primitiveValue) {
3606             if (primitiveValue->getIdent() == CSSValueAuto)
3607                 m_style->setOutlineStyle(DOTTED, true);
3608             else
3609                 m_style->setOutlineStyle(*primitiveValue);
3610         }
3611         return;
3612     case CSSPropertyCaptionSide:
3613         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
3614         return;
3615     case CSSPropertyClear:
3616         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
3617         return;
3618     case CSSPropertyDisplay:
3619         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display)
3620 #if ENABLE(WCSS)
3621         if (primitiveValue) {
3622             if (primitiveValue->getIdent() == CSSValueWapMarquee) {
3623                 // Initialize WAP Marquee style
3624                 m_style->setOverflowX(OMARQUEE);
3625                 m_style->setOverflowY(OMARQUEE);
3626                 m_style->setWhiteSpace(NOWRAP);
3627                 m_style->setMarqueeDirection(MLEFT);
3628                 m_style->setMarqueeSpeed(85); // Normal speed
3629                 m_style->setMarqueeLoopCount(1);
3630                 m_style->setMarqueeBehavior(MSCROLL);
3631 
3632                 if (m_parentStyle)
3633                     m_style->setDisplay(m_parentStyle->display());
3634                 else
3635                     m_style->setDisplay(*primitiveValue);
3636             } else
3637                 m_style->setDisplay(*primitiveValue);
3638         }
3639 #endif
3640         return;
3641     case CSSPropertyEmptyCells:
3642         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
3643         return;
3644     case CSSPropertyFloat:
3645         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
3646         return;
3647     case CSSPropertyFontStyle:
3648     {
3649         FontDescription fontDescription = m_style->fontDescription();
3650         if (isInherit)
3651             fontDescription.setItalic(m_parentStyle->fontDescription().italic());
3652         else if (isInitial)
3653             fontDescription.setItalic(false);
3654         else {
3655             if (!primitiveValue)
3656                 return;
3657             switch (primitiveValue->getIdent()) {
3658                 case CSSValueOblique:
3659                 // FIXME: oblique is the same as italic for the moment...
3660                 case CSSValueItalic:
3661                     fontDescription.setItalic(true);
3662                     break;
3663                 case CSSValueNormal:
3664                     fontDescription.setItalic(false);
3665                     break;
3666                 default:
3667                     return;
3668             }
3669         }
3670         if (m_style->setFontDescription(fontDescription))
3671             m_fontDirty = true;
3672         return;
3673     }
3674 
3675     case CSSPropertyFontVariant:
3676     {
3677         FontDescription fontDescription = m_style->fontDescription();
3678         if (isInherit)
3679             fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps());
3680         else if (isInitial)
3681             fontDescription.setSmallCaps(false);
3682         else {
3683             if (!primitiveValue)
3684                 return;
3685             int id = primitiveValue->getIdent();
3686             if (id == CSSValueNormal)
3687                 fontDescription.setSmallCaps(false);
3688             else if (id == CSSValueSmallCaps)
3689                 fontDescription.setSmallCaps(true);
3690             else
3691                 return;
3692         }
3693         if (m_style->setFontDescription(fontDescription))
3694             m_fontDirty = true;
3695         return;
3696     }
3697 
3698     case CSSPropertyFontWeight:
3699     {
3700         FontDescription fontDescription = m_style->fontDescription();
3701         if (isInherit)
3702             fontDescription.setWeight(m_parentStyle->fontDescription().weight());
3703         else if (isInitial)
3704             fontDescription.setWeight(FontWeightNormal);
3705         else {
3706             if (!primitiveValue)
3707                 return;
3708             if (primitiveValue->getIdent()) {
3709                 switch (primitiveValue->getIdent()) {
3710                     case CSSValueBolder:
3711                         fontDescription.setWeight(fontDescription.bolderWeight());
3712                         break;
3713                     case CSSValueLighter:
3714                         fontDescription.setWeight(fontDescription.lighterWeight());
3715                         break;
3716                     case CSSValueBold:
3717                     case CSSValue700:
3718                         fontDescription.setWeight(FontWeightBold);
3719                         break;
3720                     case CSSValueNormal:
3721                     case CSSValue400:
3722                         fontDescription.setWeight(FontWeightNormal);
3723                         break;
3724                     case CSSValue900:
3725                         fontDescription.setWeight(FontWeight900);
3726                         break;
3727                     case CSSValue800:
3728                         fontDescription.setWeight(FontWeight800);
3729                         break;
3730                     case CSSValue600:
3731                         fontDescription.setWeight(FontWeight600);
3732                         break;
3733                     case CSSValue500:
3734                         fontDescription.setWeight(FontWeight500);
3735                         break;
3736                     case CSSValue300:
3737                         fontDescription.setWeight(FontWeight300);
3738                         break;
3739                     case CSSValue200:
3740                         fontDescription.setWeight(FontWeight200);
3741                         break;
3742                     case CSSValue100:
3743                         fontDescription.setWeight(FontWeight100);
3744                         break;
3745                     default:
3746                         return;
3747                 }
3748             } else
3749                 ASSERT_NOT_REACHED();
3750         }
3751         if (m_style->setFontDescription(fontDescription))
3752             m_fontDirty = true;
3753         return;
3754     }
3755 
3756     case CSSPropertyListStylePosition:
3757         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStylePosition, ListStylePosition)
3758         return;
3759     case CSSPropertyListStyleType:
3760         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType)
3761         return;
3762     case CSSPropertyPageBreakBefore:
3763         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
3764         return;
3765     case CSSPropertyPageBreakAfter:
3766         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
3767         return;
3768     case CSSPropertyPageBreakInside: {
3769         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
3770         if (!primitiveValue)
3771             return;
3772         EPageBreak pageBreak = *primitiveValue;
3773         if (pageBreak != PBALWAYS)
3774             m_style->setPageBreakInside(pageBreak);
3775         return;
3776     }
3777 
3778     case CSSPropertyPosition:
3779         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
3780         return;
3781     case CSSPropertyTableLayout: {
3782         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
3783 
3784         ETableLayout l = *primitiveValue;
3785         if (l == TAUTO)
3786             l = RenderStyle::initialTableLayout();
3787 
3788         m_style->setTableLayout(l);
3789         return;
3790     }
3791 
3792     case CSSPropertyUnicodeBidi:
3793         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
3794         return;
3795     case CSSPropertyTextTransform:
3796         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
3797         return;
3798     case CSSPropertyVisibility:
3799         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
3800         return;
3801     case CSSPropertyWhiteSpace:
3802         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
3803         return;
3804     case CSSPropertyBorderSpacing: {
3805         if (isInherit) {
3806             m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing());
3807             m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing());
3808         }
3809         else if (isInitial) {
3810             m_style->setHorizontalBorderSpacing(0);
3811             m_style->setVerticalBorderSpacing(0);
3812         }
3813         return;
3814     }
3815     case CSSPropertyWebkitBorderHorizontalSpacing: {
3816         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
3817         if (!primitiveValue)
3818             return;
3819         short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3820         m_style->setHorizontalBorderSpacing(spacing);
3821         return;
3822     }
3823     case CSSPropertyWebkitBorderVerticalSpacing: {
3824         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
3825         if (!primitiveValue)
3826             return;
3827         short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3828         m_style->setVerticalBorderSpacing(spacing);
3829         return;
3830     }
3831     case CSSPropertyCursor:
3832         if (isInherit) {
3833             m_style->setCursor(m_parentStyle->cursor());
3834             m_style->setCursorList(m_parentStyle->cursors());
3835             return;
3836         }
3837         m_style->clearCursorList();
3838         if (isInitial) {
3839             m_style->setCursor(RenderStyle::initialCursor());
3840             return;
3841         }
3842         if (value->isValueList()) {
3843             CSSValueList* list = static_cast<CSSValueList*>(value);
3844             int len = list->length();
3845             m_style->setCursor(CURSOR_AUTO);
3846             for (int i = 0; i < len; i++) {
3847                 CSSValue* item = list->itemWithoutBoundsCheck(i);
3848                 if (!item->isPrimitiveValue())
3849                     continue;
3850                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3851                 int type = primitiveValue->primitiveType();
3852                 if (type == CSSPrimitiveValue::CSS_URI) {
3853                     if (primitiveValue->isCursorImageValue()) {
3854                         CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
3855                         if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style.
3856                             m_style->setUnique();
3857                         m_style->addCursor(cachedOrPendingFromValue(CSSPropertyCursor, image), image->hotSpot());
3858                     }
3859                 } else if (type == CSSPrimitiveValue::CSS_IDENT)
3860                     m_style->setCursor(*primitiveValue);
3861             }
3862         } else if (primitiveValue) {
3863             int type = primitiveValue->primitiveType();
3864             if (type == CSSPrimitiveValue::CSS_IDENT && m_style->cursor() != ECursor(*primitiveValue))
3865                 m_style->setCursor(*primitiveValue);
3866         }
3867         return;
3868 
3869 // uri || inherit
3870     case CSSPropertyListStyleImage:
3871     {
3872         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
3873         m_style->setListStyleImage(styleImage(CSSPropertyListStyleImage, value));
3874         return;
3875     }
3876 
3877 // length
3878     case CSSPropertyBorderTopWidth:
3879     case CSSPropertyBorderRightWidth:
3880     case CSSPropertyBorderBottomWidth:
3881     case CSSPropertyBorderLeftWidth:
3882     case CSSPropertyOutlineWidth:
3883     case CSSPropertyWebkitColumnRuleWidth:
3884     {
3885         if (isInherit) {
3886             HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth)
3887             HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth)
3888             HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth)
3889             HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth)
3890             HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth)
3891             HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth)
3892             return;
3893         }
3894         else if (isInitial) {
3895             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth)
3896             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth)
3897             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth)
3898             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth)
3899             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth)
3900             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth)
3901             return;
3902         }
3903 
3904         if (!primitiveValue)
3905             return;
3906         short width = 3;
3907         switch (primitiveValue->getIdent()) {
3908         case CSSValueThin:
3909             width = 1;
3910             break;
3911         case CSSValueMedium:
3912             width = 3;
3913             break;
3914         case CSSValueThick:
3915             width = 5;
3916             break;
3917         case CSSValueInvalid:
3918             width = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3919             break;
3920         default:
3921             return;
3922         }
3923 
3924         if (width < 0) return;
3925         switch (id) {
3926         case CSSPropertyBorderTopWidth:
3927             m_style->setBorderTopWidth(width);
3928             break;
3929         case CSSPropertyBorderRightWidth:
3930             m_style->setBorderRightWidth(width);
3931             break;
3932         case CSSPropertyBorderBottomWidth:
3933             m_style->setBorderBottomWidth(width);
3934             break;
3935         case CSSPropertyBorderLeftWidth:
3936             m_style->setBorderLeftWidth(width);
3937             break;
3938         case CSSPropertyOutlineWidth:
3939             m_style->setOutlineWidth(width);
3940             break;
3941         case CSSPropertyWebkitColumnRuleWidth:
3942             m_style->setColumnRuleWidth(width);
3943             break;
3944         default:
3945             return;
3946         }
3947         return;
3948     }
3949 
3950     case CSSPropertyWebkitFontSmoothing: {
3951         FontDescription fontDescription = m_style->fontDescription();
3952         if (isInherit)
3953             fontDescription.setFontSmoothing(m_parentStyle->fontDescription().fontSmoothing());
3954         else if (isInitial)
3955             fontDescription.setFontSmoothing(AutoSmoothing);
3956         else {
3957             if (!primitiveValue)
3958                 return;
3959             int id = primitiveValue->getIdent();
3960             FontSmoothingMode smoothing;
3961             switch (id) {
3962                 case CSSValueAuto:
3963                     smoothing = AutoSmoothing;
3964                     break;
3965                 case CSSValueNone:
3966                     smoothing = NoSmoothing;
3967                     break;
3968                 case CSSValueAntialiased:
3969                     smoothing = Antialiased;
3970                     break;
3971                 case CSSValueSubpixelAntialiased:
3972                     smoothing = SubpixelAntialiased;
3973                     break;
3974                 default:
3975                     ASSERT_NOT_REACHED();
3976                     smoothing = AutoSmoothing;
3977             }
3978             fontDescription.setFontSmoothing(smoothing);
3979         }
3980         if (m_style->setFontDescription(fontDescription))
3981             m_fontDirty = true;
3982         return;
3983     }
3984 
3985     case CSSPropertyLetterSpacing:
3986     case CSSPropertyWordSpacing:
3987     {
3988         if (isInherit) {
3989             HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing)
3990             HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing)
3991             return;
3992         }
3993         else if (isInitial) {
3994             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing)
3995             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing)
3996             return;
3997         }
3998 
3999         int width = 0;
4000         if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
4001             width = 0;
4002         } else {
4003             if (!primitiveValue)
4004                 return;
4005             width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules(m_element) ? 1.0f : zoomFactor);
4006         }
4007         switch (id) {
4008         case CSSPropertyLetterSpacing:
4009             m_style->setLetterSpacing(width);
4010             break;
4011         case CSSPropertyWordSpacing:
4012             m_style->setWordSpacing(width);
4013             break;
4014             // ### needs the definitions in renderstyle
4015         default: break;
4016         }
4017         return;
4018     }
4019 
4020     case CSSPropertyWordBreak:
4021         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
4022         return;
4023     case CSSPropertyWordWrap:
4024         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
4025         return;
4026     case CSSPropertyWebkitNbspMode:
4027         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
4028         return;
4029     case CSSPropertyWebkitLineBreak:
4030         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
4031         return;
4032     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
4033         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
4034         return;
4035 
4036     case CSSPropertyResize:
4037     {
4038         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
4039 
4040         if (!primitiveValue->getIdent())
4041             return;
4042 
4043         EResize r = RESIZE_NONE;
4044         if (primitiveValue->getIdent() == CSSValueAuto) {
4045             if (Settings* settings = m_checker.m_document->settings())
4046                 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
4047         } else
4048             r = *primitiveValue;
4049 
4050         m_style->setResize(r);
4051         return;
4052     }
4053 
4054     // length, percent
4055     case CSSPropertyMaxWidth:
4056         // +none +inherit
4057         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
4058             l = Length(undefinedLength, Fixed);
4059             apply = true;
4060         }
4061     case CSSPropertyTop:
4062     case CSSPropertyLeft:
4063     case CSSPropertyRight:
4064     case CSSPropertyBottom:
4065     case CSSPropertyWidth:
4066     case CSSPropertyMinWidth:
4067     case CSSPropertyMarginTop:
4068     case CSSPropertyMarginRight:
4069     case CSSPropertyMarginBottom:
4070     case CSSPropertyMarginLeft:
4071         // +inherit +auto
4072         if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) {
4073             if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
4074                 l = Length(Intrinsic);
4075                 apply = true;
4076             }
4077             else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
4078                 l = Length(MinIntrinsic);
4079                 apply = true;
4080             }
4081         }
4082         if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
4083             apply = true;
4084     case CSSPropertyPaddingTop:
4085     case CSSPropertyPaddingRight:
4086     case CSSPropertyPaddingBottom:
4087     case CSSPropertyPaddingLeft:
4088     case CSSPropertyTextIndent:
4089         // +inherit
4090     {
4091         if (isInherit) {
4092             HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth)
4093             HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom)
4094             HANDLE_INHERIT_COND(CSSPropertyTop, top, Top)
4095             HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left)
4096             HANDLE_INHERIT_COND(CSSPropertyRight, right, Right)
4097             HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width)
4098             HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth)
4099             HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop)
4100             HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight)
4101             HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom)
4102             HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft)
4103             HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop)
4104             HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight)
4105             HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom)
4106             HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft)
4107             HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent)
4108             return;
4109         }
4110         else if (isInitial) {
4111             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize)
4112             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset)
4113             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset)
4114             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset)
4115             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset)
4116             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size)
4117             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize)
4118             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding)
4119             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding)
4120             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding)
4121             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding)
4122             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin)
4123             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin)
4124             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin)
4125             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin)
4126             HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent)
4127             return;
4128         }
4129 
4130         if (primitiveValue && !apply) {
4131             int type = primitiveValue->primitiveType();
4132             if (CSSPrimitiveValue::isUnitTypeLength(type))
4133                 // Handle our quirky margin units if we have them.
4134                 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed,
4135                            primitiveValue->isQuirkValue());
4136             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4137                 l = Length(primitiveValue->getDoubleValue(), Percent);
4138             else
4139                 return;
4140             apply = true;
4141         }
4142         if (!apply) return;
4143         switch (id) {
4144             case CSSPropertyMaxWidth:
4145                 m_style->setMaxWidth(l);
4146                 break;
4147             case CSSPropertyBottom:
4148                 m_style->setBottom(l);
4149                 break;
4150             case CSSPropertyTop:
4151                 m_style->setTop(l);
4152                 break;
4153             case CSSPropertyLeft:
4154                 m_style->setLeft(l);
4155                 break;
4156             case CSSPropertyRight:
4157                 m_style->setRight(l);
4158                 break;
4159             case CSSPropertyWidth:
4160                 m_style->setWidth(l);
4161                 break;
4162             case CSSPropertyMinWidth:
4163                 m_style->setMinWidth(l);
4164                 break;
4165             case CSSPropertyPaddingTop:
4166                 m_style->setPaddingTop(l);
4167                 break;
4168             case CSSPropertyPaddingRight:
4169                 m_style->setPaddingRight(l);
4170                 break;
4171             case CSSPropertyPaddingBottom:
4172                 m_style->setPaddingBottom(l);
4173                 break;
4174             case CSSPropertyPaddingLeft:
4175                 m_style->setPaddingLeft(l);
4176                 break;
4177             case CSSPropertyMarginTop:
4178                 m_style->setMarginTop(l);
4179                 break;
4180             case CSSPropertyMarginRight:
4181                 m_style->setMarginRight(l);
4182                 break;
4183             case CSSPropertyMarginBottom:
4184                 m_style->setMarginBottom(l);
4185                 break;
4186             case CSSPropertyMarginLeft:
4187                 m_style->setMarginLeft(l);
4188                 break;
4189             case CSSPropertyTextIndent:
4190                 m_style->setTextIndent(l);
4191                 break;
4192             default:
4193                 break;
4194             }
4195         return;
4196     }
4197 
4198     case CSSPropertyMaxHeight:
4199         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
4200             l = Length(undefinedLength, Fixed);
4201             apply = true;
4202         }
4203     case CSSPropertyHeight:
4204     case CSSPropertyMinHeight:
4205         if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
4206             l = Length(Intrinsic);
4207             apply = true;
4208         } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
4209             l = Length(MinIntrinsic);
4210             apply = true;
4211         } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
4212             apply = true;
4213         if (isInherit) {
4214             HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight)
4215             HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height)
4216             HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight)
4217             return;
4218         }
4219         if (isInitial) {
4220             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize)
4221             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size)
4222             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize)
4223             return;
4224         }
4225 
4226         if (primitiveValue && !apply) {
4227             unsigned short type = primitiveValue->primitiveType();
4228             if (CSSPrimitiveValue::isUnitTypeLength(type))
4229                 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
4230             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4231                 l = Length(primitiveValue->getDoubleValue(), Percent);
4232             else
4233                 return;
4234             apply = true;
4235         }
4236         if (apply)
4237             switch (id) {
4238                 case CSSPropertyMaxHeight:
4239                     m_style->setMaxHeight(l);
4240                     break;
4241                 case CSSPropertyHeight:
4242                     m_style->setHeight(l);
4243                     break;
4244                 case CSSPropertyMinHeight:
4245                     m_style->setMinHeight(l);
4246                     break;
4247             }
4248         return;
4249 
4250     case CSSPropertyVerticalAlign:
4251         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
4252         if (!primitiveValue)
4253             return;
4254         if (primitiveValue->getIdent()) {
4255           EVerticalAlign align;
4256 
4257           switch (primitiveValue->getIdent()) {
4258                 case CSSValueTop:
4259                     align = TOP; break;
4260                 case CSSValueBottom:
4261                     align = BOTTOM; break;
4262                 case CSSValueMiddle:
4263                     align = MIDDLE; break;
4264                 case CSSValueBaseline:
4265                     align = BASELINE; break;
4266                 case CSSValueTextBottom:
4267                     align = TEXT_BOTTOM; break;
4268                 case CSSValueTextTop:
4269                     align = TEXT_TOP; break;
4270                 case CSSValueSub:
4271                     align = SUB; break;
4272                 case CSSValueSuper:
4273                     align = SUPER; break;
4274                 case CSSValueWebkitBaselineMiddle:
4275                     align = BASELINE_MIDDLE; break;
4276                 default:
4277                     return;
4278             }
4279           m_style->setVerticalAlign(align);
4280           return;
4281         } else {
4282           int type = primitiveValue->primitiveType();
4283           Length l;
4284           if (CSSPrimitiveValue::isUnitTypeLength(type))
4285             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
4286           else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4287             l = Length(primitiveValue->getDoubleValue(), Percent);
4288 
4289           m_style->setVerticalAlign(LENGTH);
4290           m_style->setVerticalAlignLength(l);
4291         }
4292         return;
4293 
4294     case CSSPropertyFontSize:
4295     {
4296         FontDescription fontDescription = m_style->fontDescription();
4297         fontDescription.setKeywordSize(0);
4298         float oldSize = 0;
4299         float size = 0;
4300 
4301         bool parentIsAbsoluteSize = false;
4302         if (m_parentNode) {
4303             oldSize = m_parentStyle->fontDescription().specifiedSize();
4304             parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
4305         }
4306 
4307         if (isInherit) {
4308             size = oldSize;
4309             if (m_parentNode)
4310                 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
4311         } else if (isInitial) {
4312             size = fontSizeForKeyword(m_checker.m_document, CSSValueMedium, fontDescription.useFixedDefaultSize());
4313             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
4314         } else if (primitiveValue->getIdent()) {
4315             // Keywords are being used.
4316             switch (primitiveValue->getIdent()) {
4317                 case CSSValueXxSmall:
4318                 case CSSValueXSmall:
4319                 case CSSValueSmall:
4320                 case CSSValueMedium:
4321                 case CSSValueLarge:
4322                 case CSSValueXLarge:
4323                 case CSSValueXxLarge:
4324                 case CSSValueWebkitXxxLarge:
4325                     size = fontSizeForKeyword(m_checker.m_document, primitiveValue->getIdent(), fontDescription.useFixedDefaultSize());
4326                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
4327                     break;
4328                 case CSSValueLarger:
4329                     size = largerFontSize(oldSize, m_checker.m_document->inQuirksMode());
4330                     break;
4331                 case CSSValueSmaller:
4332                     size = smallerFontSize(oldSize, m_checker.m_document->inQuirksMode());
4333                     break;
4334                 default:
4335                     return;
4336             }
4337 
4338             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
4339                                               (primitiveValue->getIdent() == CSSValueLarger ||
4340                                                primitiveValue->getIdent() == CSSValueSmaller));
4341         } else {
4342             int type = primitiveValue->primitiveType();
4343             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
4344                                               (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
4345                                                type != CSSPrimitiveValue::CSS_EMS &&
4346                                                type != CSSPrimitiveValue::CSS_EXS &&
4347                                                type != CSSPrimitiveValue::CSS_REMS));
4348             if (CSSPrimitiveValue::isUnitTypeLength(type))
4349                 size = primitiveValue->computeLengthFloat(m_parentStyle, m_rootElementStyle, true);
4350             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4351                 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
4352             else
4353                 return;
4354         }
4355 
4356         if (size < 0)
4357             return;
4358 
4359         setFontSize(fontDescription, size);
4360         if (m_style->setFontDescription(fontDescription))
4361             m_fontDirty = true;
4362         return;
4363     }
4364 
4365     case CSSPropertyZIndex: {
4366         if (isInherit) {
4367             if (m_parentStyle->hasAutoZIndex())
4368                 m_style->setHasAutoZIndex();
4369             else
4370                 m_style->setZIndex(m_parentStyle->zIndex());
4371             return;
4372         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
4373             m_style->setHasAutoZIndex();
4374             return;
4375         }
4376 
4377         // FIXME: Should clamp all sorts of other integer properties too.
4378         m_style->setZIndex(clampToInteger(primitiveValue->getDoubleValue()));
4379         return;
4380     }
4381     case CSSPropertyWidows:
4382     {
4383         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
4384         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4385             return;
4386         m_style->setWidows(primitiveValue->getIntValue());
4387         return;
4388     }
4389 
4390     case CSSPropertyOrphans:
4391     {
4392         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
4393         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4394             return;
4395         m_style->setOrphans(primitiveValue->getIntValue());
4396         return;
4397     }
4398 
4399 // length, percent, number
4400     case CSSPropertyLineHeight:
4401     {
4402         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
4403         if (!primitiveValue)
4404             return;
4405         Length lineHeight;
4406         int type = primitiveValue->primitiveType();
4407         if (primitiveValue->getIdent() == CSSValueNormal)
4408             lineHeight = Length(-100.0, Percent);
4409         else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
4410             double multiplier = zoomFactor;
4411             if (m_style->textSizeAdjust()) {
4412                 if (Frame* frame = m_checker.m_document->frame())
4413                     multiplier *= frame->textZoomFactor();
4414             }
4415             lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle,  multiplier), Fixed);
4416         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4417             lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
4418         else if (type == CSSPrimitiveValue::CSS_NUMBER)
4419             lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
4420         else
4421             return;
4422         m_style->setLineHeight(lineHeight);
4423         return;
4424     }
4425 
4426 // string
4427     case CSSPropertyTextAlign:
4428     {
4429         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
4430         if (!primitiveValue)
4431             return;
4432         if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) {
4433             if (m_parentStyle->textAlign() == TASTART)
4434                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT);
4435             else if (m_parentStyle->textAlign() == TAEND)
4436                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT);
4437             else
4438                 m_style->setTextAlign(m_parentStyle->textAlign());
4439             return;
4440         }
4441         m_style->setTextAlign(*primitiveValue);
4442         return;
4443     }
4444 
4445 // rect
4446     case CSSPropertyClip:
4447     {
4448         Length top;
4449         Length right;
4450         Length bottom;
4451         Length left;
4452         bool hasClip = true;
4453         if (isInherit) {
4454             if (m_parentStyle->hasClip()) {
4455                 top = m_parentStyle->clipTop();
4456                 right = m_parentStyle->clipRight();
4457                 bottom = m_parentStyle->clipBottom();
4458                 left = m_parentStyle->clipLeft();
4459             } else {
4460                 hasClip = false;
4461                 top = right = bottom = left = Length();
4462             }
4463         } else if (isInitial) {
4464             hasClip = false;
4465             top = right = bottom = left = Length();
4466         } else if (!primitiveValue) {
4467             return;
4468         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
4469             Rect* rect = primitiveValue->getRectValue();
4470             if (!rect)
4471                 return;
4472             top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
4473             right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
4474             bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
4475             left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
4476         } else if (primitiveValue->getIdent() != CSSValueAuto) {
4477             return;
4478         }
4479         m_style->setClip(top, right, bottom, left);
4480         m_style->setHasClip(hasClip);
4481 
4482         // rect, ident
4483         return;
4484     }
4485 
4486 // lists
4487     case CSSPropertyContent:
4488         // list of string, uri, counter, attr, i
4489     {
4490         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
4491         // note is a reminder that eventually "inherit" needs to be supported.
4492 
4493         if (isInitial) {
4494             m_style->clearContent();
4495             return;
4496         }
4497 
4498         if (!value->isValueList())
4499             return;
4500 
4501         CSSValueList* list = static_cast<CSSValueList*>(value);
4502         int len = list->length();
4503 
4504         bool didSet = false;
4505         for (int i = 0; i < len; i++) {
4506             CSSValue* item = list->itemWithoutBoundsCheck(i);
4507             if (item->isImageGeneratorValue()) {
4508                 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
4509                 didSet = true;
4510             }
4511 
4512             if (!item->isPrimitiveValue())
4513                 continue;
4514 
4515             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
4516             switch (contentValue->primitiveType()) {
4517             case CSSPrimitiveValue::CSS_STRING:
4518                 m_style->setContent(contentValue->getStringValue().impl(), didSet);
4519                 didSet = true;
4520                 break;
4521             case CSSPrimitiveValue::CSS_ATTR: {
4522                 // FIXME: Can a namespace be specified for an attr(foo)?
4523                 if (m_style->styleType() == NOPSEUDO)
4524                     m_style->setUnique();
4525                 else
4526                     m_parentStyle->setUnique();
4527                 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
4528                 m_style->setContent(m_element->getAttribute(attr).impl(), didSet);
4529                 didSet = true;
4530                 // register the fact that the attribute value affects the style
4531                 m_selectorAttrs.add(attr.localName().impl());
4532                 break;
4533             }
4534             case CSSPrimitiveValue::CSS_URI: {
4535                 if (!contentValue->isImageValue())
4536                     break;
4537                 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
4538                 didSet = true;
4539                 break;
4540             }
4541             case CSSPrimitiveValue::CSS_COUNTER: {
4542                 Counter* counterValue = contentValue->getCounterValue();
4543                 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(),
4544                     (EListStyleType)counterValue->listStyleNumber(), counterValue->separator()));
4545                 m_style->setContent(counter.release(), didSet);
4546                 didSet = true;
4547                 break;
4548             }
4549             case CSSPrimitiveValue::CSS_IDENT:
4550                 switch (contentValue->getIdent()) {
4551                 case CSSValueOpenQuote:
4552                     m_style->setContent(OPEN_QUOTE, didSet);
4553                     didSet = true;
4554                     break;
4555                 case CSSValueCloseQuote:
4556                     m_style->setContent(CLOSE_QUOTE, didSet);
4557                     didSet = true;
4558                     break;
4559                 case CSSValueNoOpenQuote:
4560                     m_style->setContent(NO_OPEN_QUOTE, didSet);
4561                     didSet = true;
4562                     break;
4563                 case CSSValueNoCloseQuote:
4564                     m_style->setContent(NO_CLOSE_QUOTE, didSet);
4565                     didSet = true;
4566                     break;
4567                 default:
4568                     // normal and none do not have any effect.
4569                     {}
4570                 }
4571             }
4572         }
4573         if (!didSet)
4574             m_style->clearContent();
4575         return;
4576     }
4577     case CSSPropertyQuotes:
4578         if (isInherit) {
4579             if (m_parentStyle)
4580                 m_style->setQuotes(m_parentStyle->quotes());
4581             return;
4582         }
4583         if (isInitial) {
4584             m_style->setQuotes(0);
4585             return;
4586         }
4587         if (value->isValueList()) {
4588             CSSValueList* list = static_cast<CSSValueList*>(value);
4589             size_t length = list->length();
4590             QuotesData* data = QuotesData::create(length);
4591             if (!data)
4592                 return; // Out of memory
4593             String* quotes = data->data();
4594             for (size_t i = 0; i < length; i++) {
4595                 CSSValue* item = list->itemWithoutBoundsCheck(i);
4596                 ASSERT(item->isPrimitiveValue());
4597                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
4598                 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
4599                 quotes[i] = primitiveValue->getStringValue();
4600             }
4601             m_style->setQuotes(adoptRef(data));
4602         } else if (primitiveValue) {
4603             ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
4604             if (primitiveValue->getIdent() == CSSValueNone)
4605                 m_style->setQuotes(adoptRef(QuotesData::create(0)));
4606         }
4607         return;
4608 
4609     case CSSPropertyCounterIncrement:
4610         applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false);
4611         return;
4612     case CSSPropertyCounterReset:
4613         applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true);
4614         return;
4615 
4616     case CSSPropertyFontFamily: {
4617         // list of strings and ids
4618         if (isInherit) {
4619             FontDescription parentFontDescription = m_parentStyle->fontDescription();
4620             FontDescription fontDescription = m_style->fontDescription();
4621             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
4622             fontDescription.setFamily(parentFontDescription.firstFamily());
4623             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
4624             if (m_style->setFontDescription(fontDescription))
4625                 m_fontDirty = true;
4626             return;
4627         } else if (isInitial) {
4628             FontDescription initialDesc = FontDescription();
4629             FontDescription fontDescription = m_style->fontDescription();
4630             // We need to adjust the size to account for the generic family change from monospace
4631             // to non-monospace.
4632             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
4633                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
4634             fontDescription.setGenericFamily(initialDesc.genericFamily());
4635             if (!initialDesc.firstFamily().familyIsEmpty())
4636                 fontDescription.setFamily(initialDesc.firstFamily());
4637             if (m_style->setFontDescription(fontDescription))
4638                 m_fontDirty = true;
4639             return;
4640         }
4641 
4642         if (!value->isValueList())
4643             return;
4644         FontDescription fontDescription = m_style->fontDescription();
4645         CSSValueList* list = static_cast<CSSValueList*>(value);
4646         int len = list->length();
4647         FontFamily& firstFamily = fontDescription.firstFamily();
4648         FontFamily* currFamily = 0;
4649 
4650         // Before mapping in a new font-family property, we should reset the generic family.
4651         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
4652         fontDescription.setGenericFamily(FontDescription::NoFamily);
4653 
4654         for (int i = 0; i < len; i++) {
4655             CSSValue* item = list->itemWithoutBoundsCheck(i);
4656             if (!item->isPrimitiveValue())
4657                 continue;
4658             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
4659             AtomicString face;
4660             Settings* settings = m_checker.m_document->settings();
4661             if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
4662                 if (contentValue->isFontFamilyValue())
4663                     face = static_cast<FontFamilyValue*>(contentValue)->familyName();
4664             } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
4665                 switch (contentValue->getIdent()) {
4666                     case CSSValueWebkitBody:
4667                         face = settings->standardFontFamily();
4668                         break;
4669                     case CSSValueSerif:
4670                         face = "-webkit-serif";
4671                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
4672                         break;
4673                     case CSSValueSansSerif:
4674                         face = "-webkit-sans-serif";
4675                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
4676                         break;
4677                     case CSSValueCursive:
4678                         face = "-webkit-cursive";
4679                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
4680                         break;
4681                     case CSSValueFantasy:
4682                         face = "-webkit-fantasy";
4683                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
4684                         break;
4685                     case CSSValueMonospace:
4686                         face = "-webkit-monospace";
4687                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
4688                         break;
4689                 }
4690             }
4691 
4692             if (!face.isEmpty()) {
4693                 if (!currFamily) {
4694                     // Filling in the first family.
4695                     firstFamily.setFamily(face);
4696                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
4697                     currFamily = &firstFamily;
4698                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
4699                 } else {
4700                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
4701                     newFamily->setFamily(face);
4702                     currFamily->appendFamily(newFamily);
4703                     currFamily = newFamily.get();
4704                 }
4705             }
4706         }
4707 
4708         // We can't call useFixedDefaultSize() until all new font families have been added
4709         // If currFamily is non-zero then we set at least one family on this description.
4710         if (currFamily) {
4711             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
4712                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
4713 
4714             if (m_style->setFontDescription(fontDescription))
4715                 m_fontDirty = true;
4716         }
4717         return;
4718     }
4719     case CSSPropertyTextDecoration: {
4720         // list of ident
4721         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
4722         int t = RenderStyle::initialTextDecoration();
4723         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
4724             // do nothing
4725         } else {
4726             if (!value->isValueList())
4727                 return;
4728             CSSValueList *list = static_cast<CSSValueList*>(value);
4729             int len = list->length();
4730             for (int i = 0; i < len; i++)
4731             {
4732                 CSSValue *item = list->itemWithoutBoundsCheck(i);
4733                 if (!item->isPrimitiveValue())
4734                     continue;
4735                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
4736                 switch (primitiveValue->getIdent()) {
4737                     case CSSValueNone:
4738                         t = TDNONE; break;
4739                     case CSSValueUnderline:
4740                         t |= UNDERLINE; break;
4741                     case CSSValueOverline:
4742                         t |= OVERLINE; break;
4743                     case CSSValueLineThrough:
4744                         t |= LINE_THROUGH; break;
4745                     case CSSValueBlink:
4746                         t |= BLINK; break;
4747                     default:
4748                         return;
4749                 }
4750             }
4751         }
4752 
4753         m_style->setTextDecoration(t);
4754         return;
4755     }
4756 
4757     case CSSPropertyZoom:
4758     {
4759         // Reset the zoom in effect before we do anything.  This allows the setZoom method to accurately compute a new
4760         // zoom in effect.
4761         m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
4762 
4763         // Now we can handle inherit and initial.
4764         HANDLE_INHERIT_AND_INITIAL(zoom, Zoom)
4765 
4766         // Handle normal/reset, numbers and percentages.
4767         int type = primitiveValue->primitiveType();
4768         if (primitiveValue->getIdent() == CSSValueNormal)
4769             m_style->setZoom(RenderStyle::initialZoom());
4770         else if (primitiveValue->getIdent() == CSSValueReset) {
4771             m_style->setEffectiveZoom(RenderStyle::initialZoom());
4772             m_style->setZoom(RenderStyle::initialZoom());
4773         } else if (primitiveValue->getIdent() == CSSValueDocument) {
4774             float docZoom = m_checker.m_document->renderer()->style()->zoom();
4775             m_style->setEffectiveZoom(docZoom);
4776             m_style->setZoom(docZoom);
4777         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4778             if (primitiveValue->getFloatValue())
4779                 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f);
4780         } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
4781             if (primitiveValue->getFloatValue())
4782                 m_style->setZoom(primitiveValue->getFloatValue());
4783         }
4784 
4785         m_fontDirty = true;
4786         return;
4787     }
4788 // shorthand properties
4789     case CSSPropertyBackground:
4790         if (isInitial) {
4791             m_style->clearBackgroundLayers();
4792             m_style->setBackgroundColor(Color());
4793         }
4794         else if (isInherit) {
4795             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
4796             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
4797         }
4798         return;
4799     case CSSPropertyWebkitMask:
4800         if (isInitial)
4801             m_style->clearMaskLayers();
4802         else if (isInherit)
4803             m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
4804         return;
4805 
4806     case CSSPropertyBorder:
4807     case CSSPropertyBorderStyle:
4808     case CSSPropertyBorderWidth:
4809     case CSSPropertyBorderColor:
4810         if (id == CSSPropertyBorder || id == CSSPropertyBorderColor)
4811         {
4812             if (isInherit) {
4813                 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
4814                 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
4815                 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
4816                 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color());
4817             }
4818             else if (isInitial) {
4819                 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
4820                 m_style->setBorderBottomColor(Color());
4821                 m_style->setBorderLeftColor(Color());
4822                 m_style->setBorderRightColor(Color());
4823             }
4824         }
4825         if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle)
4826         {
4827             if (isInherit) {
4828                 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
4829                 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
4830                 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
4831                 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
4832             }
4833             else if (isInitial) {
4834                 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle());
4835                 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
4836                 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
4837                 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle());
4838             }
4839         }
4840         if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth)
4841         {
4842             if (isInherit) {
4843                 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
4844                 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
4845                 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
4846                 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
4847             }
4848             else if (isInitial) {
4849                 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth());
4850                 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
4851                 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
4852                 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth());
4853             }
4854         }
4855         return;
4856     case CSSPropertyBorderTop:
4857         if (isInherit) {
4858             m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
4859             m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
4860             m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
4861         }
4862         else if (isInitial)
4863             m_style->resetBorderTop();
4864         return;
4865     case CSSPropertyBorderRight:
4866         if (isInherit) {
4867             m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color());
4868             m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
4869             m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
4870         }
4871         else if (isInitial)
4872             m_style->resetBorderRight();
4873         return;
4874     case CSSPropertyBorderBottom:
4875         if (isInherit) {
4876             m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
4877             m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
4878             m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
4879         }
4880         else if (isInitial)
4881             m_style->resetBorderBottom();
4882         return;
4883     case CSSPropertyBorderLeft:
4884         if (isInherit) {
4885             m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
4886             m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
4887             m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
4888         }
4889         else if (isInitial)
4890             m_style->resetBorderLeft();
4891         return;
4892     case CSSPropertyMargin:
4893         if (isInherit) {
4894             m_style->setMarginTop(m_parentStyle->marginTop());
4895             m_style->setMarginBottom(m_parentStyle->marginBottom());
4896             m_style->setMarginLeft(m_parentStyle->marginLeft());
4897             m_style->setMarginRight(m_parentStyle->marginRight());
4898         }
4899         else if (isInitial)
4900             m_style->resetMargin();
4901         return;
4902     case CSSPropertyPadding:
4903         if (isInherit) {
4904             m_style->setPaddingTop(m_parentStyle->paddingTop());
4905             m_style->setPaddingBottom(m_parentStyle->paddingBottom());
4906             m_style->setPaddingLeft(m_parentStyle->paddingLeft());
4907             m_style->setPaddingRight(m_parentStyle->paddingRight());
4908         }
4909         else if (isInitial)
4910             m_style->resetPadding();
4911         return;
4912     case CSSPropertyFont:
4913         if (isInherit) {
4914             FontDescription fontDescription = m_parentStyle->fontDescription();
4915             m_style->setLineHeight(m_parentStyle->lineHeight());
4916             m_lineHeightValue = 0;
4917             if (m_style->setFontDescription(fontDescription))
4918                 m_fontDirty = true;
4919         } else if (isInitial) {
4920             Settings* settings = m_checker.m_document->settings();
4921             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
4922             if (!settings)
4923                 return;
4924             FontDescription fontDescription;
4925             fontDescription.setGenericFamily(FontDescription::StandardFamily);
4926             fontDescription.setRenderingMode(settings->fontRenderingMode());
4927             fontDescription.setUsePrinterFont(m_checker.m_document->printing());
4928             const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily();
4929             if (!standardFontFamily.isEmpty()) {
4930                 fontDescription.firstFamily().setFamily(standardFontFamily);
4931                 fontDescription.firstFamily().appendFamily(0);
4932             }
4933             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
4934             setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueMedium, false));
4935             m_style->setLineHeight(RenderStyle::initialLineHeight());
4936             m_lineHeightValue = 0;
4937             if (m_style->setFontDescription(fontDescription))
4938                 m_fontDirty = true;
4939         } else if (primitiveValue) {
4940             m_style->setLineHeight(RenderStyle::initialLineHeight());
4941             m_lineHeightValue = 0;
4942 
4943             FontDescription fontDescription;
4944             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
4945 
4946             // Double-check and see if the theme did anything.  If not, don't bother updating the font.
4947             if (fontDescription.isAbsoluteSize()) {
4948                 // Make sure the rendering mode and printer font settings are updated.
4949                 Settings* settings = m_checker.m_document->settings();
4950                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
4951                 if (!settings)
4952                     return;
4953                 fontDescription.setRenderingMode(settings->fontRenderingMode());
4954                 fontDescription.setUsePrinterFont(m_checker.m_document->printing());
4955 
4956                 // Handle the zoom factor.
4957                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules(m_element)));
4958                 if (m_style->setFontDescription(fontDescription))
4959                     m_fontDirty = true;
4960             }
4961         } else if (value->isFontValue()) {
4962             FontValue *font = static_cast<FontValue*>(value);
4963             if (!font->style || !font->variant || !font->weight ||
4964                  !font->size || !font->lineHeight || !font->family)
4965                 return;
4966             applyProperty(CSSPropertyFontStyle, font->style.get());
4967             applyProperty(CSSPropertyFontVariant, font->variant.get());
4968             applyProperty(CSSPropertyFontWeight, font->weight.get());
4969             applyProperty(CSSPropertyFontSize, font->size.get());
4970 
4971             m_lineHeightValue = font->lineHeight.get();
4972 
4973             applyProperty(CSSPropertyFontFamily, font->family.get());
4974         }
4975         return;
4976 
4977     case CSSPropertyListStyle:
4978         if (isInherit) {
4979             m_style->setListStyleType(m_parentStyle->listStyleType());
4980             m_style->setListStyleImage(m_parentStyle->listStyleImage());
4981             m_style->setListStylePosition(m_parentStyle->listStylePosition());
4982         }
4983         else if (isInitial) {
4984             m_style->setListStyleType(RenderStyle::initialListStyleType());
4985             m_style->setListStyleImage(RenderStyle::initialListStyleImage());
4986             m_style->setListStylePosition(RenderStyle::initialListStylePosition());
4987         }
4988         return;
4989     case CSSPropertyOutline:
4990         if (isInherit) {
4991             m_style->setOutlineWidth(m_parentStyle->outlineWidth());
4992             m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
4993             m_style->setOutlineStyle(m_parentStyle->outlineStyle());
4994         }
4995         else if (isInitial)
4996             m_style->resetOutline();
4997         return;
4998 
4999     // CSS3 Properties
5000     case CSSPropertyWebkitAppearance: {
5001         HANDLE_INHERIT_AND_INITIAL(appearance, Appearance)
5002         if (!primitiveValue)
5003             return;
5004         m_style->setAppearance(*primitiveValue);
5005         return;
5006     }
5007 
5008     case CSSPropertyWebkitBorderImage:
5009     case CSSPropertyWebkitMaskBoxImage: {
5010         if (isInherit) {
5011             HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
5012             HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
5013             return;
5014         } else if (isInitial) {
5015             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
5016             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
5017             return;
5018         }
5019 
5020         NinePieceImage image;
5021         mapNinePieceImage(property, value, image);
5022 
5023         if (id == CSSPropertyWebkitBorderImage)
5024             m_style->setBorderImage(image);
5025         else
5026             m_style->setMaskBoxImage(image);
5027         return;
5028     }
5029 
5030     case CSSPropertyBorderRadius:
5031     case CSSPropertyWebkitBorderRadius:
5032         if (isInherit) {
5033             m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius());
5034             m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius());
5035             m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius());
5036             m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius());
5037             return;
5038         }
5039         if (isInitial) {
5040             m_style->resetBorderRadius();
5041             return;
5042         }
5043         // Fall through
5044     case CSSPropertyBorderTopLeftRadius:
5045     case CSSPropertyBorderTopRightRadius:
5046     case CSSPropertyBorderBottomLeftRadius:
5047     case CSSPropertyBorderBottomRightRadius: {
5048         if (isInherit) {
5049             HANDLE_INHERIT_COND(CSSPropertyBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius)
5050             HANDLE_INHERIT_COND(CSSPropertyBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius)
5051             HANDLE_INHERIT_COND(CSSPropertyBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius)
5052             HANDLE_INHERIT_COND(CSSPropertyBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius)
5053             return;
5054         }
5055 
5056         if (isInitial) {
5057             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius)
5058             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopRightRadius, BorderTopRightRadius, BorderRadius)
5059             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius)
5060             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius)
5061             return;
5062         }
5063 
5064         if (!primitiveValue)
5065             return;
5066 
5067         Pair* pair = primitiveValue->getPairValue();
5068         if (!pair || !pair->first() || !pair->second())
5069             return;
5070 
5071         Length radiusWidth;
5072         Length radiusHeight;
5073         if (pair->first()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
5074             radiusWidth = Length(pair->first()->getDoubleValue(), Percent);
5075         else
5076             radiusWidth = Length(max(intMinForLength, min(intMaxForLength, pair->first()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed);
5077         if (pair->second()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
5078             radiusHeight = Length(pair->second()->getDoubleValue(), Percent);
5079         else
5080             radiusHeight = Length(max(intMinForLength, min(intMaxForLength, pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed);
5081         int width = radiusWidth.value();
5082         int height = radiusHeight.value();
5083         if (width < 0 || height < 0)
5084             return;
5085         if (width == 0)
5086             radiusHeight = radiusWidth; // Null out the other value.
5087         else if (height == 0)
5088             radiusWidth = radiusHeight; // Null out the other value.
5089 
5090         LengthSize size(radiusWidth, radiusHeight);
5091         switch (id) {
5092             case CSSPropertyBorderTopLeftRadius:
5093                 m_style->setBorderTopLeftRadius(size);
5094                 break;
5095             case CSSPropertyBorderTopRightRadius:
5096                 m_style->setBorderTopRightRadius(size);
5097                 break;
5098             case CSSPropertyBorderBottomLeftRadius:
5099                 m_style->setBorderBottomLeftRadius(size);
5100                 break;
5101             case CSSPropertyBorderBottomRightRadius:
5102                 m_style->setBorderBottomRightRadius(size);
5103                 break;
5104             default:
5105                 m_style->setBorderRadius(size);
5106                 break;
5107         }
5108         return;
5109     }
5110 
5111     case CSSPropertyOutlineOffset:
5112         HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
5113         m_style->setOutlineOffset(primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor));
5114         return;
5115     case CSSPropertyTextRendering: {
5116         FontDescription fontDescription = m_style->fontDescription();
5117         if (isInherit)
5118             fontDescription.setTextRenderingMode(m_parentStyle->fontDescription().textRenderingMode());
5119         else if (isInitial)
5120             fontDescription.setTextRenderingMode(AutoTextRendering);
5121         else {
5122             if (!primitiveValue)
5123                 return;
5124             fontDescription.setTextRenderingMode(*primitiveValue);
5125         }
5126         if (m_style->setFontDescription(fontDescription))
5127             m_fontDirty = true;
5128         return;
5129     }
5130     case CSSPropertyTextShadow:
5131     case CSSPropertyBoxShadow:
5132     case CSSPropertyWebkitBoxShadow: {
5133         if (isInherit) {
5134             if (id == CSSPropertyTextShadow)
5135                 return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0);
5136             return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0);
5137         }
5138         if (isInitial || primitiveValue) // initial | none
5139             return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0);
5140 
5141         if (!value->isValueList())
5142             return;
5143 
5144         CSSValueList *list = static_cast<CSSValueList*>(value);
5145         int len = list->length();
5146         for (int i = 0; i < len; i++) {
5147             CSSValue* currValue = list->itemWithoutBoundsCheck(i);
5148             if (!currValue->isShadowValue())
5149                 continue;
5150             ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i));
5151             int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
5152             int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
5153             int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
5154             int spread = item->spread ? item->spread->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
5155             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
5156             Color color;
5157             if (item->color)
5158                 color = getColorFromPrimitiveValue(item->color.get());
5159             ShadowData* shadowData = new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent);
5160             if (id == CSSPropertyTextShadow)
5161                 m_style->setTextShadow(shadowData, i != 0);
5162             else
5163                 m_style->setBoxShadow(shadowData, i != 0);
5164         }
5165         return;
5166     }
5167     case CSSPropertyWebkitBoxReflect: {
5168         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
5169         if (primitiveValue) {
5170             m_style->setBoxReflect(RenderStyle::initialBoxReflect());
5171             return;
5172         }
5173 
5174         if (!value->isReflectValue())
5175             return;
5176 
5177         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
5178         RefPtr<StyleReflection> reflection = StyleReflection::create();
5179         reflection->setDirection(reflectValue->direction());
5180         if (reflectValue->offset()) {
5181             int type = reflectValue->offset()->primitiveType();
5182             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5183                 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
5184             else
5185                 reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed));
5186         }
5187         NinePieceImage mask;
5188         mapNinePieceImage(property, reflectValue->mask(), mask);
5189         reflection->setMask(mask);
5190 
5191         m_style->setBoxReflect(reflection.release());
5192         return;
5193     }
5194     case CSSPropertyOpacity:
5195         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
5196         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
5197             return; // Error case.
5198         // Clamp opacity to the range 0-1
5199         m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue())));
5200         return;
5201     case CSSPropertyWebkitBoxAlign:
5202     {
5203         HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign)
5204         if (!primitiveValue)
5205             return;
5206         EBoxAlignment boxAlignment = *primitiveValue;
5207         if (boxAlignment != BJUSTIFY)
5208             m_style->setBoxAlign(boxAlignment);
5209         return;
5210     }
5211     case CSSPropertySrc: // Only used in @font-face rules.
5212         return;
5213     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
5214         return;
5215     case CSSPropertyWebkitBackfaceVisibility:
5216         HANDLE_INHERIT_AND_INITIAL(backfaceVisibility, BackfaceVisibility)
5217         if (primitiveValue)
5218             m_style->setBackfaceVisibility((primitiveValue->getIdent() == CSSValueVisible) ? BackfaceVisibilityVisible : BackfaceVisibilityHidden);
5219         return;
5220     case CSSPropertyWebkitBoxDirection:
5221         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
5222         return;
5223     case CSSPropertyWebkitBoxLines:
5224         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
5225         return;
5226     case CSSPropertyWebkitBoxOrient:
5227         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
5228         return;
5229     case CSSPropertyWebkitBoxPack:
5230     {
5231         HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
5232         if (!primitiveValue)
5233             return;
5234         EBoxAlignment boxPack = *primitiveValue;
5235         if (boxPack != BSTRETCH && boxPack != BBASELINE)
5236             m_style->setBoxPack(boxPack);
5237         return;
5238     }
5239     case CSSPropertyWebkitBoxFlex:
5240         HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex)
5241         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
5242             return; // Error case.
5243         m_style->setBoxFlex(primitiveValue->getFloatValue());
5244         return;
5245     case CSSPropertyWebkitBoxFlexGroup:
5246         HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup)
5247         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
5248             return; // Error case.
5249         m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue()));
5250         return;
5251     case CSSPropertyWebkitBoxOrdinalGroup:
5252         HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup)
5253         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
5254             return; // Error case.
5255         m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue()));
5256         return;
5257     case CSSPropertyBoxSizing:
5258         HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing)
5259         if (!primitiveValue)
5260             return;
5261         if (primitiveValue->getIdent() == CSSValueContentBox)
5262             m_style->setBoxSizing(CONTENT_BOX);
5263         else
5264             m_style->setBoxSizing(BORDER_BOX);
5265         return;
5266     case CSSPropertyWebkitColumnCount: {
5267         if (isInherit) {
5268             if (m_parentStyle->hasAutoColumnCount())
5269                 m_style->setHasAutoColumnCount();
5270             else
5271                 m_style->setColumnCount(m_parentStyle->columnCount());
5272             return;
5273         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
5274             m_style->setHasAutoColumnCount();
5275             return;
5276         }
5277         m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue()));
5278         return;
5279     }
5280     case CSSPropertyWebkitColumnGap: {
5281         if (isInherit) {
5282             if (m_parentStyle->hasNormalColumnGap())
5283                 m_style->setHasNormalColumnGap();
5284             else
5285                 m_style->setColumnGap(m_parentStyle->columnGap());
5286             return;
5287         } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) {
5288             m_style->setHasNormalColumnGap();
5289             return;
5290         }
5291         m_style->setColumnGap(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
5292         return;
5293     }
5294     case CSSPropertyWebkitColumnSpan: {
5295         HANDLE_INHERIT_AND_INITIAL(columnSpan, ColumnSpan)
5296         m_style->setColumnSpan(primitiveValue->getIdent() == CSSValueAll);
5297         return;
5298     }
5299     case CSSPropertyWebkitColumnWidth: {
5300         if (isInherit) {
5301             if (m_parentStyle->hasAutoColumnWidth())
5302                 m_style->setHasAutoColumnWidth();
5303             else
5304                 m_style->setColumnWidth(m_parentStyle->columnWidth());
5305             return;
5306         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
5307             m_style->setHasAutoColumnWidth();
5308             return;
5309         }
5310         m_style->setColumnWidth(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
5311         return;
5312     }
5313     case CSSPropertyWebkitColumnRuleStyle:
5314         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
5315         return;
5316     case CSSPropertyWebkitColumnBreakBefore:
5317         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
5318         return;
5319     case CSSPropertyWebkitColumnBreakAfter:
5320         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
5321         return;
5322     case CSSPropertyWebkitColumnBreakInside: {
5323         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
5324         EPageBreak pb = *primitiveValue;
5325         if (pb != PBALWAYS)
5326             m_style->setColumnBreakInside(pb);
5327         return;
5328     }
5329      case CSSPropertyWebkitColumnRule:
5330         if (isInherit) {
5331             m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
5332             m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
5333             m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
5334         }
5335         else if (isInitial)
5336             m_style->resetColumnRule();
5337         return;
5338     case CSSPropertyWebkitColumns:
5339         if (isInherit) {
5340             if (m_parentStyle->hasAutoColumnWidth())
5341                 m_style->setHasAutoColumnWidth();
5342             else
5343                 m_style->setColumnWidth(m_parentStyle->columnWidth());
5344             m_style->setColumnCount(m_parentStyle->columnCount());
5345         } else if (isInitial) {
5346             m_style->setHasAutoColumnWidth();
5347             m_style->setColumnCount(RenderStyle::initialColumnCount());
5348         }
5349         return;
5350     case CSSPropertyWebkitMarquee:
5351         if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
5352         m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
5353         m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
5354         m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
5355         m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
5356         m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
5357         return;
5358 #if ENABLE(WCSS)
5359     case CSSPropertyWapMarqueeLoop:
5360 #endif
5361     case CSSPropertyWebkitMarqueeRepetition: {
5362         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
5363         if (!primitiveValue)
5364             return;
5365         if (primitiveValue->getIdent() == CSSValueInfinite)
5366             m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
5367         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
5368             m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
5369         return;
5370     }
5371 #if ENABLE(WCSS)
5372     case CSSPropertyWapMarqueeSpeed:
5373 #endif
5374     case CSSPropertyWebkitMarqueeSpeed: {
5375         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
5376         if (!primitiveValue)
5377             return;
5378         if (primitiveValue->getIdent()) {
5379             switch (primitiveValue->getIdent()) {
5380                 case CSSValueSlow:
5381                     m_style->setMarqueeSpeed(500); // 500 msec.
5382                     break;
5383                 case CSSValueNormal:
5384                     m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
5385                     break;
5386                 case CSSValueFast:
5387                     m_style->setMarqueeSpeed(10); // 10msec. Super fast.
5388                     break;
5389             }
5390         }
5391         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
5392             m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
5393         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
5394             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
5395         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
5396             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
5397         return;
5398     }
5399     case CSSPropertyWebkitMarqueeIncrement: {
5400         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
5401         if (!primitiveValue)
5402             return;
5403         if (primitiveValue->getIdent()) {
5404             switch (primitiveValue->getIdent()) {
5405                 case CSSValueSmall:
5406                     m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
5407                     break;
5408                 case CSSValueNormal:
5409                     m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
5410                     break;
5411                 case CSSValueLarge:
5412                     m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
5413                     break;
5414             }
5415         }
5416         else {
5417             bool ok = true;
5418             Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
5419             if (ok)
5420                 m_style->setMarqueeIncrement(marqueeLength);
5421         }
5422         return;
5423     }
5424 #if ENABLE(WCSS)
5425     case CSSPropertyWapMarqueeStyle:
5426 #endif
5427     case CSSPropertyWebkitMarqueeStyle:
5428         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
5429         return;
5430 #if ENABLE(WCSS)
5431     case CSSPropertyWapMarqueeDir:
5432         HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
5433         if (primitiveValue && primitiveValue->getIdent()) {
5434             switch (primitiveValue->getIdent()) {
5435             case CSSValueLtr:
5436                 m_style->setMarqueeDirection(MRIGHT);
5437                 break;
5438             case CSSValueRtl:
5439                 m_style->setMarqueeDirection(MLEFT);
5440                 break;
5441             default:
5442                 m_style->setMarqueeDirection(*primitiveValue);
5443                 break;
5444             }
5445         }
5446         return;
5447 #endif
5448     case CSSPropertyWebkitMarqueeDirection:
5449         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
5450         return;
5451     case CSSPropertyWebkitUserDrag:
5452         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
5453         return;
5454     case CSSPropertyWebkitUserModify:
5455         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
5456         return;
5457     case CSSPropertyWebkitUserSelect:
5458         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
5459         return;
5460 
5461     case CSSPropertyTextOverflow: {
5462         // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
5463         // work with WinIE-specific pages that use the property.
5464         HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow)
5465         if (!primitiveValue || !primitiveValue->getIdent())
5466             return;
5467         m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis);
5468         return;
5469     }
5470     case CSSPropertyWebkitMarginCollapse: {
5471         if (isInherit) {
5472             m_style->setMarginBeforeCollapse(m_parentStyle->marginBeforeCollapse());
5473             m_style->setMarginAfterCollapse(m_parentStyle->marginAfterCollapse());
5474         }
5475         else if (isInitial) {
5476             m_style->setMarginBeforeCollapse(MCOLLAPSE);
5477             m_style->setMarginAfterCollapse(MCOLLAPSE);
5478         }
5479         return;
5480     }
5481 
5482     case CSSPropertyWebkitMarginBeforeCollapse:
5483     case CSSPropertyWebkitMarginTopCollapse:
5484         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginBeforeCollapse, MarginBeforeCollapse)
5485         return;
5486     case CSSPropertyWebkitMarginAfterCollapse:
5487     case CSSPropertyWebkitMarginBottomCollapse:
5488         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginAfterCollapse, MarginAfterCollapse)
5489         return;
5490     case CSSPropertyWebkitLineClamp: {
5491         HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
5492         if (!primitiveValue)
5493             return;
5494         int type = primitiveValue->primitiveType();
5495         if (type == CSSPrimitiveValue::CSS_NUMBER)
5496             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
5497         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5498             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
5499         return;
5500     }
5501     case CSSPropertyWebkitHighlight: {
5502         HANDLE_INHERIT_AND_INITIAL(highlight, Highlight);
5503         if (primitiveValue->getIdent() == CSSValueNone)
5504             m_style->setHighlight(nullAtom);
5505         else
5506             m_style->setHighlight(primitiveValue->getStringValue());
5507         return;
5508     }
5509     case CSSPropertyWebkitHyphens: {
5510         HANDLE_INHERIT_AND_INITIAL(hyphens, Hyphens);
5511         m_style->setHyphens(*primitiveValue);
5512         return;
5513     }
5514     case CSSPropertyWebkitHyphenateCharacter: {
5515         HANDLE_INHERIT_AND_INITIAL(hyphenationString, HyphenationString);
5516         if (primitiveValue->getIdent() == CSSValueAuto)
5517             m_style->setHyphenationString(nullAtom);
5518         else
5519             m_style->setHyphenationString(primitiveValue->getStringValue());
5520         return;
5521     }
5522     case CSSPropertyWebkitHyphenateLimitAfter: {
5523         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter);
5524         if (primitiveValue->getIdent() == CSSValueAuto)
5525             m_style->setHyphenationLimitAfter(-1);
5526         else
5527             m_style->setHyphenationLimitAfter(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max())));
5528         return;
5529     }
5530     case CSSPropertyWebkitHyphenateLimitBefore: {
5531         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore);
5532         if (primitiveValue->getIdent() == CSSValueAuto)
5533             m_style->setHyphenationLimitBefore(-1);
5534         else
5535             m_style->setHyphenationLimitBefore(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max())));
5536         return;
5537     }
5538     case CSSPropertyWebkitLocale: {
5539         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
5540         if (primitiveValue->getIdent() == CSSValueAuto)
5541             m_style->setLocale(nullAtom);
5542         else
5543             m_style->setLocale(primitiveValue->getStringValue());
5544         return;
5545     }
5546     case CSSPropertyWebkitBorderFit: {
5547         HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit);
5548         if (primitiveValue->getIdent() == CSSValueBorder)
5549             m_style->setBorderFit(BorderFitBorder);
5550         else
5551             m_style->setBorderFit(BorderFitLines);
5552         return;
5553     }
5554     case CSSPropertyWebkitTextSizeAdjust: {
5555         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
5556         if (!primitiveValue || !primitiveValue->getIdent()) return;
5557         m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
5558         m_fontDirty = true;
5559         return;
5560     }
5561     case CSSPropertyWebkitTextSecurity:
5562         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
5563         return;
5564 
5565 #if ENABLE(DASHBOARD_SUPPORT)
5566     case CSSPropertyWebkitDashboardRegion: {
5567         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
5568         if (!primitiveValue)
5569             return;
5570 
5571         if (primitiveValue->getIdent() == CSSValueNone) {
5572             m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
5573             return;
5574         }
5575 
5576         DashboardRegion *region = primitiveValue->getDashboardRegionValue();
5577         if (!region)
5578             return;
5579 
5580         DashboardRegion *first = region;
5581         while (region) {
5582             Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
5583             Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
5584             Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
5585             Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
5586             if (region->m_isCircle)
5587                 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
5588             else if (region->m_isRectangle)
5589                 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
5590             region = region->m_next.get();
5591         }
5592 
5593         m_element->document()->setHasDashboardRegions(true);
5594 
5595         return;
5596     }
5597 #endif
5598     case CSSPropertyWebkitRtlOrdering:
5599         HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered)
5600         if (!primitiveValue || !primitiveValue->getIdent())
5601             return;
5602         m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual);
5603         return;
5604     case CSSPropertyWebkitTextStrokeWidth: {
5605         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
5606         float width = 0;
5607         switch (primitiveValue->getIdent()) {
5608             case CSSValueThin:
5609             case CSSValueMedium:
5610             case CSSValueThick: {
5611                 double result = 1.0 / 48;
5612                 if (primitiveValue->getIdent() == CSSValueMedium)
5613                     result *= 3;
5614                 else if (primitiveValue->getIdent() == CSSValueThick)
5615                     result *= 5;
5616                 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5617                 break;
5618             }
5619             default:
5620                 width = primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5621                 break;
5622         }
5623         m_style->setTextStrokeWidth(width);
5624         return;
5625     }
5626     case CSSPropertyWebkitTransform: {
5627         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
5628         TransformOperations operations;
5629         createTransformOperations(value, style(), m_rootElementStyle, operations);
5630         m_style->setTransform(operations);
5631         return;
5632     }
5633     case CSSPropertyWebkitTransformOrigin:
5634         HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
5635         HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
5636         HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
5637         return;
5638     case CSSPropertyWebkitTransformOriginX: {
5639         HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
5640         if (!primitiveValue)
5641             return;
5642         Length l;
5643         int type = primitiveValue->primitiveType();
5644         if (CSSPrimitiveValue::isUnitTypeLength(type))
5645             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5646         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5647             l = Length(primitiveValue->getDoubleValue(), Percent);
5648         else
5649             return;
5650         m_style->setTransformOriginX(l);
5651         break;
5652     }
5653     case CSSPropertyWebkitTransformOriginY: {
5654         HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
5655         if (!primitiveValue)
5656             return;
5657         Length l;
5658         int type = primitiveValue->primitiveType();
5659         if (CSSPrimitiveValue::isUnitTypeLength(type))
5660             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5661         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5662             l = Length(primitiveValue->getDoubleValue(), Percent);
5663         else
5664             return;
5665         m_style->setTransformOriginY(l);
5666         break;
5667     }
5668     case CSSPropertyWebkitTransformOriginZ: {
5669         HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
5670         if (!primitiveValue)
5671             return;
5672         float f;
5673         int type = primitiveValue->primitiveType();
5674         if (CSSPrimitiveValue::isUnitTypeLength(type))
5675             f = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle));
5676         else
5677             return;
5678         m_style->setTransformOriginZ(f);
5679         break;
5680     }
5681     case CSSPropertyWebkitTransformStyle:
5682         HANDLE_INHERIT_AND_INITIAL(transformStyle3D, TransformStyle3D)
5683         if (primitiveValue)
5684             m_style->setTransformStyle3D((primitiveValue->getIdent() == CSSValuePreserve3d) ? TransformStyle3DPreserve3D : TransformStyle3DFlat);
5685         return;
5686     case CSSPropertyWebkitPerspective: {
5687         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
5688         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
5689             m_style->setPerspective(0);
5690             return;
5691         }
5692 
5693         float perspectiveValue;
5694         int type = primitiveValue->primitiveType();
5695         if (CSSPrimitiveValue::isUnitTypeLength(type))
5696             perspectiveValue = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor));
5697         else if (type == CSSPrimitiveValue::CSS_NUMBER) {
5698             // For backward compatibility, treat valueless numbers as px.
5699             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5700         } else
5701             return;
5702 
5703         if (perspectiveValue >= 0.0f)
5704             m_style->setPerspective(perspectiveValue);
5705         return;
5706     }
5707     case CSSPropertyWebkitPerspectiveOrigin:
5708         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
5709         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
5710         return;
5711     case CSSPropertyWebkitPerspectiveOriginX: {
5712         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
5713         if (!primitiveValue)
5714             return;
5715         Length l;
5716         int type = primitiveValue->primitiveType();
5717         if (CSSPrimitiveValue::isUnitTypeLength(type))
5718             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5719         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5720             l = Length(primitiveValue->getDoubleValue(), Percent);
5721         else
5722             return;
5723         m_style->setPerspectiveOriginX(l);
5724         return;
5725     }
5726     case CSSPropertyWebkitPerspectiveOriginY: {
5727         HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
5728         if (!primitiveValue)
5729             return;
5730         Length l;
5731         int type = primitiveValue->primitiveType();
5732         if (CSSPrimitiveValue::isUnitTypeLength(type))
5733             l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5734         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5735             l = Length(primitiveValue->getDoubleValue(), Percent);
5736         else
5737             return;
5738         m_style->setPerspectiveOriginY(l);
5739         return;
5740     }
5741     case CSSPropertyWebkitAnimation:
5742         if (isInitial)
5743             m_style->clearAnimations();
5744         else if (isInherit)
5745             m_style->inheritAnimations(m_parentStyle->animations());
5746         return;
5747     case CSSPropertyWebkitAnimationDelay:
5748         HANDLE_ANIMATION_VALUE(delay, Delay, value)
5749         return;
5750     case CSSPropertyWebkitAnimationDirection:
5751         HANDLE_ANIMATION_VALUE(direction, Direction, value)
5752         return;
5753     case CSSPropertyWebkitAnimationDuration:
5754         HANDLE_ANIMATION_VALUE(duration, Duration, value)
5755         return;
5756     case CSSPropertyWebkitAnimationFillMode:
5757         HANDLE_ANIMATION_VALUE(fillMode, FillMode, value)
5758         return;
5759     case CSSPropertyWebkitAnimationIterationCount:
5760         HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value)
5761         return;
5762     case CSSPropertyWebkitAnimationName:
5763         HANDLE_ANIMATION_VALUE(name, Name, value)
5764         return;
5765     case CSSPropertyWebkitAnimationPlayState:
5766         HANDLE_ANIMATION_VALUE(playState, PlayState, value)
5767         return;
5768     case CSSPropertyWebkitAnimationTimingFunction:
5769         HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value)
5770         return;
5771     case CSSPropertyWebkitTransition:
5772         if (isInitial)
5773             m_style->clearTransitions();
5774         else if (isInherit)
5775             m_style->inheritTransitions(m_parentStyle->transitions());
5776         return;
5777     case CSSPropertyWebkitTransitionDelay:
5778         HANDLE_TRANSITION_VALUE(delay, Delay, value)
5779         return;
5780     case CSSPropertyWebkitTransitionDuration:
5781         HANDLE_TRANSITION_VALUE(duration, Duration, value)
5782         return;
5783     case CSSPropertyWebkitTransitionProperty:
5784         HANDLE_TRANSITION_VALUE(property, Property, value)
5785         return;
5786     case CSSPropertyWebkitTransitionTimingFunction:
5787         HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value)
5788         return;
5789     case CSSPropertyPointerEvents:
5790     {
5791 #if ENABLE(DASHBOARD_SUPPORT)
5792         // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
5793         // pointer-events property by not applying it in Dashboard.
5794         Settings* settings = m_checker.m_document->settings();
5795         if (settings && settings->usesDashboardBackwardCompatibilityMode())
5796             return;
5797 #endif
5798         HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents)
5799         if (!primitiveValue)
5800             return;
5801         m_style->setPointerEvents(*primitiveValue);
5802         return;
5803     }
5804     case CSSPropertyWebkitColorCorrection:
5805         if (isInherit)
5806             m_style->setColorSpace(m_parentStyle->colorSpace());
5807         else if (isInitial)
5808             m_style->setColorSpace(ColorSpaceDeviceRGB);
5809         else {
5810             if (!primitiveValue)
5811                 return;
5812             m_style->setColorSpace(*primitiveValue);
5813         }
5814         return;
5815     case CSSPropertySize:
5816         applyPageSizeProperty(value);
5817         return;
5818 
5819     case CSSPropertySpeak:
5820         HANDLE_INHERIT_AND_INITIAL(speak, Speak);
5821         if (!primitiveValue)
5822             return;
5823         m_style->setSpeak(*primitiveValue);
5824         return;
5825 
5826     case CSSPropertyInvalid:
5827         return;
5828 
5829     // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
5830     case CSSPropertyWebkitBorderEnd:
5831     case CSSPropertyWebkitBorderEndColor:
5832     case CSSPropertyWebkitBorderEndStyle:
5833     case CSSPropertyWebkitBorderEndWidth:
5834     case CSSPropertyWebkitBorderStart:
5835     case CSSPropertyWebkitBorderStartColor:
5836     case CSSPropertyWebkitBorderStartStyle:
5837     case CSSPropertyWebkitBorderStartWidth:
5838     case CSSPropertyWebkitBorderBefore:
5839     case CSSPropertyWebkitBorderBeforeColor:
5840     case CSSPropertyWebkitBorderBeforeStyle:
5841     case CSSPropertyWebkitBorderBeforeWidth:
5842     case CSSPropertyWebkitBorderAfter:
5843     case CSSPropertyWebkitBorderAfterColor:
5844     case CSSPropertyWebkitBorderAfterStyle:
5845     case CSSPropertyWebkitBorderAfterWidth:
5846     case CSSPropertyWebkitMarginEnd:
5847     case CSSPropertyWebkitMarginStart:
5848     case CSSPropertyWebkitMarginBefore:
5849     case CSSPropertyWebkitMarginAfter:
5850     case CSSPropertyWebkitPaddingEnd:
5851     case CSSPropertyWebkitPaddingStart:
5852     case CSSPropertyWebkitPaddingBefore:
5853     case CSSPropertyWebkitPaddingAfter:
5854     case CSSPropertyWebkitLogicalWidth:
5855     case CSSPropertyWebkitLogicalHeight:
5856     case CSSPropertyWebkitMinLogicalWidth:
5857     case CSSPropertyWebkitMinLogicalHeight:
5858     case CSSPropertyWebkitMaxLogicalWidth:
5859     case CSSPropertyWebkitMaxLogicalHeight:
5860         ASSERT_NOT_REACHED();
5861         break;
5862 
5863     case CSSPropertyFontStretch:
5864     case CSSPropertyPage:
5865     case CSSPropertyTextLineThrough:
5866     case CSSPropertyTextLineThroughColor:
5867     case CSSPropertyTextLineThroughMode:
5868     case CSSPropertyTextLineThroughStyle:
5869     case CSSPropertyTextLineThroughWidth:
5870     case CSSPropertyTextOverline:
5871     case CSSPropertyTextOverlineColor:
5872     case CSSPropertyTextOverlineMode:
5873     case CSSPropertyTextOverlineStyle:
5874     case CSSPropertyTextOverlineWidth:
5875     case CSSPropertyTextUnderline:
5876     case CSSPropertyTextUnderlineColor:
5877     case CSSPropertyTextUnderlineMode:
5878     case CSSPropertyTextUnderlineStyle:
5879     case CSSPropertyTextUnderlineWidth:
5880     case CSSPropertyWebkitFontSizeDelta:
5881     case CSSPropertyWebkitTextDecorationsInEffect:
5882     case CSSPropertyWebkitTextStroke:
5883     case CSSPropertyWebkitTextEmphasis:
5884         return;
5885 #if ENABLE(WCSS)
5886     case CSSPropertyWapInputFormat:
5887         if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) {
5888             String mask = primitiveValue->getStringValue();
5889             static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask);
5890         }
5891         return;
5892 
5893     case CSSPropertyWapInputRequired:
5894         if (primitiveValue && m_element->isFormControlElement()) {
5895             HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element);
5896             bool required = primitiveValue->getStringValue() == "true";
5897             element->setRequired(required);
5898         }
5899         return;
5900 #endif
5901 
5902     // CSS Text Layout Module Level 3: Vertical writing support
5903     case CSSPropertyWebkitWritingMode: {
5904         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
5905         if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
5906             m_element->document()->setWritingModeSetOnDocumentElement(true);
5907         FontDescription fontDescription = m_style->fontDescription();
5908         fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
5909         if (m_style->setFontDescription(fontDescription))
5910             m_fontDirty = true;
5911         return;
5912     }
5913 
5914     case CSSPropertyWebkitTextCombine:
5915         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine)
5916         return;
5917 
5918     case CSSPropertyWebkitTextEmphasisPosition:
5919         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textEmphasisPosition, TextEmphasisPosition)
5920         return;
5921 
5922     case CSSPropertyWebkitTextEmphasisStyle:
5923         HANDLE_INHERIT_AND_INITIAL(textEmphasisFill, TextEmphasisFill)
5924         HANDLE_INHERIT_AND_INITIAL(textEmphasisMark, TextEmphasisMark)
5925         HANDLE_INHERIT_AND_INITIAL(textEmphasisCustomMark, TextEmphasisCustomMark)
5926         if (isInherit || isInitial)
5927             return;
5928 
5929         if (value->isValueList()) {
5930             CSSValueList* list = static_cast<CSSValueList*>(value);
5931             ASSERT(list->length() == 2);
5932             if (list->length() != 2)
5933                 return;
5934             for (unsigned i = 0; i < 2; ++i) {
5935                 CSSValue* item = list->itemWithoutBoundsCheck(i);
5936                 if (!item->isPrimitiveValue())
5937                     continue;
5938 
5939                 CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(item);
5940                 if (value->getIdent() == CSSValueFilled || value->getIdent() == CSSValueOpen)
5941                     m_style->setTextEmphasisFill(*value);
5942                 else
5943                     m_style->setTextEmphasisMark(*value);
5944             }
5945             m_style->setTextEmphasisCustomMark(nullAtom);
5946             return;
5947         }
5948 
5949         if (!primitiveValue)
5950             return;
5951 
5952         if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
5953             m_style->setTextEmphasisFill(TextEmphasisFillFilled);
5954             m_style->setTextEmphasisMark(TextEmphasisMarkCustom);
5955             m_style->setTextEmphasisCustomMark(primitiveValue->getStringValue());
5956             return;
5957         }
5958 
5959         m_style->setTextEmphasisCustomMark(nullAtom);
5960 
5961         if (primitiveValue->getIdent() == CSSValueFilled || primitiveValue->getIdent() == CSSValueOpen) {
5962             m_style->setTextEmphasisFill(*primitiveValue);
5963             m_style->setTextEmphasisMark(TextEmphasisMarkAuto);
5964         } else {
5965             m_style->setTextEmphasisFill(TextEmphasisFillFilled);
5966             m_style->setTextEmphasisMark(*primitiveValue);
5967         }
5968 
5969         return;
5970 
5971     case CSSPropertyWebkitTextOrientation: {
5972         if (!isInherit && !isInitial && !primitiveValue)
5973             return;
5974 
5975         TextOrientation result;
5976         if (isInherit)
5977             result = m_parentStyle->fontDescription().textOrientation();
5978         else if (isInitial)
5979             result = RenderStyle::initialTextOrientation();
5980         else
5981             result = *primitiveValue;
5982 
5983         FontDescription fontDescription = m_style->fontDescription();
5984         if (fontDescription.textOrientation() != result) {
5985             fontDescription.setTextOrientation(result);
5986             if (m_style->setFontDescription(fontDescription))
5987                 m_fontDirty = true;
5988         }
5989         return;
5990     }
5991 
5992     case CSSPropertyWebkitLineBoxContain: {
5993         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
5994         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
5995             m_style->setLineBoxContain(LineBoxContainNone);
5996             return;
5997         }
5998 
5999         if (!value->isCSSLineBoxContainValue())
6000             return;
6001 
6002         CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
6003         m_style->setLineBoxContain(lineBoxContainValue->value());
6004         return;
6005     }
6006 
6007     // These properties are implemented in the CSSStyleApplyProperty lookup table.
6008     case CSSPropertyColor:
6009     case CSSPropertyDirection:
6010     case CSSPropertyBackgroundAttachment:
6011     case CSSPropertyBackgroundClip:
6012     case CSSPropertyWebkitBackgroundClip:
6013     case CSSPropertyWebkitBackgroundComposite:
6014     case CSSPropertyBackgroundOrigin:
6015     case CSSPropertyWebkitBackgroundOrigin:
6016     case CSSPropertyBackgroundImage:
6017     case CSSPropertyBackgroundSize:
6018     case CSSPropertyWebkitBackgroundSize:
6019     case CSSPropertyWebkitMaskAttachment:
6020     case CSSPropertyWebkitMaskClip:
6021     case CSSPropertyWebkitMaskComposite:
6022     case CSSPropertyWebkitMaskOrigin:
6023     case CSSPropertyWebkitMaskImage:
6024     case CSSPropertyWebkitMaskSize:
6025     case CSSPropertyBackgroundColor:
6026     case CSSPropertyBorderBottomColor:
6027     case CSSPropertyBorderLeftColor:
6028     case CSSPropertyBorderRightColor:
6029     case CSSPropertyBorderTopColor:
6030     case CSSPropertyBorderTopStyle:
6031     case CSSPropertyBorderRightStyle:
6032     case CSSPropertyBorderBottomStyle:
6033     case CSSPropertyBorderLeftStyle:
6034     case CSSPropertyOutlineColor:
6035     case CSSPropertyWebkitColumnRuleColor:
6036     case CSSPropertyWebkitTextEmphasisColor:
6037     case CSSPropertyWebkitTextFillColor:
6038     case CSSPropertyWebkitTextStrokeColor:
6039     case CSSPropertyBackgroundPosition:
6040     case CSSPropertyBackgroundPositionX:
6041     case CSSPropertyBackgroundPositionY:
6042     case CSSPropertyWebkitMaskPosition:
6043     case CSSPropertyWebkitMaskPositionX:
6044     case CSSPropertyWebkitMaskPositionY:
6045     case CSSPropertyBackgroundRepeat:
6046     case CSSPropertyBackgroundRepeatX:
6047     case CSSPropertyBackgroundRepeatY:
6048     case CSSPropertyWebkitMaskRepeat:
6049     case CSSPropertyWebkitMaskRepeatX:
6050     case CSSPropertyWebkitMaskRepeatY:
6051     case CSSPropertyOverflow:
6052     case CSSPropertyOverflowX:
6053     case CSSPropertyOverflowY:
6054         ASSERT_NOT_REACHED();
6055         return;
6056 
6057 #ifdef ANDROID_CSS_RING
6058     case CSSPropertyWebkitRing:
6059         if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
6060         m_style->setRingFillColor(m_parentStyle->ringFillColor());
6061         m_style->setRingInnerWidth(m_parentStyle->ringInnerWidth());
6062         m_style->setRingOuterWidth(m_parentStyle->ringOuterWidth());
6063         m_style->setRingOutset(m_parentStyle->ringOutset());
6064         m_style->setRingPressedInnerColor(m_parentStyle->ringPressedInnerColor());
6065         m_style->setRingPressedOuterColor(m_parentStyle->ringPressedOuterColor());
6066         m_style->setRingRadius(m_parentStyle->ringRadius());
6067         m_style->setRingSelectedInnerColor(m_parentStyle->ringSelectedInnerColor());
6068         m_style->setRingSelectedOuterColor(m_parentStyle->ringSelectedOuterColor());
6069         return;
6070     case CSSPropertyWebkitRingFillColor: {
6071         HANDLE_INHERIT_AND_INITIAL(ringFillColor, RingFillColor);
6072         if (!primitiveValue)
6073             break;
6074         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6075         m_style->setRingFillColor(col);
6076         return;
6077     }
6078     case CSSPropertyWebkitRingInnerWidth: {
6079         HANDLE_INHERIT_AND_INITIAL(ringInnerWidth, RingInnerWidth)
6080         if (!primitiveValue)
6081             break;
6082         Length l;
6083         int type = primitiveValue->primitiveType();
6084         if (CSSPrimitiveValue::isUnitTypeLength(type)) {
6085             // width can be specified with fractional px
6086             // scale by 16 here (and unscale in android_graphics) to keep
6087             // 4 bits of fraction
6088             RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create(
6089                 primitiveValue->getFloatValue() * 16,
6090                 (CSSPrimitiveValue::UnitTypes) type);
6091             l = Length(scaledValue->computeLengthIntForLength(style(),
6092                 m_rootElementStyle, zoomFactor), Fixed);
6093             scaledValue.release();
6094         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6095             l = Length(primitiveValue->getDoubleValue(), Percent);
6096         else
6097             return;
6098         m_style->setRingInnerWidth(l);
6099         return;
6100     }
6101     case CSSPropertyWebkitRingOuterWidth: {
6102         HANDLE_INHERIT_AND_INITIAL(ringOuterWidth, RingOuterWidth)
6103         if (!primitiveValue)
6104             break;
6105         Length l;
6106         int type = primitiveValue->primitiveType();
6107         if (CSSPrimitiveValue::isUnitTypeLength(type)) {
6108             // width can be specified with fractional px
6109             // scale by 16 here (and unscale in android_graphics) to keep
6110             // 4 bits of fraction
6111             RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create(
6112                 primitiveValue->getFloatValue() * 16,
6113                 (CSSPrimitiveValue::UnitTypes) type);
6114             l = Length(scaledValue->computeLengthIntForLength(style(),
6115                 m_rootElementStyle, zoomFactor), Fixed);
6116             scaledValue.release();
6117         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6118             l = Length(primitiveValue->getDoubleValue(), Percent);
6119         else
6120             return;
6121         m_style->setRingOuterWidth(l);
6122         return;
6123     }
6124     case CSSPropertyWebkitRingOutset: {
6125         HANDLE_INHERIT_AND_INITIAL(ringOutset, RingOutset)
6126         if (!primitiveValue)
6127             break;
6128         Length l;
6129         int type = primitiveValue->primitiveType();
6130         if (CSSPrimitiveValue::isUnitTypeLength(type))
6131             l = Length(primitiveValue->computeLengthIntForLength(style(),
6132                 m_rootElementStyle, zoomFactor), Fixed);
6133         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6134             l = Length(primitiveValue->getDoubleValue(), Percent);
6135         else
6136             return;
6137         m_style->setRingOutset(l);
6138         return;
6139     }
6140     case CSSPropertyWebkitRingPressedInnerColor: {
6141         HANDLE_INHERIT_AND_INITIAL(ringPressedInnerColor, RingPressedInnerColor);
6142         if (!primitiveValue)
6143             break;
6144         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6145         m_style->setRingPressedInnerColor(col);
6146         return;
6147     }
6148     case CSSPropertyWebkitRingPressedOuterColor: {
6149         HANDLE_INHERIT_AND_INITIAL(ringPressedOuterColor, RingPressedOuterColor);
6150         if (!primitiveValue)
6151             break;
6152         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6153         m_style->setRingPressedOuterColor(col);
6154         return;
6155     }
6156     case CSSPropertyWebkitRingRadius: {
6157         HANDLE_INHERIT_AND_INITIAL(ringRadius, RingRadius)
6158         if (!primitiveValue)
6159             break;
6160         Length l;
6161         int type = primitiveValue->primitiveType();
6162         if (CSSPrimitiveValue::isUnitTypeLength(type))
6163             l = Length(primitiveValue->computeLengthIntForLength(style(),
6164                 m_rootElementStyle, zoomFactor), Fixed);
6165         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6166             l = Length(primitiveValue->getDoubleValue(), Percent);
6167         else
6168             return;
6169         m_style->setRingRadius(l);
6170         return;
6171     }
6172     case CSSPropertyWebkitRingSelectedInnerColor: {
6173         HANDLE_INHERIT_AND_INITIAL(ringSelectedInnerColor, RingSelectedInnerColor);
6174         if (!primitiveValue)
6175             break;
6176         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6177         m_style->setRingSelectedInnerColor(col);
6178         return;
6179     }
6180     case CSSPropertyWebkitRingSelectedOuterColor: {
6181         HANDLE_INHERIT_AND_INITIAL(ringSelectedOuterColor, RingSelectedOuterColor);
6182         if (!primitiveValue)
6183             break;
6184         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6185         m_style->setRingSelectedOuterColor(col);
6186         return;
6187     }
6188 #endif
6189 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
6190     case CSSPropertyWebkitTapHighlightColor: {
6191         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
6192         if (!primitiveValue)
6193             break;
6194 
6195         Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
6196         m_style->setTapHighlightColor(col);
6197         return;
6198     }
6199 #endif
6200 
6201 #if ENABLE(SVG)
6202     default:
6203         // Try the SVG properties
6204         applySVGProperty(id, value);
6205         return;
6206 #endif
6207     }
6208 }
6209 
applyPageSizeProperty(CSSValue * value)6210 void CSSStyleSelector::applyPageSizeProperty(CSSValue* value)
6211 {
6212     m_style->resetPageSizeType();
6213     if (!value->isValueList())
6214         return;
6215     CSSValueList* valueList = static_cast<CSSValueList*>(value);
6216     Length width;
6217     Length height;
6218     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
6219     switch (valueList->length()) {
6220     case 2: {
6221         // <length>{2} | <page-size> <orientation>
6222         pageSizeType = PAGE_SIZE_RESOLVED;
6223         if (!valueList->item(0)->isPrimitiveValue() || !valueList->item(1)->isPrimitiveValue())
6224             return;
6225         CSSPrimitiveValue* primitiveValue0 = static_cast<CSSPrimitiveValue*>(valueList->item(0));
6226         CSSPrimitiveValue* primitiveValue1 = static_cast<CSSPrimitiveValue*>(valueList->item(1));
6227         int type0 = primitiveValue0->primitiveType();
6228         int type1 = primitiveValue1->primitiveType();
6229         if (CSSPrimitiveValue::isUnitTypeLength(type0)) {
6230             // <length>{2}
6231             if (!CSSPrimitiveValue::isUnitTypeLength(type1))
6232                 return;
6233             width = Length(primitiveValue0->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
6234             height = Length(primitiveValue1->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
6235         } else {
6236             // <page-size> <orientation>
6237             // The value order is guaranteed. See CSSParser::parseSizeParameter.
6238             if (!pageSizeFromName(primitiveValue0, primitiveValue1, width, height))
6239                 return;
6240         }
6241         break;
6242     }
6243     case 1: {
6244         // <length> | auto | <page-size> | [ portrait | landscape]
6245         if (!valueList->item(0)->isPrimitiveValue())
6246             return;
6247         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valueList->item(0));
6248         int type = primitiveValue->primitiveType();
6249         if (CSSPrimitiveValue::isUnitTypeLength(type)) {
6250             // <length>
6251             pageSizeType = PAGE_SIZE_RESOLVED;
6252             width = height = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
6253         } else {
6254             if (type != CSSPrimitiveValue::CSS_IDENT)
6255                 return;
6256             switch (primitiveValue->getIdent()) {
6257             case CSSValueAuto:
6258                 pageSizeType = PAGE_SIZE_AUTO;
6259                 break;
6260             case CSSValuePortrait:
6261                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
6262                 break;
6263             case CSSValueLandscape:
6264                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
6265                 break;
6266             default:
6267                 // <page-size>
6268                 pageSizeType = PAGE_SIZE_RESOLVED;
6269                 if (!pageSizeFromName(primitiveValue, 0, width, height))
6270                     return;
6271             }
6272         }
6273         break;
6274     }
6275     default:
6276         return;
6277     }
6278     m_style->setPageSizeType(pageSizeType);
6279     m_style->setPageSize(LengthSize(width, height));
6280     return;
6281 }
6282 
pageSizeFromName(CSSPrimitiveValue * pageSizeName,CSSPrimitiveValue * pageOrientation,Length & width,Length & height)6283 bool CSSStyleSelector::pageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
6284 {
6285     static const Length a5Width = mmLength(148), a5Height = mmLength(210);
6286     static const Length a4Width = mmLength(210), a4Height = mmLength(297);
6287     static const Length a3Width = mmLength(297), a3Height = mmLength(420);
6288     static const Length b5Width = mmLength(176), b5Height = mmLength(250);
6289     static const Length b4Width = mmLength(250), b4Height = mmLength(353);
6290     static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11);
6291     static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14);
6292     static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17);
6293 
6294     if (!pageSizeName || pageSizeName->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
6295         return false;
6296 
6297     switch (pageSizeName->getIdent()) {
6298     case CSSValueA5:
6299         width = a5Width;
6300         height = a5Height;
6301         break;
6302     case CSSValueA4:
6303         width = a4Width;
6304         height = a4Height;
6305         break;
6306     case CSSValueA3:
6307         width = a3Width;
6308         height = a3Height;
6309         break;
6310     case CSSValueB5:
6311         width = b5Width;
6312         height = b5Height;
6313         break;
6314     case CSSValueB4:
6315         width = b4Width;
6316         height = b4Height;
6317         break;
6318     case CSSValueLetter:
6319         width = letterWidth;
6320         height = letterHeight;
6321         break;
6322     case CSSValueLegal:
6323         width = legalWidth;
6324         height = legalHeight;
6325         break;
6326     case CSSValueLedger:
6327         width = ledgerWidth;
6328         height = ledgerHeight;
6329         break;
6330     default:
6331         return false;
6332     }
6333 
6334     if (pageOrientation) {
6335         if (pageOrientation->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
6336             return false;
6337         switch (pageOrientation->getIdent()) {
6338         case CSSValueLandscape:
6339             std::swap(width, height);
6340             break;
6341         case CSSValuePortrait:
6342             // Nothing to do.
6343             break;
6344         default:
6345             return false;
6346         }
6347     }
6348     return true;
6349 }
6350 
mmLength(double mm) const6351 Length CSSStyleSelector::mmLength(double mm) const
6352 {
6353     return Length(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
6354 }
6355 
inchLength(double inch) const6356 Length CSSStyleSelector::inchLength(double inch) const
6357 {
6358     return Length(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
6359 }
6360 
mapFillAttachment(CSSPropertyID,FillLayer * layer,CSSValue * value)6361 void CSSStyleSelector::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value)
6362 {
6363     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6364         layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
6365         return;
6366     }
6367 
6368     if (!value->isPrimitiveValue())
6369         return;
6370 
6371     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6372     switch (primitiveValue->getIdent()) {
6373         case CSSValueFixed:
6374             layer->setAttachment(FixedBackgroundAttachment);
6375             break;
6376         case CSSValueScroll:
6377             layer->setAttachment(ScrollBackgroundAttachment);
6378             break;
6379         case CSSValueLocal:
6380             layer->setAttachment(LocalBackgroundAttachment);
6381             break;
6382         default:
6383             return;
6384     }
6385 }
6386 
mapFillClip(CSSPropertyID,FillLayer * layer,CSSValue * value)6387 void CSSStyleSelector::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value)
6388 {
6389     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6390         layer->setClip(FillLayer::initialFillClip(layer->type()));
6391         return;
6392     }
6393 
6394     if (!value->isPrimitiveValue())
6395         return;
6396 
6397     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6398     layer->setClip(*primitiveValue);
6399 }
6400 
mapFillComposite(CSSPropertyID,FillLayer * layer,CSSValue * value)6401 void CSSStyleSelector::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value)
6402 {
6403     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6404         layer->setComposite(FillLayer::initialFillComposite(layer->type()));
6405         return;
6406     }
6407 
6408     if (!value->isPrimitiveValue())
6409         return;
6410 
6411     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6412     layer->setComposite(*primitiveValue);
6413 }
6414 
mapFillOrigin(CSSPropertyID,FillLayer * layer,CSSValue * value)6415 void CSSStyleSelector::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value)
6416 {
6417     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6418         layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
6419         return;
6420     }
6421 
6422     if (!value->isPrimitiveValue())
6423         return;
6424 
6425     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6426     layer->setOrigin(*primitiveValue);
6427 }
6428 
styleImage(CSSPropertyID property,CSSValue * value)6429 StyleImage* CSSStyleSelector::styleImage(CSSPropertyID property, CSSValue* value)
6430 {
6431     if (value->isImageValue())
6432         return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value));
6433 
6434     if (value->isImageGeneratorValue())
6435         return static_cast<CSSImageGeneratorValue*>(value)->generatedImage();
6436 
6437     return 0;
6438 }
6439 
cachedOrPendingFromValue(CSSPropertyID property,CSSImageValue * value)6440 StyleImage* CSSStyleSelector::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
6441 {
6442     StyleImage* image = value->cachedOrPendingImage();
6443     if (image && image->isPendingImage())
6444         m_pendingImageProperties.add(property);
6445     return image;
6446 }
6447 
mapFillImage(CSSPropertyID property,FillLayer * layer,CSSValue * value)6448 void CSSStyleSelector::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
6449 {
6450     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6451         layer->setImage(FillLayer::initialFillImage(layer->type()));
6452         return;
6453     }
6454 
6455     layer->setImage(styleImage(property, value));
6456 }
6457 
mapFillRepeatX(CSSPropertyID,FillLayer * layer,CSSValue * value)6458 void CSSStyleSelector::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value)
6459 {
6460     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6461         layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
6462         return;
6463     }
6464 
6465     if (!value->isPrimitiveValue())
6466         return;
6467 
6468     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6469     layer->setRepeatX(*primitiveValue);
6470 }
6471 
mapFillRepeatY(CSSPropertyID,FillLayer * layer,CSSValue * value)6472 void CSSStyleSelector::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value)
6473 {
6474     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6475         layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
6476         return;
6477     }
6478 
6479     if (!value->isPrimitiveValue())
6480         return;
6481 
6482     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6483     layer->setRepeatY(*primitiveValue);
6484 }
6485 
mapFillSize(CSSPropertyID,FillLayer * layer,CSSValue * value)6486 void CSSStyleSelector::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value)
6487 {
6488     if (!value->isPrimitiveValue()) {
6489         layer->setSizeType(SizeNone);
6490         return;
6491     }
6492 
6493     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6494     if (primitiveValue->getIdent() == CSSValueContain)
6495         layer->setSizeType(Contain);
6496     else if (primitiveValue->getIdent() == CSSValueCover)
6497         layer->setSizeType(Cover);
6498     else
6499         layer->setSizeType(SizeLength);
6500 
6501     LengthSize b = FillLayer::initialFillSizeLength(layer->type());
6502 
6503     if (value->cssValueType() == CSSValue::CSS_INITIAL || primitiveValue->getIdent() == CSSValueContain
6504         || primitiveValue->getIdent() == CSSValueCover) {
6505         layer->setSizeLength(b);
6506         return;
6507     }
6508 
6509     Pair* pair = primitiveValue->getPairValue();
6510     if (!pair || !pair->first() || !pair->second())
6511         return;
6512 
6513     CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first());
6514     CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second());
6515 
6516     Length firstLength, secondLength;
6517     int firstType = first->primitiveType();
6518     int secondType = second->primitiveType();
6519 
6520     float zoomFactor = m_style->effectiveZoom();
6521 
6522     if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
6523         firstLength = Length(Auto);
6524     else if (CSSPrimitiveValue::isUnitTypeLength(firstType))
6525         firstLength = Length(first->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
6526     else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
6527         firstLength = Length(first->getDoubleValue(), Percent);
6528     else
6529         return;
6530 
6531     if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
6532         secondLength = Length(Auto);
6533     else if (CSSPrimitiveValue::isUnitTypeLength(secondType))
6534         secondLength = Length(second->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
6535     else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
6536         secondLength = Length(second->getDoubleValue(), Percent);
6537     else
6538         return;
6539 
6540     b.setWidth(firstLength);
6541     b.setHeight(secondLength);
6542     layer->setSizeLength(b);
6543 }
6544 
mapFillXPosition(CSSPropertyID,FillLayer * layer,CSSValue * value)6545 void CSSStyleSelector::mapFillXPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
6546 {
6547     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6548         layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
6549         return;
6550     }
6551 
6552     if (!value->isPrimitiveValue())
6553         return;
6554 
6555     float zoomFactor = m_style->effectiveZoom();
6556 
6557     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6558     Length l;
6559     int type = primitiveValue->primitiveType();
6560     if (CSSPrimitiveValue::isUnitTypeLength(type))
6561         l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
6562     else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6563         l = Length(primitiveValue->getDoubleValue(), Percent);
6564     else
6565         return;
6566     layer->setXPosition(l);
6567 }
6568 
mapFillYPosition(CSSPropertyID,FillLayer * layer,CSSValue * value)6569 void CSSStyleSelector::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
6570 {
6571     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6572         layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
6573         return;
6574     }
6575 
6576     if (!value->isPrimitiveValue())
6577         return;
6578 
6579     float zoomFactor = m_style->effectiveZoom();
6580 
6581     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6582     Length l;
6583     int type = primitiveValue->primitiveType();
6584     if (CSSPrimitiveValue::isUnitTypeLength(type))
6585         l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
6586     else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
6587         l = Length(primitiveValue->getDoubleValue(), Percent);
6588     else
6589         return;
6590     layer->setYPosition(l);
6591 }
6592 
mapAnimationDelay(Animation * animation,CSSValue * value)6593 void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value)
6594 {
6595     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6596         animation->setDelay(Animation::initialAnimationDelay());
6597         return;
6598     }
6599 
6600     if (!value->isPrimitiveValue())
6601         return;
6602 
6603     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6604     if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
6605         animation->setDelay(primitiveValue->getFloatValue());
6606     else
6607         animation->setDelay(primitiveValue->getFloatValue()/1000.0f);
6608 }
6609 
mapAnimationDirection(Animation * layer,CSSValue * value)6610 void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value)
6611 {
6612     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6613         layer->setDirection(Animation::initialAnimationDirection());
6614         return;
6615     }
6616 
6617     if (!value->isPrimitiveValue())
6618         return;
6619 
6620     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6621     layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal);
6622 }
6623 
mapAnimationDuration(Animation * animation,CSSValue * value)6624 void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
6625 {
6626     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6627         animation->setDuration(Animation::initialAnimationDuration());
6628         return;
6629     }
6630 
6631     if (!value->isPrimitiveValue())
6632         return;
6633 
6634     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6635     if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
6636         animation->setDuration(primitiveValue->getFloatValue());
6637     else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
6638         animation->setDuration(primitiveValue->getFloatValue()/1000.0f);
6639 }
6640 
mapAnimationFillMode(Animation * layer,CSSValue * value)6641 void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value)
6642 {
6643     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6644         layer->setFillMode(Animation::initialAnimationFillMode());
6645         return;
6646     }
6647 
6648     if (!value->isPrimitiveValue())
6649         return;
6650 
6651     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6652     switch (primitiveValue->getIdent()) {
6653     case CSSValueNone:
6654         layer->setFillMode(AnimationFillModeNone);
6655         break;
6656     case CSSValueForwards:
6657         layer->setFillMode(AnimationFillModeForwards);
6658         break;
6659     case CSSValueBackwards:
6660         layer->setFillMode(AnimationFillModeBackwards);
6661         break;
6662     case CSSValueBoth:
6663         layer->setFillMode(AnimationFillModeBoth);
6664         break;
6665     }
6666 }
6667 
mapAnimationIterationCount(Animation * animation,CSSValue * value)6668 void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value)
6669 {
6670     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6671         animation->setIterationCount(Animation::initialAnimationIterationCount());
6672         return;
6673     }
6674 
6675     if (!value->isPrimitiveValue())
6676         return;
6677 
6678     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6679     if (primitiveValue->getIdent() == CSSValueInfinite)
6680         animation->setIterationCount(-1);
6681     else
6682         animation->setIterationCount(int(primitiveValue->getFloatValue()));
6683 }
6684 
mapAnimationName(Animation * layer,CSSValue * value)6685 void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value)
6686 {
6687     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6688         layer->setName(Animation::initialAnimationName());
6689         return;
6690     }
6691 
6692     if (!value->isPrimitiveValue())
6693         return;
6694 
6695     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6696     if (primitiveValue->getIdent() == CSSValueNone)
6697         layer->setIsNoneAnimation(true);
6698     else
6699         layer->setName(primitiveValue->getStringValue());
6700 }
6701 
mapAnimationPlayState(Animation * layer,CSSValue * value)6702 void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value)
6703 {
6704     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6705         layer->setPlayState(Animation::initialAnimationPlayState());
6706         return;
6707     }
6708 
6709     if (!value->isPrimitiveValue())
6710         return;
6711 
6712     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6713     EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
6714     layer->setPlayState(playState);
6715 }
6716 
mapAnimationProperty(Animation * animation,CSSValue * value)6717 void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value)
6718 {
6719     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6720         animation->setProperty(Animation::initialAnimationProperty());
6721         return;
6722     }
6723 
6724     if (!value->isPrimitiveValue())
6725         return;
6726 
6727     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6728     if (primitiveValue->getIdent() == CSSValueAll)
6729         animation->setProperty(cAnimateAll);
6730     else if (primitiveValue->getIdent() == CSSValueNone)
6731         animation->setProperty(cAnimateNone);
6732     else
6733         animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
6734 }
6735 
mapAnimationTimingFunction(Animation * animation,CSSValue * value)6736 void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
6737 {
6738     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6739         animation->setTimingFunction(Animation::initialAnimationTimingFunction());
6740         return;
6741     }
6742 
6743     if (value->isPrimitiveValue()) {
6744         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6745         switch (primitiveValue->getIdent()) {
6746             case CSSValueLinear:
6747                 animation->setTimingFunction(LinearTimingFunction::create());
6748                 break;
6749             case CSSValueEase:
6750                 animation->setTimingFunction(CubicBezierTimingFunction::create());
6751                 break;
6752             case CSSValueEaseIn:
6753                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 1.0, 1.0));
6754                 break;
6755             case CSSValueEaseOut:
6756                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.0, 0.0, 0.58, 1.0));
6757                 break;
6758             case CSSValueEaseInOut:
6759                 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 0.58, 1.0));
6760                 break;
6761             case CSSValueStepStart:
6762                 animation->setTimingFunction(StepsTimingFunction::create(1, true));
6763                 break;
6764             case CSSValueStepEnd:
6765                 animation->setTimingFunction(StepsTimingFunction::create(1, false));
6766                 break;
6767         }
6768         return;
6769     }
6770 
6771     if (value->isTimingFunctionValue()) {
6772         CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
6773         if (timingFunction->isCubicBezierTimingFunctionValue()) {
6774             CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value);
6775             animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()));
6776         } else if (timingFunction->isStepsTimingFunctionValue()) {
6777             CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value);
6778             animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()));
6779         } else
6780             animation->setTimingFunction(LinearTimingFunction::create());
6781     }
6782 }
6783 
mapNinePieceImage(CSSPropertyID property,CSSValue * value,NinePieceImage & image)6784 void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
6785 {
6786     // If we're a primitive value, then we are "none" and don't need to alter the empty image at all.
6787     if (!value || value->isPrimitiveValue() || !value->isBorderImageValue())
6788         return;
6789 
6790     // Retrieve the border image value.
6791     CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
6792 
6793     // Set the image (this kicks off the load).
6794     image.setImage(styleImage(property, borderImage->imageValue()));
6795 
6796     // Set up a length box to represent our image slices.
6797     LengthBox l;
6798     Rect* r = borderImage->m_imageSliceRect.get();
6799     if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6800         l.m_top = Length(r->top()->getDoubleValue(), Percent);
6801     else
6802         l.m_top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6803     if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6804         l.m_bottom = Length(r->bottom()->getDoubleValue(), Percent);
6805     else
6806         l.m_bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6807     if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6808         l.m_left = Length(r->left()->getDoubleValue(), Percent);
6809     else
6810         l.m_left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6811     if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6812         l.m_right = Length(r->right()->getDoubleValue(), Percent);
6813     else
6814         l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6815     image.setSlices(l);
6816 
6817     // Set the appropriate rules for stretch/round/repeat of the slices
6818     ENinePieceImageRule horizontalRule;
6819     switch (borderImage->m_horizontalSizeRule) {
6820         case CSSValueStretch:
6821             horizontalRule = StretchImageRule;
6822             break;
6823         case CSSValueRound:
6824             horizontalRule = RoundImageRule;
6825             break;
6826         default: // CSSValueRepeat
6827             horizontalRule = RepeatImageRule;
6828             break;
6829     }
6830     image.setHorizontalRule(horizontalRule);
6831 
6832     ENinePieceImageRule verticalRule;
6833     switch (borderImage->m_verticalSizeRule) {
6834         case CSSValueStretch:
6835             verticalRule = StretchImageRule;
6836             break;
6837         case CSSValueRound:
6838             verticalRule = RoundImageRule;
6839             break;
6840         default: // CSSValueRepeat
6841             verticalRule = RepeatImageRule;
6842             break;
6843     }
6844     image.setVerticalRule(verticalRule);
6845 }
6846 
checkForTextSizeAdjust()6847 void CSSStyleSelector::checkForTextSizeAdjust()
6848 {
6849     if (m_style->textSizeAdjust())
6850         return;
6851 
6852     /* TODO: Remove this when a fix for webkit bug 56543 is submitted and can
6853      * be cherry picked.
6854      * This is a quick fix for Android to prevent sites from using
6855      * -webkit-text-size-adjust: none; which breaks font size accessibility
6856      * options on all platforms. The purpose of the property is to prevent
6857      * the automatic font size changes done by platforms like iOS when the
6858      * rotation changes. Since Android doesn't do this, we can safely ignore
6859      * the 'none' option.
6860      */
6861 #if PLATFORM(ANDROID)
6862     return;
6863 #endif
6864 
6865     FontDescription newFontDescription(m_style->fontDescription());
6866     newFontDescription.setComputedSize(newFontDescription.specifiedSize());
6867     m_style->setFontDescription(newFontDescription);
6868 }
6869 
checkForZoomChange(RenderStyle * style,RenderStyle * parentStyle)6870 void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
6871 {
6872     if (style->effectiveZoom() == parentStyle->effectiveZoom())
6873         return;
6874 
6875     const FontDescription& childFont = style->fontDescription();
6876     FontDescription newFontDescription(childFont);
6877     setFontSize(newFontDescription, childFont.specifiedSize());
6878     style->setFontDescription(newFontDescription);
6879 }
6880 
checkForGenericFamilyChange(RenderStyle * style,RenderStyle * parentStyle)6881 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
6882 {
6883     const FontDescription& childFont = style->fontDescription();
6884 
6885     if (childFont.isAbsoluteSize() || !parentStyle)
6886         return;
6887 
6888     const FontDescription& parentFont = parentStyle->fontDescription();
6889     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
6890         return;
6891 
6892     // For now, lump all families but monospace together.
6893     if (childFont.genericFamily() != FontDescription::MonospaceFamily &&
6894         parentFont.genericFamily() != FontDescription::MonospaceFamily)
6895         return;
6896 
6897     // We know the parent is monospace or the child is monospace, and that font
6898     // size was unspecified.  We want to scale our font size as appropriate.
6899     // If the font uses a keyword size, then we refetch from the table rather than
6900     // multiplying by our scale factor.
6901     float size;
6902     if (childFont.keywordSize())
6903         size = fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize());
6904     else {
6905         Settings* settings = m_checker.m_document->settings();
6906         float fixedScaleFactor = settings
6907             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
6908             : 1;
6909         size = parentFont.useFixedDefaultSize() ?
6910                 childFont.specifiedSize() / fixedScaleFactor :
6911                 childFont.specifiedSize() * fixedScaleFactor;
6912     }
6913 
6914     FontDescription newFontDescription(childFont);
6915     setFontSize(newFontDescription, size);
6916     style->setFontDescription(newFontDescription);
6917 }
6918 
setFontSize(FontDescription & fontDescription,float size)6919 void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size)
6920 {
6921     fontDescription.setSpecifiedSize(size);
6922 
6923     bool useSVGZoomRules = m_element && m_element->isSVGElement();
6924     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
6925 }
6926 
getComputedSizeFromSpecifiedSize(Document * document,RenderStyle * style,bool isAbsoluteSize,float specifiedSize,bool useSVGZoomRules)6927 float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules)
6928 {
6929     // Text with a 0px font size should not be visible and therefore needs to be
6930     // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
6931     // rendering. This is also compatible with other browsers that have minimum
6932     // font size settings (e.g. Firefox).
6933     if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon())
6934         return 0.0f;
6935 
6936     float zoomFactor = 1.0f;
6937     if (!useSVGZoomRules) {
6938         zoomFactor = style->effectiveZoom();
6939         if (Frame* frame = document->frame())
6940             zoomFactor *= frame->textZoomFactor();
6941     }
6942 
6943     // We support two types of minimum font size.  The first is a hard override that applies to
6944     // all fonts.  This is "minSize."  The second type of minimum font size is a "smart minimum"
6945     // that is applied only when the Web page can't know what size it really asked for, e.g.,
6946     // when it uses logical sizes like "small" or expresses the font-size as a percentage of
6947     // the user's default font setting.
6948 
6949     // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
6950     // However we always allow the page to set an explicit pixel size that is smaller,
6951     // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
6952 
6953     Settings* settings = document->settings();
6954     if (!settings)
6955         return 1.0f;
6956 
6957     int minSize = settings->minimumFontSize();
6958     int minLogicalSize = settings->minimumLogicalFontSize();
6959     float zoomedSize = specifiedSize * zoomFactor;
6960 
6961     // Apply the hard minimum first.  We only apply the hard minimum if after zooming we're still too small.
6962     if (zoomedSize < minSize)
6963         zoomedSize = minSize;
6964 
6965     // Now apply the "smart minimum."  This minimum is also only applied if we're still too small
6966     // after zooming.  The font size must either be relative to the user default or the original size
6967     // must have been acceptable.  In other words, we only apply the smart minimum whenever we're positive
6968     // doing so won't disrupt the layout.
6969     if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
6970         zoomedSize = minLogicalSize;
6971 
6972     // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
6973     // platforms (I'm looking at you, Windows.)
6974     return min(1000000.0f, zoomedSize);
6975 }
6976 
6977 const int fontSizeTableMax = 16;
6978 const int fontSizeTableMin = 9;
6979 const int totalKeywords = 8;
6980 
6981 // WinIE/Nav4 table for font sizes.  Designed to match the legacy font mapping system of HTML.
6982 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
6983 {
6984       { 9,    9,     9,     9,    11,    14,    18,    28 },
6985       { 9,    9,     9,    10,    12,    15,    20,    31 },
6986       { 9,    9,     9,    11,    13,    17,    22,    34 },
6987       { 9,    9,    10,    12,    14,    18,    24,    37 },
6988       { 9,    9,    10,    13,    16,    20,    26,    40 }, // fixed font default (13)
6989       { 9,    9,    11,    14,    17,    21,    28,    42 },
6990       { 9,   10,    12,    15,    17,    23,    30,    45 },
6991       { 9,   10,    13,    16,    18,    24,    32,    48 }  // proportional font default (16)
6992 };
6993 // HTML       1      2      3      4      5      6      7
6994 // CSS  xxs   xs     s      m      l     xl     xxl
6995 //                          |
6996 //                      user pref
6997 
6998 // Strict mode table matches MacIE and Mozilla's settings exactly.
6999 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
7000 {
7001       { 9,    9,     9,     9,    11,    14,    18,    27 },
7002       { 9,    9,     9,    10,    12,    15,    20,    30 },
7003       { 9,    9,    10,    11,    13,    17,    22,    33 },
7004       { 9,    9,    10,    12,    14,    18,    24,    36 },
7005       { 9,   10,    12,    13,    16,    20,    26,    39 }, // fixed font default (13)
7006       { 9,   10,    12,    14,    17,    21,    28,    42 },
7007       { 9,   10,    13,    15,    18,    23,    30,    45 },
7008       { 9,   10,    13,    16,    18,    24,    32,    48 }  // proportional font default (16)
7009 };
7010 // HTML       1      2      3      4      5      6      7
7011 // CSS  xxs   xs     s      m      l     xl     xxl
7012 //                          |
7013 //                      user pref
7014 
7015 // For values outside the range of the table, we use Todd Fahrner's suggested scale
7016 // factors for each keyword value.
7017 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
7018 
fontSizeForKeyword(Document * document,int keyword,bool shouldUseFixedDefaultSize)7019 float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool shouldUseFixedDefaultSize)
7020 {
7021     Settings* settings = document->settings();
7022     if (!settings)
7023         return 1.0f;
7024 
7025     bool quirksMode = document->inQuirksMode();
7026     int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
7027     if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
7028         // Look up the entry in the table.
7029         int row = mediumSize - fontSizeTableMin;
7030         int col = (keyword - CSSValueXxSmall);
7031         return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
7032     }
7033 
7034     // Value is outside the range of the table. Apply the scale factor instead.
7035     float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
7036     return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
7037 }
7038 
7039 template<typename T>
findNearestLegacyFontSize(int pixelFontSize,const T * table,int multiplier)7040 static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier)
7041 {
7042     // Ignore table[0] because xx-small does not correspond to any legacy font size.
7043     for (int i = 1; i < totalKeywords - 1; i++) {
7044         if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier)
7045             return i;
7046     }
7047     return totalKeywords - 1;
7048 }
7049 
legacyFontSize(Document * document,int pixelFontSize,bool shouldUseFixedDefaultSize)7050 int CSSStyleSelector::legacyFontSize(Document* document, int pixelFontSize, bool shouldUseFixedDefaultSize)
7051 {
7052     Settings* settings = document->settings();
7053     if (!settings)
7054         return 1;
7055 
7056     bool quirksMode = document->inQuirksMode();
7057     int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
7058     if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
7059         int row = mediumSize - fontSizeTableMin;
7060         return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1);
7061     }
7062 
7063     return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize);
7064 }
7065 
largerFontSize(float size,bool) const7066 float CSSStyleSelector::largerFontSize(float size, bool) const
7067 {
7068     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
7069     // the next size level.
7070     return size * 1.2f;
7071 }
7072 
smallerFontSize(float size,bool) const7073 float CSSStyleSelector::smallerFontSize(float size, bool) const
7074 {
7075     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
7076     // the next size level.
7077     return size / 1.2f;
7078 }
7079 
colorForCSSValue(int cssValueId)7080 static Color colorForCSSValue(int cssValueId)
7081 {
7082     struct ColorValue {
7083         int cssValueId;
7084         RGBA32 color;
7085     };
7086 
7087     static const ColorValue colorValues[] = {
7088         { CSSValueAqua, 0xFF00FFFF },
7089         { CSSValueBlack, 0xFF000000 },
7090         { CSSValueBlue, 0xFF0000FF },
7091         { CSSValueFuchsia, 0xFFFF00FF },
7092         { CSSValueGray, 0xFF808080 },
7093         { CSSValueGreen, 0xFF008000  },
7094         { CSSValueGrey, 0xFF808080 },
7095         { CSSValueLime, 0xFF00FF00 },
7096         { CSSValueMaroon, 0xFF800000 },
7097         { CSSValueNavy, 0xFF000080 },
7098         { CSSValueOlive, 0xFF808000  },
7099         { CSSValueOrange, 0xFFFFA500 },
7100         { CSSValuePurple, 0xFF800080 },
7101         { CSSValueRed, 0xFFFF0000 },
7102         { CSSValueSilver, 0xFFC0C0C0 },
7103         { CSSValueTeal, 0xFF008080  },
7104         { CSSValueTransparent, 0x00000000 },
7105         { CSSValueWhite, 0xFFFFFFFF },
7106         { CSSValueYellow, 0xFFFFFF00 },
7107         { 0, 0 }
7108     };
7109 
7110     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
7111         if (col->cssValueId == cssValueId)
7112             return col->color;
7113     }
7114     return RenderTheme::defaultTheme()->systemColor(cssValueId);
7115 }
7116 
getColorFromPrimitiveValue(CSSPrimitiveValue * primitiveValue) const7117 Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) const
7118 {
7119     Color col;
7120     int ident = primitiveValue->getIdent();
7121     if (ident) {
7122         if (ident == CSSValueWebkitText)
7123             col = m_element->document()->textColor();
7124         else if (ident == CSSValueWebkitLink)
7125             col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor();
7126         else if (ident == CSSValueWebkitActivelink)
7127             col = m_element->document()->activeLinkColor();
7128         else if (ident == CSSValueWebkitFocusRingColor)
7129             col = RenderTheme::focusRingColor();
7130         else if (ident == CSSValueCurrentcolor)
7131             col = m_style->color();
7132         else
7133             col = colorForCSSValue(ident);
7134     } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
7135         col.setRGB(primitiveValue->getRGBA32Value());
7136     return col;
7137 }
7138 
hasSelectorForAttribute(const AtomicString & attrname) const7139 bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) const
7140 {
7141     return m_selectorAttrs.contains(attrname.impl());
7142 }
7143 
addViewportDependentMediaQueryResult(const MediaQueryExp * expr,bool result)7144 void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
7145 {
7146     m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
7147 }
7148 
affectedByViewportChange() const7149 bool CSSStyleSelector::affectedByViewportChange() const
7150 {
7151     unsigned s = m_viewportDependentMediaQueryResults.size();
7152     for (unsigned i = 0; i < s; i++) {
7153         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
7154             return true;
7155     }
7156     return false;
7157 }
7158 
allVisitedStateChanged()7159 void CSSStyleSelector::SelectorChecker::allVisitedStateChanged()
7160 {
7161     if (m_linksCheckedForVisitedState.isEmpty())
7162         return;
7163     for (Node* node = m_document; node; node = node->traverseNextNode()) {
7164         if (node->isLink())
7165             node->setNeedsStyleRecalc();
7166     }
7167 }
7168 
visitedStateChanged(LinkHash visitedHash)7169 void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash)
7170 {
7171     if (!m_linksCheckedForVisitedState.contains(visitedHash))
7172         return;
7173     for (Node* node = m_document; node; node = node->traverseNextNode()) {
7174         const AtomicString* attr = linkAttribute(node);
7175         if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash)
7176             node->setNeedsStyleRecalc();
7177     }
7178 }
7179 
getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type)7180 static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type)
7181 {
7182     switch (type) {
7183         case WebKitCSSTransformValue::ScaleTransformOperation:          return TransformOperation::SCALE;
7184         case WebKitCSSTransformValue::ScaleXTransformOperation:         return TransformOperation::SCALE_X;
7185         case WebKitCSSTransformValue::ScaleYTransformOperation:         return TransformOperation::SCALE_Y;
7186         case WebKitCSSTransformValue::ScaleZTransformOperation:         return TransformOperation::SCALE_Z;
7187         case WebKitCSSTransformValue::Scale3DTransformOperation:        return TransformOperation::SCALE_3D;
7188         case WebKitCSSTransformValue::TranslateTransformOperation:      return TransformOperation::TRANSLATE;
7189         case WebKitCSSTransformValue::TranslateXTransformOperation:     return TransformOperation::TRANSLATE_X;
7190         case WebKitCSSTransformValue::TranslateYTransformOperation:     return TransformOperation::TRANSLATE_Y;
7191         case WebKitCSSTransformValue::TranslateZTransformOperation:     return TransformOperation::TRANSLATE_Z;
7192         case WebKitCSSTransformValue::Translate3DTransformOperation:    return TransformOperation::TRANSLATE_3D;
7193         case WebKitCSSTransformValue::RotateTransformOperation:         return TransformOperation::ROTATE;
7194         case WebKitCSSTransformValue::RotateXTransformOperation:        return TransformOperation::ROTATE_X;
7195         case WebKitCSSTransformValue::RotateYTransformOperation:        return TransformOperation::ROTATE_Y;
7196         case WebKitCSSTransformValue::RotateZTransformOperation:        return TransformOperation::ROTATE_Z;
7197         case WebKitCSSTransformValue::Rotate3DTransformOperation:       return TransformOperation::ROTATE_3D;
7198         case WebKitCSSTransformValue::SkewTransformOperation:           return TransformOperation::SKEW;
7199         case WebKitCSSTransformValue::SkewXTransformOperation:          return TransformOperation::SKEW_X;
7200         case WebKitCSSTransformValue::SkewYTransformOperation:          return TransformOperation::SKEW_Y;
7201         case WebKitCSSTransformValue::MatrixTransformOperation:         return TransformOperation::MATRIX;
7202         case WebKitCSSTransformValue::Matrix3DTransformOperation:       return TransformOperation::MATRIX_3D;
7203         case WebKitCSSTransformValue::PerspectiveTransformOperation:    return TransformOperation::PERSPECTIVE;
7204         case WebKitCSSTransformValue::UnknownTransformOperation:        return TransformOperation::NONE;
7205     }
7206     return TransformOperation::NONE;
7207 }
7208 
createTransformOperations(CSSValue * inValue,RenderStyle * style,RenderStyle * rootStyle,TransformOperations & outOperations)7209 bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations)
7210 {
7211     if (!inValue || !inValue->isValueList()) {
7212         outOperations.clear();
7213         return false;
7214     }
7215 
7216     float zoomFactor = style ? style->effectiveZoom() : 1;
7217     TransformOperations operations;
7218     CSSValueList* list = static_cast<CSSValueList*>(inValue);
7219     unsigned size = list->length();
7220     for (unsigned i = 0; i < size; i++) {
7221         CSSValue* currValue = list->itemWithoutBoundsCheck(i);
7222         if (!currValue->isWebKitCSSTransformValue())
7223             continue;
7224 
7225         WebKitCSSTransformValue* transformValue = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i));
7226         if (!transformValue->length())
7227             continue;
7228 
7229         bool haveNonPrimitiveValue = false;
7230         for (unsigned j = 0; j < transformValue->length(); ++j) {
7231             if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
7232                 haveNonPrimitiveValue = true;
7233                 break;
7234             }
7235         }
7236         if (haveNonPrimitiveValue)
7237             continue;
7238 
7239         CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0));
7240 
7241         switch (transformValue->operationType()) {
7242             case WebKitCSSTransformValue::ScaleTransformOperation:
7243             case WebKitCSSTransformValue::ScaleXTransformOperation:
7244             case WebKitCSSTransformValue::ScaleYTransformOperation: {
7245                 double sx = 1.0;
7246                 double sy = 1.0;
7247                 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
7248                     sy = firstValue->getDoubleValue();
7249                 else {
7250                     sx = firstValue->getDoubleValue();
7251                     if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
7252                         if (transformValue->length() > 1) {
7253                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7254                             sy = secondValue->getDoubleValue();
7255                         } else
7256                             sy = sx;
7257                     }
7258                 }
7259                 operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType())));
7260                 break;
7261             }
7262             case WebKitCSSTransformValue::ScaleZTransformOperation:
7263             case WebKitCSSTransformValue::Scale3DTransformOperation: {
7264                 double sx = 1.0;
7265                 double sy = 1.0;
7266                 double sz = 1.0;
7267                 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation)
7268                     sz = firstValue->getDoubleValue();
7269                 else if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
7270                     sy = firstValue->getDoubleValue();
7271                 else {
7272                     sx = firstValue->getDoubleValue();
7273                     if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
7274                         if (transformValue->length() > 2) {
7275                             CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
7276                             sz = thirdValue->getDoubleValue();
7277                         }
7278                         if (transformValue->length() > 1) {
7279                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7280                             sy = secondValue->getDoubleValue();
7281                         } else
7282                             sy = sx;
7283                     }
7284                 }
7285                 operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType())));
7286                 break;
7287             }
7288             case WebKitCSSTransformValue::TranslateTransformOperation:
7289             case WebKitCSSTransformValue::TranslateXTransformOperation:
7290             case WebKitCSSTransformValue::TranslateYTransformOperation: {
7291                 bool ok = true;
7292                 Length tx = Length(0, Fixed);
7293                 Length ty = Length(0, Fixed);
7294                 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
7295                     ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7296                 else {
7297                     tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7298                     if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
7299                         if (transformValue->length() > 1) {
7300                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7301                             ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
7302                         }
7303                     }
7304                 }
7305 
7306                 if (!ok)
7307                     return false;
7308 
7309                 operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType())));
7310                 break;
7311             }
7312             case WebKitCSSTransformValue::TranslateZTransformOperation:
7313             case WebKitCSSTransformValue::Translate3DTransformOperation: {
7314                 bool ok = true;
7315                 Length tx = Length(0, Fixed);
7316                 Length ty = Length(0, Fixed);
7317                 Length tz = Length(0, Fixed);
7318                 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation)
7319                     tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7320                 else if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
7321                     ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7322                 else {
7323                     tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7324                     if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
7325                         if (transformValue->length() > 2) {
7326                             CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
7327                             tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor, &ok);
7328                         }
7329                         if (transformValue->length() > 1) {
7330                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7331                             ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
7332                         }
7333                     }
7334                 }
7335 
7336                 if (!ok)
7337                     return false;
7338 
7339                 operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType())));
7340                 break;
7341             }
7342             case WebKitCSSTransformValue::RotateTransformOperation: {
7343                 double angle = firstValue->getDoubleValue();
7344                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
7345                     angle = rad2deg(angle);
7346                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
7347                     angle = grad2deg(angle);
7348                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
7349                     angle = turn2deg(angle);
7350 
7351                 operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType())));
7352                 break;
7353             }
7354             case WebKitCSSTransformValue::RotateXTransformOperation:
7355             case WebKitCSSTransformValue::RotateYTransformOperation:
7356             case WebKitCSSTransformValue::RotateZTransformOperation: {
7357                 double x = 0;
7358                 double y = 0;
7359                 double z = 0;
7360                 double angle = firstValue->getDoubleValue();
7361                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
7362                     angle = rad2deg(angle);
7363                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
7364                     angle = grad2deg(angle);
7365 
7366                 if (transformValue->operationType() == WebKitCSSTransformValue::RotateXTransformOperation)
7367                     x = 1;
7368                 else if (transformValue->operationType() == WebKitCSSTransformValue::RotateYTransformOperation)
7369                     y = 1;
7370                 else
7371                     z = 1;
7372                 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
7373                 break;
7374             }
7375             case WebKitCSSTransformValue::Rotate3DTransformOperation: {
7376                 if (transformValue->length() < 4)
7377                     break;
7378                 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7379                 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
7380                 CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3));
7381                 double x = firstValue->getDoubleValue();
7382                 double y = secondValue->getDoubleValue();
7383                 double z = thirdValue->getDoubleValue();
7384                 double angle = fourthValue->getDoubleValue();
7385                 if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
7386                     angle = rad2deg(angle);
7387                 else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
7388                     angle = grad2deg(angle);
7389                 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
7390                 break;
7391             }
7392             case WebKitCSSTransformValue::SkewTransformOperation:
7393             case WebKitCSSTransformValue::SkewXTransformOperation:
7394             case WebKitCSSTransformValue::SkewYTransformOperation: {
7395                 double angleX = 0;
7396                 double angleY = 0;
7397                 double angle = firstValue->getDoubleValue();
7398                 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
7399                     angle = rad2deg(angle);
7400                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
7401                     angle = grad2deg(angle);
7402                 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
7403                     angle = turn2deg(angle);
7404                 if (transformValue->operationType() == WebKitCSSTransformValue::SkewYTransformOperation)
7405                     angleY = angle;
7406                 else {
7407                     angleX = angle;
7408                     if (transformValue->operationType() == WebKitCSSTransformValue::SkewTransformOperation) {
7409                         if (transformValue->length() > 1) {
7410                             CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
7411                             angleY = secondValue->getDoubleValue();
7412                             if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
7413                                 angleY = rad2deg(angleY);
7414                             else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
7415                                 angleY = grad2deg(angleY);
7416                             else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
7417                                 angleY = turn2deg(angleY);
7418                         }
7419                     }
7420                 }
7421                 operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType())));
7422                 break;
7423             }
7424             case WebKitCSSTransformValue::MatrixTransformOperation: {
7425                 if (transformValue->length() < 6)
7426                     break;
7427                 double a = firstValue->getDoubleValue();
7428                 double b = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue();
7429                 double c = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue();
7430                 double d = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue();
7431                 double e = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue();
7432                 double f = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue();
7433                 operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f));
7434                 break;
7435             }
7436             case WebKitCSSTransformValue::Matrix3DTransformOperation: {
7437                 if (transformValue->length() < 16)
7438                     break;
7439                 TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(),
7440                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(),
7441                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(),
7442                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(),
7443                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(),
7444                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(),
7445                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(),
7446                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(),
7447                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(),
7448                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(),
7449                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(),
7450                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(),
7451                                    zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(),
7452                                    zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(),
7453                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(),
7454                                    static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue());
7455                 operations.operations().append(Matrix3DTransformOperation::create(matrix));
7456                 break;
7457             }
7458             case WebKitCSSTransformValue::PerspectiveTransformOperation: {
7459                 bool ok = true;
7460                 Length p = Length(0, Fixed);
7461                 if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType()))
7462                     p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
7463                 else {
7464                     // This is a quirk that should go away when 3d transforms are finalized.
7465                     double val = firstValue->getDoubleValue();
7466                     ok = val >= 0;
7467                     val = clampToPositiveInteger(val);
7468                     p = Length(static_cast<int>(val), Fixed);
7469                 }
7470 
7471                 if (!ok)
7472                     return false;
7473 
7474                 operations.operations().append(PerspectiveTransformOperation::create(p));
7475                 break;
7476             }
7477             case WebKitCSSTransformValue::UnknownTransformOperation:
7478                 ASSERT_NOT_REACHED();
7479                 break;
7480         }
7481     }
7482 
7483     outOperations = operations;
7484     return true;
7485 }
7486 
loadPendingImages()7487 void CSSStyleSelector::loadPendingImages()
7488 {
7489     if (m_pendingImageProperties.isEmpty())
7490         return;
7491 
7492     HashSet<int>::const_iterator end = m_pendingImageProperties.end();
7493     for (HashSet<int>::const_iterator it = m_pendingImageProperties.begin(); it != end; ++it) {
7494         CSSPropertyID currentProperty = static_cast<CSSPropertyID>(*it);
7495 
7496         CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
7497 
7498         switch (currentProperty) {
7499             case CSSPropertyBackgroundImage: {
7500                 for (FillLayer* backgroundLayer = m_style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
7501                     if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage()) {
7502                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(backgroundLayer->image())->cssImageValue();
7503                         backgroundLayer->setImage(imageValue->cachedImage(cachedResourceLoader));
7504                     }
7505                 }
7506                 break;
7507             }
7508 
7509             case CSSPropertyContent: {
7510                 for (ContentData* contentData = const_cast<ContentData*>(m_style->contentData()); contentData; contentData = contentData->next()) {
7511                     if (contentData->isImage() && contentData->image()->isPendingImage()) {
7512                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(contentData->image())->cssImageValue();
7513                         if (StyleCachedImage* cachedImage = imageValue->cachedImage(cachedResourceLoader))
7514                             contentData->setImage(cachedImage);
7515                     }
7516                 }
7517                 break;
7518             }
7519 
7520             case CSSPropertyCursor: {
7521                 if (CursorList* cursorList = m_style->cursors()) {
7522                     for (size_t i = 0; i < cursorList->size(); ++i) {
7523                         CursorData& currentCursor = cursorList->at(i);
7524                         if (StyleImage* image = currentCursor.image()) {
7525                             if (image->isPendingImage()) {
7526                                 CSSImageValue* imageValue = static_cast<StylePendingImage*>(image)->cssImageValue();
7527                                 currentCursor.setImage(imageValue->cachedImage(cachedResourceLoader));
7528                             }
7529                         }
7530                     }
7531                 }
7532                 break;
7533             }
7534 
7535             case CSSPropertyListStyleImage: {
7536                 if (m_style->listStyleImage() && m_style->listStyleImage()->isPendingImage()) {
7537                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(m_style->listStyleImage())->cssImageValue();
7538                     m_style->setListStyleImage(imageValue->cachedImage(cachedResourceLoader));
7539                 }
7540                 break;
7541             }
7542 
7543             case CSSPropertyWebkitBorderImage: {
7544                 const NinePieceImage& borderImage = m_style->borderImage();
7545                 if (borderImage.image() && borderImage.image()->isPendingImage()) {
7546                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(borderImage.image())->cssImageValue();
7547                     m_style->setBorderImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), borderImage.slices(), borderImage.horizontalRule(), borderImage.verticalRule()));
7548                 }
7549                 break;
7550             }
7551 
7552             case CSSPropertyWebkitBoxReflect: {
7553                 if (StyleReflection* reflection = m_style->boxReflect()) {
7554                     const NinePieceImage& maskImage = reflection->mask();
7555                     if (maskImage.image() && maskImage.image()->isPendingImage()) {
7556                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskImage.image())->cssImageValue();
7557                         reflection->setMask(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskImage.slices(), maskImage.horizontalRule(), maskImage.verticalRule()));
7558                     }
7559                 }
7560                 break;
7561             }
7562 
7563             case CSSPropertyWebkitMaskBoxImage: {
7564                 const NinePieceImage& maskBoxImage = m_style->maskBoxImage();
7565                 if (maskBoxImage.image() && maskBoxImage.image()->isPendingImage()) {
7566                     CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskBoxImage.image())->cssImageValue();
7567                     m_style->setMaskBoxImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskBoxImage.slices(), maskBoxImage.horizontalRule(), maskBoxImage.verticalRule()));
7568                 }
7569                 break;
7570             }
7571 
7572             case CSSPropertyWebkitMaskImage: {
7573                 for (FillLayer* maskLayer = m_style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
7574                     if (maskLayer->image() && maskLayer->image()->isPendingImage()) {
7575                         CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskLayer->image())->cssImageValue();
7576                         maskLayer->setImage(imageValue->cachedImage(cachedResourceLoader));
7577                     }
7578                 }
7579                 break;
7580             }
7581             default:
7582                 ASSERT_NOT_REACHED();
7583         }
7584     }
7585 
7586     m_pendingImageProperties.clear();
7587 }
7588 
7589 } // namespace WebCore
7590