Changeset 167799 in webkit
- Timestamp:
- Apr 25, 2014 5:06:53 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r167797 r167799 1 2014-04-25 Javier Fernandez <jfernandez@igalia.com> 2 3 [CSS Grid Layout] Implementation of the grid-template shorthand. 4 https://bugs.webkit.org/show_bug.cgi?id=128980 5 6 Reviewed by Darin Adler. 7 8 Layout Test for the basic functionality of the grid-template shorthand. It was 9 also added a new javascript file with some utility functions. 10 11 This shorthand sets the values for the grid-template-columns, 12 grid-template-rows and grid-template-areas, so the implementation 13 tries to reuse as much available parsing functions as possible. 14 15 * fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt: Added. 16 * fast/css-grid-layout/grid-template-shorthand-get-set.html: Added. 17 * fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js: Added. 18 (testGridDefinitionsValues): 19 (testGridDefinitionsSetJSValues): 20 (testNonGridDefinitionsSetJSValues): 21 (checkGridDefinitionsSetJSValues): 22 (testGridDefinitionsSetBadJSValues): 23 1 24 2014-04-25 Antoine Quint <graouts@webkit.org> 2 25 -
trunk/Source/WebCore/ChangeLog
r167798 r167799 1 2014-04-25 Javier Fernandez <jfernandez@igalia.com> 2 3 [CSS Grid Layout] Implementation of the grid-template shorthand. 4 https://bugs.webkit.org/show_bug.cgi?id=128980 5 6 Reviewed by Darin Adler. 7 8 This shorthand sets the values for the grid-template-columns, 9 grid-template-rows and grid-template-areas, so the implementation 10 tries to reuse as much available parsing functions as possible. 11 12 The "parsingGridTrackList" was refactored to return a CSSValue and 13 let the "parseValue" function to assign the property value. The 14 "forwardSlash" operator is now valid when the track-list clause is 15 part of a shorthand. The "parseValue" function checkouts that only 16 additional clauses are allowed when processing shorthands; the 17 grid-columns-rows-get-set.html tests was modified to verify this. 18 19 The "parseGridTemplateAreas" was refactored too, in order to 20 process single areas's rows. This is very useful for the 21 gris-template secondary syntax, which mixes areas and rows values. 22 23 Finally, the "parseGirdLineNames" function was modified as well by 24 defining an new argument to concatenate head/tail custom-ident 25 elements and ensure the identList is at the heading index, since 26 it's now possible the parseList was rewound. 27 28 The implementation of the grid-template shorthand tries first to 29 match the <grid-template-columns> / <grid-template-rows> syntax, 30 failing back to the secondary syntax if needed. This approach 31 requires to rewind the parseList but it produces a clearer code. 32 33 Test: fast/css-grid-layout/grid-template-shorthand-get-set.html 34 35 * css/CSSComputedStyleDeclaration.cpp: 36 (WebCore::ComputedStyleExtractor::propertyValue): 37 * css/CSSParser.cpp: 38 (WebCore::CSSParser::parseValue): 39 (WebCore::CSSParser::parseGridTemplateRowsAndAreas): 40 (WebCore::CSSParser::parseGridTemplateShorthand): 41 (WebCore::CSSParser::parseGridLineNames): 42 (WebCore::CSSParser::parseGridTrackList): 43 (WebCore::CSSParser::parseGridTemplateAreasRow): 44 (WebCore::CSSParser::parseGridTemplateAreas): 45 * css/CSSParser.h: 46 * css/CSSParserValues.h: 47 (WebCore::CSSParserValueList::setCurrentIndex): 48 * css/CSSPropertyNames.in: 49 * css/StylePropertyShorthand.cpp: 50 (WebCore::webkitGridTemplateShorthand): 51 * css/StylePropertyShorthand.h: 52 1 53 2014-04-25 Andreas Kling <akling@apple.com> 2 54 -
trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
r167448 r167799 2083 2083 case CSSPropertyWebkitGridArea: 2084 2084 return getCSSPropertyValuesForGridShorthand(webkitGridAreaShorthand()); 2085 case CSSPropertyWebkitGridTemplate: 2086 return getCSSPropertyValuesForGridShorthand(webkitGridTemplateShorthand()); 2085 2087 case CSSPropertyWebkitGridColumn: 2086 2088 return getCSSPropertyValuesForGridShorthand(webkitGridColumnShorthand()); -
trunk/Source/WebCore/css/CSSParser.cpp
r167620 r167799 96 96 #if ENABLE(CSS_GRID_LAYOUT) 97 97 #include "CSSGridLineNamesValue.h" 98 #include "CSSGridTemplateAreasValue.h"99 98 #endif 100 99 … … 2574 2573 if (!cssGridLayoutEnabled()) 2575 2574 return false; 2576 return parseGridTrackList(propId, important); 2575 parsedValue = parseGridTrackList(); 2576 break; 2577 2577 2578 2578 case CSSPropertyWebkitGridColumnStart: … … 2593 2593 return parseGridItemPositionShorthand(propId, important); 2594 2594 } 2595 2596 case CSSPropertyWebkitGridTemplate: 2597 if (!cssGridLayoutEnabled()) 2598 return false; 2599 return parseGridTemplateShorthand(important); 2595 2600 2596 2601 case CSSPropertyWebkitGridArea: … … 4797 4802 } 4798 4803 4804 bool CSSParser::parseGridTemplateRowsAndAreas(PassRefPtr<CSSValue> templateColumns, bool important) 4805 { 4806 // At least template-areas strings must be defined. 4807 if (!m_valueList->current()) 4808 return false; 4809 4810 NamedGridAreaMap gridAreaMap; 4811 unsigned rowCount = 0; 4812 unsigned columnCount = 0; 4813 bool trailingIdentWasAdded = false; 4814 RefPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated(); 4815 4816 do { 4817 // Handle leading <custom-ident>*. 4818 if (m_valueList->current()->unit == CSSParserValue::ValueList) { 4819 if (trailingIdentWasAdded) { 4820 // A row's trailing ident must be concatenated with the next row's leading one. 4821 parseGridLineNames(*m_valueList, *templateRows, static_cast<CSSGridLineNamesValue*>(templateRows->item(templateRows->length() - 1))); 4822 } else 4823 parseGridLineNames(*m_valueList, *templateRows); 4824 } 4825 4826 // Handle a template-area's row. 4827 if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount)) 4828 return false; 4829 ++rowCount; 4830 4831 // Handle template-rows's track-size. 4832 if (m_valueList->current() && m_valueList->current()->unit != CSSParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS_STRING) { 4833 RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList); 4834 if (!value) 4835 return false; 4836 templateRows->append(value.release()); 4837 } else 4838 templateRows->append(cssValuePool().createIdentifierValue(CSSValueAuto)); 4839 4840 // This will handle the trailing/leading <custom-ident>* in the grammar. 4841 trailingIdentWasAdded = false; 4842 if (m_valueList->current() && m_valueList->current()->unit == CSSParserValue::ValueList) { 4843 parseGridLineNames(*m_valueList, *templateRows); 4844 trailingIdentWasAdded = true; 4845 } 4846 } while (m_valueList->current()); 4847 4848 // [<track-list> /]? 4849 if (templateColumns) 4850 addProperty(CSSPropertyWebkitGridTemplateColumns, templateColumns, important); 4851 else 4852 addProperty(CSSPropertyWebkitGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important); 4853 4854 // [<line-names>? <string> [<track-size> <line-names>]? ]+ 4855 RefPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount); 4856 addProperty(CSSPropertyWebkitGridTemplateAreas, templateAreas.release(), important); 4857 addProperty(CSSPropertyWebkitGridTemplateRows, templateRows.release(), important); 4858 4859 return true; 4860 } 4861 4862 bool CSSParser::parseGridTemplateShorthand(bool important) 4863 { 4864 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); 4865 4866 ShorthandScope scope(this, CSSPropertyWebkitGridTemplate); 4867 ASSERT(gridTemplateShorthand().length() == 3); 4868 4869 // At least "none" must be defined. 4870 if (!m_valueList->current()) 4871 return false; 4872 4873 bool firstValueIsNone = m_valueList->current()->id == CSSValueNone; 4874 4875 // 1- 'none' case. 4876 if (firstValueIsNone && !m_valueList->next()) { 4877 addProperty(CSSPropertyWebkitGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important); 4878 addProperty(CSSPropertyWebkitGridTemplateRows, cssValuePool().createIdentifierValue(CSSValueNone), important); 4879 addProperty(CSSPropertyWebkitGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important); 4880 return true; 4881 } 4882 4883 unsigned index = 0; 4884 RefPtr<CSSValue> columnsValue = firstValueIsNone ? cssValuePool().createIdentifierValue(CSSValueNone) : parseGridTrackList(); 4885 4886 // 2- <grid-template-columns> / <grid-template-columns> syntax. 4887 if (columnsValue) { 4888 if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current()) && m_valueList->next())) 4889 return false; 4890 index = m_valueList->currentIndex(); 4891 if (RefPtr<CSSValue> rowsValue = parseGridTrackList()) { 4892 if (m_valueList->current()) 4893 return false; 4894 addProperty(CSSPropertyWebkitGridTemplateColumns, columnsValue.release(), important); 4895 addProperty(CSSPropertyWebkitGridTemplateRows, rowsValue.release(), important); 4896 addProperty(CSSPropertyWebkitGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important); 4897 return true; 4898 } 4899 } 4900 4901 4902 // 3- [<track-list> /]? [<line-names>? <string> [<track-size> <line-names>]? ]+ syntax. 4903 // The template-columns <track-list> can't be 'none'. 4904 if (firstValueIsNone) 4905 return false; 4906 // It requires to rewind parsing due to previous syntax failures. 4907 m_valueList->setCurrentIndex(index); 4908 return parseGridTemplateRowsAndAreas(columnsValue, important); 4909 } 4910 4799 4911 bool CSSParser::parseGridAreaShorthand(bool important) 4800 4912 { … … 4851 4963 } 4852 4964 4853 void CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList )4965 void CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames) 4854 4966 { 4855 4967 ASSERT(inputList.current() && inputList.current()->unit == CSSParserValue::ValueList); … … 4861 4973 } 4862 4974 4863 RefPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create(); 4975 // Need to ensure the identList is at the heading index, since the parserList might have been rewound. 4976 identList->setCurrentIndex(0); 4977 4978 RefPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames ? previousNamedAreaTrailingLineNames : CSSGridLineNamesValue::create(); 4864 4979 while (CSSParserValue* identValue = identList->current()) { 4865 4980 ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT); … … 4867 4982 identList->next(); 4868 4983 } 4869 valueList.append(lineNames.release()); 4984 if (!previousNamedAreaTrailingLineNames) 4985 valueList.append(lineNames.release()); 4870 4986 4871 4987 inputList.next(); 4872 4988 } 4873 4989 4874 bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important)4990 PassRefPtr<CSSValue> CSSParser::parseGridTrackList() 4875 4991 { 4876 4992 CSSParserValue* value = m_valueList->current(); 4877 4993 if (value->id == CSSValueNone) { 4878 if (m_valueList->next()) 4879 return false; 4880 4881 addProperty(propId, cssValuePool().createIdentifierValue(value->id), important); 4882 return true; 4994 m_valueList->next(); 4995 return cssValuePool().createIdentifierValue(CSSValueNone); 4883 4996 } 4884 4997 … … 4891 5004 bool seenTrackSizeOrRepeatFunction = false; 4892 5005 while (CSSParserValue* currentValue = m_valueList->current()) { 5006 if (isForwardSlashOperator(currentValue)) 5007 break; 4893 5008 if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) { 4894 5009 if (!parseGridTrackRepeatFunction(*values)) 4895 return false;5010 return nullptr; 4896 5011 } else { 4897 5012 RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList); 4898 5013 if (!value) 4899 return false;5014 return nullptr; 4900 5015 values->append(value.release()); 4901 5016 } … … 4909 5024 4910 5025 if (!seenTrackSizeOrRepeatFunction) 4911 return false; 4912 4913 addProperty(propId, values.release(), important); 4914 return true; 5026 return nullptr; 5027 5028 return values.release(); 4915 5029 } 4916 5030 … … 5149 5263 5150 5264 #if ENABLE(CSS_GRID_LAYOUT) 5265 bool CSSParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const unsigned rowCount, unsigned& columnCount) 5266 { 5267 CSSParserValue* currentValue = m_valueList->current(); 5268 if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING) 5269 return false; 5270 5271 String gridRowNames = currentValue->string; 5272 if (gridRowNames.isEmpty()) 5273 return false; 5274 5275 Vector<String> columnNames; 5276 gridRowNames.split(' ', columnNames); 5277 5278 if (!columnCount) { 5279 columnCount = columnNames.size(); 5280 ASSERT(columnCount); 5281 } else if (columnCount != columnNames.size()) { 5282 // The declaration is invalid is all the rows don't have the number of columns. 5283 return false; 5284 } 5285 5286 for (unsigned currentColumn = 0; currentColumn < columnCount; ++currentColumn) { 5287 const String& gridAreaName = columnNames[currentColumn]; 5288 5289 // Unamed areas are always valid (we consider them to be 1x1). 5290 if (gridAreaName == ".") 5291 continue; 5292 5293 // We handle several grid areas with the same name at once to simplify the validation code. 5294 unsigned lookAheadColumn; 5295 for (lookAheadColumn = currentColumn; lookAheadColumn < columnCount - 1; ++lookAheadColumn) { 5296 if (columnNames[lookAheadColumn + 1] != gridAreaName) 5297 break; 5298 } 5299 5300 auto gridAreaIterator = gridAreaMap.find(gridAreaName); 5301 if (gridAreaIterator == gridAreaMap.end()) 5302 gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentColumn, lookAheadColumn))); 5303 else { 5304 GridCoordinate& gridCoordinate = gridAreaIterator->value; 5305 5306 // The following checks test that the grid area is a single filled-in rectangle. 5307 // 1. The new row is adjacent to the previously parsed row. 5308 if (rowCount != gridCoordinate.rows.finalPositionIndex + 1) 5309 return 0; 5310 5311 // 2. The new area starts at the same position as the previously parsed area. 5312 if (currentColumn != gridCoordinate.columns.initialPositionIndex) 5313 return 0; 5314 5315 // 3. The new area ends at the same position as the previously parsed area. 5316 if (lookAheadColumn != gridCoordinate.columns.finalPositionIndex) 5317 return 0; 5318 5319 ++gridCoordinate.rows.finalPositionIndex; 5320 } 5321 currentColumn = lookAheadColumn; 5322 } 5323 5324 m_valueList->next(); 5325 return true; 5326 } 5327 5151 5328 PassRefPtr<CSSValue> CSSParser::parseGridTemplateAreas() 5152 5329 { 5153 5330 NamedGridAreaMap gridAreaMap; 5154 size_trowCount = 0;5155 size_tcolumnCount = 0;5156 5157 while ( CSSParserValue* currentValue =m_valueList->current()) {5158 if ( currentValue->unit != CSSPrimitiveValue::CSS_STRING)5331 unsigned rowCount = 0; 5332 unsigned columnCount = 0; 5333 5334 while (m_valueList->current()) { 5335 if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount)) 5159 5336 return 0; 5160 5161 String gridRowNames = currentValue->string;5162 if (!gridRowNames.length())5163 return 0;5164 5165 Vector<String> columnNames;5166 gridRowNames.split(' ', columnNames);5167 5168 if (columnCount && (columnCount != columnNames.size())) {5169 // The declaration is invalid if all the rows don't have the number of columns.5170 return 0;5171 }5172 5173 if (!columnCount) {5174 columnCount = columnNames.size();5175 ASSERT(columnCount);5176 }5177 5178 for (size_t currentColumn = 0; currentColumn < columnCount; ++currentColumn) {5179 const String& gridAreaName = columnNames[currentColumn];5180 5181 // Unamed areas are always valid (we consider them to be 1x1).5182 if (gridAreaName == ".")5183 continue;5184 5185 // We handle several grid areas with the same name at once to simplify the validation code.5186 size_t lookAheadColumn;5187 for (lookAheadColumn = currentColumn; lookAheadColumn < (columnCount - 1); ++lookAheadColumn) {5188 if (columnNames[lookAheadColumn + 1] != gridAreaName)5189 break;5190 }5191 5192 auto gridAreaIterator = gridAreaMap.find(gridAreaName);5193 if (gridAreaIterator == gridAreaMap.end())5194 gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentColumn, lookAheadColumn)));5195 else {5196 GridCoordinate& gridCoordinate = gridAreaIterator->value;5197 5198 // The following checks test that the grid area is a single filled-in rectangle.5199 // 1. The new row is adjacent to the previously parsed row.5200 if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)5201 return 0;5202 5203 // 2. The new area starts at the same position as the previously parsed area.5204 if (currentColumn != gridCoordinate.columns.initialPositionIndex)5205 return 0;5206 5207 // 3. The new area ends at the same position as the previously parsed area.5208 if (lookAheadColumn != gridCoordinate.columns.finalPositionIndex)5209 return 0;5210 5211 ++gridCoordinate.rows.finalPositionIndex;5212 }5213 currentColumn = lookAheadColumn;5214 }5215 5216 5337 ++rowCount; 5217 m_valueList->next();5218 5338 } 5219 5339 -
trunk/Source/WebCore/css/CSSParser.h
r166712 r167799 44 44 #endif 45 45 46 #if ENABLE(CSS_GRID_LAYOUT) 47 #include "CSSGridTemplateAreasValue.h" 48 #endif 49 46 50 namespace WebCore { 47 51 … … 54 58 class CSSBasicShape; 55 59 class CSSBasicShapeInset; 60 class CSSGridLineNamesValue; 56 61 class Document; 57 62 class Element; … … 157 162 PassRefPtr<CSSValue> parseGridPosition(); 158 163 bool parseGridItemPositionShorthand(CSSPropertyID, bool important); 164 bool parseGridTemplateRowsAndAreas(PassRefPtr<CSSValue>, bool important); 165 bool parseGridTemplateShorthand(bool important); 159 166 bool parseGridAreaShorthand(bool important); 160 167 bool parseSingleGridAreaLonghand(RefPtr<CSSValue>&); 161 bool parseGridTrackList(CSSPropertyID, bool important);168 PassRefPtr<CSSValue> parseGridTrackList(); 162 169 bool parseGridTrackRepeatFunction(CSSValueList&); 163 170 PassRefPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList); 164 171 PassRefPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue*); 172 bool parseGridTemplateAreasRow(NamedGridAreaMap&, const unsigned, unsigned&); 165 173 PassRefPtr<CSSValue> parseGridTemplateAreas(); 166 void parseGridLineNames(CSSParserValueList&, CSSValueList& );174 void parseGridLineNames(CSSParserValueList&, CSSValueList&, CSSGridLineNamesValue* = nullptr); 167 175 #endif 168 176 -
trunk/Source/WebCore/css/CSSParserValues.h
r167571 r167799 156 156 return current(); 157 157 } 158 void setCurrentIndex(unsigned index) 159 { 160 ASSERT(index < m_values.size()); 161 if (index < m_values.size()) 162 m_current = index; 163 } 158 164 159 165 CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; } -
trunk/Source/WebCore/css/CSSPropertyNames.in
r167448 r167799 311 311 -webkit-grid-column-end 312 312 -webkit-grid-column-start 313 -webkit-grid-template 313 314 -webkit-grid-template-columns 314 315 -webkit-grid-template-rows -
trunk/Source/WebCore/css/StylePropertyShorthand.cpp
r164659 r167799 353 353 354 354 #if ENABLE(CSS_GRID_LAYOUT) 355 StylePropertyShorthand webkitGridTemplateShorthand() 356 { 357 static const CSSPropertyID webkitGridTemplateProperties[] = { 358 CSSPropertyWebkitGridTemplateColumns, 359 CSSPropertyWebkitGridTemplateRows, 360 CSSPropertyWebkitGridTemplateAreas 361 }; 362 return StylePropertyShorthand(CSSPropertyWebkitGridTemplate, webkitGridTemplateProperties, WTF_ARRAY_LENGTH(webkitGridTemplateProperties)); 363 } 364 355 365 StylePropertyShorthand webkitGridAreaShorthand() 356 366 { -
trunk/Source/WebCore/css/StylePropertyShorthand.h
r163440 r167799 100 100 StylePropertyShorthand webkitFlexFlowShorthand(); 101 101 StylePropertyShorthand webkitFlexShorthand(); 102 StylePropertyShorthand webkitGridTemplateShorthand(); 102 103 StylePropertyShorthand webkitGridAreaShorthand(); 103 104 StylePropertyShorthand webkitGridColumnShorthand();
Note: See TracChangeset
for help on using the changeset viewer.