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