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

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: Fix endX code 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)
Timothy Loh 2015/12/10 04:20:07 Can you update all the CSSParserContext arguments
rwlbuis 2015/12/10 14:00:08 Done.
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 do {
2416 CSSGradientColorStop stop;
2417 stop.m_color = consumeColor(range, context);
2418 // Two hints in a row are not allowed.
2419 if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint))
2420 return false;
2421 previousStopWasColorHint = !stop.m_color;
2422 stop.m_position = consumeLengthOrPercent(range, context.mode(), ValueRan geAll);
2423 if (!stop.m_color && !stop.m_position)
2424 return false;
2425 gradient->addStop(stop);
2426 } while (consumeCommaIncludingWhitespace(range));
2427
2428 // The last color stop cannot be a color hint.
2429 if (previousStopWasColorHint)
2430 return false;
2431
2432 // Must have 2 or more stops to be valid.
2433 return gradient->stopCount() >= 2;
2434 }
2435
2436 static PassRefPtrWillBeRawPtr<CSSValue> consumeRadialGradient(CSSParserTokenRang e& args, CSSParserContext context, CSSGradientRepeat repeating)
2437 {
2438 RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue:: create(repeating, CSSRadialGradient);
2439
2440 RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = nullptr;
2441 RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeKeyword = nullptr;
2442 RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr;
2443 RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr;
2444
2445 // First part of grammar, the size/shape clause:
2446 // [ circle || <length> ] |
2447 // [ ellipse || [ <length> | <percentage> ]{2} ] |
2448 // [ [ circle | ellipse] || <size-keyword> ]
2449 for (int i = 0; i < 3; ++i) {
2450 if (args.peek().type() == IdentToken) {
2451 CSSValueID id = args.peek().id();
2452 if (id == CSSValueCircle || id == CSSValueEllipse) {
2453 if (shape)
2454 return nullptr;
2455 shape = consumeIdent(args);
2456 } else if (id == CSSValueClosestSide || id == CSSValueClosestCorner || id == CSSValueFarthestSide || id == CSSValueFarthestCorner) {
2457 if (sizeKeyword)
2458 return nullptr;
2459 sizeKeyword = consumeIdent(args);
2460 } else {
2461 break;
2462 }
2463 } else {
2464 RefPtrWillBeRawPtr<CSSPrimitiveValue> center = consumeLengthOrPercen t(args, context.mode(), ValueRangeAll);
2465 if (!center)
2466 break;
2467 if (horizontalSize)
2468 return nullptr;
2469 horizontalSize = center;
2470 if ((center = consumeLengthOrPercent(args, context.mode(), ValueRang eAll))) {
2471 verticalSize = center.release();
2472 ++i;
2473 }
2474 }
2475 }
2476
2477 // You can specify size as a keyword or a length/percentage, not both.
2478 if (sizeKeyword && horizontalSize)
2479 return nullptr;
2480 // Circles must have 0 or 1 lengths.
2481 if (shape && shape->getValueID() == CSSValueCircle && verticalSize)
2482 return nullptr;
2483 // Ellipses must have 0 or 2 length/percentages.
2484 if (shape && shape->getValueID() == CSSValueEllipse && horizontalSize && !ve rticalSize)
2485 return nullptr;
2486 // If there's only one size, it must be a length.
2487 // TODO(timloh): Calcs with both lengths and percentages should be rejected.
2488 if (!verticalSize && horizontalSize && horizontalSize->isPercentage())
2489 return nullptr;
2490
2491 result->setShape(shape);
2492 result->setSizingBehavior(sizeKeyword);
2493 result->setEndHorizontalSize(horizontalSize);
2494 result->setEndVerticalSize(verticalSize);
2495
2496 RefPtrWillBeRawPtr<CSSValue> centerX = nullptr;
2497 RefPtrWillBeRawPtr<CSSValue> centerY = nullptr;
2498 if (args.peek().id() == CSSValueAt) {
2499 args.consumeIncludingWhitespace();
2500 consumePosition(args, context.mode(), UnitlessQuirk::Forbid, centerX, ce nterY);
2501 if (!(centerX && centerY))
2502 return nullptr;
2503 result->setFirstX(centerX);
2504 result->setFirstY(centerY);
2505 // Right now, CSS radial gradients have the same start and end centers.
2506 result->setSecondX(centerX);
2507 result->setSecondY(centerY);
2508 }
2509
2510 if ((shape || sizeKeyword || horizontalSize || centerX || centerY) && !consu meCommaIncludingWhitespace(args))
2511 return nullptr;
2512 if (!consumeGradientColorStops(args, context, result.get()))
2513 return nullptr;
2514 return result.release();
2515 }
2516
2517 static PassRefPtrWillBeRawPtr<CSSValue> consumeLinearGradient(CSSParserTokenRang e& args, CSSParserContext context, CSSGradientRepeat repeating, CSSGradientType gradientType)
2518 {
2519 RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue:: create(repeating, gradientType);
2520
2521 bool expectComma = true;
2522 RefPtrWillBeRawPtr<CSSPrimitiveValue> angle = consumeAngle(args, context.mod e());
2523 if (angle) {
2524 result->setAngle(angle.release());
2525 } else if (gradientType == CSSPrefixedLinearGradient || consumeIdent<CSSValu eTo>(args)) {
2526 RefPtrWillBeRawPtr<CSSPrimitiveValue> endX = consumeIdent<CSSValueLeft, CSSValueRight>(args);
2527 RefPtrWillBeRawPtr<CSSPrimitiveValue> endY = consumeIdent<CSSValueBottom , CSSValueTop>(args);
2528 if (gradientType == CSSLinearGradient && !endX && !endY)
Timothy Loh 2015/12/10 04:20:07 Clearer like this IMO, moving the two !endX && !en
rwlbuis 2015/12/10 14:00:08 Much better, done.
2529 return nullptr;
2530 if (!endX)
2531 endX = consumeIdent<CSSValueLeft, CSSValueRight>(args);
2532 if (!endY)
2533 endY = consumeIdent<CSSValueBottom, CSSValueTop>(args);
2534
2535 if (!endX && !endY) {
2536 endY = cssValuePool().createIdentifierValue(CSSValueTop);
2537 expectComma = false;
2538 }
2539
2540 result->setFirstX(endX.release());
2541 result->setFirstY(endY.release());
2542 }
Timothy Loh 2015/12/10 04:20:07 Since you made expectComma start at true, we need
rwlbuis 2015/12/10 14:00:08 Done.
2543
2544 if (expectComma && !consumeCommaIncludingWhitespace(args))
2545 return nullptr;
2546 if (!consumeGradientColorStops(args, context, result.get()))
2547 return nullptr;
2548 return result.release();
2549 }
2550
2551 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange&, CSSPa rserContext);
2552
2553 static PassRefPtrWillBeRawPtr<CSSValue> consumeCrossFade(CSSParserTokenRange& ar gs, CSSParserContext context)
2554 {
2555 RefPtrWillBeRawPtr<CSSValue> fromImageValue = consumeImage(args, context);
2556 if (!fromImageValue || !consumeCommaIncludingWhitespace(args))
2557 return nullptr;
2558 RefPtrWillBeRawPtr<CSSValue> toImageValue = consumeImage(args, context);
2559 if (!toImageValue || !consumeCommaIncludingWhitespace(args))
2560 return nullptr;
2561
2562 RefPtrWillBeRawPtr<CSSPrimitiveValue> percentage = nullptr;
2563 const CSSParserToken& percentageArg = args.consumeIncludingWhitespace();
2564 if (percentageArg.type() == PercentageToken)
2565 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue() / 100, 0, 1), CSSPrimitiveValue::UnitType::Number);
2566 else if (percentageArg.type() == NumberToken)
2567 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue(), 0, 1), CSSPrimitiveValue::UnitType::Number);
2568
2569 if (!percentage)
2570 return nullptr;
2571 return CSSCrossfadeValue::create(fromImageValue, toImageValue, percentage);
2572 }
2573
2574 static PassRefPtrWillBeRawPtr<CSSValue> consumeGeneratedImage(CSSParserTokenRang e& range, CSSParserContext context)
2575 {
2576 CSSValueID id = range.peek().functionId();
2577 CSSParserTokenRange rangeCopy = range;
2578 CSSParserTokenRange args = consumeFunction(rangeCopy);
2579 RefPtrWillBeRawPtr<CSSValue> result = nullptr;
2580 if (id == CSSValueRadialGradient)
2581 result = consumeRadialGradient(args, context, NonRepeating);
2582 if (id == CSSValueWebkitLinearGradient) {
2583 // FIXME: This should send a deprecation message.
2584 if (context.useCounter())
2585 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie nt);
2586 result = consumeLinearGradient(args, context, NonRepeating, CSSPrefixedL inearGradient);
2587 }
2588 if (id == CSSValueWebkitRepeatingLinearGradient) {
2589 // FIXME: This should send a deprecation message.
2590 if (context.useCounter())
2591 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin earGradient);
2592 result = consumeLinearGradient(args, context, Repeating, CSSPrefixedLine arGradient);
2593 }
2594 if (id == CSSValueLinearGradient)
2595 result = consumeLinearGradient(args, context, NonRepeating, CSSLinearGra dient);
2596 if (id == CSSValueWebkitCrossFade)
2597 result = consumeCrossFade(args, context);
2598 if (!result || !args.atEnd())
2599 return nullptr;
2600 range = rangeCopy;
2601 return result;
2602 }
2603
2604 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange& range, CSSParserContext context)
2605 {
2606 if (range.peek().id() == CSSValueNone)
2607 return consumeIdent(range);
2608
2609 AtomicString uri(consumeUrl(range));
2610 if (!uri.isNull())
2611 return CSSPropertyParser::createCSSImageValueWithReferrer(uri, context);
2612 if (range.peek().type() == FunctionToken) {
2613 CSSValueID id = range.peek().functionId();
2614 if (id == CSSValueWebkitImageSet)
2615 return consumeImageSet(range, context);
2616 if (CSSPropertyParser::isGeneratedImage(id))
2617 return consumeGeneratedImage(range, context);
2618 }
2619 return nullptr;
2620 }
2621
2408 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty) 2622 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty)
2409 { 2623 {
2410 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); 2624 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
2411 switch (property) { 2625 switch (property) {
2412 case CSSPropertyWillChange: 2626 case CSSPropertyWillChange:
2413 return consumeWillChange(m_range); 2627 return consumeWillChange(m_range);
2414 case CSSPropertyPage: 2628 case CSSPropertyPage:
2415 return consumePage(m_range); 2629 return consumePage(m_range);
2416 case CSSPropertyQuotes: 2630 case CSSPropertyQuotes:
2417 return consumeQuotes(m_range); 2631 return consumeQuotes(m_range);
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
3234 return consumeShorthandGreedily(flexFlowShorthand(), important); 3448 return consumeShorthandGreedily(flexFlowShorthand(), important);
3235 case CSSPropertyWebkitColumnRule: 3449 case CSSPropertyWebkitColumnRule:
3236 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important); 3450 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important);
3237 default: 3451 default:
3238 m_currentShorthand = oldShorthand; 3452 m_currentShorthand = oldShorthand;
3239 return false; 3453 return false;
3240 } 3454 }
3241 } 3455 }
3242 3456
3243 } // namespace blink 3457 } // 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