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

Side by Side Diff: third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp

Issue 1192983003: CSS Custom Properties (Variables) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Use m_unit Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2015 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/CSSVariableResolver.h"
7
8 #include "core/CSSPropertyNames.h"
9 #include "core/CSSValueKeywords.h"
10 #include "core/StyleBuilderFunctions.h"
11 #include "core/css/CSSVariableData.h"
12 #include "core/css/CSSVariableReferenceValue.h"
13 #include "core/css/parser/CSSParserToken.h"
14 #include "core/css/parser/CSSParserTokenRange.h"
15 #include "core/css/parser/CSSParserValues.h"
16 #include "core/css/parser/CSSPropertyParser.h"
17 #include "core/css/resolver/StyleBuilder.h"
18 #include "core/css/resolver/StyleResolverState.h"
19 #include "core/style/StyleVariableData.h"
20 #include "wtf/Vector.h"
21
22 namespace blink {
23
24 // TODO(leviw): This should take a CSSParserTokenRange
25 static void findEndIndexOfVariableReference(const Vector<CSSParserToken>& resolv edTokens, unsigned startIndex, unsigned& endIndex, unsigned& commaIndex, bool& h asClosingBracket)
26 {
27 endIndex = 0;
28 commaIndex = 0;
29 unsigned bracketCount = 1;
30 for (unsigned i = startIndex; i < resolvedTokens.size(); ++i) {
31 CSSParserTokenType type = resolvedTokens[i].type();
32
33 if (type == CommaToken && !commaIndex) {
34 commaIndex = i;
35 } else if (type == LeftParenthesisToken || type == FunctionToken) {
36 bracketCount++;
37 } else if (type == RightParenthesisToken) {
38 if (bracketCount == 1) {
39 hasClosingBracket = true;
40 endIndex = i;
41 return;
42 }
43 bracketCount--;
44 }
45 }
46 hasClosingBracket = false;
47 endIndex = resolvedTokens.size() - 1;
48 }
49
50 unsigned CSSVariableResolver::resolveVariableTokensRecursive(Vector<CSSParserTok en>& resolvedTokens, unsigned startIndex)
51 {
52 unsigned variableLocation = startIndex;
53 while (resolvedTokens[variableLocation].type() != IdentToken)
54 variableLocation++;
55
56 unsigned commaIndex;
57 unsigned endIndex;
58 bool hasClosingBracket;
59 // Find default value and match braces
60 findEndIndexOfVariableReference(resolvedTokens, variableLocation + 1, endInd ex, commaIndex, hasClosingBracket);
61
62 unsigned length = endIndex - startIndex + 1;
63 unsigned varFunctionPosition = startIndex;
64
65 AtomicString variableName = resolvedTokens[variableLocation].value();
66
67 if (m_variablesSeen.contains(variableName)) {
68 m_cycleDetected = true;
69 resolvedTokens.clear();
70 return 0;
71 }
72
73 CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->g etVariable(variableName) : nullptr;
74 if (variableData) {
75 Vector<CSSParserToken> tokens(variableData->tokens());
76 if (variableData->needsVariableResolution()) {
77 m_variablesSeen.add(variableName);
78 resolveVariableReferencesFromTokens(tokens);
79 m_variablesSeen.remove(variableName);
80
81 // The old variable data holds onto the backing string the new resol ved CSSVariableData
82 // relies on. Ensure it will live beyond us overwriting the RefPtr i n StyleVariableData.
83 ASSERT(variableData->refCount() > 1);
84
85 m_styleVariableData->setVariable(variableName, CSSVariableData::crea teResolved(tokens));
86 }
87 if (tokens.size()) {
88 resolvedTokens.remove(startIndex, length);
89 resolvedTokens.insert(startIndex, tokens);
90 return tokens.size();
91 }
92 }
93
94 // Fallback on default value if present
95 if (!commaIndex || m_cycleDetected) {
96 resolvedTokens.clear();
97 return 0;
98 }
99
100 // Move the tokens to the beginning of the variable reference
101 unsigned defaultValueStart = commaIndex + 1;
102 unsigned defaultValueLength = endIndex - commaIndex - (hasClosingBracket ? 1 : 0);
103 for (unsigned i = 0; i < defaultValueLength; ++i)
104 resolvedTokens[varFunctionPosition + i] = resolvedTokens[defaultValueSta rt + i];
105 resolvedTokens.remove(varFunctionPosition + defaultValueLength, length - def aultValueLength);
106
107 resolveVariableReferencesFromTokens(resolvedTokens);
108
109 return resolvedTokens.size();
110 }
111
112 void CSSVariableResolver::resolveVariableReferencesFromTokens(Vector<CSSParserTo ken>& tokens)
113 {
114 for (unsigned i = 0; i < tokens.size(); ++i) {
115 if (tokens[i].functionId() == CSSValueVar) {
116 unsigned validTokens = resolveVariableTokensRecursive(tokens, i);
117 if (validTokens < 1 || m_cycleDetected) {
118 tokens.clear();
119 break;
120 }
121 i += validTokens - 1;
122 }
123 }
124 }
125
126 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value)
127 {
128 // TODO(leviw): This should be a stack
129 Vector<CSSParserToken> tokens = value.variableDataValue()->tokens();
130
131 CSSVariableResolver resolver(state.style()->variables());
132
133 resolver.resolveVariableReferencesFromTokens(tokens);
134
135 if (!tokens.size())
136 return;
137
138 CSSParserContext context(HTMLStandardMode, 0);
139
140 WillBeHeapVector<CSSProperty, 256> parsedProperties;
141
142 CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), contex t, parsedProperties, StyleRule::Type::Style);
143
144 unsigned parsedPropertiesCount = parsedProperties.size();
145 for (unsigned i = 0; i < parsedPropertiesCount; ++i)
146 StyleBuilder::applyProperty(parsedProperties[i].id(), state, parsedPrope rties[i].value());
147 }
148
149 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s)
150 {
151 if (!variables)
152 return;
153
154 for (auto& variable : variables->m_data) {
155 if (!variable.value->needsVariableResolution())
156 continue;
157 Vector<CSSParserToken> resolvedTokens(variable.value->tokens());
158
159 CSSVariableResolver resolver(variables, variable.key);
160 resolver.resolveVariableReferencesFromTokens(resolvedTokens);
161
162 variable.value = CSSVariableData::createResolved(resolvedTokens);
163 }
164 }
165
166 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData)
167 : m_styleVariableData(styleVariableData)
168 , m_cycleDetected(false)
169 {
170 }
171
172 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, A tomicString& variable)
173 : m_styleVariableData(styleVariableData)
174 , m_cycleDetected(false)
175 {
176 m_variablesSeen.add(variable);
177 }
178
179 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698