| Index: Source/core/css/StyleResolver.cpp
|
| diff --git a/Source/core/css/StyleResolver.cpp b/Source/core/css/StyleResolver.cpp
|
| deleted file mode 100644
|
| index 8c73ead520de80ed4b7cb992ec79d0dde316e08c..0000000000000000000000000000000000000000
|
| --- a/Source/core/css/StyleResolver.cpp
|
| +++ /dev/null
|
| @@ -1,3849 +0,0 @@
|
| -/*
|
| - * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
| - * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
|
| - * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
|
| - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
|
| - * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
|
| - * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
|
| - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
| - * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
| - * Copyright (C) Research In Motion Limited 2011. All rights reserved.
|
| - * Copyright (C) 2012 Google Inc. All rights reserved.
|
| - *
|
| - * This library is free software; you can redistribute it and/or
|
| - * modify it under the terms of the GNU Library General Public
|
| - * License as published by the Free Software Foundation; either
|
| - * version 2 of the License, or (at your option) any later version.
|
| - *
|
| - * This library is distributed in the hope that it will be useful,
|
| - * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| - * Library General Public License for more details.
|
| - *
|
| - * You should have received a copy of the GNU Library General Public License
|
| - * along with this library; see the file COPYING.LIB. If not, write to
|
| - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
| - * Boston, MA 02110-1301, USA.
|
| - */
|
| -
|
| -#include "config.h"
|
| -#include "core/css/StyleResolver.h"
|
| -
|
| -#include "CSSPropertyNames.h"
|
| -#include "HTMLNames.h"
|
| -#include "MathMLNames.h"
|
| -#include "RuntimeEnabledFeatures.h"
|
| -#include "UserAgentStyleSheets.h"
|
| -#include "WebKitFontFamilyNames.h"
|
| -#include "XMLNames.h"
|
| -#include "core/animation/Animation.h"
|
| -#include "core/css/CSSBorderImage.h"
|
| -#include "core/css/CSSCalculationValue.h"
|
| -#include "core/css/CSSCursorImageValue.h"
|
| -#include "core/css/CSSDefaultStyleSheets.h"
|
| -#include "core/css/CSSFontFaceRule.h"
|
| -#include "core/css/CSSFontSelector.h"
|
| -#include "core/css/CSSLineBoxContainValue.h"
|
| -#include "core/css/CSSPageRule.h"
|
| -#include "core/css/CSSParser.h"
|
| -#include "core/css/CSSPrimitiveValueMappings.h"
|
| -#include "core/css/CSSReflectValue.h"
|
| -#include "core/css/CSSSelector.h"
|
| -#include "core/css/CSSSelectorList.h"
|
| -#include "core/css/CSSStyleRule.h"
|
| -#include "core/css/CSSSupportsRule.h"
|
| -#include "core/css/CSSTimingFunctionValue.h"
|
| -#include "core/css/CSSValueList.h"
|
| -#include "core/css/CSSVariableValue.h"
|
| -#include "core/css/Counter.h"
|
| -#include "core/css/DeprecatedStyleBuilder.h"
|
| -#include "core/css/ElementRuleCollector.h"
|
| -#include "core/css/FilterOperationResolver.h"
|
| -#include "core/css/FontFeatureValue.h"
|
| -#include "core/css/FontValue.h"
|
| -#include "core/css/MediaList.h"
|
| -#include "core/css/MediaQueryEvaluator.h"
|
| -#include "core/css/PageRuleCollector.h"
|
| -#include "core/css/Pair.h"
|
| -#include "core/css/Rect.h"
|
| -#include "core/css/RuleSet.h"
|
| -#include "core/css/SelectorCheckerFastPath.h"
|
| -#include "core/css/ShadowValue.h"
|
| -#include "core/css/StylePropertySet.h"
|
| -#include "core/css/StylePropertyShorthand.h"
|
| -#include "core/css/StyleRule.h"
|
| -#include "core/css/StyleRuleImport.h"
|
| -#include "core/css/StyleSheetContents.h"
|
| -#include "core/css/StyleSheetList.h"
|
| -#include "core/css/TransformBuilder.h"
|
| -#include "core/css/ViewportStyleResolver.h"
|
| -#include "core/css/WebKitCSSKeyframeRule.h"
|
| -#include "core/css/WebKitCSSKeyframesRule.h"
|
| -#include "core/css/WebKitCSSRegionRule.h"
|
| -#include "core/dom/Attribute.h"
|
| -#include "core/dom/ContextFeatures.h"
|
| -#include "core/dom/DocumentStyleSheetCollection.h"
|
| -#include "core/dom/ElementShadow.h"
|
| -#include "core/dom/NodeRenderStyle.h"
|
| -#include "core/dom/NodeRenderingContext.h"
|
| -#include "core/dom/ShadowRoot.h"
|
| -#include "core/dom/Text.h"
|
| -#include "core/dom/VisitedLinkState.h"
|
| -#include "core/dom/WebCoreMemoryInstrumentation.h"
|
| -#include "core/editing/FrameSelection.h"
|
| -#include "core/html/HTMLDocument.h"
|
| -#include "core/html/HTMLIFrameElement.h"
|
| -#include "core/html/HTMLInputElement.h"
|
| -#include "core/html/HTMLOptionElement.h"
|
| -#include "core/html/HTMLProgressElement.h"
|
| -#include "core/html/HTMLStyleElement.h"
|
| -#include "core/html/HTMLTextAreaElement.h"
|
| -#include "core/html/shadow/InsertionPoint.h"
|
| -#include "core/inspector/InspectorInstrumentation.h"
|
| -#include "core/loader/cache/CachedImage.h"
|
| -#include "core/page/Frame.h"
|
| -#include "core/page/FrameView.h"
|
| -#include "core/page/Page.h"
|
| -#include "core/page/SecurityOrigin.h"
|
| -#include "core/page/Settings.h"
|
| -#include "core/platform/CalculationValue.h"
|
| -#include "core/platform/LinkHash.h"
|
| -#include "core/platform/text/LocaleToScriptMapping.h"
|
| -#include "core/rendering/RenderRegion.h"
|
| -#include "core/rendering/RenderScrollbar.h"
|
| -#include "core/rendering/RenderScrollbarTheme.h"
|
| -#include "core/rendering/RenderTheme.h"
|
| -#include "core/rendering/RenderView.h"
|
| -#include "core/rendering/style/ContentData.h"
|
| -#include "core/rendering/style/CounterContent.h"
|
| -#include "core/rendering/style/CursorList.h"
|
| -#include "core/rendering/style/KeyframeList.h"
|
| -#include "core/rendering/style/QuotesData.h"
|
| -#include "core/rendering/style/RenderStyleConstants.h"
|
| -#include "core/rendering/style/ShadowData.h"
|
| -#include "core/rendering/style/StyleCachedImage.h"
|
| -#include "core/rendering/style/StyleGeneratedImage.h"
|
| -#include "core/rendering/style/StylePendingImage.h"
|
| -#include "core/svg/SVGDocumentExtensions.h"
|
| -#include "core/svg/SVGFontFaceElement.h"
|
| -#include <wtf/MemoryInstrumentationHashMap.h>
|
| -#include <wtf/MemoryInstrumentationHashSet.h>
|
| -#include <wtf/MemoryInstrumentationVector.h>
|
| -#include <wtf/StdLibExtras.h>
|
| -#include <wtf/Vector.h>
|
| -
|
| -#if ENABLE(SVG)
|
| -#include "SVGNames.h"
|
| -#include "core/css/WebKitCSSSVGDocumentValue.h"
|
| -#include "core/loader/cache/CachedSVGDocument.h"
|
| -#include "core/loader/cache/CachedSVGDocumentReference.h"
|
| -#include "core/svg/SVGDocument.h"
|
| -#include "core/svg/SVGElement.h"
|
| -#include "core/svg/SVGURIReference.h"
|
| -#endif
|
| -
|
| -#include "core/css/CSSImageSetValue.h"
|
| -#include "core/css/WebKitCSSMixFunctionValue.h"
|
| -#include "core/css/WebKitCSSShaderValue.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterArrayParameter.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterConstants.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterNumberParameter.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterParameter.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterProgramInfo.h"
|
| -#include "core/platform/graphics/filters/custom/CustomFilterTransformParameter.h"
|
| -#include "core/rendering/style/StyleCachedImageSet.h"
|
| -#include "core/rendering/style/StyleCachedShader.h"
|
| -#include "core/rendering/style/StyleCustomFilterProgram.h"
|
| -#include "core/rendering/style/StyleCustomFilterProgramCache.h"
|
| -#include "core/rendering/style/StylePendingShader.h"
|
| -#include "core/rendering/style/StyleShader.h"
|
| -
|
| -#include "core/html/track/WebVTTElement.h"
|
| -
|
| -using namespace std;
|
| -
|
| -namespace WTF {
|
| -
|
| -template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*> {
|
| - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
|
| -};
|
| -
|
| -}
|
| -
|
| -namespace WebCore {
|
| -
|
| -using namespace HTMLNames;
|
| -
|
| -#define HANDLE_INHERIT(prop, Prop) \
|
| -if (isInherit) { \
|
| - m_state.style()->set##Prop(m_state.parentStyle()->prop()); \
|
| - return; \
|
| -}
|
| -
|
| -#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
|
| -HANDLE_INHERIT(prop, Prop) \
|
| -if (isInitial) { \
|
| - m_state.style()->set##Prop(RenderStyle::initial##Prop()); \
|
| - return; \
|
| -}
|
| -
|
| -RenderStyle* StyleResolver::s_styleNotYetAvailable;
|
| -
|
| -static StylePropertySet* leftToRightDeclaration()
|
| -{
|
| - DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
|
| - if (leftToRightDecl->isEmpty())
|
| - leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
|
| - return leftToRightDecl.get();
|
| -}
|
| -
|
| -static StylePropertySet* rightToLeftDeclaration()
|
| -{
|
| - DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
|
| - if (rightToLeftDecl->isEmpty())
|
| - rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
|
| - return rightToLeftDecl.get();
|
| -}
|
| -
|
| -
|
| -void StyleResolver::MatchResult::addMatchedProperties(const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
|
| -{
|
| - matchedProperties.grow(matchedProperties.size() + 1);
|
| - StyleResolver::MatchedProperties& newProperties = matchedProperties.last();
|
| - newProperties.properties = const_cast<StylePropertySet*>(properties);
|
| - newProperties.linkMatchType = linkMatchType;
|
| - newProperties.whitelistType = propertyWhitelistType;
|
| - matchedRules.append(rule);
|
| -}
|
| -
|
| -StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
|
| - : m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
|
| - , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
|
| - , m_document(document)
|
| - , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
|
| - , m_fontSelector(CSSFontSelector::create(document))
|
| -#if ENABLE(CSS_DEVICE_ADAPTATION)
|
| - , m_viewportStyleResolver(ViewportStyleResolver::create(document))
|
| -#endif
|
| - , m_styleBuilder(DeprecatedStyleBuilder::sharedStyleBuilder())
|
| - , m_styleMap(this)
|
| -{
|
| - Element* root = document->documentElement();
|
| -
|
| - CSSDefaultStyleSheets::initDefaultStyle(root);
|
| -
|
| - // construct document root element default style. this is needed
|
| - // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
|
| - // This is here instead of constructor, because when constructor is run,
|
| - // document doesn't have documentElement
|
| - // NOTE: this assumes that element that gets passed to styleForElement -call
|
| - // is always from the document that owns the style selector
|
| - FrameView* view = document->view();
|
| - if (view)
|
| - m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
|
| - else
|
| - m_medium = adoptPtr(new MediaQueryEvaluator("all"));
|
| -
|
| - if (root)
|
| - m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
|
| -
|
| - if (m_rootDefaultStyle && view)
|
| - m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
|
| -
|
| - m_ruleSets.resetAuthorStyle();
|
| -
|
| - DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
|
| - m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this);
|
| -
|
| -#if ENABLE(SVG_FONTS)
|
| - if (document->svgExtensions()) {
|
| - const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
|
| - HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
|
| - for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
|
| - fontSelector()->addFontFaceRule((*it)->fontFaceRule());
|
| - }
|
| -#endif
|
| -
|
| - appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets());
|
| -}
|
| -
|
| -void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
|
| -{
|
| - m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, document()->isViewSource(), this);
|
| - if (document()->renderer() && document()->renderer()->style())
|
| - document()->renderer()->style()->font().update(fontSelector());
|
| -
|
| -#if ENABLE(CSS_DEVICE_ADAPTATION)
|
| - viewportStyleResolver()->resolve();
|
| -#endif
|
| -}
|
| -
|
| -void StyleResolver::pushParentElement(Element* parent)
|
| -{
|
| - const ContainerNode* parentsParent = parent->parentOrShadowHostElement();
|
| -
|
| - // We are not always invoked consistently. For example, script execution can cause us to enter
|
| - // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
|
| - // Reset the stack in this case, or if we see a new root element.
|
| - // Otherwise just push the new parent.
|
| - if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
|
| - m_selectorFilter.setupParentStack(parent);
|
| - else
|
| - m_selectorFilter.pushParent(parent);
|
| -
|
| - // Note: We mustn't skip ShadowRoot nodes for the scope stack.
|
| - if (m_scopeResolver)
|
| - m_scopeResolver->push(parent, parent->parentOrShadowHostNode());
|
| -}
|
| -
|
| -void StyleResolver::popParentElement(Element* parent)
|
| -{
|
| - // Note that we may get invoked for some random elements in some wacky cases during style resolve.
|
| - // Pause maintaining the stack in this case.
|
| - if (m_selectorFilter.parentStackIsConsistent(parent))
|
| - m_selectorFilter.popParent();
|
| - if (m_scopeResolver)
|
| - m_scopeResolver->pop(parent);
|
| -}
|
| -
|
| -void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
|
| -{
|
| - ASSERT(shadowRoot->host());
|
| - if (m_scopeResolver)
|
| - m_scopeResolver->push(shadowRoot, shadowRoot->host());
|
| -}
|
| -
|
| -void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
|
| -{
|
| - ASSERT(shadowRoot->host());
|
| - if (m_scopeResolver)
|
| - m_scopeResolver->pop(shadowRoot);
|
| -}
|
| -
|
| -// This is a simplified style setting function for keyframe styles
|
| -void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
|
| -{
|
| - AtomicString s(rule->name());
|
| - m_keyframesRuleMap.set(s.impl(), rule);
|
| -}
|
| -
|
| -StyleResolver::~StyleResolver()
|
| -{
|
| - m_fontSelector->clearDocument();
|
| -
|
| -#if ENABLE(CSS_DEVICE_ADAPTATION)
|
| - m_viewportStyleResolver->clearDocument();
|
| -#endif
|
| -}
|
| -
|
| -void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
|
| -{
|
| - // Look for cache entries containing a style declaration with a single ref and remove them.
|
| - // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
|
| - // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
|
| - Vector<unsigned, 16> toRemove;
|
| - MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
|
| - MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
|
| - for (; it != end; ++it) {
|
| - Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
|
| - for (size_t i = 0; i < matchedProperties.size(); ++i) {
|
| - if (matchedProperties[i].properties->hasOneRef()) {
|
| - toRemove.append(it->key);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - for (size_t i = 0; i < toRemove.size(); ++i)
|
| - m_matchedPropertiesCache.remove(toRemove[i]);
|
| -
|
| - m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
|
| -}
|
| -
|
| -inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
|
| -{
|
| - return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_state.element());
|
| -}
|
| -
|
| -bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
|
| -{
|
| - for (unsigned i = 0; i < classNames.size(); ++i) {
|
| - if (m_ruleSets.features().classesInRules.contains(classNames[i].impl()))
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -inline void StyleResolver::matchShadowDistributedRules(ElementRuleCollector& collector, bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
|
| -{
|
| - if (m_ruleSets.shadowDistributedRules().isEmpty())
|
| - return;
|
| -
|
| - bool previousCanUseFastReject = collector.canUseFastReject();
|
| - SelectorChecker::BehaviorAtBoundary previousBoundary = collector.behaviorAtBoundary();
|
| - collector.setBehaviorAtBoundary(static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::CrossesBoundary | SelectorChecker::ScopeContainsLastMatchedElement));
|
| - collector.setCanUseFastReject(false);
|
| -
|
| - Vector<MatchRequest> matchRequests;
|
| - m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules, matchRequests);
|
| - for (size_t i = 0; i < matchRequests.size(); ++i)
|
| - collector.collectMatchingRules(matchRequests[i], ruleRange);
|
| -
|
| - collector.setBehaviorAtBoundary(previousBoundary);
|
| - collector.setCanUseFastReject(previousCanUseFastReject);
|
| -}
|
| -
|
| -void StyleResolver::matchHostRules(ElementRuleCollector& collector, bool includeEmptyRules)
|
| -{
|
| - ASSERT(m_scopeResolver);
|
| -
|
| - collector.clearMatchedRules();
|
| - collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
|
| -
|
| - Vector<RuleSet*> matchedRules;
|
| - m_scopeResolver->matchHostRules(m_state.element(), matchedRules);
|
| - if (matchedRules.isEmpty())
|
| - return;
|
| -
|
| - for (unsigned i = matchedRules.size(); i > 0; --i) {
|
| - StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
|
| - collector.collectMatchingRules(MatchRequest(matchedRules.at(i-1), includeEmptyRules, m_state.element()), ruleRange);
|
| - }
|
| - collector.sortAndTransferMatchedRules();
|
| -}
|
| -
|
| -void StyleResolver::matchScopedAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules)
|
| -{
|
| - if (!m_scopeResolver)
|
| - return;
|
| -
|
| - // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
|
| - if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsistency(m_state.element())) {
|
| - bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyles();
|
| - bool documentScope = true;
|
| -
|
| - unsigned scopeSize = m_scopeResolver->stackSize();
|
| - for (unsigned i = 0; i < scopeSize; ++i) {
|
| - collector.clearMatchedRules();
|
| - collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
|
| -
|
| - const ScopedStyleResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
|
| - documentScope = documentScope && !frame.m_scope->isInShadowTree();
|
| - if (documentScope) {
|
| - if (!applyAuthorStyles)
|
| - continue;
|
| - } else {
|
| - if (!m_scopeResolver->matchesStyleBounds(frame))
|
| - continue;
|
| - }
|
| -
|
| - MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.m_scope);
|
| - StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
|
| - collector.collectMatchingRules(matchRequest, ruleRange);
|
| - collector.collectMatchingRulesForRegion(matchRequest, ruleRange);
|
| - collector.sortAndTransferMatchedRules();
|
| - }
|
| - }
|
| -
|
| - matchHostRules(collector, includeEmptyRules);
|
| -}
|
| -
|
| -void StyleResolver::matchAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules)
|
| -{
|
| - collector.clearMatchedRules();
|
| - collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
|
| -
|
| - if (!m_state.element())
|
| - return;
|
| -
|
| - // Match global author rules.
|
| - MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules);
|
| - StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
|
| - collector.collectMatchingRules(matchRequest, ruleRange);
|
| - collector.collectMatchingRulesForRegion(matchRequest, ruleRange);
|
| - matchShadowDistributedRules(collector, includeEmptyRules, ruleRange);
|
| - collector.sortAndTransferMatchedRules();
|
| -
|
| - matchScopedAuthorRules(collector, includeEmptyRules);
|
| -}
|
| -
|
| -void StyleResolver::matchUserRules(ElementRuleCollector& collector, bool includeEmptyRules)
|
| -{
|
| - if (!m_ruleSets.userStyle())
|
| - return;
|
| -
|
| - collector.clearMatchedRules();
|
| - collector.matchedResult().ranges.lastUserRule = collector.matchedResult().matchedProperties.size() - 1;
|
| -
|
| - MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules);
|
| - RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange();
|
| - collector.collectMatchingRules(matchRequest, ruleRange);
|
| - collector.collectMatchingRulesForRegion(matchRequest, ruleRange);
|
| -
|
| - collector.sortAndTransferMatchedRules();
|
| -}
|
| -
|
| -void StyleResolver::matchUARules(ElementRuleCollector& collector)
|
| -{
|
| - collector.setMatchingUARules(true);
|
| -
|
| - // First we match rules from the user agent sheet.
|
| - if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
|
| - collector.matchedResult().isCacheable = false;
|
| -
|
| - RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
|
| - ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
|
| - matchUARules(collector, userAgentStyleSheet);
|
| -
|
| - // In quirks mode, we match rules from the quirks user agent sheet.
|
| - if (document()->inQuirksMode())
|
| - matchUARules(collector, CSSDefaultStyleSheets::defaultQuirksStyle);
|
| -
|
| - // 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.
|
| - if (document()->isViewSource())
|
| - matchUARules(collector, CSSDefaultStyleSheets::viewSourceStyle());
|
| -
|
| - collector.setMatchingUARules(false);
|
| -}
|
| -
|
| -void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules)
|
| -{
|
| - collector.clearMatchedRules();
|
| - collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1;
|
| -
|
| - RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange();
|
| - collector.collectMatchingRules(MatchRequest(rules), ruleRange);
|
| -
|
| - collector.sortAndTransferMatchedRules();
|
| -}
|
| -
|
| -void StyleResolver::matchAllRules(ElementRuleCollector& collector, bool matchAuthorAndUserStyles, bool includeSMILProperties)
|
| -{
|
| - matchUARules(collector);
|
| -
|
| - // Now we check user sheet rules.
|
| - if (matchAuthorAndUserStyles)
|
| - matchUserRules(collector, false);
|
| -
|
| - // Now check author rules, beginning first with presentational attributes mapped from HTML.
|
| - if (m_state.styledElement()) {
|
| - collector.addElementStyleProperties(m_state.styledElement()->presentationAttributeStyle());
|
| -
|
| - // Now we check additional mapped declarations.
|
| - // Tables and table cells share an additional mapped rule that must be applied
|
| - // after all attributes, since their mapped style depends on the values of multiple attributes.
|
| - collector.addElementStyleProperties(m_state.styledElement()->additionalPresentationAttributeStyle());
|
| -
|
| - if (m_state.styledElement()->isHTMLElement()) {
|
| - bool isAuto;
|
| - TextDirection textDirection = toHTMLElement(m_state.styledElement())->directionalityIfhasDirAutoAttribute(isAuto);
|
| - if (isAuto)
|
| - collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
|
| - }
|
| - }
|
| -
|
| - // Check the rules in author sheets next.
|
| - if (matchAuthorAndUserStyles)
|
| - matchAuthorRules(collector, false);
|
| -
|
| - // Now check our inline style attribute.
|
| - if (matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->inlineStyle()) {
|
| - // Inline style is immutable as long as there is no CSSOM wrapper.
|
| - // FIXME: Media control shadow trees seem to have problems with caching.
|
| - bool isInlineStyleCacheable = !m_state.styledElement()->inlineStyle()->isMutable() && !m_state.styledElement()->isInShadowTree();
|
| - // FIXME: Constify.
|
| - collector.addElementStyleProperties(m_state.styledElement()->inlineStyle(), isInlineStyleCacheable);
|
| - }
|
| -
|
| -#if ENABLE(SVG)
|
| - // Now check SMIL animation override style.
|
| - if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->isSVGElement())
|
| - collector.addElementStyleProperties(toSVGElement(m_state.styledElement())->animatedSMILStyleProperties(), false /* isCacheable */);
|
| -#else
|
| - UNUSED_PARAM(includeSMILProperties);
|
| -#endif
|
| -
|
| - if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations())
|
| - collector.matchedResult().isCacheable = false;
|
| -}
|
| -
|
| -inline void StyleResolver::initElement(Element* e)
|
| -{
|
| - if (m_state.element() != e) {
|
| - m_state.initElement(e);
|
| - if (e && e == e->document()->documentElement()) {
|
| - e->document()->setDirectionSetOnDocumentElement(false);
|
| - e->document()->setWritingModeSetOnDocumentElement(false);
|
| - }
|
| - }
|
| -}
|
| -
|
| -static const unsigned cStyleSearchThreshold = 10;
|
| -static const unsigned cStyleSearchLevelThreshold = 10;
|
| -
|
| -static inline bool parentElementPreventsSharing(const Element* parentElement)
|
| -{
|
| - if (!parentElement)
|
| - return false;
|
| - return parentElement->hasFlagsSetDuringStylingOfChildren();
|
| -}
|
| -
|
| -Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
|
| -{
|
| - if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
|
| - return 0;
|
| - if (!parent || !parent->isStyledElement())
|
| - return 0;
|
| - if (parent->hasScopedHTMLStyleChild())
|
| - return 0;
|
| - StyledElement* p = static_cast<StyledElement*>(parent);
|
| - if (p->inlineStyle())
|
| - return 0;
|
| -#if ENABLE(SVG)
|
| - if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties())
|
| - return 0;
|
| -#endif
|
| - if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleResolution().impl()))
|
| - return 0;
|
| -
|
| - RenderStyle* parentStyle = p->renderStyle();
|
| - unsigned subcount = 0;
|
| - Node* thisCousin = p;
|
| - Node* currentNode = p->previousSibling();
|
| -
|
| - // Reserve the tries for this level. This effectively makes sure that the algorithm
|
| - // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
|
| - visitedNodeCount += cStyleSearchThreshold;
|
| - while (thisCousin) {
|
| - while (currentNode) {
|
| - ++subcount;
|
| - if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()
|
| - && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode))
|
| - && !toElement(currentNode)->shadow()
|
| - ) {
|
| - // Adjust for unused reserved tries.
|
| - visitedNodeCount -= cStyleSearchThreshold - subcount;
|
| - return currentNode->lastChild();
|
| - }
|
| - if (subcount >= cStyleSearchThreshold)
|
| - return 0;
|
| - currentNode = currentNode->previousSibling();
|
| - }
|
| - currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
|
| - thisCousin = currentNode;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
|
| -{
|
| - if (!ruleSet)
|
| - return false;
|
| -
|
| - ElementRuleCollector collector(this, m_state);
|
| - return collector.hasAnyMatchingRules(ruleSet);
|
| -}
|
| -
|
| -bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
|
| -{
|
| - const StyleResolverState& state = m_state;
|
| - HTMLInputElement* thisInputElement = element->toInputElement();
|
| - HTMLInputElement* otherInputElement = state.element()->toInputElement();
|
| -
|
| - if (!thisInputElement || !otherInputElement)
|
| - return false;
|
| -
|
| - if (thisInputElement->elementData() != otherInputElement->elementData()) {
|
| - if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
|
| - return false;
|
| - if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
|
| - return false;
|
| - }
|
| -
|
| - if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
|
| - return false;
|
| - if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
|
| - return false;
|
| - if (thisInputElement->shouldAppearIndeterminate() != otherInputElement->shouldAppearIndeterminate())
|
| - return false;
|
| - if (thisInputElement->isRequired() != otherInputElement->isRequired())
|
| - return false;
|
| -
|
| - if (element->isDisabledFormControl() != state.element()->isDisabledFormControl())
|
| - return false;
|
| -
|
| - if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonForForm())
|
| - return false;
|
| -
|
| - if (state.document()->containsValidityStyleRules()) {
|
| - bool willValidate = element->willValidate();
|
| -
|
| - if (willValidate != state.element()->willValidate())
|
| - return false;
|
| -
|
| - if (willValidate && (element->isValidFormControlElement() != state.element()->isValidFormControlElement()))
|
| - return false;
|
| -
|
| - if (element->isInRange() != state.element()->isInRange())
|
| - return false;
|
| -
|
| - if (element->isOutOfRange() != state.element()->isOutOfRange())
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -static inline bool elementHasDirectionAuto(Element* element)
|
| -{
|
| - // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
|
| - return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
|
| -}
|
| -
|
| -bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement* sharingCandidate) const
|
| -{
|
| - const StyleResolverState& state = m_state;
|
| - if (state.element()->elementData() == sharingCandidate->elementData())
|
| - return true;
|
| - if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate->fastGetAttribute(XMLNames::langAttr))
|
| - return false;
|
| - if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGetAttribute(langAttr))
|
| - return false;
|
| -
|
| - if (!state.elementAffectedByClassRules()) {
|
| - if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCandidate->classNames()))
|
| - return false;
|
| - } else if (sharingCandidate->hasClass()) {
|
| -#if ENABLE(SVG)
|
| - // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
|
| - if (state.element()->isSVGElement()) {
|
| - if (state.element()->getAttribute(classAttr) != sharingCandidate->getAttribute(classAttr))
|
| - return false;
|
| - } else {
|
| -#endif
|
| - if (state.element()->classNames() != sharingCandidate->classNames())
|
| - return false;
|
| -#if ENABLE(SVG)
|
| - }
|
| -#endif
|
| - } else
|
| - return false;
|
| -
|
| - if (state.styledElement()->presentationAttributeStyle() != sharingCandidate->presentationAttributeStyle())
|
| - return false;
|
| -
|
| - if (state.element()->hasTagName(progressTag)) {
|
| - if (state.element()->shouldAppearIndeterminate() != sharingCandidate->shouldAppearIndeterminate())
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
|
| -{
|
| - RenderStyle* style = element->renderStyle();
|
| - const StyleResolverState& state = m_state;
|
| -
|
| - if (!style)
|
| - return false;
|
| - if (style->unique())
|
| - return false;
|
| - if (style->hasUniquePseudoStyle())
|
| - return false;
|
| - if (element->tagQName() != state.element()->tagQName())
|
| - return false;
|
| - if (element->inlineStyle())
|
| - return false;
|
| - if (element->needsStyleRecalc())
|
| - return false;
|
| -#if ENABLE(SVG)
|
| - if (element->isSVGElement() && toSVGElement(element)->animatedSMILStyleProperties())
|
| - return false;
|
| -#endif
|
| - if (element->isLink() != state.element()->isLink())
|
| - return false;
|
| - if (element->hovered() != state.element()->hovered())
|
| - return false;
|
| - if (element->active() != state.element()->active())
|
| - return false;
|
| - if (element->focused() != state.element()->focused())
|
| - return false;
|
| - if (element->shadowPseudoId() != state.element()->shadowPseudoId())
|
| - return false;
|
| - if (element == element->document()->cssTarget())
|
| - return false;
|
| - if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element))
|
| - return false;
|
| - if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle())
|
| - return false;
|
| -
|
| - if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl()))
|
| - return false;
|
| - if (element->hasScopedHTMLStyleChild())
|
| - return false;
|
| -
|
| - // FIXME: We should share style for option and optgroup whenever possible.
|
| - // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
|
| - // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
|
| - if (element->hasTagName(optionTag) || element->hasTagName(optgroupTag))
|
| - return false;
|
| -
|
| - bool isControl = element->isFormControlElement();
|
| -
|
| - if (isControl != state.element()->isFormControlElement())
|
| - return false;
|
| -
|
| - if (isControl && !canShareStyleWithControl(element))
|
| - return false;
|
| -
|
| - if (style->transitions() || style->animations())
|
| - return false;
|
| -
|
| - // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
|
| - // See comments in RenderObject::setStyle().
|
| - if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag))
|
| - return false;
|
| -
|
| - if (elementHasDirectionAuto(element))
|
| - return false;
|
| -
|
| - if (element->isLink() && state.elementLinkState() != style->insideLink())
|
| - return false;
|
| -
|
| - if (element->isUnresolvedCustomElement() != state.element()->isUnresolvedCustomElement())
|
| - return false;
|
| -
|
| - // Deny sharing styles between WebVTT and non-WebVTT nodes.
|
| - if (element->isWebVTTElement() != state.element()->isWebVTTElement())
|
| - return false;
|
| -
|
| - if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWebVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNode())
|
| - return false;
|
| -
|
| - if (element == element->document()->webkitCurrentFullScreenElement() || state.element() == state.document()->webkitCurrentFullScreenElement())
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
|
| -{
|
| - for (; node; node = node->previousSibling()) {
|
| - if (!node->isStyledElement())
|
| - continue;
|
| - if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
|
| - break;
|
| - if (count++ == cStyleSearchThreshold)
|
| - return 0;
|
| - }
|
| - return static_cast<StyledElement*>(node);
|
| -}
|
| -
|
| -RenderStyle* StyleResolver::locateSharedStyle()
|
| -{
|
| - StyleResolverState& state = m_state;
|
| - if (!state.styledElement() || !state.parentStyle())
|
| - return 0;
|
| -
|
| - // If the element has inline style it is probably unique.
|
| - if (state.styledElement()->inlineStyle())
|
| - return 0;
|
| -#if ENABLE(SVG)
|
| - if (state.styledElement()->isSVGElement() && toSVGElement(state.styledElement())->animatedSMILStyleProperties())
|
| - return 0;
|
| -#endif
|
| - // Ids stop style sharing if they show up in the stylesheets.
|
| - if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl()))
|
| - return 0;
|
| - if (parentElementPreventsSharing(state.element()->parentElement()))
|
| - return 0;
|
| - if (state.styledElement()->hasScopedHTMLStyleChild())
|
| - return 0;
|
| - if (state.element() == state.document()->cssTarget())
|
| - return 0;
|
| - if (elementHasDirectionAuto(state.element()))
|
| - return 0;
|
| - if (state.element()->hasActiveAnimations())
|
| - return 0;
|
| -
|
| - // Cache whether state.element is affected by any known class selectors.
|
| - // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
|
| - state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames()));
|
| -
|
| - // Check previous siblings and their cousins.
|
| - unsigned count = 0;
|
| - unsigned visitedNodeCount = 0;
|
| - StyledElement* shareElement = 0;
|
| - Node* cousinList = state.styledElement()->previousSibling();
|
| - while (cousinList) {
|
| - shareElement = findSiblingForStyleSharing(cousinList, count);
|
| - if (shareElement)
|
| - break;
|
| - cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
|
| - }
|
| -
|
| - // If we have exhausted all our budget or our cousins.
|
| - if (!shareElement)
|
| - return 0;
|
| -
|
| - // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
|
| - if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling()))
|
| - return 0;
|
| - // Can't share if attribute rules apply.
|
| - if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute()))
|
| - return 0;
|
| - // Can't share if @host @-rules apply.
|
| - if (styleSharingCandidateMatchesHostRules())
|
| - return 0;
|
| - // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
|
| - if (parentElementPreventsSharing(state.element()->parentElement()))
|
| - return 0;
|
| - return shareElement->renderStyle();
|
| -}
|
| -
|
| -static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderStyle* style)
|
| -{
|
| - if (paginationMode == Pagination::Unpaginated)
|
| - return;
|
| -
|
| - switch (paginationMode) {
|
| - case Pagination::LeftToRightPaginated:
|
| - style->setColumnAxis(HorizontalColumnAxis);
|
| - if (style->isHorizontalWritingMode())
|
| - style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
|
| - else
|
| - style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
|
| - break;
|
| - case Pagination::RightToLeftPaginated:
|
| - style->setColumnAxis(HorizontalColumnAxis);
|
| - if (style->isHorizontalWritingMode())
|
| - style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
|
| - else
|
| - style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
|
| - break;
|
| - case Pagination::TopToBottomPaginated:
|
| - style->setColumnAxis(VerticalColumnAxis);
|
| - if (style->isHorizontalWritingMode())
|
| - style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
|
| - else
|
| - style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
|
| - break;
|
| - case Pagination::BottomToTopPaginated:
|
| - style->setColumnAxis(VerticalColumnAxis);
|
| - if (style->isHorizontalWritingMode())
|
| - style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
|
| - else
|
| - style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
|
| - break;
|
| - case Pagination::Unpaginated:
|
| - ASSERT_NOT_REACHED();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -static void getFontAndGlyphOrientation(const RenderStyle* style, FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
|
| -{
|
| - if (style->isHorizontalWritingMode()) {
|
| - fontOrientation = Horizontal;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - }
|
| -
|
| - switch (style->textOrientation()) {
|
| - case TextOrientationVerticalRight:
|
| - fontOrientation = Vertical;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - case TextOrientationUpright:
|
| - fontOrientation = Vertical;
|
| - glyphOrientation = NonCJKGlyphOrientationUpright;
|
| - return;
|
| - case TextOrientationSideways:
|
| - if (style->writingMode() == LeftToRightWritingMode) {
|
| - // FIXME: This should map to sideways-left, which is not supported yet.
|
| - fontOrientation = Vertical;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - }
|
| - fontOrientation = Horizontal;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - case TextOrientationSidewaysRight:
|
| - fontOrientation = Horizontal;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| - fontOrientation = Horizontal;
|
| - glyphOrientation = NonCJKGlyphOrientationVerticalRight;
|
| - return;
|
| - }
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document* document, CSSFontSelector* fontSelector)
|
| -{
|
| - Frame* frame = document->frame();
|
| -
|
| - // HTML5 states that seamless iframes should replace default CSS values
|
| - // with values inherited from the containing iframe element. However,
|
| - // some values (such as the case of designMode = "on") still need to
|
| - // be set by this "document style".
|
| - RefPtr<RenderStyle> documentStyle = RenderStyle::create();
|
| - bool seamlessWithParent = document->shouldDisplaySeamlesslyWithParent();
|
| - if (seamlessWithParent) {
|
| - RenderStyle* iframeStyle = document->seamlessParentIFrame()->renderStyle();
|
| - if (iframeStyle)
|
| - documentStyle->inheritFrom(iframeStyle);
|
| - }
|
| -
|
| - // FIXME: It's not clear which values below we want to override in the seamless case!
|
| - documentStyle->setDisplay(BLOCK);
|
| - if (!seamlessWithParent) {
|
| - documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
|
| - documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomFactor() : 1);
|
| - documentStyle->setLocale(document->contentLanguage());
|
| - }
|
| - // This overrides any -webkit-user-modify inherited from the parent iframe.
|
| - documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
|
| -
|
| - Element* docElement = document->documentElement();
|
| - RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
|
| - if (docElementRenderer) {
|
| - // Use the direction and writing-mode of the body to set the
|
| - // viewport's direction and writing-mode unless the property is set on the document element.
|
| - // If there is no body, then use the document element.
|
| - RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
|
| - if (bodyRenderer && !document->writingModeSetOnDocumentElement())
|
| - documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
|
| - else
|
| - documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
|
| - if (bodyRenderer && !document->directionSetOnDocumentElement())
|
| - documentStyle->setDirection(bodyRenderer->style()->direction());
|
| - else
|
| - documentStyle->setDirection(docElementRenderer->style()->direction());
|
| - }
|
| -
|
| - if (frame) {
|
| - if (FrameView* frameView = frame->view()) {
|
| - const Pagination& pagination = frameView->pagination();
|
| - if (pagination.mode != Pagination::Unpaginated) {
|
| - setStylesForPaginationMode(pagination.mode, documentStyle.get());
|
| - documentStyle->setColumnGap(pagination.gap);
|
| - if (RenderView* view = document->renderView()) {
|
| - if (view->hasColumns())
|
| - view->updateColumnInfoFromStyle(documentStyle.get());
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Seamless iframes want to inherit their font from their parent iframe, so early return before setting the font.
|
| - if (seamlessWithParent)
|
| - return documentStyle.release();
|
| -
|
| - FontDescription fontDescription;
|
| - fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
|
| - if (Settings* settings = document->settings()) {
|
| - fontDescription.setUsePrinterFont(document->printing());
|
| - fontDescription.setRenderingMode(settings->fontRenderingMode());
|
| - const AtomicString& standardFont = settings->standardFontFamily(fontDescription.script());
|
| - if (!standardFont.isEmpty()) {
|
| - fontDescription.setGenericFamily(FontDescription::StandardFamily);
|
| - fontDescription.firstFamily().setFamily(standardFont);
|
| - fontDescription.firstFamily().appendFamily(0);
|
| - }
|
| - fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
|
| - int size = StyleResolver::fontSizeForKeyword(document, CSSValueMedium, false);
|
| - fontDescription.setSpecifiedSize(size);
|
| - bool useSVGZoomRules = document->isSVGDocument();
|
| - fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
|
| - } else
|
| - fontDescription.setUsePrinterFont(document->printing());
|
| -
|
| - FontOrientation fontOrientation;
|
| - NonCJKGlyphOrientation glyphOrientation;
|
| - getFontAndGlyphOrientation(documentStyle.get(), fontOrientation, glyphOrientation);
|
| - fontDescription.setOrientation(fontOrientation);
|
| - fontDescription.setNonCJKGlyphOrientation(glyphOrientation);
|
| -
|
| - documentStyle->setFontDescription(fontDescription);
|
| - documentStyle->font().update(fontSelector);
|
| -
|
| - return documentStyle.release();
|
| -}
|
| -
|
| -static inline bool isAtShadowBoundary(const Element* element)
|
| -{
|
| - if (!element)
|
| - return false;
|
| - ContainerNode* parentNode = element->parentNode();
|
| - return parentNode && parentNode->isShadowRoot();
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
|
| - StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
|
| -{
|
| - // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
|
| - // will vanish if a style recalc happens during loading.
|
| - if (sharingBehavior == AllowStyleSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
|
| - if (!s_styleNotYetAvailable) {
|
| - s_styleNotYetAvailable = RenderStyle::create().leakRef();
|
| - s_styleNotYetAvailable->setDisplay(NONE);
|
| - s_styleNotYetAvailable->font().update(m_fontSelector);
|
| - }
|
| - element->document()->setHasNodesWithPlaceholderStyle();
|
| - return s_styleNotYetAvailable;
|
| - }
|
| -
|
| - StyleResolverState& state = m_state;
|
| - initElement(element);
|
| - state.initForStyleResolve(document(), element, defaultParent, regionForStyling);
|
| - if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoint()) {
|
| - RenderStyle* sharedStyle = locateSharedStyle();
|
| - if (sharedStyle)
|
| - {
|
| - state.clear();
|
| - return sharedStyle;
|
| - }
|
| - }
|
| -
|
| - if (state.parentStyle()) {
|
| - state.setStyle(RenderStyle::create());
|
| - state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
|
| - } else {
|
| - state.setStyle(defaultStyleForElement());
|
| - state.setParentStyle(RenderStyle::clone(state.style()));
|
| - }
|
| - // contenteditable attribute (implemented by -webkit-user-modify) should
|
| - // be propagated from shadow host to distributed node.
|
| - if (state.distributedToInsertionPoint()) {
|
| - if (Element* parent = element->parentElement()) {
|
| - if (RenderStyle* styleOfShadowHost = parent->renderStyle())
|
| - state.style()->setUserModify(styleOfShadowHost->userModify());
|
| - }
|
| - }
|
| -
|
| - if (element->isLink()) {
|
| - state.style()->setIsLink(true);
|
| - EInsideLink linkState = state.elementLinkState();
|
| - if (linkState != NotInsideLink) {
|
| - bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
|
| - if (forceVisited)
|
| - linkState = InsideVisitedLink;
|
| - }
|
| - state.style()->setInsideLink(linkState);
|
| - }
|
| -
|
| - bool needsCollection = false;
|
| - CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection);
|
| - if (needsCollection) {
|
| - m_ruleSets.collectFeatures(document()->isViewSource(), m_scopeResolver.get());
|
| - m_inspectorCSSOMWrappers.reset();
|
| - }
|
| -
|
| - ElementRuleCollector collector(this, state);
|
| - collector.setRegionForStyling(regionForStyling);
|
| -
|
| - if (matchingBehavior == MatchOnlyUserAgentRules)
|
| - matchUARules(collector);
|
| - else
|
| - matchAllRules(collector, m_matchAuthorAndUserStyles, matchingBehavior != MatchAllRulesExcludingSMIL);
|
| -
|
| - applyMatchedProperties(collector.matchedResult(), element);
|
| -
|
| - // Clean up our style object's display and text decorations (among other fixups).
|
| - adjustRenderStyle(state.style(), state.parentStyle(), element);
|
| -
|
| - state.clear(); // Clear out for the next resolve.
|
| -
|
| - document()->didAccessStyleResolver();
|
| -
|
| - // Now return the style.
|
| - return state.takeStyle();
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
|
| -{
|
| - MatchResult result;
|
| - if (keyframe->properties())
|
| - result.addMatchedProperties(keyframe->properties());
|
| -
|
| - ASSERT(!m_state.style());
|
| -
|
| - StyleResolverState& state = m_state;
|
| -
|
| - // Create the style
|
| - state.setStyle(RenderStyle::clone(elementStyle));
|
| - state.setLineHeightValue(0);
|
| -
|
| - // We don't need to bother with !important. Since there is only ever one
|
| - // decl, there's nothing to override. So just add the first properties.
|
| - bool inheritedOnly = false;
|
| - if (keyframe->properties())
|
| - applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
|
| -
|
| - // If our font got dirtied, go ahead and update it now.
|
| - updateFont();
|
| -
|
| - // Line-height is set when we are sure we decided on the font-size
|
| - if (state.lineHeightValue())
|
| - applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
|
| -
|
| - // Now do rest of the properties.
|
| - if (keyframe->properties())
|
| - applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
|
| -
|
| - // If our font got dirtied by one of the non-essential font props,
|
| - // go ahead and update it a second time.
|
| - updateFont();
|
| -
|
| - // Start loading resources referenced by this style.
|
| - loadPendingResources();
|
| -
|
| - // Add all the animating properties to the keyframe.
|
| - if (const StylePropertySet* styleDeclaration = keyframe->properties()) {
|
| - unsigned propertyCount = styleDeclaration->propertyCount();
|
| - for (unsigned i = 0; i < propertyCount; ++i) {
|
| - CSSPropertyID property = styleDeclaration->propertyAt(i).id();
|
| - // Timing-function within keyframes is special, because it is not animated; it just
|
| - // describes the timing function between this keyframe and the next.
|
| - if (property != CSSPropertyWebkitAnimationTimingFunction)
|
| - keyframeValue.addProperty(property);
|
| - }
|
| - }
|
| -
|
| - document()->didAccessStyleResolver();
|
| -
|
| - return state.takeStyle();
|
| -}
|
| -
|
| -void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
|
| -{
|
| - list.clear();
|
| -
|
| - // Get the keyframesRule for this name
|
| - if (!e || list.animationName().isEmpty())
|
| - return;
|
| -
|
| - m_keyframesRuleMap.checkConsistency();
|
| -
|
| - KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
|
| - if (it == m_keyframesRuleMap.end())
|
| - return;
|
| -
|
| - const StyleRuleKeyframes* keyframesRule = it->value.get();
|
| -
|
| - // Construct and populate the style for each keyframe
|
| - const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
|
| - for (unsigned i = 0; i < keyframes.size(); ++i) {
|
| - // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
|
| - initElement(e);
|
| - m_state.initForStyleResolve(document(), e);
|
| -
|
| - const StyleKeyframe* keyframe = keyframes[i].get();
|
| -
|
| - KeyframeValue keyframeValue(0, 0);
|
| - keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
|
| -
|
| - // Add this keyframe style to all the indicated key times
|
| - Vector<float> keys;
|
| - keyframe->getKeys(keys);
|
| - for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
|
| - keyframeValue.setKey(keys[keyIndex]);
|
| - list.insert(keyframeValue);
|
| - }
|
| - }
|
| -
|
| - // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
|
| - int initialListSize = list.size();
|
| - if (initialListSize > 0 && list[0].key()) {
|
| - static StyleKeyframe* zeroPercentKeyframe;
|
| - if (!zeroPercentKeyframe) {
|
| - zeroPercentKeyframe = StyleKeyframe::create().leakRef();
|
| - zeroPercentKeyframe->setKeyText("0%");
|
| - }
|
| - KeyframeValue keyframeValue(0, 0);
|
| - keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
|
| - list.insert(keyframeValue);
|
| - }
|
| -
|
| - // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
|
| - if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
|
| - static StyleKeyframe* hundredPercentKeyframe;
|
| - if (!hundredPercentKeyframe) {
|
| - hundredPercentKeyframe = StyleKeyframe::create().leakRef();
|
| - hundredPercentKeyframe->setKeyText("100%");
|
| - }
|
| - KeyframeValue keyframeValue(1, 0);
|
| - keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
|
| - list.insert(keyframeValue);
|
| - }
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
|
| -{
|
| - ASSERT(parentStyle);
|
| - if (!e)
|
| - return 0;
|
| -
|
| - StyleResolverState& state = m_state;
|
| -
|
| - initElement(e);
|
| -
|
| - state.initForStyleResolve(document(), e, parentStyle);
|
| -
|
| - if (m_state.parentStyle()) {
|
| - state.setStyle(RenderStyle::create());
|
| - state.style()->inheritFrom(m_state.parentStyle());
|
| - } else {
|
| - state.setStyle(defaultStyleForElement());
|
| - state.setParentStyle(RenderStyle::clone(state.style()));
|
| - }
|
| -
|
| - // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
|
| - // those rules.
|
| -
|
| - // Check UA, user and author rules.
|
| - ElementRuleCollector collector(this, state);
|
| - collector.setPseudoStyleRequest(pseudoStyleRequest);
|
| - matchUARules(collector);
|
| -
|
| - if (m_matchAuthorAndUserStyles) {
|
| - matchUserRules(collector, false);
|
| - matchAuthorRules(collector, false);
|
| - }
|
| -
|
| - if (collector.matchedResult().matchedProperties.isEmpty())
|
| - return 0;
|
| -
|
| - state.style()->setStyleType(pseudoStyleRequest.pseudoId);
|
| -
|
| - applyMatchedProperties(collector.matchedResult(), e);
|
| -
|
| - // Clean up our style object's display and text decorations (among other fixups).
|
| - adjustRenderStyle(state.style(), m_state.parentStyle(), 0);
|
| -
|
| - // Start loading resources referenced by this style.
|
| - loadPendingResources();
|
| -
|
| - document()->didAccessStyleResolver();
|
| -
|
| - // Now return the style.
|
| - return state.takeStyle();
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
|
| -{
|
| - m_state.initForStyleResolve(document(), document()->documentElement()); // m_rootElementStyle will be set to the document style.
|
| -
|
| - m_state.setStyle(RenderStyle::create());
|
| - m_state.style()->inheritFrom(m_state.rootElementStyle());
|
| -
|
| - PageRuleCollector collector(m_state, pageIndex);
|
| -
|
| - collector.matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle);
|
| - collector.matchPageRules(m_ruleSets.userStyle());
|
| - collector.matchPageRules(m_ruleSets.authorStyle());
|
| -
|
| - m_state.setLineHeightValue(0);
|
| - bool inheritedOnly = false;
|
| -
|
| - MatchResult& result = collector.matchedResult();
|
| - applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
|
| - applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
|
| -
|
| - // If our font got dirtied, go ahead and update it now.
|
| - updateFont();
|
| -
|
| - // Line-height is set when we are sure we decided on the font-size.
|
| - if (m_state.lineHeightValue())
|
| - applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue());
|
| -
|
| - applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
|
| -
|
| - // Start loading resources referenced by this style.
|
| - loadPendingResources();
|
| -
|
| - document()->didAccessStyleResolver();
|
| -
|
| - // Now return the style.
|
| - return m_state.takeStyle();
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
|
| -{
|
| - m_state.setStyle(RenderStyle::create());
|
| - // Make sure our fonts are initialized if we don't inherit them from our parent style.
|
| - if (Settings* settings = documentSettings()) {
|
| - initializeFontStyle(settings);
|
| - m_state.style()->font().update(fontSelector());
|
| - } else
|
| - m_state.style()->font().update(0);
|
| -
|
| - return m_state.takeStyle();
|
| -}
|
| -
|
| -PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
|
| -{
|
| - ASSERT(textNode);
|
| -
|
| - NodeRenderingContext context(textNode);
|
| - Node* parentNode = context.parentNodeForRenderingAndStyle();
|
| - return context.resetStyleInheritance() || !parentNode || !parentNode->renderStyle() ?
|
| - defaultStyleForElement() : parentNode->renderStyle();
|
| -}
|
| -
|
| -static void addIntrinsicMargins(RenderStyle* style)
|
| -{
|
| - // Intrinsic margin value.
|
| - const int intrinsicMargin = 2 * style->effectiveZoom();
|
| -
|
| - // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
|
| - // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
|
| - if (style->width().isIntrinsicOrAuto()) {
|
| - if (style->marginLeft().quirk())
|
| - style->setMarginLeft(Length(intrinsicMargin, Fixed));
|
| - if (style->marginRight().quirk())
|
| - style->setMarginRight(Length(intrinsicMargin, Fixed));
|
| - }
|
| -
|
| - if (style->height().isAuto()) {
|
| - if (style->marginTop().quirk())
|
| - style->setMarginTop(Length(intrinsicMargin, Fixed));
|
| - if (style->marginBottom().quirk())
|
| - style->setMarginBottom(Length(intrinsicMargin, Fixed));
|
| - }
|
| -}
|
| -
|
| -static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
|
| -{
|
| - switch (display) {
|
| - case BLOCK:
|
| - case TABLE:
|
| - case BOX:
|
| - case FLEX:
|
| - case GRID:
|
| - case LAZY_BLOCK:
|
| - return display;
|
| -
|
| - case LIST_ITEM:
|
| - // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
|
| - if (!strictParsing && isFloating)
|
| - return BLOCK;
|
| - return display;
|
| - case INLINE_TABLE:
|
| - return TABLE;
|
| - case INLINE_BOX:
|
| - return BOX;
|
| - case INLINE_FLEX:
|
| - return FLEX;
|
| - case INLINE_GRID:
|
| - return GRID;
|
| -
|
| - case INLINE:
|
| - case RUN_IN:
|
| - case COMPACT:
|
| - case INLINE_BLOCK:
|
| - case TABLE_ROW_GROUP:
|
| - case TABLE_HEADER_GROUP:
|
| - case TABLE_FOOTER_GROUP:
|
| - case TABLE_ROW:
|
| - case TABLE_COLUMN_GROUP:
|
| - case TABLE_COLUMN:
|
| - case TABLE_CELL:
|
| - case TABLE_CAPTION:
|
| - return BLOCK;
|
| - case NONE:
|
| - ASSERT_NOT_REACHED();
|
| - return NONE;
|
| - }
|
| - ASSERT_NOT_REACHED();
|
| - return BLOCK;
|
| -}
|
| -
|
| -// CSS requires text-decoration to be reset at each DOM element for tables,
|
| -// inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
|
| -// and absolute or relatively positioned elements.
|
| -static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e)
|
| -{
|
| - return style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
|
| - || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
|
| - || style->isFloating() || style->hasOutOfFlowPosition();
|
| -}
|
| -
|
| -static bool isDisplayFlexibleBox(EDisplay display)
|
| -{
|
| - return display == FLEX || display == INLINE_FLEX;
|
| -}
|
| -
|
| -void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
|
| -{
|
| - ASSERT(parentStyle);
|
| -
|
| - // Cache our original display.
|
| - style->setOriginalDisplay(style->display());
|
| -
|
| - if (style->display() != NONE) {
|
| - // If we have a <td> that specifies a float property, in quirks mode we just drop the float
|
| - // property.
|
| - // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
|
| - // these tags to retain their display types.
|
| - if (document()->inQuirksMode() && e) {
|
| - if (e->hasTagName(tdTag)) {
|
| - style->setDisplay(TABLE_CELL);
|
| - style->setFloating(NoFloat);
|
| - } else if (e->hasTagName(tableTag))
|
| - style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
|
| - }
|
| -
|
| - if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
|
| - if (style->whiteSpace() == KHTML_NOWRAP) {
|
| - // Figure out if we are really nowrapping or if we should just
|
| - // use normal instead. If the width of the cell is fixed, then
|
| - // we don't actually use NOWRAP.
|
| - if (style->width().isFixed())
|
| - style->setWhiteSpace(NORMAL);
|
| - else
|
| - style->setWhiteSpace(NOWRAP);
|
| - }
|
| - }
|
| -
|
| - // Tables never support the -webkit-* values for text-align and will reset back to the default.
|
| - if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
|
| - style->setTextAlign(TASTART);
|
| -
|
| - // Frames and framesets never honor position:relative or position:absolute. This is necessary to
|
| - // fix a crash where a site tries to position these objects. They also never honor display.
|
| - if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
|
| - style->setPosition(StaticPosition);
|
| - style->setDisplay(BLOCK);
|
| - }
|
| -
|
| - // Ruby text does not support float or position. This might change with evolution of the specification.
|
| - if (e && e->hasTagName(rtTag)) {
|
| - style->setPosition(StaticPosition);
|
| - style->setFloating(NoFloat);
|
| - }
|
| -
|
| - // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
|
| - // Table headers with a text-align of -webkit-auto will change the text-align to center.
|
| - if (e && e->hasTagName(thTag) && style->textAlign() == TASTART)
|
| - style->setTextAlign(CENTER);
|
| -
|
| - if (e && e->hasTagName(legendTag))
|
| - style->setDisplay(BLOCK);
|
| -
|
| - // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
|
| - if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document()->documentElement() == e))
|
| - style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document()->inQuirksMode()));
|
| -
|
| - // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
|
| - // clear how that should work.
|
| - if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
|
| - style->setDisplay(INLINE_BLOCK);
|
| -
|
| - // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
|
| - // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
|
| - // on some sites).
|
| - if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
|
| - || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
|
| - && style->hasInFlowPosition())
|
| - style->setPosition(StaticPosition);
|
| -
|
| - // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
|
| - // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
|
| - if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
|
| - || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
|
| - || style->display() == TABLE_CELL)
|
| - style->setWritingMode(parentStyle->writingMode());
|
| -
|
| - // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
|
| - // of block-flow to anything other than TopToBottomWritingMode.
|
| - // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
|
| - if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
|
| - style->setWritingMode(TopToBottomWritingMode);
|
| -
|
| - if (isDisplayFlexibleBox(parentStyle->display())) {
|
| - style->setFloating(NoFloat);
|
| - style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document()->inQuirksMode()));
|
| - }
|
| -
|
| - // Per the spec, position 'static' and 'relative' in the top layer compute to 'absolute'.
|
| - if (e && e->isInTopLayer() && (style->position() == StaticPosition || style->position() == RelativePosition)) {
|
| - style->setPosition(AbsolutePosition);
|
| - style->setDisplay(BLOCK);
|
| - }
|
| - }
|
| -
|
| - // Make sure our z-index value is only applied if the object is positioned.
|
| - if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle->display()))
|
| - style->setHasAutoZIndex();
|
| -
|
| - // Auto z-index becomes 0 for the root element and transparent objects. This prevents
|
| - // cases where objects that should be blended as a single unit end up with a non-transparent
|
| - // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
|
| - if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e)
|
| - || style->opacity() < 1.0f
|
| - || style->hasTransformRelatedProperty()
|
| - || style->hasMask()
|
| - || style->clipPath()
|
| - || style->boxReflect()
|
| - || style->hasFilter()
|
| - || style->hasBlendMode()
|
| - || style->position() == StickyPosition
|
| - || (style->position() == FixedPosition && e && e->document()->page() && e->document()->page()->settings()->fixedPositionCreatesStackingContext())
|
| -#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
|
| - // Touch overflow scrolling creates a stacking context.
|
| - || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
|
| -#endif
|
| - || (e && e->isInTopLayer())
|
| - ))
|
| - style->setZIndex(0);
|
| -
|
| - // Textarea considers overflow visible as auto.
|
| - if (e && e->hasTagName(textareaTag)) {
|
| - style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
|
| - style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
|
| - }
|
| -
|
| - if (doesNotInheritTextDecoration(style, e))
|
| - style->setTextDecorationsInEffect(style->textDecoration());
|
| - else
|
| - style->addToTextDecorationsInEffect(style->textDecoration());
|
| -
|
| - // If either overflow value is not visible, change to auto.
|
| - if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
|
| - style->setOverflowY(OMARQUEE);
|
| - else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
|
| - style->setOverflowX(OMARQUEE);
|
| - else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
|
| - // FIXME: Once we implement pagination controls, overflow-x should default to hidden
|
| - // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
|
| - // default to auto so we can at least scroll through the pages.
|
| - style->setOverflowX(OAUTO);
|
| - } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
|
| - style->setOverflowY(OAUTO);
|
| -
|
| - // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
|
| - // styles are specified on a root element, then they will be incorporated in
|
| - // StyleResolver::styleForDocument().
|
| - if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
|
| - setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style), style);
|
| -
|
| - // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
|
| - // FIXME: Eventually table sections will support auto and scroll.
|
| - if (style->display() == TABLE || style->display() == INLINE_TABLE
|
| - || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
|
| - if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
|
| - style->setOverflowX(OVISIBLE);
|
| - if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
|
| - style->setOverflowY(OVISIBLE);
|
| - }
|
| -
|
| - // Menulists should have visible overflow
|
| - if (style->appearance() == MenulistPart) {
|
| - style->setOverflowX(OVISIBLE);
|
| - style->setOverflowY(OVISIBLE);
|
| - }
|
| -
|
| - // Cull out any useless layers and also repeat patterns into additional layers.
|
| - style->adjustBackgroundLayers();
|
| - style->adjustMaskLayers();
|
| -
|
| - // Do the same for animations and transitions.
|
| - style->adjustAnimations();
|
| - style->adjustTransitions();
|
| -
|
| - // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
|
| - // alter fonts and heights/widths.
|
| - if (e && e->isFormControlElement() && style->fontSize() >= 11) {
|
| - // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
|
| - // so we have to treat all image buttons as though they were explicitly sized.
|
| - if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
|
| - addIntrinsicMargins(style);
|
| - }
|
| -
|
| - // Let the theme also have a crack at adjusting the style.
|
| - if (style->hasAppearance())
|
| - RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
|
| -
|
| - // If we have first-letter pseudo style, do not share this style.
|
| - if (style->hasPseudoStyle(FIRST_LETTER))
|
| - style->setUnique();
|
| -
|
| - // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
|
| - if (style->preserves3D() && (style->overflowX() != OVISIBLE
|
| - || style->overflowY() != OVISIBLE
|
| - || style->hasFilter()))
|
| - style->setTransformStyle3D(TransformStyle3DFlat);
|
| -
|
| - // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
|
| - if (e && e->hasTagName(iframeTag) && style->display() == INLINE && static_cast<HTMLIFrameElement*>(e)->shouldDisplaySeamlessly())
|
| - style->setDisplay(INLINE_BLOCK);
|
| -
|
| - adjustGridItemPosition(style);
|
| -
|
| -#if ENABLE(SVG)
|
| - if (e && e->isSVGElement()) {
|
| - // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
|
| - if (style->overflowY() == OSCROLL)
|
| - style->setOverflowY(OHIDDEN);
|
| - else if (style->overflowY() == OAUTO)
|
| - style->setOverflowY(OVISIBLE);
|
| -
|
| - if (style->overflowX() == OSCROLL)
|
| - style->setOverflowX(OHIDDEN);
|
| - else if (style->overflowX() == OAUTO)
|
| - style->setOverflowX(OVISIBLE);
|
| -
|
| - // Only the root <svg> element in an SVG document fragment tree honors css position
|
| - if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
|
| - style->setPosition(RenderStyle::initialPosition());
|
| -
|
| - // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
|
| - // not be scaled again.
|
| - if (e->hasTagName(SVGNames::foreignObjectTag))
|
| - style->setEffectiveZoom(RenderStyle::initialZoom());
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -void StyleResolver::adjustGridItemPosition(RenderStyle* style) const
|
| -{
|
| - // If opposing grid-placement properties both specify a grid span, they both compute to ‘auto’.
|
| - if (style->gridStart().isSpan() && style->gridEnd().isSpan()) {
|
| - style->setGridStart(GridPosition());
|
| - style->setGridEnd(GridPosition());
|
| - }
|
| -
|
| - if (style->gridBefore().isSpan() && style->gridAfter().isSpan()) {
|
| - style->setGridBefore(GridPosition());
|
| - style->setGridAfter(GridPosition());
|
| - }
|
| -}
|
| -
|
| -bool StyleResolver::checkRegionStyle(Element* regionElement)
|
| -{
|
| - // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
|
| - // so all region rules are global by default. Verify whether that can stand or needs changing.
|
| -
|
| - unsigned rulesSize = m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.size();
|
| - for (unsigned i = 0; i < rulesSize; ++i) {
|
| - ASSERT(m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
|
| - if (checkRegionSelector(m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
|
| - return true;
|
| - }
|
| -
|
| - if (m_ruleSets.userStyle()) {
|
| - rulesSize = m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.size();
|
| - for (unsigned i = 0; i < rulesSize; ++i) {
|
| - ASSERT(m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
|
| - if (checkRegionSelector(m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -static void checkForOrientationChange(RenderStyle* style)
|
| -{
|
| - FontOrientation fontOrientation;
|
| - NonCJKGlyphOrientation glyphOrientation;
|
| - getFontAndGlyphOrientation(style, fontOrientation, glyphOrientation);
|
| -
|
| - const FontDescription& fontDescription = style->fontDescription();
|
| - if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
|
| - return;
|
| -
|
| - FontDescription newFontDescription(fontDescription);
|
| - newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
|
| - newFontDescription.setOrientation(fontOrientation);
|
| - style->setFontDescription(newFontDescription);
|
| -}
|
| -
|
| -void StyleResolver::updateFont()
|
| -{
|
| - if (!m_state.fontDirty())
|
| - return;
|
| -
|
| - RenderStyle* style = m_state.style();
|
| - checkForGenericFamilyChange(style, m_state.parentStyle());
|
| - checkForZoomChange(style, m_state.parentStyle());
|
| - checkForOrientationChange(style);
|
| - style->font().update(m_fontSelector);
|
| - m_state.setFontDirty(false);
|
| -}
|
| -
|
| -PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
|
| -{
|
| - return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
|
| -}
|
| -
|
| -PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
|
| -{
|
| - if (!e || !e->document()->haveStylesheetsLoaded())
|
| - return 0;
|
| -
|
| - initElement(e);
|
| - m_state.initForStyleResolve(document(), e, 0);
|
| -
|
| - ElementRuleCollector collector(this, m_state);
|
| - collector.setMode(SelectorChecker::CollectingRules);
|
| - collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
|
| -
|
| - if (rulesToInclude & UAAndUserCSSRules) {
|
| - // First we match rules from the user agent sheet.
|
| - matchUARules(collector);
|
| -
|
| - // Now we check user sheet rules.
|
| - if (m_matchAuthorAndUserStyles)
|
| - matchUserRules(collector, rulesToInclude & EmptyCSSRules);
|
| - }
|
| -
|
| - if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
|
| - collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
|
| -
|
| - // Check the rules in author sheets.
|
| - matchAuthorRules(collector, rulesToInclude & EmptyCSSRules);
|
| - }
|
| -
|
| - return collector.matchedRuleList();
|
| -}
|
| -
|
| -// -------------------------------------------------------------------------------------
|
| -// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
|
| -
|
| -Length StyleResolver::convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
|
| -{
|
| - return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
|
| -}
|
| -
|
| -Length StyleResolver::convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
|
| -{
|
| - return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
|
| -}
|
| -
|
| -template <StyleResolver::StyleApplicationPass pass>
|
| -void StyleResolver::applyAnimatedProperties(const Element* target)
|
| -{
|
| - if (!target->hasActiveAnimations())
|
| - return;
|
| -
|
| - Vector<Animation*>* animations = target->activeAnimations();
|
| -
|
| - for (size_t i = 0; i < animations->size(); ++i) {
|
| - RefPtr<Animation> animation = animations->at(i);
|
| - RefPtr<StylePropertySet> properties = animation->cachedStyle();
|
| - for (unsigned j = 0; j < properties->propertyCount(); ++j) {
|
| - StylePropertySet::PropertyReference current = properties->propertyAt(j);
|
| - CSSPropertyID property = current.id();
|
| - switch (pass) {
|
| - case VariableDefinitions:
|
| - ASSERT_NOT_REACHED();
|
| - continue;
|
| - case HighPriorityProperties:
|
| - if (property < CSSPropertyLineHeight)
|
| - applyProperty(current.id(), current.value());
|
| - else if (property == CSSPropertyLineHeight)
|
| - m_state.setLineHeightValue(current.value());
|
| - continue;
|
| - case LowPriorityProperties:
|
| - if (property > CSSPropertyLineHeight)
|
| - applyProperty(current.id(), current.value());
|
| - continue;
|
| - }
|
| - }
|
| - }
|
| -
|
| -}
|
| -
|
| -template <StyleResolver::StyleApplicationPass pass>
|
| -void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
|
| -{
|
| - ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || m_state.regionForStyling());
|
| - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), rule, this);
|
| -
|
| - unsigned propertyCount = properties->propertyCount();
|
| - for (unsigned i = 0; i < propertyCount; ++i) {
|
| - StylePropertySet::PropertyReference current = properties->propertyAt(i);
|
| - if (isImportant != current.isImportant())
|
| - continue;
|
| - if (inheritedOnly && !current.isInherited()) {
|
| - // If the property value is explicitly inherited, we need to apply further non-inherited properties
|
| - // as they might override the value inherited here. For this reason we don't allow declarations with
|
| - // explicitly inherited properties to be cached.
|
| - ASSERT(!current.value()->isInheritedValue());
|
| - continue;
|
| - }
|
| - CSSPropertyID property = current.id();
|
| -
|
| - if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(property))
|
| - continue;
|
| - if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(property))
|
| - continue;
|
| - switch (pass) {
|
| - case VariableDefinitions:
|
| - COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_is_before_first_property);
|
| - if (property == CSSPropertyVariable)
|
| - applyProperty(current.id(), current.value());
|
| - break;
|
| - case HighPriorityProperties:
|
| - COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
|
| - COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is_end_of_first_prop_range);
|
| - COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
|
| - if (property == CSSPropertyVariable)
|
| - continue;
|
| - // give special priority to font-xxx, color properties, etc
|
| - if (property < CSSPropertyLineHeight)
|
| - applyProperty(current.id(), current.value());
|
| - // we apply line-height later
|
| - else if (property == CSSPropertyLineHeight)
|
| - m_state.setLineHeightValue(current.value());
|
| - break;
|
| - case LowPriorityProperties:
|
| - if (property > CSSPropertyLineHeight)
|
| - applyProperty(current.id(), current.value());
|
| - }
|
| - }
|
| - InspectorInstrumentation::didProcessRule(cookie);
|
| -}
|
| -
|
| -template <StyleResolver::StyleApplicationPass pass>
|
| -void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
|
| -{
|
| - if (startIndex == -1)
|
| - return;
|
| -
|
| - StyleResolverState& state = m_state;
|
| - if (state.style()->insideLink() != NotInsideLink) {
|
| - for (int i = startIndex; i <= endIndex; ++i) {
|
| - const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
|
| - unsigned linkMatchType = matchedProperties.linkMatchType;
|
| - // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
|
| - state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
|
| - state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
|
| -
|
| - applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
|
| - }
|
| - state.setApplyPropertyToRegularStyle(true);
|
| - state.setApplyPropertyToVisitedLinkStyle(false);
|
| - return;
|
| - }
|
| - for (int i = startIndex; i <= endIndex; ++i) {
|
| - const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
|
| - applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
|
| - }
|
| -}
|
| -
|
| -unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
|
| -{
|
| -
|
| - return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
|
| -}
|
| -
|
| -bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
|
| -{
|
| - return a.firstUARule == b.firstUARule
|
| - && a.lastUARule == b.lastUARule
|
| - && a.firstAuthorRule == b.firstAuthorRule
|
| - && a.lastAuthorRule == b.lastAuthorRule
|
| - && a.firstUserRule == b.firstUserRule
|
| - && a.lastUserRule == b.lastUserRule;
|
| -}
|
| -
|
| -bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
|
| -{
|
| - return !(a == b);
|
| -}
|
| -
|
| -bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
|
| -{
|
| - return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
|
| -}
|
| -
|
| -bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
|
| -{
|
| - return !(a == b);
|
| -}
|
| -
|
| -const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
|
| -{
|
| - ASSERT(hash);
|
| -
|
| - MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
|
| - if (it == m_matchedPropertiesCache.end())
|
| - return 0;
|
| - MatchedPropertiesCacheItem& cacheItem = it->value;
|
| -
|
| - size_t size = matchResult.matchedProperties.size();
|
| - if (size != cacheItem.matchedProperties.size())
|
| - return 0;
|
| - if (cacheItem.renderStyle->insideLink() != m_state.style()->insideLink())
|
| - return 0;
|
| - for (size_t i = 0; i < size; ++i) {
|
| - if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
|
| - return 0;
|
| - }
|
| - if (cacheItem.ranges != matchResult.ranges)
|
| - return 0;
|
| - return &cacheItem;
|
| -}
|
| -
|
| -void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
|
| -{
|
| - static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
|
| - if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps
|
| - && !m_matchedPropertiesCacheSweepTimer.isActive()) {
|
| - static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
|
| - m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
|
| - }
|
| -
|
| - ASSERT(hash);
|
| - MatchedPropertiesCacheItem cacheItem;
|
| - cacheItem.matchedProperties.append(matchResult.matchedProperties);
|
| - cacheItem.ranges = matchResult.ranges;
|
| - // Note that we don't cache the original RenderStyle instance. It may be further modified.
|
| - // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
|
| - cacheItem.renderStyle = RenderStyle::clone(style);
|
| - cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
|
| - m_matchedPropertiesCache.add(hash, cacheItem);
|
| -}
|
| -
|
| -void StyleResolver::invalidateMatchedPropertiesCache()
|
| -{
|
| - m_matchedPropertiesCache.clear();
|
| -}
|
| -
|
| -static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
|
| -{
|
| - // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
|
| - if (element == element->document()->documentElement() && element->document()->writingModeSetOnDocumentElement())
|
| - return false;
|
| - if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
|
| - return false;
|
| - if (style->hasAppearance())
|
| - return false;
|
| - if (style->zoom() != RenderStyle::initialZoom())
|
| - return false;
|
| - if (style->writingMode() != RenderStyle::initialWritingMode())
|
| - return false;
|
| - // The cache assumes static knowledge about which properties are inherited.
|
| - if (parentStyle->hasExplicitlyInheritedProperties())
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element)
|
| -{
|
| - ASSERT(element);
|
| - StyleResolverState& state = m_state;
|
| - unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
|
| - bool applyInheritedOnly = false;
|
| - const MatchedPropertiesCacheItem* cacheItem = 0;
|
| - if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
|
| - // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
|
| - // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
|
| - // element context. This is fast and saves memory by reusing the style data structures.
|
| - state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
|
| - if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
|
| - EInsideLink linkStatus = state.style()->insideLink();
|
| - // If the cache item parent style has identical inherited properties to the current parent style then the
|
| - // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
|
| - state.style()->inheritFrom(cacheItem->renderStyle.get());
|
| -
|
| - // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
|
| - state.style()->setInsideLink(linkStatus);
|
| - return;
|
| - }
|
| - applyInheritedOnly = true;
|
| - }
|
| -
|
| - // First apply all variable definitions, as they may be used during application of later properties.
|
| - applyMatchedProperties<VariableDefinitions>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
|
| - applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
|
| - applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
|
| - applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
|
| -
|
| - // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
|
| - // high-priority properties first, i.e., those properties that other properties depend on.
|
| - // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
|
| - // and (4) normal important.
|
| - state.setLineHeightValue(0);
|
| - applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
|
| - // Animation contributions are processed here because CSS Animations are overridable by user !important rules.
|
| - if (RuntimeEnabledFeatures::webAnimationEnabled())
|
| - applyAnimatedProperties<HighPriorityProperties>(element);
|
| - applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
|
| - applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
|
| - applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
|
| -
|
| - if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
|
| - state.setFontDirty(true);
|
| - applyInheritedOnly = false;
|
| - }
|
| -
|
| - // If our font got dirtied, go ahead and update it now.
|
| - updateFont();
|
| -
|
| - // Line-height is set when we are sure we decided on the font-size.
|
| - if (state.lineHeightValue())
|
| - applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
|
| -
|
| - // Many properties depend on the font. If it changes we just apply all properties.
|
| - if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
|
| - applyInheritedOnly = false;
|
| -
|
| - // Now do the normal priority UA properties.
|
| - applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
|
| -
|
| - // Cache our border and background so that we can examine them later.
|
| - state.cacheBorderAndBackground();
|
| -
|
| - // Now do the author and user normal priority properties and all the !important properties.
|
| - applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
|
| - if (RuntimeEnabledFeatures::webAnimationEnabled())
|
| - applyAnimatedProperties<LowPriorityProperties>(element);
|
| - applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
|
| - applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
|
| - applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
|
| -
|
| - // Start loading resources referenced by this style.
|
| - loadPendingResources();
|
| -
|
| - ASSERT(!state.fontDirty());
|
| -
|
| - if (cacheItem || !cacheHash)
|
| - return;
|
| - if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
|
| - return;
|
| - addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
|
| -}
|
| -
|
| -void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
|
| -{
|
| - initElement(0);
|
| - m_state.initForStyleResolve(document(), 0, style);
|
| - m_state.setStyle(style);
|
| - applyPropertyToCurrentStyle(id, value);
|
| -}
|
| -
|
| -void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
|
| -{
|
| - if (value)
|
| - applyProperty(id, value);
|
| -}
|
| -
|
| -inline bool isValidVisitedLinkProperty(CSSPropertyID id)
|
| -{
|
| - switch (id) {
|
| - case CSSPropertyBackgroundColor:
|
| - case CSSPropertyBorderLeftColor:
|
| - case CSSPropertyBorderRightColor:
|
| - case CSSPropertyBorderTopColor:
|
| - case CSSPropertyBorderBottomColor:
|
| - case CSSPropertyColor:
|
| - case CSSPropertyOutlineColor:
|
| - case CSSPropertyWebkitColumnRuleColor:
|
| -#if ENABLE(CSS3_TEXT)
|
| - case CSSPropertyWebkitTextDecorationColor:
|
| -#endif // CSS3_TEXT
|
| - case CSSPropertyWebkitTextEmphasisColor:
|
| - case CSSPropertyWebkitTextFillColor:
|
| - case CSSPropertyWebkitTextStrokeColor:
|
| -#if ENABLE(SVG)
|
| - case CSSPropertyFill:
|
| - case CSSPropertyStroke:
|
| -#endif
|
| - return true;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -// http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
|
| -// FIXME: add incremental support for other region styling properties.
|
| -inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
|
| -{
|
| - switch (id) {
|
| - case CSSPropertyBackgroundColor:
|
| - case CSSPropertyColor:
|
| - return true;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
|
| -{
|
| - switch (id) {
|
| - case CSSPropertyBackground:
|
| - case CSSPropertyBackgroundAttachment:
|
| - case CSSPropertyBackgroundClip:
|
| - case CSSPropertyBackgroundColor:
|
| - case CSSPropertyBackgroundImage:
|
| - case CSSPropertyBackgroundOrigin:
|
| - case CSSPropertyBackgroundPosition:
|
| - case CSSPropertyBackgroundPositionX:
|
| - case CSSPropertyBackgroundPositionY:
|
| - case CSSPropertyBackgroundRepeat:
|
| - case CSSPropertyBackgroundRepeatX:
|
| - case CSSPropertyBackgroundRepeatY:
|
| - case CSSPropertyBackgroundSize:
|
| - case CSSPropertyColor:
|
| - case CSSPropertyFont:
|
| - case CSSPropertyFontFamily:
|
| - case CSSPropertyFontSize:
|
| - case CSSPropertyFontStyle:
|
| - case CSSPropertyFontVariant:
|
| - case CSSPropertyFontWeight:
|
| - case CSSPropertyLineHeight:
|
| - case CSSPropertyOpacity:
|
| - case CSSPropertyOutline:
|
| - case CSSPropertyOutlineColor:
|
| - case CSSPropertyOutlineOffset:
|
| - case CSSPropertyOutlineStyle:
|
| - case CSSPropertyOutlineWidth:
|
| - case CSSPropertyVisibility:
|
| - case CSSPropertyWhiteSpace:
|
| - case CSSPropertyTextDecoration:
|
| - case CSSPropertyTextShadow:
|
| - case CSSPropertyBorderStyle:
|
| - return true;
|
| - default:
|
| - break;
|
| - }
|
| - return false;
|
| -}
|
| -// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
|
| -// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
|
| -// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
|
| -// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
|
| -// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
|
| -// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
|
| -// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
|
| -// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
|
| -bool StyleResolver::useSVGZoomRules()
|
| -{
|
| - return m_state.element() && m_state.element()->isSVGElement();
|
| -}
|
| -
|
| -static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolverState& state, GridLength& workingLength)
|
| -{
|
| - if (primitiveValue->getIdent() == CSSValueWebkitMinContent) {
|
| - workingLength = Length(MinContent);
|
| - return true;
|
| - }
|
| -
|
| - if (primitiveValue->getIdent() == CSSValueWebkitMaxContent) {
|
| - workingLength = Length(MaxContent);
|
| - return true;
|
| - }
|
| -
|
| - if (primitiveValue->isFlex()) {
|
| - // Fractional unit.
|
| - workingLength.setFlex(primitiveValue->getFloatValue());
|
| - return true;
|
| - }
|
| -
|
| - workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
|
| - if (workingLength.length().isUndefined())
|
| - return false;
|
| -
|
| - if (primitiveValue->isLength())
|
| - workingLength.length().setQuirk(primitiveValue->isQuirkValue());
|
| -
|
| - return true;
|
| -}
|
| -
|
| -static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolverState& state)
|
| -{
|
| - if (!value->isPrimitiveValue())
|
| - return false;
|
| -
|
| - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
|
| - Pair* minMaxTrackBreadth = primitiveValue->getPairValue();
|
| - if (!minMaxTrackBreadth) {
|
| - GridLength workingLength;
|
| - if (!createGridTrackBreadth(primitiveValue, state, workingLength))
|
| - return false;
|
| -
|
| - trackSize.setLength(workingLength);
|
| - return true;
|
| - }
|
| -
|
| - GridLength minTrackBreadth;
|
| - GridLength maxTrackBreadth;
|
| - if (!createGridTrackBreadth(minMaxTrackBreadth->first(), state, minTrackBreadth) || !createGridTrackBreadth(minMaxTrackBreadth->second(), state, maxTrackBreadth))
|
| - return false;
|
| -
|
| - trackSize.setMinMax(minTrackBreadth, maxTrackBreadth);
|
| - return true;
|
| -}
|
| -
|
| -static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, const StyleResolverState& state)
|
| -{
|
| - // Handle 'none'.
|
| - if (value->isPrimitiveValue()) {
|
| - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
|
| - return primitiveValue->getIdent() == CSSValueNone;
|
| - }
|
| -
|
| - if (!value->isValueList())
|
| - return false;
|
| -
|
| - size_t currentNamedGridLine = 0;
|
| - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
|
| - CSSValue* currValue = i.value();
|
| - if (currValue->isPrimitiveValue()) {
|
| - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(currValue);
|
| - if (primitiveValue->isString()) {
|
| - NamedGridLinesMap::AddResult result = namedGridLines.add(primitiveValue->getStringValue(), Vector<size_t>());
|
| - result.iterator->value.append(currentNamedGridLine);
|
| - continue;
|
| - }
|
| - }
|
| -
|
| - ++currentNamedGridLine;
|
| - GridTrackSize trackSize;
|
| - if (!createGridTrackSize(currValue, trackSize, state))
|
| - return false;
|
| -
|
| - trackSizes.append(trackSize);
|
| - }
|
| -
|
| - if (trackSizes.isEmpty())
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -
|
| -static bool createGridPosition(CSSValue* value, GridPosition& position)
|
| -{
|
| - // For now, we only accept: 'auto' | <integer> | span && <integer>?
|
| - if (value->isPrimitiveValue()) {
|
| - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
|
| - if (primitiveValue->getIdent() == CSSValueAuto)
|
| - return true;
|
| -
|
| - if (primitiveValue->getIdent() == CSSValueSpan) {
|
| - // If the <integer> is omitted, it defaults to '1'.
|
| - position.setSpanPosition(1);
|
| - return true;
|
| - }
|
| -
|
| - ASSERT(primitiveValue->isNumber());
|
| - position.setIntegerPosition(primitiveValue->getIntValue());
|
| - return true;
|
| - }
|
| -
|
| - ASSERT_WITH_SECURITY_IMPLICATION(value->isValueList());
|
| - CSSValueList* values = static_cast<CSSValueList*>(value);
|
| - ASSERT(values->length() == 2);
|
| - ASSERT_WITH_SECURITY_IMPLICATION(values->itemWithoutBoundsCheck(1)->isPrimitiveValue());
|
| - CSSPrimitiveValue* numericValue = static_cast<CSSPrimitiveValue*>(values->itemWithoutBoundsCheck(1));
|
| - ASSERT(numericValue->isNumber());
|
| - position.setSpanPosition(numericValue->getIntValue());
|
| - return true;
|
| -}
|
| -
|
| -static bool hasVariableReference(CSSValue* value)
|
| -{
|
| - if (value->isPrimitiveValue()) {
|
| - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
|
| - return primitiveValue->hasVariableReference();
|
| - }
|
| -
|
| - if (value->isCalculationValue())
|
| - return static_cast<CSSCalcValue*>(value)->hasVariableReference();
|
| -
|
| - if (value->isReflectValue()) {
|
| - CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
|
| - CSSPrimitiveValue* direction = reflectValue->direction();
|
| - CSSPrimitiveValue* offset = reflectValue->offset();
|
| - CSSValue* mask = reflectValue->mask();
|
| - return (direction && hasVariableReference(direction)) || (offset && hasVariableReference(offset)) || (mask && hasVariableReference(mask));
|
| - }
|
| -
|
| - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
|
| - if (hasVariableReference(i.value()))
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<std::pair<CSSPropertyID, String> >& knownExpressions)
|
| -{
|
| - std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVariables(*m_state.style()->variables()));
|
| -
|
| - if (knownExpressions.contains(expression))
|
| - return; // cycle detected.
|
| -
|
| - knownExpressions.append(expression);
|
| -
|
| - // FIXME: It would be faster not to re-parse from strings, but for now CSS property validation lives inside the parser so we do it there.
|
| - RefPtr<StylePropertySet> resultSet = StylePropertySet::create();
|
| - if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, document()))
|
| - return; // expression failed to parse.
|
| -
|
| - for (unsigned i = 0; i < resultSet->propertyCount(); i++) {
|
| - StylePropertySet::PropertyReference property = resultSet->propertyAt(i);
|
| - if (property.id() != CSSPropertyVariable && hasVariableReference(property.value()))
|
| - resolveVariables(property.id(), property.value(), knownExpressions);
|
| - else
|
| - applyProperty(property.id(), property.value());
|
| - }
|
| -}
|
| -
|
| -void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
|
| -{
|
| - if (id != CSSPropertyVariable && hasVariableReference(value)) {
|
| - Vector<std::pair<CSSPropertyID, String> > knownExpressions;
|
| - resolveVariables(id, value, knownExpressions);
|
| - return;
|
| - }
|
| -
|
| - // CSS variables don't resolve shorthands at parsing time, so this should be *after* handling variables.
|
| - ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
|
| -
|
| - StyleResolverState& state = m_state;
|
| - bool isInherit = state.parentNode() && value->isInheritedValue();
|
| - bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
|
| -
|
| - ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
|
| - ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
|
| -
|
| - if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
|
| - // Limit the properties that can be applied to only the ones honored by :visited.
|
| - return;
|
| - }
|
| -
|
| - if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
|
| - state.parentStyle()->setHasExplicitlyInheritedProperties();
|
| -
|
| - if (id == CSSPropertyVariable) {
|
| - ASSERT_WITH_SECURITY_IMPLICATION(value->isVariableValue());
|
| - CSSVariableValue* variable = static_cast<CSSVariableValue*>(value);
|
| - ASSERT(!variable->name().isEmpty());
|
| - ASSERT(!variable->value().isEmpty());
|
| - state.style()->setVariable(variable->name(), variable->value());
|
| - return;
|
| - }
|
| -
|
| - // Check lookup table for implementations and use when available.
|
| - const PropertyHandler& handler = m_styleBuilder.propertyHandler(id);
|
| - if (handler.isValid()) {
|
| - if (isInherit)
|
| - handler.applyInheritValue(id, this);
|
| - else if (isInitial)
|
| - handler.applyInitialValue(id, this);
|
| - else
|
| - handler.applyValue(id, this, value);
|
| - return;
|
| - }
|
| -
|
| - CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
|
| -
|
| - float zoomFactor = state.style()->effectiveZoom();
|
| -
|
| - // What follows is a list that maps the CSS properties into their corresponding front-end
|
| - // RenderStyle values.
|
| - switch (id) {
|
| - // lists
|
| - case CSSPropertyContent:
|
| - // list of string, uri, counter, attr, i
|
| - {
|
| - // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
|
| - // note is a reminder that eventually "inherit" needs to be supported.
|
| -
|
| - if (isInitial) {
|
| - state.style()->clearContent();
|
| - return;
|
| - }
|
| -
|
| - if (!value->isValueList())
|
| - return;
|
| -
|
| - bool didSet = false;
|
| - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
|
| - CSSValue* item = i.value();
|
| - if (item->isImageGeneratorValue()) {
|
| - if (item->isGradientValue())
|
| - state.style()->setContent(StyleGeneratedImage::create(static_cast<CSSGradientValue*>(item)->gradientWithStylesResolved(this).get()), didSet);
|
| - else
|
| - state.style()->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
|
| - didSet = true;
|
| - } else if (item->isImageSetValue()) {
|
| - state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageSetValue*>(item)), didSet);
|
| - didSet = true;
|
| - }
|
| -
|
| - if (item->isImageValue()) {
|
| - state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(item)), didSet);
|
| - didSet = true;
|
| - continue;
|
| - }
|
| -
|
| - if (!item->isPrimitiveValue())
|
| - continue;
|
| -
|
| - CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
|
| -
|
| - if (contentValue->isString()) {
|
| - state.style()->setContent(contentValue->getStringValue().impl(), didSet);
|
| - didSet = true;
|
| - } else if (contentValue->isAttr()) {
|
| - // FIXME: Can a namespace be specified for an attr(foo)?
|
| - if (state.style()->styleType() == NOPSEUDO)
|
| - state.style()->setUnique();
|
| - else
|
| - state.parentStyle()->setUnique();
|
| - QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
|
| - const AtomicString& value = state.element()->getAttribute(attr);
|
| - state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
|
| - didSet = true;
|
| - // register the fact that the attribute value affects the style
|
| - m_ruleSets.features().attrsInRules.add(attr.localName().impl());
|
| - } else if (contentValue->isCounter()) {
|
| - Counter* counterValue = contentValue->getCounterValue();
|
| - EListStyleType listStyleType = NoneListStyle;
|
| - int listStyleIdent = counterValue->listStyleIdent();
|
| - if (listStyleIdent != CSSValueNone)
|
| - listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
|
| - OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
|
| - state.style()->setContent(counter.release(), didSet);
|
| - didSet = true;
|
| - } else {
|
| - switch (contentValue->getIdent()) {
|
| - case CSSValueOpenQuote:
|
| - state.style()->setContent(OPEN_QUOTE, didSet);
|
| - didSet = true;
|
| - break;
|
| - case CSSValueCloseQuote:
|
| - state.style()->setContent(CLOSE_QUOTE, didSet);
|
| - didSet = true;
|
| - break;
|
| - case CSSValueNoOpenQuote:
|
| - state.style()->setContent(NO_OPEN_QUOTE, didSet);
|
| - didSet = true;
|
| - break;
|
| - case CSSValueNoCloseQuote:
|
| - state.style()->setContent(NO_CLOSE_QUOTE, didSet);
|
| - didSet = true;
|
| - break;
|
| - default:
|
| - // normal and none do not have any effect.
|
| - { }
|
| - }
|
| - }
|
| - }
|
| - if (!didSet)
|
| - state.style()->clearContent();
|
| - return;
|
| - }
|
| - case CSSPropertyQuotes:
|
| - if (isInherit) {
|
| - state.style()->setQuotes(state.parentStyle()->quotes());
|
| - return;
|
| - }
|
| - if (isInitial) {
|
| - state.style()->setQuotes(0);
|
| - return;
|
| - }
|
| - if (value->isValueList()) {
|
| - CSSValueList* list = static_cast<CSSValueList*>(value);
|
| - RefPtr<QuotesData> quotes = QuotesData::create();
|
| - for (size_t i = 0; i < list->length(); i += 2) {
|
| - CSSValue* first = list->itemWithoutBoundsCheck(i);
|
| - // item() returns null if out of bounds so this is safe.
|
| - CSSValue* second = list->item(i + 1);
|
| - if (!second)
|
| - continue;
|
| - ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue());
|
| - ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue());
|
| - String startQuote = static_cast<CSSPrimitiveValue*>(first)->getStringValue();
|
| - String endQuote = static_cast<CSSPrimitiveValue*>(second)->getStringValue();
|
| - quotes->addPair(std::make_pair(startQuote, endQuote));
|
| - }
|
| - state.style()->setQuotes(quotes);
|
| - return;
|
| - }
|
| - if (primitiveValue) {
|
| - if (primitiveValue->getIdent() == CSSValueNone)
|
| - state.style()->setQuotes(QuotesData::create());
|
| - }
|
| - return;
|
| - // Shorthand properties.
|
| - case CSSPropertyFont:
|
| - if (isInherit) {
|
| - FontDescription fontDescription = state.parentStyle()->fontDescription();
|
| - state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight());
|
| - state.setLineHeightValue(0);
|
| - setFontDescription(fontDescription);
|
| - } else if (isInitial) {
|
| - Settings* settings = documentSettings();
|
| - ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
|
| - if (!settings)
|
| - return;
|
| - initializeFontStyle(settings);
|
| - } else if (primitiveValue) {
|
| - state.style()->setLineHeight(RenderStyle::initialLineHeight());
|
| - state.setLineHeightValue(0);
|
| -
|
| - FontDescription fontDescription;
|
| - RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
|
| -
|
| - // Double-check and see if the theme did anything. If not, don't bother updating the font.
|
| - if (fontDescription.isAbsoluteSize()) {
|
| - // Make sure the rendering mode and printer font settings are updated.
|
| - Settings* settings = documentSettings();
|
| - ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
|
| - if (!settings)
|
| - return;
|
| - fontDescription.setRenderingMode(settings->fontRenderingMode());
|
| - fontDescription.setUsePrinterFont(document()->printing());
|
| -
|
| - // Handle the zoom factor.
|
| - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(document(), state.style(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
|
| - setFontDescription(fontDescription);
|
| - }
|
| - } else if (value->isFontValue()) {
|
| - FontValue* font = static_cast<FontValue*>(value);
|
| - if (!font->style || !font->variant || !font->weight
|
| - || !font->size || !font->lineHeight || !font->family)
|
| - return;
|
| - applyProperty(CSSPropertyFontStyle, font->style.get());
|
| - applyProperty(CSSPropertyFontVariant, font->variant.get());
|
| - applyProperty(CSSPropertyFontWeight, font->weight.get());
|
| - // The previous properties can dirty our font but they don't try to read the font's
|
| - // properties back, which is safe. However if font-size is using the 'ex' unit, it will
|
| - // need query the dirtied font's x-height to get the computed size. To be safe in this
|
| - // case, let's just update the font now.
|
| - updateFont();
|
| - applyProperty(CSSPropertyFontSize, font->size.get());
|
| -
|
| - state.setLineHeightValue(font->lineHeight.get());
|
| -
|
| - applyProperty(CSSPropertyFontFamily, font->family.get());
|
| - }
|
| - return;
|
| -
|
| - case CSSPropertyBackground:
|
| - case CSSPropertyBackgroundPosition:
|
| - case CSSPropertyBackgroundRepeat:
|
| - case CSSPropertyBorder:
|
| - case CSSPropertyBorderBottom:
|
| - case CSSPropertyBorderColor:
|
| - case CSSPropertyBorderImage:
|
| - case CSSPropertyBorderLeft:
|
| - case CSSPropertyBorderRadius:
|
| - case CSSPropertyBorderRight:
|
| - case CSSPropertyBorderSpacing:
|
| - case CSSPropertyBorderStyle:
|
| - case CSSPropertyBorderTop:
|
| - case CSSPropertyBorderWidth:
|
| - case CSSPropertyListStyle:
|
| - case CSSPropertyMargin:
|
| - case CSSPropertyOutline:
|
| - case CSSPropertyOverflow:
|
| - case CSSPropertyPadding:
|
| - case CSSPropertyTransition:
|
| - case CSSPropertyWebkitAnimation:
|
| - case CSSPropertyWebkitBorderAfter:
|
| - case CSSPropertyWebkitBorderBefore:
|
| - case CSSPropertyWebkitBorderEnd:
|
| - case CSSPropertyWebkitBorderStart:
|
| - case CSSPropertyWebkitBorderRadius:
|
| - case CSSPropertyWebkitColumns:
|
| - case CSSPropertyWebkitColumnRule:
|
| - case CSSPropertyWebkitFlex:
|
| - case CSSPropertyWebkitFlexFlow:
|
| - case CSSPropertyWebkitGridColumn:
|
| - case CSSPropertyWebkitGridRow:
|
| - case CSSPropertyWebkitMarginCollapse:
|
| - case CSSPropertyWebkitMarquee:
|
| - case CSSPropertyWebkitMask:
|
| - case CSSPropertyWebkitMaskPosition:
|
| - case CSSPropertyWebkitMaskRepeat:
|
| - case CSSPropertyWebkitTextEmphasis:
|
| - case CSSPropertyWebkitTextStroke:
|
| - case CSSPropertyWebkitTransition:
|
| - case CSSPropertyWebkitTransformOrigin:
|
| - case CSSPropertyWebkitWrap:
|
| - ASSERT(isExpandedShorthand(id));
|
| - ASSERT_NOT_REACHED();
|
| - break;
|
| -
|
| - // CSS3 Properties
|
| - case CSSPropertyTextShadow:
|
| - case CSSPropertyBoxShadow:
|
| - case CSSPropertyWebkitBoxShadow: {
|
| - if (isInherit) {
|
| - if (id == CSSPropertyTextShadow)
|
| - return state.style()->setTextShadow(state.parentStyle()->textShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr);
|
| - return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr);
|
| - }
|
| - if (isInitial || primitiveValue) // initial | none
|
| - return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr);
|
| -
|
| - if (!value->isValueList())
|
| - return;
|
| -
|
| - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
|
| - CSSValue* currValue = i.value();
|
| - if (!currValue->isShadowValue())
|
| - continue;
|
| - ShadowValue* item = static_cast<ShadowValue*>(currValue);
|
| - int x = item->x->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - int y = item->y->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
|
| - int spread = item->spread ? item->spread->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
|
| - ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
|
| - Color color;
|
| - if (item->color)
|
| - color = m_state.colorFromPrimitiveValue(item->color.get());
|
| - else if (state.style())
|
| - color = state.style()->color();
|
| -
|
| - OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
|
| - if (id == CSSPropertyTextShadow)
|
| - state.style()->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
|
| - else
|
| - state.style()->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
|
| - }
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitBoxReflect: {
|
| - HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
|
| - if (primitiveValue) {
|
| - state.style()->setBoxReflect(RenderStyle::initialBoxReflect());
|
| - return;
|
| - }
|
| -
|
| - if (!value->isReflectValue())
|
| - return;
|
| -
|
| - CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
|
| - RefPtr<StyleReflection> reflection = StyleReflection::create();
|
| - reflection->setDirection(*reflectValue->direction());
|
| - if (reflectValue->offset())
|
| - reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.style(), state.rootElementStyle(), zoomFactor));
|
| - NinePieceImage mask;
|
| - mask.setMaskDefaults();
|
| - m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
|
| - reflection->setMask(mask);
|
| -
|
| - state.style()->setBoxReflect(reflection.release());
|
| - return;
|
| - }
|
| - case CSSPropertySrc: // Only used in @font-face rules.
|
| - return;
|
| - case CSSPropertyUnicodeRange: // Only used in @font-face rules.
|
| - return;
|
| - case CSSPropertyWebkitLocale: {
|
| - HANDLE_INHERIT_AND_INITIAL(locale, Locale);
|
| - if (!primitiveValue)
|
| - return;
|
| - if (primitiveValue->getIdent() == CSSValueAuto)
|
| - state.style()->setLocale(nullAtom);
|
| - else
|
| - state.style()->setLocale(primitiveValue->getStringValue());
|
| - FontDescription fontDescription = state.style()->fontDescription();
|
| - fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale()));
|
| - setFontDescription(fontDescription);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitAppRegion: {
|
| - if (!primitiveValue || !primitiveValue->getIdent())
|
| - return;
|
| - state.style()->setDraggableRegionMode(primitiveValue->getIdent() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
|
| - state.document()->setHasAnnotatedRegions(true);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitTextStrokeWidth: {
|
| - HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
|
| - float width = 0;
|
| - switch (primitiveValue->getIdent()) {
|
| - case CSSValueThin:
|
| - case CSSValueMedium:
|
| - case CSSValueThick: {
|
| - double result = 1.0 / 48;
|
| - if (primitiveValue->getIdent() == CSSValueMedium)
|
| - result *= 3;
|
| - else if (primitiveValue->getIdent() == CSSValueThick)
|
| - result *= 5;
|
| - width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - break;
|
| - }
|
| - default:
|
| - width = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - break;
|
| - }
|
| - state.style()->setTextStrokeWidth(width);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitTransform: {
|
| - HANDLE_INHERIT_AND_INITIAL(transform, Transform);
|
| - TransformOperations operations;
|
| - TransformBuilder::createTransformOperations(value, state.style(), state.rootElementStyle(), operations);
|
| - state.style()->setTransform(operations);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitPerspective: {
|
| - HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
|
| -
|
| - if (!primitiveValue)
|
| - return;
|
| -
|
| - if (primitiveValue->getIdent() == CSSValueNone) {
|
| - state.style()->setPerspective(0);
|
| - return;
|
| - }
|
| -
|
| - float perspectiveValue;
|
| - if (primitiveValue->isLength())
|
| - perspectiveValue = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - else if (primitiveValue->isNumber()) {
|
| - // For backward compatibility, treat valueless numbers as px.
|
| - perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
|
| - } else
|
| - return;
|
| -
|
| - if (perspectiveValue >= 0.0f)
|
| - state.style()->setPerspective(perspectiveValue);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitTapHighlightColor: {
|
| - HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
|
| - if (!primitiveValue)
|
| - break;
|
| -
|
| - Color col = m_state.colorFromPrimitiveValue(primitiveValue);
|
| - state.style()->setTapHighlightColor(col);
|
| - return;
|
| - }
|
| -#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
|
| - case CSSPropertyWebkitOverflowScrolling: {
|
| - HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
|
| - if (!primitiveValue)
|
| - break;
|
| - state.style()->setUseTouchOverflowScrolling(primitiveValue->getIdent() == CSSValueTouch);
|
| - return;
|
| - }
|
| -#endif
|
| - case CSSPropertyInvalid:
|
| - return;
|
| - // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
|
| - case CSSPropertyWebkitBorderEndColor:
|
| - case CSSPropertyWebkitBorderEndStyle:
|
| - case CSSPropertyWebkitBorderEndWidth:
|
| - case CSSPropertyWebkitBorderStartColor:
|
| - case CSSPropertyWebkitBorderStartStyle:
|
| - case CSSPropertyWebkitBorderStartWidth:
|
| - case CSSPropertyWebkitBorderBeforeColor:
|
| - case CSSPropertyWebkitBorderBeforeStyle:
|
| - case CSSPropertyWebkitBorderBeforeWidth:
|
| - case CSSPropertyWebkitBorderAfterColor:
|
| - case CSSPropertyWebkitBorderAfterStyle:
|
| - case CSSPropertyWebkitBorderAfterWidth:
|
| - case CSSPropertyWebkitMarginEnd:
|
| - case CSSPropertyWebkitMarginStart:
|
| - case CSSPropertyWebkitMarginBefore:
|
| - case CSSPropertyWebkitMarginAfter:
|
| - case CSSPropertyWebkitMarginBeforeCollapse:
|
| - case CSSPropertyWebkitMarginTopCollapse:
|
| - case CSSPropertyWebkitMarginAfterCollapse:
|
| - case CSSPropertyWebkitMarginBottomCollapse:
|
| - case CSSPropertyWebkitPaddingEnd:
|
| - case CSSPropertyWebkitPaddingStart:
|
| - case CSSPropertyWebkitPaddingBefore:
|
| - case CSSPropertyWebkitPaddingAfter:
|
| - case CSSPropertyWebkitLogicalWidth:
|
| - case CSSPropertyWebkitLogicalHeight:
|
| - case CSSPropertyWebkitMinLogicalWidth:
|
| - case CSSPropertyWebkitMinLogicalHeight:
|
| - case CSSPropertyWebkitMaxLogicalWidth:
|
| - case CSSPropertyWebkitMaxLogicalHeight:
|
| - {
|
| - CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
|
| - ASSERT(newId != id);
|
| - return applyProperty(newId, value);
|
| - }
|
| - case CSSPropertyFontStretch:
|
| - case CSSPropertyPage:
|
| - case CSSPropertyTextLineThrough:
|
| - case CSSPropertyTextLineThroughColor:
|
| - case CSSPropertyTextLineThroughMode:
|
| - case CSSPropertyTextLineThroughStyle:
|
| - case CSSPropertyTextLineThroughWidth:
|
| - case CSSPropertyTextOverline:
|
| - case CSSPropertyTextOverlineColor:
|
| - case CSSPropertyTextOverlineMode:
|
| - case CSSPropertyTextOverlineStyle:
|
| - case CSSPropertyTextOverlineWidth:
|
| - case CSSPropertyTextUnderline:
|
| - case CSSPropertyTextUnderlineColor:
|
| - case CSSPropertyTextUnderlineMode:
|
| - case CSSPropertyTextUnderlineStyle:
|
| - case CSSPropertyTextUnderlineWidth:
|
| - case CSSPropertyWebkitFontSizeDelta:
|
| - case CSSPropertyWebkitTextDecorationsInEffect:
|
| - return;
|
| -
|
| - // CSS Text Layout Module Level 3: Vertical writing support
|
| - case CSSPropertyWebkitWritingMode: {
|
| - HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
|
| -
|
| - if (primitiveValue)
|
| - setWritingMode(*primitiveValue);
|
| -
|
| - // FIXME: It is not ok to modify document state while applying style.
|
| - if (state.element() && state.element() == state.document()->documentElement())
|
| - state.document()->setWritingModeSetOnDocumentElement(true);
|
| - return;
|
| - }
|
| -
|
| - case CSSPropertyWebkitTextOrientation: {
|
| - HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation);
|
| -
|
| - if (primitiveValue)
|
| - setTextOrientation(*primitiveValue);
|
| -
|
| - return;
|
| - }
|
| -
|
| - case CSSPropertyWebkitLineBoxContain: {
|
| - HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
|
| - if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
|
| - state.style()->setLineBoxContain(LineBoxContainNone);
|
| - return;
|
| - }
|
| -
|
| - if (!value->isCSSLineBoxContainValue())
|
| - return;
|
| -
|
| - CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
|
| - state.style()->setLineBoxContain(lineBoxContainValue->value());
|
| - return;
|
| - }
|
| -
|
| - // CSS Fonts Module Level 3
|
| - case CSSPropertyWebkitFontFeatureSettings: {
|
| - if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
|
| - setFontDescription(state.style()->fontDescription().makeNormalFeatureSettings());
|
| - return;
|
| - }
|
| -
|
| - if (!value->isValueList())
|
| - return;
|
| -
|
| - FontDescription fontDescription = state.style()->fontDescription();
|
| - CSSValueList* list = static_cast<CSSValueList*>(value);
|
| - RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
|
| - int len = list->length();
|
| - for (int i = 0; i < len; ++i) {
|
| - CSSValue* item = list->itemWithoutBoundsCheck(i);
|
| - if (!item->isFontFeatureValue())
|
| - continue;
|
| - FontFeatureValue* feature = static_cast<FontFeatureValue*>(item);
|
| - settings->append(FontFeature(feature->tag(), feature->value()));
|
| - }
|
| - fontDescription.setFeatureSettings(settings.release());
|
| - setFontDescription(fontDescription);
|
| - return;
|
| - }
|
| -
|
| - case CSSPropertyWebkitFilter: {
|
| - HANDLE_INHERIT_AND_INITIAL(filter, Filter);
|
| - FilterOperations operations;
|
| - if (FilterOperationResolver::createFilterOperations(value, state.style(), state.rootElementStyle(), operations, m_customFilterProgramCache.get(), m_state))
|
| - state.style()->setFilter(operations);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridAutoColumns: {
|
| - GridTrackSize trackSize;
|
| - if (!createGridTrackSize(value, trackSize, state))
|
| - return;
|
| - state.style()->setGridAutoColumns(trackSize);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridAutoRows: {
|
| - GridTrackSize trackSize;
|
| - if (!createGridTrackSize(value, trackSize, state))
|
| - return;
|
| - state.style()->setGridAutoRows(trackSize);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridColumns: {
|
| - Vector<GridTrackSize> trackSizes;
|
| - NamedGridLinesMap namedGridLines;
|
| - if (!createGridTrackList(value, trackSizes, namedGridLines, state))
|
| - return;
|
| - state.style()->setGridColumns(trackSizes);
|
| - state.style()->setNamedGridColumnLines(namedGridLines);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridRows: {
|
| - Vector<GridTrackSize> trackSizes;
|
| - NamedGridLinesMap namedGridLines;
|
| - if (!createGridTrackList(value, trackSizes, namedGridLines, state))
|
| - return;
|
| - state.style()->setGridRows(trackSizes);
|
| - state.style()->setNamedGridRowLines(namedGridLines);
|
| - return;
|
| - }
|
| -
|
| - case CSSPropertyWebkitGridStart: {
|
| - HANDLE_INHERIT_AND_INITIAL(gridStart, GridStart);
|
| - GridPosition startPosition;
|
| - if (!createGridPosition(value, startPosition))
|
| - return;
|
| - state.style()->setGridStart(startPosition);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridEnd: {
|
| - HANDLE_INHERIT_AND_INITIAL(gridEnd, GridEnd);
|
| - GridPosition endPosition;
|
| - if (!createGridPosition(value, endPosition))
|
| - return;
|
| - state.style()->setGridEnd(endPosition);
|
| - return;
|
| - }
|
| -
|
| - case CSSPropertyWebkitGridBefore: {
|
| - HANDLE_INHERIT_AND_INITIAL(gridBefore, GridBefore);
|
| - GridPosition beforePosition;
|
| - if (!createGridPosition(value, beforePosition))
|
| - return;
|
| - state.style()->setGridBefore(beforePosition);
|
| - return;
|
| - }
|
| - case CSSPropertyWebkitGridAfter: {
|
| - HANDLE_INHERIT_AND_INITIAL(gridAfter, GridAfter);
|
| - GridPosition afterPosition;
|
| - if (!createGridPosition(value, afterPosition))
|
| - return;
|
| - state.style()->setGridAfter(afterPosition);
|
| - return;
|
| - }
|
| -
|
| - // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version.
|
| - case CSSPropertyTransitionDelay:
|
| - case CSSPropertyTransitionDuration:
|
| - case CSSPropertyTransitionProperty:
|
| - case CSSPropertyTransitionTimingFunction:
|
| - return;
|
| - // These properties are implemented in the DeprecatedStyleBuilder lookup table.
|
| - case CSSPropertyBackgroundAttachment:
|
| - case CSSPropertyBackgroundBlendMode:
|
| - case CSSPropertyBackgroundClip:
|
| - case CSSPropertyBackgroundColor:
|
| - case CSSPropertyBackgroundImage:
|
| - case CSSPropertyBackgroundOrigin:
|
| - case CSSPropertyBackgroundPositionX:
|
| - case CSSPropertyBackgroundPositionY:
|
| - case CSSPropertyBackgroundRepeatX:
|
| - case CSSPropertyBackgroundRepeatY:
|
| - case CSSPropertyBackgroundSize:
|
| - case CSSPropertyBorderBottomColor:
|
| - case CSSPropertyBorderBottomLeftRadius:
|
| - case CSSPropertyBorderBottomRightRadius:
|
| - case CSSPropertyBorderBottomStyle:
|
| - case CSSPropertyBorderBottomWidth:
|
| - case CSSPropertyBorderCollapse:
|
| - case CSSPropertyBorderImageOutset:
|
| - case CSSPropertyBorderImageRepeat:
|
| - case CSSPropertyBorderImageSlice:
|
| - case CSSPropertyBorderImageSource:
|
| - case CSSPropertyBorderImageWidth:
|
| - case CSSPropertyBorderLeftColor:
|
| - case CSSPropertyBorderLeftStyle:
|
| - case CSSPropertyBorderLeftWidth:
|
| - case CSSPropertyBorderRightColor:
|
| - case CSSPropertyBorderRightStyle:
|
| - case CSSPropertyBorderRightWidth:
|
| - case CSSPropertyBorderTopColor:
|
| - case CSSPropertyBorderTopLeftRadius:
|
| - case CSSPropertyBorderTopRightRadius:
|
| - case CSSPropertyBorderTopStyle:
|
| - case CSSPropertyBorderTopWidth:
|
| - case CSSPropertyBottom:
|
| - case CSSPropertyBoxSizing:
|
| - case CSSPropertyCaptionSide:
|
| - case CSSPropertyClear:
|
| - case CSSPropertyClip:
|
| - case CSSPropertyColor:
|
| - case CSSPropertyCounterIncrement:
|
| - case CSSPropertyCounterReset:
|
| - case CSSPropertyCursor:
|
| - case CSSPropertyDirection:
|
| - case CSSPropertyDisplay:
|
| - case CSSPropertyEmptyCells:
|
| - case CSSPropertyFloat:
|
| - case CSSPropertyFontSize:
|
| - case CSSPropertyFontStyle:
|
| - case CSSPropertyFontVariant:
|
| - case CSSPropertyFontWeight:
|
| - case CSSPropertyHeight:
|
| - case CSSPropertyImageRendering:
|
| - case CSSPropertyLeft:
|
| - case CSSPropertyLetterSpacing:
|
| - case CSSPropertyLineHeight:
|
| - case CSSPropertyListStyleImage:
|
| - case CSSPropertyListStylePosition:
|
| - case CSSPropertyListStyleType:
|
| - case CSSPropertyMarginBottom:
|
| - case CSSPropertyMarginLeft:
|
| - case CSSPropertyMarginRight:
|
| - case CSSPropertyMarginTop:
|
| - case CSSPropertyMaxHeight:
|
| - case CSSPropertyMaxWidth:
|
| - case CSSPropertyMinHeight:
|
| - case CSSPropertyMixBlendMode:
|
| - case CSSPropertyMinWidth:
|
| - case CSSPropertyOpacity:
|
| - case CSSPropertyOrphans:
|
| - case CSSPropertyOutlineColor:
|
| - case CSSPropertyOutlineOffset:
|
| - case CSSPropertyOutlineStyle:
|
| - case CSSPropertyOutlineWidth:
|
| - case CSSPropertyOverflowWrap:
|
| - case CSSPropertyOverflowX:
|
| - case CSSPropertyOverflowY:
|
| - case CSSPropertyPaddingBottom:
|
| - case CSSPropertyPaddingLeft:
|
| - case CSSPropertyPaddingRight:
|
| - case CSSPropertyPaddingTop:
|
| - case CSSPropertyPageBreakAfter:
|
| - case CSSPropertyPageBreakBefore:
|
| - case CSSPropertyPageBreakInside:
|
| - case CSSPropertyPointerEvents:
|
| - case CSSPropertyPosition:
|
| - case CSSPropertyResize:
|
| - case CSSPropertyRight:
|
| - case CSSPropertySize:
|
| - case CSSPropertySpeak:
|
| - case CSSPropertyTabSize:
|
| - case CSSPropertyTableLayout:
|
| - case CSSPropertyTextAlign:
|
| - case CSSPropertyTextDecoration:
|
| - case CSSPropertyTextIndent:
|
| - case CSSPropertyTextOverflow:
|
| - case CSSPropertyTextRendering:
|
| - case CSSPropertyTextTransform:
|
| - case CSSPropertyTop:
|
| - case CSSPropertyUnicodeBidi:
|
| - case CSSPropertyVariable:
|
| - case CSSPropertyVerticalAlign:
|
| - case CSSPropertyVisibility:
|
| - case CSSPropertyWebkitAnimationDelay:
|
| - case CSSPropertyWebkitAnimationDirection:
|
| - case CSSPropertyWebkitAnimationDuration:
|
| - case CSSPropertyWebkitAnimationFillMode:
|
| - case CSSPropertyWebkitAnimationIterationCount:
|
| - case CSSPropertyWebkitAnimationName:
|
| - case CSSPropertyWebkitAnimationPlayState:
|
| - case CSSPropertyWebkitAnimationTimingFunction:
|
| - case CSSPropertyWebkitAppearance:
|
| - case CSSPropertyWebkitAspectRatio:
|
| - case CSSPropertyWebkitBackfaceVisibility:
|
| - case CSSPropertyWebkitBackgroundClip:
|
| - case CSSPropertyWebkitBackgroundComposite:
|
| - case CSSPropertyWebkitBackgroundOrigin:
|
| - case CSSPropertyWebkitBackgroundSize:
|
| - case CSSPropertyWebkitBorderFit:
|
| - case CSSPropertyWebkitBorderHorizontalSpacing:
|
| - case CSSPropertyWebkitBorderImage:
|
| - case CSSPropertyWebkitBorderVerticalSpacing:
|
| - case CSSPropertyWebkitBoxAlign:
|
| - case CSSPropertyWebkitBoxDecorationBreak:
|
| - case CSSPropertyWebkitBoxDirection:
|
| - case CSSPropertyWebkitBoxFlex:
|
| - case CSSPropertyWebkitBoxFlexGroup:
|
| - case CSSPropertyWebkitBoxLines:
|
| - case CSSPropertyWebkitBoxOrdinalGroup:
|
| - case CSSPropertyWebkitBoxOrient:
|
| - case CSSPropertyWebkitBoxPack:
|
| - case CSSPropertyWebkitColorCorrection:
|
| - case CSSPropertyWebkitColumnAxis:
|
| - case CSSPropertyWebkitColumnBreakAfter:
|
| - case CSSPropertyWebkitColumnBreakBefore:
|
| - case CSSPropertyWebkitColumnBreakInside:
|
| - case CSSPropertyWebkitColumnCount:
|
| - case CSSPropertyWebkitColumnGap:
|
| - case CSSPropertyWebkitColumnProgression:
|
| - case CSSPropertyWebkitColumnRuleColor:
|
| - case CSSPropertyWebkitColumnRuleStyle:
|
| - case CSSPropertyWebkitColumnRuleWidth:
|
| - case CSSPropertyWebkitColumnSpan:
|
| - case CSSPropertyWebkitColumnWidth:
|
| - case CSSPropertyWebkitAlignContent:
|
| - case CSSPropertyWebkitAlignItems:
|
| - case CSSPropertyWebkitAlignSelf:
|
| - case CSSPropertyWebkitFlexBasis:
|
| - case CSSPropertyWebkitFlexDirection:
|
| - case CSSPropertyWebkitFlexGrow:
|
| - case CSSPropertyWebkitFlexShrink:
|
| - case CSSPropertyWebkitFlexWrap:
|
| - case CSSPropertyWebkitJustifyContent:
|
| - case CSSPropertyWebkitOrder:
|
| - case CSSPropertyWebkitFlowFrom:
|
| - case CSSPropertyWebkitFlowInto:
|
| - case CSSPropertyWebkitFontKerning:
|
| - case CSSPropertyWebkitFontSmoothing:
|
| - case CSSPropertyWebkitFontVariantLigatures:
|
| - case CSSPropertyWebkitHighlight:
|
| - case CSSPropertyWebkitHyphenateCharacter:
|
| - case CSSPropertyWebkitHyphenateLimitAfter:
|
| - case CSSPropertyWebkitHyphenateLimitBefore:
|
| - case CSSPropertyWebkitHyphenateLimitLines:
|
| - case CSSPropertyWebkitHyphens:
|
| - case CSSPropertyWebkitLineAlign:
|
| - case CSSPropertyWebkitLineBreak:
|
| - case CSSPropertyWebkitLineClamp:
|
| - case CSSPropertyWebkitLineGrid:
|
| - case CSSPropertyWebkitLineSnap:
|
| - case CSSPropertyWebkitMarqueeDirection:
|
| - case CSSPropertyWebkitMarqueeIncrement:
|
| - case CSSPropertyWebkitMarqueeRepetition:
|
| - case CSSPropertyWebkitMarqueeSpeed:
|
| - case CSSPropertyWebkitMarqueeStyle:
|
| - case CSSPropertyWebkitMaskBoxImage:
|
| - case CSSPropertyWebkitMaskBoxImageOutset:
|
| - case CSSPropertyWebkitMaskBoxImageRepeat:
|
| - case CSSPropertyWebkitMaskBoxImageSlice:
|
| - case CSSPropertyWebkitMaskBoxImageSource:
|
| - case CSSPropertyWebkitMaskBoxImageWidth:
|
| - case CSSPropertyWebkitMaskClip:
|
| - case CSSPropertyWebkitMaskComposite:
|
| - case CSSPropertyWebkitMaskImage:
|
| - case CSSPropertyWebkitMaskOrigin:
|
| - case CSSPropertyWebkitMaskPositionX:
|
| - case CSSPropertyWebkitMaskPositionY:
|
| - case CSSPropertyWebkitMaskRepeatX:
|
| - case CSSPropertyWebkitMaskRepeatY:
|
| - case CSSPropertyWebkitMaskSize:
|
| - case CSSPropertyWebkitPerspectiveOrigin:
|
| - case CSSPropertyWebkitPerspectiveOriginX:
|
| - case CSSPropertyWebkitPerspectiveOriginY:
|
| - case CSSPropertyWebkitPrintColorAdjust:
|
| - case CSSPropertyWebkitRegionBreakAfter:
|
| - case CSSPropertyWebkitRegionBreakBefore:
|
| - case CSSPropertyWebkitRegionBreakInside:
|
| - case CSSPropertyWebkitRegionOverflow:
|
| - case CSSPropertyWebkitRtlOrdering:
|
| - case CSSPropertyWebkitRubyPosition:
|
| - case CSSPropertyWebkitTextCombine:
|
| -#if ENABLE(CSS3_TEXT)
|
| - case CSSPropertyWebkitTextDecorationLine:
|
| - case CSSPropertyWebkitTextDecorationStyle:
|
| - case CSSPropertyWebkitTextDecorationColor:
|
| - case CSSPropertyWebkitTextAlignLast:
|
| - case CSSPropertyWebkitTextUnderlinePosition:
|
| -#endif // CSS3_TEXT
|
| - case CSSPropertyWebkitTextEmphasisColor:
|
| - case CSSPropertyWebkitTextEmphasisPosition:
|
| - case CSSPropertyWebkitTextEmphasisStyle:
|
| - case CSSPropertyWebkitTextFillColor:
|
| - case CSSPropertyWebkitTextSecurity:
|
| - case CSSPropertyWebkitTextStrokeColor:
|
| - case CSSPropertyWebkitTransformOriginX:
|
| - case CSSPropertyWebkitTransformOriginY:
|
| - case CSSPropertyWebkitTransformOriginZ:
|
| - case CSSPropertyWebkitTransformStyle:
|
| - case CSSPropertyWebkitTransitionDelay:
|
| - case CSSPropertyWebkitTransitionDuration:
|
| - case CSSPropertyWebkitTransitionProperty:
|
| - case CSSPropertyWebkitTransitionTimingFunction:
|
| - case CSSPropertyWebkitUserDrag:
|
| - case CSSPropertyWebkitUserModify:
|
| - case CSSPropertyWebkitUserSelect:
|
| - case CSSPropertyWebkitClipPath:
|
| - case CSSPropertyWebkitWrapFlow:
|
| - case CSSPropertyWebkitShapeMargin:
|
| - case CSSPropertyWebkitShapePadding:
|
| - case CSSPropertyWebkitWrapThrough:
|
| - case CSSPropertyWebkitShapeInside:
|
| - case CSSPropertyWebkitShapeOutside:
|
| - case CSSPropertyWhiteSpace:
|
| - case CSSPropertyWidows:
|
| - case CSSPropertyWidth:
|
| - case CSSPropertyWordBreak:
|
| - case CSSPropertyWordSpacing:
|
| - case CSSPropertyWordWrap:
|
| - case CSSPropertyZIndex:
|
| - case CSSPropertyZoom:
|
| -#if ENABLE(CSS_DEVICE_ADAPTATION)
|
| - case CSSPropertyMaxZoom:
|
| - case CSSPropertyMinZoom:
|
| - case CSSPropertyOrientation:
|
| - case CSSPropertyUserZoom:
|
| -#endif
|
| - ASSERT_NOT_REACHED();
|
| - return;
|
| - default:
|
| -#if ENABLE(SVG)
|
| - // Try the SVG properties
|
| - applySVGProperty(id, value);
|
| -#endif
|
| - return;
|
| - }
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value)
|
| -{
|
| - if (value->isImageValue())
|
| - return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value));
|
| -
|
| - if (value->isImageGeneratorValue()) {
|
| - if (value->isGradientValue())
|
| - return generatedOrPendingFromValue(property, static_cast<CSSGradientValue*>(value)->gradientWithStylesResolved(this).get());
|
| - return generatedOrPendingFromValue(property, static_cast<CSSImageGeneratorValue*>(value));
|
| - }
|
| -
|
| - if (value->isImageSetValue())
|
| - return setOrPendingFromValue(property, static_cast<CSSImageSetValue*>(value));
|
| -
|
| - if (value->isCursorImageValue())
|
| - return cursorOrPendingFromValue(property, static_cast<CSSCursorImageValue*>(value));
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
|
| -{
|
| - RefPtr<StyleImage> image = value->cachedOrPendingImage();
|
| - if (image && image->isPendingImage())
|
| - m_state.pendingImageProperties().set(property, value);
|
| - return image.release();
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue* value)
|
| -{
|
| - if (value->isPending()) {
|
| - m_state.pendingImageProperties().set(property, value);
|
| - return StylePendingImage::create(value);
|
| - }
|
| - return StyleGeneratedImage::create(value);
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value)
|
| -{
|
| - RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document());
|
| - if (image && image->isPendingImage())
|
| - m_state.pendingImageProperties().set(property, value);
|
| - return image.release();
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue* value)
|
| -{
|
| - RefPtr<StyleImage> image = value->cachedOrPendingImage(document());
|
| - if (image && image->isPendingImage())
|
| - m_state.pendingImageProperties().set(property, value);
|
| - return image.release();
|
| -}
|
| -
|
| -void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
|
| -{
|
| - if (style->effectiveZoom() == parentStyle->effectiveZoom())
|
| - return;
|
| -
|
| - const FontDescription& childFont = style->fontDescription();
|
| - FontDescription newFontDescription(childFont);
|
| - setFontSize(newFontDescription, childFont.specifiedSize());
|
| - style->setFontDescription(newFontDescription);
|
| -}
|
| -
|
| -void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
|
| -{
|
| - const FontDescription& childFont = style->fontDescription();
|
| -
|
| - if (childFont.isAbsoluteSize() || !parentStyle)
|
| - return;
|
| -
|
| - const FontDescription& parentFont = parentStyle->fontDescription();
|
| - if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
|
| - return;
|
| -
|
| - // For now, lump all families but monospace together.
|
| - if (childFont.genericFamily() != FontDescription::MonospaceFamily
|
| - && parentFont.genericFamily() != FontDescription::MonospaceFamily)
|
| - return;
|
| -
|
| - // We know the parent is monospace or the child is monospace, and that font
|
| - // size was unspecified. We want to scale our font size as appropriate.
|
| - // If the font uses a keyword size, then we refetch from the table rather than
|
| - // multiplying by our scale factor.
|
| - float size;
|
| - if (childFont.keywordSize())
|
| - size = fontSizeForKeyword(document(), CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize());
|
| - else {
|
| - Settings* settings = documentSettings();
|
| - float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
|
| - ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
|
| - : 1;
|
| - size = parentFont.useFixedDefaultSize() ?
|
| - childFont.specifiedSize() / fixedScaleFactor :
|
| - childFont.specifiedSize() * fixedScaleFactor;
|
| - }
|
| -
|
| - FontDescription newFontDescription(childFont);
|
| - setFontSize(newFontDescription, size);
|
| - style->setFontDescription(newFontDescription);
|
| -}
|
| -
|
| -void StyleResolver::initializeFontStyle(Settings* settings)
|
| -{
|
| - FontDescription fontDescription;
|
| - fontDescription.setGenericFamily(FontDescription::StandardFamily);
|
| - fontDescription.setRenderingMode(settings->fontRenderingMode());
|
| - fontDescription.setUsePrinterFont(document()->printing());
|
| - const AtomicString& standardFontFamily = documentSettings()->standardFontFamily();
|
| - if (!standardFontFamily.isEmpty()) {
|
| - fontDescription.firstFamily().setFamily(standardFontFamily);
|
| - fontDescription.firstFamily().appendFamily(0);
|
| - }
|
| - fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
|
| - setFontSize(fontDescription, fontSizeForKeyword(document(), CSSValueMedium, false));
|
| - m_state.style()->setLineHeight(RenderStyle::initialLineHeight());
|
| - m_state.setLineHeightValue(0);
|
| - setFontDescription(fontDescription);
|
| -}
|
| -
|
| -void StyleResolver::setFontSize(FontDescription& fontDescription, float size)
|
| -{
|
| - fontDescription.setSpecifiedSize(size);
|
| - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(document(), m_state.style(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules()));
|
| -}
|
| -
|
| -float StyleResolver::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules)
|
| -{
|
| - float zoomFactor = 1.0f;
|
| - if (!useSVGZoomRules) {
|
| - zoomFactor = style->effectiveZoom();
|
| - if (Frame* frame = document->frame())
|
| - zoomFactor *= frame->textZoomFactor();
|
| - }
|
| -
|
| - return StyleResolver::getComputedSizeFromSpecifiedSize(document, zoomFactor, isAbsoluteSize, specifiedSize);
|
| -}
|
| -
|
| -float StyleResolver::getComputedSizeFromSpecifiedSize(Document* document, float zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize useSmartMinimumForFontSize)
|
| -{
|
| - // Text with a 0px font size should not be visible and therefore needs to be
|
| - // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
|
| - // rendering. This is also compatible with other browsers that have minimum
|
| - // font size settings (e.g. Firefox).
|
| - if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon())
|
| - return 0.0f;
|
| -
|
| - // We support two types of minimum font size. The first is a hard override that applies to
|
| - // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum"
|
| - // that is applied only when the Web page can't know what size it really asked for, e.g.,
|
| - // when it uses logical sizes like "small" or expresses the font-size as a percentage of
|
| - // the user's default font setting.
|
| -
|
| - // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
|
| - // However we always allow the page to set an explicit pixel size that is smaller,
|
| - // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
|
| -
|
| - Settings* settings = document->settings();
|
| - if (!settings)
|
| - return 1.0f;
|
| -
|
| - int minSize = settings->minimumFontSize();
|
| - int minLogicalSize = settings->minimumLogicalFontSize();
|
| - float zoomedSize = specifiedSize * zoomFactor;
|
| -
|
| - // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small.
|
| - if (zoomedSize < minSize)
|
| - zoomedSize = minSize;
|
| -
|
| - // Now apply the "smart minimum." This minimum is also only applied if we're still too small
|
| - // after zooming. The font size must either be relative to the user default or the original size
|
| - // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive
|
| - // doing so won't disrupt the layout.
|
| - if (useSmartMinimumForFontSize && zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
|
| - zoomedSize = minLogicalSize;
|
| -
|
| - // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
|
| - // platforms (I'm looking at you, Windows.)
|
| - return min(maximumAllowedFontSize, zoomedSize);
|
| -}
|
| -
|
| -const int fontSizeTableMax = 16;
|
| -const int fontSizeTableMin = 9;
|
| -const int totalKeywords = 8;
|
| -
|
| -// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML.
|
| -static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
|
| -{
|
| - { 9, 9, 9, 9, 11, 14, 18, 28 },
|
| - { 9, 9, 9, 10, 12, 15, 20, 31 },
|
| - { 9, 9, 9, 11, 13, 17, 22, 34 },
|
| - { 9, 9, 10, 12, 14, 18, 24, 37 },
|
| - { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13)
|
| - { 9, 9, 11, 14, 17, 21, 28, 42 },
|
| - { 9, 10, 12, 15, 17, 23, 30, 45 },
|
| - { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
|
| -};
|
| -// HTML 1 2 3 4 5 6 7
|
| -// CSS xxs xs s m l xl xxl
|
| -// |
|
| -// user pref
|
| -
|
| -// Strict mode table matches MacIE and Mozilla's settings exactly.
|
| -static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
|
| -{
|
| - { 9, 9, 9, 9, 11, 14, 18, 27 },
|
| - { 9, 9, 9, 10, 12, 15, 20, 30 },
|
| - { 9, 9, 10, 11, 13, 17, 22, 33 },
|
| - { 9, 9, 10, 12, 14, 18, 24, 36 },
|
| - { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13)
|
| - { 9, 10, 12, 14, 17, 21, 28, 42 },
|
| - { 9, 10, 13, 15, 18, 23, 30, 45 },
|
| - { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
|
| -};
|
| -// HTML 1 2 3 4 5 6 7
|
| -// CSS xxs xs s m l xl xxl
|
| -// |
|
| -// user pref
|
| -
|
| -// For values outside the range of the table, we use Todd Fahrner's suggested scale
|
| -// factors for each keyword value.
|
| -static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
|
| -
|
| -float StyleResolver::fontSizeForKeyword(Document* document, int keyword, bool shouldUseFixedDefaultSize)
|
| -{
|
| - Settings* settings = document->settings();
|
| - if (!settings)
|
| - return 1.0f;
|
| -
|
| - bool quirksMode = document->inQuirksMode();
|
| - int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
|
| - if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
|
| - // Look up the entry in the table.
|
| - int row = mediumSize - fontSizeTableMin;
|
| - int col = (keyword - CSSValueXxSmall);
|
| - return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
|
| - }
|
| -
|
| - // Value is outside the range of the table. Apply the scale factor instead.
|
| - float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
|
| - return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
|
| -}
|
| -
|
| -template<typename T>
|
| -static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier)
|
| -{
|
| - // Ignore table[0] because xx-small does not correspond to any legacy font size.
|
| - for (int i = 1; i < totalKeywords - 1; i++) {
|
| - if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier)
|
| - return i;
|
| - }
|
| - return totalKeywords - 1;
|
| -}
|
| -
|
| -int StyleResolver::legacyFontSize(Document* document, int pixelFontSize, bool shouldUseFixedDefaultSize)
|
| -{
|
| - Settings* settings = document->settings();
|
| - if (!settings)
|
| - return 1;
|
| -
|
| - bool quirksMode = document->inQuirksMode();
|
| - int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
|
| - if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
|
| - int row = mediumSize - fontSizeTableMin;
|
| - return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1);
|
| - }
|
| -
|
| - return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize);
|
| -}
|
| -
|
| -bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue* value)
|
| -{
|
| - int ident = value->getIdent();
|
| - switch (ident) {
|
| - case CSSValueWebkitText:
|
| - case CSSValueWebkitLink:
|
| - case CSSValueWebkitActivelink:
|
| - case CSSValueCurrentcolor:
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
|
| -{
|
| - m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*expr, result)));
|
| -}
|
| -
|
| -bool StyleResolver::affectedByViewportChange() const
|
| -{
|
| - unsigned s = m_viewportDependentMediaQueryResults.size();
|
| - for (unsigned i = 0; i < s; i++) {
|
| - if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -#if ENABLE(SVG)
|
| -void StyleResolver::loadPendingSVGDocuments()
|
| -{
|
| - StyleResolverState& state = m_state;
|
| - if (!state.style()->hasFilter() || state.pendingSVGDocuments().isEmpty())
|
| - return;
|
| -
|
| - CachedResourceLoader* cachedResourceLoader = state.document()->cachedResourceLoader();
|
| - Vector<RefPtr<FilterOperation> >& filterOperations = state.style()->mutableFilter().operations();
|
| - for (unsigned i = 0; i < filterOperations.size(); ++i) {
|
| - RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
|
| - if (filterOperation->getOperationType() == FilterOperation::REFERENCE) {
|
| - ReferenceFilterOperation* referenceFilter = static_cast<ReferenceFilterOperation*>(filterOperation.get());
|
| -
|
| - WebKitCSSSVGDocumentValue* value = state.pendingSVGDocuments().get(referenceFilter);
|
| - if (!value)
|
| - continue;
|
| - CachedSVGDocument* cachedDocument = value->load(cachedResourceLoader);
|
| - if (!cachedDocument)
|
| - continue;
|
| -
|
| - // Stash the CachedSVGDocument on the reference filter.
|
| - referenceFilter->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(cachedDocument)));
|
| - }
|
| - }
|
| - state.pendingSVGDocuments().clear();
|
| -}
|
| -#endif
|
| -
|
| -void StyleResolver::loadPendingShaders()
|
| -{
|
| - if (!m_state.style()->hasFilter() || !m_state.hasPendingShaders())
|
| - return;
|
| -
|
| - CachedResourceLoader* cachedResourceLoader = m_state.document()->cachedResourceLoader();
|
| -
|
| - Vector<RefPtr<FilterOperation> >& filterOperations = m_state.style()->mutableFilter().operations();
|
| - for (unsigned i = 0; i < filterOperations.size(); ++i) {
|
| - RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
|
| - if (filterOperation->getOperationType() == FilterOperation::CUSTOM) {
|
| - CustomFilterOperation* customFilter = static_cast<CustomFilterOperation*>(filterOperation.get());
|
| - ASSERT(customFilter->program());
|
| - StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customFilter->program());
|
| - // Note that the StylePendingShaders could be already resolved to StyleCachedShaders. That's because the rule was matched before.
|
| - // However, the StyleCustomFilterProgram that was initially created could have been removed from the cache in the meanwhile,
|
| - // meaning that we get a new StyleCustomFilterProgram here that is not yet in the cache, but already has loaded StyleShaders.
|
| - if (!program->hasPendingShaders() && program->inCache())
|
| - continue;
|
| - if (!m_customFilterProgramCache)
|
| - m_customFilterProgramCache = adoptPtr(new StyleCustomFilterProgramCache());
|
| - RefPtr<StyleCustomFilterProgram> styleProgram = m_customFilterProgramCache->lookup(program);
|
| - if (styleProgram.get())
|
| - customFilter->setProgram(styleProgram.release());
|
| - else {
|
| - if (program->vertexShader() && program->vertexShader()->isPendingShader()) {
|
| - WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->vertexShader())->cssShaderValue();
|
| - program->setVertexShader(shaderValue->cachedShader(cachedResourceLoader));
|
| - }
|
| - if (program->fragmentShader() && program->fragmentShader()->isPendingShader()) {
|
| - WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->fragmentShader())->cssShaderValue();
|
| - program->setFragmentShader(shaderValue->cachedShader(cachedResourceLoader));
|
| - }
|
| - m_customFilterProgramCache->add(program);
|
| - }
|
| - }
|
| - }
|
| - m_state.setHasPendingShaders(false);
|
| -}
|
| -
|
| -PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendingImage)
|
| -{
|
| - CachedResourceLoader* cachedResourceLoader = m_state.document()->cachedResourceLoader();
|
| -
|
| - if (pendingImage->cssImageValue()) {
|
| - CSSImageValue* imageValue = pendingImage->cssImageValue();
|
| - return imageValue->cachedImage(cachedResourceLoader);
|
| - }
|
| -
|
| - if (pendingImage->cssImageGeneratorValue()) {
|
| - CSSImageGeneratorValue* imageGeneratorValue = pendingImage->cssImageGeneratorValue();
|
| - imageGeneratorValue->loadSubimages(cachedResourceLoader);
|
| - return StyleGeneratedImage::create(imageGeneratorValue);
|
| - }
|
| -
|
| - if (pendingImage->cssCursorImageValue()) {
|
| - CSSCursorImageValue* cursorImageValue = pendingImage->cssCursorImageValue();
|
| - return cursorImageValue->cachedImage(cachedResourceLoader);
|
| - }
|
| -
|
| - if (pendingImage->cssImageSetValue()) {
|
| - CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue();
|
| - return imageSetValue->cachedImageSet(cachedResourceLoader);
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -void StyleResolver::loadPendingImages()
|
| -{
|
| - if (m_state.pendingImageProperties().isEmpty())
|
| - return;
|
| -
|
| - PendingImagePropertyMap::const_iterator::Keys end = m_state.pendingImageProperties().end().keys();
|
| - for (PendingImagePropertyMap::const_iterator::Keys it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) {
|
| - CSSPropertyID currentProperty = *it;
|
| -
|
| - switch (currentProperty) {
|
| - case CSSPropertyBackgroundImage: {
|
| - for (FillLayer* backgroundLayer = m_state.style()->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
|
| - if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
|
| - backgroundLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(backgroundLayer->image())));
|
| - }
|
| - break;
|
| - }
|
| - case CSSPropertyContent: {
|
| - for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
|
| - if (contentData->isImage()) {
|
| - StyleImage* image = static_cast<ImageContentData*>(contentData)->image();
|
| - if (image->isPendingImage()) {
|
| - RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(image));
|
| - if (loadedImage)
|
| - static_cast<ImageContentData*>(contentData)->setImage(loadedImage.release());
|
| - }
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - case CSSPropertyCursor: {
|
| - if (CursorList* cursorList = m_state.style()->cursors()) {
|
| - for (size_t i = 0; i < cursorList->size(); ++i) {
|
| - CursorData& currentCursor = cursorList->at(i);
|
| - if (StyleImage* image = currentCursor.image()) {
|
| - if (image->isPendingImage())
|
| - currentCursor.setImage(loadPendingImage(static_cast<StylePendingImage*>(image)));
|
| - }
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - case CSSPropertyListStyleImage: {
|
| - if (m_state.style()->listStyleImage() && m_state.style()->listStyleImage()->isPendingImage())
|
| - m_state.style()->setListStyleImage(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->listStyleImage())));
|
| - break;
|
| - }
|
| - case CSSPropertyBorderImageSource: {
|
| - if (m_state.style()->borderImageSource() && m_state.style()->borderImageSource()->isPendingImage())
|
| - m_state.style()->setBorderImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->borderImageSource())));
|
| - break;
|
| - }
|
| - case CSSPropertyWebkitBoxReflect: {
|
| - if (StyleReflection* reflection = m_state.style()->boxReflect()) {
|
| - const NinePieceImage& maskImage = reflection->mask();
|
| - if (maskImage.image() && maskImage.image()->isPendingImage()) {
|
| - RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(maskImage.image()));
|
| - reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - case CSSPropertyWebkitMaskBoxImageSource: {
|
| - if (m_state.style()->maskBoxImageSource() && m_state.style()->maskBoxImageSource()->isPendingImage())
|
| - m_state.style()->setMaskBoxImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->maskBoxImageSource())));
|
| - break;
|
| - }
|
| - case CSSPropertyWebkitMaskImage: {
|
| - for (FillLayer* maskLayer = m_state.style()->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
|
| - if (maskLayer->image() && maskLayer->image()->isPendingImage())
|
| - maskLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(maskLayer->image())));
|
| - }
|
| - break;
|
| - }
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| - }
|
| -
|
| - m_state.pendingImageProperties().clear();
|
| -}
|
| -
|
| -void StyleResolver::loadPendingResources()
|
| -{
|
| - // Start loading images referenced by this style.
|
| - loadPendingImages();
|
| -
|
| - // Start loading the shaders referenced by this style.
|
| - loadPendingShaders();
|
| -
|
| -#if ENABLE(SVG)
|
| - // Start loading the SVG Documents referenced by this style.
|
| - loadPendingSVGDocuments();
|
| -#endif
|
| -}
|
| -
|
| -inline StyleResolver::MatchedProperties::MatchedProperties()
|
| - : possiblyPaddedMember(0)
|
| -{
|
| -}
|
| -
|
| -inline StyleResolver::MatchedProperties::~MatchedProperties()
|
| -{
|
| -}
|
| -
|
| -void StyleResolver::MatchedProperties::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
| -{
|
| - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
|
| - info.addMember(properties, "properties");
|
| -}
|
| -
|
| -void StyleResolver::MatchedPropertiesCacheItem::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
| -{
|
| - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
|
| - info.addMember(matchedProperties, "matchedProperties");
|
| - info.addMember(ranges, "ranges");
|
| - info.addMember(renderStyle, "renderStyle");
|
| - info.addMember(parentRenderStyle, "parentRenderStyle");
|
| -}
|
| -
|
| -void MediaQueryResult::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
| -{
|
| - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
|
| - info.addMember(m_expression, "expression");
|
| -}
|
| -
|
| -void StyleResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
| -{
|
| - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
|
| - info.addMember(m_ruleSets, "ruleSets");
|
| - info.addMember(m_keyframesRuleMap, "keyframesRuleMap");
|
| - info.addMember(m_matchedPropertiesCache, "matchedPropertiesCache");
|
| - info.addMember(m_matchedPropertiesCacheSweepTimer, "matchedPropertiesCacheSweepTimer");
|
| -
|
| - info.addMember(m_medium, "medium");
|
| - info.addMember(m_rootDefaultStyle, "rootDefaultStyle");
|
| - info.addMember(m_document, "document");
|
| -
|
| - info.addMember(m_fontSelector, "fontSelector");
|
| - info.addMember(m_viewportDependentMediaQueryResults, "viewportDependentMediaQueryResults");
|
| - info.ignoreMember(m_styleBuilder);
|
| - info.addMember(m_inspectorCSSOMWrappers);
|
| - info.addMember(m_scopeResolver, "scopeResolver");
|
| -
|
| - info.addMember(m_state, "state");
|
| -
|
| - // FIXME: move this to a place where it would be called only once?
|
| - info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle");
|
| - info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyle");
|
| - info.addMember(CSSDefaultStyleSheets::defaultPrintStyle,"defaultPrintStyle");
|
| - info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSourceStyle");
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|