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