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 |