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

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: Patch for landing 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, CSSParserMode cssParserMode, CSSGradientValue* gradient)
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, cssParserMode);
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, cssParserMode, ValueRang eAll);
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, CSSParserMode cssParserMode, 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, cssParserMode, ValueRangeAll);
2465 if (!center)
2466 break;
2467 if (horizontalSize)
2468 return nullptr;
2469 horizontalSize = center;
2470 if ((center = consumeLengthOrPercent(args, cssParserMode, ValueRange All))) {
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, cssParserMode, UnitlessQuirk::Forbid, centerX, cen terY);
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, cssParserMode, result.get()))
2513 return nullptr;
2514 return result.release();
2515 }
2516
2517 static PassRefPtrWillBeRawPtr<CSSValue> consumeLinearGradient(CSSParserTokenRang e& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating, CSSGradientTy pe gradientType)
2518 {
2519 RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue:: create(repeating, gradientType);
2520
2521 bool expectComma = true;
2522 RefPtrWillBeRawPtr<CSSPrimitiveValue> angle = consumeAngle(args, cssParserMo de);
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 (!endX && !endY) {
2529 if (gradientType == CSSLinearGradient)
2530 return nullptr;
2531 endY = cssValuePool().createIdentifierValue(CSSValueTop);
2532 expectComma = false;
2533 } else if (!endX) {
2534 endX = consumeIdent<CSSValueLeft, CSSValueRight>(args);
2535 }
2536
2537 result->setFirstX(endX.release());
2538 result->setFirstY(endY.release());
2539 } else {
2540 expectComma = false;
2541 }
2542
2543 if (expectComma && !consumeCommaIncludingWhitespace(args))
2544 return nullptr;
2545 if (!consumeGradientColorStops(args, cssParserMode, result.get()))
2546 return nullptr;
2547 return result.release();
2548 }
2549
2550 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange&, CSSPa rserContext);
2551
2552 static PassRefPtrWillBeRawPtr<CSSValue> consumeCrossFade(CSSParserTokenRange& ar gs, CSSParserContext context)
2553 {
2554 RefPtrWillBeRawPtr<CSSValue> fromImageValue = consumeImage(args, context);
2555 if (!fromImageValue || !consumeCommaIncludingWhitespace(args))
2556 return nullptr;
2557 RefPtrWillBeRawPtr<CSSValue> toImageValue = consumeImage(args, context);
2558 if (!toImageValue || !consumeCommaIncludingWhitespace(args))
2559 return nullptr;
2560
2561 RefPtrWillBeRawPtr<CSSPrimitiveValue> percentage = nullptr;
2562 const CSSParserToken& percentageArg = args.consumeIncludingWhitespace();
2563 if (percentageArg.type() == PercentageToken)
2564 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue() / 100, 0, 1), CSSPrimitiveValue::UnitType::Number);
2565 else if (percentageArg.type() == NumberToken)
2566 percentage = cssValuePool().createValue(clampTo<double>(percentageArg.nu mericValue(), 0, 1), CSSPrimitiveValue::UnitType::Number);
2567
2568 if (!percentage)
2569 return nullptr;
2570 return CSSCrossfadeValue::create(fromImageValue, toImageValue, percentage);
2571 }
2572
2573 static PassRefPtrWillBeRawPtr<CSSValue> consumeGeneratedImage(CSSParserTokenRang e& range, CSSParserContext context)
2574 {
2575 CSSValueID id = range.peek().functionId();
2576 CSSParserTokenRange rangeCopy = range;
2577 CSSParserTokenRange args = consumeFunction(rangeCopy);
2578 RefPtrWillBeRawPtr<CSSValue> result = nullptr;
2579 if (id == CSSValueRadialGradient) {
2580 result = consumeRadialGradient(args, context.mode(), NonRepeating);
2581 } else if (id == CSSValueWebkitLinearGradient) {
2582 // FIXME: This should send a deprecation message.
2583 if (context.useCounter())
2584 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie nt);
2585 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSPr efixedLinearGradient);
2586 } else if (id == CSSValueWebkitRepeatingLinearGradient) {
2587 // FIXME: This should send a deprecation message.
2588 if (context.useCounter())
2589 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin earGradient);
2590 result = consumeLinearGradient(args, context.mode(), Repeating, CSSPrefi xedLinearGradient);
2591 } else if (id == CSSValueLinearGradient) {
2592 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSLi nearGradient);
2593 } else if (id == CSSValueWebkitCrossFade) {
2594 result = consumeCrossFade(args, context);
2595 }
2596 if (!result || !args.atEnd())
2597 return nullptr;
2598 range = rangeCopy;
2599 return result;
2600 }
2601
2602 static PassRefPtrWillBeRawPtr<CSSValue> consumeImage(CSSParserTokenRange& range, CSSParserContext context)
2603 {
2604 if (range.peek().id() == CSSValueNone)
2605 return consumeIdent(range);
2606
2607 AtomicString uri(consumeUrl(range));
2608 if (!uri.isNull())
2609 return CSSPropertyParser::createCSSImageValueWithReferrer(uri, context);
2610 if (range.peek().type() == FunctionToken) {
2611 CSSValueID id = range.peek().functionId();
2612 if (id == CSSValueWebkitImageSet)
2613 return consumeImageSet(range, context);
2614 if (CSSPropertyParser::isGeneratedImage(id))
2615 return consumeGeneratedImage(range, context);
2616 }
2617 return nullptr;
2618 }
2619
2408 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty) 2620 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID unresolvedProperty)
2409 { 2621 {
2410 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); 2622 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
2411 switch (property) { 2623 switch (property) {
2412 case CSSPropertyWillChange: 2624 case CSSPropertyWillChange:
2413 return consumeWillChange(m_range); 2625 return consumeWillChange(m_range);
2414 case CSSPropertyPage: 2626 case CSSPropertyPage:
2415 return consumePage(m_range); 2627 return consumePage(m_range);
2416 case CSSPropertyQuotes: 2628 case CSSPropertyQuotes:
2417 return consumeQuotes(m_range); 2629 return consumeQuotes(m_range);
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
3234 return consumeShorthandGreedily(flexFlowShorthand(), important); 3446 return consumeShorthandGreedily(flexFlowShorthand(), important);
3235 case CSSPropertyWebkitColumnRule: 3447 case CSSPropertyWebkitColumnRule:
3236 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important); 3448 return consumeShorthandGreedily(webkitColumnRuleShorthand(), important);
3237 default: 3449 default:
3238 m_currentShorthand = oldShorthand; 3450 m_currentShorthand = oldShorthand;
3239 return false; 3451 return false;
3240 } 3452 }
3241 } 3453 }
3242 3454
3243 } // namespace blink 3455 } // 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