| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
| 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) | |
| 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) | |
| 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
All rights reserved. | |
| 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | |
| 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> | |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | |
| 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | |
| 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | |
| 11 * Copyright (C) 2012 Google Inc. All rights reserved. | |
| 12 * | |
| 13 * This library is free software; you can redistribute it and/or | |
| 14 * modify it under the terms of the GNU Library General Public | |
| 15 * License as published by the Free Software Foundation; either | |
| 16 * version 2 of the License, or (at your option) any later version. | |
| 17 * | |
| 18 * This library is distributed in the hope that it will be useful, | |
| 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 21 * Library General Public License for more details. | |
| 22 * | |
| 23 * You should have received a copy of the GNU Library General Public License | |
| 24 * along with this library; see the file COPYING.LIB. If not, write to | |
| 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
| 26 * Boston, MA 02110-1301, USA. | |
| 27 */ | |
| 28 | |
| 29 #include "config.h" | |
| 30 #include "core/css/StyleResolver.h" | |
| 31 | |
| 32 #include "CSSPropertyNames.h" | |
| 33 #include "HTMLNames.h" | |
| 34 #include "MathMLNames.h" | |
| 35 #include "RuntimeEnabledFeatures.h" | |
| 36 #include "UserAgentStyleSheets.h" | |
| 37 #include "WebKitFontFamilyNames.h" | |
| 38 #include "XMLNames.h" | |
| 39 #include "core/animation/Animation.h" | |
| 40 #include "core/css/CSSBorderImage.h" | |
| 41 #include "core/css/CSSCalculationValue.h" | |
| 42 #include "core/css/CSSCursorImageValue.h" | |
| 43 #include "core/css/CSSDefaultStyleSheets.h" | |
| 44 #include "core/css/CSSFontFaceRule.h" | |
| 45 #include "core/css/CSSFontSelector.h" | |
| 46 #include "core/css/CSSLineBoxContainValue.h" | |
| 47 #include "core/css/CSSPageRule.h" | |
| 48 #include "core/css/CSSParser.h" | |
| 49 #include "core/css/CSSPrimitiveValueMappings.h" | |
| 50 #include "core/css/CSSReflectValue.h" | |
| 51 #include "core/css/CSSSelector.h" | |
| 52 #include "core/css/CSSSelectorList.h" | |
| 53 #include "core/css/CSSStyleRule.h" | |
| 54 #include "core/css/CSSSupportsRule.h" | |
| 55 #include "core/css/CSSTimingFunctionValue.h" | |
| 56 #include "core/css/CSSValueList.h" | |
| 57 #include "core/css/CSSVariableValue.h" | |
| 58 #include "core/css/Counter.h" | |
| 59 #include "core/css/DeprecatedStyleBuilder.h" | |
| 60 #include "core/css/ElementRuleCollector.h" | |
| 61 #include "core/css/FilterOperationResolver.h" | |
| 62 #include "core/css/FontFeatureValue.h" | |
| 63 #include "core/css/FontValue.h" | |
| 64 #include "core/css/MediaList.h" | |
| 65 #include "core/css/MediaQueryEvaluator.h" | |
| 66 #include "core/css/PageRuleCollector.h" | |
| 67 #include "core/css/Pair.h" | |
| 68 #include "core/css/Rect.h" | |
| 69 #include "core/css/RuleSet.h" | |
| 70 #include "core/css/SelectorCheckerFastPath.h" | |
| 71 #include "core/css/ShadowValue.h" | |
| 72 #include "core/css/StylePropertySet.h" | |
| 73 #include "core/css/StylePropertyShorthand.h" | |
| 74 #include "core/css/StyleRule.h" | |
| 75 #include "core/css/StyleRuleImport.h" | |
| 76 #include "core/css/StyleSheetContents.h" | |
| 77 #include "core/css/StyleSheetList.h" | |
| 78 #include "core/css/TransformBuilder.h" | |
| 79 #include "core/css/ViewportStyleResolver.h" | |
| 80 #include "core/css/WebKitCSSKeyframeRule.h" | |
| 81 #include "core/css/WebKitCSSKeyframesRule.h" | |
| 82 #include "core/css/WebKitCSSRegionRule.h" | |
| 83 #include "core/dom/Attribute.h" | |
| 84 #include "core/dom/ContextFeatures.h" | |
| 85 #include "core/dom/DocumentStyleSheetCollection.h" | |
| 86 #include "core/dom/ElementShadow.h" | |
| 87 #include "core/dom/NodeRenderStyle.h" | |
| 88 #include "core/dom/NodeRenderingContext.h" | |
| 89 #include "core/dom/ShadowRoot.h" | |
| 90 #include "core/dom/Text.h" | |
| 91 #include "core/dom/VisitedLinkState.h" | |
| 92 #include "core/dom/WebCoreMemoryInstrumentation.h" | |
| 93 #include "core/editing/FrameSelection.h" | |
| 94 #include "core/html/HTMLDocument.h" | |
| 95 #include "core/html/HTMLIFrameElement.h" | |
| 96 #include "core/html/HTMLInputElement.h" | |
| 97 #include "core/html/HTMLOptionElement.h" | |
| 98 #include "core/html/HTMLProgressElement.h" | |
| 99 #include "core/html/HTMLStyleElement.h" | |
| 100 #include "core/html/HTMLTextAreaElement.h" | |
| 101 #include "core/html/shadow/InsertionPoint.h" | |
| 102 #include "core/inspector/InspectorInstrumentation.h" | |
| 103 #include "core/loader/cache/CachedImage.h" | |
| 104 #include "core/page/Frame.h" | |
| 105 #include "core/page/FrameView.h" | |
| 106 #include "core/page/Page.h" | |
| 107 #include "core/page/SecurityOrigin.h" | |
| 108 #include "core/page/Settings.h" | |
| 109 #include "core/platform/CalculationValue.h" | |
| 110 #include "core/platform/LinkHash.h" | |
| 111 #include "core/platform/text/LocaleToScriptMapping.h" | |
| 112 #include "core/rendering/RenderRegion.h" | |
| 113 #include "core/rendering/RenderScrollbar.h" | |
| 114 #include "core/rendering/RenderScrollbarTheme.h" | |
| 115 #include "core/rendering/RenderTheme.h" | |
| 116 #include "core/rendering/RenderView.h" | |
| 117 #include "core/rendering/style/ContentData.h" | |
| 118 #include "core/rendering/style/CounterContent.h" | |
| 119 #include "core/rendering/style/CursorList.h" | |
| 120 #include "core/rendering/style/KeyframeList.h" | |
| 121 #include "core/rendering/style/QuotesData.h" | |
| 122 #include "core/rendering/style/RenderStyleConstants.h" | |
| 123 #include "core/rendering/style/ShadowData.h" | |
| 124 #include "core/rendering/style/StyleCachedImage.h" | |
| 125 #include "core/rendering/style/StyleGeneratedImage.h" | |
| 126 #include "core/rendering/style/StylePendingImage.h" | |
| 127 #include "core/svg/SVGDocumentExtensions.h" | |
| 128 #include "core/svg/SVGFontFaceElement.h" | |
| 129 #include <wtf/MemoryInstrumentationHashMap.h> | |
| 130 #include <wtf/MemoryInstrumentationHashSet.h> | |
| 131 #include <wtf/MemoryInstrumentationVector.h> | |
| 132 #include <wtf/StdLibExtras.h> | |
| 133 #include <wtf/Vector.h> | |
| 134 | |
| 135 #if ENABLE(SVG) | |
| 136 #include "SVGNames.h" | |
| 137 #include "core/css/WebKitCSSSVGDocumentValue.h" | |
| 138 #include "core/loader/cache/CachedSVGDocument.h" | |
| 139 #include "core/loader/cache/CachedSVGDocumentReference.h" | |
| 140 #include "core/svg/SVGDocument.h" | |
| 141 #include "core/svg/SVGElement.h" | |
| 142 #include "core/svg/SVGURIReference.h" | |
| 143 #endif | |
| 144 | |
| 145 #include "core/css/CSSImageSetValue.h" | |
| 146 #include "core/css/WebKitCSSMixFunctionValue.h" | |
| 147 #include "core/css/WebKitCSSShaderValue.h" | |
| 148 #include "core/platform/graphics/filters/custom/CustomFilterArrayParameter.h" | |
| 149 #include "core/platform/graphics/filters/custom/CustomFilterConstants.h" | |
| 150 #include "core/platform/graphics/filters/custom/CustomFilterNumberParameter.h" | |
| 151 #include "core/platform/graphics/filters/custom/CustomFilterOperation.h" | |
| 152 #include "core/platform/graphics/filters/custom/CustomFilterParameter.h" | |
| 153 #include "core/platform/graphics/filters/custom/CustomFilterProgramInfo.h" | |
| 154 #include "core/platform/graphics/filters/custom/CustomFilterTransformParameter.h
" | |
| 155 #include "core/rendering/style/StyleCachedImageSet.h" | |
| 156 #include "core/rendering/style/StyleCachedShader.h" | |
| 157 #include "core/rendering/style/StyleCustomFilterProgram.h" | |
| 158 #include "core/rendering/style/StyleCustomFilterProgramCache.h" | |
| 159 #include "core/rendering/style/StylePendingShader.h" | |
| 160 #include "core/rendering/style/StyleShader.h" | |
| 161 | |
| 162 #include "core/html/track/WebVTTElement.h" | |
| 163 | |
| 164 using namespace std; | |
| 165 | |
| 166 namespace WTF { | |
| 167 | |
| 168 template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*>
{ | |
| 169 template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&)
{ } | |
| 170 }; | |
| 171 | |
| 172 } | |
| 173 | |
| 174 namespace WebCore { | |
| 175 | |
| 176 using namespace HTMLNames; | |
| 177 | |
| 178 #define HANDLE_INHERIT(prop, Prop) \ | |
| 179 if (isInherit) { \ | |
| 180 m_state.style()->set##Prop(m_state.parentStyle()->prop()); \ | |
| 181 return; \ | |
| 182 } | |
| 183 | |
| 184 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ | |
| 185 HANDLE_INHERIT(prop, Prop) \ | |
| 186 if (isInitial) { \ | |
| 187 m_state.style()->set##Prop(RenderStyle::initial##Prop()); \ | |
| 188 return; \ | |
| 189 } | |
| 190 | |
| 191 RenderStyle* StyleResolver::s_styleNotYetAvailable; | |
| 192 | |
| 193 static StylePropertySet* leftToRightDeclaration() | |
| 194 { | |
| 195 DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropert
ySet::create())); | |
| 196 if (leftToRightDecl->isEmpty()) | |
| 197 leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr); | |
| 198 return leftToRightDecl.get(); | |
| 199 } | |
| 200 | |
| 201 static StylePropertySet* rightToLeftDeclaration() | |
| 202 { | |
| 203 DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropert
ySet::create())); | |
| 204 if (rightToLeftDecl->isEmpty()) | |
| 205 rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl); | |
| 206 return rightToLeftDecl.get(); | |
| 207 } | |
| 208 | |
| 209 | |
| 210 void StyleResolver::MatchResult::addMatchedProperties(const StylePropertySet* pr
operties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propert
yWhitelistType) | |
| 211 { | |
| 212 matchedProperties.grow(matchedProperties.size() + 1); | |
| 213 StyleResolver::MatchedProperties& newProperties = matchedProperties.last(); | |
| 214 newProperties.properties = const_cast<StylePropertySet*>(properties); | |
| 215 newProperties.linkMatchType = linkMatchType; | |
| 216 newProperties.whitelistType = propertyWhitelistType; | |
| 217 matchedRules.append(rule); | |
| 218 } | |
| 219 | |
| 220 StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles) | |
| 221 : m_matchedPropertiesCacheAdditionsSinceLastSweep(0) | |
| 222 , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPrope
rtiesCache) | |
| 223 , m_document(document) | |
| 224 , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles) | |
| 225 , m_fontSelector(CSSFontSelector::create(document)) | |
| 226 #if ENABLE(CSS_DEVICE_ADAPTATION) | |
| 227 , m_viewportStyleResolver(ViewportStyleResolver::create(document)) | |
| 228 #endif | |
| 229 , m_styleBuilder(DeprecatedStyleBuilder::sharedStyleBuilder()) | |
| 230 , m_styleMap(this) | |
| 231 { | |
| 232 Element* root = document->documentElement(); | |
| 233 | |
| 234 CSSDefaultStyleSheets::initDefaultStyle(root); | |
| 235 | |
| 236 // construct document root element default style. this is needed | |
| 237 // to evaluate media queries that contain relative constraints, like "screen
and (max-width: 10em)" | |
| 238 // This is here instead of constructor, because when constructor is run, | |
| 239 // document doesn't have documentElement | |
| 240 // NOTE: this assumes that element that gets passed to styleForElement -call | |
| 241 // is always from the document that owns the style selector | |
| 242 FrameView* view = document->view(); | |
| 243 if (view) | |
| 244 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType())); | |
| 245 else | |
| 246 m_medium = adoptPtr(new MediaQueryEvaluator("all")); | |
| 247 | |
| 248 if (root) | |
| 249 m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, Matc
hOnlyUserAgentRules); | |
| 250 | |
| 251 if (m_rootDefaultStyle && view) | |
| 252 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->fra
me(), m_rootDefaultStyle.get())); | |
| 253 | |
| 254 m_ruleSets.resetAuthorStyle(); | |
| 255 | |
| 256 DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCol
lection(); | |
| 257 m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this); | |
| 258 | |
| 259 #if ENABLE(SVG_FONTS) | |
| 260 if (document->svgExtensions()) { | |
| 261 const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgE
xtensions()->svgFontFaceElements(); | |
| 262 HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.e
nd(); | |
| 263 for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElemen
ts.begin(); it != end; ++it) | |
| 264 fontSelector()->addFontFaceRule((*it)->fontFaceRule()); | |
| 265 } | |
| 266 #endif | |
| 267 | |
| 268 appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets()); | |
| 269 } | |
| 270 | |
| 271 void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefP
tr<CSSStyleSheet> >& styleSheets) | |
| 272 { | |
| 273 m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_
inspectorCSSOMWrappers, document()->isViewSource(), this); | |
| 274 if (document()->renderer() && document()->renderer()->style()) | |
| 275 document()->renderer()->style()->font().update(fontSelector()); | |
| 276 | |
| 277 #if ENABLE(CSS_DEVICE_ADAPTATION) | |
| 278 viewportStyleResolver()->resolve(); | |
| 279 #endif | |
| 280 } | |
| 281 | |
| 282 void StyleResolver::pushParentElement(Element* parent) | |
| 283 { | |
| 284 const ContainerNode* parentsParent = parent->parentOrShadowHostElement(); | |
| 285 | |
| 286 // We are not always invoked consistently. For example, script execution can
cause us to enter | |
| 287 // style recalc in the middle of tree building. We may also be invoked from
somewhere within the tree. | |
| 288 // Reset the stack in this case, or if we see a new root element. | |
| 289 // Otherwise just push the new parent. | |
| 290 if (!parentsParent || m_selectorFilter.parentStackIsEmpty()) | |
| 291 m_selectorFilter.setupParentStack(parent); | |
| 292 else | |
| 293 m_selectorFilter.pushParent(parent); | |
| 294 | |
| 295 // Note: We mustn't skip ShadowRoot nodes for the scope stack. | |
| 296 if (m_scopeResolver) | |
| 297 m_scopeResolver->push(parent, parent->parentOrShadowHostNode()); | |
| 298 } | |
| 299 | |
| 300 void StyleResolver::popParentElement(Element* parent) | |
| 301 { | |
| 302 // Note that we may get invoked for some random elements in some wacky cases
during style resolve. | |
| 303 // Pause maintaining the stack in this case. | |
| 304 if (m_selectorFilter.parentStackIsConsistent(parent)) | |
| 305 m_selectorFilter.popParent(); | |
| 306 if (m_scopeResolver) | |
| 307 m_scopeResolver->pop(parent); | |
| 308 } | |
| 309 | |
| 310 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot) | |
| 311 { | |
| 312 ASSERT(shadowRoot->host()); | |
| 313 if (m_scopeResolver) | |
| 314 m_scopeResolver->push(shadowRoot, shadowRoot->host()); | |
| 315 } | |
| 316 | |
| 317 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot) | |
| 318 { | |
| 319 ASSERT(shadowRoot->host()); | |
| 320 if (m_scopeResolver) | |
| 321 m_scopeResolver->pop(shadowRoot); | |
| 322 } | |
| 323 | |
| 324 // This is a simplified style setting function for keyframe styles | |
| 325 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule) | |
| 326 { | |
| 327 AtomicString s(rule->name()); | |
| 328 m_keyframesRuleMap.set(s.impl(), rule); | |
| 329 } | |
| 330 | |
| 331 StyleResolver::~StyleResolver() | |
| 332 { | |
| 333 m_fontSelector->clearDocument(); | |
| 334 | |
| 335 #if ENABLE(CSS_DEVICE_ADAPTATION) | |
| 336 m_viewportStyleResolver->clearDocument(); | |
| 337 #endif | |
| 338 } | |
| 339 | |
| 340 void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*) | |
| 341 { | |
| 342 // Look for cache entries containing a style declaration with a single ref a
nd remove them. | |
| 343 // This may happen when an element attribute mutation causes it to generate
a new inlineStyle() | |
| 344 // or presentationAttributeStyle(), potentially leaving this cache with the
last ref on the old one. | |
| 345 Vector<unsigned, 16> toRemove; | |
| 346 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin(); | |
| 347 MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end(); | |
| 348 for (; it != end; ++it) { | |
| 349 Vector<MatchedProperties>& matchedProperties = it->value.matchedProperti
es; | |
| 350 for (size_t i = 0; i < matchedProperties.size(); ++i) { | |
| 351 if (matchedProperties[i].properties->hasOneRef()) { | |
| 352 toRemove.append(it->key); | |
| 353 break; | |
| 354 } | |
| 355 } | |
| 356 } | |
| 357 for (size_t i = 0; i < toRemove.size(); ++i) | |
| 358 m_matchedPropertiesCache.remove(toRemove[i]); | |
| 359 | |
| 360 m_matchedPropertiesCacheAdditionsSinceLastSweep = 0; | |
| 361 } | |
| 362 | |
| 363 inline bool StyleResolver::styleSharingCandidateMatchesHostRules() | |
| 364 { | |
| 365 return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostR
ules(m_state.element()); | |
| 366 } | |
| 367 | |
| 368 bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames
) const | |
| 369 { | |
| 370 for (unsigned i = 0; i < classNames.size(); ++i) { | |
| 371 if (m_ruleSets.features().classesInRules.contains(classNames[i].impl())) | |
| 372 return true; | |
| 373 } | |
| 374 return false; | |
| 375 } | |
| 376 | |
| 377 inline void StyleResolver::matchShadowDistributedRules(ElementRuleCollector& col
lector, bool includeEmptyRules, StyleResolver::RuleRange& ruleRange) | |
| 378 { | |
| 379 if (m_ruleSets.shadowDistributedRules().isEmpty()) | |
| 380 return; | |
| 381 | |
| 382 bool previousCanUseFastReject = collector.canUseFastReject(); | |
| 383 SelectorChecker::BehaviorAtBoundary previousBoundary = collector.behaviorAtB
oundary(); | |
| 384 collector.setBehaviorAtBoundary(static_cast<SelectorChecker::BehaviorAtBound
ary>(SelectorChecker::CrossesBoundary | SelectorChecker::ScopeContainsLastMatche
dElement)); | |
| 385 collector.setCanUseFastReject(false); | |
| 386 | |
| 387 Vector<MatchRequest> matchRequests; | |
| 388 m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules,
matchRequests); | |
| 389 for (size_t i = 0; i < matchRequests.size(); ++i) | |
| 390 collector.collectMatchingRules(matchRequests[i], ruleRange); | |
| 391 | |
| 392 collector.setBehaviorAtBoundary(previousBoundary); | |
| 393 collector.setCanUseFastReject(previousCanUseFastReject); | |
| 394 } | |
| 395 | |
| 396 void StyleResolver::matchHostRules(ElementRuleCollector& collector, bool include
EmptyRules) | |
| 397 { | |
| 398 ASSERT(m_scopeResolver); | |
| 399 | |
| 400 collector.clearMatchedRules(); | |
| 401 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().
matchedProperties.size() - 1; | |
| 402 | |
| 403 Vector<RuleSet*> matchedRules; | |
| 404 m_scopeResolver->matchHostRules(m_state.element(), matchedRules); | |
| 405 if (matchedRules.isEmpty()) | |
| 406 return; | |
| 407 | |
| 408 for (unsigned i = matchedRules.size(); i > 0; --i) { | |
| 409 StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.au
thorRuleRange(); | |
| 410 collector.collectMatchingRules(MatchRequest(matchedRules.at(i-1), includ
eEmptyRules, m_state.element()), ruleRange); | |
| 411 } | |
| 412 collector.sortAndTransferMatchedRules(); | |
| 413 } | |
| 414 | |
| 415 void StyleResolver::matchScopedAuthorRules(ElementRuleCollector& collector, bool
includeEmptyRules) | |
| 416 { | |
| 417 if (!m_scopeResolver) | |
| 418 return; | |
| 419 | |
| 420 // Match scoped author rules by traversing the scoped element stack (rebuild
it if it got inconsistent). | |
| 421 if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsis
tency(m_state.element())) { | |
| 422 bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyl
es(); | |
| 423 bool documentScope = true; | |
| 424 | |
| 425 unsigned scopeSize = m_scopeResolver->stackSize(); | |
| 426 for (unsigned i = 0; i < scopeSize; ++i) { | |
| 427 collector.clearMatchedRules(); | |
| 428 collector.matchedResult().ranges.lastAuthorRule = collector.matchedR
esult().matchedProperties.size() - 1; | |
| 429 | |
| 430 const ScopedStyleResolver::StackFrame& frame = m_scopeResolver->stac
kFrameAt(i); | |
| 431 documentScope = documentScope && !frame.m_scope->isInShadowTree(); | |
| 432 if (documentScope) { | |
| 433 if (!applyAuthorStyles) | |
| 434 continue; | |
| 435 } else { | |
| 436 if (!m_scopeResolver->matchesStyleBounds(frame)) | |
| 437 continue; | |
| 438 } | |
| 439 | |
| 440 MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.
m_scope); | |
| 441 StyleResolver::RuleRange ruleRange = collector.matchedResult().range
s.authorRuleRange(); | |
| 442 collector.collectMatchingRules(matchRequest, ruleRange); | |
| 443 collector.collectMatchingRulesForRegion(matchRequest, ruleRange); | |
| 444 collector.sortAndTransferMatchedRules(); | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 matchHostRules(collector, includeEmptyRules); | |
| 449 } | |
| 450 | |
| 451 void StyleResolver::matchAuthorRules(ElementRuleCollector& collector, bool inclu
deEmptyRules) | |
| 452 { | |
| 453 collector.clearMatchedRules(); | |
| 454 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().
matchedProperties.size() - 1; | |
| 455 | |
| 456 if (!m_state.element()) | |
| 457 return; | |
| 458 | |
| 459 // Match global author rules. | |
| 460 MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules); | |
| 461 StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.author
RuleRange(); | |
| 462 collector.collectMatchingRules(matchRequest, ruleRange); | |
| 463 collector.collectMatchingRulesForRegion(matchRequest, ruleRange); | |
| 464 matchShadowDistributedRules(collector, includeEmptyRules, ruleRange); | |
| 465 collector.sortAndTransferMatchedRules(); | |
| 466 | |
| 467 matchScopedAuthorRules(collector, includeEmptyRules); | |
| 468 } | |
| 469 | |
| 470 void StyleResolver::matchUserRules(ElementRuleCollector& collector, bool include
EmptyRules) | |
| 471 { | |
| 472 if (!m_ruleSets.userStyle()) | |
| 473 return; | |
| 474 | |
| 475 collector.clearMatchedRules(); | |
| 476 collector.matchedResult().ranges.lastUserRule = collector.matchedResult().ma
tchedProperties.size() - 1; | |
| 477 | |
| 478 MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules); | |
| 479 RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange(); | |
| 480 collector.collectMatchingRules(matchRequest, ruleRange); | |
| 481 collector.collectMatchingRulesForRegion(matchRequest, ruleRange); | |
| 482 | |
| 483 collector.sortAndTransferMatchedRules(); | |
| 484 } | |
| 485 | |
| 486 void StyleResolver::matchUARules(ElementRuleCollector& collector) | |
| 487 { | |
| 488 collector.setMatchingUARules(true); | |
| 489 | |
| 490 // First we match rules from the user agent sheet. | |
| 491 if (CSSDefaultStyleSheets::simpleDefaultStyleSheet) | |
| 492 collector.matchedResult().isCacheable = false; | |
| 493 | |
| 494 RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") | |
| 495 ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defa
ultStyle; | |
| 496 matchUARules(collector, userAgentStyleSheet); | |
| 497 | |
| 498 // In quirks mode, we match rules from the quirks user agent sheet. | |
| 499 if (document()->inQuirksMode()) | |
| 500 matchUARules(collector, CSSDefaultStyleSheets::defaultQuirksStyle); | |
| 501 | |
| 502 // 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. | |
| 503 if (document()->isViewSource()) | |
| 504 matchUARules(collector, CSSDefaultStyleSheets::viewSourceStyle()); | |
| 505 | |
| 506 collector.setMatchingUARules(false); | |
| 507 } | |
| 508 | |
| 509 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules
) | |
| 510 { | |
| 511 collector.clearMatchedRules(); | |
| 512 collector.matchedResult().ranges.lastUARule = collector.matchedResult().matc
hedProperties.size() - 1; | |
| 513 | |
| 514 RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange(); | |
| 515 collector.collectMatchingRules(MatchRequest(rules), ruleRange); | |
| 516 | |
| 517 collector.sortAndTransferMatchedRules(); | |
| 518 } | |
| 519 | |
| 520 void StyleResolver::matchAllRules(ElementRuleCollector& collector, bool matchAut
horAndUserStyles, bool includeSMILProperties) | |
| 521 { | |
| 522 matchUARules(collector); | |
| 523 | |
| 524 // Now we check user sheet rules. | |
| 525 if (matchAuthorAndUserStyles) | |
| 526 matchUserRules(collector, false); | |
| 527 | |
| 528 // Now check author rules, beginning first with presentational attributes ma
pped from HTML. | |
| 529 if (m_state.styledElement()) { | |
| 530 collector.addElementStyleProperties(m_state.styledElement()->presentatio
nAttributeStyle()); | |
| 531 | |
| 532 // Now we check additional mapped declarations. | |
| 533 // Tables and table cells share an additional mapped rule that must be a
pplied | |
| 534 // after all attributes, since their mapped style depends on the values
of multiple attributes. | |
| 535 collector.addElementStyleProperties(m_state.styledElement()->additionalP
resentationAttributeStyle()); | |
| 536 | |
| 537 if (m_state.styledElement()->isHTMLElement()) { | |
| 538 bool isAuto; | |
| 539 TextDirection textDirection = toHTMLElement(m_state.styledElement())
->directionalityIfhasDirAutoAttribute(isAuto); | |
| 540 if (isAuto) | |
| 541 collector.matchedResult().addMatchedProperties(textDirection ==
LTR ? leftToRightDeclaration() : rightToLeftDeclaration()); | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 // Check the rules in author sheets next. | |
| 546 if (matchAuthorAndUserStyles) | |
| 547 matchAuthorRules(collector, false); | |
| 548 | |
| 549 // Now check our inline style attribute. | |
| 550 if (matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledEle
ment()->inlineStyle()) { | |
| 551 // Inline style is immutable as long as there is no CSSOM wrapper. | |
| 552 // FIXME: Media control shadow trees seem to have problems with caching. | |
| 553 bool isInlineStyleCacheable = !m_state.styledElement()->inlineStyle()->isM
utable() && !m_state.styledElement()->isInShadowTree(); | |
| 554 // FIXME: Constify. | |
| 555 collector.addElementStyleProperties(m_state.styledElement()->inlineStyle()
, isInlineStyleCacheable); | |
| 556 } | |
| 557 | |
| 558 #if ENABLE(SVG) | |
| 559 // Now check SMIL animation override style. | |
| 560 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme
nt() && m_state.styledElement()->isSVGElement()) | |
| 561 collector.addElementStyleProperties(toSVGElement(m_state.styledElement()
)->animatedSMILStyleProperties(), false /* isCacheable */); | |
| 562 #else | |
| 563 UNUSED_PARAM(includeSMILProperties); | |
| 564 #endif | |
| 565 | |
| 566 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations(
)) | |
| 567 collector.matchedResult().isCacheable = false; | |
| 568 } | |
| 569 | |
| 570 inline void StyleResolver::initElement(Element* e) | |
| 571 { | |
| 572 if (m_state.element() != e) { | |
| 573 m_state.initElement(e); | |
| 574 if (e && e == e->document()->documentElement()) { | |
| 575 e->document()->setDirectionSetOnDocumentElement(false); | |
| 576 e->document()->setWritingModeSetOnDocumentElement(false); | |
| 577 } | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 static const unsigned cStyleSearchThreshold = 10; | |
| 582 static const unsigned cStyleSearchLevelThreshold = 10; | |
| 583 | |
| 584 static inline bool parentElementPreventsSharing(const Element* parentElement) | |
| 585 { | |
| 586 if (!parentElement) | |
| 587 return false; | |
| 588 return parentElement->hasFlagsSetDuringStylingOfChildren(); | |
| 589 } | |
| 590 | |
| 591 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCoun
t) const | |
| 592 { | |
| 593 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold) | |
| 594 return 0; | |
| 595 if (!parent || !parent->isStyledElement()) | |
| 596 return 0; | |
| 597 if (parent->hasScopedHTMLStyleChild()) | |
| 598 return 0; | |
| 599 StyledElement* p = static_cast<StyledElement*>(parent); | |
| 600 if (p->inlineStyle()) | |
| 601 return 0; | |
| 602 #if ENABLE(SVG) | |
| 603 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties()) | |
| 604 return 0; | |
| 605 #endif | |
| 606 if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleRes
olution().impl())) | |
| 607 return 0; | |
| 608 | |
| 609 RenderStyle* parentStyle = p->renderStyle(); | |
| 610 unsigned subcount = 0; | |
| 611 Node* thisCousin = p; | |
| 612 Node* currentNode = p->previousSibling(); | |
| 613 | |
| 614 // Reserve the tries for this level. This effectively makes sure that the al
gorithm | |
| 615 // will never go deeper than cStyleSearchLevelThreshold levels into recursio
n. | |
| 616 visitedNodeCount += cStyleSearchThreshold; | |
| 617 while (thisCousin) { | |
| 618 while (currentNode) { | |
| 619 ++subcount; | |
| 620 if (currentNode->renderStyle() == parentStyle && currentNode->lastCh
ild() | |
| 621 && currentNode->isElementNode() && !parentElementPreventsSharing
(toElement(currentNode)) | |
| 622 && !toElement(currentNode)->shadow() | |
| 623 ) { | |
| 624 // Adjust for unused reserved tries. | |
| 625 visitedNodeCount -= cStyleSearchThreshold - subcount; | |
| 626 return currentNode->lastChild(); | |
| 627 } | |
| 628 if (subcount >= cStyleSearchThreshold) | |
| 629 return 0; | |
| 630 currentNode = currentNode->previousSibling(); | |
| 631 } | |
| 632 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC
ount); | |
| 633 thisCousin = currentNode; | |
| 634 } | |
| 635 | |
| 636 return 0; | |
| 637 } | |
| 638 | |
| 639 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) | |
| 640 { | |
| 641 if (!ruleSet) | |
| 642 return false; | |
| 643 | |
| 644 ElementRuleCollector collector(this, m_state); | |
| 645 return collector.hasAnyMatchingRules(ruleSet); | |
| 646 } | |
| 647 | |
| 648 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const | |
| 649 { | |
| 650 const StyleResolverState& state = m_state; | |
| 651 HTMLInputElement* thisInputElement = element->toInputElement(); | |
| 652 HTMLInputElement* otherInputElement = state.element()->toInputElement(); | |
| 653 | |
| 654 if (!thisInputElement || !otherInputElement) | |
| 655 return false; | |
| 656 | |
| 657 if (thisInputElement->elementData() != otherInputElement->elementData()) { | |
| 658 if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->f
astGetAttribute(typeAttr)) | |
| 659 return false; | |
| 660 if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElemen
t->fastGetAttribute(readonlyAttr)) | |
| 661 return false; | |
| 662 } | |
| 663 | |
| 664 if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) | |
| 665 return false; | |
| 666 if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppe
arChecked()) | |
| 667 return false; | |
| 668 if (thisInputElement->shouldAppearIndeterminate() != otherInputElement->shou
ldAppearIndeterminate()) | |
| 669 return false; | |
| 670 if (thisInputElement->isRequired() != otherInputElement->isRequired()) | |
| 671 return false; | |
| 672 | |
| 673 if (element->isDisabledFormControl() != state.element()->isDisabledFormContr
ol()) | |
| 674 return false; | |
| 675 | |
| 676 if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonFor
Form()) | |
| 677 return false; | |
| 678 | |
| 679 if (state.document()->containsValidityStyleRules()) { | |
| 680 bool willValidate = element->willValidate(); | |
| 681 | |
| 682 if (willValidate != state.element()->willValidate()) | |
| 683 return false; | |
| 684 | |
| 685 if (willValidate && (element->isValidFormControlElement() != state.eleme
nt()->isValidFormControlElement())) | |
| 686 return false; | |
| 687 | |
| 688 if (element->isInRange() != state.element()->isInRange()) | |
| 689 return false; | |
| 690 | |
| 691 if (element->isOutOfRange() != state.element()->isOutOfRange()) | |
| 692 return false; | |
| 693 } | |
| 694 | |
| 695 return true; | |
| 696 } | |
| 697 | |
| 698 static inline bool elementHasDirectionAuto(Element* element) | |
| 699 { | |
| 700 // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionA
uto into StyleResolver. | |
| 701 return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto(
); | |
| 702 } | |
| 703 | |
| 704 bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledE
lement* sharingCandidate) const | |
| 705 { | |
| 706 const StyleResolverState& state = m_state; | |
| 707 if (state.element()->elementData() == sharingCandidate->elementData()) | |
| 708 return true; | |
| 709 if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidat
e->fastGetAttribute(XMLNames::langAttr)) | |
| 710 return false; | |
| 711 if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGet
Attribute(langAttr)) | |
| 712 return false; | |
| 713 | |
| 714 if (!state.elementAffectedByClassRules()) { | |
| 715 if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCan
didate->classNames())) | |
| 716 return false; | |
| 717 } else if (sharingCandidate->hasClass()) { | |
| 718 #if ENABLE(SVG) | |
| 719 // SVG elements require a (slow!) getAttribute comparision because "clas
s" is an animatable attribute for SVG. | |
| 720 if (state.element()->isSVGElement()) { | |
| 721 if (state.element()->getAttribute(classAttr) != sharingCandidate->ge
tAttribute(classAttr)) | |
| 722 return false; | |
| 723 } else { | |
| 724 #endif | |
| 725 if (state.element()->classNames() != sharingCandidate->classNames()) | |
| 726 return false; | |
| 727 #if ENABLE(SVG) | |
| 728 } | |
| 729 #endif | |
| 730 } else | |
| 731 return false; | |
| 732 | |
| 733 if (state.styledElement()->presentationAttributeStyle() != sharingCandidate-
>presentationAttributeStyle()) | |
| 734 return false; | |
| 735 | |
| 736 if (state.element()->hasTagName(progressTag)) { | |
| 737 if (state.element()->shouldAppearIndeterminate() != sharingCandidate->sh
ouldAppearIndeterminate()) | |
| 738 return false; | |
| 739 } | |
| 740 | |
| 741 return true; | |
| 742 } | |
| 743 | |
| 744 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const | |
| 745 { | |
| 746 RenderStyle* style = element->renderStyle(); | |
| 747 const StyleResolverState& state = m_state; | |
| 748 | |
| 749 if (!style) | |
| 750 return false; | |
| 751 if (style->unique()) | |
| 752 return false; | |
| 753 if (style->hasUniquePseudoStyle()) | |
| 754 return false; | |
| 755 if (element->tagQName() != state.element()->tagQName()) | |
| 756 return false; | |
| 757 if (element->inlineStyle()) | |
| 758 return false; | |
| 759 if (element->needsStyleRecalc()) | |
| 760 return false; | |
| 761 #if ENABLE(SVG) | |
| 762 if (element->isSVGElement() && toSVGElement(element)->animatedSMILStylePrope
rties()) | |
| 763 return false; | |
| 764 #endif | |
| 765 if (element->isLink() != state.element()->isLink()) | |
| 766 return false; | |
| 767 if (element->hovered() != state.element()->hovered()) | |
| 768 return false; | |
| 769 if (element->active() != state.element()->active()) | |
| 770 return false; | |
| 771 if (element->focused() != state.element()->focused()) | |
| 772 return false; | |
| 773 if (element->shadowPseudoId() != state.element()->shadowPseudoId()) | |
| 774 return false; | |
| 775 if (element == element->document()->cssTarget()) | |
| 776 return false; | |
| 777 if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element)) | |
| 778 return false; | |
| 779 if (element->additionalPresentationAttributeStyle() != state.styledElement()
->additionalPresentationAttributeStyle()) | |
| 780 return false; | |
| 781 | |
| 782 if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->i
dForStyleResolution().impl())) | |
| 783 return false; | |
| 784 if (element->hasScopedHTMLStyleChild()) | |
| 785 return false; | |
| 786 | |
| 787 // FIXME: We should share style for option and optgroup whenever possible. | |
| 788 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcLi
stItems | |
| 789 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cg
i?id=88405 | |
| 790 if (element->hasTagName(optionTag) || element->hasTagName(optgroupTag)) | |
| 791 return false; | |
| 792 | |
| 793 bool isControl = element->isFormControlElement(); | |
| 794 | |
| 795 if (isControl != state.element()->isFormControlElement()) | |
| 796 return false; | |
| 797 | |
| 798 if (isControl && !canShareStyleWithControl(element)) | |
| 799 return false; | |
| 800 | |
| 801 if (style->transitions() || style->animations()) | |
| 802 return false; | |
| 803 | |
| 804 // Turn off style sharing for elements that can gain layers for reasons outs
ide of the style system. | |
| 805 // See comments in RenderObject::setStyle(). | |
| 806 if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || eleme
nt->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagNam
e(appletTag) || element->hasTagName(canvasTag)) | |
| 807 return false; | |
| 808 | |
| 809 if (elementHasDirectionAuto(element)) | |
| 810 return false; | |
| 811 | |
| 812 if (element->isLink() && state.elementLinkState() != style->insideLink()) | |
| 813 return false; | |
| 814 | |
| 815 if (element->isUnresolvedCustomElement() != state.element()->isUnresolvedCus
tomElement()) | |
| 816 return false; | |
| 817 | |
| 818 // Deny sharing styles between WebVTT and non-WebVTT nodes. | |
| 819 if (element->isWebVTTElement() != state.element()->isWebVTTElement()) | |
| 820 return false; | |
| 821 | |
| 822 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWe
bVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNo
de()) | |
| 823 return false; | |
| 824 | |
| 825 if (element == element->document()->webkitCurrentFullScreenElement() || stat
e.element() == state.document()->webkitCurrentFullScreenElement()) | |
| 826 return false; | |
| 827 return true; | |
| 828 } | |
| 829 | |
| 830 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsi
gned& count) const | |
| 831 { | |
| 832 for (; node; node = node->previousSibling()) { | |
| 833 if (!node->isStyledElement()) | |
| 834 continue; | |
| 835 if (canShareStyleWithElement(static_cast<StyledElement*>(node))) | |
| 836 break; | |
| 837 if (count++ == cStyleSearchThreshold) | |
| 838 return 0; | |
| 839 } | |
| 840 return static_cast<StyledElement*>(node); | |
| 841 } | |
| 842 | |
| 843 RenderStyle* StyleResolver::locateSharedStyle() | |
| 844 { | |
| 845 StyleResolverState& state = m_state; | |
| 846 if (!state.styledElement() || !state.parentStyle()) | |
| 847 return 0; | |
| 848 | |
| 849 // If the element has inline style it is probably unique. | |
| 850 if (state.styledElement()->inlineStyle()) | |
| 851 return 0; | |
| 852 #if ENABLE(SVG) | |
| 853 if (state.styledElement()->isSVGElement() && toSVGElement(state.styledElemen
t())->animatedSMILStyleProperties()) | |
| 854 return 0; | |
| 855 #endif | |
| 856 // Ids stop style sharing if they show up in the stylesheets. | |
| 857 if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.conta
ins(state.styledElement()->idForStyleResolution().impl())) | |
| 858 return 0; | |
| 859 if (parentElementPreventsSharing(state.element()->parentElement())) | |
| 860 return 0; | |
| 861 if (state.styledElement()->hasScopedHTMLStyleChild()) | |
| 862 return 0; | |
| 863 if (state.element() == state.document()->cssTarget()) | |
| 864 return 0; | |
| 865 if (elementHasDirectionAuto(state.element())) | |
| 866 return 0; | |
| 867 if (state.element()->hasActiveAnimations()) | |
| 868 return 0; | |
| 869 | |
| 870 // Cache whether state.element is affected by any known class selectors. | |
| 871 // FIXME: This shouldn't be a member variable. The style sharing code could
be factored out of StyleResolver. | |
| 872 state.setElementAffectedByClassRules(state.element() && state.element()->has
Class() && classNamesAffectedByRules(state.element()->classNames())); | |
| 873 | |
| 874 // Check previous siblings and their cousins. | |
| 875 unsigned count = 0; | |
| 876 unsigned visitedNodeCount = 0; | |
| 877 StyledElement* shareElement = 0; | |
| 878 Node* cousinList = state.styledElement()->previousSibling(); | |
| 879 while (cousinList) { | |
| 880 shareElement = findSiblingForStyleSharing(cousinList, count); | |
| 881 if (shareElement) | |
| 882 break; | |
| 883 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo
unt); | |
| 884 } | |
| 885 | |
| 886 // If we have exhausted all our budget or our cousins. | |
| 887 if (!shareElement) | |
| 888 return 0; | |
| 889 | |
| 890 // Can't share if sibling rules apply. This is checked at the end as it shou
ld rarely fail. | |
| 891 if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling())) | |
| 892 return 0; | |
| 893 // Can't share if attribute rules apply. | |
| 894 if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute())) | |
| 895 return 0; | |
| 896 // Can't share if @host @-rules apply. | |
| 897 if (styleSharingCandidateMatchesHostRules()) | |
| 898 return 0; | |
| 899 // Tracking child index requires unique style for each node. This may get se
t by the sibling rule match above. | |
| 900 if (parentElementPreventsSharing(state.element()->parentElement())) | |
| 901 return 0; | |
| 902 return shareElement->renderStyle(); | |
| 903 } | |
| 904 | |
| 905 static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderSt
yle* style) | |
| 906 { | |
| 907 if (paginationMode == Pagination::Unpaginated) | |
| 908 return; | |
| 909 | |
| 910 switch (paginationMode) { | |
| 911 case Pagination::LeftToRightPaginated: | |
| 912 style->setColumnAxis(HorizontalColumnAxis); | |
| 913 if (style->isHorizontalWritingMode()) | |
| 914 style->setColumnProgression(style->isLeftToRightDirection() ? Normal
ColumnProgression : ReverseColumnProgression); | |
| 915 else | |
| 916 style->setColumnProgression(style->isFlippedBlocksWritingMode() ? Re
verseColumnProgression : NormalColumnProgression); | |
| 917 break; | |
| 918 case Pagination::RightToLeftPaginated: | |
| 919 style->setColumnAxis(HorizontalColumnAxis); | |
| 920 if (style->isHorizontalWritingMode()) | |
| 921 style->setColumnProgression(style->isLeftToRightDirection() ? Revers
eColumnProgression : NormalColumnProgression); | |
| 922 else | |
| 923 style->setColumnProgression(style->isFlippedBlocksWritingMode() ? No
rmalColumnProgression : ReverseColumnProgression); | |
| 924 break; | |
| 925 case Pagination::TopToBottomPaginated: | |
| 926 style->setColumnAxis(VerticalColumnAxis); | |
| 927 if (style->isHorizontalWritingMode()) | |
| 928 style->setColumnProgression(style->isFlippedBlocksWritingMode() ? Re
verseColumnProgression : NormalColumnProgression); | |
| 929 else | |
| 930 style->setColumnProgression(style->isLeftToRightDirection() ? Normal
ColumnProgression : ReverseColumnProgression); | |
| 931 break; | |
| 932 case Pagination::BottomToTopPaginated: | |
| 933 style->setColumnAxis(VerticalColumnAxis); | |
| 934 if (style->isHorizontalWritingMode()) | |
| 935 style->setColumnProgression(style->isFlippedBlocksWritingMode() ? No
rmalColumnProgression : ReverseColumnProgression); | |
| 936 else | |
| 937 style->setColumnProgression(style->isLeftToRightDirection() ? Revers
eColumnProgression : NormalColumnProgression); | |
| 938 break; | |
| 939 case Pagination::Unpaginated: | |
| 940 ASSERT_NOT_REACHED(); | |
| 941 break; | |
| 942 } | |
| 943 } | |
| 944 | |
| 945 static void getFontAndGlyphOrientation(const RenderStyle* style, FontOrientation
& fontOrientation, NonCJKGlyphOrientation& glyphOrientation) | |
| 946 { | |
| 947 if (style->isHorizontalWritingMode()) { | |
| 948 fontOrientation = Horizontal; | |
| 949 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 950 return; | |
| 951 } | |
| 952 | |
| 953 switch (style->textOrientation()) { | |
| 954 case TextOrientationVerticalRight: | |
| 955 fontOrientation = Vertical; | |
| 956 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 957 return; | |
| 958 case TextOrientationUpright: | |
| 959 fontOrientation = Vertical; | |
| 960 glyphOrientation = NonCJKGlyphOrientationUpright; | |
| 961 return; | |
| 962 case TextOrientationSideways: | |
| 963 if (style->writingMode() == LeftToRightWritingMode) { | |
| 964 // FIXME: This should map to sideways-left, which is not supported y
et. | |
| 965 fontOrientation = Vertical; | |
| 966 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 967 return; | |
| 968 } | |
| 969 fontOrientation = Horizontal; | |
| 970 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 971 return; | |
| 972 case TextOrientationSidewaysRight: | |
| 973 fontOrientation = Horizontal; | |
| 974 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 975 return; | |
| 976 default: | |
| 977 ASSERT_NOT_REACHED(); | |
| 978 fontOrientation = Horizontal; | |
| 979 glyphOrientation = NonCJKGlyphOrientationVerticalRight; | |
| 980 return; | |
| 981 } | |
| 982 } | |
| 983 | |
| 984 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document* document, CSSF
ontSelector* fontSelector) | |
| 985 { | |
| 986 Frame* frame = document->frame(); | |
| 987 | |
| 988 // HTML5 states that seamless iframes should replace default CSS values | |
| 989 // with values inherited from the containing iframe element. However, | |
| 990 // some values (such as the case of designMode = "on") still need to | |
| 991 // be set by this "document style". | |
| 992 RefPtr<RenderStyle> documentStyle = RenderStyle::create(); | |
| 993 bool seamlessWithParent = document->shouldDisplaySeamlesslyWithParent(); | |
| 994 if (seamlessWithParent) { | |
| 995 RenderStyle* iframeStyle = document->seamlessParentIFrame()->renderStyle
(); | |
| 996 if (iframeStyle) | |
| 997 documentStyle->inheritFrom(iframeStyle); | |
| 998 } | |
| 999 | |
| 1000 // FIXME: It's not clear which values below we want to override in the seaml
ess case! | |
| 1001 documentStyle->setDisplay(BLOCK); | |
| 1002 if (!seamlessWithParent) { | |
| 1003 documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder
: LogicalOrder); | |
| 1004 documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomF
actor() : 1); | |
| 1005 documentStyle->setLocale(document->contentLanguage()); | |
| 1006 } | |
| 1007 // This overrides any -webkit-user-modify inherited from the parent iframe. | |
| 1008 documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ON
LY); | |
| 1009 | |
| 1010 Element* docElement = document->documentElement(); | |
| 1011 RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0; | |
| 1012 if (docElementRenderer) { | |
| 1013 // Use the direction and writing-mode of the body to set the | |
| 1014 // viewport's direction and writing-mode unless the property is set on t
he document element. | |
| 1015 // If there is no body, then use the document element. | |
| 1016 RenderObject* bodyRenderer = document->body() ? document->body()->render
er() : 0; | |
| 1017 if (bodyRenderer && !document->writingModeSetOnDocumentElement()) | |
| 1018 documentStyle->setWritingMode(bodyRenderer->style()->writingMode()); | |
| 1019 else | |
| 1020 documentStyle->setWritingMode(docElementRenderer->style()->writingMo
de()); | |
| 1021 if (bodyRenderer && !document->directionSetOnDocumentElement()) | |
| 1022 documentStyle->setDirection(bodyRenderer->style()->direction()); | |
| 1023 else | |
| 1024 documentStyle->setDirection(docElementRenderer->style()->direction()
); | |
| 1025 } | |
| 1026 | |
| 1027 if (frame) { | |
| 1028 if (FrameView* frameView = frame->view()) { | |
| 1029 const Pagination& pagination = frameView->pagination(); | |
| 1030 if (pagination.mode != Pagination::Unpaginated) { | |
| 1031 setStylesForPaginationMode(pagination.mode, documentStyle.get())
; | |
| 1032 documentStyle->setColumnGap(pagination.gap); | |
| 1033 if (RenderView* view = document->renderView()) { | |
| 1034 if (view->hasColumns()) | |
| 1035 view->updateColumnInfoFromStyle(documentStyle.get()); | |
| 1036 } | |
| 1037 } | |
| 1038 } | |
| 1039 } | |
| 1040 | |
| 1041 // Seamless iframes want to inherit their font from their parent iframe, so
early return before setting the font. | |
| 1042 if (seamlessWithParent) | |
| 1043 return documentStyle.release(); | |
| 1044 | |
| 1045 FontDescription fontDescription; | |
| 1046 fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->
locale())); | |
| 1047 if (Settings* settings = document->settings()) { | |
| 1048 fontDescription.setUsePrinterFont(document->printing()); | |
| 1049 fontDescription.setRenderingMode(settings->fontRenderingMode()); | |
| 1050 const AtomicString& standardFont = settings->standardFontFamily(fontDesc
ription.script()); | |
| 1051 if (!standardFont.isEmpty()) { | |
| 1052 fontDescription.setGenericFamily(FontDescription::StandardFamily); | |
| 1053 fontDescription.firstFamily().setFamily(standardFont); | |
| 1054 fontDescription.firstFamily().appendFamily(0); | |
| 1055 } | |
| 1056 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); | |
| 1057 int size = StyleResolver::fontSizeForKeyword(document, CSSValueMedium, f
alse); | |
| 1058 fontDescription.setSpecifiedSize(size); | |
| 1059 bool useSVGZoomRules = document->isSVGDocument(); | |
| 1060 fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecif
iedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, u
seSVGZoomRules)); | |
| 1061 } else | |
| 1062 fontDescription.setUsePrinterFont(document->printing()); | |
| 1063 | |
| 1064 FontOrientation fontOrientation; | |
| 1065 NonCJKGlyphOrientation glyphOrientation; | |
| 1066 getFontAndGlyphOrientation(documentStyle.get(), fontOrientation, glyphOrient
ation); | |
| 1067 fontDescription.setOrientation(fontOrientation); | |
| 1068 fontDescription.setNonCJKGlyphOrientation(glyphOrientation); | |
| 1069 | |
| 1070 documentStyle->setFontDescription(fontDescription); | |
| 1071 documentStyle->font().update(fontSelector); | |
| 1072 | |
| 1073 return documentStyle.release(); | |
| 1074 } | |
| 1075 | |
| 1076 static inline bool isAtShadowBoundary(const Element* element) | |
| 1077 { | |
| 1078 if (!element) | |
| 1079 return false; | |
| 1080 ContainerNode* parentNode = element->parentNode(); | |
| 1081 return parentNode && parentNode->isShadowRoot(); | |
| 1082 } | |
| 1083 | |
| 1084 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS
tyle* defaultParent, | |
| 1085 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior,
RenderRegion* regionForStyling) | |
| 1086 { | |
| 1087 // Once an element has a renderer, we don't try to destroy it, since otherwi
se the renderer | |
| 1088 // will vanish if a style recalc happens during loading. | |
| 1089 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles
heetsLoaded() && !element->renderer()) { | |
| 1090 if (!s_styleNotYetAvailable) { | |
| 1091 s_styleNotYetAvailable = RenderStyle::create().leakRef(); | |
| 1092 s_styleNotYetAvailable->setDisplay(NONE); | |
| 1093 s_styleNotYetAvailable->font().update(m_fontSelector); | |
| 1094 } | |
| 1095 element->document()->setHasNodesWithPlaceholderStyle(); | |
| 1096 return s_styleNotYetAvailable; | |
| 1097 } | |
| 1098 | |
| 1099 StyleResolverState& state = m_state; | |
| 1100 initElement(element); | |
| 1101 state.initForStyleResolve(document(), element, defaultParent, regionForStyli
ng); | |
| 1102 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi
nt()) { | |
| 1103 RenderStyle* sharedStyle = locateSharedStyle(); | |
| 1104 if (sharedStyle) | |
| 1105 { | |
| 1106 state.clear(); | |
| 1107 return sharedStyle; | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 1111 if (state.parentStyle()) { | |
| 1112 state.setStyle(RenderStyle::create()); | |
| 1113 state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(eleme
nt) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary); | |
| 1114 } else { | |
| 1115 state.setStyle(defaultStyleForElement()); | |
| 1116 state.setParentStyle(RenderStyle::clone(state.style())); | |
| 1117 } | |
| 1118 // contenteditable attribute (implemented by -webkit-user-modify) should | |
| 1119 // be propagated from shadow host to distributed node. | |
| 1120 if (state.distributedToInsertionPoint()) { | |
| 1121 if (Element* parent = element->parentElement()) { | |
| 1122 if (RenderStyle* styleOfShadowHost = parent->renderStyle()) | |
| 1123 state.style()->setUserModify(styleOfShadowHost->userModify()); | |
| 1124 } | |
| 1125 } | |
| 1126 | |
| 1127 if (element->isLink()) { | |
| 1128 state.style()->setIsLink(true); | |
| 1129 EInsideLink linkState = state.elementLinkState(); | |
| 1130 if (linkState != NotInsideLink) { | |
| 1131 bool forceVisited = InspectorInstrumentation::forcePseudoState(eleme
nt, CSSSelector::PseudoVisited); | |
| 1132 if (forceVisited) | |
| 1133 linkState = InsideVisitedLink; | |
| 1134 } | |
| 1135 state.style()->setInsideLink(linkState); | |
| 1136 } | |
| 1137 | |
| 1138 bool needsCollection = false; | |
| 1139 CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsColl
ection); | |
| 1140 if (needsCollection) { | |
| 1141 m_ruleSets.collectFeatures(document()->isViewSource(), m_scopeResolver.g
et()); | |
| 1142 m_inspectorCSSOMWrappers.reset(); | |
| 1143 } | |
| 1144 | |
| 1145 ElementRuleCollector collector(this, state); | |
| 1146 collector.setRegionForStyling(regionForStyling); | |
| 1147 | |
| 1148 if (matchingBehavior == MatchOnlyUserAgentRules) | |
| 1149 matchUARules(collector); | |
| 1150 else | |
| 1151 matchAllRules(collector, m_matchAuthorAndUserStyles, matchingBehavior != M
atchAllRulesExcludingSMIL); | |
| 1152 | |
| 1153 applyMatchedProperties(collector.matchedResult(), element); | |
| 1154 | |
| 1155 // Clean up our style object's display and text decorations (among other fix
ups). | |
| 1156 adjustRenderStyle(state.style(), state.parentStyle(), element); | |
| 1157 | |
| 1158 state.clear(); // Clear out for the next resolve. | |
| 1159 | |
| 1160 document()->didAccessStyleResolver(); | |
| 1161 | |
| 1162 // Now return the style. | |
| 1163 return state.takeStyle(); | |
| 1164 } | |
| 1165 | |
| 1166 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* eleme
ntStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue) | |
| 1167 { | |
| 1168 MatchResult result; | |
| 1169 if (keyframe->properties()) | |
| 1170 result.addMatchedProperties(keyframe->properties()); | |
| 1171 | |
| 1172 ASSERT(!m_state.style()); | |
| 1173 | |
| 1174 StyleResolverState& state = m_state; | |
| 1175 | |
| 1176 // Create the style | |
| 1177 state.setStyle(RenderStyle::clone(elementStyle)); | |
| 1178 state.setLineHeightValue(0); | |
| 1179 | |
| 1180 // We don't need to bother with !important. Since there is only ever one | |
| 1181 // decl, there's nothing to override. So just add the first properties. | |
| 1182 bool inheritedOnly = false; | |
| 1183 if (keyframe->properties()) | |
| 1184 applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.
matchedProperties.size() - 1, inheritedOnly); | |
| 1185 | |
| 1186 // If our font got dirtied, go ahead and update it now. | |
| 1187 updateFont(); | |
| 1188 | |
| 1189 // Line-height is set when we are sure we decided on the font-size | |
| 1190 if (state.lineHeightValue()) | |
| 1191 applyProperty(CSSPropertyLineHeight, state.lineHeightValue()); | |
| 1192 | |
| 1193 // Now do rest of the properties. | |
| 1194 if (keyframe->properties()) | |
| 1195 applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.m
atchedProperties.size() - 1, inheritedOnly); | |
| 1196 | |
| 1197 // If our font got dirtied by one of the non-essential font props, | |
| 1198 // go ahead and update it a second time. | |
| 1199 updateFont(); | |
| 1200 | |
| 1201 // Start loading resources referenced by this style. | |
| 1202 loadPendingResources(); | |
| 1203 | |
| 1204 // Add all the animating properties to the keyframe. | |
| 1205 if (const StylePropertySet* styleDeclaration = keyframe->properties()) { | |
| 1206 unsigned propertyCount = styleDeclaration->propertyCount(); | |
| 1207 for (unsigned i = 0; i < propertyCount; ++i) { | |
| 1208 CSSPropertyID property = styleDeclaration->propertyAt(i).id(); | |
| 1209 // Timing-function within keyframes is special, because it is not an
imated; it just | |
| 1210 // describes the timing function between this keyframe and the next. | |
| 1211 if (property != CSSPropertyWebkitAnimationTimingFunction) | |
| 1212 keyframeValue.addProperty(property); | |
| 1213 } | |
| 1214 } | |
| 1215 | |
| 1216 document()->didAccessStyleResolver(); | |
| 1217 | |
| 1218 return state.takeStyle(); | |
| 1219 } | |
| 1220 | |
| 1221 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* el
ementStyle, KeyframeList& list) | |
| 1222 { | |
| 1223 list.clear(); | |
| 1224 | |
| 1225 // Get the keyframesRule for this name | |
| 1226 if (!e || list.animationName().isEmpty()) | |
| 1227 return; | |
| 1228 | |
| 1229 m_keyframesRuleMap.checkConsistency(); | |
| 1230 | |
| 1231 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName()
.impl()); | |
| 1232 if (it == m_keyframesRuleMap.end()) | |
| 1233 return; | |
| 1234 | |
| 1235 const StyleRuleKeyframes* keyframesRule = it->value.get(); | |
| 1236 | |
| 1237 // Construct and populate the style for each keyframe | |
| 1238 const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes()
; | |
| 1239 for (unsigned i = 0; i < keyframes.size(); ++i) { | |
| 1240 // Apply the declaration to the style. This is a simplified version of t
he logic in styleForElement | |
| 1241 initElement(e); | |
| 1242 m_state.initForStyleResolve(document(), e); | |
| 1243 | |
| 1244 const StyleKeyframe* keyframe = keyframes[i].get(); | |
| 1245 | |
| 1246 KeyframeValue keyframeValue(0, 0); | |
| 1247 keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframe
Value)); | |
| 1248 | |
| 1249 // Add this keyframe style to all the indicated key times | |
| 1250 Vector<float> keys; | |
| 1251 keyframe->getKeys(keys); | |
| 1252 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) { | |
| 1253 keyframeValue.setKey(keys[keyIndex]); | |
| 1254 list.insert(keyframeValue); | |
| 1255 } | |
| 1256 } | |
| 1257 | |
| 1258 // If the 0% keyframe is missing, create it (but only if there is at least o
ne other keyframe) | |
| 1259 int initialListSize = list.size(); | |
| 1260 if (initialListSize > 0 && list[0].key()) { | |
| 1261 static StyleKeyframe* zeroPercentKeyframe; | |
| 1262 if (!zeroPercentKeyframe) { | |
| 1263 zeroPercentKeyframe = StyleKeyframe::create().leakRef(); | |
| 1264 zeroPercentKeyframe->setKeyText("0%"); | |
| 1265 } | |
| 1266 KeyframeValue keyframeValue(0, 0); | |
| 1267 keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyfram
e, keyframeValue)); | |
| 1268 list.insert(keyframeValue); | |
| 1269 } | |
| 1270 | |
| 1271 // If the 100% keyframe is missing, create it (but only if there is at least
one other keyframe) | |
| 1272 if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) { | |
| 1273 static StyleKeyframe* hundredPercentKeyframe; | |
| 1274 if (!hundredPercentKeyframe) { | |
| 1275 hundredPercentKeyframe = StyleKeyframe::create().leakRef(); | |
| 1276 hundredPercentKeyframe->setKeyText("100%"); | |
| 1277 } | |
| 1278 KeyframeValue keyframeValue(1, 0); | |
| 1279 keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyf
rame, keyframeValue)); | |
| 1280 list.insert(keyframeValue); | |
| 1281 } | |
| 1282 } | |
| 1283 | |
| 1284 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P
seudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle) | |
| 1285 { | |
| 1286 ASSERT(parentStyle); | |
| 1287 if (!e) | |
| 1288 return 0; | |
| 1289 | |
| 1290 StyleResolverState& state = m_state; | |
| 1291 | |
| 1292 initElement(e); | |
| 1293 | |
| 1294 state.initForStyleResolve(document(), e, parentStyle); | |
| 1295 | |
| 1296 if (m_state.parentStyle()) { | |
| 1297 state.setStyle(RenderStyle::create()); | |
| 1298 state.style()->inheritFrom(m_state.parentStyle()); | |
| 1299 } else { | |
| 1300 state.setStyle(defaultStyleForElement()); | |
| 1301 state.setParentStyle(RenderStyle::clone(state.style())); | |
| 1302 } | |
| 1303 | |
| 1304 // Since we don't use pseudo-elements in any of our quirk/print user agent r
ules, don't waste time walking | |
| 1305 // those rules. | |
| 1306 | |
| 1307 // Check UA, user and author rules. | |
| 1308 ElementRuleCollector collector(this, state); | |
| 1309 collector.setPseudoStyleRequest(pseudoStyleRequest); | |
| 1310 matchUARules(collector); | |
| 1311 | |
| 1312 if (m_matchAuthorAndUserStyles) { | |
| 1313 matchUserRules(collector, false); | |
| 1314 matchAuthorRules(collector, false); | |
| 1315 } | |
| 1316 | |
| 1317 if (collector.matchedResult().matchedProperties.isEmpty()) | |
| 1318 return 0; | |
| 1319 | |
| 1320 state.style()->setStyleType(pseudoStyleRequest.pseudoId); | |
| 1321 | |
| 1322 applyMatchedProperties(collector.matchedResult(), e); | |
| 1323 | |
| 1324 // Clean up our style object's display and text decorations (among other fix
ups). | |
| 1325 adjustRenderStyle(state.style(), m_state.parentStyle(), 0); | |
| 1326 | |
| 1327 // Start loading resources referenced by this style. | |
| 1328 loadPendingResources(); | |
| 1329 | |
| 1330 document()->didAccessStyleResolver(); | |
| 1331 | |
| 1332 // Now return the style. | |
| 1333 return state.takeStyle(); | |
| 1334 } | |
| 1335 | |
| 1336 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) | |
| 1337 { | |
| 1338 m_state.initForStyleResolve(document(), document()->documentElement()); // m
_rootElementStyle will be set to the document style. | |
| 1339 | |
| 1340 m_state.setStyle(RenderStyle::create()); | |
| 1341 m_state.style()->inheritFrom(m_state.rootElementStyle()); | |
| 1342 | |
| 1343 PageRuleCollector collector(m_state, pageIndex); | |
| 1344 | |
| 1345 collector.matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle); | |
| 1346 collector.matchPageRules(m_ruleSets.userStyle()); | |
| 1347 collector.matchPageRules(m_ruleSets.authorStyle()); | |
| 1348 | |
| 1349 m_state.setLineHeightValue(0); | |
| 1350 bool inheritedOnly = false; | |
| 1351 | |
| 1352 MatchResult& result = collector.matchedResult(); | |
| 1353 applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matched
Properties.size() - 1, inheritedOnly); | |
| 1354 applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matc
hedProperties.size() - 1, inheritedOnly); | |
| 1355 | |
| 1356 // If our font got dirtied, go ahead and update it now. | |
| 1357 updateFont(); | |
| 1358 | |
| 1359 // Line-height is set when we are sure we decided on the font-size. | |
| 1360 if (m_state.lineHeightValue()) | |
| 1361 applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue()); | |
| 1362 | |
| 1363 applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.match
edProperties.size() - 1, inheritedOnly); | |
| 1364 | |
| 1365 // Start loading resources referenced by this style. | |
| 1366 loadPendingResources(); | |
| 1367 | |
| 1368 document()->didAccessStyleResolver(); | |
| 1369 | |
| 1370 // Now return the style. | |
| 1371 return m_state.takeStyle(); | |
| 1372 } | |
| 1373 | |
| 1374 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement() | |
| 1375 { | |
| 1376 m_state.setStyle(RenderStyle::create()); | |
| 1377 // Make sure our fonts are initialized if we don't inherit them from our par
ent style. | |
| 1378 if (Settings* settings = documentSettings()) { | |
| 1379 initializeFontStyle(settings); | |
| 1380 m_state.style()->font().update(fontSelector()); | |
| 1381 } else | |
| 1382 m_state.style()->font().update(0); | |
| 1383 | |
| 1384 return m_state.takeStyle(); | |
| 1385 } | |
| 1386 | |
| 1387 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode) | |
| 1388 { | |
| 1389 ASSERT(textNode); | |
| 1390 | |
| 1391 NodeRenderingContext context(textNode); | |
| 1392 Node* parentNode = context.parentNodeForRenderingAndStyle(); | |
| 1393 return context.resetStyleInheritance() || !parentNode || !parentNode->render
Style() ? | |
| 1394 defaultStyleForElement() : parentNode->renderStyle(); | |
| 1395 } | |
| 1396 | |
| 1397 static void addIntrinsicMargins(RenderStyle* style) | |
| 1398 { | |
| 1399 // Intrinsic margin value. | |
| 1400 const int intrinsicMargin = 2 * style->effectiveZoom(); | |
| 1401 | |
| 1402 // FIXME: Using width/height alone and not also dealing with min-width/max-w
idth is flawed. | |
| 1403 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame. | |
| 1404 if (style->width().isIntrinsicOrAuto()) { | |
| 1405 if (style->marginLeft().quirk()) | |
| 1406 style->setMarginLeft(Length(intrinsicMargin, Fixed)); | |
| 1407 if (style->marginRight().quirk()) | |
| 1408 style->setMarginRight(Length(intrinsicMargin, Fixed)); | |
| 1409 } | |
| 1410 | |
| 1411 if (style->height().isAuto()) { | |
| 1412 if (style->marginTop().quirk()) | |
| 1413 style->setMarginTop(Length(intrinsicMargin, Fixed)); | |
| 1414 if (style->marginBottom().quirk()) | |
| 1415 style->setMarginBottom(Length(intrinsicMargin, Fixed)); | |
| 1416 } | |
| 1417 } | |
| 1418 | |
| 1419 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool s
trictParsing) | |
| 1420 { | |
| 1421 switch (display) { | |
| 1422 case BLOCK: | |
| 1423 case TABLE: | |
| 1424 case BOX: | |
| 1425 case FLEX: | |
| 1426 case GRID: | |
| 1427 case LAZY_BLOCK: | |
| 1428 return display; | |
| 1429 | |
| 1430 case LIST_ITEM: | |
| 1431 // It is a WinIE bug that floated list items lose their bullets, so we'l
l emulate the quirk, but only in quirks mode. | |
| 1432 if (!strictParsing && isFloating) | |
| 1433 return BLOCK; | |
| 1434 return display; | |
| 1435 case INLINE_TABLE: | |
| 1436 return TABLE; | |
| 1437 case INLINE_BOX: | |
| 1438 return BOX; | |
| 1439 case INLINE_FLEX: | |
| 1440 return FLEX; | |
| 1441 case INLINE_GRID: | |
| 1442 return GRID; | |
| 1443 | |
| 1444 case INLINE: | |
| 1445 case RUN_IN: | |
| 1446 case COMPACT: | |
| 1447 case INLINE_BLOCK: | |
| 1448 case TABLE_ROW_GROUP: | |
| 1449 case TABLE_HEADER_GROUP: | |
| 1450 case TABLE_FOOTER_GROUP: | |
| 1451 case TABLE_ROW: | |
| 1452 case TABLE_COLUMN_GROUP: | |
| 1453 case TABLE_COLUMN: | |
| 1454 case TABLE_CELL: | |
| 1455 case TABLE_CAPTION: | |
| 1456 return BLOCK; | |
| 1457 case NONE: | |
| 1458 ASSERT_NOT_REACHED(); | |
| 1459 return NONE; | |
| 1460 } | |
| 1461 ASSERT_NOT_REACHED(); | |
| 1462 return BLOCK; | |
| 1463 } | |
| 1464 | |
| 1465 // CSS requires text-decoration to be reset at each DOM element for tables, | |
| 1466 // inline blocks, inline tables, run-ins, shadow DOM crossings, floating element
s, | |
| 1467 // and absolute or relatively positioned elements. | |
| 1468 static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e) | |
| 1469 { | |
| 1470 return style->display() == TABLE || style->display() == INLINE_TABLE || styl
e->display() == RUN_IN | |
| 1471 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX ||
isAtShadowBoundary(e) | |
| 1472 || style->isFloating() || style->hasOutOfFlowPosition(); | |
| 1473 } | |
| 1474 | |
| 1475 static bool isDisplayFlexibleBox(EDisplay display) | |
| 1476 { | |
| 1477 return display == FLEX || display == INLINE_FLEX; | |
| 1478 } | |
| 1479 | |
| 1480 void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentSty
le, Element *e) | |
| 1481 { | |
| 1482 ASSERT(parentStyle); | |
| 1483 | |
| 1484 // Cache our original display. | |
| 1485 style->setOriginalDisplay(style->display()); | |
| 1486 | |
| 1487 if (style->display() != NONE) { | |
| 1488 // If we have a <td> that specifies a float property, in quirks mode we
just drop the float | |
| 1489 // property. | |
| 1490 // Sites also commonly use display:inline/block on <td>s and <table>s. I
n quirks mode we force | |
| 1491 // these tags to retain their display types. | |
| 1492 if (document()->inQuirksMode() && e) { | |
| 1493 if (e->hasTagName(tdTag)) { | |
| 1494 style->setDisplay(TABLE_CELL); | |
| 1495 style->setFloating(NoFloat); | |
| 1496 } else if (e->hasTagName(tableTag)) | |
| 1497 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE :
TABLE); | |
| 1498 } | |
| 1499 | |
| 1500 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) { | |
| 1501 if (style->whiteSpace() == KHTML_NOWRAP) { | |
| 1502 // Figure out if we are really nowrapping or if we should just | |
| 1503 // use normal instead. If the width of the cell is fixed, then | |
| 1504 // we don't actually use NOWRAP. | |
| 1505 if (style->width().isFixed()) | |
| 1506 style->setWhiteSpace(NORMAL); | |
| 1507 else | |
| 1508 style->setWhiteSpace(NOWRAP); | |
| 1509 } | |
| 1510 } | |
| 1511 | |
| 1512 // Tables never support the -webkit-* values for text-align and will res
et back to the default. | |
| 1513 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT |
| style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) | |
| 1514 style->setTextAlign(TASTART); | |
| 1515 | |
| 1516 // Frames and framesets never honor position:relative or position:absolu
te. This is necessary to | |
| 1517 // fix a crash where a site tries to position these objects. They also n
ever honor display. | |
| 1518 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { | |
| 1519 style->setPosition(StaticPosition); | |
| 1520 style->setDisplay(BLOCK); | |
| 1521 } | |
| 1522 | |
| 1523 // Ruby text does not support float or position. This might change with
evolution of the specification. | |
| 1524 if (e && e->hasTagName(rtTag)) { | |
| 1525 style->setPosition(StaticPosition); | |
| 1526 style->setFloating(NoFloat); | |
| 1527 } | |
| 1528 | |
| 1529 // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it
in html.css instead. | |
| 1530 // Table headers with a text-align of -webkit-auto will change the text-
align to center. | |
| 1531 if (e && e->hasTagName(thTag) && style->textAlign() == TASTART) | |
| 1532 style->setTextAlign(CENTER); | |
| 1533 | |
| 1534 if (e && e->hasTagName(legendTag)) | |
| 1535 style->setDisplay(BLOCK); | |
| 1536 | |
| 1537 // Absolute/fixed positioned elements, floating elements and the documen
t element need block-like outside display. | |
| 1538 if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->doc
ument()->documentElement() == e)) | |
| 1539 style->setDisplay(equivalentBlockDisplay(style->display(), style->is
Floating(), !document()->inQuirksMode())); | |
| 1540 | |
| 1541 // FIXME: Don't support this mutation for pseudo styles like first-lette
r or first-line, since it's not completely | |
| 1542 // clear how that should work. | |
| 1543 if (style->display() == INLINE && style->styleType() == NOPSEUDO && styl
e->writingMode() != parentStyle->writingMode()) | |
| 1544 style->setDisplay(INLINE_BLOCK); | |
| 1545 | |
| 1546 // After performing the display mutation, check table rows. We do not ho
nor position:relative or position:sticky on | |
| 1547 // table rows or cells. This has been established for position:relative
in CSS2.1 (and caused a crash in containingBlock() | |
| 1548 // on some sites). | |
| 1549 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE
_ROW_GROUP | |
| 1550 || style->display() == TABLE_FOOTER_GROUP || style->display() == TAB
LE_ROW) | |
| 1551 && style->hasInFlowPosition()) | |
| 1552 style->setPosition(StaticPosition); | |
| 1553 | |
| 1554 // writing-mode does not apply to table row groups, table column groups,
table rows, and table columns. | |
| 1555 // FIXME: Table cells should be allowed to be perpendicular or flipped w
ith respect to the table, though. | |
| 1556 if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN
_GROUP || style->display() == TABLE_FOOTER_GROUP | |
| 1557 || style->display() == TABLE_HEADER_GROUP || style->display() == TAB
LE_ROW || style->display() == TABLE_ROW_GROUP | |
| 1558 || style->display() == TABLE_CELL) | |
| 1559 style->setWritingMode(parentStyle->writingMode()); | |
| 1560 | |
| 1561 // FIXME: Since we don't support block-flow on flexible boxes yet, disal
low setting | |
| 1562 // of block-flow to anything other than TopToBottomWritingMode. | |
| 1563 // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support. | |
| 1564 if (style->writingMode() != TopToBottomWritingMode && (style->display()
== BOX || style->display() == INLINE_BOX)) | |
| 1565 style->setWritingMode(TopToBottomWritingMode); | |
| 1566 | |
| 1567 if (isDisplayFlexibleBox(parentStyle->display())) { | |
| 1568 style->setFloating(NoFloat); | |
| 1569 style->setDisplay(equivalentBlockDisplay(style->display(), style->is
Floating(), !document()->inQuirksMode())); | |
| 1570 } | |
| 1571 | |
| 1572 // Per the spec, position 'static' and 'relative' in the top layer compu
te to 'absolute'. | |
| 1573 if (e && e->isInTopLayer() && (style->position() == StaticPosition || st
yle->position() == RelativePosition)) { | |
| 1574 style->setPosition(AbsolutePosition); | |
| 1575 style->setDisplay(BLOCK); | |
| 1576 } | |
| 1577 } | |
| 1578 | |
| 1579 // Make sure our z-index value is only applied if the object is positioned. | |
| 1580 if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle
->display())) | |
| 1581 style->setHasAutoZIndex(); | |
| 1582 | |
| 1583 // Auto z-index becomes 0 for the root element and transparent objects. This
prevents | |
| 1584 // cases where objects that should be blended as a single unit end up with a
non-transparent | |
| 1585 // object wedged in between them. Auto z-index also becomes 0 for objects th
at specify transforms/masks/reflections. | |
| 1586 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) | |
| 1587 || style->opacity() < 1.0f | |
| 1588 || style->hasTransformRelatedProperty() | |
| 1589 || style->hasMask() | |
| 1590 || style->clipPath() | |
| 1591 || style->boxReflect() | |
| 1592 || style->hasFilter() | |
| 1593 || style->hasBlendMode() | |
| 1594 || style->position() == StickyPosition | |
| 1595 || (style->position() == FixedPosition && e && e->document()->page() &&
e->document()->page()->settings()->fixedPositionCreatesStackingContext()) | |
| 1596 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) | |
| 1597 // Touch overflow scrolling creates a stacking context. | |
| 1598 || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) &&
style->useTouchOverflowScrolling()) | |
| 1599 #endif | |
| 1600 || (e && e->isInTopLayer()) | |
| 1601 )) | |
| 1602 style->setZIndex(0); | |
| 1603 | |
| 1604 // Textarea considers overflow visible as auto. | |
| 1605 if (e && e->hasTagName(textareaTag)) { | |
| 1606 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->over
flowX()); | |
| 1607 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->over
flowY()); | |
| 1608 } | |
| 1609 | |
| 1610 if (doesNotInheritTextDecoration(style, e)) | |
| 1611 style->setTextDecorationsInEffect(style->textDecoration()); | |
| 1612 else | |
| 1613 style->addToTextDecorationsInEffect(style->textDecoration()); | |
| 1614 | |
| 1615 // If either overflow value is not visible, change to auto. | |
| 1616 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) | |
| 1617 style->setOverflowY(OMARQUEE); | |
| 1618 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) | |
| 1619 style->setOverflowX(OMARQUEE); | |
| 1620 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) { | |
| 1621 // FIXME: Once we implement pagination controls, overflow-x should defau
lt to hidden | |
| 1622 // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, w
e'll let it | |
| 1623 // default to auto so we can at least scroll through the pages. | |
| 1624 style->setOverflowX(OAUTO); | |
| 1625 } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) | |
| 1626 style->setOverflowY(OAUTO); | |
| 1627 | |
| 1628 // Call setStylesForPaginationMode() if a pagination mode is set for any non
-root elements. If these | |
| 1629 // styles are specified on a root element, then they will be incorporated in | |
| 1630 // StyleResolver::styleForDocument(). | |
| 1631 if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e
&& (e->hasTagName(htmlTag) || e->hasTagName(bodyTag)))) | |
| 1632 setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style),
style); | |
| 1633 | |
| 1634 // Table rows, sections and the table itself will support overflow:hidden an
d will ignore scroll/auto. | |
| 1635 // FIXME: Eventually table sections will support auto and scroll. | |
| 1636 if (style->display() == TABLE || style->display() == INLINE_TABLE | |
| 1637 || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW)
{ | |
| 1638 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) | |
| 1639 style->setOverflowX(OVISIBLE); | |
| 1640 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) | |
| 1641 style->setOverflowY(OVISIBLE); | |
| 1642 } | |
| 1643 | |
| 1644 // Menulists should have visible overflow | |
| 1645 if (style->appearance() == MenulistPart) { | |
| 1646 style->setOverflowX(OVISIBLE); | |
| 1647 style->setOverflowY(OVISIBLE); | |
| 1648 } | |
| 1649 | |
| 1650 // Cull out any useless layers and also repeat patterns into additional laye
rs. | |
| 1651 style->adjustBackgroundLayers(); | |
| 1652 style->adjustMaskLayers(); | |
| 1653 | |
| 1654 // Do the same for animations and transitions. | |
| 1655 style->adjustAnimations(); | |
| 1656 style->adjustTransitions(); | |
| 1657 | |
| 1658 // Important: Intrinsic margins get added to controls before the theme has a
djusted the style, since the theme will | |
| 1659 // alter fonts and heights/widths. | |
| 1660 if (e && e->isFormControlElement() && style->fontSize() >= 11) { | |
| 1661 // Don't apply intrinsic margins to image buttons. The designer knows ho
w big the images are, | |
| 1662 // so we have to treat all image buttons as though they were explicitly
sized. | |
| 1663 if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isIm
ageButton()) | |
| 1664 addIntrinsicMargins(style); | |
| 1665 } | |
| 1666 | |
| 1667 // Let the theme also have a crack at adjusting the style. | |
| 1668 if (style->hasAppearance()) | |
| 1669 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_state.hasUAAp
pearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundCo
lor()); | |
| 1670 | |
| 1671 // If we have first-letter pseudo style, do not share this style. | |
| 1672 if (style->hasPseudoStyle(FIRST_LETTER)) | |
| 1673 style->setUnique(); | |
| 1674 | |
| 1675 // FIXME: when dropping the -webkit prefix on transform-style, we should als
o have opacity < 1 cause flattening. | |
| 1676 if (style->preserves3D() && (style->overflowX() != OVISIBLE | |
| 1677 || style->overflowY() != OVISIBLE | |
| 1678 || style->hasFilter())) | |
| 1679 style->setTransformStyle3D(TransformStyle3DFlat); | |
| 1680 | |
| 1681 // Seamless iframes behave like blocks. Map their display to inline-block wh
en marked inline. | |
| 1682 if (e && e->hasTagName(iframeTag) && style->display() == INLINE && static_ca
st<HTMLIFrameElement*>(e)->shouldDisplaySeamlessly()) | |
| 1683 style->setDisplay(INLINE_BLOCK); | |
| 1684 | |
| 1685 adjustGridItemPosition(style); | |
| 1686 | |
| 1687 #if ENABLE(SVG) | |
| 1688 if (e && e->isSVGElement()) { | |
| 1689 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty | |
| 1690 if (style->overflowY() == OSCROLL) | |
| 1691 style->setOverflowY(OHIDDEN); | |
| 1692 else if (style->overflowY() == OAUTO) | |
| 1693 style->setOverflowY(OVISIBLE); | |
| 1694 | |
| 1695 if (style->overflowX() == OSCROLL) | |
| 1696 style->setOverflowX(OHIDDEN); | |
| 1697 else if (style->overflowX() == OAUTO) | |
| 1698 style->setOverflowX(OVISIBLE); | |
| 1699 | |
| 1700 // Only the root <svg> element in an SVG document fragment tree honors c
ss position | |
| 1701 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNo
de()->isSVGElement())) | |
| 1702 style->setPosition(RenderStyle::initialPosition()); | |
| 1703 | |
| 1704 // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignOb
ject content should | |
| 1705 // not be scaled again. | |
| 1706 if (e->hasTagName(SVGNames::foreignObjectTag)) | |
| 1707 style->setEffectiveZoom(RenderStyle::initialZoom()); | |
| 1708 } | |
| 1709 #endif | |
| 1710 } | |
| 1711 | |
| 1712 void StyleResolver::adjustGridItemPosition(RenderStyle* style) const | |
| 1713 { | |
| 1714 // If opposing grid-placement properties both specify a grid span, they both
compute to ‘auto’. | |
| 1715 if (style->gridStart().isSpan() && style->gridEnd().isSpan()) { | |
| 1716 style->setGridStart(GridPosition()); | |
| 1717 style->setGridEnd(GridPosition()); | |
| 1718 } | |
| 1719 | |
| 1720 if (style->gridBefore().isSpan() && style->gridAfter().isSpan()) { | |
| 1721 style->setGridBefore(GridPosition()); | |
| 1722 style->setGridAfter(GridPosition()); | |
| 1723 } | |
| 1724 } | |
| 1725 | |
| 1726 bool StyleResolver::checkRegionStyle(Element* regionElement) | |
| 1727 { | |
| 1728 // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style she
ets for the moment, | |
| 1729 // so all region rules are global by default. Verify whether that can stand
or needs changing. | |
| 1730 | |
| 1731 unsigned rulesSize = m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.
size(); | |
| 1732 for (unsigned i = 0; i < rulesSize; ++i) { | |
| 1733 ASSERT(m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.at(i).rule
Set.get()); | |
| 1734 if (checkRegionSelector(m_ruleSets.authorStyle()->m_regionSelectorsAndRu
leSets.at(i).selector, regionElement)) | |
| 1735 return true; | |
| 1736 } | |
| 1737 | |
| 1738 if (m_ruleSets.userStyle()) { | |
| 1739 rulesSize = m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.size(); | |
| 1740 for (unsigned i = 0; i < rulesSize; ++i) { | |
| 1741 ASSERT(m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.at(i).ru
leSet.get()); | |
| 1742 if (checkRegionSelector(m_ruleSets.userStyle()->m_regionSelectorsAnd
RuleSets.at(i).selector, regionElement)) | |
| 1743 return true; | |
| 1744 } | |
| 1745 } | |
| 1746 | |
| 1747 return false; | |
| 1748 } | |
| 1749 | |
| 1750 static void checkForOrientationChange(RenderStyle* style) | |
| 1751 { | |
| 1752 FontOrientation fontOrientation; | |
| 1753 NonCJKGlyphOrientation glyphOrientation; | |
| 1754 getFontAndGlyphOrientation(style, fontOrientation, glyphOrientation); | |
| 1755 | |
| 1756 const FontDescription& fontDescription = style->fontDescription(); | |
| 1757 if (fontDescription.orientation() == fontOrientation && fontDescription.nonC
JKGlyphOrientation() == glyphOrientation) | |
| 1758 return; | |
| 1759 | |
| 1760 FontDescription newFontDescription(fontDescription); | |
| 1761 newFontDescription.setNonCJKGlyphOrientation(glyphOrientation); | |
| 1762 newFontDescription.setOrientation(fontOrientation); | |
| 1763 style->setFontDescription(newFontDescription); | |
| 1764 } | |
| 1765 | |
| 1766 void StyleResolver::updateFont() | |
| 1767 { | |
| 1768 if (!m_state.fontDirty()) | |
| 1769 return; | |
| 1770 | |
| 1771 RenderStyle* style = m_state.style(); | |
| 1772 checkForGenericFamilyChange(style, m_state.parentStyle()); | |
| 1773 checkForZoomChange(style, m_state.parentStyle()); | |
| 1774 checkForOrientationChange(style); | |
| 1775 style->font().update(m_fontSelector); | |
| 1776 m_state.setFontDirty(false); | |
| 1777 } | |
| 1778 | |
| 1779 PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned
rulesToInclude) | |
| 1780 { | |
| 1781 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude); | |
| 1782 } | |
| 1783 | |
| 1784 PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps
eudoId pseudoId, unsigned rulesToInclude) | |
| 1785 { | |
| 1786 if (!e || !e->document()->haveStylesheetsLoaded()) | |
| 1787 return 0; | |
| 1788 | |
| 1789 initElement(e); | |
| 1790 m_state.initForStyleResolve(document(), e, 0); | |
| 1791 | |
| 1792 ElementRuleCollector collector(this, m_state); | |
| 1793 collector.setMode(SelectorChecker::CollectingRules); | |
| 1794 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId)); | |
| 1795 | |
| 1796 if (rulesToInclude & UAAndUserCSSRules) { | |
| 1797 // First we match rules from the user agent sheet. | |
| 1798 matchUARules(collector); | |
| 1799 | |
| 1800 // Now we check user sheet rules. | |
| 1801 if (m_matchAuthorAndUserStyles) | |
| 1802 matchUserRules(collector, rulesToInclude & EmptyCSSRules); | |
| 1803 } | |
| 1804 | |
| 1805 if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) { | |
| 1806 collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules)); | |
| 1807 | |
| 1808 // Check the rules in author sheets. | |
| 1809 matchAuthorRules(collector, rulesToInclude & EmptyCSSRules); | |
| 1810 } | |
| 1811 | |
| 1812 return collector.matchedRuleList(); | |
| 1813 } | |
| 1814 | |
| 1815 // -----------------------------------------------------------------------------
-------- | |
| 1816 // this is mostly boring stuff on how to apply a certain rule to the renderstyle
... | |
| 1817 | |
| 1818 Length StyleResolver::convertToIntLength(CSSPrimitiveValue* primitiveValue, Rend
erStyle* style, RenderStyle* rootStyle, double multiplier) | |
| 1819 { | |
| 1820 return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversi
on | PercentConversion | CalculatedConversion | FractionConversion | ViewportPer
centageConversion>(style, rootStyle, multiplier) : Length(Undefined); | |
| 1821 } | |
| 1822 | |
| 1823 Length StyleResolver::convertToFloatLength(CSSPrimitiveValue* primitiveValue, Re
nderStyle* style, RenderStyle* rootStyle, double multiplier) | |
| 1824 { | |
| 1825 return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion
| PercentConversion | CalculatedConversion | FractionConversion | ViewportPerce
ntageConversion>(style, rootStyle, multiplier) : Length(Undefined); | |
| 1826 } | |
| 1827 | |
| 1828 template <StyleResolver::StyleApplicationPass pass> | |
| 1829 void StyleResolver::applyAnimatedProperties(const Element* target) | |
| 1830 { | |
| 1831 if (!target->hasActiveAnimations()) | |
| 1832 return; | |
| 1833 | |
| 1834 Vector<Animation*>* animations = target->activeAnimations(); | |
| 1835 | |
| 1836 for (size_t i = 0; i < animations->size(); ++i) { | |
| 1837 RefPtr<Animation> animation = animations->at(i); | |
| 1838 RefPtr<StylePropertySet> properties = animation->cachedStyle(); | |
| 1839 for (unsigned j = 0; j < properties->propertyCount(); ++j) { | |
| 1840 StylePropertySet::PropertyReference current = properties->propertyAt
(j); | |
| 1841 CSSPropertyID property = current.id(); | |
| 1842 switch (pass) { | |
| 1843 case VariableDefinitions: | |
| 1844 ASSERT_NOT_REACHED(); | |
| 1845 continue; | |
| 1846 case HighPriorityProperties: | |
| 1847 if (property < CSSPropertyLineHeight) | |
| 1848 applyProperty(current.id(), current.value()); | |
| 1849 else if (property == CSSPropertyLineHeight) | |
| 1850 m_state.setLineHeightValue(current.value()); | |
| 1851 continue; | |
| 1852 case LowPriorityProperties: | |
| 1853 if (property > CSSPropertyLineHeight) | |
| 1854 applyProperty(current.id(), current.value()); | |
| 1855 continue; | |
| 1856 } | |
| 1857 } | |
| 1858 } | |
| 1859 | |
| 1860 } | |
| 1861 | |
| 1862 template <StyleResolver::StyleApplicationPass pass> | |
| 1863 void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRul
e* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhi
telistType) | |
| 1864 { | |
| 1865 ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || m_state.regionF
orStyling()); | |
| 1866 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProces
sRule(document(), rule, this); | |
| 1867 | |
| 1868 unsigned propertyCount = properties->propertyCount(); | |
| 1869 for (unsigned i = 0; i < propertyCount; ++i) { | |
| 1870 StylePropertySet::PropertyReference current = properties->propertyAt(i); | |
| 1871 if (isImportant != current.isImportant()) | |
| 1872 continue; | |
| 1873 if (inheritedOnly && !current.isInherited()) { | |
| 1874 // If the property value is explicitly inherited, we need to apply f
urther non-inherited properties | |
| 1875 // as they might override the value inherited here. For this reason
we don't allow declarations with | |
| 1876 // explicitly inherited properties to be cached. | |
| 1877 ASSERT(!current.value()->isInheritedValue()); | |
| 1878 continue; | |
| 1879 } | |
| 1880 CSSPropertyID property = current.id(); | |
| 1881 | |
| 1882 if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::
isValidRegionStyleProperty(property)) | |
| 1883 continue; | |
| 1884 if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isV
alidCueStyleProperty(property)) | |
| 1885 continue; | |
| 1886 switch (pass) { | |
| 1887 case VariableDefinitions: | |
| 1888 COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_
is_before_first_property); | |
| 1889 if (property == CSSPropertyVariable) | |
| 1890 applyProperty(current.id(), current.value()); | |
| 1891 break; | |
| 1892 case HighPriorityProperties: | |
| 1893 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_fi
rst_property); | |
| 1894 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is
_end_of_first_prop_range); | |
| 1895 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_lin
e_height_is_after_zoom); | |
| 1896 if (property == CSSPropertyVariable) | |
| 1897 continue; | |
| 1898 // give special priority to font-xxx, color properties, etc | |
| 1899 if (property < CSSPropertyLineHeight) | |
| 1900 applyProperty(current.id(), current.value()); | |
| 1901 // we apply line-height later | |
| 1902 else if (property == CSSPropertyLineHeight) | |
| 1903 m_state.setLineHeightValue(current.value()); | |
| 1904 break; | |
| 1905 case LowPriorityProperties: | |
| 1906 if (property > CSSPropertyLineHeight) | |
| 1907 applyProperty(current.id(), current.value()); | |
| 1908 } | |
| 1909 } | |
| 1910 InspectorInstrumentation::didProcessRule(cookie); | |
| 1911 } | |
| 1912 | |
| 1913 template <StyleResolver::StyleApplicationPass pass> | |
| 1914 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool
isImportant, int startIndex, int endIndex, bool inheritedOnly) | |
| 1915 { | |
| 1916 if (startIndex == -1) | |
| 1917 return; | |
| 1918 | |
| 1919 StyleResolverState& state = m_state; | |
| 1920 if (state.style()->insideLink() != NotInsideLink) { | |
| 1921 for (int i = startIndex; i <= endIndex; ++i) { | |
| 1922 const MatchedProperties& matchedProperties = matchResult.matchedProp
erties[i]; | |
| 1923 unsigned linkMatchType = matchedProperties.linkMatchType; | |
| 1924 // FIXME: It would be nicer to pass these as arguments but that requ
ires changes in many places. | |
| 1925 state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker
::MatchLink); | |
| 1926 state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChe
cker::MatchVisited); | |
| 1927 | |
| 1928 applyProperties<pass>(matchedProperties.properties.get(), matchResul
t.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType
>(matchedProperties.whitelistType)); | |
| 1929 } | |
| 1930 state.setApplyPropertyToRegularStyle(true); | |
| 1931 state.setApplyPropertyToVisitedLinkStyle(false); | |
| 1932 return; | |
| 1933 } | |
| 1934 for (int i = startIndex; i <= endIndex; ++i) { | |
| 1935 const MatchedProperties& matchedProperties = matchResult.matchedProperti
es[i]; | |
| 1936 applyProperties<pass>(matchedProperties.properties.get(), matchResult.ma
tchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(ma
tchedProperties.whitelistType)); | |
| 1937 } | |
| 1938 } | |
| 1939 | |
| 1940 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* pr
operties, unsigned size) | |
| 1941 { | |
| 1942 | |
| 1943 return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size
); | |
| 1944 } | |
| 1945 | |
| 1946 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchR
anges& b) | |
| 1947 { | |
| 1948 return a.firstUARule == b.firstUARule | |
| 1949 && a.lastUARule == b.lastUARule | |
| 1950 && a.firstAuthorRule == b.firstAuthorRule | |
| 1951 && a.lastAuthorRule == b.lastAuthorRule | |
| 1952 && a.firstUserRule == b.firstUserRule | |
| 1953 && a.lastUserRule == b.lastUserRule; | |
| 1954 } | |
| 1955 | |
| 1956 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchR
anges& b) | |
| 1957 { | |
| 1958 return !(a == b); | |
| 1959 } | |
| 1960 | |
| 1961 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::
MatchedProperties& b) | |
| 1962 { | |
| 1963 return a.properties == b.properties && a.linkMatchType == b.linkMatchType; | |
| 1964 } | |
| 1965 | |
| 1966 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::
MatchedProperties& b) | |
| 1967 { | |
| 1968 return !(a == b); | |
| 1969 } | |
| 1970 | |
| 1971 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedP
ropertiesCache(unsigned hash, const MatchResult& matchResult) | |
| 1972 { | |
| 1973 ASSERT(hash); | |
| 1974 | |
| 1975 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash); | |
| 1976 if (it == m_matchedPropertiesCache.end()) | |
| 1977 return 0; | |
| 1978 MatchedPropertiesCacheItem& cacheItem = it->value; | |
| 1979 | |
| 1980 size_t size = matchResult.matchedProperties.size(); | |
| 1981 if (size != cacheItem.matchedProperties.size()) | |
| 1982 return 0; | |
| 1983 if (cacheItem.renderStyle->insideLink() != m_state.style()->insideLink()) | |
| 1984 return 0; | |
| 1985 for (size_t i = 0; i < size; ++i) { | |
| 1986 if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i]) | |
| 1987 return 0; | |
| 1988 } | |
| 1989 if (cacheItem.ranges != matchResult.ranges) | |
| 1990 return 0; | |
| 1991 return &cacheItem; | |
| 1992 } | |
| 1993 | |
| 1994 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const
RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult) | |
| 1995 { | |
| 1996 static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100; | |
| 1997 if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationC
acheAdditionsBetweenSweeps | |
| 1998 && !m_matchedPropertiesCacheSweepTimer.isActive()) { | |
| 1999 static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60; | |
| 2000 m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheS
weepTimeInSeconds); | |
| 2001 } | |
| 2002 | |
| 2003 ASSERT(hash); | |
| 2004 MatchedPropertiesCacheItem cacheItem; | |
| 2005 cacheItem.matchedProperties.append(matchResult.matchedProperties); | |
| 2006 cacheItem.ranges = matchResult.ranges; | |
| 2007 // Note that we don't cache the original RenderStyle instance. It may be fur
ther modified. | |
| 2008 // The RenderStyle in the cache is really just a holder for the substructure
s and never used as-is. | |
| 2009 cacheItem.renderStyle = RenderStyle::clone(style); | |
| 2010 cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle); | |
| 2011 m_matchedPropertiesCache.add(hash, cacheItem); | |
| 2012 } | |
| 2013 | |
| 2014 void StyleResolver::invalidateMatchedPropertiesCache() | |
| 2015 { | |
| 2016 m_matchedPropertiesCache.clear(); | |
| 2017 } | |
| 2018 | |
| 2019 static bool isCacheableInMatchedPropertiesCache(const Element* element, const Re
nderStyle* style, const RenderStyle* parentStyle) | |
| 2020 { | |
| 2021 // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to docum
ent element. We can't skip the applying by caching. | |
| 2022 if (element == element->document()->documentElement() && element->document()
->writingModeSetOnDocumentElement()) | |
| 2023 return false; | |
| 2024 if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->uniqu
e())) | |
| 2025 return false; | |
| 2026 if (style->hasAppearance()) | |
| 2027 return false; | |
| 2028 if (style->zoom() != RenderStyle::initialZoom()) | |
| 2029 return false; | |
| 2030 if (style->writingMode() != RenderStyle::initialWritingMode()) | |
| 2031 return false; | |
| 2032 // The cache assumes static knowledge about which properties are inherited. | |
| 2033 if (parentStyle->hasExplicitlyInheritedProperties()) | |
| 2034 return false; | |
| 2035 return true; | |
| 2036 } | |
| 2037 | |
| 2038 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
Element* element) | |
| 2039 { | |
| 2040 ASSERT(element); | |
| 2041 StyleResolverState& state = m_state; | |
| 2042 unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(
matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0; | |
| 2043 bool applyInheritedOnly = false; | |
| 2044 const MatchedPropertiesCacheItem* cacheItem = 0; | |
| 2045 if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matc
hResult))) { | |
| 2046 // We can build up the style by copying non-inherited properties from an
earlier style object built using the same exact | |
| 2047 // style declarations. We then only need to apply the inherited properti
es, if any, as their values can depend on the | |
| 2048 // element context. This is fast and saves memory by reusing the style d
ata structures. | |
| 2049 state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get()); | |
| 2050 if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyl
e.get()) && !isAtShadowBoundary(element)) { | |
| 2051 EInsideLink linkStatus = state.style()->insideLink(); | |
| 2052 // If the cache item parent style has identical inherited properties
to the current parent style then the | |
| 2053 // resulting style will be identical too. We copy the inherited prop
erties over from the cache and are done. | |
| 2054 state.style()->inheritFrom(cacheItem->renderStyle.get()); | |
| 2055 | |
| 2056 // Unfortunately the link status is treated like an inherited proper
ty. We need to explicitly restore it. | |
| 2057 state.style()->setInsideLink(linkStatus); | |
| 2058 return; | |
| 2059 } | |
| 2060 applyInheritedOnly = true; | |
| 2061 } | |
| 2062 | |
| 2063 // First apply all variable definitions, as they may be used during applicat
ion of later properties. | |
| 2064 applyMatchedProperties<VariableDefinitions>(matchResult, false, 0, matchResu
lt.matchedProperties.size() - 1, applyInheritedOnly); | |
| 2065 applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.r
anges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); | |
| 2066 applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.r
anges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); | |
| 2067 applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.r
anges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); | |
| 2068 | |
| 2069 // Now we have all of the matched rules in the appropriate order. Walk the r
ules and apply | |
| 2070 // high-priority properties first, i.e., those properties that other propert
ies depend on. | |
| 2071 // The order is (1) high-priority not important, (2) high-priority important
, (3) normal not important | |
| 2072 // and (4) normal important. | |
| 2073 state.setLineHeightValue(0); | |
| 2074 applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchR
esult.matchedProperties.size() - 1, applyInheritedOnly); | |
| 2075 // Animation contributions are processed here because CSS Animations are ove
rridable by user !important rules. | |
| 2076 if (RuntimeEnabledFeatures::webAnimationEnabled()) | |
| 2077 applyAnimatedProperties<HighPriorityProperties>(element); | |
| 2078 applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResul
t.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly)
; | |
| 2079 applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResul
t.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); | |
| 2080 applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResul
t.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); | |
| 2081 | |
| 2082 if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->e
ffectiveZoom()) { | |
| 2083 state.setFontDirty(true); | |
| 2084 applyInheritedOnly = false; | |
| 2085 } | |
| 2086 | |
| 2087 // If our font got dirtied, go ahead and update it now. | |
| 2088 updateFont(); | |
| 2089 | |
| 2090 // Line-height is set when we are sure we decided on the font-size. | |
| 2091 if (state.lineHeightValue()) | |
| 2092 applyProperty(CSSPropertyLineHeight, state.lineHeightValue()); | |
| 2093 | |
| 2094 // Many properties depend on the font. If it changes we just apply all prope
rties. | |
| 2095 if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()-
>fontDescription()) | |
| 2096 applyInheritedOnly = false; | |
| 2097 | |
| 2098 // Now do the normal priority UA properties. | |
| 2099 applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResul
t.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); | |
| 2100 | |
| 2101 // Cache our border and background so that we can examine them later. | |
| 2102 state.cacheBorderAndBackground(); | |
| 2103 | |
| 2104 // Now do the author and user normal priority properties and all the !import
ant properties. | |
| 2105 applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResul
t.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInherite
dOnly); | |
| 2106 if (RuntimeEnabledFeatures::webAnimationEnabled()) | |
| 2107 applyAnimatedProperties<LowPriorityProperties>(element); | |
| 2108 applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult
.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); | |
| 2109 applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult
.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); | |
| 2110 applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult
.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); | |
| 2111 | |
| 2112 // Start loading resources referenced by this style. | |
| 2113 loadPendingResources(); | |
| 2114 | |
| 2115 ASSERT(!state.fontDirty()); | |
| 2116 | |
| 2117 if (cacheItem || !cacheHash) | |
| 2118 return; | |
| 2119 if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), sta
te.parentStyle())) | |
| 2120 return; | |
| 2121 addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, m
atchResult); | |
| 2122 } | |
| 2123 | |
| 2124 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, Rend
erStyle* style) | |
| 2125 { | |
| 2126 initElement(0); | |
| 2127 m_state.initForStyleResolve(document(), 0, style); | |
| 2128 m_state.setStyle(style); | |
| 2129 applyPropertyToCurrentStyle(id, value); | |
| 2130 } | |
| 2131 | |
| 2132 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* valu
e) | |
| 2133 { | |
| 2134 if (value) | |
| 2135 applyProperty(id, value); | |
| 2136 } | |
| 2137 | |
| 2138 inline bool isValidVisitedLinkProperty(CSSPropertyID id) | |
| 2139 { | |
| 2140 switch (id) { | |
| 2141 case CSSPropertyBackgroundColor: | |
| 2142 case CSSPropertyBorderLeftColor: | |
| 2143 case CSSPropertyBorderRightColor: | |
| 2144 case CSSPropertyBorderTopColor: | |
| 2145 case CSSPropertyBorderBottomColor: | |
| 2146 case CSSPropertyColor: | |
| 2147 case CSSPropertyOutlineColor: | |
| 2148 case CSSPropertyWebkitColumnRuleColor: | |
| 2149 #if ENABLE(CSS3_TEXT) | |
| 2150 case CSSPropertyWebkitTextDecorationColor: | |
| 2151 #endif // CSS3_TEXT | |
| 2152 case CSSPropertyWebkitTextEmphasisColor: | |
| 2153 case CSSPropertyWebkitTextFillColor: | |
| 2154 case CSSPropertyWebkitTextStrokeColor: | |
| 2155 #if ENABLE(SVG) | |
| 2156 case CSSPropertyFill: | |
| 2157 case CSSPropertyStroke: | |
| 2158 #endif | |
| 2159 return true; | |
| 2160 default: | |
| 2161 break; | |
| 2162 } | |
| 2163 | |
| 2164 return false; | |
| 2165 } | |
| 2166 | |
| 2167 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule | |
| 2168 // FIXME: add incremental support for other region styling properties. | |
| 2169 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id) | |
| 2170 { | |
| 2171 switch (id) { | |
| 2172 case CSSPropertyBackgroundColor: | |
| 2173 case CSSPropertyColor: | |
| 2174 return true; | |
| 2175 default: | |
| 2176 break; | |
| 2177 } | |
| 2178 | |
| 2179 return false; | |
| 2180 } | |
| 2181 | |
| 2182 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id) | |
| 2183 { | |
| 2184 switch (id) { | |
| 2185 case CSSPropertyBackground: | |
| 2186 case CSSPropertyBackgroundAttachment: | |
| 2187 case CSSPropertyBackgroundClip: | |
| 2188 case CSSPropertyBackgroundColor: | |
| 2189 case CSSPropertyBackgroundImage: | |
| 2190 case CSSPropertyBackgroundOrigin: | |
| 2191 case CSSPropertyBackgroundPosition: | |
| 2192 case CSSPropertyBackgroundPositionX: | |
| 2193 case CSSPropertyBackgroundPositionY: | |
| 2194 case CSSPropertyBackgroundRepeat: | |
| 2195 case CSSPropertyBackgroundRepeatX: | |
| 2196 case CSSPropertyBackgroundRepeatY: | |
| 2197 case CSSPropertyBackgroundSize: | |
| 2198 case CSSPropertyColor: | |
| 2199 case CSSPropertyFont: | |
| 2200 case CSSPropertyFontFamily: | |
| 2201 case CSSPropertyFontSize: | |
| 2202 case CSSPropertyFontStyle: | |
| 2203 case CSSPropertyFontVariant: | |
| 2204 case CSSPropertyFontWeight: | |
| 2205 case CSSPropertyLineHeight: | |
| 2206 case CSSPropertyOpacity: | |
| 2207 case CSSPropertyOutline: | |
| 2208 case CSSPropertyOutlineColor: | |
| 2209 case CSSPropertyOutlineOffset: | |
| 2210 case CSSPropertyOutlineStyle: | |
| 2211 case CSSPropertyOutlineWidth: | |
| 2212 case CSSPropertyVisibility: | |
| 2213 case CSSPropertyWhiteSpace: | |
| 2214 case CSSPropertyTextDecoration: | |
| 2215 case CSSPropertyTextShadow: | |
| 2216 case CSSPropertyBorderStyle: | |
| 2217 return true; | |
| 2218 default: | |
| 2219 break; | |
| 2220 } | |
| 2221 return false; | |
| 2222 } | |
| 2223 // SVG handles zooming in a different way compared to CSS. The whole document is
scaled instead | |
| 2224 // of each individual length value in the render style / tree. CSSPrimitiveValue
::computeLength*() | |
| 2225 // multiplies each resolved length with the zoom multiplier - so for SVG we need
to disable that. | |
| 2226 // Though all CSS values that can be applied to outermost <svg> elements (width/
height/border/padding...) | |
| 2227 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) gr
abs values like | |
| 2228 // width/height/border/padding/... from the RenderStyle -> for SVG these values
would never scale, | |
| 2229 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1
.0 for specific | |
| 2230 // properties that are NOT allowed to scale within a zoomed SVG document (letter
/word-spacing/font-size). | |
| 2231 bool StyleResolver::useSVGZoomRules() | |
| 2232 { | |
| 2233 return m_state.element() && m_state.element()->isSVGElement(); | |
| 2234 } | |
| 2235 | |
| 2236 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const Styl
eResolverState& state, GridLength& workingLength) | |
| 2237 { | |
| 2238 if (primitiveValue->getIdent() == CSSValueWebkitMinContent) { | |
| 2239 workingLength = Length(MinContent); | |
| 2240 return true; | |
| 2241 } | |
| 2242 | |
| 2243 if (primitiveValue->getIdent() == CSSValueWebkitMaxContent) { | |
| 2244 workingLength = Length(MaxContent); | |
| 2245 return true; | |
| 2246 } | |
| 2247 | |
| 2248 if (primitiveValue->isFlex()) { | |
| 2249 // Fractional unit. | |
| 2250 workingLength.setFlex(primitiveValue->getFloatValue()); | |
| 2251 return true; | |
| 2252 } | |
| 2253 | |
| 2254 workingLength = primitiveValue->convertToLength<FixedIntegerConversion | Per
centConversion | ViewportPercentageConversion | AutoConversion>(state.style(), s
tate.rootElementStyle(), state.style()->effectiveZoom()); | |
| 2255 if (workingLength.length().isUndefined()) | |
| 2256 return false; | |
| 2257 | |
| 2258 if (primitiveValue->isLength()) | |
| 2259 workingLength.length().setQuirk(primitiveValue->isQuirkValue()); | |
| 2260 | |
| 2261 return true; | |
| 2262 } | |
| 2263 | |
| 2264 static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const
StyleResolverState& state) | |
| 2265 { | |
| 2266 if (!value->isPrimitiveValue()) | |
| 2267 return false; | |
| 2268 | |
| 2269 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); | |
| 2270 Pair* minMaxTrackBreadth = primitiveValue->getPairValue(); | |
| 2271 if (!minMaxTrackBreadth) { | |
| 2272 GridLength workingLength; | |
| 2273 if (!createGridTrackBreadth(primitiveValue, state, workingLength)) | |
| 2274 return false; | |
| 2275 | |
| 2276 trackSize.setLength(workingLength); | |
| 2277 return true; | |
| 2278 } | |
| 2279 | |
| 2280 GridLength minTrackBreadth; | |
| 2281 GridLength maxTrackBreadth; | |
| 2282 if (!createGridTrackBreadth(minMaxTrackBreadth->first(), state, minTrackBrea
dth) || !createGridTrackBreadth(minMaxTrackBreadth->second(), state, maxTrackBre
adth)) | |
| 2283 return false; | |
| 2284 | |
| 2285 trackSize.setMinMax(minTrackBreadth, maxTrackBreadth); | |
| 2286 return true; | |
| 2287 } | |
| 2288 | |
| 2289 static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSiz
es, NamedGridLinesMap& namedGridLines, const StyleResolverState& state) | |
| 2290 { | |
| 2291 // Handle 'none'. | |
| 2292 if (value->isPrimitiveValue()) { | |
| 2293 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valu
e); | |
| 2294 return primitiveValue->getIdent() == CSSValueNone; | |
| 2295 } | |
| 2296 | |
| 2297 if (!value->isValueList()) | |
| 2298 return false; | |
| 2299 | |
| 2300 size_t currentNamedGridLine = 0; | |
| 2301 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { | |
| 2302 CSSValue* currValue = i.value(); | |
| 2303 if (currValue->isPrimitiveValue()) { | |
| 2304 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(
currValue); | |
| 2305 if (primitiveValue->isString()) { | |
| 2306 NamedGridLinesMap::AddResult result = namedGridLines.add(primiti
veValue->getStringValue(), Vector<size_t>()); | |
| 2307 result.iterator->value.append(currentNamedGridLine); | |
| 2308 continue; | |
| 2309 } | |
| 2310 } | |
| 2311 | |
| 2312 ++currentNamedGridLine; | |
| 2313 GridTrackSize trackSize; | |
| 2314 if (!createGridTrackSize(currValue, trackSize, state)) | |
| 2315 return false; | |
| 2316 | |
| 2317 trackSizes.append(trackSize); | |
| 2318 } | |
| 2319 | |
| 2320 if (trackSizes.isEmpty()) | |
| 2321 return false; | |
| 2322 | |
| 2323 return true; | |
| 2324 } | |
| 2325 | |
| 2326 | |
| 2327 static bool createGridPosition(CSSValue* value, GridPosition& position) | |
| 2328 { | |
| 2329 // For now, we only accept: 'auto' | <integer> | span && <integer>? | |
| 2330 if (value->isPrimitiveValue()) { | |
| 2331 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valu
e); | |
| 2332 if (primitiveValue->getIdent() == CSSValueAuto) | |
| 2333 return true; | |
| 2334 | |
| 2335 if (primitiveValue->getIdent() == CSSValueSpan) { | |
| 2336 // If the <integer> is omitted, it defaults to '1'. | |
| 2337 position.setSpanPosition(1); | |
| 2338 return true; | |
| 2339 } | |
| 2340 | |
| 2341 ASSERT(primitiveValue->isNumber()); | |
| 2342 position.setIntegerPosition(primitiveValue->getIntValue()); | |
| 2343 return true; | |
| 2344 } | |
| 2345 | |
| 2346 ASSERT_WITH_SECURITY_IMPLICATION(value->isValueList()); | |
| 2347 CSSValueList* values = static_cast<CSSValueList*>(value); | |
| 2348 ASSERT(values->length() == 2); | |
| 2349 ASSERT_WITH_SECURITY_IMPLICATION(values->itemWithoutBoundsCheck(1)->isPrimit
iveValue()); | |
| 2350 CSSPrimitiveValue* numericValue = static_cast<CSSPrimitiveValue*>(values->it
emWithoutBoundsCheck(1)); | |
| 2351 ASSERT(numericValue->isNumber()); | |
| 2352 position.setSpanPosition(numericValue->getIntValue()); | |
| 2353 return true; | |
| 2354 } | |
| 2355 | |
| 2356 static bool hasVariableReference(CSSValue* value) | |
| 2357 { | |
| 2358 if (value->isPrimitiveValue()) { | |
| 2359 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valu
e); | |
| 2360 return primitiveValue->hasVariableReference(); | |
| 2361 } | |
| 2362 | |
| 2363 if (value->isCalculationValue()) | |
| 2364 return static_cast<CSSCalcValue*>(value)->hasVariableReference(); | |
| 2365 | |
| 2366 if (value->isReflectValue()) { | |
| 2367 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value); | |
| 2368 CSSPrimitiveValue* direction = reflectValue->direction(); | |
| 2369 CSSPrimitiveValue* offset = reflectValue->offset(); | |
| 2370 CSSValue* mask = reflectValue->mask(); | |
| 2371 return (direction && hasVariableReference(direction)) || (offset && hasV
ariableReference(offset)) || (mask && hasVariableReference(mask)); | |
| 2372 } | |
| 2373 | |
| 2374 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { | |
| 2375 if (hasVariableReference(i.value())) | |
| 2376 return true; | |
| 2377 } | |
| 2378 | |
| 2379 return false; | |
| 2380 } | |
| 2381 | |
| 2382 void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<s
td::pair<CSSPropertyID, String> >& knownExpressions) | |
| 2383 { | |
| 2384 std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVar
iables(*m_state.style()->variables())); | |
| 2385 | |
| 2386 if (knownExpressions.contains(expression)) | |
| 2387 return; // cycle detected. | |
| 2388 | |
| 2389 knownExpressions.append(expression); | |
| 2390 | |
| 2391 // FIXME: It would be faster not to re-parse from strings, but for now CSS p
roperty validation lives inside the parser so we do it there. | |
| 2392 RefPtr<StylePropertySet> resultSet = StylePropertySet::create(); | |
| 2393 if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, do
cument())) | |
| 2394 return; // expression failed to parse. | |
| 2395 | |
| 2396 for (unsigned i = 0; i < resultSet->propertyCount(); i++) { | |
| 2397 StylePropertySet::PropertyReference property = resultSet->propertyAt(i); | |
| 2398 if (property.id() != CSSPropertyVariable && hasVariableReference(propert
y.value())) | |
| 2399 resolveVariables(property.id(), property.value(), knownExpressions); | |
| 2400 else | |
| 2401 applyProperty(property.id(), property.value()); | |
| 2402 } | |
| 2403 } | |
| 2404 | |
| 2405 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value) | |
| 2406 { | |
| 2407 if (id != CSSPropertyVariable && hasVariableReference(value)) { | |
| 2408 Vector<std::pair<CSSPropertyID, String> > knownExpressions; | |
| 2409 resolveVariables(id, value, knownExpressions); | |
| 2410 return; | |
| 2411 } | |
| 2412 | |
| 2413 // CSS variables don't resolve shorthands at parsing time, so this should be
*after* handling variables. | |
| 2414 ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wa
sn't expanded at parsing time", id); | |
| 2415 | |
| 2416 StyleResolverState& state = m_state; | |
| 2417 bool isInherit = state.parentNode() && value->isInheritedValue(); | |
| 2418 bool isInitial = value->isInitialValue() || (!state.parentNode() && value->i
sInheritedValue()); | |
| 2419 | |
| 2420 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial ->
!isInherit | |
| 2421 ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInhe
rit -> (state.parentNode() && state.parentStyle()) | |
| 2422 | |
| 2423 if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLi
nkStyle() || !isValidVisitedLinkProperty(id))) { | |
| 2424 // Limit the properties that can be applied to only the ones honored by
:visited. | |
| 2425 return; | |
| 2426 } | |
| 2427 | |
| 2428 if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() &&
!CSSProperty::isInheritedProperty(id)) | |
| 2429 state.parentStyle()->setHasExplicitlyInheritedProperties(); | |
| 2430 | |
| 2431 if (id == CSSPropertyVariable) { | |
| 2432 ASSERT_WITH_SECURITY_IMPLICATION(value->isVariableValue()); | |
| 2433 CSSVariableValue* variable = static_cast<CSSVariableValue*>(value); | |
| 2434 ASSERT(!variable->name().isEmpty()); | |
| 2435 ASSERT(!variable->value().isEmpty()); | |
| 2436 state.style()->setVariable(variable->name(), variable->value()); | |
| 2437 return; | |
| 2438 } | |
| 2439 | |
| 2440 // Check lookup table for implementations and use when available. | |
| 2441 const PropertyHandler& handler = m_styleBuilder.propertyHandler(id); | |
| 2442 if (handler.isValid()) { | |
| 2443 if (isInherit) | |
| 2444 handler.applyInheritValue(id, this); | |
| 2445 else if (isInitial) | |
| 2446 handler.applyInitialValue(id, this); | |
| 2447 else | |
| 2448 handler.applyValue(id, this, value); | |
| 2449 return; | |
| 2450 } | |
| 2451 | |
| 2452 CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<
CSSPrimitiveValue*>(value) : 0; | |
| 2453 | |
| 2454 float zoomFactor = state.style()->effectiveZoom(); | |
| 2455 | |
| 2456 // What follows is a list that maps the CSS properties into their correspond
ing front-end | |
| 2457 // RenderStyle values. | |
| 2458 switch (id) { | |
| 2459 // lists | |
| 2460 case CSSPropertyContent: | |
| 2461 // list of string, uri, counter, attr, i | |
| 2462 { | |
| 2463 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 i
t is not. This | |
| 2464 // note is a reminder that eventually "inherit" needs to be supporte
d. | |
| 2465 | |
| 2466 if (isInitial) { | |
| 2467 state.style()->clearContent(); | |
| 2468 return; | |
| 2469 } | |
| 2470 | |
| 2471 if (!value->isValueList()) | |
| 2472 return; | |
| 2473 | |
| 2474 bool didSet = false; | |
| 2475 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { | |
| 2476 CSSValue* item = i.value(); | |
| 2477 if (item->isImageGeneratorValue()) { | |
| 2478 if (item->isGradientValue()) | |
| 2479 state.style()->setContent(StyleGeneratedImage::create(st
atic_cast<CSSGradientValue*>(item)->gradientWithStylesResolved(this).get()), did
Set); | |
| 2480 else | |
| 2481 state.style()->setContent(StyleGeneratedImage::create(st
atic_cast<CSSImageGeneratorValue*>(item)), didSet); | |
| 2482 didSet = true; | |
| 2483 } else if (item->isImageSetValue()) { | |
| 2484 state.style()->setContent(setOrPendingFromValue(CSSPropertyC
ontent, static_cast<CSSImageSetValue*>(item)), didSet); | |
| 2485 didSet = true; | |
| 2486 } | |
| 2487 | |
| 2488 if (item->isImageValue()) { | |
| 2489 state.style()->setContent(cachedOrPendingFromValue(CSSProper
tyContent, static_cast<CSSImageValue*>(item)), didSet); | |
| 2490 didSet = true; | |
| 2491 continue; | |
| 2492 } | |
| 2493 | |
| 2494 if (!item->isPrimitiveValue()) | |
| 2495 continue; | |
| 2496 | |
| 2497 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*
>(item); | |
| 2498 | |
| 2499 if (contentValue->isString()) { | |
| 2500 state.style()->setContent(contentValue->getStringValue().imp
l(), didSet); | |
| 2501 didSet = true; | |
| 2502 } else if (contentValue->isAttr()) { | |
| 2503 // FIXME: Can a namespace be specified for an attr(foo)? | |
| 2504 if (state.style()->styleType() == NOPSEUDO) | |
| 2505 state.style()->setUnique(); | |
| 2506 else | |
| 2507 state.parentStyle()->setUnique(); | |
| 2508 QualifiedName attr(nullAtom, contentValue->getStringValue().
impl(), nullAtom); | |
| 2509 const AtomicString& value = state.element()->getAttribute(at
tr); | |
| 2510 state.style()->setContent(value.isNull() ? emptyAtom : value
.impl(), didSet); | |
| 2511 didSet = true; | |
| 2512 // register the fact that the attribute value affects the st
yle | |
| 2513 m_ruleSets.features().attrsInRules.add(attr.localName().impl
()); | |
| 2514 } else if (contentValue->isCounter()) { | |
| 2515 Counter* counterValue = contentValue->getCounterValue(); | |
| 2516 EListStyleType listStyleType = NoneListStyle; | |
| 2517 int listStyleIdent = counterValue->listStyleIdent(); | |
| 2518 if (listStyleIdent != CSSValueNone) | |
| 2519 listStyleType = static_cast<EListStyleType>(listStyleIde
nt - CSSValueDisc); | |
| 2520 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent
(counterValue->identifier(), listStyleType, counterValue->separator())); | |
| 2521 state.style()->setContent(counter.release(), didSet); | |
| 2522 didSet = true; | |
| 2523 } else { | |
| 2524 switch (contentValue->getIdent()) { | |
| 2525 case CSSValueOpenQuote: | |
| 2526 state.style()->setContent(OPEN_QUOTE, didSet); | |
| 2527 didSet = true; | |
| 2528 break; | |
| 2529 case CSSValueCloseQuote: | |
| 2530 state.style()->setContent(CLOSE_QUOTE, didSet); | |
| 2531 didSet = true; | |
| 2532 break; | |
| 2533 case CSSValueNoOpenQuote: | |
| 2534 state.style()->setContent(NO_OPEN_QUOTE, didSet); | |
| 2535 didSet = true; | |
| 2536 break; | |
| 2537 case CSSValueNoCloseQuote: | |
| 2538 state.style()->setContent(NO_CLOSE_QUOTE, didSet); | |
| 2539 didSet = true; | |
| 2540 break; | |
| 2541 default: | |
| 2542 // normal and none do not have any effect. | |
| 2543 { } | |
| 2544 } | |
| 2545 } | |
| 2546 } | |
| 2547 if (!didSet) | |
| 2548 state.style()->clearContent(); | |
| 2549 return; | |
| 2550 } | |
| 2551 case CSSPropertyQuotes: | |
| 2552 if (isInherit) { | |
| 2553 state.style()->setQuotes(state.parentStyle()->quotes()); | |
| 2554 return; | |
| 2555 } | |
| 2556 if (isInitial) { | |
| 2557 state.style()->setQuotes(0); | |
| 2558 return; | |
| 2559 } | |
| 2560 if (value->isValueList()) { | |
| 2561 CSSValueList* list = static_cast<CSSValueList*>(value); | |
| 2562 RefPtr<QuotesData> quotes = QuotesData::create(); | |
| 2563 for (size_t i = 0; i < list->length(); i += 2) { | |
| 2564 CSSValue* first = list->itemWithoutBoundsCheck(i); | |
| 2565 // item() returns null if out of bounds so this is safe. | |
| 2566 CSSValue* second = list->item(i + 1); | |
| 2567 if (!second) | |
| 2568 continue; | |
| 2569 ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue()); | |
| 2570 ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue()); | |
| 2571 String startQuote = static_cast<CSSPrimitiveValue*>(first)->getS
tringValue(); | |
| 2572 String endQuote = static_cast<CSSPrimitiveValue*>(second)->getSt
ringValue(); | |
| 2573 quotes->addPair(std::make_pair(startQuote, endQuote)); | |
| 2574 } | |
| 2575 state.style()->setQuotes(quotes); | |
| 2576 return; | |
| 2577 } | |
| 2578 if (primitiveValue) { | |
| 2579 if (primitiveValue->getIdent() == CSSValueNone) | |
| 2580 state.style()->setQuotes(QuotesData::create()); | |
| 2581 } | |
| 2582 return; | |
| 2583 // Shorthand properties. | |
| 2584 case CSSPropertyFont: | |
| 2585 if (isInherit) { | |
| 2586 FontDescription fontDescription = state.parentStyle()->fontDescripti
on(); | |
| 2587 state.style()->setLineHeight(state.parentStyle()->specifiedLineHeigh
t()); | |
| 2588 state.setLineHeightValue(0); | |
| 2589 setFontDescription(fontDescription); | |
| 2590 } else if (isInitial) { | |
| 2591 Settings* settings = documentSettings(); | |
| 2592 ASSERT(settings); // If we're doing style resolution, this document
should always be in a frame and thus have settings | |
| 2593 if (!settings) | |
| 2594 return; | |
| 2595 initializeFontStyle(settings); | |
| 2596 } else if (primitiveValue) { | |
| 2597 state.style()->setLineHeight(RenderStyle::initialLineHeight()); | |
| 2598 state.setLineHeightValue(0); | |
| 2599 | |
| 2600 FontDescription fontDescription; | |
| 2601 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(),
fontDescription); | |
| 2602 | |
| 2603 // Double-check and see if the theme did anything. If not, don't bot
her updating the font. | |
| 2604 if (fontDescription.isAbsoluteSize()) { | |
| 2605 // Make sure the rendering mode and printer font settings are up
dated. | |
| 2606 Settings* settings = documentSettings(); | |
| 2607 ASSERT(settings); // If we're doing style resolution, this docum
ent should always be in a frame and thus have settings | |
| 2608 if (!settings) | |
| 2609 return; | |
| 2610 fontDescription.setRenderingMode(settings->fontRenderingMode()); | |
| 2611 fontDescription.setUsePrinterFont(document()->printing()); | |
| 2612 | |
| 2613 // Handle the zoom factor. | |
| 2614 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize
(document(), state.style(), fontDescription.isAbsoluteSize(), fontDescription.sp
ecifiedSize(), useSVGZoomRules())); | |
| 2615 setFontDescription(fontDescription); | |
| 2616 } | |
| 2617 } else if (value->isFontValue()) { | |
| 2618 FontValue* font = static_cast<FontValue*>(value); | |
| 2619 if (!font->style || !font->variant || !font->weight | |
| 2620 || !font->size || !font->lineHeight || !font->family) | |
| 2621 return; | |
| 2622 applyProperty(CSSPropertyFontStyle, font->style.get()); | |
| 2623 applyProperty(CSSPropertyFontVariant, font->variant.get()); | |
| 2624 applyProperty(CSSPropertyFontWeight, font->weight.get()); | |
| 2625 // The previous properties can dirty our font but they don't try to
read the font's | |
| 2626 // properties back, which is safe. However if font-size is using the
'ex' unit, it will | |
| 2627 // need query the dirtied font's x-height to get the computed size.
To be safe in this | |
| 2628 // case, let's just update the font now. | |
| 2629 updateFont(); | |
| 2630 applyProperty(CSSPropertyFontSize, font->size.get()); | |
| 2631 | |
| 2632 state.setLineHeightValue(font->lineHeight.get()); | |
| 2633 | |
| 2634 applyProperty(CSSPropertyFontFamily, font->family.get()); | |
| 2635 } | |
| 2636 return; | |
| 2637 | |
| 2638 case CSSPropertyBackground: | |
| 2639 case CSSPropertyBackgroundPosition: | |
| 2640 case CSSPropertyBackgroundRepeat: | |
| 2641 case CSSPropertyBorder: | |
| 2642 case CSSPropertyBorderBottom: | |
| 2643 case CSSPropertyBorderColor: | |
| 2644 case CSSPropertyBorderImage: | |
| 2645 case CSSPropertyBorderLeft: | |
| 2646 case CSSPropertyBorderRadius: | |
| 2647 case CSSPropertyBorderRight: | |
| 2648 case CSSPropertyBorderSpacing: | |
| 2649 case CSSPropertyBorderStyle: | |
| 2650 case CSSPropertyBorderTop: | |
| 2651 case CSSPropertyBorderWidth: | |
| 2652 case CSSPropertyListStyle: | |
| 2653 case CSSPropertyMargin: | |
| 2654 case CSSPropertyOutline: | |
| 2655 case CSSPropertyOverflow: | |
| 2656 case CSSPropertyPadding: | |
| 2657 case CSSPropertyTransition: | |
| 2658 case CSSPropertyWebkitAnimation: | |
| 2659 case CSSPropertyWebkitBorderAfter: | |
| 2660 case CSSPropertyWebkitBorderBefore: | |
| 2661 case CSSPropertyWebkitBorderEnd: | |
| 2662 case CSSPropertyWebkitBorderStart: | |
| 2663 case CSSPropertyWebkitBorderRadius: | |
| 2664 case CSSPropertyWebkitColumns: | |
| 2665 case CSSPropertyWebkitColumnRule: | |
| 2666 case CSSPropertyWebkitFlex: | |
| 2667 case CSSPropertyWebkitFlexFlow: | |
| 2668 case CSSPropertyWebkitGridColumn: | |
| 2669 case CSSPropertyWebkitGridRow: | |
| 2670 case CSSPropertyWebkitMarginCollapse: | |
| 2671 case CSSPropertyWebkitMarquee: | |
| 2672 case CSSPropertyWebkitMask: | |
| 2673 case CSSPropertyWebkitMaskPosition: | |
| 2674 case CSSPropertyWebkitMaskRepeat: | |
| 2675 case CSSPropertyWebkitTextEmphasis: | |
| 2676 case CSSPropertyWebkitTextStroke: | |
| 2677 case CSSPropertyWebkitTransition: | |
| 2678 case CSSPropertyWebkitTransformOrigin: | |
| 2679 case CSSPropertyWebkitWrap: | |
| 2680 ASSERT(isExpandedShorthand(id)); | |
| 2681 ASSERT_NOT_REACHED(); | |
| 2682 break; | |
| 2683 | |
| 2684 // CSS3 Properties | |
| 2685 case CSSPropertyTextShadow: | |
| 2686 case CSSPropertyBoxShadow: | |
| 2687 case CSSPropertyWebkitBoxShadow: { | |
| 2688 if (isInherit) { | |
| 2689 if (id == CSSPropertyTextShadow) | |
| 2690 return state.style()->setTextShadow(state.parentStyle()->textSha
dow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr); | |
| 2691 return state.style()->setBoxShadow(state.parentStyle()->boxShadow()
? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr); | |
| 2692 } | |
| 2693 if (isInitial || primitiveValue) // initial | none | |
| 2694 return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nu
llptr) : state.style()->setBoxShadow(nullptr); | |
| 2695 | |
| 2696 if (!value->isValueList()) | |
| 2697 return; | |
| 2698 | |
| 2699 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { | |
| 2700 CSSValue* currValue = i.value(); | |
| 2701 if (!currValue->isShadowValue()) | |
| 2702 continue; | |
| 2703 ShadowValue* item = static_cast<ShadowValue*>(currValue); | |
| 2704 int x = item->x->computeLength<int>(state.style(), state.rootElement
Style(), zoomFactor); | |
| 2705 int y = item->y->computeLength<int>(state.style(), state.rootElement
Style(), zoomFactor); | |
| 2706 int blur = item->blur ? item->blur->computeLength<int>(state.style()
, state.rootElementStyle(), zoomFactor) : 0; | |
| 2707 int spread = item->spread ? item->spread->computeLength<int>(state.s
tyle(), state.rootElementStyle(), zoomFactor) : 0; | |
| 2708 ShadowStyle shadowStyle = item->style && item->style->getIdent() ==
CSSValueInset ? Inset : Normal; | |
| 2709 Color color; | |
| 2710 if (item->color) | |
| 2711 color = m_state.colorFromPrimitiveValue(item->color.get()); | |
| 2712 else if (state.style()) | |
| 2713 color = state.style()->color(); | |
| 2714 | |
| 2715 OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x,
y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid()
? color : Color::transparent)); | |
| 2716 if (id == CSSPropertyTextShadow) | |
| 2717 state.style()->setTextShadow(shadowData.release(), i.index()); /
/ add to the list if this is not the first entry | |
| 2718 else | |
| 2719 state.style()->setBoxShadow(shadowData.release(), i.index()); //
add to the list if this is not the first entry | |
| 2720 } | |
| 2721 return; | |
| 2722 } | |
| 2723 case CSSPropertyWebkitBoxReflect: { | |
| 2724 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect) | |
| 2725 if (primitiveValue) { | |
| 2726 state.style()->setBoxReflect(RenderStyle::initialBoxReflect()); | |
| 2727 return; | |
| 2728 } | |
| 2729 | |
| 2730 if (!value->isReflectValue()) | |
| 2731 return; | |
| 2732 | |
| 2733 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value); | |
| 2734 RefPtr<StyleReflection> reflection = StyleReflection::create(); | |
| 2735 reflection->setDirection(*reflectValue->direction()); | |
| 2736 if (reflectValue->offset()) | |
| 2737 reflection->setOffset(reflectValue->offset()->convertToLength<FixedI
ntegerConversion | PercentConversion | CalculatedConversion>(state.style(), stat
e.rootElementStyle(), zoomFactor)); | |
| 2738 NinePieceImage mask; | |
| 2739 mask.setMaskDefaults(); | |
| 2740 m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask); | |
| 2741 reflection->setMask(mask); | |
| 2742 | |
| 2743 state.style()->setBoxReflect(reflection.release()); | |
| 2744 return; | |
| 2745 } | |
| 2746 case CSSPropertySrc: // Only used in @font-face rules. | |
| 2747 return; | |
| 2748 case CSSPropertyUnicodeRange: // Only used in @font-face rules. | |
| 2749 return; | |
| 2750 case CSSPropertyWebkitLocale: { | |
| 2751 HANDLE_INHERIT_AND_INITIAL(locale, Locale); | |
| 2752 if (!primitiveValue) | |
| 2753 return; | |
| 2754 if (primitiveValue->getIdent() == CSSValueAuto) | |
| 2755 state.style()->setLocale(nullAtom); | |
| 2756 else | |
| 2757 state.style()->setLocale(primitiveValue->getStringValue()); | |
| 2758 FontDescription fontDescription = state.style()->fontDescription(); | |
| 2759 fontDescription.setScript(localeToScriptCodeForFontSelection(state.style
()->locale())); | |
| 2760 setFontDescription(fontDescription); | |
| 2761 return; | |
| 2762 } | |
| 2763 case CSSPropertyWebkitAppRegion: { | |
| 2764 if (!primitiveValue || !primitiveValue->getIdent()) | |
| 2765 return; | |
| 2766 state.style()->setDraggableRegionMode(primitiveValue->getIdent() == CSSV
alueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); | |
| 2767 state.document()->setHasAnnotatedRegions(true); | |
| 2768 return; | |
| 2769 } | |
| 2770 case CSSPropertyWebkitTextStrokeWidth: { | |
| 2771 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) | |
| 2772 float width = 0; | |
| 2773 switch (primitiveValue->getIdent()) { | |
| 2774 case CSSValueThin: | |
| 2775 case CSSValueMedium: | |
| 2776 case CSSValueThick: { | |
| 2777 double result = 1.0 / 48; | |
| 2778 if (primitiveValue->getIdent() == CSSValueMedium) | |
| 2779 result *= 3; | |
| 2780 else if (primitiveValue->getIdent() == CSSValueThick) | |
| 2781 result *= 5; | |
| 2782 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS
)->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor); | |
| 2783 break; | |
| 2784 } | |
| 2785 default: | |
| 2786 width = primitiveValue->computeLength<float>(state.style(), state.ro
otElementStyle(), zoomFactor); | |
| 2787 break; | |
| 2788 } | |
| 2789 state.style()->setTextStrokeWidth(width); | |
| 2790 return; | |
| 2791 } | |
| 2792 case CSSPropertyWebkitTransform: { | |
| 2793 HANDLE_INHERIT_AND_INITIAL(transform, Transform); | |
| 2794 TransformOperations operations; | |
| 2795 TransformBuilder::createTransformOperations(value, state.style(), state.
rootElementStyle(), operations); | |
| 2796 state.style()->setTransform(operations); | |
| 2797 return; | |
| 2798 } | |
| 2799 case CSSPropertyWebkitPerspective: { | |
| 2800 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective) | |
| 2801 | |
| 2802 if (!primitiveValue) | |
| 2803 return; | |
| 2804 | |
| 2805 if (primitiveValue->getIdent() == CSSValueNone) { | |
| 2806 state.style()->setPerspective(0); | |
| 2807 return; | |
| 2808 } | |
| 2809 | |
| 2810 float perspectiveValue; | |
| 2811 if (primitiveValue->isLength()) | |
| 2812 perspectiveValue = primitiveValue->computeLength<float>(state.style(
), state.rootElementStyle(), zoomFactor); | |
| 2813 else if (primitiveValue->isNumber()) { | |
| 2814 // For backward compatibility, treat valueless numbers as px. | |
| 2815 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoub
leValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.style(), state
.rootElementStyle(), zoomFactor); | |
| 2816 } else | |
| 2817 return; | |
| 2818 | |
| 2819 if (perspectiveValue >= 0.0f) | |
| 2820 state.style()->setPerspective(perspectiveValue); | |
| 2821 return; | |
| 2822 } | |
| 2823 case CSSPropertyWebkitTapHighlightColor: { | |
| 2824 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); | |
| 2825 if (!primitiveValue) | |
| 2826 break; | |
| 2827 | |
| 2828 Color col = m_state.colorFromPrimitiveValue(primitiveValue); | |
| 2829 state.style()->setTapHighlightColor(col); | |
| 2830 return; | |
| 2831 } | |
| 2832 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) | |
| 2833 case CSSPropertyWebkitOverflowScrolling: { | |
| 2834 HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowSc
rolling); | |
| 2835 if (!primitiveValue) | |
| 2836 break; | |
| 2837 state.style()->setUseTouchOverflowScrolling(primitiveValue->getIdent() =
= CSSValueTouch); | |
| 2838 return; | |
| 2839 } | |
| 2840 #endif | |
| 2841 case CSSPropertyInvalid: | |
| 2842 return; | |
| 2843 // Directional properties are resolved by resolveDirectionAwareProperty() be
fore the switch. | |
| 2844 case CSSPropertyWebkitBorderEndColor: | |
| 2845 case CSSPropertyWebkitBorderEndStyle: | |
| 2846 case CSSPropertyWebkitBorderEndWidth: | |
| 2847 case CSSPropertyWebkitBorderStartColor: | |
| 2848 case CSSPropertyWebkitBorderStartStyle: | |
| 2849 case CSSPropertyWebkitBorderStartWidth: | |
| 2850 case CSSPropertyWebkitBorderBeforeColor: | |
| 2851 case CSSPropertyWebkitBorderBeforeStyle: | |
| 2852 case CSSPropertyWebkitBorderBeforeWidth: | |
| 2853 case CSSPropertyWebkitBorderAfterColor: | |
| 2854 case CSSPropertyWebkitBorderAfterStyle: | |
| 2855 case CSSPropertyWebkitBorderAfterWidth: | |
| 2856 case CSSPropertyWebkitMarginEnd: | |
| 2857 case CSSPropertyWebkitMarginStart: | |
| 2858 case CSSPropertyWebkitMarginBefore: | |
| 2859 case CSSPropertyWebkitMarginAfter: | |
| 2860 case CSSPropertyWebkitMarginBeforeCollapse: | |
| 2861 case CSSPropertyWebkitMarginTopCollapse: | |
| 2862 case CSSPropertyWebkitMarginAfterCollapse: | |
| 2863 case CSSPropertyWebkitMarginBottomCollapse: | |
| 2864 case CSSPropertyWebkitPaddingEnd: | |
| 2865 case CSSPropertyWebkitPaddingStart: | |
| 2866 case CSSPropertyWebkitPaddingBefore: | |
| 2867 case CSSPropertyWebkitPaddingAfter: | |
| 2868 case CSSPropertyWebkitLogicalWidth: | |
| 2869 case CSSPropertyWebkitLogicalHeight: | |
| 2870 case CSSPropertyWebkitMinLogicalWidth: | |
| 2871 case CSSPropertyWebkitMinLogicalHeight: | |
| 2872 case CSSPropertyWebkitMaxLogicalWidth: | |
| 2873 case CSSPropertyWebkitMaxLogicalHeight: | |
| 2874 { | |
| 2875 CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, sta
te.style()->direction(), state.style()->writingMode()); | |
| 2876 ASSERT(newId != id); | |
| 2877 return applyProperty(newId, value); | |
| 2878 } | |
| 2879 case CSSPropertyFontStretch: | |
| 2880 case CSSPropertyPage: | |
| 2881 case CSSPropertyTextLineThrough: | |
| 2882 case CSSPropertyTextLineThroughColor: | |
| 2883 case CSSPropertyTextLineThroughMode: | |
| 2884 case CSSPropertyTextLineThroughStyle: | |
| 2885 case CSSPropertyTextLineThroughWidth: | |
| 2886 case CSSPropertyTextOverline: | |
| 2887 case CSSPropertyTextOverlineColor: | |
| 2888 case CSSPropertyTextOverlineMode: | |
| 2889 case CSSPropertyTextOverlineStyle: | |
| 2890 case CSSPropertyTextOverlineWidth: | |
| 2891 case CSSPropertyTextUnderline: | |
| 2892 case CSSPropertyTextUnderlineColor: | |
| 2893 case CSSPropertyTextUnderlineMode: | |
| 2894 case CSSPropertyTextUnderlineStyle: | |
| 2895 case CSSPropertyTextUnderlineWidth: | |
| 2896 case CSSPropertyWebkitFontSizeDelta: | |
| 2897 case CSSPropertyWebkitTextDecorationsInEffect: | |
| 2898 return; | |
| 2899 | |
| 2900 // CSS Text Layout Module Level 3: Vertical writing support | |
| 2901 case CSSPropertyWebkitWritingMode: { | |
| 2902 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode); | |
| 2903 | |
| 2904 if (primitiveValue) | |
| 2905 setWritingMode(*primitiveValue); | |
| 2906 | |
| 2907 // FIXME: It is not ok to modify document state while applying style. | |
| 2908 if (state.element() && state.element() == state.document()->documentElem
ent()) | |
| 2909 state.document()->setWritingModeSetOnDocumentElement(true); | |
| 2910 return; | |
| 2911 } | |
| 2912 | |
| 2913 case CSSPropertyWebkitTextOrientation: { | |
| 2914 HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation); | |
| 2915 | |
| 2916 if (primitiveValue) | |
| 2917 setTextOrientation(*primitiveValue); | |
| 2918 | |
| 2919 return; | |
| 2920 } | |
| 2921 | |
| 2922 case CSSPropertyWebkitLineBoxContain: { | |
| 2923 HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain) | |
| 2924 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { | |
| 2925 state.style()->setLineBoxContain(LineBoxContainNone); | |
| 2926 return; | |
| 2927 } | |
| 2928 | |
| 2929 if (!value->isCSSLineBoxContainValue()) | |
| 2930 return; | |
| 2931 | |
| 2932 CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxCont
ainValue*>(value); | |
| 2933 state.style()->setLineBoxContain(lineBoxContainValue->value()); | |
| 2934 return; | |
| 2935 } | |
| 2936 | |
| 2937 // CSS Fonts Module Level 3 | |
| 2938 case CSSPropertyWebkitFontFeatureSettings: { | |
| 2939 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) { | |
| 2940 setFontDescription(state.style()->fontDescription().makeNormalFeatur
eSettings()); | |
| 2941 return; | |
| 2942 } | |
| 2943 | |
| 2944 if (!value->isValueList()) | |
| 2945 return; | |
| 2946 | |
| 2947 FontDescription fontDescription = state.style()->fontDescription(); | |
| 2948 CSSValueList* list = static_cast<CSSValueList*>(value); | |
| 2949 RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create(); | |
| 2950 int len = list->length(); | |
| 2951 for (int i = 0; i < len; ++i) { | |
| 2952 CSSValue* item = list->itemWithoutBoundsCheck(i); | |
| 2953 if (!item->isFontFeatureValue()) | |
| 2954 continue; | |
| 2955 FontFeatureValue* feature = static_cast<FontFeatureValue*>(item); | |
| 2956 settings->append(FontFeature(feature->tag(), feature->value())); | |
| 2957 } | |
| 2958 fontDescription.setFeatureSettings(settings.release()); | |
| 2959 setFontDescription(fontDescription); | |
| 2960 return; | |
| 2961 } | |
| 2962 | |
| 2963 case CSSPropertyWebkitFilter: { | |
| 2964 HANDLE_INHERIT_AND_INITIAL(filter, Filter); | |
| 2965 FilterOperations operations; | |
| 2966 if (FilterOperationResolver::createFilterOperations(value, state.style()
, state.rootElementStyle(), operations, m_customFilterProgramCache.get(), m_stat
e)) | |
| 2967 state.style()->setFilter(operations); | |
| 2968 return; | |
| 2969 } | |
| 2970 case CSSPropertyWebkitGridAutoColumns: { | |
| 2971 GridTrackSize trackSize; | |
| 2972 if (!createGridTrackSize(value, trackSize, state)) | |
| 2973 return; | |
| 2974 state.style()->setGridAutoColumns(trackSize); | |
| 2975 return; | |
| 2976 } | |
| 2977 case CSSPropertyWebkitGridAutoRows: { | |
| 2978 GridTrackSize trackSize; | |
| 2979 if (!createGridTrackSize(value, trackSize, state)) | |
| 2980 return; | |
| 2981 state.style()->setGridAutoRows(trackSize); | |
| 2982 return; | |
| 2983 } | |
| 2984 case CSSPropertyWebkitGridColumns: { | |
| 2985 Vector<GridTrackSize> trackSizes; | |
| 2986 NamedGridLinesMap namedGridLines; | |
| 2987 if (!createGridTrackList(value, trackSizes, namedGridLines, state)) | |
| 2988 return; | |
| 2989 state.style()->setGridColumns(trackSizes); | |
| 2990 state.style()->setNamedGridColumnLines(namedGridLines); | |
| 2991 return; | |
| 2992 } | |
| 2993 case CSSPropertyWebkitGridRows: { | |
| 2994 Vector<GridTrackSize> trackSizes; | |
| 2995 NamedGridLinesMap namedGridLines; | |
| 2996 if (!createGridTrackList(value, trackSizes, namedGridLines, state)) | |
| 2997 return; | |
| 2998 state.style()->setGridRows(trackSizes); | |
| 2999 state.style()->setNamedGridRowLines(namedGridLines); | |
| 3000 return; | |
| 3001 } | |
| 3002 | |
| 3003 case CSSPropertyWebkitGridStart: { | |
| 3004 HANDLE_INHERIT_AND_INITIAL(gridStart, GridStart); | |
| 3005 GridPosition startPosition; | |
| 3006 if (!createGridPosition(value, startPosition)) | |
| 3007 return; | |
| 3008 state.style()->setGridStart(startPosition); | |
| 3009 return; | |
| 3010 } | |
| 3011 case CSSPropertyWebkitGridEnd: { | |
| 3012 HANDLE_INHERIT_AND_INITIAL(gridEnd, GridEnd); | |
| 3013 GridPosition endPosition; | |
| 3014 if (!createGridPosition(value, endPosition)) | |
| 3015 return; | |
| 3016 state.style()->setGridEnd(endPosition); | |
| 3017 return; | |
| 3018 } | |
| 3019 | |
| 3020 case CSSPropertyWebkitGridBefore: { | |
| 3021 HANDLE_INHERIT_AND_INITIAL(gridBefore, GridBefore); | |
| 3022 GridPosition beforePosition; | |
| 3023 if (!createGridPosition(value, beforePosition)) | |
| 3024 return; | |
| 3025 state.style()->setGridBefore(beforePosition); | |
| 3026 return; | |
| 3027 } | |
| 3028 case CSSPropertyWebkitGridAfter: { | |
| 3029 HANDLE_INHERIT_AND_INITIAL(gridAfter, GridAfter); | |
| 3030 GridPosition afterPosition; | |
| 3031 if (!createGridPosition(value, afterPosition)) | |
| 3032 return; | |
| 3033 state.style()->setGridAfter(afterPosition); | |
| 3034 return; | |
| 3035 } | |
| 3036 | |
| 3037 // These properties are aliased and DeprecatedStyleBuilder already applied t
he property on the prefixed version. | |
| 3038 case CSSPropertyTransitionDelay: | |
| 3039 case CSSPropertyTransitionDuration: | |
| 3040 case CSSPropertyTransitionProperty: | |
| 3041 case CSSPropertyTransitionTimingFunction: | |
| 3042 return; | |
| 3043 // These properties are implemented in the DeprecatedStyleBuilder lookup tab
le. | |
| 3044 case CSSPropertyBackgroundAttachment: | |
| 3045 case CSSPropertyBackgroundBlendMode: | |
| 3046 case CSSPropertyBackgroundClip: | |
| 3047 case CSSPropertyBackgroundColor: | |
| 3048 case CSSPropertyBackgroundImage: | |
| 3049 case CSSPropertyBackgroundOrigin: | |
| 3050 case CSSPropertyBackgroundPositionX: | |
| 3051 case CSSPropertyBackgroundPositionY: | |
| 3052 case CSSPropertyBackgroundRepeatX: | |
| 3053 case CSSPropertyBackgroundRepeatY: | |
| 3054 case CSSPropertyBackgroundSize: | |
| 3055 case CSSPropertyBorderBottomColor: | |
| 3056 case CSSPropertyBorderBottomLeftRadius: | |
| 3057 case CSSPropertyBorderBottomRightRadius: | |
| 3058 case CSSPropertyBorderBottomStyle: | |
| 3059 case CSSPropertyBorderBottomWidth: | |
| 3060 case CSSPropertyBorderCollapse: | |
| 3061 case CSSPropertyBorderImageOutset: | |
| 3062 case CSSPropertyBorderImageRepeat: | |
| 3063 case CSSPropertyBorderImageSlice: | |
| 3064 case CSSPropertyBorderImageSource: | |
| 3065 case CSSPropertyBorderImageWidth: | |
| 3066 case CSSPropertyBorderLeftColor: | |
| 3067 case CSSPropertyBorderLeftStyle: | |
| 3068 case CSSPropertyBorderLeftWidth: | |
| 3069 case CSSPropertyBorderRightColor: | |
| 3070 case CSSPropertyBorderRightStyle: | |
| 3071 case CSSPropertyBorderRightWidth: | |
| 3072 case CSSPropertyBorderTopColor: | |
| 3073 case CSSPropertyBorderTopLeftRadius: | |
| 3074 case CSSPropertyBorderTopRightRadius: | |
| 3075 case CSSPropertyBorderTopStyle: | |
| 3076 case CSSPropertyBorderTopWidth: | |
| 3077 case CSSPropertyBottom: | |
| 3078 case CSSPropertyBoxSizing: | |
| 3079 case CSSPropertyCaptionSide: | |
| 3080 case CSSPropertyClear: | |
| 3081 case CSSPropertyClip: | |
| 3082 case CSSPropertyColor: | |
| 3083 case CSSPropertyCounterIncrement: | |
| 3084 case CSSPropertyCounterReset: | |
| 3085 case CSSPropertyCursor: | |
| 3086 case CSSPropertyDirection: | |
| 3087 case CSSPropertyDisplay: | |
| 3088 case CSSPropertyEmptyCells: | |
| 3089 case CSSPropertyFloat: | |
| 3090 case CSSPropertyFontSize: | |
| 3091 case CSSPropertyFontStyle: | |
| 3092 case CSSPropertyFontVariant: | |
| 3093 case CSSPropertyFontWeight: | |
| 3094 case CSSPropertyHeight: | |
| 3095 case CSSPropertyImageRendering: | |
| 3096 case CSSPropertyLeft: | |
| 3097 case CSSPropertyLetterSpacing: | |
| 3098 case CSSPropertyLineHeight: | |
| 3099 case CSSPropertyListStyleImage: | |
| 3100 case CSSPropertyListStylePosition: | |
| 3101 case CSSPropertyListStyleType: | |
| 3102 case CSSPropertyMarginBottom: | |
| 3103 case CSSPropertyMarginLeft: | |
| 3104 case CSSPropertyMarginRight: | |
| 3105 case CSSPropertyMarginTop: | |
| 3106 case CSSPropertyMaxHeight: | |
| 3107 case CSSPropertyMaxWidth: | |
| 3108 case CSSPropertyMinHeight: | |
| 3109 case CSSPropertyMixBlendMode: | |
| 3110 case CSSPropertyMinWidth: | |
| 3111 case CSSPropertyOpacity: | |
| 3112 case CSSPropertyOrphans: | |
| 3113 case CSSPropertyOutlineColor: | |
| 3114 case CSSPropertyOutlineOffset: | |
| 3115 case CSSPropertyOutlineStyle: | |
| 3116 case CSSPropertyOutlineWidth: | |
| 3117 case CSSPropertyOverflowWrap: | |
| 3118 case CSSPropertyOverflowX: | |
| 3119 case CSSPropertyOverflowY: | |
| 3120 case CSSPropertyPaddingBottom: | |
| 3121 case CSSPropertyPaddingLeft: | |
| 3122 case CSSPropertyPaddingRight: | |
| 3123 case CSSPropertyPaddingTop: | |
| 3124 case CSSPropertyPageBreakAfter: | |
| 3125 case CSSPropertyPageBreakBefore: | |
| 3126 case CSSPropertyPageBreakInside: | |
| 3127 case CSSPropertyPointerEvents: | |
| 3128 case CSSPropertyPosition: | |
| 3129 case CSSPropertyResize: | |
| 3130 case CSSPropertyRight: | |
| 3131 case CSSPropertySize: | |
| 3132 case CSSPropertySpeak: | |
| 3133 case CSSPropertyTabSize: | |
| 3134 case CSSPropertyTableLayout: | |
| 3135 case CSSPropertyTextAlign: | |
| 3136 case CSSPropertyTextDecoration: | |
| 3137 case CSSPropertyTextIndent: | |
| 3138 case CSSPropertyTextOverflow: | |
| 3139 case CSSPropertyTextRendering: | |
| 3140 case CSSPropertyTextTransform: | |
| 3141 case CSSPropertyTop: | |
| 3142 case CSSPropertyUnicodeBidi: | |
| 3143 case CSSPropertyVariable: | |
| 3144 case CSSPropertyVerticalAlign: | |
| 3145 case CSSPropertyVisibility: | |
| 3146 case CSSPropertyWebkitAnimationDelay: | |
| 3147 case CSSPropertyWebkitAnimationDirection: | |
| 3148 case CSSPropertyWebkitAnimationDuration: | |
| 3149 case CSSPropertyWebkitAnimationFillMode: | |
| 3150 case CSSPropertyWebkitAnimationIterationCount: | |
| 3151 case CSSPropertyWebkitAnimationName: | |
| 3152 case CSSPropertyWebkitAnimationPlayState: | |
| 3153 case CSSPropertyWebkitAnimationTimingFunction: | |
| 3154 case CSSPropertyWebkitAppearance: | |
| 3155 case CSSPropertyWebkitAspectRatio: | |
| 3156 case CSSPropertyWebkitBackfaceVisibility: | |
| 3157 case CSSPropertyWebkitBackgroundClip: | |
| 3158 case CSSPropertyWebkitBackgroundComposite: | |
| 3159 case CSSPropertyWebkitBackgroundOrigin: | |
| 3160 case CSSPropertyWebkitBackgroundSize: | |
| 3161 case CSSPropertyWebkitBorderFit: | |
| 3162 case CSSPropertyWebkitBorderHorizontalSpacing: | |
| 3163 case CSSPropertyWebkitBorderImage: | |
| 3164 case CSSPropertyWebkitBorderVerticalSpacing: | |
| 3165 case CSSPropertyWebkitBoxAlign: | |
| 3166 case CSSPropertyWebkitBoxDecorationBreak: | |
| 3167 case CSSPropertyWebkitBoxDirection: | |
| 3168 case CSSPropertyWebkitBoxFlex: | |
| 3169 case CSSPropertyWebkitBoxFlexGroup: | |
| 3170 case CSSPropertyWebkitBoxLines: | |
| 3171 case CSSPropertyWebkitBoxOrdinalGroup: | |
| 3172 case CSSPropertyWebkitBoxOrient: | |
| 3173 case CSSPropertyWebkitBoxPack: | |
| 3174 case CSSPropertyWebkitColorCorrection: | |
| 3175 case CSSPropertyWebkitColumnAxis: | |
| 3176 case CSSPropertyWebkitColumnBreakAfter: | |
| 3177 case CSSPropertyWebkitColumnBreakBefore: | |
| 3178 case CSSPropertyWebkitColumnBreakInside: | |
| 3179 case CSSPropertyWebkitColumnCount: | |
| 3180 case CSSPropertyWebkitColumnGap: | |
| 3181 case CSSPropertyWebkitColumnProgression: | |
| 3182 case CSSPropertyWebkitColumnRuleColor: | |
| 3183 case CSSPropertyWebkitColumnRuleStyle: | |
| 3184 case CSSPropertyWebkitColumnRuleWidth: | |
| 3185 case CSSPropertyWebkitColumnSpan: | |
| 3186 case CSSPropertyWebkitColumnWidth: | |
| 3187 case CSSPropertyWebkitAlignContent: | |
| 3188 case CSSPropertyWebkitAlignItems: | |
| 3189 case CSSPropertyWebkitAlignSelf: | |
| 3190 case CSSPropertyWebkitFlexBasis: | |
| 3191 case CSSPropertyWebkitFlexDirection: | |
| 3192 case CSSPropertyWebkitFlexGrow: | |
| 3193 case CSSPropertyWebkitFlexShrink: | |
| 3194 case CSSPropertyWebkitFlexWrap: | |
| 3195 case CSSPropertyWebkitJustifyContent: | |
| 3196 case CSSPropertyWebkitOrder: | |
| 3197 case CSSPropertyWebkitFlowFrom: | |
| 3198 case CSSPropertyWebkitFlowInto: | |
| 3199 case CSSPropertyWebkitFontKerning: | |
| 3200 case CSSPropertyWebkitFontSmoothing: | |
| 3201 case CSSPropertyWebkitFontVariantLigatures: | |
| 3202 case CSSPropertyWebkitHighlight: | |
| 3203 case CSSPropertyWebkitHyphenateCharacter: | |
| 3204 case CSSPropertyWebkitHyphenateLimitAfter: | |
| 3205 case CSSPropertyWebkitHyphenateLimitBefore: | |
| 3206 case CSSPropertyWebkitHyphenateLimitLines: | |
| 3207 case CSSPropertyWebkitHyphens: | |
| 3208 case CSSPropertyWebkitLineAlign: | |
| 3209 case CSSPropertyWebkitLineBreak: | |
| 3210 case CSSPropertyWebkitLineClamp: | |
| 3211 case CSSPropertyWebkitLineGrid: | |
| 3212 case CSSPropertyWebkitLineSnap: | |
| 3213 case CSSPropertyWebkitMarqueeDirection: | |
| 3214 case CSSPropertyWebkitMarqueeIncrement: | |
| 3215 case CSSPropertyWebkitMarqueeRepetition: | |
| 3216 case CSSPropertyWebkitMarqueeSpeed: | |
| 3217 case CSSPropertyWebkitMarqueeStyle: | |
| 3218 case CSSPropertyWebkitMaskBoxImage: | |
| 3219 case CSSPropertyWebkitMaskBoxImageOutset: | |
| 3220 case CSSPropertyWebkitMaskBoxImageRepeat: | |
| 3221 case CSSPropertyWebkitMaskBoxImageSlice: | |
| 3222 case CSSPropertyWebkitMaskBoxImageSource: | |
| 3223 case CSSPropertyWebkitMaskBoxImageWidth: | |
| 3224 case CSSPropertyWebkitMaskClip: | |
| 3225 case CSSPropertyWebkitMaskComposite: | |
| 3226 case CSSPropertyWebkitMaskImage: | |
| 3227 case CSSPropertyWebkitMaskOrigin: | |
| 3228 case CSSPropertyWebkitMaskPositionX: | |
| 3229 case CSSPropertyWebkitMaskPositionY: | |
| 3230 case CSSPropertyWebkitMaskRepeatX: | |
| 3231 case CSSPropertyWebkitMaskRepeatY: | |
| 3232 case CSSPropertyWebkitMaskSize: | |
| 3233 case CSSPropertyWebkitPerspectiveOrigin: | |
| 3234 case CSSPropertyWebkitPerspectiveOriginX: | |
| 3235 case CSSPropertyWebkitPerspectiveOriginY: | |
| 3236 case CSSPropertyWebkitPrintColorAdjust: | |
| 3237 case CSSPropertyWebkitRegionBreakAfter: | |
| 3238 case CSSPropertyWebkitRegionBreakBefore: | |
| 3239 case CSSPropertyWebkitRegionBreakInside: | |
| 3240 case CSSPropertyWebkitRegionOverflow: | |
| 3241 case CSSPropertyWebkitRtlOrdering: | |
| 3242 case CSSPropertyWebkitRubyPosition: | |
| 3243 case CSSPropertyWebkitTextCombine: | |
| 3244 #if ENABLE(CSS3_TEXT) | |
| 3245 case CSSPropertyWebkitTextDecorationLine: | |
| 3246 case CSSPropertyWebkitTextDecorationStyle: | |
| 3247 case CSSPropertyWebkitTextDecorationColor: | |
| 3248 case CSSPropertyWebkitTextAlignLast: | |
| 3249 case CSSPropertyWebkitTextUnderlinePosition: | |
| 3250 #endif // CSS3_TEXT | |
| 3251 case CSSPropertyWebkitTextEmphasisColor: | |
| 3252 case CSSPropertyWebkitTextEmphasisPosition: | |
| 3253 case CSSPropertyWebkitTextEmphasisStyle: | |
| 3254 case CSSPropertyWebkitTextFillColor: | |
| 3255 case CSSPropertyWebkitTextSecurity: | |
| 3256 case CSSPropertyWebkitTextStrokeColor: | |
| 3257 case CSSPropertyWebkitTransformOriginX: | |
| 3258 case CSSPropertyWebkitTransformOriginY: | |
| 3259 case CSSPropertyWebkitTransformOriginZ: | |
| 3260 case CSSPropertyWebkitTransformStyle: | |
| 3261 case CSSPropertyWebkitTransitionDelay: | |
| 3262 case CSSPropertyWebkitTransitionDuration: | |
| 3263 case CSSPropertyWebkitTransitionProperty: | |
| 3264 case CSSPropertyWebkitTransitionTimingFunction: | |
| 3265 case CSSPropertyWebkitUserDrag: | |
| 3266 case CSSPropertyWebkitUserModify: | |
| 3267 case CSSPropertyWebkitUserSelect: | |
| 3268 case CSSPropertyWebkitClipPath: | |
| 3269 case CSSPropertyWebkitWrapFlow: | |
| 3270 case CSSPropertyWebkitShapeMargin: | |
| 3271 case CSSPropertyWebkitShapePadding: | |
| 3272 case CSSPropertyWebkitWrapThrough: | |
| 3273 case CSSPropertyWebkitShapeInside: | |
| 3274 case CSSPropertyWebkitShapeOutside: | |
| 3275 case CSSPropertyWhiteSpace: | |
| 3276 case CSSPropertyWidows: | |
| 3277 case CSSPropertyWidth: | |
| 3278 case CSSPropertyWordBreak: | |
| 3279 case CSSPropertyWordSpacing: | |
| 3280 case CSSPropertyWordWrap: | |
| 3281 case CSSPropertyZIndex: | |
| 3282 case CSSPropertyZoom: | |
| 3283 #if ENABLE(CSS_DEVICE_ADAPTATION) | |
| 3284 case CSSPropertyMaxZoom: | |
| 3285 case CSSPropertyMinZoom: | |
| 3286 case CSSPropertyOrientation: | |
| 3287 case CSSPropertyUserZoom: | |
| 3288 #endif | |
| 3289 ASSERT_NOT_REACHED(); | |
| 3290 return; | |
| 3291 default: | |
| 3292 #if ENABLE(SVG) | |
| 3293 // Try the SVG properties | |
| 3294 applySVGProperty(id, value); | |
| 3295 #endif | |
| 3296 return; | |
| 3297 } | |
| 3298 } | |
| 3299 | |
| 3300 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValu
e* value) | |
| 3301 { | |
| 3302 if (value->isImageValue()) | |
| 3303 return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(va
lue)); | |
| 3304 | |
| 3305 if (value->isImageGeneratorValue()) { | |
| 3306 if (value->isGradientValue()) | |
| 3307 return generatedOrPendingFromValue(property, static_cast<CSSGradient
Value*>(value)->gradientWithStylesResolved(this).get()); | |
| 3308 return generatedOrPendingFromValue(property, static_cast<CSSImageGenerat
orValue*>(value)); | |
| 3309 } | |
| 3310 | |
| 3311 if (value->isImageSetValue()) | |
| 3312 return setOrPendingFromValue(property, static_cast<CSSImageSetValue*>(va
lue)); | |
| 3313 | |
| 3314 if (value->isCursorImageValue()) | |
| 3315 return cursorOrPendingFromValue(property, static_cast<CSSCursorImageValu
e*>(value)); | |
| 3316 | |
| 3317 return 0; | |
| 3318 } | |
| 3319 | |
| 3320 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID pro
perty, CSSImageValue* value) | |
| 3321 { | |
| 3322 RefPtr<StyleImage> image = value->cachedOrPendingImage(); | |
| 3323 if (image && image->isPendingImage()) | |
| 3324 m_state.pendingImageProperties().set(property, value); | |
| 3325 return image.release(); | |
| 3326 } | |
| 3327 | |
| 3328 PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID
property, CSSImageGeneratorValue* value) | |
| 3329 { | |
| 3330 if (value->isPending()) { | |
| 3331 m_state.pendingImageProperties().set(property, value); | |
| 3332 return StylePendingImage::create(value); | |
| 3333 } | |
| 3334 return StyleGeneratedImage::create(value); | |
| 3335 } | |
| 3336 | |
| 3337 PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID proper
ty, CSSImageSetValue* value) | |
| 3338 { | |
| 3339 RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document()); | |
| 3340 if (image && image->isPendingImage()) | |
| 3341 m_state.pendingImageProperties().set(property, value); | |
| 3342 return image.release(); | |
| 3343 } | |
| 3344 | |
| 3345 PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID pro
perty, CSSCursorImageValue* value) | |
| 3346 { | |
| 3347 RefPtr<StyleImage> image = value->cachedOrPendingImage(document()); | |
| 3348 if (image && image->isPendingImage()) | |
| 3349 m_state.pendingImageProperties().set(property, value); | |
| 3350 return image.release(); | |
| 3351 } | |
| 3352 | |
| 3353 void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentSt
yle) | |
| 3354 { | |
| 3355 if (style->effectiveZoom() == parentStyle->effectiveZoom()) | |
| 3356 return; | |
| 3357 | |
| 3358 const FontDescription& childFont = style->fontDescription(); | |
| 3359 FontDescription newFontDescription(childFont); | |
| 3360 setFontSize(newFontDescription, childFont.specifiedSize()); | |
| 3361 style->setFontDescription(newFontDescription); | |
| 3362 } | |
| 3363 | |
| 3364 void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle*
parentStyle) | |
| 3365 { | |
| 3366 const FontDescription& childFont = style->fontDescription(); | |
| 3367 | |
| 3368 if (childFont.isAbsoluteSize() || !parentStyle) | |
| 3369 return; | |
| 3370 | |
| 3371 const FontDescription& parentFont = parentStyle->fontDescription(); | |
| 3372 if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize()) | |
| 3373 return; | |
| 3374 | |
| 3375 // For now, lump all families but monospace together. | |
| 3376 if (childFont.genericFamily() != FontDescription::MonospaceFamily | |
| 3377 && parentFont.genericFamily() != FontDescription::MonospaceFamily) | |
| 3378 return; | |
| 3379 | |
| 3380 // We know the parent is monospace or the child is monospace, and that font | |
| 3381 // size was unspecified. We want to scale our font size as appropriate. | |
| 3382 // If the font uses a keyword size, then we refetch from the table rather th
an | |
| 3383 // multiplying by our scale factor. | |
| 3384 float size; | |
| 3385 if (childFont.keywordSize()) | |
| 3386 size = fontSizeForKeyword(document(), CSSValueXxSmall + childFont.keywor
dSize() - 1, childFont.useFixedDefaultSize()); | |
| 3387 else { | |
| 3388 Settings* settings = documentSettings(); | |
| 3389 float fixedScaleFactor = (settings && settings->defaultFixedFontSize() &
& settings->defaultFontSize()) | |
| 3390 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->d
efaultFontSize() | |
| 3391 : 1; | |
| 3392 size = parentFont.useFixedDefaultSize() ? | |
| 3393 childFont.specifiedSize() / fixedScaleFactor : | |
| 3394 childFont.specifiedSize() * fixedScaleFactor; | |
| 3395 } | |
| 3396 | |
| 3397 FontDescription newFontDescription(childFont); | |
| 3398 setFontSize(newFontDescription, size); | |
| 3399 style->setFontDescription(newFontDescription); | |
| 3400 } | |
| 3401 | |
| 3402 void StyleResolver::initializeFontStyle(Settings* settings) | |
| 3403 { | |
| 3404 FontDescription fontDescription; | |
| 3405 fontDescription.setGenericFamily(FontDescription::StandardFamily); | |
| 3406 fontDescription.setRenderingMode(settings->fontRenderingMode()); | |
| 3407 fontDescription.setUsePrinterFont(document()->printing()); | |
| 3408 const AtomicString& standardFontFamily = documentSettings()->standardFontFam
ily(); | |
| 3409 if (!standardFontFamily.isEmpty()) { | |
| 3410 fontDescription.firstFamily().setFamily(standardFontFamily); | |
| 3411 fontDescription.firstFamily().appendFamily(0); | |
| 3412 } | |
| 3413 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); | |
| 3414 setFontSize(fontDescription, fontSizeForKeyword(document(), CSSValueMedium,
false)); | |
| 3415 m_state.style()->setLineHeight(RenderStyle::initialLineHeight()); | |
| 3416 m_state.setLineHeightValue(0); | |
| 3417 setFontDescription(fontDescription); | |
| 3418 } | |
| 3419 | |
| 3420 void StyleResolver::setFontSize(FontDescription& fontDescription, float size) | |
| 3421 { | |
| 3422 fontDescription.setSpecifiedSize(size); | |
| 3423 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(document(),
m_state.style(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules())); | |
| 3424 } | |
| 3425 | |
| 3426 float StyleResolver::getComputedSizeFromSpecifiedSize(Document* document, Render
Style* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules) | |
| 3427 { | |
| 3428 float zoomFactor = 1.0f; | |
| 3429 if (!useSVGZoomRules) { | |
| 3430 zoomFactor = style->effectiveZoom(); | |
| 3431 if (Frame* frame = document->frame()) | |
| 3432 zoomFactor *= frame->textZoomFactor(); | |
| 3433 } | |
| 3434 | |
| 3435 return StyleResolver::getComputedSizeFromSpecifiedSize(document, zoomFactor,
isAbsoluteSize, specifiedSize); | |
| 3436 } | |
| 3437 | |
| 3438 float StyleResolver::getComputedSizeFromSpecifiedSize(Document* document, float
zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize u
seSmartMinimumForFontSize) | |
| 3439 { | |
| 3440 // Text with a 0px font size should not be visible and therefore needs to be | |
| 3441 // exempt from minimum font size rules. Acid3 relies on this for pixel-perfe
ct | |
| 3442 // rendering. This is also compatible with other browsers that have minimum | |
| 3443 // font size settings (e.g. Firefox). | |
| 3444 if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon()) | |
| 3445 return 0.0f; | |
| 3446 | |
| 3447 // We support two types of minimum font size. The first is a hard override t
hat applies to | |
| 3448 // all fonts. This is "minSize." The second type of minimum font size is a "
smart minimum" | |
| 3449 // that is applied only when the Web page can't know what size it really ask
ed for, e.g., | |
| 3450 // when it uses logical sizes like "small" or expresses the font-size as a p
ercentage of | |
| 3451 // the user's default font setting. | |
| 3452 | |
| 3453 // With the smart minimum, we never want to get smaller than the minimum fon
t size to keep fonts readable. | |
| 3454 // However we always allow the page to set an explicit pixel size that is sm
aller, | |
| 3455 // since sites will mis-render otherwise (e.g., http://www.gamespot.com with
a 9px minimum). | |
| 3456 | |
| 3457 Settings* settings = document->settings(); | |
| 3458 if (!settings) | |
| 3459 return 1.0f; | |
| 3460 | |
| 3461 int minSize = settings->minimumFontSize(); | |
| 3462 int minLogicalSize = settings->minimumLogicalFontSize(); | |
| 3463 float zoomedSize = specifiedSize * zoomFactor; | |
| 3464 | |
| 3465 // Apply the hard minimum first. We only apply the hard minimum if after zoo
ming we're still too small. | |
| 3466 if (zoomedSize < minSize) | |
| 3467 zoomedSize = minSize; | |
| 3468 | |
| 3469 // Now apply the "smart minimum." This minimum is also only applied if we're
still too small | |
| 3470 // after zooming. The font size must either be relative to the user default
or the original size | |
| 3471 // must have been acceptable. In other words, we only apply the smart minimu
m whenever we're positive | |
| 3472 // doing so won't disrupt the layout. | |
| 3473 if (useSmartMinimumForFontSize && zoomedSize < minLogicalSize && (specifiedS
ize >= minLogicalSize || !isAbsoluteSize)) | |
| 3474 zoomedSize = minLogicalSize; | |
| 3475 | |
| 3476 // Also clamp to a reasonable maximum to prevent insane font sizes from caus
ing crashes on various | |
| 3477 // platforms (I'm looking at you, Windows.) | |
| 3478 return min(maximumAllowedFontSize, zoomedSize); | |
| 3479 } | |
| 3480 | |
| 3481 const int fontSizeTableMax = 16; | |
| 3482 const int fontSizeTableMin = 9; | |
| 3483 const int totalKeywords = 8; | |
| 3484 | |
| 3485 // WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping sy
stem of HTML. | |
| 3486 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][to
talKeywords] = | |
| 3487 { | |
| 3488 { 9, 9, 9, 9, 11, 14, 18, 28 }, | |
| 3489 { 9, 9, 9, 10, 12, 15, 20, 31 }, | |
| 3490 { 9, 9, 9, 11, 13, 17, 22, 34 }, | |
| 3491 { 9, 9, 10, 12, 14, 18, 24, 37 }, | |
| 3492 { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font defau
lt (13) | |
| 3493 { 9, 9, 11, 14, 17, 21, 28, 42 }, | |
| 3494 { 9, 10, 12, 15, 17, 23, 30, 45 }, | |
| 3495 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font
default (16) | |
| 3496 }; | |
| 3497 // HTML 1 2 3 4 5 6 7 | |
| 3498 // CSS xxs xs s m l xl xxl | |
| 3499 // | | |
| 3500 // user pref | |
| 3501 | |
| 3502 // Strict mode table matches MacIE and Mozilla's settings exactly. | |
| 3503 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][to
talKeywords] = | |
| 3504 { | |
| 3505 { 9, 9, 9, 9, 11, 14, 18, 27 }, | |
| 3506 { 9, 9, 9, 10, 12, 15, 20, 30 }, | |
| 3507 { 9, 9, 10, 11, 13, 17, 22, 33 }, | |
| 3508 { 9, 9, 10, 12, 14, 18, 24, 36 }, | |
| 3509 { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font defau
lt (13) | |
| 3510 { 9, 10, 12, 14, 17, 21, 28, 42 }, | |
| 3511 { 9, 10, 13, 15, 18, 23, 30, 45 }, | |
| 3512 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font
default (16) | |
| 3513 }; | |
| 3514 // HTML 1 2 3 4 5 6 7 | |
| 3515 // CSS xxs xs s m l xl xxl | |
| 3516 // | | |
| 3517 // user pref | |
| 3518 | |
| 3519 // For values outside the range of the table, we use Todd Fahrner's suggested sc
ale | |
| 3520 // factors for each keyword value. | |
| 3521 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f,
1.2f, 1.5f, 2.0f, 3.0f }; | |
| 3522 | |
| 3523 float StyleResolver::fontSizeForKeyword(Document* document, int keyword, bool sh
ouldUseFixedDefaultSize) | |
| 3524 { | |
| 3525 Settings* settings = document->settings(); | |
| 3526 if (!settings) | |
| 3527 return 1.0f; | |
| 3528 | |
| 3529 bool quirksMode = document->inQuirksMode(); | |
| 3530 int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize(
) : settings->defaultFontSize(); | |
| 3531 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { | |
| 3532 // Look up the entry in the table. | |
| 3533 int row = mediumSize - fontSizeTableMin; | |
| 3534 int col = (keyword - CSSValueXxSmall); | |
| 3535 return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[
row][col]; | |
| 3536 } | |
| 3537 | |
| 3538 // Value is outside the range of the table. Apply the scale factor instead. | |
| 3539 float minLogicalSize = max(settings->minimumLogicalFontSize(), 1); | |
| 3540 return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogical
Size); | |
| 3541 } | |
| 3542 | |
| 3543 template<typename T> | |
| 3544 static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int mult
iplier) | |
| 3545 { | |
| 3546 // Ignore table[0] because xx-small does not correspond to any legacy font s
ize. | |
| 3547 for (int i = 1; i < totalKeywords - 1; i++) { | |
| 3548 if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier) | |
| 3549 return i; | |
| 3550 } | |
| 3551 return totalKeywords - 1; | |
| 3552 } | |
| 3553 | |
| 3554 int StyleResolver::legacyFontSize(Document* document, int pixelFontSize, bool sh
ouldUseFixedDefaultSize) | |
| 3555 { | |
| 3556 Settings* settings = document->settings(); | |
| 3557 if (!settings) | |
| 3558 return 1; | |
| 3559 | |
| 3560 bool quirksMode = document->inQuirksMode(); | |
| 3561 int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize(
) : settings->defaultFontSize(); | |
| 3562 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { | |
| 3563 int row = mediumSize - fontSizeTableMin; | |
| 3564 return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirks
FontSizeTable[row] : strictFontSizeTable[row], 1); | |
| 3565 } | |
| 3566 | |
| 3567 return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, medi
umSize); | |
| 3568 } | |
| 3569 | |
| 3570 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValu
e* value) | |
| 3571 { | |
| 3572 int ident = value->getIdent(); | |
| 3573 switch (ident) { | |
| 3574 case CSSValueWebkitText: | |
| 3575 case CSSValueWebkitLink: | |
| 3576 case CSSValueWebkitActivelink: | |
| 3577 case CSSValueCurrentcolor: | |
| 3578 return true; | |
| 3579 default: | |
| 3580 return false; | |
| 3581 } | |
| 3582 } | |
| 3583 | |
| 3584 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* ex
pr, bool result) | |
| 3585 { | |
| 3586 m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*e
xpr, result))); | |
| 3587 } | |
| 3588 | |
| 3589 bool StyleResolver::affectedByViewportChange() const | |
| 3590 { | |
| 3591 unsigned s = m_viewportDependentMediaQueryResults.size(); | |
| 3592 for (unsigned i = 0; i < s; i++) { | |
| 3593 if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expressio
n) != m_viewportDependentMediaQueryResults[i]->m_result) | |
| 3594 return true; | |
| 3595 } | |
| 3596 return false; | |
| 3597 } | |
| 3598 | |
| 3599 #if ENABLE(SVG) | |
| 3600 void StyleResolver::loadPendingSVGDocuments() | |
| 3601 { | |
| 3602 StyleResolverState& state = m_state; | |
| 3603 if (!state.style()->hasFilter() || state.pendingSVGDocuments().isEmpty()) | |
| 3604 return; | |
| 3605 | |
| 3606 CachedResourceLoader* cachedResourceLoader = state.document()->cachedResourc
eLoader(); | |
| 3607 Vector<RefPtr<FilterOperation> >& filterOperations = state.style()->mutableF
ilter().operations(); | |
| 3608 for (unsigned i = 0; i < filterOperations.size(); ++i) { | |
| 3609 RefPtr<FilterOperation> filterOperation = filterOperations.at(i); | |
| 3610 if (filterOperation->getOperationType() == FilterOperation::REFERENCE) { | |
| 3611 ReferenceFilterOperation* referenceFilter = static_cast<ReferenceFil
terOperation*>(filterOperation.get()); | |
| 3612 | |
| 3613 WebKitCSSSVGDocumentValue* value = state.pendingSVGDocuments().get(r
eferenceFilter); | |
| 3614 if (!value) | |
| 3615 continue; | |
| 3616 CachedSVGDocument* cachedDocument = value->load(cachedResourceLoader
); | |
| 3617 if (!cachedDocument) | |
| 3618 continue; | |
| 3619 | |
| 3620 // Stash the CachedSVGDocument on the reference filter. | |
| 3621 referenceFilter->setCachedSVGDocumentReference(adoptPtr(new CachedSV
GDocumentReference(cachedDocument))); | |
| 3622 } | |
| 3623 } | |
| 3624 state.pendingSVGDocuments().clear(); | |
| 3625 } | |
| 3626 #endif | |
| 3627 | |
| 3628 void StyleResolver::loadPendingShaders() | |
| 3629 { | |
| 3630 if (!m_state.style()->hasFilter() || !m_state.hasPendingShaders()) | |
| 3631 return; | |
| 3632 | |
| 3633 CachedResourceLoader* cachedResourceLoader = m_state.document()->cachedResou
rceLoader(); | |
| 3634 | |
| 3635 Vector<RefPtr<FilterOperation> >& filterOperations = m_state.style()->mutabl
eFilter().operations(); | |
| 3636 for (unsigned i = 0; i < filterOperations.size(); ++i) { | |
| 3637 RefPtr<FilterOperation> filterOperation = filterOperations.at(i); | |
| 3638 if (filterOperation->getOperationType() == FilterOperation::CUSTOM) { | |
| 3639 CustomFilterOperation* customFilter = static_cast<CustomFilterOperat
ion*>(filterOperation.get()); | |
| 3640 ASSERT(customFilter->program()); | |
| 3641 StyleCustomFilterProgram* program = static_cast<StyleCustomFilterPro
gram*>(customFilter->program()); | |
| 3642 // Note that the StylePendingShaders could be already resolved to St
yleCachedShaders. That's because the rule was matched before. | |
| 3643 // However, the StyleCustomFilterProgram that was initially created
could have been removed from the cache in the meanwhile, | |
| 3644 // meaning that we get a new StyleCustomFilterProgram here that is n
ot yet in the cache, but already has loaded StyleShaders. | |
| 3645 if (!program->hasPendingShaders() && program->inCache()) | |
| 3646 continue; | |
| 3647 if (!m_customFilterProgramCache) | |
| 3648 m_customFilterProgramCache = adoptPtr(new StyleCustomFilterProgr
amCache()); | |
| 3649 RefPtr<StyleCustomFilterProgram> styleProgram = m_customFilterProgra
mCache->lookup(program); | |
| 3650 if (styleProgram.get()) | |
| 3651 customFilter->setProgram(styleProgram.release()); | |
| 3652 else { | |
| 3653 if (program->vertexShader() && program->vertexShader()->isPendin
gShader()) { | |
| 3654 WebKitCSSShaderValue* shaderValue = static_cast<StylePending
Shader*>(program->vertexShader())->cssShaderValue(); | |
| 3655 program->setVertexShader(shaderValue->cachedShader(cachedRes
ourceLoader)); | |
| 3656 } | |
| 3657 if (program->fragmentShader() && program->fragmentShader()->isPe
ndingShader()) { | |
| 3658 WebKitCSSShaderValue* shaderValue = static_cast<StylePending
Shader*>(program->fragmentShader())->cssShaderValue(); | |
| 3659 program->setFragmentShader(shaderValue->cachedShader(cachedR
esourceLoader)); | |
| 3660 } | |
| 3661 m_customFilterProgramCache->add(program); | |
| 3662 } | |
| 3663 } | |
| 3664 } | |
| 3665 m_state.setHasPendingShaders(false); | |
| 3666 } | |
| 3667 | |
| 3668 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendin
gImage) | |
| 3669 { | |
| 3670 CachedResourceLoader* cachedResourceLoader = m_state.document()->cachedResou
rceLoader(); | |
| 3671 | |
| 3672 if (pendingImage->cssImageValue()) { | |
| 3673 CSSImageValue* imageValue = pendingImage->cssImageValue(); | |
| 3674 return imageValue->cachedImage(cachedResourceLoader); | |
| 3675 } | |
| 3676 | |
| 3677 if (pendingImage->cssImageGeneratorValue()) { | |
| 3678 CSSImageGeneratorValue* imageGeneratorValue = pendingImage->cssImageGene
ratorValue(); | |
| 3679 imageGeneratorValue->loadSubimages(cachedResourceLoader); | |
| 3680 return StyleGeneratedImage::create(imageGeneratorValue); | |
| 3681 } | |
| 3682 | |
| 3683 if (pendingImage->cssCursorImageValue()) { | |
| 3684 CSSCursorImageValue* cursorImageValue = pendingImage->cssCursorImageValu
e(); | |
| 3685 return cursorImageValue->cachedImage(cachedResourceLoader); | |
| 3686 } | |
| 3687 | |
| 3688 if (pendingImage->cssImageSetValue()) { | |
| 3689 CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue(); | |
| 3690 return imageSetValue->cachedImageSet(cachedResourceLoader); | |
| 3691 } | |
| 3692 | |
| 3693 return 0; | |
| 3694 } | |
| 3695 | |
| 3696 void StyleResolver::loadPendingImages() | |
| 3697 { | |
| 3698 if (m_state.pendingImageProperties().isEmpty()) | |
| 3699 return; | |
| 3700 | |
| 3701 PendingImagePropertyMap::const_iterator::Keys end = m_state.pendingImageProp
erties().end().keys(); | |
| 3702 for (PendingImagePropertyMap::const_iterator::Keys it = m_state.pendingImage
Properties().begin().keys(); it != end; ++it) { | |
| 3703 CSSPropertyID currentProperty = *it; | |
| 3704 | |
| 3705 switch (currentProperty) { | |
| 3706 case CSSPropertyBackgroundImage: { | |
| 3707 for (FillLayer* backgroundLayer = m_state.style()->accessBackgroundL
ayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) { | |
| 3708 if (backgroundLayer->image() && backgroundLayer->image()->isPend
ingImage()) | |
| 3709 backgroundLayer->setImage(loadPendingImage(static_cast<Style
PendingImage*>(backgroundLayer->image()))); | |
| 3710 } | |
| 3711 break; | |
| 3712 } | |
| 3713 case CSSPropertyContent: { | |
| 3714 for (ContentData* contentData = const_cast<ContentData*>(m_state.sty
le()->contentData()); contentData; contentData = contentData->next()) { | |
| 3715 if (contentData->isImage()) { | |
| 3716 StyleImage* image = static_cast<ImageContentData*>(contentDa
ta)->image(); | |
| 3717 if (image->isPendingImage()) { | |
| 3718 RefPtr<StyleImage> loadedImage = loadPendingImage(static
_cast<StylePendingImage*>(image)); | |
| 3719 if (loadedImage) | |
| 3720 static_cast<ImageContentData*>(contentData)->setImag
e(loadedImage.release()); | |
| 3721 } | |
| 3722 } | |
| 3723 } | |
| 3724 break; | |
| 3725 } | |
| 3726 case CSSPropertyCursor: { | |
| 3727 if (CursorList* cursorList = m_state.style()->cursors()) { | |
| 3728 for (size_t i = 0; i < cursorList->size(); ++i) { | |
| 3729 CursorData& currentCursor = cursorList->at(i); | |
| 3730 if (StyleImage* image = currentCursor.image()) { | |
| 3731 if (image->isPendingImage()) | |
| 3732 currentCursor.setImage(loadPendingImage(static_cast<
StylePendingImage*>(image))); | |
| 3733 } | |
| 3734 } | |
| 3735 } | |
| 3736 break; | |
| 3737 } | |
| 3738 case CSSPropertyListStyleImage: { | |
| 3739 if (m_state.style()->listStyleImage() && m_state.style()->listStyleI
mage()->isPendingImage()) | |
| 3740 m_state.style()->setListStyleImage(loadPendingImage(static_cast<
StylePendingImage*>(m_state.style()->listStyleImage()))); | |
| 3741 break; | |
| 3742 } | |
| 3743 case CSSPropertyBorderImageSource: { | |
| 3744 if (m_state.style()->borderImageSource() && m_state.style()->borderI
mageSource()->isPendingImage()) | |
| 3745 m_state.style()->setBorderImageSource(loadPendingImage(static_ca
st<StylePendingImage*>(m_state.style()->borderImageSource()))); | |
| 3746 break; | |
| 3747 } | |
| 3748 case CSSPropertyWebkitBoxReflect: { | |
| 3749 if (StyleReflection* reflection = m_state.style()->boxReflect()) { | |
| 3750 const NinePieceImage& maskImage = reflection->mask(); | |
| 3751 if (maskImage.image() && maskImage.image()->isPendingImage()) { | |
| 3752 RefPtr<StyleImage> loadedImage = loadPendingImage(static_cas
t<StylePendingImage*>(maskImage.image())); | |
| 3753 reflection->setMask(NinePieceImage(loadedImage.release(), ma
skImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.out
set(), maskImage.horizontalRule(), maskImage.verticalRule())); | |
| 3754 } | |
| 3755 } | |
| 3756 break; | |
| 3757 } | |
| 3758 case CSSPropertyWebkitMaskBoxImageSource: { | |
| 3759 if (m_state.style()->maskBoxImageSource() && m_state.style()->maskBo
xImageSource()->isPendingImage()) | |
| 3760 m_state.style()->setMaskBoxImageSource(loadPendingImage(static_c
ast<StylePendingImage*>(m_state.style()->maskBoxImageSource()))); | |
| 3761 break; | |
| 3762 } | |
| 3763 case CSSPropertyWebkitMaskImage: { | |
| 3764 for (FillLayer* maskLayer = m_state.style()->accessMaskLayers(); mas
kLayer; maskLayer = maskLayer->next()) { | |
| 3765 if (maskLayer->image() && maskLayer->image()->isPendingImage()) | |
| 3766 maskLayer->setImage(loadPendingImage(static_cast<StylePendin
gImage*>(maskLayer->image()))); | |
| 3767 } | |
| 3768 break; | |
| 3769 } | |
| 3770 default: | |
| 3771 ASSERT_NOT_REACHED(); | |
| 3772 } | |
| 3773 } | |
| 3774 | |
| 3775 m_state.pendingImageProperties().clear(); | |
| 3776 } | |
| 3777 | |
| 3778 void StyleResolver::loadPendingResources() | |
| 3779 { | |
| 3780 // Start loading images referenced by this style. | |
| 3781 loadPendingImages(); | |
| 3782 | |
| 3783 // Start loading the shaders referenced by this style. | |
| 3784 loadPendingShaders(); | |
| 3785 | |
| 3786 #if ENABLE(SVG) | |
| 3787 // Start loading the SVG Documents referenced by this style. | |
| 3788 loadPendingSVGDocuments(); | |
| 3789 #endif | |
| 3790 } | |
| 3791 | |
| 3792 inline StyleResolver::MatchedProperties::MatchedProperties() | |
| 3793 : possiblyPaddedMember(0) | |
| 3794 { | |
| 3795 } | |
| 3796 | |
| 3797 inline StyleResolver::MatchedProperties::~MatchedProperties() | |
| 3798 { | |
| 3799 } | |
| 3800 | |
| 3801 void StyleResolver::MatchedProperties::reportMemoryUsage(MemoryObjectInfo* memor
yObjectInfo) const | |
| 3802 { | |
| 3803 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); | |
| 3804 info.addMember(properties, "properties"); | |
| 3805 } | |
| 3806 | |
| 3807 void StyleResolver::MatchedPropertiesCacheItem::reportMemoryUsage(MemoryObjectIn
fo* memoryObjectInfo) const | |
| 3808 { | |
| 3809 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); | |
| 3810 info.addMember(matchedProperties, "matchedProperties"); | |
| 3811 info.addMember(ranges, "ranges"); | |
| 3812 info.addMember(renderStyle, "renderStyle"); | |
| 3813 info.addMember(parentRenderStyle, "parentRenderStyle"); | |
| 3814 } | |
| 3815 | |
| 3816 void MediaQueryResult::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) con
st | |
| 3817 { | |
| 3818 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); | |
| 3819 info.addMember(m_expression, "expression"); | |
| 3820 } | |
| 3821 | |
| 3822 void StyleResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | |
| 3823 { | |
| 3824 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); | |
| 3825 info.addMember(m_ruleSets, "ruleSets"); | |
| 3826 info.addMember(m_keyframesRuleMap, "keyframesRuleMap"); | |
| 3827 info.addMember(m_matchedPropertiesCache, "matchedPropertiesCache"); | |
| 3828 info.addMember(m_matchedPropertiesCacheSweepTimer, "matchedPropertiesCacheSw
eepTimer"); | |
| 3829 | |
| 3830 info.addMember(m_medium, "medium"); | |
| 3831 info.addMember(m_rootDefaultStyle, "rootDefaultStyle"); | |
| 3832 info.addMember(m_document, "document"); | |
| 3833 | |
| 3834 info.addMember(m_fontSelector, "fontSelector"); | |
| 3835 info.addMember(m_viewportDependentMediaQueryResults, "viewportDependentMedia
QueryResults"); | |
| 3836 info.ignoreMember(m_styleBuilder); | |
| 3837 info.addMember(m_inspectorCSSOMWrappers); | |
| 3838 info.addMember(m_scopeResolver, "scopeResolver"); | |
| 3839 | |
| 3840 info.addMember(m_state, "state"); | |
| 3841 | |
| 3842 // FIXME: move this to a place where it would be called only once? | |
| 3843 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle"); | |
| 3844 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl
e"); | |
| 3845 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle,"defaultPrintStyle")
; | |
| 3846 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo
urceStyle"); | |
| 3847 } | |
| 3848 | |
| 3849 } // namespace WebCore | |
| OLD | NEW |