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

Side by Side Diff: Source/core/css/StyleResolver.cpp

Issue 15072003: Move StyleResolver and related classes to core/css/resolver (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/css/StyleResolver.h ('k') | Source/core/css/StyleResolverState.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 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
OLDNEW
« no previous file with comments | « Source/core/css/StyleResolver.h ('k') | Source/core/css/StyleResolverState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698