Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
index 1138b51e3f84f6dc929d24c480e83bf67aa65c93..ab03ed339436fe8fcf80a2112523758aec0e4d5a 100644 |
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
@@ -9,21 +9,17 @@ |
#include "core/css/CSSBorderImage.h" |
#include "core/css/CSSContentDistributionValue.h" |
#include "core/css/CSSCounterValue.h" |
-#include "core/css/CSSCrossfadeValue.h" |
#include "core/css/CSSCursorImageValue.h" |
#include "core/css/CSSCustomIdentValue.h" |
#include "core/css/CSSFontFaceSrcValue.h" |
#include "core/css/CSSFontFamilyValue.h" |
#include "core/css/CSSFontFeatureValue.h" |
#include "core/css/CSSFunctionValue.h" |
-#include "core/css/CSSGradientValue.h" |
#include "core/css/CSSGridAutoRepeatValue.h" |
#include "core/css/CSSGridLineNamesValue.h" |
#include "core/css/CSSGridTemplateAreasValue.h" |
-#include "core/css/CSSImageSetValue.h" |
#include "core/css/CSSInheritedValue.h" |
#include "core/css/CSSInitialValue.h" |
-#include "core/css/CSSPaintValue.h" |
#include "core/css/CSSPathValue.h" |
#include "core/css/CSSPendingSubstitutionValue.h" |
#include "core/css/CSSPrimitiveValueMappings.h" |
@@ -1917,59 +1913,10 @@ static CSSPrimitiveValue* consumeRxOrRy(CSSParserTokenRange& range) |
return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll, UnitlessQuirk::Forbid); |
} |
-static CSSValue* createCSSImageValueWithReferrer(const AtomicString& rawValue, const CSSParserContext& context) |
-{ |
- CSSValue* imageValue = CSSImageValue::create(rawValue, context.completeURL(rawValue)); |
- toCSSImageValue(imageValue)->setReferrer(context.referrer()); |
- return imageValue; |
-} |
- |
-static CSSValue* consumeImageSet(CSSParserTokenRange& range, const CSSParserContext& context) |
-{ |
- CSSParserTokenRange rangeCopy = range; |
- CSSParserTokenRange args = consumeFunction(rangeCopy); |
- CSSImageSetValue* imageSet = CSSImageSetValue::create(); |
- do { |
- AtomicString urlValue = consumeUrl(args).toAtomicString(); |
- if (urlValue.isNull()) |
- return nullptr; |
- |
- CSSValue* image = createCSSImageValueWithReferrer(urlValue, context); |
- imageSet->append(*image); |
- |
- const CSSParserToken& token = args.consumeIncludingWhitespace(); |
- if (token.type() != DimensionToken) |
- return nullptr; |
- if (token.value() != "x") |
- return nullptr; |
- ASSERT(token.unitType() == CSSPrimitiveValue::UnitType::Unknown); |
- double imageScaleFactor = token.numericValue(); |
- if (imageScaleFactor <= 0) |
- return nullptr; |
- imageSet->append(*CSSPrimitiveValue::create(imageScaleFactor, CSSPrimitiveValue::UnitType::Number)); |
- } while (consumeCommaIncludingWhitespace(args)); |
- if (!args.atEnd()) |
- return nullptr; |
- range = rangeCopy; |
- return imageSet; |
-} |
- |
static CSSValue* consumeCursor(CSSParserTokenRange& range, const CSSParserContext& context, bool inQuirksMode) |
{ |
CSSValueList* list = nullptr; |
- while (true) { |
- CSSValue* image = nullptr; |
- AtomicString uri = consumeUrl(range).toAtomicString(); |
- if (!uri.isNull()) { |
- image = createCSSImageValueWithReferrer(uri, context); |
- } else if (range.peek().type() == FunctionToken && range.peek().functionId() == CSSValueWebkitImageSet) { |
- image = consumeImageSet(range, context); |
- if (!image) |
- return nullptr; |
- } else { |
- break; |
- } |
- |
+ while (CSSValue* image = consumeImage(range, context, ConsumeGeneratedImage::Forbid)) { |
double num; |
IntPoint hotSpot(-1, -1); |
bool hotSpotSpecified = false; |
@@ -2014,422 +1961,6 @@ static CSSValue* consumeCursor(CSSParserTokenRange& range, const CSSParserContex |
return list; |
} |
-// This should go away once we drop support for -webkit-gradient |
-static CSSPrimitiveValue* consumeDeprecatedGradientPoint(CSSParserTokenRange& args, bool horizontal) |
-{ |
- if (args.peek().type() == IdentToken) { |
- if ((horizontal && consumeIdent<CSSValueLeft>(args)) || (!horizontal && consumeIdent<CSSValueTop>(args))) |
- return CSSPrimitiveValue::create(0., CSSPrimitiveValue::UnitType::Percentage); |
- if ((horizontal && consumeIdent<CSSValueRight>(args)) || (!horizontal && consumeIdent<CSSValueBottom>(args))) |
- return CSSPrimitiveValue::create(100., CSSPrimitiveValue::UnitType::Percentage); |
- if (consumeIdent<CSSValueCenter>(args)) |
- return CSSPrimitiveValue::create(50., CSSPrimitiveValue::UnitType::Percentage); |
- return nullptr; |
- } |
- CSSPrimitiveValue* result = consumePercent(args, ValueRangeAll); |
- if (!result) |
- result = consumeNumber(args, ValueRangeAll); |
- return result; |
-} |
- |
-// Used to parse colors for -webkit-gradient(...). |
-static CSSValue* consumeDeprecatedGradientStopColor(CSSParserTokenRange& args, CSSParserMode cssParserMode) |
-{ |
- if (args.peek().id() == CSSValueCurrentcolor) |
- return nullptr; |
- return consumeColor(args, cssParserMode); |
-} |
- |
-static bool consumeDeprecatedGradientColorStop(CSSParserTokenRange& range, CSSGradientColorStop& stop, CSSParserMode cssParserMode) |
-{ |
- CSSValueID id = range.peek().functionId(); |
- if (id != CSSValueFrom && id != CSSValueTo && id != CSSValueColorStop) |
- return false; |
- |
- CSSParserTokenRange args = consumeFunction(range); |
- double position; |
- if (id == CSSValueFrom || id == CSSValueTo) { |
- position = (id == CSSValueFrom) ? 0 : 1; |
- } else { |
- ASSERT(id == CSSValueColorStop); |
- const CSSParserToken& arg = args.consumeIncludingWhitespace(); |
- if (arg.type() == PercentageToken) |
- position = arg.numericValue() / 100.0; |
- else if (arg.type() == NumberToken) |
- position = arg.numericValue(); |
- else |
- return false; |
- |
- if (!consumeCommaIncludingWhitespace(args)) |
- return false; |
- } |
- |
- stop.m_position = CSSPrimitiveValue::create(position, CSSPrimitiveValue::UnitType::Number); |
- stop.m_color = consumeDeprecatedGradientStopColor(args, cssParserMode); |
- return stop.m_color && args.atEnd(); |
-} |
- |
-static CSSValue* consumeDeprecatedGradient(CSSParserTokenRange& args, CSSParserMode cssParserMode) |
-{ |
- CSSGradientValue* result = nullptr; |
- CSSValueID id = args.consumeIncludingWhitespace().id(); |
- bool isDeprecatedRadialGradient = (id == CSSValueRadial); |
- if (isDeprecatedRadialGradient) |
- result = CSSRadialGradientValue::create(NonRepeating, CSSDeprecatedRadialGradient); |
- else if (id == CSSValueLinear) |
- result = CSSLinearGradientValue::create(NonRepeating, CSSDeprecatedLinearGradient); |
- if (!result || !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- |
- CSSPrimitiveValue* point = consumeDeprecatedGradientPoint(args, true); |
- if (!point) |
- return nullptr; |
- result->setFirstX(point); |
- point = consumeDeprecatedGradientPoint(args, false); |
- if (!point) |
- return nullptr; |
- result->setFirstY(point); |
- |
- if (!consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- |
- // For radial gradients only, we now expect a numeric radius. |
- if (isDeprecatedRadialGradient) { |
- CSSPrimitiveValue* radius = consumeNumber(args, ValueRangeAll); |
- if (!radius || !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- toCSSRadialGradientValue(result)->setFirstRadius(radius); |
- } |
- |
- point = consumeDeprecatedGradientPoint(args, true); |
- if (!point) |
- return nullptr; |
- result->setSecondX(point); |
- point = consumeDeprecatedGradientPoint(args, false); |
- if (!point) |
- return nullptr; |
- result->setSecondY(point); |
- |
- // For radial gradients only, we now expect the second radius. |
- if (isDeprecatedRadialGradient) { |
- if (!consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- CSSPrimitiveValue* radius = consumeNumber(args, ValueRangeAll); |
- if (!radius) |
- return nullptr; |
- toCSSRadialGradientValue(result)->setSecondRadius(radius); |
- } |
- |
- CSSGradientColorStop stop; |
- while (consumeCommaIncludingWhitespace(args)) { |
- if (!consumeDeprecatedGradientColorStop(args, stop, cssParserMode)) |
- return nullptr; |
- result->addStop(stop); |
- } |
- |
- return result; |
-} |
- |
-static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue* gradient) |
-{ |
- bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || gradient->gradientType() == CSSRadialGradient; |
- |
- // The first color stop cannot be a color hint. |
- bool previousStopWasColorHint = true; |
- do { |
- CSSGradientColorStop stop; |
- stop.m_color = consumeColor(range, cssParserMode); |
- // Two hints in a row are not allowed. |
- if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint)) |
- return false; |
- previousStopWasColorHint = !stop.m_color; |
- stop.m_position = consumeLengthOrPercent(range, cssParserMode, ValueRangeAll); |
- if (!stop.m_color && !stop.m_position) |
- return false; |
- gradient->addStop(stop); |
- } while (consumeCommaIncludingWhitespace(range)); |
- |
- // The last color stop cannot be a color hint. |
- if (previousStopWasColorHint) |
- return false; |
- |
- // Must have 2 or more stops to be valid. |
- return gradient->stopCount() >= 2; |
-} |
- |
-static CSSValue* consumeDeprecatedRadialGradient(CSSParserTokenRange& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating) |
-{ |
- CSSRadialGradientValue* result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient); |
- CSSValue* centerX = nullptr; |
- CSSValue* centerY = nullptr; |
- consumeOneOrTwoValuedPosition(args, cssParserMode, UnitlessQuirk::Forbid, centerX, centerY); |
- if ((centerX || centerY) && !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- |
- result->setFirstX(toCSSPrimitiveValue(centerX)); |
- result->setSecondX(toCSSPrimitiveValue(centerX)); |
- result->setFirstY(toCSSPrimitiveValue(centerY)); |
- result->setSecondY(toCSSPrimitiveValue(centerY)); |
- |
- CSSPrimitiveValue* shape = consumeIdent<CSSValueCircle, CSSValueEllipse>(args); |
- CSSPrimitiveValue* sizeKeyword = consumeIdent<CSSValueClosestSide, CSSValueClosestCorner, CSSValueFarthestSide, CSSValueFarthestCorner, CSSValueContain, CSSValueCover>(args); |
- if (!shape) |
- shape = consumeIdent<CSSValueCircle, CSSValueEllipse>(args); |
- result->setShape(shape); |
- result->setSizingBehavior(sizeKeyword); |
- |
- // Or, two lengths or percentages |
- if (!shape && !sizeKeyword) { |
- CSSPrimitiveValue* horizontalSize = consumeLengthOrPercent(args, cssParserMode, ValueRangeAll); |
- CSSPrimitiveValue* verticalSize = nullptr; |
- if (horizontalSize) { |
- verticalSize = consumeLengthOrPercent(args, cssParserMode, ValueRangeAll); |
- if (!verticalSize) |
- return nullptr; |
- consumeCommaIncludingWhitespace(args); |
- result->setEndHorizontalSize(horizontalSize); |
- result->setEndVerticalSize(verticalSize); |
- } |
- } else { |
- consumeCommaIncludingWhitespace(args); |
- } |
- if (!consumeGradientColorStops(args, cssParserMode, result)) |
- return nullptr; |
- |
- return result; |
-} |
- |
-static CSSValue* consumeRadialGradient(CSSParserTokenRange& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating) |
-{ |
- CSSRadialGradientValue* result = CSSRadialGradientValue::create(repeating, CSSRadialGradient); |
- |
- CSSPrimitiveValue* shape = nullptr; |
- CSSPrimitiveValue* sizeKeyword = nullptr; |
- CSSPrimitiveValue* horizontalSize = nullptr; |
- CSSPrimitiveValue* verticalSize = nullptr; |
- |
- // First part of grammar, the size/shape clause: |
- // [ circle || <length> ] | |
- // [ ellipse || [ <length> | <percentage> ]{2} ] | |
- // [ [ circle | ellipse] || <size-keyword> ] |
- for (int i = 0; i < 3; ++i) { |
- if (args.peek().type() == IdentToken) { |
- CSSValueID id = args.peek().id(); |
- if (id == CSSValueCircle || id == CSSValueEllipse) { |
- if (shape) |
- return nullptr; |
- shape = consumeIdent(args); |
- } else if (id == CSSValueClosestSide || id == CSSValueClosestCorner || id == CSSValueFarthestSide || id == CSSValueFarthestCorner) { |
- if (sizeKeyword) |
- return nullptr; |
- sizeKeyword = consumeIdent(args); |
- } else { |
- break; |
- } |
- } else { |
- CSSPrimitiveValue* center = consumeLengthOrPercent(args, cssParserMode, ValueRangeAll); |
- if (!center) |
- break; |
- if (horizontalSize) |
- return nullptr; |
- horizontalSize = center; |
- center = consumeLengthOrPercent(args, cssParserMode, ValueRangeAll); |
- if (center) { |
- verticalSize = center; |
- ++i; |
- } |
- } |
- } |
- |
- // You can specify size as a keyword or a length/percentage, not both. |
- if (sizeKeyword && horizontalSize) |
- return nullptr; |
- // Circles must have 0 or 1 lengths. |
- if (shape && shape->getValueID() == CSSValueCircle && verticalSize) |
- return nullptr; |
- // Ellipses must have 0 or 2 length/percentages. |
- if (shape && shape->getValueID() == CSSValueEllipse && horizontalSize && !verticalSize) |
- return nullptr; |
- // If there's only one size, it must be a length. |
- if (!verticalSize && horizontalSize && horizontalSize->isPercentage()) |
- return nullptr; |
- if ((horizontalSize && horizontalSize->isCalculatedPercentageWithLength()) |
- || (verticalSize && verticalSize->isCalculatedPercentageWithLength())) |
- return nullptr; |
- |
- result->setShape(shape); |
- result->setSizingBehavior(sizeKeyword); |
- result->setEndHorizontalSize(horizontalSize); |
- result->setEndVerticalSize(verticalSize); |
- |
- CSSValue* centerX = nullptr; |
- CSSValue* centerY = nullptr; |
- if (args.peek().id() == CSSValueAt) { |
- args.consumeIncludingWhitespace(); |
- consumePosition(args, cssParserMode, UnitlessQuirk::Forbid, centerX, centerY); |
- if (!(centerX && centerY)) |
- return nullptr; |
- result->setFirstX(centerX); |
- result->setFirstY(centerY); |
- // Right now, CSS radial gradients have the same start and end centers. |
- result->setSecondX(centerX); |
- result->setSecondY(centerY); |
- } |
- |
- if ((shape || sizeKeyword || horizontalSize || centerX || centerY) && !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- if (!consumeGradientColorStops(args, cssParserMode, result)) |
- return nullptr; |
- return result; |
-} |
- |
-static CSSValue* consumeLinearGradient(CSSParserTokenRange& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating, CSSGradientType gradientType) |
-{ |
- CSSLinearGradientValue* result = CSSLinearGradientValue::create(repeating, gradientType); |
- |
- bool expectComma = true; |
- CSSPrimitiveValue* angle = consumeAngle(args); |
- if (angle) { |
- result->setAngle(angle); |
- } else if (gradientType == CSSPrefixedLinearGradient || consumeIdent<CSSValueTo>(args)) { |
- CSSPrimitiveValue* endX = consumeIdent<CSSValueLeft, CSSValueRight>(args); |
- CSSPrimitiveValue* endY = consumeIdent<CSSValueBottom, CSSValueTop>(args); |
- if (!endX && !endY) { |
- if (gradientType == CSSLinearGradient) |
- return nullptr; |
- endY = CSSPrimitiveValue::createIdentifier(CSSValueTop); |
- expectComma = false; |
- } else if (!endX) { |
- endX = consumeIdent<CSSValueLeft, CSSValueRight>(args); |
- } |
- |
- result->setFirstX(endX); |
- result->setFirstY(endY); |
- } else { |
- expectComma = false; |
- } |
- |
- if (expectComma && !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- if (!consumeGradientColorStops(args, cssParserMode, result)) |
- return nullptr; |
- return result; |
-} |
- |
-static CSSValue* consumeImageOrNone(CSSParserTokenRange&, CSSParserContext); |
- |
-static CSSValue* consumeCrossFade(CSSParserTokenRange& args, CSSParserContext context) |
-{ |
- CSSValue* fromImageValue = consumeImageOrNone(args, context); |
- if (!fromImageValue || !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- CSSValue* toImageValue = consumeImageOrNone(args, context); |
- if (!toImageValue || !consumeCommaIncludingWhitespace(args)) |
- return nullptr; |
- |
- CSSPrimitiveValue* percentage = nullptr; |
- const CSSParserToken& percentageArg = args.consumeIncludingWhitespace(); |
- if (percentageArg.type() == PercentageToken) |
- percentage = CSSPrimitiveValue::create(clampTo<double>(percentageArg.numericValue() / 100, 0, 1), CSSPrimitiveValue::UnitType::Number); |
- else if (percentageArg.type() == NumberToken) |
- percentage = CSSPrimitiveValue::create(clampTo<double>(percentageArg.numericValue(), 0, 1), CSSPrimitiveValue::UnitType::Number); |
- |
- if (!percentage) |
- return nullptr; |
- return CSSCrossfadeValue::create(fromImageValue, toImageValue, percentage); |
-} |
- |
-static CSSValue* consumePaint(CSSParserTokenRange& args, CSSParserContext context) |
-{ |
- ASSERT(RuntimeEnabledFeatures::cssPaintAPIEnabled()); |
- |
- CSSCustomIdentValue* name = consumeCustomIdent(args); |
- if (!name) |
- return nullptr; |
- |
- return CSSPaintValue::create(name); |
-} |
- |
-static CSSValue* consumeGeneratedImage(CSSParserTokenRange& range, CSSParserContext context) |
-{ |
- CSSValueID id = range.peek().functionId(); |
- CSSParserTokenRange rangeCopy = range; |
- CSSParserTokenRange args = consumeFunction(rangeCopy); |
- CSSValue* result = nullptr; |
- if (id == CSSValueRadialGradient) { |
- result = consumeRadialGradient(args, context.mode(), NonRepeating); |
- } else if (id == CSSValueRepeatingRadialGradient) { |
- result = consumeRadialGradient(args, context.mode(), Repeating); |
- } else if (id == CSSValueWebkitLinearGradient) { |
- // FIXME: This should send a deprecation message. |
- if (context.useCounter()) |
- context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradient); |
- result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSPrefixedLinearGradient); |
- } else if (id == CSSValueWebkitRepeatingLinearGradient) { |
- // FIXME: This should send a deprecation message. |
- if (context.useCounter()) |
- context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLinearGradient); |
- result = consumeLinearGradient(args, context.mode(), Repeating, CSSPrefixedLinearGradient); |
- } else if (id == CSSValueRepeatingLinearGradient) { |
- result = consumeLinearGradient(args, context.mode(), Repeating, CSSLinearGradient); |
- } else if (id == CSSValueLinearGradient) { |
- result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSLinearGradient); |
- } else if (id == CSSValueWebkitGradient) { |
- // FIXME: This should send a deprecation message. |
- if (context.useCounter()) |
- context.useCounter()->count(UseCounter::DeprecatedWebKitGradient); |
- result = consumeDeprecatedGradient(args, context.mode()); |
- } else if (id == CSSValueWebkitRadialGradient) { |
- // FIXME: This should send a deprecation message. |
- if (context.useCounter()) |
- context.useCounter()->count(UseCounter::DeprecatedWebKitRadialGradient); |
- result = consumeDeprecatedRadialGradient(args, context.mode(), NonRepeating); |
- } else if (id == CSSValueWebkitRepeatingRadialGradient) { |
- if (context.useCounter()) |
- context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingRadialGradient); |
- result = consumeDeprecatedRadialGradient(args, context.mode(), Repeating); |
- } else if (id == CSSValueWebkitCrossFade) { |
- result = consumeCrossFade(args, context); |
- } else if (id == CSSValuePaint) { |
- result = RuntimeEnabledFeatures::cssPaintAPIEnabled() ? consumePaint(args, context) : nullptr; |
- } |
- if (!result || !args.atEnd()) |
- return nullptr; |
- range = rangeCopy; |
- return result; |
-} |
- |
-static bool isGeneratedImage(CSSValueID id) |
-{ |
- return id == CSSValueLinearGradient || id == CSSValueRadialGradient |
- || id == CSSValueRepeatingLinearGradient || id == CSSValueRepeatingRadialGradient |
- || id == CSSValueWebkitLinearGradient || id == CSSValueWebkitRadialGradient |
- || id == CSSValueWebkitRepeatingLinearGradient || id == CSSValueWebkitRepeatingRadialGradient |
- || id == CSSValueWebkitGradient || id == CSSValueWebkitCrossFade || id == CSSValuePaint; |
-} |
- |
-static CSSValue* consumeImage(CSSParserTokenRange& range, CSSParserContext context) |
-{ |
- AtomicString uri = consumeUrl(range).toAtomicString(); |
- if (!uri.isNull()) |
- return createCSSImageValueWithReferrer(uri, context); |
- if (range.peek().type() == FunctionToken) { |
- CSSValueID id = range.peek().functionId(); |
- if (id == CSSValueWebkitImageSet) |
- return consumeImageSet(range, context); |
- if (isGeneratedImage(id)) |
- return consumeGeneratedImage(range, context); |
- } |
- return nullptr; |
-} |
- |
-static CSSValue* consumeImageOrNone(CSSParserTokenRange& range, CSSParserContext context) |
-{ |
- if (range.peek().id() == CSSValueNone) |
- return consumeIdent(range); |
- return consumeImage(range, context); |
-} |
- |
static CSSValue* consumeAttr(CSSParserTokenRange args, CSSParserContext context) |
{ |
if (args.peek().type() != IdentToken) |