OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | |
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
All rights reserved. | |
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | |
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | |
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | |
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | |
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | |
10 * | |
11 * This library is free software; you can redistribute it and/or | |
12 * modify it under the terms of the GNU Library General Public | |
13 * License as published by the Free Software Foundation; either | |
14 * version 2 of the License, or (at your option) any later version. | |
15 * | |
16 * This library is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 * Library General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU Library General Public License | |
22 * along with this library; see the file COPYING.LIB. If not, write to | |
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
24 * Boston, MA 02110-1301, USA. | |
25 */ | |
26 | |
27 #include "core/css/parser/CSSPropertyParser.h" | |
28 | |
29 #include "core/StylePropertyShorthand.h" | |
30 #include "core/css/CSSCustomIdentValue.h" | |
31 #include "core/css/CSSFunctionValue.h" | |
32 #include "core/css/CSSGridAutoRepeatValue.h" | |
33 #include "core/css/CSSGridLineNamesValue.h" | |
34 #include "core/css/CSSPrimitiveValueMappings.h" | |
35 #include "core/css/CSSValuePair.h" | |
36 #include "core/css/CSSValuePool.h" | |
37 #include "core/css/parser/CSSParserValues.h" | |
38 #include "core/css/parser/CSSPropertyParserHelpers.h" | |
39 #include "core/style/GridArea.h" | |
40 #include "platform/RuntimeEnabledFeatures.h" | |
41 | |
42 namespace blink { | |
43 | |
44 using namespace CSSPropertyParserHelpers; | |
45 | |
46 void CSSPropertyParser::addProperty(CSSPropertyID propId, CSSValue* value, bool
important, bool implicit) | |
47 { | |
48 ASSERT(!isPropertyAlias(propId)); | |
49 | |
50 int shorthandIndex = 0; | |
51 bool setFromShorthand = false; | |
52 | |
53 if (m_currentShorthand) { | |
54 Vector<StylePropertyShorthand, 4> shorthands; | |
55 getMatchingShorthandsForLonghand(propId, &shorthands); | |
56 setFromShorthand = true; | |
57 if (shorthands.size() > 1) | |
58 shorthandIndex = indexOfShorthandForLonghand(m_currentShorthand, sho
rthands); | |
59 } | |
60 | |
61 m_parsedProperties->append(CSSProperty(propId, value, important, setFromShor
thand, shorthandIndex, implicit)); | |
62 } | |
63 | |
64 void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID propId, CSSVal
ue* value, bool important) | |
65 { | |
66 const StylePropertyShorthand& shorthand = shorthandForProperty(propId); | |
67 unsigned shorthandLength = shorthand.length(); | |
68 if (!shorthandLength) { | |
69 addProperty(propId, value, important); | |
70 return; | |
71 } | |
72 | |
73 ShorthandScope scope(this, propId); | |
74 const CSSPropertyID* longhands = shorthand.properties(); | |
75 for (unsigned i = 0; i < shorthandLength; ++i) | |
76 addProperty(longhands[i], value, important); | |
77 } | |
78 | |
79 bool CSSPropertyParser::legacyParseShorthand(CSSPropertyID propertyID, bool impo
rtant) | |
80 { | |
81 switch (propertyID) { | |
82 case CSSPropertyGrid: | |
83 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | |
84 return parseGridShorthand(important); | |
85 | |
86 // The remaining shorthands are handled in CSSPropertyParser.cpp | |
87 default: | |
88 return false; | |
89 } | |
90 } | |
91 | |
92 bool CSSPropertyParser::parseGridShorthand(bool important) | |
93 { | |
94 ShorthandScope scope(this, CSSPropertyGrid); | |
95 ASSERT(shorthandForProperty(CSSPropertyGrid).length() == 8); | |
96 | |
97 CSSParserTokenRange rangeCopy = m_range; | |
98 | |
99 // 1- <grid-template> | |
100 if (consumeGridTemplateShorthand(important)) { | |
101 // It can only be specified the explicit or the implicit grid properties
in a single grid declaration. | |
102 // The sub-properties not specified are set to their initial value, as n
ormal for shorthands. | |
103 addProperty(CSSPropertyGridAutoFlow, cssValuePool().createImplicitInitia
lValue(), important); | |
104 addProperty(CSSPropertyGridAutoColumns, cssValuePool().createImplicitIni
tialValue(), important); | |
105 addProperty(CSSPropertyGridAutoRows, cssValuePool().createImplicitInitia
lValue(), important); | |
106 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitIniti
alValue(), important); | |
107 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialV
alue(), important); | |
108 return true; | |
109 } | |
110 | |
111 m_range = rangeCopy; | |
112 | |
113 // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ] | |
114 CSSValueList* gridAutoFlow = consumeGridAutoFlow(m_range); | |
115 if (!gridAutoFlow) | |
116 return false; | |
117 | |
118 CSSValue* autoColumnsValue = nullptr; | |
119 CSSValue* autoRowsValue = nullptr; | |
120 | |
121 if (!m_range.atEnd()) { | |
122 autoRowsValue = consumeGridTrackSize(m_range, m_context.mode()); | |
123 if (!autoRowsValue) | |
124 return false; | |
125 if (consumeSlashIncludingWhitespace(m_range)) { | |
126 autoColumnsValue = consumeGridTrackSize(m_range, m_context.mode()); | |
127 if (!autoColumnsValue) | |
128 return false; | |
129 } | |
130 if (!m_range.atEnd()) | |
131 return false; | |
132 } else { | |
133 // Other omitted values are set to their initial values. | |
134 autoColumnsValue = cssValuePool().createImplicitInitialValue(); | |
135 autoRowsValue = cssValuePool().createImplicitInitialValue(); | |
136 } | |
137 | |
138 // if <grid-auto-columns> value is omitted, it is set to the value specified
for grid-auto-rows. | |
139 if (!autoColumnsValue) | |
140 autoColumnsValue = autoRowsValue; | |
141 | |
142 addProperty(CSSPropertyGridAutoFlow, gridAutoFlow, important); | |
143 addProperty(CSSPropertyGridAutoColumns, autoColumnsValue, important); | |
144 addProperty(CSSPropertyGridAutoRows, autoRowsValue, important); | |
145 | |
146 // It can only be specified the explicit or the implicit grid properties in
a single grid declaration. | |
147 // The sub-properties not specified are set to their initial value, as norma
l for shorthands. | |
148 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createImplicitIni
tialValue(), important); | |
149 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createImplicitInitia
lValue(), important); | |
150 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createImplicitIniti
alValue(), important); | |
151 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitInitialVa
lue(), important); | |
152 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialValue
(), important); | |
153 | |
154 return true; | |
155 } | |
156 | |
157 bool allTracksAreFixedSized(CSSValueList& valueList) | |
158 { | |
159 for (auto value : valueList) { | |
160 if (value->isGridLineNamesValue()) | |
161 continue; | |
162 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax
( <fixed-breadth>, <track-breadth> ) | |
163 if (value->isGridAutoRepeatValue()) { | |
164 if (!allTracksAreFixedSized(toCSSValueList(*value))) | |
165 return false; | |
166 continue; | |
167 } | |
168 ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFu
nctionValue(*value).item(0))); | |
169 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() | |
170 ? toCSSPrimitiveValue(*value) | |
171 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); | |
172 CSSValueID valueID = primitiveValue.getValueID(); | |
173 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va
lueID == CSSValueAuto || primitiveValue.isFlex()) | |
174 return false; | |
175 } | |
176 return true; | |
177 } | |
178 | |
179 static Vector<String> parseGridTemplateAreasColumnNames(const String& gridRowNam
es) | |
180 { | |
181 ASSERT(!gridRowNames.isEmpty()); | |
182 Vector<String> columnNames; | |
183 // Using StringImpl to avoid checks and indirection in every call to String:
:operator[]. | |
184 StringImpl& text = *gridRowNames.impl(); | |
185 | |
186 StringBuilder areaName; | |
187 for (unsigned i = 0; i < text.length(); ++i) { | |
188 if (text[i] == ' ') { | |
189 if (!areaName.isEmpty()) { | |
190 columnNames.append(areaName.toString()); | |
191 areaName.clear(); | |
192 } | |
193 continue; | |
194 } | |
195 if (text[i] == '.') { | |
196 if (areaName == ".") | |
197 continue; | |
198 if (!areaName.isEmpty()) { | |
199 columnNames.append(areaName.toString()); | |
200 areaName.clear(); | |
201 } | |
202 } else { | |
203 if (areaName == ".") { | |
204 columnNames.append(areaName.toString()); | |
205 areaName.clear(); | |
206 } | |
207 } | |
208 | |
209 areaName.append(text[i]); | |
210 } | |
211 | |
212 if (!areaName.isEmpty()) | |
213 columnNames.append(areaName.toString()); | |
214 | |
215 return columnNames; | |
216 } | |
217 | |
218 bool parseGridTemplateAreasRow(const String& gridRowNames, NamedGridAreaMap& gri
dAreaMap, const size_t rowCount, size_t& columnCount) | |
219 { | |
220 if (gridRowNames.isEmpty() || gridRowNames.containsOnlyWhitespace()) | |
221 return false; | |
222 | |
223 Vector<String> columnNames = parseGridTemplateAreasColumnNames(gridRowNames)
; | |
224 if (!columnCount) { | |
225 columnCount = columnNames.size(); | |
226 ASSERT(columnCount); | |
227 } else if (columnCount != columnNames.size()) { | |
228 // The declaration is invalid is all the rows don't have the number of c
olumns. | |
229 return false; | |
230 } | |
231 | |
232 for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { | |
233 const String& gridAreaName = columnNames[currentCol]; | |
234 | |
235 // Unamed areas are always valid (we consider them to be 1x1). | |
236 if (gridAreaName == ".") | |
237 continue; | |
238 | |
239 // We handle several grid areas with the same name at once to simplify t
he validation code. | |
240 size_t lookAheadCol; | |
241 for (lookAheadCol = currentCol + 1; lookAheadCol < columnCount; ++lookAh
eadCol) { | |
242 if (columnNames[lookAheadCol] != gridAreaName) | |
243 break; | |
244 } | |
245 | |
246 NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName); | |
247 if (gridAreaIt == gridAreaMap.end()) { | |
248 gridAreaMap.add(gridAreaName, GridArea(GridSpan::translatedDefiniteG
ridSpan(rowCount, rowCount + 1), GridSpan::translatedDefiniteGridSpan(currentCol
, lookAheadCol))); | |
249 } else { | |
250 GridArea& gridArea = gridAreaIt->value; | |
251 | |
252 // The following checks test that the grid area is a single filled-i
n rectangle. | |
253 // 1. The new row is adjacent to the previously parsed row. | |
254 if (rowCount != gridArea.rows.endLine()) | |
255 return false; | |
256 | |
257 // 2. The new area starts at the same position as the previously par
sed area. | |
258 if (currentCol != gridArea.columns.startLine()) | |
259 return false; | |
260 | |
261 // 3. The new area ends at the same position as the previously parse
d area. | |
262 if (lookAheadCol != gridArea.columns.endLine()) | |
263 return false; | |
264 | |
265 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); | |
266 } | |
267 currentCol = lookAheadCol - 1; | |
268 } | |
269 | |
270 return true; | |
271 } | |
272 | |
273 } // namespace blink | |
OLD | NEW |