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 "config.h" | 5 #include "config.h" |
6 #include "core/css/parser/CSSPropertyParser.h" | 6 #include "core/css/parser/CSSPropertyParser.h" |
7 | 7 |
8 #include "core/StylePropertyShorthand.h" | 8 #include "core/StylePropertyShorthand.h" |
9 #include "core/css/CSSCalculationValue.h" | 9 #include "core/css/CSSCalculationValue.h" |
10 #include "core/css/CSSCrossfadeValue.h" | 10 #include "core/css/CSSCrossfadeValue.h" |
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 | 825 |
826 static PassRefPtrWillBeRawPtr<CSSValue> consumePosition(CSSParserTokenRange& ran ge, CSSParserMode cssParserMode, UnitlessQuirk unitless) | 826 static PassRefPtrWillBeRawPtr<CSSValue> consumePosition(CSSParserTokenRange& ran ge, CSSParserMode cssParserMode, UnitlessQuirk unitless) |
827 { | 827 { |
828 RefPtrWillBeRawPtr<CSSValue> resultX = nullptr; | 828 RefPtrWillBeRawPtr<CSSValue> resultX = nullptr; |
829 RefPtrWillBeRawPtr<CSSValue> resultY = nullptr; | 829 RefPtrWillBeRawPtr<CSSValue> resultY = nullptr; |
830 if (consumePosition(range, cssParserMode, unitless, resultX, resultY)) | 830 if (consumePosition(range, cssParserMode, unitless, resultX, resultY)) |
831 return CSSValuePair::create(resultX.release(), resultY.release(), CSSVal uePair::KeepIdenticalValues); | 831 return CSSValuePair::create(resultX.release(), resultY.release(), CSSVal uePair::KeepIdenticalValues); |
832 return nullptr; | 832 return nullptr; |
833 } | 833 } |
834 | 834 |
835 static bool consumeTransformOrigin(CSSParserTokenRange& range, CSSParserMode css ParserMode, UnitlessQuirk unitless, RefPtrWillBeRawPtr<CSSValue>& resultX, RefPt rWillBeRawPtr<CSSValue>& resultY) | 835 static bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserM ode cssParserMode, UnitlessQuirk unitless, RefPtrWillBeRawPtr<CSSValue>& resultX , RefPtrWillBeRawPtr<CSSValue>& resultY) |
836 { | 836 { |
837 RefPtrWillBeRawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(rang e, cssParserMode, unitless); | 837 RefPtrWillBeRawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(rang e, cssParserMode, unitless); |
838 if (!value1) | 838 if (!value1) |
839 return false; | 839 return false; |
840 RefPtrWillBeRawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(rang e, cssParserMode, unitless); | 840 RefPtrWillBeRawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(rang e, cssParserMode, unitless); |
841 if (!value2) { | 841 if (!value2) { |
842 positionFromOneValue(value1.release(), resultX, resultY); | 842 positionFromOneValue(value1.release(), resultX, resultY); |
843 return true; | 843 return true; |
844 } | 844 } |
845 return positionFromTwoValues(value1.release(), value2.release(), resultX, re sultY); | 845 return positionFromTwoValues(value1.release(), value2.release(), resultX, re sultY); |
846 } | 846 } |
847 | 847 |
848 static PassRefPtrWillBeRawPtr<CSSValueList> consumeTransformOrigin(CSSParserToke nRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless) | 848 static PassRefPtrWillBeRawPtr<CSSValueList> consumeTransformOrigin(CSSParserToke nRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless) |
849 { | 849 { |
850 RefPtrWillBeRawPtr<CSSValue> resultX = nullptr; | 850 RefPtrWillBeRawPtr<CSSValue> resultX = nullptr; |
851 RefPtrWillBeRawPtr<CSSValue> resultY = nullptr; | 851 RefPtrWillBeRawPtr<CSSValue> resultY = nullptr; |
852 if (consumeTransformOrigin(range, cssParserMode, unitless, resultX, resultY) ) { | 852 if (consumeOneOrTwoValuedPosition(range, cssParserMode, unitless, resultX, r esultY)) { |
853 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparat ed(); | 853 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparat ed(); |
854 list->append(resultX.release()); | 854 list->append(resultX.release()); |
855 list->append(resultY.release()); | 855 list->append(resultY.release()); |
856 RefPtrWillBeRawPtr<CSSValue> resultZ = consumeLength(range, cssParserMod e, ValueRangeAll); | 856 RefPtrWillBeRawPtr<CSSValue> resultZ = consumeLength(range, cssParserMod e, ValueRangeAll); |
857 if (!resultZ) | 857 if (!resultZ) |
858 resultZ = cssValuePool().createValue(0, CSSPrimitiveValue::UnitType: :Pixels); | 858 resultZ = cssValuePool().createValue(0, CSSPrimitiveValue::UnitType: :Pixels); |
859 list->append(resultZ.release()); | 859 list->append(resultZ.release()); |
860 return list.release(); | 860 return list.release(); |
861 } | 861 } |
862 return nullptr; | 862 return nullptr; |
(...skipping 1536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2399 cursorType = consumeIdent(range); | 2399 cursorType = consumeIdent(range); |
2400 } | 2400 } |
2401 | 2401 |
2402 if (!list) | 2402 if (!list) |
2403 return cursorType.release(); | 2403 return cursorType.release(); |
2404 if (cursorType) | 2404 if (cursorType) |
2405 list->append(cursorType.release()); | 2405 list->append(cursorType.release()); |
2406 return list.release(); | 2406 return list.release(); |
2407 } | 2407 } |
2408 | 2408 |
2409 // This should go away once we drop support for -webkit-gradient | |
2410 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeDeprecatedGradientPoint( CSSParserTokenRange& args, bool horizontal) | |
2411 { | |
2412 if (args.peek().type() == IdentToken) { | |
2413 if ((horizontal && consumeIdent<CSSValueLeft>(args)) || (!horizontal && consumeIdent<CSSValueTop>(args))) | |
2414 return cssValuePool().createValue(0., CSSPrimitiveValue::UnitType::P ercentage); | |
2415 if ((horizontal && consumeIdent<CSSValueRight>(args)) || (!horizontal && consumeIdent<CSSValueBottom>(args))) | |
2416 return cssValuePool().createValue(100., CSSPrimitiveValue::UnitType: :Percentage); | |
2417 if (consumeIdent<CSSValueCenter>(args)) | |
2418 return cssValuePool().createValue(50., CSSPrimitiveValue::UnitType:: Percentage); | |
2419 return nullptr; | |
2420 } | |
2421 RefPtrWillBeRawPtr<CSSPrimitiveValue> result = consumePercent(args, ValueRan geAll); | |
2422 if (!result) | |
2423 result = consumeNumber(args, ValueRangeAll); | |
2424 return result; | |
2425 } | |
2426 | |
2427 // Used to parse colors for -webkit-gradient(...). | |
2428 static PassRefPtrWillBeRawPtr<CSSValue> consumeDeprecatedGradientStopColor(CSSPa rserTokenRange& args, CSSParserMode cssParserMode) | |
2429 { | |
2430 if (args.peek().id() == CSSValueCurrentcolor) | |
2431 return nullptr; | |
2432 return consumeColor(args, cssParserMode); | |
2433 } | |
2434 | |
2435 static bool consumeDeprecatedGradientColorStop(CSSParserTokenRange& range, CSSGr adientColorStop& stop, CSSParserMode cssParserMode) | |
2436 { | |
2437 CSSValueID id = range.peek().functionId(); | |
2438 if (id != CSSValueFrom && id != CSSValueTo && id != CSSValueColorStop) | |
2439 return false; | |
2440 | |
2441 CSSParserTokenRange args = consumeFunction(range); | |
2442 const CSSParserToken& arg = args.consumeIncludingWhitespace(); | |
Timothy Loh
2015/12/14 23:30:40
Probably should be in the else branch, since we do
| |
2443 double position; | |
2444 if (id == CSSValueFrom || id == CSSValueTo) { | |
2445 position = (id == CSSValueFrom) ? 0 : 1; | |
2446 } else { | |
2447 ASSERT(id == CSSValueColorStop); | |
2448 if (arg.type() == PercentageToken) | |
2449 position = arg.numericValue() / 100.0; | |
2450 else if (arg.type() == NumberToken) | |
2451 position = arg.numericValue(); | |
2452 else | |
2453 return false; | |
2454 | |
2455 if (!consumeCommaIncludingWhitespace(args)) | |
2456 return false; | |
2457 } | |
2458 | |
2459 stop.m_position = cssValuePool().createValue(position, CSSPrimitiveValue::Un itType::Number); | |
2460 stop.m_color = consumeDeprecatedGradientStopColor(args, cssParserMode); | |
2461 return stop.m_color && args.atEnd(); | |
2462 } | |
2463 | |
2464 static PassRefPtrWillBeRawPtr<CSSValue> consumeDeprecatedGradient(CSSParserToken Range& args, CSSParserMode cssParserMode) | |
2465 { | |
2466 RefPtrWillBeRawPtr<CSSGradientValue> result = nullptr; | |
2467 CSSValueID id = args.consumeIncludingWhitespace().id(); | |
2468 bool isDeprecatedRadialGradient = (id == CSSValueRadial); | |
2469 if (isDeprecatedRadialGradient) | |
2470 result = CSSRadialGradientValue::create(NonRepeating, CSSDeprecatedRadia lGradient); | |
2471 else if (id == CSSValueLinear) | |
2472 result = CSSLinearGradientValue::create(NonRepeating, CSSDeprecatedLinea rGradient); | |
2473 if (!result || !consumeCommaIncludingWhitespace(args)) | |
2474 return nullptr; | |
2475 | |
2476 RefPtrWillBeRawPtr<CSSPrimitiveValue> point = consumeDeprecatedGradientPoint (args, true); | |
2477 if (!point) | |
2478 return nullptr; | |
2479 result->setFirstX(point.release()); | |
2480 point = consumeDeprecatedGradientPoint(args, false); | |
2481 if (!point) | |
2482 return nullptr; | |
2483 result->setFirstY(point.release()); | |
2484 | |
2485 if (!consumeCommaIncludingWhitespace(args)) | |
2486 return nullptr; | |
2487 | |
2488 // For radial gradients only, we now expect a numeric radius. | |
2489 if (isDeprecatedRadialGradient) { | |
2490 RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = consumeNumber(args, Value RangeAll); | |
2491 if (!radius || !consumeCommaIncludingWhitespace(args)) | |
2492 return nullptr; | |
2493 toCSSRadialGradientValue(result.get())->setFirstRadius(radius.release()) ; | |
2494 } | |
2495 | |
2496 point = consumeDeprecatedGradientPoint(args, true); | |
2497 if (!point) | |
2498 return nullptr; | |
2499 result->setSecondX(point.release()); | |
2500 point = consumeDeprecatedGradientPoint(args, false); | |
2501 if (!point) | |
2502 return nullptr; | |
2503 result->setSecondY(point.release()); | |
2504 | |
2505 // For radial gradients only, we now expect the second radius. | |
2506 if (isDeprecatedRadialGradient) { | |
2507 if (!consumeCommaIncludingWhitespace(args)) | |
2508 return nullptr; | |
2509 RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = consumeNumber(args, Value RangeAll); | |
2510 if (!radius) | |
2511 return nullptr; | |
2512 toCSSRadialGradientValue(result.get())->setSecondRadius(radius.release() ); | |
2513 } | |
2514 | |
2515 CSSGradientColorStop stop; | |
2516 while (consumeCommaIncludingWhitespace(args)) { | |
2517 if (!consumeDeprecatedGradientColorStop(args, stop, cssParserMode)) | |
2518 return nullptr; | |
2519 result->addStop(stop); | |
2520 } | |
2521 | |
2522 return result.release(); | |
2523 } | |
2524 | |
2409 static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue* gradient) | 2525 static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue* gradient) |
2410 { | 2526 { |
2411 bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || g radient->gradientType() == CSSRadialGradient; | 2527 bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || g radient->gradientType() == CSSRadialGradient; |
2412 | 2528 |
2413 // The first color stop cannot be a color hint. | 2529 // The first color stop cannot be a color hint. |
2414 bool previousStopWasColorHint = true; | 2530 bool previousStopWasColorHint = true; |
2415 do { | 2531 do { |
2416 CSSGradientColorStop stop; | 2532 CSSGradientColorStop stop; |
2417 stop.m_color = consumeColor(range, cssParserMode); | 2533 stop.m_color = consumeColor(range, cssParserMode); |
2418 // Two hints in a row are not allowed. | 2534 // Two hints in a row are not allowed. |
2419 if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint)) | 2535 if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint)) |
2420 return false; | 2536 return false; |
2421 previousStopWasColorHint = !stop.m_color; | 2537 previousStopWasColorHint = !stop.m_color; |
2422 stop.m_position = consumeLengthOrPercent(range, cssParserMode, ValueRang eAll); | 2538 stop.m_position = consumeLengthOrPercent(range, cssParserMode, ValueRang eAll); |
2423 if (!stop.m_color && !stop.m_position) | 2539 if (!stop.m_color && !stop.m_position) |
2424 return false; | 2540 return false; |
2425 gradient->addStop(stop); | 2541 gradient->addStop(stop); |
2426 } while (consumeCommaIncludingWhitespace(range)); | 2542 } while (consumeCommaIncludingWhitespace(range)); |
2427 | 2543 |
2428 // The last color stop cannot be a color hint. | 2544 // The last color stop cannot be a color hint. |
2429 if (previousStopWasColorHint) | 2545 if (previousStopWasColorHint) |
2430 return false; | 2546 return false; |
2431 | 2547 |
2432 // Must have 2 or more stops to be valid. | 2548 // Must have 2 or more stops to be valid. |
2433 return gradient->stopCount() >= 2; | 2549 return gradient->stopCount() >= 2; |
2434 } | 2550 } |
2435 | 2551 |
2552 static PassRefPtrWillBeRawPtr<CSSValue> consumeDeprecatedRadialGradient(CSSParse rTokenRange& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating) | |
2553 { | |
2554 RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue:: create(repeating, CSSPrefixedRadialGradient); | |
2555 RefPtrWillBeRawPtr<CSSValue> centerX = nullptr; | |
2556 RefPtrWillBeRawPtr<CSSValue> centerY = nullptr; | |
2557 consumeOneOrTwoValuedPosition(args, cssParserMode, UnitlessQuirk::Forbid, ce nterX, centerY); | |
2558 if ((centerX || centerY) && !consumeCommaIncludingWhitespace(args)) | |
2559 return nullptr; | |
2560 | |
2561 result->setFirstX(toCSSPrimitiveValue(centerX.get())); | |
2562 result->setSecondX(toCSSPrimitiveValue(centerX.get())); | |
2563 result->setFirstY(toCSSPrimitiveValue(centerY.get())); | |
2564 result->setSecondY(toCSSPrimitiveValue(centerY.get())); | |
2565 | |
2566 RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = consumeIdent<CSSValueCircle, C SSValueEllipse>(args); | |
2567 RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeKeyword = consumeIdent<CSSValueClo sestSide, CSSValueClosestCorner, CSSValueFarthestSide, CSSValueFarthestCorner, C SSValueContain, CSSValueCover>(args); | |
2568 if (!shape) | |
2569 shape = consumeIdent<CSSValueCircle, CSSValueEllipse>(args); | |
2570 result->setShape(shape); | |
2571 result->setSizingBehavior(sizeKeyword); | |
2572 | |
2573 // Or, two lengths or percentages | |
2574 if (!shape && !sizeKeyword) { | |
2575 RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr; | |
2576 RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr; | |
2577 if ((horizontalSize = consumeLengthOrPercent(args, cssParserMode, ValueR angeAll))) { | |
2578 verticalSize = consumeLengthOrPercent(args, cssParserMode, ValueRang eAll); | |
2579 if (!verticalSize) | |
2580 return nullptr; | |
2581 consumeCommaIncludingWhitespace(args); | |
2582 result->setEndHorizontalSize(horizontalSize); | |
2583 result->setEndVerticalSize(verticalSize); | |
2584 } | |
2585 } else { | |
2586 consumeCommaIncludingWhitespace(args); | |
2587 } | |
2588 if (!consumeGradientColorStops(args, cssParserMode, result.get())) | |
2589 return nullptr; | |
2590 | |
2591 return result.release(); | |
2592 } | |
2593 | |
2436 static PassRefPtrWillBeRawPtr<CSSValue> consumeRadialGradient(CSSParserTokenRang e& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating) | 2594 static PassRefPtrWillBeRawPtr<CSSValue> consumeRadialGradient(CSSParserTokenRang e& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating) |
2437 { | 2595 { |
2438 RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue:: create(repeating, CSSRadialGradient); | 2596 RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue:: create(repeating, CSSRadialGradient); |
2439 | 2597 |
2440 RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = nullptr; | 2598 RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = nullptr; |
2441 RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeKeyword = nullptr; | 2599 RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeKeyword = nullptr; |
2442 RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr; | 2600 RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr; |
2443 RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr; | 2601 RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr; |
2444 | 2602 |
2445 // First part of grammar, the size/shape clause: | 2603 // First part of grammar, the size/shape clause: |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2583 if (context.useCounter()) | 2741 if (context.useCounter()) |
2584 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie nt); | 2742 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie nt); |
2585 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSPr efixedLinearGradient); | 2743 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSPr efixedLinearGradient); |
2586 } else if (id == CSSValueWebkitRepeatingLinearGradient) { | 2744 } else if (id == CSSValueWebkitRepeatingLinearGradient) { |
2587 // FIXME: This should send a deprecation message. | 2745 // FIXME: This should send a deprecation message. |
2588 if (context.useCounter()) | 2746 if (context.useCounter()) |
2589 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin earGradient); | 2747 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin earGradient); |
2590 result = consumeLinearGradient(args, context.mode(), Repeating, CSSPrefi xedLinearGradient); | 2748 result = consumeLinearGradient(args, context.mode(), Repeating, CSSPrefi xedLinearGradient); |
2591 } else if (id == CSSValueLinearGradient) { | 2749 } else if (id == CSSValueLinearGradient) { |
2592 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSLi nearGradient); | 2750 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSLi nearGradient); |
2751 } else if (id == CSSValueWebkitGradient) { | |
2752 // FIXME: This should send a deprecation message. | |
2753 if (context.useCounter()) | |
2754 context.useCounter()->count(UseCounter::DeprecatedWebKitGradient); | |
2755 result = consumeDeprecatedGradient(args, context.mode()); | |
2756 } else if (id == CSSValueWebkitRadialGradient) { | |
2757 // FIXME: This should send a deprecation message. | |
2758 if (context.useCounter()) | |
2759 context.useCounter()->count(UseCounter::DeprecatedWebKitRadialGradie nt); | |
2760 result = consumeDeprecatedRadialGradient(args, context.mode(), NonRepeat ing); | |
2761 } else if (id == CSSValueWebkitRepeatingRadialGradient) { | |
2762 if (context.useCounter()) | |
2763 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingRad ialGradient); | |
2764 result = consumeDeprecatedRadialGradient(args, context.mode(), Repeating ); | |
2593 } else if (id == CSSValueWebkitCrossFade) { | 2765 } else if (id == CSSValueWebkitCrossFade) { |
2594 result = consumeCrossFade(args, context); | 2766 result = consumeCrossFade(args, context); |
2595 } | 2767 } |
2596 if (!result || !args.atEnd()) | 2768 if (!result || !args.atEnd()) |
2597 return nullptr; | 2769 return nullptr; |
2598 range = rangeCopy; | 2770 range = rangeCopy; |
2599 return result; | 2771 return result; |
2600 } | 2772 } |
2601 | 2773 |
2602 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange& range, CSSParserContext context) | 2774 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange& range, CSSParserContext context) |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3446 return consumeShorthandGreedily(flexFlowShorthand(), important); | 3618 return consumeShorthandGreedily(flexFlowShorthand(), important); |
3447 case CSSPropertyWebkitColumnRule: | 3619 case CSSPropertyWebkitColumnRule: |
3448 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important); | 3620 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important); |
3449 default: | 3621 default: |
3450 m_currentShorthand = oldShorthand; | 3622 m_currentShorthand = oldShorthand; |
3451 return false; | 3623 return false; |
3452 } | 3624 } |
3453 } | 3625 } |
3454 | 3626 |
3455 } // namespace blink | 3627 } // namespace blink |
OLD | NEW |