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