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

Unified Diff: Source/core/css/parser/CSSPropertyParser.cpp

Issue 149373004: [CSS Grid Layout] Implementation of the grid-template shorthand. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@grid-template-working
Patch Set: Patch rebased and adapted to the new parsing approach. Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/css/parser/CSSPropertyParser.h ('k') | Source/core/css/resolver/StyleBuilderCustom.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/parser/CSSPropertyParser.cpp
diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp
index 44d4a11799e1f3955d745b6643d136329b31d4bf..3e53a383e1b9d2e1332932856082dc8f50964583 100644
--- a/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1214,7 +1214,8 @@ bool CSSPropertyParser::parseValue(CSSPropertyID propId, bool important)
case CSSPropertyGridTemplateRows:
if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
return false;
- return parseGridTrackList(propId, important);
+ parsedValue = parseGridTrackList(important);
+ break;
case CSSPropertyGridColumnEnd:
case CSSPropertyGridColumnStart:
@@ -1242,6 +1243,11 @@ bool CSSPropertyParser::parseValue(CSSPropertyID propId, bool important)
parsedValue = parseGridTemplateAreas();
break;
+ case CSSPropertyGridTemplate:
+ if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
+ return false;
+ return parseGridTemplateShorthand(important);
+
case CSSPropertyWebkitMarginCollapse: {
if (num == 1) {
ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
@@ -3443,6 +3449,121 @@ bool CSSPropertyParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId
return true;
}
+bool CSSPropertyParser::parseGridTemplateRowsAndAreas(PassRefPtrWillBeRawPtr<CSSValue> templateColumns, bool important)
+{
+ NamedGridAreaMap gridAreaMap;
+ size_t rowCount = 0;
+ size_t columnCount = 0;
+ bool traillingIdentAdded = false;
Julien - ping for review 2014/03/21 19:25:55 This name is not English and it would be if it was
jfernandez 2014/03/22 00:30:45 Done.
+ RefPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated();
+
+ // At least template-areas strings must be defined.
+ if (!m_valueList->current())
+ return false;
+
+ // The template-columns <track-list> can't be 'none'.
+ if (templateColumns && templateColumns->isPrimitiveValue() && toCSSPrimitiveValue(templateColumns.get())->getValueID() == CSSValueNone)
Julien - ping for review 2014/03/21 19:25:55 This check feels misplaced and I think it should b
jfernandez 2014/03/22 00:30:45 Yes, I had lot of doubts. I understand your point
+ return false;
+
+ while (m_valueList->current()) {
+ // Handle leading <custom-ident>*.
+ if (m_valueList->current()->unit == CSSParserValue::ValueList) {
+ if (traillingIdentAdded) {
+ // A row's trailing ident must be concatenated with the next row's leading one.
+ parseGridLineNames(*m_valueList, *templateRows, static_cast<CSSGridLineNamesValue*>(templateRows->item(templateRows->length() - 1)));
+ } else {
+ parseGridLineNames(*m_valueList, *templateRows);
+ }
+ }
+
+ // Handle a template-area's row.
+ if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
+ return false;
+ ++rowCount;
+
+ // Handle template-rows's track-size.
+ if (m_valueList->current() && m_valueList->current()->unit != CSSParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS_STRING) {
+ RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
+ if (!value)
+ return false;
+ templateRows->append(value);
+ } else {
+ templateRows->append(cssValuePool().createIdentifierValue(CSSValueAuto));
+ }
+
+ // This will handle the trailing/leading <custom-ident>* in the grammar.
+ traillingIdentAdded = false;
+ if (m_valueList->current() && m_valueList->current()->unit == CSSParserValue::ValueList) {
+ parseGridLineNames(*m_valueList, *templateRows);
+ traillingIdentAdded = true;
+ }
+ }
+
+ // [<track-list> /]?
+ if (templateColumns)
+ addProperty(CSSPropertyGridTemplateColumns, templateColumns, important);
+ else
+ addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important);
+
+ // [<line-names>? <string> [<track-size> <line-names>]? ]+
+ RefPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount);
+ addProperty(CSSPropertyGridTemplateAreas, templateAreas.release(), important);
+ addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important);
+
+
+ return true;
+}
+
+
+bool CSSPropertyParser::parseGridTemplateShorthand(bool important)
+{
+ ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
+
+ ShorthandScope scope(this, CSSPropertyGridTemplate);
+ ASSERT(gridTemplateShorthand().length() == 3);
+
+ // At least "none" must be defined.
+ if (!m_valueList->current())
+ return false;
+
+ RefPtr<CSSValue> columnsValue;
+ unsigned index = 0;
+
+ // 1- 'none' case.
+ if (m_valueList->current()->id == CSSValueNone) {
+ if (!m_valueList->next()) {
+ addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important);
+ addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifierValue(CSSValueNone), important);
+ addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+ return true;
+ }
+ columnsValue = cssValuePool().createIdentifierValue(CSSValueNone);
+ } else {
+ columnsValue = parseGridTrackList(important);
+ }
+
+
+ // 2- <grid-template-columns> / <grid-template-columns> syntax.
+ if (columnsValue) {
+ if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current()) && m_valueList->next()))
+ return false;
+ index = m_valueList->currentIndex();
+ if (RefPtr<CSSValue> rowsValue = parseGridTrackList(important)) {
+ if (m_valueList->current())
+ return false;
+ addProperty(CSSPropertyGridTemplateColumns, columnsValue, important);
+ addProperty(CSSPropertyGridTemplateRows, rowsValue, important);
+ addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+ return true;
+ }
+ }
+
+ // 3- [<track-list> /]? [<line-names>? <string> [<track-size> <line-names>]? ]+ syntax.
+ // It requires to rewind parsing due to previous syntax failures.
+ m_valueList->setCurrentIndex(index);
+ return parseGridTemplateRowsAndAreas(columnsValue, important);
+}
+
bool CSSPropertyParser::parseGridAreaShorthand(bool important)
{
ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
@@ -3498,72 +3619,74 @@ bool CSSPropertyParser::parseSingleGridAreaLonghand(RefPtrWillBeRawPtr<CSSValue>
return true;
}
-void CSSPropertyParser::parseGridLineNames(CSSParserValueList* parserValueList, CSSValueList& valueList)
+void CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList, CSSGridLineNamesValue* lineNamesToConcat)
Julien - ping for review 2014/03/21 19:25:55 Let's rename lineNamesToConcat to something cleare
jfernandez 2014/03/22 00:30:45 Done.
{
- ASSERT(parserValueList->current() && parserValueList->current()->unit == CSSParserValue::ValueList);
+ ASSERT(inputList.current() && inputList.current()->unit == CSSParserValue::ValueList);
- CSSParserValueList* identList = parserValueList->current()->valueList;
+ CSSParserValueList* identList = inputList.current()->valueList;
if (!identList->size()) {
- parserValueList->next();
+ inputList.next();
return;
}
- RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create();
+ // Need to ensure the identList is at the heading index, since the parserList might have been rewound.
+ identList->setCurrentIndex(0);
+
+ RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = lineNamesToConcat ? lineNamesToConcat : CSSGridLineNamesValue::create();
while (CSSParserValue* identValue = identList->current()) {
ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT);
RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringValue(identValue);
lineNames->append(lineName.release());
identList->next();
}
- valueList.append(lineNames.release());
+ if (!lineNamesToConcat)
+ valueList.append(lineNames.release());
- parserValueList->next();
+ inputList.next();
}
-bool CSSPropertyParser::parseGridTrackList(CSSPropertyID propId, bool important)
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackList(bool important)
{
ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
CSSParserValue* value = m_valueList->current();
if (value->id == CSSValueNone) {
- if (m_valueList->next())
- return false;
-
- addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
- return true;
+ m_valueList->next();
+ return cssValuePool().createIdentifierValue(CSSValueNone);
}
RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
// Handle leading <ident>*.
value = m_valueList->current();
if (value && value->unit == CSSParserValue::ValueList)
- parseGridLineNames(m_valueList.get(), *values);
+ parseGridLineNames(*m_valueList, *values);
bool seenTrackSizeOrRepeatFunction = false;
while (CSSParserValue* currentValue = m_valueList->current()) {
+ if (isForwardSlashOperator(currentValue))
+ break;
if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) {
if (!parseGridTrackRepeatFunction(*values))
- return false;
+ return nullptr;
seenTrackSizeOrRepeatFunction = true;
} else {
RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
if (!value)
- return false;
+ return nullptr;
values->append(value);
seenTrackSizeOrRepeatFunction = true;
}
// This will handle the trailing <ident>* in the grammar.
value = m_valueList->current();
if (value && value->unit == CSSParserValue::ValueList)
- parseGridLineNames(m_valueList.get(), *values);
+ parseGridLineNames(*m_valueList, *values);
}
// We should have found a <track-size> or else it is not a valid <track-list>
if (!seenTrackSizeOrRepeatFunction)
- return false;
+ return nullptr;
- addProperty(propId, values.release(), important);
- return true;
+ return values;
}
bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list)
@@ -3581,7 +3704,7 @@ bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list)
// Handle leading <ident>*.
CSSParserValue* currentValue = arguments->current();
if (currentValue && currentValue->unit == CSSParserValue::ValueList)
- parseGridLineNames(arguments, *repeatedValues);
+ parseGridLineNames(*arguments, *repeatedValues);
while (arguments->current()) {
RefPtrWillBeRawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments);
@@ -3593,7 +3716,7 @@ bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list)
// This takes care of any trailing <ident>* in the grammar.
currentValue = arguments->current();
if (currentValue && currentValue->unit == CSSParserValue::ValueList)
- parseGridLineNames(arguments, *repeatedValues);
+ parseGridLineNames(*arguments, *repeatedValues);
}
for (size_t i = 0; i < repetitions; ++i) {
@@ -3661,71 +3784,79 @@ PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseGridBreadth(CS
return createPrimitiveNumericValue(currentValue);
}
-PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTemplateAreas()
+bool CSSPropertyParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const size_t rowCount, size_t& columnCount)
{
- NamedGridAreaMap gridAreaMap;
- size_t rowCount = 0;
- size_t columnCount = 0;
-
- while (CSSParserValue* currentValue = m_valueList->current()) {
- if (currentValue->unit != CSSPrimitiveValue::CSS_STRING)
- return nullptr;
+ CSSParserValue* currentValue = m_valueList->current();
+ if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING)
+ return false;
- String gridRowNames = currentValue->string;
- if (!gridRowNames.length())
- return nullptr;
+ String gridRowNames = currentValue->string;
+ if (!gridRowNames.length())
+ return false;
- Vector<String> columnNames;
- gridRowNames.split(' ', columnNames);
+ Vector<String> columnNames;
+ gridRowNames.split(' ', columnNames);
- if (!columnCount) {
- columnCount = columnNames.size();
- ASSERT(columnCount);
- } else if (columnCount != columnNames.size()) {
- // The declaration is invalid is all the rows don't have the number of columns.
- return nullptr;
- }
+ if (!columnCount) {
+ columnCount = columnNames.size();
+ ASSERT(columnCount);
+ } else if (columnCount != columnNames.size()) {
+ // The declaration is invalid is all the rows don't have the number of columns.
+ return false;
+ }
- for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
- const String& gridAreaName = columnNames[currentCol];
+ for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
+ const String& gridAreaName = columnNames[currentCol];
- // Unamed areas are always valid (we consider them to be 1x1).
- if (gridAreaName == ".")
- continue;
+ // Unamed areas are always valid (we consider them to be 1x1).
+ if (gridAreaName == ".")
+ continue;
- // We handle several grid areas with the same name at once to simplify the validation code.
- size_t lookAheadCol;
- for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) {
- if (columnNames[lookAheadCol + 1] != gridAreaName)
- break;
- }
+ // We handle several grid areas with the same name at once to simplify the validation code.
+ size_t lookAheadCol;
+ for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) {
+ if (columnNames[lookAheadCol + 1] != gridAreaName)
+ break;
+ }
- NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
- if (gridAreaIt == gridAreaMap.end()) {
- gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol)));
- } else {
- GridCoordinate& gridCoordinate = gridAreaIt->value;
+ NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
+ if (gridAreaIt == gridAreaMap.end()) {
+ gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol)));
+ } else {
+ GridCoordinate& gridCoordinate = gridAreaIt->value;
- // The following checks test that the grid area is a single filled-in rectangle.
- // 1. The new row is adjacent to the previously parsed row.
- if (rowCount != gridCoordinate.rows.initialPositionIndex + 1)
- return nullptr;
+ // The following checks test that the grid area is a single filled-in rectangle.
+ // 1. The new row is adjacent to the previously parsed row.
+ if (rowCount != gridCoordinate.rows.initialPositionIndex + 1)
+ return false;
- // 2. The new area starts at the same position as the previously parsed area.
- if (currentCol != gridCoordinate.columns.initialPositionIndex)
- return nullptr;
+ // 2. The new area starts at the same position as the previously parsed area.
+ if (currentCol != gridCoordinate.columns.initialPositionIndex)
+ return false;
- // 3. The new area ends at the same position as the previously parsed area.
- if (lookAheadCol != gridCoordinate.columns.finalPositionIndex)
- return nullptr;
+ // 3. The new area ends at the same position as the previously parsed area.
+ if (lookAheadCol != gridCoordinate.columns.finalPositionIndex)
+ return false;
- ++gridCoordinate.rows.finalPositionIndex;
- }
- currentCol = lookAheadCol;
+ ++gridCoordinate.rows.finalPositionIndex;
}
+ currentCol = lookAheadCol;
+ }
+
+ m_valueList->next();
+ return true;
+}
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTemplateAreas()
+{
+ NamedGridAreaMap gridAreaMap;
+ size_t rowCount = 0;
+ size_t columnCount = 0;
+
+ while (m_valueList->current()) {
+ if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
+ return nullptr;
++rowCount;
- m_valueList->next();
}
if (!rowCount || !columnCount)
« no previous file with comments | « Source/core/css/parser/CSSPropertyParser.h ('k') | Source/core/css/resolver/StyleBuilderCustom.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698