Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: webkit/pending/CSSStyleSelector.cpp

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

Powered by Google App Engine
This is Rietveld 408576698