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

Side by Side Diff: Source/core/css/resolver/CascadedValues.cpp

Issue 350333003: Cascade declared property values instead of applying values on top of each other (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/css/resolver/CascadedValues.h"
7
8 #include "core/css/CSSValuePool.h"
9 #include "core/css/StylePropertySet.h"
10 #include "core/css/resolver/MatchResult.h"
11 #include "core/css/resolver/StyleBuilder.h"
12 #include "core/css/resolver/StyleResolver.h"
13 #include "core/css/resolver/StyleResolverState.h"
14 #include <algorithm>
15
16 namespace blink {
17
18 // We want properties in their prefixed and non-prefixed variants to cascade
19 // together, so we map them to the same property before adding to the cascade.
20 static CSSPropertyID resolveProperty(CSSPropertyID property, TextDirection direc tion, WritingMode writingMode)
21 {
22 switch (property) {
23 case CSSPropertyWebkitBorderEndColor:
24 case CSSPropertyWebkitBorderBeforeStyle:
25 case CSSPropertyWebkitBorderEndStyle:
26 case CSSPropertyWebkitPaddingStart:
27 case CSSPropertyWebkitBorderStartWidth:
28 case CSSPropertyWebkitMaxLogicalWidth:
29 case CSSPropertyWebkitLogicalHeight:
30 case CSSPropertyWebkitMinLogicalWidth:
31 case CSSPropertyWebkitBorderBeforeWidth:
32 case CSSPropertyWebkitPaddingBefore:
33 case CSSPropertyWebkitBorderBeforeColor:
34 case CSSPropertyWebkitMarginEnd:
35 case CSSPropertyWebkitBorderAfterWidth:
36 case CSSPropertyWebkitMinLogicalHeight:
37 case CSSPropertyWebkitBorderEndWidth:
38 case CSSPropertyWebkitPaddingEnd:
39 case CSSPropertyWebkitLogicalWidth:
40 case CSSPropertyWebkitBorderAfterColor:
41 case CSSPropertyWebkitMaxLogicalHeight:
42 case CSSPropertyWebkitBorderStartColor:
43 case CSSPropertyWebkitBorderAfterStyle:
44 case CSSPropertyWebkitPaddingAfter:
45 case CSSPropertyWebkitBorderStartStyle:
46 case CSSPropertyWebkitMarginBefore:
47 case CSSPropertyWebkitMarginStart:
48 case CSSPropertyWebkitMarginAfter:
49 return CSSProperty::resolveDirectionAwareProperty(property, direction, w ritingMode);
50 case CSSPropertyWebkitBackfaceVisibility:
51 return CSSPropertyBackfaceVisibility;
52 case CSSPropertyWebkitBackgroundClip:
53 return CSSPropertyBackgroundClip;
54 case CSSPropertyWebkitBackgroundOrigin:
55 return CSSPropertyBackgroundOrigin;
56 case CSSPropertyWebkitBackgroundSize:
57 return CSSPropertyBackgroundSize;
58 case CSSPropertyWebkitBoxShadow:
59 return CSSPropertyBoxShadow;
60 case CSSPropertyWebkitTransform:
61 return CSSPropertyTransform;
62 case CSSPropertyWebkitTransformStyle:
63 return CSSPropertyTransformStyle;
64 case CSSPropertyWebkitPerspective:
65 return CSSPropertyPerspective;
66 case CSSPropertyWebkitPerspectiveOrigin:
67 return CSSPropertyPerspectiveOrigin;
68 // Used by editing when the css3 text decorations flag is off
69 case CSSPropertyTextDecoration:
70 ASSERT(!RuntimeEnabledFeatures::css3TextDecorationsEnabled());
71 return CSSPropertyTextDecorationLine;
72 // As per css3-text, word-wrap is an alias for overflow-wrap
73 case CSSPropertyWordWrap:
74 return CSSPropertyOverflowWrap;
75 default:
76 return property;
77 }
78 }
79
80 CascadedValues::CascadedValues(StyleResolverState& state, const MatchResult& mat chResult, bool onlyAddUARules)
81 : m_state(state)
82 {
83 memset(m_values, 0, sizeof(m_values));
84 if (m_state.style()->insideLink())
85 memset(m_visitedLinkValues, 0, sizeof(m_visitedLinkValues));
86
87 // The MatchResult has rules in UA - User - Author order, although we only
88 // use user rules for callback selectors.
89 addMatchResult(matchResult, CSSPropertyDirection, CSSPropertyWebkitWritingMo de);
90 applyValues(CSSPropertyDirection, CSSPropertyWebkitWritingMode);
91 m_direction = state.style()->direction();
92 m_writingMode = state.style()->writingMode();
93
94 COMPILE_ASSERT(CSSPropertyColor == CSSPropertyWebkitWritingMode + 1, CSS_col or_is_after_super_high_priority);
95 if (onlyAddUARules) {
96 addMatchResultRange(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, CSSPropertyColor, convertToCSSPropertyID(lastCSSP roperty));
97 } else {
98 addMatchResult(matchResult, CSSPropertyColor, convertToCSSPropertyID(las tCSSProperty));
99 }
100
101 std::sort(setProperties.begin(), setProperties.end());
102 std::sort(setVisitedProperties.begin(), setVisitedProperties.end());
103 }
104
105 void CascadedValues::addMatchResult(const MatchResult& matchResult, CSSPropertyI D firstId, CSSPropertyID lastId)
106 {
107 addMatchResultRange(matchResult, false, 0, matchResult.matchedProperties.siz e() - 1, firstId, lastId);
108 addMatchResultRange(matchResult, true, matchResult.ranges.firstAuthorRule, m atchResult.ranges.lastAuthorRule, firstId, lastId);
109 addMatchResultRange(matchResult, true, matchResult.ranges.firstUARule, match Result.ranges.lastUARule, firstId, lastId);
110 }
111
112 void CascadedValues::addMatchResultRange(const MatchResult& matchResult, bool is Important, int firstIndex, int lastIndex, CSSPropertyID firstId, CSSPropertyID l astId)
113 {
114 if (firstIndex == -1)
115 return;
116
117 for (int i = firstIndex; i <= lastIndex; ++i) {
118 const MatchedProperties& matchedProperties = matchResult.matchedProperti es[i];
119 SelectorChecker::LinkMatchMask linkMatchType = SelectorChecker::MatchLin k;
120 if (m_state.style()->insideLink())
121 linkMatchType = static_cast<SelectorChecker::LinkMatchMask>(matchedP roperties.m_types.linkMatchType);
122 addStylePropertySet(matchedProperties.properties.get(), matchResult.matc hedRules[i], isImportant, firstId, lastId, static_cast<PropertyWhitelistType>(ma tchedProperties.m_types.whitelistType), linkMatchType);
123 }
124 }
125
126 void CascadedValues::addStylePropertySet(const StylePropertySet* properties, con st StyleRule* rule, bool isImportant, CSSPropertyID first, CSSPropertyID last, P ropertyWhitelistType propertyWhitelistType, SelectorChecker::LinkMatchMask linkM atchType)
127 {
128 unsigned propertyCount = properties->propertyCount();
129 for (unsigned i = 0; i < propertyCount; ++i) {
130 StylePropertySet::PropertyReference current = properties->propertyAt(i);
131 if (isImportant != current.isImportant())
132 continue;
133
134 CSSPropertyID property = current.id();
135 if (property < first || property > last)
136 continue;
137
138 // FIXME: We should check the whitelist, otherwise we might run into
139 // problems with e.g. foo:first-letter { all: inherit; }
140 if (property == CSSPropertyAll) {
141 addAllProperty(current.value(), linkMatchType);
142 continue;
143 }
144
145 if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isV alidCueStyleProperty(property))
146 continue;
147 if (propertyWhitelistType == PropertyWhitelistFirstLetter && !StyleResol ver::isValidFirstLetterStyleProperty(property))
148 continue;
149 addValue(current.id(), current.value(), rule, linkMatchType);
150 }
151 }
152
153 void CascadedValues::addValue(CSSPropertyID property, CSSValue* value, const Sty leRule* rule, SelectorChecker::LinkMatchMask linkMatchType)
154 {
155 property = resolveProperty(property, m_direction, m_writingMode);
156
157 if (property == CSSPropertyInternalCallback) {
158 ASSERT(value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValue ID() == CSSValueInternalPresence);
159 m_state.style()->addCallbackSelector(rule->selectorList().selectorsText( ));
160 return;
161 }
162
163 // Shorthands that are not expanded in the parser need special handling here .
164 // The shorthand property occurs earlier in CSSPropertyNames.in than its
165 // longhands so we can cascade properly. If a longhand value is explicitly
166 // set, with higher priority than the shorthand, then the value computed
167 // from the shorthand will be overriden.
168
169 // FIXME: font should always be expanded by the parser; crbug.com/353932
170 if (property == CSSPropertyFont) {
171 clearCascadedValue(CSSPropertyLineHeight);
172 clearCascadedValue(CSSPropertyFontStyle);
173 clearCascadedValue(CSSPropertyFontFamily);
174 clearCascadedValue(CSSPropertyFontVariant);
175 clearCascadedValue(CSSPropertyFontWeight);
176 clearCascadedValue(CSSPropertyFontStretch);
177 clearCascadedValue(CSSPropertyFontSize);
178 }
179
180 // -webkit-border-image sometimes also sets border-*-width, but properly
181 // cascading this requires too much effort
182 if (property == CSSPropertyWebkitBorderImage) {
183 clearCascadedValue(CSSPropertyBorderImageSource);
184 clearCascadedValue(CSSPropertyBorderImageSlice);
185 clearCascadedValue(CSSPropertyBorderImageWidth);
186 clearCascadedValue(CSSPropertyBorderImageOutset);
187 clearCascadedValue(CSSPropertyBorderImageRepeat);
188 }
189
190 if (linkMatchType & SelectorChecker::MatchLink)
191 setCascadedValue(property, value);
192 if (linkMatchType & SelectorChecker::MatchVisited)
193 setCascadedVisitedLinkValue(property, value);
194 }
195
196 void CascadedValues::addAllProperty(CSSValue* value, SelectorChecker::LinkMatchM ask linkMatchType)
197 {
198 if (!value->isInitialValue() && !value->isInheritedValue()) {
199 ASSERT(value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValue ID() == CSSValueUnset);
200 value = nullptr;
201 }
202
203 for (int i = firstCSSProperty; i <= lastCSSProperty; ++i) {
204 CSSPropertyID property = convertToCSSPropertyID(i);
205 if (CSSProperty::isAffectedByAllProperty(property))
206 addValue(property, value, nullptr, linkMatchType);
207 }
208 }
209
210 void CascadedValues::setCascadedValue(CSSPropertyID id, CSSValue* value)
211 {
212 if (!m_values[id - firstCSSProperty])
213 setProperties.append(id);
214 m_values[id - firstCSSProperty] = value;
215 }
216
217 void CascadedValues::setCascadedVisitedLinkValue(CSSPropertyID id, CSSValue* val ue)
218 {
219 ASSERT(m_state.style()->insideLink());
220 if (!m_visitedLinkValues[id - firstCSSProperty])
221 setVisitedProperties.append(id);
222 m_visitedLinkValues[id - firstCSSProperty] = value;
223 }
224
225 void CascadedValues::applyValues(CSSPropertyID first, CSSPropertyID last, bool i nheritedOnly)
226 {
227 for (size_t i = 0; i < setProperties.size(); i++) {
228 CSSPropertyID property = setProperties[i];
229 if (property < first || property > last)
230 continue;
231 // We might not have a value due to the shorthand special-cases in addVa lue
232 if (!cascadedValue(property))
233 continue;
234 if (!inheritedOnly || CSSProperty::isInheritedProperty(property))
235 StyleBuilder::applyProperty(property, m_state, cascadedValue(propert y));
236 }
237
238 if (!m_state.style()->insideLink())
239 return;
240
241 m_state.setApplyPropertyToRegularStyle(false);
242 m_state.setApplyPropertyToVisitedLinkStyle(true);
243 for (size_t i = 0; i < setVisitedProperties.size(); i++) {
244 CSSPropertyID property = setVisitedProperties[i];
245 if (property < first || property > last)
246 continue;
247 ASSERT(cascadedVisitedLinkValue(property));
248 if (!inheritedOnly || CSSProperty::isInheritedProperty(property))
249 StyleBuilder::applyProperty(property, m_state, cascadedVisitedLinkVa lue(property));
250 }
251 m_state.setApplyPropertyToRegularStyle(true);
252 m_state.setApplyPropertyToVisitedLinkStyle(false);
253 }
254
255
256 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/css/resolver/CascadedValues.h ('k') | Source/core/css/resolver/StyleBuilderCustom.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698