| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 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. | 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> | 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
| 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
| 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 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. | 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
| 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
| 10 * | 10 * |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 return CSSPrimitiveValue::create(m_parsedCalculation.release()); | 199 return CSSPrimitiveValue::create(m_parsedCalculation.release()); |
| 200 } | 200 } |
| 201 | 201 |
| 202 ASSERT((value->unit() >= CSSPrimitiveValue::UnitType::Number && value->unit(
) <= CSSPrimitiveValue::UnitType::Kilohertz) | 202 ASSERT((value->unit() >= CSSPrimitiveValue::UnitType::Number && value->unit(
) <= CSSPrimitiveValue::UnitType::Kilohertz) |
| 203 || (value->unit() >= CSSPrimitiveValue::UnitType::Turns && value->unit()
<= CSSPrimitiveValue::UnitType::Chs) | 203 || (value->unit() >= CSSPrimitiveValue::UnitType::Turns && value->unit()
<= CSSPrimitiveValue::UnitType::Chs) |
| 204 || (value->unit() >= CSSPrimitiveValue::UnitType::ViewportWidth && value
->unit() <= CSSPrimitiveValue::UnitType::ViewportMax) | 204 || (value->unit() >= CSSPrimitiveValue::UnitType::ViewportWidth && value
->unit() <= CSSPrimitiveValue::UnitType::ViewportMax) |
| 205 || (value->unit() >= CSSPrimitiveValue::UnitType::DotsPerPixel && value-
>unit() <= CSSPrimitiveValue::UnitType::DotsPerCentimeter)); | 205 || (value->unit() >= CSSPrimitiveValue::UnitType::DotsPerPixel && value-
>unit() <= CSSPrimitiveValue::UnitType::DotsPerCentimeter)); |
| 206 return cssValuePool().createValue(value->fValue, value->unit()); | 206 return cssValuePool().createValue(value->fValue, value->unit()); |
| 207 } | 207 } |
| 208 | 208 |
| 209 inline RawPtr<CSSCustomIdentValue> CSSPropertyParser::createPrimitiveCustomIdent
Value(CSSParserValue* value) | |
| 210 { | |
| 211 ASSERT(value->m_unit == CSSParserValue::String || value->m_unit == CSSParser
Value::Identifier); | |
| 212 return CSSCustomIdentValue::create(value->string); | |
| 213 } | |
| 214 | |
| 215 static inline bool isComma(CSSParserValue* value) | 209 static inline bool isComma(CSSParserValue* value) |
| 216 { | 210 { |
| 217 ASSERT(value); | 211 ASSERT(value); |
| 218 return value->m_unit == CSSParserValue::Operator && value->iValue == ','; | 212 return value->m_unit == CSSParserValue::Operator && value->iValue == ','; |
| 219 } | 213 } |
| 220 | 214 |
| 221 static inline bool isForwardSlashOperator(CSSParserValue* value) | 215 static inline bool isForwardSlashOperator(CSSParserValue* value) |
| 222 { | 216 { |
| 223 ASSERT(value); | 217 ASSERT(value); |
| 224 return value->m_unit == CSSParserValue::Operator && value->iValue == '/'; | 218 return value->m_unit == CSSParserValue::Operator && value->iValue == '/'; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 if (parsedValue) { | 268 if (parsedValue) { |
| 275 if (!m_valueList->current() || inShorthand()) | 269 if (!m_valueList->current() || inShorthand()) |
| 276 return parsedValue.release(); | 270 return parsedValue.release(); |
| 277 } | 271 } |
| 278 return nullptr; | 272 return nullptr; |
| 279 } | 273 } |
| 280 | 274 |
| 281 bool CSSPropertyParser::legacyParseShorthand(CSSPropertyID propertyID, bool impo
rtant) | 275 bool CSSPropertyParser::legacyParseShorthand(CSSPropertyID propertyID, bool impo
rtant) |
| 282 { | 276 { |
| 283 switch (propertyID) { | 277 switch (propertyID) { |
| 284 case CSSPropertyGridTemplate: | |
| 285 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | |
| 286 return parseGridTemplateShorthand(important); | |
| 287 | |
| 288 case CSSPropertyGrid: | 278 case CSSPropertyGrid: |
| 289 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 279 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
| 290 return parseGridShorthand(important); | 280 return parseGridShorthand(important); |
| 291 | 281 |
| 292 // The remaining shorthands are handled in CSSPropertyParser.cpp | 282 // The remaining shorthands are handled in CSSPropertyParser.cpp |
| 293 default: | 283 default: |
| 294 return false; | 284 return false; |
| 295 } | 285 } |
| 296 } | 286 } |
| 297 | 287 |
| 298 static inline bool isCSSWideKeyword(const CSSParserValue& value) | |
| 299 { | |
| 300 return value.id == CSSValueInitial || value.id == CSSValueInherit || value.i
d == CSSValueUnset || value.id == CSSValueDefault; | |
| 301 } | |
| 302 | |
| 303 static inline bool isValidCustomIdentForGridPositions(const CSSParserValue& valu
e) | |
| 304 { | |
| 305 // FIXME: we need a more general solution for <custom-ident> in all properti
es. | |
| 306 return value.m_unit == CSSParserValue::Identifier && value.id != CSSValueSpa
n && value.id != CSSValueAuto && !isCSSWideKeyword(value); | |
| 307 } | |
| 308 | |
| 309 RawPtr<CSSValue> CSSPropertyParser::parseGridTemplateColumns(bool important) | |
| 310 { | |
| 311 if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current(
)) && m_valueList->next())) | |
| 312 return nullptr; | |
| 313 if (RawPtr<CSSValue> columnsValue = parseGridTrackList()) { | |
| 314 if (m_valueList->current()) | |
| 315 return nullptr; | |
| 316 return columnsValue; | |
| 317 } | |
| 318 | |
| 319 return nullptr; | |
| 320 } | |
| 321 | |
| 322 bool CSSPropertyParser::parseGridTemplateRowsAndAreasAndColumns(bool important) | |
| 323 { | |
| 324 NamedGridAreaMap gridAreaMap; | |
| 325 size_t rowCount = 0; | |
| 326 size_t columnCount = 0; | |
| 327 bool trailingIdentWasAdded = false; | |
| 328 RawPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated(); | |
| 329 | |
| 330 // At least template-areas strings must be defined. | |
| 331 if (!m_valueList->current() || isForwardSlashOperator(m_valueList->current()
)) | |
| 332 return false; | |
| 333 | |
| 334 while (m_valueList->current() && !isForwardSlashOperator(m_valueList->curren
t())) { | |
| 335 // Handle leading <custom-ident>*. | |
| 336 if (!parseGridLineNames(*m_valueList, *templateRows, trailingIdentWasAdd
ed ? toCSSGridLineNamesValue(templateRows->item(templateRows->length() - 1)) : n
ullptr)) | |
| 337 return false; | |
| 338 | |
| 339 // Handle a template-area's row. | |
| 340 CSSParserValue* currentValue = m_valueList->current(); | |
| 341 if (!currentValue || currentValue->m_unit != CSSParserValue::String) | |
| 342 return false; | |
| 343 if (!parseGridTemplateAreasRow(currentValue->string, gridAreaMap, rowCou
nt, columnCount)) | |
| 344 return false; | |
| 345 m_valueList->next(); | |
| 346 ++rowCount; | |
| 347 | |
| 348 // Handle template-rows's track-size. | |
| 349 if (m_valueList->current() && m_valueList->current()->m_unit != CSSParse
rValue::Operator && m_valueList->current()->m_unit != CSSParserValue::String) { | |
| 350 RawPtr<CSSValue> value = parseGridTrackSize(*m_valueList); | |
| 351 if (!value) | |
| 352 return false; | |
| 353 templateRows->append(value); | |
| 354 } else { | |
| 355 templateRows->append(cssValuePool().createIdentifierValue(CSSValueAu
to)); | |
| 356 } | |
| 357 | |
| 358 // This will handle the trailing/leading <custom-ident>* in the grammar. | |
| 359 if (!parseGridLineNames(*m_valueList, *templateRows)) | |
| 360 return false; | |
| 361 trailingIdentWasAdded = templateRows->item(templateRows->length() - 1)->
isGridLineNamesValue(); | |
| 362 } | |
| 363 | |
| 364 RawPtr<CSSValue> columnsValue = nullptr; | |
| 365 if (m_valueList->current()) { | |
| 366 ASSERT(isForwardSlashOperator(m_valueList->current())); | |
| 367 columnsValue = parseGridTemplateColumns(important); | |
| 368 if (!columnsValue) | |
| 369 return false; | |
| 370 // The template-columns <track-list> can't be 'none'. | |
| 371 if (columnsValue->isPrimitiveValue() && toCSSPrimitiveValue(*columnsValu
e).getValueID() == CSSValueNone) | |
| 372 return false; | |
| 373 } | |
| 374 | |
| 375 addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important); | |
| 376 addProperty(CSSPropertyGridTemplateColumns, columnsValue ? columnsValue.rele
ase() : cssValuePool().createIdentifierValue(CSSValueNone), important); | |
| 377 | |
| 378 RawPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaM
ap, rowCount, columnCount); | |
| 379 addProperty(CSSPropertyGridTemplateAreas, templateAreas.release(), important
); | |
| 380 | |
| 381 return true; | |
| 382 } | |
| 383 | |
| 384 | |
| 385 bool CSSPropertyParser::parseGridTemplateShorthand(bool important) | |
| 386 { | |
| 387 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | |
| 388 | |
| 389 ShorthandScope scope(this, CSSPropertyGridTemplate); | |
| 390 ASSERT(gridTemplateShorthand().length() == 3); | |
| 391 | |
| 392 // At least "none" must be defined. | |
| 393 if (!m_valueList->current()) | |
| 394 return false; | |
| 395 | |
| 396 bool firstValueIsNone = m_valueList->current()->id == CSSValueNone; | |
| 397 | |
| 398 // 1- 'none' case. | |
| 399 if (firstValueIsNone && !m_valueList->next()) { | |
| 400 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentif
ierValue(CSSValueNone), important); | |
| 401 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifier
Value(CSSValueNone), important); | |
| 402 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); | |
| 403 return true; | |
| 404 } | |
| 405 | |
| 406 // 2- <grid-template-rows> / <grid-template-columns> | |
| 407 RawPtr<CSSValue> rowsValue = nullptr; | |
| 408 if (firstValueIsNone) { | |
| 409 rowsValue = cssValuePool().createIdentifierValue(CSSValueNone); | |
| 410 } else { | |
| 411 rowsValue = parseGridTrackList(); | |
| 412 } | |
| 413 | |
| 414 if (rowsValue) { | |
| 415 RawPtr<CSSValue> columnsValue = parseGridTemplateColumns(important); | |
| 416 if (!columnsValue) | |
| 417 return false; | |
| 418 | |
| 419 addProperty(CSSPropertyGridTemplateRows, rowsValue.release(), important)
; | |
| 420 addProperty(CSSPropertyGridTemplateColumns, columnsValue.release(), impo
rtant); | |
| 421 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); | |
| 422 return true; | |
| 423 } | |
| 424 | |
| 425 // 3- [<line-names>? <string> <track-size>? <line-names>? ]+ syntax. | |
| 426 // It requires to rewind parsing due to previous syntax failures. | |
| 427 m_valueList->setCurrentIndex(0); | |
| 428 return parseGridTemplateRowsAndAreasAndColumns(important); | |
| 429 } | |
| 430 | |
| 431 bool CSSPropertyParser::parseGridShorthand(bool important) | 288 bool CSSPropertyParser::parseGridShorthand(bool important) |
| 432 { | 289 { |
| 433 ShorthandScope scope(this, CSSPropertyGrid); | 290 ShorthandScope scope(this, CSSPropertyGrid); |
| 434 ASSERT(shorthandForProperty(CSSPropertyGrid).length() == 8); | 291 ASSERT(shorthandForProperty(CSSPropertyGrid).length() == 8); |
| 435 | 292 |
| 436 // 1- <grid-template> | 293 // 1- <grid-template> |
| 437 if (parseGridTemplateShorthand(important)) { | 294 if (consumeGridTemplateShorthand(important)) { |
| 438 // It can only be specified the explicit or the implicit grid properties
in a single grid declaration. | 295 // It can only be specified the explicit or the implicit grid properties
in a single grid declaration. |
| 439 // The sub-properties not specified are set to their initial value, as n
ormal for shorthands. | 296 // The sub-properties not specified are set to their initial value, as n
ormal for shorthands. |
| 440 addProperty(CSSPropertyGridAutoFlow, cssValuePool().createImplicitInitia
lValue(), important); | 297 addProperty(CSSPropertyGridAutoFlow, cssValuePool().createImplicitInitia
lValue(), important); |
| 441 addProperty(CSSPropertyGridAutoColumns, cssValuePool().createImplicitIni
tialValue(), important); | 298 addProperty(CSSPropertyGridAutoColumns, cssValuePool().createImplicitIni
tialValue(), important); |
| 442 addProperty(CSSPropertyGridAutoRows, cssValuePool().createImplicitInitia
lValue(), important); | 299 addProperty(CSSPropertyGridAutoRows, cssValuePool().createImplicitInitia
lValue(), important); |
| 443 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitIniti
alValue(), important); | 300 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitIniti
alValue(), important); |
| 444 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialV
alue(), important); | 301 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialV
alue(), important); |
| 445 return true; | 302 return true; |
| 446 } | 303 } |
| 447 | 304 |
| 448 // Need to rewind parsing to explore the alternative syntax of this shorthan
d. | |
| 449 m_valueList->setCurrentIndex(0); | |
| 450 | |
| 451 // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ] | 305 // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ] |
| 452 if (!legacyParseAndApplyValue(CSSPropertyGridAutoFlow, important)) | 306 if (!legacyParseAndApplyValue(CSSPropertyGridAutoFlow, important)) |
| 453 return false; | 307 return false; |
| 454 | 308 |
| 455 RawPtr<CSSValue> autoColumnsValue = nullptr; | 309 RawPtr<CSSValue> autoColumnsValue = nullptr; |
| 456 RawPtr<CSSValue> autoRowsValue = nullptr; | 310 RawPtr<CSSValue> autoRowsValue = nullptr; |
| 457 | 311 |
| 458 if (m_valueList->current()) { | 312 if (m_valueList->current()) { |
| 459 autoRowsValue = parseGridTrackSize(*m_valueList); | 313 autoRowsValue = parseGridTrackSize(*m_valueList); |
| 460 if (!autoRowsValue) | 314 if (!autoRowsValue) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 485 // The sub-properties not specified are set to their initial value, as norma
l for shorthands. | 339 // The sub-properties not specified are set to their initial value, as norma
l for shorthands. |
| 486 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createImplicitIni
tialValue(), important); | 340 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createImplicitIni
tialValue(), important); |
| 487 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createImplicitInitia
lValue(), important); | 341 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createImplicitInitia
lValue(), important); |
| 488 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createImplicitIniti
alValue(), important); | 342 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createImplicitIniti
alValue(), important); |
| 489 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitInitialVa
lue(), important); | 343 addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitInitialVa
lue(), important); |
| 490 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialValue
(), important); | 344 addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialValue
(), important); |
| 491 | 345 |
| 492 return true; | 346 return true; |
| 493 } | 347 } |
| 494 | 348 |
| 495 static inline bool isClosingBracket(const CSSParserValue& value) | |
| 496 { | |
| 497 return value.m_unit == CSSParserValue::Operator && value.iValue == ']'; | |
| 498 } | |
| 499 | |
| 500 bool CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSVal
ueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames) | |
| 501 { | |
| 502 if (!inputList.current() || inputList.current()->m_unit != CSSParserValue::O
perator || inputList.current()->iValue != '[') | |
| 503 return true; | |
| 504 | |
| 505 // Skip '[' | |
| 506 inputList.next(); | |
| 507 | |
| 508 RawPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames
; | |
| 509 if (!lineNames) | |
| 510 lineNames = CSSGridLineNamesValue::create(); | |
| 511 | |
| 512 while (CSSParserValue* identValue = inputList.current()) { | |
| 513 if (isClosingBracket(*identValue)) | |
| 514 break; | |
| 515 | |
| 516 if (!isValidCustomIdentForGridPositions(*identValue)) | |
| 517 return false; | |
| 518 | |
| 519 RawPtr<CSSCustomIdentValue> lineName = createPrimitiveCustomIdentValue(i
dentValue); | |
| 520 lineNames->append(lineName.release()); | |
| 521 inputList.next(); | |
| 522 } | |
| 523 | |
| 524 if (!inputList.current() || !isClosingBracket(*inputList.current())) | |
| 525 return false; | |
| 526 | |
| 527 if (!previousNamedAreaTrailingLineNames) | |
| 528 valueList.append(lineNames.release()); | |
| 529 | |
| 530 // Consume ']' | |
| 531 inputList.next(); | |
| 532 return true; | |
| 533 } | |
| 534 | |
| 535 bool allTracksAreFixedSized(CSSValueList& valueList) | |
| 536 { | |
| 537 for (auto value : valueList) { | |
| 538 if (value->isGridLineNamesValue()) | |
| 539 continue; | |
| 540 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax
( <fixed-breadth>, <track-breadth> ) | |
| 541 if (value->isGridAutoRepeatValue()) { | |
| 542 if (!allTracksAreFixedSized(toCSSValueList(*value))) | |
| 543 return false; | |
| 544 continue; | |
| 545 } | |
| 546 ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFu
nctionValue(*value).item(0))); | |
| 547 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() | |
| 548 ? toCSSPrimitiveValue(*value) | |
| 549 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); | |
| 550 CSSValueID valueID = primitiveValue.getValueID(); | |
| 551 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va
lueID == CSSValueAuto || primitiveValue.isFlex()) | |
| 552 return false; | |
| 553 } | |
| 554 return true; | |
| 555 } | |
| 556 | |
| 557 RawPtr<CSSValue> CSSPropertyParser::parseGridTrackList() | |
| 558 { | |
| 559 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | |
| 560 | |
| 561 CSSParserValue* value = m_valueList->current(); | |
| 562 if (value->id == CSSValueNone) { | |
| 563 m_valueList->next(); | |
| 564 return cssValuePool().createIdentifierValue(CSSValueNone); | |
| 565 } | |
| 566 | |
| 567 RawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); | |
| 568 // Handle leading <custom-ident>*. | |
| 569 if (!parseGridLineNames(*m_valueList, *values)) | |
| 570 return nullptr; | |
| 571 | |
| 572 bool seenTrackSizeOrRepeatFunction = false; | |
| 573 bool seenAutoRepeat = false; | |
| 574 while (CSSParserValue* currentValue = m_valueList->current()) { | |
| 575 if (isForwardSlashOperator(currentValue)) | |
| 576 break; | |
| 577 if (currentValue->m_unit == CSSParserValue::Function && currentValue->fu
nction->id == CSSValueRepeat) { | |
| 578 bool isAutoRepeat; | |
| 579 if (!parseGridTrackRepeatFunction(*values, isAutoRepeat)) | |
| 580 return nullptr; | |
| 581 if (isAutoRepeat && seenAutoRepeat) | |
| 582 return nullptr; | |
| 583 seenTrackSizeOrRepeatFunction = true; | |
| 584 seenAutoRepeat = seenAutoRepeat || isAutoRepeat; | |
| 585 } else { | |
| 586 RawPtr<CSSValue> value = parseGridTrackSize(*m_valueList, seenAutoRe
peat ? FixedSizeOnly : AllowAll); | |
| 587 if (!value) | |
| 588 return nullptr; | |
| 589 values->append(value); | |
| 590 seenTrackSizeOrRepeatFunction = true; | |
| 591 } | |
| 592 // This will handle the trailing <custom-ident>* in the grammar. | |
| 593 if (!parseGridLineNames(*m_valueList, *values)) | |
| 594 return nullptr; | |
| 595 } | |
| 596 | |
| 597 // We should have found a <track-size> or else it is not a valid <track-list
> | |
| 598 if (!seenTrackSizeOrRepeatFunction) | |
| 599 return nullptr; | |
| 600 | |
| 601 // <auto-repeat> requires definite minimum track sizes in order to compute t
he number of repetitions. | |
| 602 // The above while loop detects those appearances after the <auto-repeat> bu
t not the ones before. | |
| 603 if (seenAutoRepeat && !allTracksAreFixedSized(*values)) | |
| 604 return nullptr; | |
| 605 | |
| 606 return values; | |
| 607 } | |
| 608 | |
| 609 bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list, bool& i
sAutoRepeat) | |
| 610 { | |
| 611 CSSParserValueList* arguments = m_valueList->current()->function->args.get()
; | |
| 612 if (!arguments || arguments->size() < 3 || !isComma(arguments->valueAt(1))) | |
| 613 return false; | |
| 614 | |
| 615 CSSParserValue* currentValue = arguments->valueAt(0); | |
| 616 isAutoRepeat = currentValue->id == CSSValueAutoFill || currentValue->id == C
SSValueAutoFit; | |
| 617 if (!isAutoRepeat && !validUnit(currentValue, FPositiveInteger)) | |
| 618 return false; | |
| 619 | |
| 620 // The number of repetitions for <auto-repeat> is not important at parsing l
evel | |
| 621 // because it will be computed later, let's set it to 1. | |
| 622 size_t repetitions = isAutoRepeat ? 1 : clampTo<size_t>(currentValue->fValue
, 0, kGridMaxTracks); | |
| 623 | |
| 624 RawPtr<CSSValueList> repeatedValues = isAutoRepeat ? CSSGridAutoRepeatValue:
:create(currentValue->id) : CSSValueList::createSpaceSeparated(); | |
| 625 arguments->next(); // Skip the repetition count. | |
| 626 arguments->next(); // Skip the comma. | |
| 627 | |
| 628 // Handle leading <custom-ident>*. | |
| 629 if (!parseGridLineNames(*arguments, *repeatedValues)) | |
| 630 return false; | |
| 631 | |
| 632 size_t numberOfTracks = 0; | |
| 633 TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll; | |
| 634 while (arguments->current()) { | |
| 635 if (isAutoRepeat && numberOfTracks) | |
| 636 return false; | |
| 637 | |
| 638 RawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments, restriction)
; | |
| 639 if (!trackSize) | |
| 640 return false; | |
| 641 | |
| 642 repeatedValues->append(trackSize); | |
| 643 ++numberOfTracks; | |
| 644 | |
| 645 // This takes care of any trailing <custom-ident>* in the grammar. | |
| 646 if (!parseGridLineNames(*arguments, *repeatedValues)) | |
| 647 return false; | |
| 648 } | |
| 649 | |
| 650 // We should have found at least one <track-size> or else it is not a valid
<track-list>. | |
| 651 if (!numberOfTracks) | |
| 652 return false; | |
| 653 | |
| 654 if (isAutoRepeat) { | |
| 655 list.append(repeatedValues.release()); | |
| 656 } else { | |
| 657 // We clamp the number of repetitions to a multiple of the repeat() trac
k list's size, while staying below the max | |
| 658 // grid size. | |
| 659 repetitions = std::min(repetitions, kGridMaxTracks / numberOfTracks); | |
| 660 | |
| 661 for (size_t i = 0; i < repetitions; ++i) { | |
| 662 for (size_t j = 0; j < repeatedValues->length(); ++j) | |
| 663 list.append(repeatedValues->item(j)); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 // parseGridTrackSize iterated over the repeat arguments, move to the next v
alue. | |
| 668 m_valueList->next(); | |
| 669 return true; | |
| 670 } | |
| 671 | |
| 672 | |
| 673 RawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& input
List, TrackSizeRestriction restriction) | 349 RawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& input
List, TrackSizeRestriction restriction) |
| 674 { | 350 { |
| 675 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 351 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
| 676 | 352 |
| 677 CSSParserValue* currentValue = inputList.current(); | 353 CSSParserValue* currentValue = inputList.current(); |
| 678 inputList.next(); | 354 inputList.next(); |
| 679 | 355 |
| 680 if (currentValue->id == CSSValueAuto) | 356 if (currentValue->id == CSSValueAuto) |
| 681 return restriction == AllowAll ? cssValuePool().createIdentifierValue(CS
SValueAuto) : nullptr; | 357 return restriction == AllowAll ? cssValuePool().createIdentifierValue(CS
SValueAuto) : nullptr; |
| 682 | 358 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 | 396 |
| 721 return cssValuePool().createValue(flexValue, CSSPrimitiveValue::UnitType
::Fraction); | 397 return cssValuePool().createValue(flexValue, CSSPrimitiveValue::UnitType
::Fraction); |
| 722 } | 398 } |
| 723 | 399 |
| 724 if (!validUnit(currentValue, FNonNeg | FLength | FPercent)) | 400 if (!validUnit(currentValue, FNonNeg | FLength | FPercent)) |
| 725 return nullptr; | 401 return nullptr; |
| 726 | 402 |
| 727 return createPrimitiveNumericValue(currentValue); | 403 return createPrimitiveNumericValue(currentValue); |
| 728 } | 404 } |
| 729 | 405 |
| 730 static Vector<String> parseGridTemplateAreasColumnNames(const String& gridRowNam
es) | |
| 731 { | |
| 732 ASSERT(!gridRowNames.isEmpty()); | |
| 733 Vector<String> columnNames; | |
| 734 // Using StringImpl to avoid checks and indirection in every call to String:
:operator[]. | |
| 735 StringImpl& text = *gridRowNames.impl(); | |
| 736 | |
| 737 StringBuilder areaName; | |
| 738 for (unsigned i = 0; i < text.length(); ++i) { | |
| 739 if (text[i] == ' ') { | |
| 740 if (!areaName.isEmpty()) { | |
| 741 columnNames.append(areaName.toString()); | |
| 742 areaName.clear(); | |
| 743 } | |
| 744 continue; | |
| 745 } | |
| 746 if (text[i] == '.') { | |
| 747 if (areaName == ".") | |
| 748 continue; | |
| 749 if (!areaName.isEmpty()) { | |
| 750 columnNames.append(areaName.toString()); | |
| 751 areaName.clear(); | |
| 752 } | |
| 753 } else { | |
| 754 if (areaName == ".") { | |
| 755 columnNames.append(areaName.toString()); | |
| 756 areaName.clear(); | |
| 757 } | |
| 758 } | |
| 759 | |
| 760 areaName.append(text[i]); | |
| 761 } | |
| 762 | |
| 763 if (!areaName.isEmpty()) | |
| 764 columnNames.append(areaName.toString()); | |
| 765 | |
| 766 return columnNames; | |
| 767 } | |
| 768 | |
| 769 bool parseGridTemplateAreasRow(const String& gridRowNames, NamedGridAreaMap& gri
dAreaMap, const size_t rowCount, size_t& columnCount) | |
| 770 { | |
| 771 if (gridRowNames.isEmpty() || gridRowNames.containsOnlyWhitespace()) | |
| 772 return false; | |
| 773 | |
| 774 Vector<String> columnNames = parseGridTemplateAreasColumnNames(gridRowNames)
; | |
| 775 if (!columnCount) { | |
| 776 columnCount = columnNames.size(); | |
| 777 ASSERT(columnCount); | |
| 778 } else if (columnCount != columnNames.size()) { | |
| 779 // The declaration is invalid is all the rows don't have the number of c
olumns. | |
| 780 return false; | |
| 781 } | |
| 782 | |
| 783 for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { | |
| 784 const String& gridAreaName = columnNames[currentCol]; | |
| 785 | |
| 786 // Unamed areas are always valid (we consider them to be 1x1). | |
| 787 if (gridAreaName == ".") | |
| 788 continue; | |
| 789 | |
| 790 // We handle several grid areas with the same name at once to simplify t
he validation code. | |
| 791 size_t lookAheadCol; | |
| 792 for (lookAheadCol = currentCol + 1; lookAheadCol < columnCount; ++lookAh
eadCol) { | |
| 793 if (columnNames[lookAheadCol] != gridAreaName) | |
| 794 break; | |
| 795 } | |
| 796 | |
| 797 NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName); | |
| 798 if (gridAreaIt == gridAreaMap.end()) { | |
| 799 gridAreaMap.add(gridAreaName, GridArea(GridSpan::translatedDefiniteG
ridSpan(rowCount, rowCount + 1), GridSpan::translatedDefiniteGridSpan(currentCol
, lookAheadCol))); | |
| 800 } else { | |
| 801 GridArea& gridArea = gridAreaIt->value; | |
| 802 | |
| 803 // The following checks test that the grid area is a single filled-i
n rectangle. | |
| 804 // 1. The new row is adjacent to the previously parsed row. | |
| 805 if (rowCount != gridArea.rows.endLine()) | |
| 806 return false; | |
| 807 | |
| 808 // 2. The new area starts at the same position as the previously par
sed area. | |
| 809 if (currentCol != gridArea.columns.startLine()) | |
| 810 return false; | |
| 811 | |
| 812 // 3. The new area ends at the same position as the previously parse
d area. | |
| 813 if (lookAheadCol != gridArea.columns.endLine()) | |
| 814 return false; | |
| 815 | |
| 816 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); | |
| 817 } | |
| 818 currentCol = lookAheadCol - 1; | |
| 819 } | |
| 820 | |
| 821 return true; | |
| 822 } | |
| 823 | |
| 824 RawPtr<CSSValue> CSSPropertyParser::parseGridAutoFlow(CSSParserValueList& list) | 406 RawPtr<CSSValue> CSSPropertyParser::parseGridAutoFlow(CSSParserValueList& list) |
| 825 { | 407 { |
| 826 // [ row | column ] || dense | 408 // [ row | column ] || dense |
| 827 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 409 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
| 828 | 410 |
| 829 CSSParserValue* value = list.current(); | 411 CSSParserValue* value = list.current(); |
| 830 if (!value) | 412 if (!value) |
| 831 return nullptr; | 413 return nullptr; |
| 832 | 414 |
| 833 RawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); | 415 RawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 ASSERT(!m_parsedCalculation); | 452 ASSERT(!m_parsedCalculation); |
| 871 m_parsedCalculation = CSSCalcValue::create(args, range); | 453 m_parsedCalculation = CSSCalcValue::create(args, range); |
| 872 | 454 |
| 873 if (!m_parsedCalculation) | 455 if (!m_parsedCalculation) |
| 874 return false; | 456 return false; |
| 875 | 457 |
| 876 return true; | 458 return true; |
| 877 } | 459 } |
| 878 | 460 |
| 879 } // namespace blink | 461 } // namespace blink |
| OLD | NEW |