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