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

Side by Side Diff: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp

Issue 1508913002: Add support for <image> type parsing using CSSParserTokens (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add deprecated linear gradient support Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/CSSCursorImageValue.h" 11 #include "core/css/CSSCursorImageValue.h"
11 #include "core/css/CSSCustomIdentValue.h" 12 #include "core/css/CSSCustomIdentValue.h"
12 #include "core/css/CSSFontFaceSrcValue.h" 13 #include "core/css/CSSFontFaceSrcValue.h"
13 #include "core/css/CSSFontFeatureValue.h" 14 #include "core/css/CSSFontFeatureValue.h"
14 #include "core/css/CSSFunctionValue.h" 15 #include "core/css/CSSFunctionValue.h"
15 #include "core/css/CSSImageSetValue.h" 16 #include "core/css/CSSImageSetValue.h"
16 #include "core/css/CSSPathValue.h" 17 #include "core/css/CSSPathValue.h"
17 #include "core/css/CSSPrimitiveValueMappings.h" 18 #include "core/css/CSSPrimitiveValueMappings.h"
18 #include "core/css/CSSQuadValue.h" 19 #include "core/css/CSSQuadValue.h"
19 #include "core/css/CSSSVGDocumentValue.h" 20 #include "core/css/CSSSVGDocumentValue.h"
(...skipping 2378 matching lines...) Expand 10 before | Expand all | Expand 10 after
2398 cursorType = consumeIdent(range); 2399 cursorType = consumeIdent(range);
2399 } 2400 }
2400 2401
2401 if (!list) 2402 if (!list)
2402 return cursorType.release(); 2403 return cursorType.release();
2403 if (cursorType) 2404 if (cursorType)
2404 list->append(cursorType.release()); 2405 list->append(cursorType.release());
2405 return list.release(); 2406 return list.release();
2406 } 2407 }
2407 2408
2409 static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserConte xt context, CSSGradientValue* gradient, bool expectComma)
2410 {
2411 bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || g radient->gradientType() == CSSRadialGradient;
2412
2413 // The first color stop cannot be a color hint.
2414 bool previousStopWasColorHint = true;
2415 while (!range.atEnd()) {
Timothy Loh 2015/12/09 06:59:57 Can we just use a regular do-while loop here and m
rwlbuis 2015/12/09 21:31:13 Done.
2416 if (expectComma && !consumeCommaIncludingWhitespace(range))
2417 return false;
2418
2419 CSSGradientColorStop stop;
2420 stop.m_color = consumeColor(range, context);
2421
2422 // Two hints in a row are not allowed.
2423 if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint))
2424 return false;
2425 previousStopWasColorHint = !stop.m_color;
2426 stop.m_position = consumeLengthOrPercent(range, context.mode(), ValueRan geAll);
2427 if (!stop.m_color && !stop.m_position)
2428 return false;
2429
2430 gradient->addStop(stop);
2431 expectComma = true;
2432 }
2433
2434 // The last color stop cannot be a color hint.
2435 if (previousStopWasColorHint)
2436 return false;
2437
2438 // Must have 2 or more stops to be valid.
2439 return gradient->stopCount() >= 2;
2440 }
2441
2442 static PassRefPtrWillBeRawPtr<CSSValue> consumeRadialGradient(CSSParserTokenRang e args, CSSParserContext context, CSSGradientRepeat repeating)
2443 {
2444 RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue:: create(repeating, CSSRadialGradient);
2445
2446 RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue = nullptr;
Timothy Loh 2015/12/09 06:59:57 imo shapeValue -> shape, sizeValue -> sizeKeyword
rwlbuis 2015/12/09 21:31:13 Done.
2447 RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeValue = nullptr;
2448 RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr;
2449 RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr;
2450
2451 // First part of grammar, the size/shape clause:
2452 // [ circle || <length> ] |
2453 // [ ellipse || [ <length> | <percentage> ]{2} ] |
2454 // [ [ circle | ellipse] || <size-keyword> ]
2455 for (int i = 0; i < 3; ++i) {
2456 if (args.peek().type() == IdentToken) {
2457 CSSValueID id = args.peek().id();
2458 if (id == CSSValueCircle || id == CSSValueEllipse) {
2459 if (shapeValue)
2460 return nullptr;
2461 shapeValue = consumeIdent(args);
2462 } else if (id == CSSValueClosestSide || id == CSSValueClosestCorner || id == CSSValueFarthestSide || id == CSSValueFarthestCorner) {
2463 if (sizeValue || horizontalSize)
Timothy Loh 2015/12/09 06:59:57 Probably nicer to leave out the horizontalSize che
rwlbuis 2015/12/09 21:31:14 Done.
2464 return nullptr;
2465 sizeValue = consumeIdent(args);
2466 } else {
2467 break;
2468 }
2469 } else {
2470 RefPtrWillBeRawPtr<CSSPrimitiveValue> center = consumeLengthOrPercen t(args, context.mode(), ValueRangeAll);
2471 if (!center)
2472 break;
2473 if (sizeValue || horizontalSize)
Timothy Loh 2015/12/09 06:59:57 and leave out the sizeValue check here
rwlbuis 2015/12/09 21:31:14 Done.
2474 return nullptr;
2475 horizontalSize = center;
2476
2477 if ((center = consumeLengthOrPercent(args, context.mode(), ValueRang eAll))) {
2478 verticalSize = center.release();
2479 ++i;
2480 }
2481 }
2482 }
2483
2484 // You can specify size as a keyword or a length/percentage, not both.
2485 if (sizeValue && horizontalSize)
2486 return nullptr;
2487 // Circles must have 0 or 1 lengths.
2488 if (shapeValue && shapeValue->getValueID() == CSSValueCircle && verticalSize )
2489 return nullptr;
2490 // Ellipses must have 0 or 2 length/percentages.
2491 if (shapeValue && shapeValue->getValueID() == CSSValueEllipse && horizontalS ize && !verticalSize)
2492 return nullptr;
2493 // If there's only one size, it must be a length.
2494 if (!verticalSize && horizontalSize && horizontalSize->isPercentage())
Timothy Loh 2015/12/09 06:59:57 // TODO(timloh): Calcs with both lengths and perce
rwlbuis 2015/12/09 21:31:13 Done.
2495 return nullptr;
2496
2497 result->setShape(shapeValue);
2498 result->setSizingBehavior(sizeValue);
2499 result->setEndHorizontalSize(horizontalSize);
2500 result->setEndVerticalSize(verticalSize);
2501
2502 RefPtrWillBeRawPtr<CSSValue> centerX = nullptr;
2503 RefPtrWillBeRawPtr<CSSValue> centerY = nullptr;
2504 if (args.peek().id() == CSSValueAt) {
2505 args.consumeIncludingWhitespace();
2506
2507 consumePosition(args, context.mode(), UnitlessQuirk::Forbid, centerX, ce nterY);
2508 if (!(centerX && centerY))
2509 return nullptr;
2510
2511 result->setFirstX(centerX);
2512 result->setFirstY(centerY);
2513 // Right now, CSS radial gradients have the same start and end centers.
2514 result->setSecondX(centerX);
2515 result->setSecondY(centerY);
2516 }
2517
2518 bool expectComma = shapeValue || sizeValue || horizontalSize || centerX || c enterY;
2519 if (!consumeGradientColorStops(args, context, result.get(), expectComma) || !args.atEnd())
2520 return nullptr;
2521
2522 return result.release();
2523 }
2524
2525 static PassRefPtrWillBeRawPtr<CSSValue> consumeLinearGradient(CSSParserTokenRang e args, CSSParserContext context, CSSGradientRepeat repeating, CSSGradientType g radientType)
2526 {
2527 RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue:: create(repeating, gradientType);
2528
2529 bool expectComma = true;
2530 RefPtrWillBeRawPtr<CSSPrimitiveValue> angle = consumeAngle(args, context.mod e());
2531 if (angle) {
2532 result->setAngle(angle.release());
2533 } else if (gradientType == CSSPrefixedLinearGradient || consumeIdent<CSSValu eTo>(args)) {
2534 RefPtrWillBeRawPtr<CSSPrimitiveValue> endX = consumeIdent<CSSValueLeft, CSSValueRight>(args);
2535 RefPtrWillBeRawPtr<CSSPrimitiveValue> endY = consumeIdent<CSSValueBottom , CSSValueTop>(args);
2536 if (!endX && !endY)
2537 return nullptr;
2538 RefPtrWillBeRawPtr<CSSPrimitiveValue> location = consumeIdent<CSSValueLe ft, CSSValueRight>(args);
Timothy Loh 2015/12/09 06:59:57 Should be enough to just write if (!endX) end
rwlbuis 2015/12/09 21:31:13 I think endX and location have to be separate. Oth
rwlbuis 2015/12/09 23:08:46 Oh, I see why you mean here too now, should be fix
2539 if (location) {
2540 if (endX)
2541 return nullptr;
2542 endX = location;
2543 } else if ((location = consumeIdent<CSSValueBottom, CSSValueTop>(args))) {
2544 if (endY)
2545 return nullptr;
2546 endY = location;
2547 }
2548
2549 if (!endX && !endY) {
2550 endY = cssValuePool().createIdentifierValue(CSSValueTop);
Timothy Loh 2015/12/09 06:59:57 Unreachable?
rwlbuis 2015/12/09 21:31:13 Sorry, I merged a patch wrong, this is still neede
2551 expectComma = false;
2552 }
2553
2554 result->setFirstX(endX.release());
2555 result->setFirstY(endY.release());
2556 }
2557
2558 if (!consumeGradientColorStops(args, context, result.get(), expectComma) || !args.atEnd())
2559 return nullptr;
2560
2561 return result.release();
2562 }
2563
2564 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange&, CSSPa rserContext);
2565
2566 static PassRefPtrWillBeRawPtr<CSSValue> consumeCrossFade(CSSParserTokenRange arg s, CSSParserContext context)
2567 {
2568 RefPtrWillBeRawPtr<CSSValue> fromImageValue = consumeImage(args, context);
2569 if (!fromImageValue || !consumeCommaIncludingWhitespace(args))
2570 return nullptr;
2571 RefPtrWillBeRawPtr<CSSValue> toImageValue = consumeImage(args, context);
2572 if (!toImageValue || !consumeCommaIncludingWhitespace(args))
2573 return nullptr;
2574
2575 RefPtrWillBeRawPtr<CSSPrimitiveValue> percentage = nullptr;
2576 const CSSParserToken& percentageArg = args.consumeIncludingWhitespace();
2577 if (percentageArg.type() == PercentageToken)
2578 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue() / 100, 0, 1), CSSPrimitiveValue::UnitType::Number);
2579 else if (percentageArg.type() == NumberToken)
2580 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue(), 0, 1), CSSPrimitiveValue::UnitType::Number);
2581
2582 if (!percentage || !args.atEnd())
2583 return nullptr;
2584
2585 return CSSCrossfadeValue::create(fromImageValue, toImageValue, percentage);
2586 }
2587
2588 static PassRefPtrWillBeRawPtr<CSSValue> consumeGeneratedImage(CSSParserTokenRang e& range, CSSParserContext context)
Timothy Loh 2015/12/09 06:59:57 As usual, we need to make sure this doesn't accide
rwlbuis 2015/12/09 21:31:14 Done.
Timothy Loh 2015/12/10 04:20:07 Any reason to not use else if here? (which imo mak
2589 {
2590 CSSValueID id = range.peek().functionId();
2591 if (id == CSSValueRadialGradient)
2592 return consumeRadialGradient(consumeFunction(range), context, NonRepeati ng);
2593 if (id == CSSValueWebkitLinearGradient) {
2594 // FIXME: This should send a deprecation message.
2595 if (context.useCounter())
2596 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie nt);
2597 return consumeLinearGradient(consumeFunction(range), context, NonRepeati ng, CSSPrefixedLinearGradient);
2598 }
2599 if (id == CSSValueWebkitRepeatingLinearGradient) {
2600 // FIXME: This should send a deprecation message.
2601 if (context.useCounter())
2602 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin earGradient);
2603 return consumeLinearGradient(consumeFunction(range), context, Repeating, CSSPrefixedLinearGradient);
2604 }
2605 if (id == CSSValueLinearGradient)
2606 return consumeLinearGradient(consumeFunction(range), context, NonRepeati ng, CSSLinearGradient);
2607 if (id == CSSValueWebkitCrossFade)
2608 return consumeCrossFade(consumeFunction(range), context);
2609 return nullptr;
2610 }
2611
2612 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange& range, CSSParserContext context)
2613 {
2614 if (range.peek().id() == CSSValueNone)
2615 return consumeIdent(range);
2616
2617 AtomicString uri(consumeUrl(range));
2618 if (!uri.isNull())
2619 return CSSPropertyParser::createCSSImageValueWithReferrer(uri, context);
2620 if (range.peek().type() == FunctionToken) {
2621 CSSValueID id = range.peek().functionId();
2622 if (id == CSSValueWebkitImageSet)
2623 return consumeImageSet(range, context);
2624 if (CSSPropertyParser::isGeneratedImage(id))
2625 return consumeGeneratedImage(range, context);
2626 }
2627 return nullptr;
2628 }
2629
2408 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty) 2630 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty)
2409 { 2631 {
2410 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); 2632 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
2411 switch (property) { 2633 switch (property) {
2412 case CSSPropertyWillChange: 2634 case CSSPropertyWillChange:
2413 return consumeWillChange(m_range); 2635 return consumeWillChange(m_range);
2414 case CSSPropertyPage: 2636 case CSSPropertyPage:
2415 return consumePage(m_range); 2637 return consumePage(m_range);
2416 case CSSPropertyQuotes: 2638 case CSSPropertyQuotes:
2417 return consumeQuotes(m_range); 2639 return consumeQuotes(m_range);
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
3234 return consumeShorthandGreedily(flexFlowShorthand(), important); 3456 return consumeShorthandGreedily(flexFlowShorthand(), important);
3235 case CSSPropertyWebkitColumnRule: 3457 case CSSPropertyWebkitColumnRule:
3236 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important); 3458 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important);
3237 default: 3459 default:
3238 m_currentShorthand = oldShorthand; 3460 m_currentShorthand = oldShorthand;
3239 return false; 3461 return false;
3240 } 3462 }
3241 } 3463 }
3242 3464
3243 } // namespace blink 3465 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698