OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/css/parser/CSSPropertyParser.h" | 5 #include "core/css/parser/CSSPropertyParser.h" |
6 | 6 |
7 #include "core/StylePropertyShorthand.h" | 7 #include "core/StylePropertyShorthand.h" |
8 #include "core/css/CSSBasicShapeValues.h" | 8 #include "core/css/CSSBasicShapeValues.h" |
9 #include "core/css/CSSBorderImage.h" | 9 #include "core/css/CSSBorderImage.h" |
10 #include "core/css/CSSContentDistributionValue.h" | 10 #include "core/css/CSSContentDistributionValue.h" |
(...skipping 3241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3252 if (spanValue) | 3252 if (spanValue) |
3253 values->append(spanValue); | 3253 values->append(spanValue); |
3254 if (numericValue) | 3254 if (numericValue) |
3255 values->append(numericValue); | 3255 values->append(numericValue); |
3256 if (gridLineName) | 3256 if (gridLineName) |
3257 values->append(gridLineName); | 3257 values->append(gridLineName); |
3258 ASSERT(values->length()); | 3258 ASSERT(values->length()); |
3259 return values; | 3259 return values; |
3260 } | 3260 } |
3261 | 3261 |
3262 static bool allTracksAreFixedSized(CSSValueList& valueList) | 3262 static bool isGridTrackFixedSized(const CSSValue& value) |
3263 { | 3263 { |
3264 for (CSSValue* value : valueList) { | 3264 const CSSPrimitiveValue& primitiveValue = value.isPrimitiveValue() |
3265 if (value->isGridLineNamesValue()) | 3265 ? toCSSPrimitiveValue(value) |
3266 continue; | 3266 : toCSSPrimitiveValue(*toCSSFunctionValue(value).item(0)); |
3267 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax
( <fixed-breadth>, <track-breadth> ) | 3267 CSSValueID valueID = primitiveValue.getValueID(); |
3268 if (value->isGridAutoRepeatValue()) { | 3268 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || valueI
D == CSSValueAuto || primitiveValue.isFlex()) |
3269 if (!allTracksAreFixedSized(toCSSValueList(*value))) | 3269 return false; |
3270 return false; | 3270 |
3271 continue; | |
3272 } | |
3273 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() | |
3274 ? toCSSPrimitiveValue(*value) | |
3275 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); | |
3276 CSSValueID valueID = primitiveValue.getValueID(); | |
3277 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va
lueID == CSSValueAuto || primitiveValue.isFlex()) | |
3278 return false; | |
3279 } | |
3280 return true; | 3271 return true; |
3281 } | 3272 } |
3282 | 3273 |
3283 static Vector<String> parseGridTemplateAreasColumnNames(const String& gridRowNam
es) | 3274 static Vector<String> parseGridTemplateAreasColumnNames(const String& gridRowNam
es) |
3284 { | 3275 { |
3285 ASSERT(!gridRowNames.isEmpty()); | 3276 ASSERT(!gridRowNames.isEmpty()); |
3286 Vector<String> columnNames; | 3277 Vector<String> columnNames; |
3287 // Using StringImpl to avoid checks and indirection in every call to String:
:operator[]. | 3278 // Using StringImpl to avoid checks and indirection in every call to String:
:operator[]. |
3288 StringImpl& text = *gridRowNames.impl(); | 3279 StringImpl& text = *gridRowNames.impl(); |
3289 | 3280 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3367 return false; | 3358 return false; |
3368 | 3359 |
3369 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); | 3360 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); |
3370 } | 3361 } |
3371 currentColumn = lookAheadColumn - 1; | 3362 currentColumn = lookAheadColumn - 1; |
3372 } | 3363 } |
3373 | 3364 |
3374 return true; | 3365 return true; |
3375 } | 3366 } |
3376 | 3367 |
3377 enum TrackSizeRestriction { FixedSizeOnly, InflexibleSizeOnly, AllowAll }; | 3368 static CSSPrimitiveValue* consumeGridBreadth(CSSParserTokenRange& range, CSSPars
erMode cssParserMode) |
3378 | |
3379 static CSSPrimitiveValue* consumeGridBreadth(CSSParserTokenRange& range, CSSPars
erMode cssParserMode, TrackSizeRestriction restriction = AllowAll) | |
3380 { | 3369 { |
3381 if (restriction != FixedSizeOnly) { | 3370 const CSSParserToken& token = range.peek(); |
3382 const CSSParserToken& token = range.peek(); | 3371 if (identMatches<CSSValueMinContent, CSSValueMaxContent, CSSValueAuto>(token
.id())) |
3383 if (identMatches<CSSValueMinContent, CSSValueMaxContent, CSSValueAuto>(t
oken.id())) | 3372 return consumeIdent(range); |
3384 return consumeIdent(range); | 3373 if (token.type() == DimensionToken && token.unitType() == CSSPrimitiveValue:
:UnitType::Fraction) { |
3385 if (token.type() == DimensionToken && token.unitType() == CSSPrimitiveVa
lue::UnitType::Fraction) { | 3374 if (range.peek().numericValue() < 0) |
3386 if (restriction == InflexibleSizeOnly || range.peek().numericValue()
< 0) | 3375 return nullptr; |
3387 return nullptr; | 3376 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), CSSPrimitiveValue::UnitType::Fraction); |
3388 return cssValuePool().createValue(range.consumeIncludingWhitespace()
.numericValue(), CSSPrimitiveValue::UnitType::Fraction); | |
3389 } | |
3390 } | 3377 } |
3391 return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative, U
nitlessQuirk::Allow); | 3378 return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative, U
nitlessQuirk::Allow); |
3392 } | 3379 } |
3393 | 3380 |
3394 // TODO(rob.buis): This needs a bool parameter so we can disallow <auto-track-li
st> for the grid shorthand. | 3381 // TODO(rob.buis): This needs a bool parameter so we can disallow <auto-track-li
st> for the grid shorthand. |
3395 static CSSValue* consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode
cssParserMode, TrackSizeRestriction restriction = AllowAll) | 3382 static CSSValue* consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode
cssParserMode) |
3396 { | 3383 { |
3397 const CSSParserToken& token = range.peek(); | 3384 const CSSParserToken& token = range.peek(); |
3398 if (restriction == AllowAll && identMatches<CSSValueAuto>(token.id())) | 3385 if (identMatches<CSSValueAuto>(token.id())) |
3399 return consumeIdent(range); | 3386 return consumeIdent(range); |
3400 | 3387 |
3401 if (token.functionId() == CSSValueMinmax) { | 3388 if (token.functionId() == CSSValueMinmax) { |
3402 CSSParserTokenRange rangeCopy = range; | 3389 CSSParserTokenRange rangeCopy = range; |
3403 CSSParserTokenRange args = consumeFunction(rangeCopy); | 3390 CSSParserTokenRange args = consumeFunction(rangeCopy); |
3404 TrackSizeRestriction minTrackBreadthRestriction = restriction == AllowAl
l ? InflexibleSizeOnly : restriction; | 3391 CSSPrimitiveValue* minTrackBreadth = consumeGridBreadth(args, cssParserM
ode); |
3405 CSSPrimitiveValue* minTrackBreadth = consumeGridBreadth(args, cssParserM
ode, minTrackBreadthRestriction); | 3392 if (!minTrackBreadth || minTrackBreadth->isFlex() || !consumeCommaInclud
ingWhitespace(args)) |
3406 if (!minTrackBreadth || !consumeCommaIncludingWhitespace(args)) | |
3407 return nullptr; | 3393 return nullptr; |
3408 CSSPrimitiveValue* maxTrackBreadth = consumeGridBreadth(args, cssParserM
ode); | 3394 CSSPrimitiveValue* maxTrackBreadth = consumeGridBreadth(args, cssParserM
ode); |
3409 if (!maxTrackBreadth || !args.atEnd()) | 3395 if (!maxTrackBreadth || !args.atEnd()) |
3410 return nullptr; | 3396 return nullptr; |
3411 range = rangeCopy; | 3397 range = rangeCopy; |
3412 CSSFunctionValue* result = CSSFunctionValue::create(CSSValueMinmax); | 3398 CSSFunctionValue* result = CSSFunctionValue::create(CSSValueMinmax); |
3413 result->append(minTrackBreadth); | 3399 result->append(minTrackBreadth); |
3414 result->append(maxTrackBreadth); | 3400 result->append(maxTrackBreadth); |
3415 return result; | 3401 return result; |
3416 } | 3402 } |
3417 return consumeGridBreadth(range, cssParserMode, restriction); | 3403 return consumeGridBreadth(range, cssParserMode); |
3418 } | 3404 } |
3419 | 3405 |
3420 // Appends to the passed in CSSGridLineNamesValue if any, otherwise creates a ne
w one. | 3406 // Appends to the passed in CSSGridLineNamesValue if any, otherwise creates a ne
w one. |
3421 static CSSGridLineNamesValue* consumeGridLineNames(CSSParserTokenRange& range, C
SSGridLineNamesValue* lineNames = nullptr) | 3407 static CSSGridLineNamesValue* consumeGridLineNames(CSSParserTokenRange& range, C
SSGridLineNamesValue* lineNames = nullptr) |
3422 { | 3408 { |
3423 CSSParserTokenRange rangeCopy = range; | 3409 CSSParserTokenRange rangeCopy = range; |
3424 if (rangeCopy.consumeIncludingWhitespace().type() != LeftBracketToken) | 3410 if (rangeCopy.consumeIncludingWhitespace().type() != LeftBracketToken) |
3425 return nullptr; | 3411 return nullptr; |
3426 if (!lineNames) | 3412 if (!lineNames) |
3427 lineNames = CSSGridLineNamesValue::create(); | 3413 lineNames = CSSGridLineNamesValue::create(); |
3428 while (CSSCustomIdentValue* lineName = consumeCustomIdentForGridLine(rangeCo
py)) | 3414 while (CSSCustomIdentValue* lineName = consumeCustomIdentForGridLine(rangeCo
py)) |
3429 lineNames->append(lineName); | 3415 lineNames->append(lineName); |
3430 if (rangeCopy.consumeIncludingWhitespace().type() != RightBracketToken) | 3416 if (rangeCopy.consumeIncludingWhitespace().type() != RightBracketToken) |
3431 return nullptr; | 3417 return nullptr; |
3432 range = rangeCopy; | 3418 range = rangeCopy; |
3433 return lineNames; | 3419 return lineNames; |
3434 } | 3420 } |
3435 | 3421 |
3436 static bool consumeGridTrackRepeatFunction(CSSParserTokenRange& range, CSSParser
Mode cssParserMode, CSSValueList& list, bool& isAutoRepeat) | 3422 static bool consumeGridTrackRepeatFunction(CSSParserTokenRange& range, CSSParser
Mode cssParserMode, CSSValueList& list, bool& isAutoRepeat, bool& allTracksAreFi
xedSized) |
3437 { | 3423 { |
3438 CSSParserTokenRange args = consumeFunction(range); | 3424 CSSParserTokenRange args = consumeFunction(range); |
3439 // The number of repetitions for <auto-repeat> is not important at parsing l
evel | 3425 // The number of repetitions for <auto-repeat> is not important at parsing l
evel |
3440 // because it will be computed later, let's set it to 1. | 3426 // because it will be computed later, let's set it to 1. |
3441 size_t repetitions = 1; | 3427 size_t repetitions = 1; |
3442 isAutoRepeat = identMatches<CSSValueAutoFill, CSSValueAutoFit>(args.peek().i
d()); | 3428 isAutoRepeat = identMatches<CSSValueAutoFill, CSSValueAutoFit>(args.peek().i
d()); |
3443 CSSValueList* repeatedValues; | 3429 CSSValueList* repeatedValues; |
3444 if (isAutoRepeat) { | 3430 if (isAutoRepeat) { |
3445 repeatedValues = CSSGridAutoRepeatValue::create(args.consumeIncludingWhi
tespace().id()); | 3431 repeatedValues = CSSGridAutoRepeatValue::create(args.consumeIncludingWhi
tespace().id()); |
3446 } else { | 3432 } else { |
3447 // TODO(rob.buis): a consumeIntegerRaw would be more efficient here. | 3433 // TODO(rob.buis): a consumeIntegerRaw would be more efficient here. |
3448 CSSPrimitiveValue* repetition = consumePositiveInteger(args); | 3434 CSSPrimitiveValue* repetition = consumePositiveInteger(args); |
3449 if (!repetition) | 3435 if (!repetition) |
3450 return false; | 3436 return false; |
3451 repetitions = clampTo<size_t>(repetition->getDoubleValue(), 0, kGridMaxT
racks); | 3437 repetitions = clampTo<size_t>(repetition->getDoubleValue(), 0, kGridMaxT
racks); |
3452 repeatedValues = CSSValueList::createSpaceSeparated(); | 3438 repeatedValues = CSSValueList::createSpaceSeparated(); |
3453 } | 3439 } |
3454 if (!consumeCommaIncludingWhitespace(args)) | 3440 if (!consumeCommaIncludingWhitespace(args)) |
3455 return false; | 3441 return false; |
3456 CSSGridLineNamesValue* lineNames = consumeGridLineNames(args); | 3442 CSSGridLineNamesValue* lineNames = consumeGridLineNames(args); |
3457 if (lineNames) | 3443 if (lineNames) |
3458 repeatedValues->append(lineNames); | 3444 repeatedValues->append(lineNames); |
3459 | 3445 |
3460 size_t numberOfTracks = 0; | 3446 size_t numberOfTracks = 0; |
3461 TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll; | |
3462 while (!args.atEnd()) { | 3447 while (!args.atEnd()) { |
3463 if (isAutoRepeat && numberOfTracks) | 3448 if (isAutoRepeat && numberOfTracks) |
3464 return false; | 3449 return false; |
3465 CSSValue* trackSize = consumeGridTrackSize(args, cssParserMode, restrict
ion); | 3450 CSSValue* trackSize = consumeGridTrackSize(args, cssParserMode); |
3466 if (!trackSize) | 3451 if (!trackSize) |
3467 return false; | 3452 return false; |
| 3453 if (allTracksAreFixedSized) |
| 3454 allTracksAreFixedSized = isGridTrackFixedSized(*trackSize); |
3468 repeatedValues->append(trackSize); | 3455 repeatedValues->append(trackSize); |
3469 ++numberOfTracks; | 3456 ++numberOfTracks; |
3470 lineNames = consumeGridLineNames(args); | 3457 lineNames = consumeGridLineNames(args); |
3471 if (lineNames) | 3458 if (lineNames) |
3472 repeatedValues->append(lineNames); | 3459 repeatedValues->append(lineNames); |
3473 } | 3460 } |
3474 // We should have found at least one <track-size> or else it is not a valid
<track-list>. | 3461 // We should have found at least one <track-size> or else it is not a valid
<track-list>. |
3475 if (!numberOfTracks) | 3462 if (!numberOfTracks) |
3476 return false; | 3463 return false; |
3477 | 3464 |
(...skipping 11 matching lines...) Expand all Loading... |
3489 } | 3476 } |
3490 | 3477 |
3491 static CSSValue* consumeGridTrackList(CSSParserTokenRange& range, CSSParserMode
cssParserMode) | 3478 static CSSValue* consumeGridTrackList(CSSParserTokenRange& range, CSSParserMode
cssParserMode) |
3492 { | 3479 { |
3493 CSSValueList* values = CSSValueList::createSpaceSeparated(); | 3480 CSSValueList* values = CSSValueList::createSpaceSeparated(); |
3494 CSSGridLineNamesValue* lineNames = consumeGridLineNames(range); | 3481 CSSGridLineNamesValue* lineNames = consumeGridLineNames(range); |
3495 if (lineNames) | 3482 if (lineNames) |
3496 values->append(lineNames); | 3483 values->append(lineNames); |
3497 | 3484 |
3498 bool seenAutoRepeat = false; | 3485 bool seenAutoRepeat = false; |
| 3486 bool allTracksAreFixedSized = true; |
3499 // TODO(rob.buis): <line-names> should not be able to directly precede <auto
-repeat>. | 3487 // TODO(rob.buis): <line-names> should not be able to directly precede <auto
-repeat>. |
3500 do { | 3488 do { |
3501 bool isAutoRepeat; | 3489 bool isAutoRepeat; |
3502 if (range.peek().functionId() == CSSValueRepeat) { | 3490 if (range.peek().functionId() == CSSValueRepeat) { |
3503 if (!consumeGridTrackRepeatFunction(range, cssParserMode, *values, i
sAutoRepeat)) | 3491 if (!consumeGridTrackRepeatFunction(range, cssParserMode, *values, i
sAutoRepeat, allTracksAreFixedSized)) |
3504 return nullptr; | 3492 return nullptr; |
3505 if (isAutoRepeat && seenAutoRepeat) | 3493 if (isAutoRepeat && seenAutoRepeat) |
3506 return nullptr; | 3494 return nullptr; |
3507 seenAutoRepeat = seenAutoRepeat || isAutoRepeat; | 3495 seenAutoRepeat = seenAutoRepeat || isAutoRepeat; |
3508 } else if (CSSValue* value = consumeGridTrackSize(range, cssParserMode,
seenAutoRepeat ? FixedSizeOnly : AllowAll)) { | 3496 } else if (CSSValue* value = consumeGridTrackSize(range, cssParserMode))
{ |
| 3497 if (allTracksAreFixedSized) |
| 3498 allTracksAreFixedSized = isGridTrackFixedSized(*value); |
3509 values->append(value); | 3499 values->append(value); |
3510 } else { | 3500 } else { |
3511 return nullptr; | 3501 return nullptr; |
3512 } | 3502 } |
| 3503 if (seenAutoRepeat && !allTracksAreFixedSized) |
| 3504 return nullptr; |
3513 lineNames = consumeGridLineNames(range); | 3505 lineNames = consumeGridLineNames(range); |
3514 if (lineNames) | 3506 if (lineNames) |
3515 values->append(lineNames); | 3507 values->append(lineNames); |
3516 } while (!range.atEnd() && range.peek().type() != DelimiterToken); | 3508 } while (!range.atEnd() && range.peek().type() != DelimiterToken); |
3517 // <auto-repeat> requires definite minimum track sizes in order to compute t
he number of repetitions. | |
3518 // The above while loop detects those appearances after the <auto-repeat> bu
t not the ones before. | |
3519 if (seenAutoRepeat && !allTracksAreFixedSized(*values)) | |
3520 return nullptr; | |
3521 return values; | 3509 return values; |
3522 } | 3510 } |
3523 | 3511 |
3524 static CSSValue* consumeGridTemplatesRowsOrColumns(CSSParserTokenRange& range, C
SSParserMode cssParserMode) | 3512 static CSSValue* consumeGridTemplatesRowsOrColumns(CSSParserTokenRange& range, C
SSParserMode cssParserMode) |
3525 { | 3513 { |
3526 if (range.peek().id() == CSSValueNone) | 3514 if (range.peek().id() == CSSValueNone) |
3527 return consumeIdent(range); | 3515 return consumeIdent(range); |
3528 return consumeGridTrackList(range, cssParserMode); | 3516 return consumeGridTrackList(range, cssParserMode); |
3529 } | 3517 } |
3530 | 3518 |
(...skipping 1643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5174 case CSSPropertyGridTemplate: | 5162 case CSSPropertyGridTemplate: |
5175 return consumeGridTemplateShorthand(CSSPropertyGridTemplate, important); | 5163 return consumeGridTemplateShorthand(CSSPropertyGridTemplate, important); |
5176 case CSSPropertyGrid: | 5164 case CSSPropertyGrid: |
5177 return consumeGridShorthand(important); | 5165 return consumeGridShorthand(important); |
5178 default: | 5166 default: |
5179 return false; | 5167 return false; |
5180 } | 5168 } |
5181 } | 5169 } |
5182 | 5170 |
5183 } // namespace blink | 5171 } // namespace blink |
OLD | NEW |