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