| 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 "core/css/parser/CSSPropertyParser.h" | 5 #include "core/css/parser/CSSPropertyParser.h" |
| 6 | 6 |
| 7 #include "core/StylePropertyShorthand.h" | 7 #include "core/StylePropertyShorthand.h" |
| 8 #include "core/css/CSSBasicShapeValues.h" | 8 #include "core/css/CSSBasicShapeValues.h" |
| 9 #include "core/css/CSSBorderImage.h" | 9 #include "core/css/CSSBorderImage.h" |
| 10 #include "core/css/CSSContentDistributionValue.h" | 10 #include "core/css/CSSContentDistributionValue.h" |
| 11 #include "core/css/CSSCounterValue.h" | 11 #include "core/css/CSSCounterValue.h" |
| 12 #include "core/css/CSSCrossfadeValue.h" | |
| 13 #include "core/css/CSSCursorImageValue.h" | 12 #include "core/css/CSSCursorImageValue.h" |
| 14 #include "core/css/CSSCustomIdentValue.h" | 13 #include "core/css/CSSCustomIdentValue.h" |
| 15 #include "core/css/CSSFontFaceSrcValue.h" | 14 #include "core/css/CSSFontFaceSrcValue.h" |
| 16 #include "core/css/CSSFontFamilyValue.h" | 15 #include "core/css/CSSFontFamilyValue.h" |
| 17 #include "core/css/CSSFontFeatureValue.h" | 16 #include "core/css/CSSFontFeatureValue.h" |
| 18 #include "core/css/CSSFunctionValue.h" | 17 #include "core/css/CSSFunctionValue.h" |
| 19 #include "core/css/CSSGradientValue.h" | |
| 20 #include "core/css/CSSGridAutoRepeatValue.h" | 18 #include "core/css/CSSGridAutoRepeatValue.h" |
| 21 #include "core/css/CSSGridLineNamesValue.h" | 19 #include "core/css/CSSGridLineNamesValue.h" |
| 22 #include "core/css/CSSGridTemplateAreasValue.h" | 20 #include "core/css/CSSGridTemplateAreasValue.h" |
| 23 #include "core/css/CSSImageSetValue.h" | |
| 24 #include "core/css/CSSInheritedValue.h" | 21 #include "core/css/CSSInheritedValue.h" |
| 25 #include "core/css/CSSInitialValue.h" | 22 #include "core/css/CSSInitialValue.h" |
| 26 #include "core/css/CSSPaintValue.h" | |
| 27 #include "core/css/CSSPathValue.h" | 23 #include "core/css/CSSPathValue.h" |
| 28 #include "core/css/CSSPendingSubstitutionValue.h" | 24 #include "core/css/CSSPendingSubstitutionValue.h" |
| 29 #include "core/css/CSSPrimitiveValueMappings.h" | 25 #include "core/css/CSSPrimitiveValueMappings.h" |
| 30 #include "core/css/CSSQuadValue.h" | 26 #include "core/css/CSSQuadValue.h" |
| 31 #include "core/css/CSSReflectValue.h" | 27 #include "core/css/CSSReflectValue.h" |
| 32 #include "core/css/CSSShadowValue.h" | 28 #include "core/css/CSSShadowValue.h" |
| 33 #include "core/css/CSSStringValue.h" | 29 #include "core/css/CSSStringValue.h" |
| 34 #include "core/css/CSSTimingFunctionValue.h" | 30 #include "core/css/CSSTimingFunctionValue.h" |
| 35 #include "core/css/CSSURIValue.h" | 31 #include "core/css/CSSURIValue.h" |
| 36 #include "core/css/CSSUnicodeRangeValue.h" | 32 #include "core/css/CSSUnicodeRangeValue.h" |
| (...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll); | 1906 return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll); |
| 1911 } | 1907 } |
| 1912 | 1908 |
| 1913 static CSSPrimitiveValue* consumeRxOrRy(CSSParserTokenRange& range) | 1909 static CSSPrimitiveValue* consumeRxOrRy(CSSParserTokenRange& range) |
| 1914 { | 1910 { |
| 1915 if (range.peek().id() == CSSValueAuto) | 1911 if (range.peek().id() == CSSValueAuto) |
| 1916 return consumeIdent(range); | 1912 return consumeIdent(range); |
| 1917 return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll, Unitle
ssQuirk::Forbid); | 1913 return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll, Unitle
ssQuirk::Forbid); |
| 1918 } | 1914 } |
| 1919 | 1915 |
| 1920 static CSSValue* createCSSImageValueWithReferrer(const AtomicString& rawValue, c
onst CSSParserContext& context) | |
| 1921 { | |
| 1922 CSSValue* imageValue = CSSImageValue::create(rawValue, context.completeURL(r
awValue)); | |
| 1923 toCSSImageValue(imageValue)->setReferrer(context.referrer()); | |
| 1924 return imageValue; | |
| 1925 } | |
| 1926 | |
| 1927 static CSSValue* consumeImageSet(CSSParserTokenRange& range, const CSSParserCont
ext& context) | |
| 1928 { | |
| 1929 CSSParserTokenRange rangeCopy = range; | |
| 1930 CSSParserTokenRange args = consumeFunction(rangeCopy); | |
| 1931 CSSImageSetValue* imageSet = CSSImageSetValue::create(); | |
| 1932 do { | |
| 1933 AtomicString urlValue = consumeUrl(args).toAtomicString(); | |
| 1934 if (urlValue.isNull()) | |
| 1935 return nullptr; | |
| 1936 | |
| 1937 CSSValue* image = createCSSImageValueWithReferrer(urlValue, context); | |
| 1938 imageSet->append(*image); | |
| 1939 | |
| 1940 const CSSParserToken& token = args.consumeIncludingWhitespace(); | |
| 1941 if (token.type() != DimensionToken) | |
| 1942 return nullptr; | |
| 1943 if (token.value() != "x") | |
| 1944 return nullptr; | |
| 1945 ASSERT(token.unitType() == CSSPrimitiveValue::UnitType::Unknown); | |
| 1946 double imageScaleFactor = token.numericValue(); | |
| 1947 if (imageScaleFactor <= 0) | |
| 1948 return nullptr; | |
| 1949 imageSet->append(*CSSPrimitiveValue::create(imageScaleFactor, CSSPrimiti
veValue::UnitType::Number)); | |
| 1950 } while (consumeCommaIncludingWhitespace(args)); | |
| 1951 if (!args.atEnd()) | |
| 1952 return nullptr; | |
| 1953 range = rangeCopy; | |
| 1954 return imageSet; | |
| 1955 } | |
| 1956 | |
| 1957 static CSSValue* consumeCursor(CSSParserTokenRange& range, const CSSParserContex
t& context, bool inQuirksMode) | 1916 static CSSValue* consumeCursor(CSSParserTokenRange& range, const CSSParserContex
t& context, bool inQuirksMode) |
| 1958 { | 1917 { |
| 1959 CSSValueList* list = nullptr; | 1918 CSSValueList* list = nullptr; |
| 1960 while (true) { | 1919 while (CSSValue* image = consumeImage(range, context, ConsumeGeneratedImage:
:Forbid)) { |
| 1961 CSSValue* image = nullptr; | |
| 1962 AtomicString uri = consumeUrl(range).toAtomicString(); | |
| 1963 if (!uri.isNull()) { | |
| 1964 image = createCSSImageValueWithReferrer(uri, context); | |
| 1965 } else if (range.peek().type() == FunctionToken && range.peek().function
Id() == CSSValueWebkitImageSet) { | |
| 1966 image = consumeImageSet(range, context); | |
| 1967 if (!image) | |
| 1968 return nullptr; | |
| 1969 } else { | |
| 1970 break; | |
| 1971 } | |
| 1972 | |
| 1973 double num; | 1920 double num; |
| 1974 IntPoint hotSpot(-1, -1); | 1921 IntPoint hotSpot(-1, -1); |
| 1975 bool hotSpotSpecified = false; | 1922 bool hotSpotSpecified = false; |
| 1976 if (consumeNumberRaw(range, num)) { | 1923 if (consumeNumberRaw(range, num)) { |
| 1977 hotSpot.setX(int(num)); | 1924 hotSpot.setX(int(num)); |
| 1978 if (!consumeNumberRaw(range, num)) | 1925 if (!consumeNumberRaw(range, num)) |
| 1979 return nullptr; | 1926 return nullptr; |
| 1980 hotSpot.setY(int(num)); | 1927 hotSpot.setY(int(num)); |
| 1981 hotSpotSpecified = true; | 1928 hotSpotSpecified = true; |
| 1982 } | 1929 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2007 } else { | 1954 } else { |
| 2008 return nullptr; | 1955 return nullptr; |
| 2009 } | 1956 } |
| 2010 | 1957 |
| 2011 if (!list) | 1958 if (!list) |
| 2012 return cursorType; | 1959 return cursorType; |
| 2013 list->append(*cursorType); | 1960 list->append(*cursorType); |
| 2014 return list; | 1961 return list; |
| 2015 } | 1962 } |
| 2016 | 1963 |
| 2017 // This should go away once we drop support for -webkit-gradient | |
| 2018 static CSSPrimitiveValue* consumeDeprecatedGradientPoint(CSSParserTokenRange& ar
gs, bool horizontal) | |
| 2019 { | |
| 2020 if (args.peek().type() == IdentToken) { | |
| 2021 if ((horizontal && consumeIdent<CSSValueLeft>(args)) || (!horizontal &&
consumeIdent<CSSValueTop>(args))) | |
| 2022 return CSSPrimitiveValue::create(0., CSSPrimitiveValue::UnitType::Pe
rcentage); | |
| 2023 if ((horizontal && consumeIdent<CSSValueRight>(args)) || (!horizontal &&
consumeIdent<CSSValueBottom>(args))) | |
| 2024 return CSSPrimitiveValue::create(100., CSSPrimitiveValue::UnitType::
Percentage); | |
| 2025 if (consumeIdent<CSSValueCenter>(args)) | |
| 2026 return CSSPrimitiveValue::create(50., CSSPrimitiveValue::UnitType::P
ercentage); | |
| 2027 return nullptr; | |
| 2028 } | |
| 2029 CSSPrimitiveValue* result = consumePercent(args, ValueRangeAll); | |
| 2030 if (!result) | |
| 2031 result = consumeNumber(args, ValueRangeAll); | |
| 2032 return result; | |
| 2033 } | |
| 2034 | |
| 2035 // Used to parse colors for -webkit-gradient(...). | |
| 2036 static CSSValue* consumeDeprecatedGradientStopColor(CSSParserTokenRange& args, C
SSParserMode cssParserMode) | |
| 2037 { | |
| 2038 if (args.peek().id() == CSSValueCurrentcolor) | |
| 2039 return nullptr; | |
| 2040 return consumeColor(args, cssParserMode); | |
| 2041 } | |
| 2042 | |
| 2043 static bool consumeDeprecatedGradientColorStop(CSSParserTokenRange& range, CSSGr
adientColorStop& stop, CSSParserMode cssParserMode) | |
| 2044 { | |
| 2045 CSSValueID id = range.peek().functionId(); | |
| 2046 if (id != CSSValueFrom && id != CSSValueTo && id != CSSValueColorStop) | |
| 2047 return false; | |
| 2048 | |
| 2049 CSSParserTokenRange args = consumeFunction(range); | |
| 2050 double position; | |
| 2051 if (id == CSSValueFrom || id == CSSValueTo) { | |
| 2052 position = (id == CSSValueFrom) ? 0 : 1; | |
| 2053 } else { | |
| 2054 ASSERT(id == CSSValueColorStop); | |
| 2055 const CSSParserToken& arg = args.consumeIncludingWhitespace(); | |
| 2056 if (arg.type() == PercentageToken) | |
| 2057 position = arg.numericValue() / 100.0; | |
| 2058 else if (arg.type() == NumberToken) | |
| 2059 position = arg.numericValue(); | |
| 2060 else | |
| 2061 return false; | |
| 2062 | |
| 2063 if (!consumeCommaIncludingWhitespace(args)) | |
| 2064 return false; | |
| 2065 } | |
| 2066 | |
| 2067 stop.m_position = CSSPrimitiveValue::create(position, CSSPrimitiveValue::Uni
tType::Number); | |
| 2068 stop.m_color = consumeDeprecatedGradientStopColor(args, cssParserMode); | |
| 2069 return stop.m_color && args.atEnd(); | |
| 2070 } | |
| 2071 | |
| 2072 static CSSValue* consumeDeprecatedGradient(CSSParserTokenRange& args, CSSParserM
ode cssParserMode) | |
| 2073 { | |
| 2074 CSSGradientValue* result = nullptr; | |
| 2075 CSSValueID id = args.consumeIncludingWhitespace().id(); | |
| 2076 bool isDeprecatedRadialGradient = (id == CSSValueRadial); | |
| 2077 if (isDeprecatedRadialGradient) | |
| 2078 result = CSSRadialGradientValue::create(NonRepeating, CSSDeprecatedRadia
lGradient); | |
| 2079 else if (id == CSSValueLinear) | |
| 2080 result = CSSLinearGradientValue::create(NonRepeating, CSSDeprecatedLinea
rGradient); | |
| 2081 if (!result || !consumeCommaIncludingWhitespace(args)) | |
| 2082 return nullptr; | |
| 2083 | |
| 2084 CSSPrimitiveValue* point = consumeDeprecatedGradientPoint(args, true); | |
| 2085 if (!point) | |
| 2086 return nullptr; | |
| 2087 result->setFirstX(point); | |
| 2088 point = consumeDeprecatedGradientPoint(args, false); | |
| 2089 if (!point) | |
| 2090 return nullptr; | |
| 2091 result->setFirstY(point); | |
| 2092 | |
| 2093 if (!consumeCommaIncludingWhitespace(args)) | |
| 2094 return nullptr; | |
| 2095 | |
| 2096 // For radial gradients only, we now expect a numeric radius. | |
| 2097 if (isDeprecatedRadialGradient) { | |
| 2098 CSSPrimitiveValue* radius = consumeNumber(args, ValueRangeAll); | |
| 2099 if (!radius || !consumeCommaIncludingWhitespace(args)) | |
| 2100 return nullptr; | |
| 2101 toCSSRadialGradientValue(result)->setFirstRadius(radius); | |
| 2102 } | |
| 2103 | |
| 2104 point = consumeDeprecatedGradientPoint(args, true); | |
| 2105 if (!point) | |
| 2106 return nullptr; | |
| 2107 result->setSecondX(point); | |
| 2108 point = consumeDeprecatedGradientPoint(args, false); | |
| 2109 if (!point) | |
| 2110 return nullptr; | |
| 2111 result->setSecondY(point); | |
| 2112 | |
| 2113 // For radial gradients only, we now expect the second radius. | |
| 2114 if (isDeprecatedRadialGradient) { | |
| 2115 if (!consumeCommaIncludingWhitespace(args)) | |
| 2116 return nullptr; | |
| 2117 CSSPrimitiveValue* radius = consumeNumber(args, ValueRangeAll); | |
| 2118 if (!radius) | |
| 2119 return nullptr; | |
| 2120 toCSSRadialGradientValue(result)->setSecondRadius(radius); | |
| 2121 } | |
| 2122 | |
| 2123 CSSGradientColorStop stop; | |
| 2124 while (consumeCommaIncludingWhitespace(args)) { | |
| 2125 if (!consumeDeprecatedGradientColorStop(args, stop, cssParserMode)) | |
| 2126 return nullptr; | |
| 2127 result->addStop(stop); | |
| 2128 } | |
| 2129 | |
| 2130 return result; | |
| 2131 } | |
| 2132 | |
| 2133 static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode
cssParserMode, CSSGradientValue* gradient) | |
| 2134 { | |
| 2135 bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || g
radient->gradientType() == CSSRadialGradient; | |
| 2136 | |
| 2137 // The first color stop cannot be a color hint. | |
| 2138 bool previousStopWasColorHint = true; | |
| 2139 do { | |
| 2140 CSSGradientColorStop stop; | |
| 2141 stop.m_color = consumeColor(range, cssParserMode); | |
| 2142 // Two hints in a row are not allowed. | |
| 2143 if (!stop.m_color && (!supportsColorHints || previousStopWasColorHint)) | |
| 2144 return false; | |
| 2145 previousStopWasColorHint = !stop.m_color; | |
| 2146 stop.m_position = consumeLengthOrPercent(range, cssParserMode, ValueRang
eAll); | |
| 2147 if (!stop.m_color && !stop.m_position) | |
| 2148 return false; | |
| 2149 gradient->addStop(stop); | |
| 2150 } while (consumeCommaIncludingWhitespace(range)); | |
| 2151 | |
| 2152 // The last color stop cannot be a color hint. | |
| 2153 if (previousStopWasColorHint) | |
| 2154 return false; | |
| 2155 | |
| 2156 // Must have 2 or more stops to be valid. | |
| 2157 return gradient->stopCount() >= 2; | |
| 2158 } | |
| 2159 | |
| 2160 static CSSValue* consumeDeprecatedRadialGradient(CSSParserTokenRange& args, CSSP
arserMode cssParserMode, CSSGradientRepeat repeating) | |
| 2161 { | |
| 2162 CSSRadialGradientValue* result = CSSRadialGradientValue::create(repeating, C
SSPrefixedRadialGradient); | |
| 2163 CSSValue* centerX = nullptr; | |
| 2164 CSSValue* centerY = nullptr; | |
| 2165 consumeOneOrTwoValuedPosition(args, cssParserMode, UnitlessQuirk::Forbid, ce
nterX, centerY); | |
| 2166 if ((centerX || centerY) && !consumeCommaIncludingWhitespace(args)) | |
| 2167 return nullptr; | |
| 2168 | |
| 2169 result->setFirstX(toCSSPrimitiveValue(centerX)); | |
| 2170 result->setSecondX(toCSSPrimitiveValue(centerX)); | |
| 2171 result->setFirstY(toCSSPrimitiveValue(centerY)); | |
| 2172 result->setSecondY(toCSSPrimitiveValue(centerY)); | |
| 2173 | |
| 2174 CSSPrimitiveValue* shape = consumeIdent<CSSValueCircle, CSSValueEllipse>(arg
s); | |
| 2175 CSSPrimitiveValue* sizeKeyword = consumeIdent<CSSValueClosestSide, CSSValueC
losestCorner, CSSValueFarthestSide, CSSValueFarthestCorner, CSSValueContain, CSS
ValueCover>(args); | |
| 2176 if (!shape) | |
| 2177 shape = consumeIdent<CSSValueCircle, CSSValueEllipse>(args); | |
| 2178 result->setShape(shape); | |
| 2179 result->setSizingBehavior(sizeKeyword); | |
| 2180 | |
| 2181 // Or, two lengths or percentages | |
| 2182 if (!shape && !sizeKeyword) { | |
| 2183 CSSPrimitiveValue* horizontalSize = consumeLengthOrPercent(args, cssPars
erMode, ValueRangeAll); | |
| 2184 CSSPrimitiveValue* verticalSize = nullptr; | |
| 2185 if (horizontalSize) { | |
| 2186 verticalSize = consumeLengthOrPercent(args, cssParserMode, ValueRang
eAll); | |
| 2187 if (!verticalSize) | |
| 2188 return nullptr; | |
| 2189 consumeCommaIncludingWhitespace(args); | |
| 2190 result->setEndHorizontalSize(horizontalSize); | |
| 2191 result->setEndVerticalSize(verticalSize); | |
| 2192 } | |
| 2193 } else { | |
| 2194 consumeCommaIncludingWhitespace(args); | |
| 2195 } | |
| 2196 if (!consumeGradientColorStops(args, cssParserMode, result)) | |
| 2197 return nullptr; | |
| 2198 | |
| 2199 return result; | |
| 2200 } | |
| 2201 | |
| 2202 static CSSValue* consumeRadialGradient(CSSParserTokenRange& args, CSSParserMode
cssParserMode, CSSGradientRepeat repeating) | |
| 2203 { | |
| 2204 CSSRadialGradientValue* result = CSSRadialGradientValue::create(repeating, C
SSRadialGradient); | |
| 2205 | |
| 2206 CSSPrimitiveValue* shape = nullptr; | |
| 2207 CSSPrimitiveValue* sizeKeyword = nullptr; | |
| 2208 CSSPrimitiveValue* horizontalSize = nullptr; | |
| 2209 CSSPrimitiveValue* verticalSize = nullptr; | |
| 2210 | |
| 2211 // First part of grammar, the size/shape clause: | |
| 2212 // [ circle || <length> ] | | |
| 2213 // [ ellipse || [ <length> | <percentage> ]{2} ] | | |
| 2214 // [ [ circle | ellipse] || <size-keyword> ] | |
| 2215 for (int i = 0; i < 3; ++i) { | |
| 2216 if (args.peek().type() == IdentToken) { | |
| 2217 CSSValueID id = args.peek().id(); | |
| 2218 if (id == CSSValueCircle || id == CSSValueEllipse) { | |
| 2219 if (shape) | |
| 2220 return nullptr; | |
| 2221 shape = consumeIdent(args); | |
| 2222 } else if (id == CSSValueClosestSide || id == CSSValueClosestCorner
|| id == CSSValueFarthestSide || id == CSSValueFarthestCorner) { | |
| 2223 if (sizeKeyword) | |
| 2224 return nullptr; | |
| 2225 sizeKeyword = consumeIdent(args); | |
| 2226 } else { | |
| 2227 break; | |
| 2228 } | |
| 2229 } else { | |
| 2230 CSSPrimitiveValue* center = consumeLengthOrPercent(args, cssParserMo
de, ValueRangeAll); | |
| 2231 if (!center) | |
| 2232 break; | |
| 2233 if (horizontalSize) | |
| 2234 return nullptr; | |
| 2235 horizontalSize = center; | |
| 2236 center = consumeLengthOrPercent(args, cssParserMode, ValueRangeAll); | |
| 2237 if (center) { | |
| 2238 verticalSize = center; | |
| 2239 ++i; | |
| 2240 } | |
| 2241 } | |
| 2242 } | |
| 2243 | |
| 2244 // You can specify size as a keyword or a length/percentage, not both. | |
| 2245 if (sizeKeyword && horizontalSize) | |
| 2246 return nullptr; | |
| 2247 // Circles must have 0 or 1 lengths. | |
| 2248 if (shape && shape->getValueID() == CSSValueCircle && verticalSize) | |
| 2249 return nullptr; | |
| 2250 // Ellipses must have 0 or 2 length/percentages. | |
| 2251 if (shape && shape->getValueID() == CSSValueEllipse && horizontalSize && !ve
rticalSize) | |
| 2252 return nullptr; | |
| 2253 // If there's only one size, it must be a length. | |
| 2254 if (!verticalSize && horizontalSize && horizontalSize->isPercentage()) | |
| 2255 return nullptr; | |
| 2256 if ((horizontalSize && horizontalSize->isCalculatedPercentageWithLength()) | |
| 2257 || (verticalSize && verticalSize->isCalculatedPercentageWithLength())) | |
| 2258 return nullptr; | |
| 2259 | |
| 2260 result->setShape(shape); | |
| 2261 result->setSizingBehavior(sizeKeyword); | |
| 2262 result->setEndHorizontalSize(horizontalSize); | |
| 2263 result->setEndVerticalSize(verticalSize); | |
| 2264 | |
| 2265 CSSValue* centerX = nullptr; | |
| 2266 CSSValue* centerY = nullptr; | |
| 2267 if (args.peek().id() == CSSValueAt) { | |
| 2268 args.consumeIncludingWhitespace(); | |
| 2269 consumePosition(args, cssParserMode, UnitlessQuirk::Forbid, centerX, cen
terY); | |
| 2270 if (!(centerX && centerY)) | |
| 2271 return nullptr; | |
| 2272 result->setFirstX(centerX); | |
| 2273 result->setFirstY(centerY); | |
| 2274 // Right now, CSS radial gradients have the same start and end centers. | |
| 2275 result->setSecondX(centerX); | |
| 2276 result->setSecondY(centerY); | |
| 2277 } | |
| 2278 | |
| 2279 if ((shape || sizeKeyword || horizontalSize || centerX || centerY) && !consu
meCommaIncludingWhitespace(args)) | |
| 2280 return nullptr; | |
| 2281 if (!consumeGradientColorStops(args, cssParserMode, result)) | |
| 2282 return nullptr; | |
| 2283 return result; | |
| 2284 } | |
| 2285 | |
| 2286 static CSSValue* consumeLinearGradient(CSSParserTokenRange& args, CSSParserMode
cssParserMode, CSSGradientRepeat repeating, CSSGradientType gradientType) | |
| 2287 { | |
| 2288 CSSLinearGradientValue* result = CSSLinearGradientValue::create(repeating, g
radientType); | |
| 2289 | |
| 2290 bool expectComma = true; | |
| 2291 CSSPrimitiveValue* angle = consumeAngle(args); | |
| 2292 if (angle) { | |
| 2293 result->setAngle(angle); | |
| 2294 } else if (gradientType == CSSPrefixedLinearGradient || consumeIdent<CSSValu
eTo>(args)) { | |
| 2295 CSSPrimitiveValue* endX = consumeIdent<CSSValueLeft, CSSValueRight>(args
); | |
| 2296 CSSPrimitiveValue* endY = consumeIdent<CSSValueBottom, CSSValueTop>(args
); | |
| 2297 if (!endX && !endY) { | |
| 2298 if (gradientType == CSSLinearGradient) | |
| 2299 return nullptr; | |
| 2300 endY = CSSPrimitiveValue::createIdentifier(CSSValueTop); | |
| 2301 expectComma = false; | |
| 2302 } else if (!endX) { | |
| 2303 endX = consumeIdent<CSSValueLeft, CSSValueRight>(args); | |
| 2304 } | |
| 2305 | |
| 2306 result->setFirstX(endX); | |
| 2307 result->setFirstY(endY); | |
| 2308 } else { | |
| 2309 expectComma = false; | |
| 2310 } | |
| 2311 | |
| 2312 if (expectComma && !consumeCommaIncludingWhitespace(args)) | |
| 2313 return nullptr; | |
| 2314 if (!consumeGradientColorStops(args, cssParserMode, result)) | |
| 2315 return nullptr; | |
| 2316 return result; | |
| 2317 } | |
| 2318 | |
| 2319 static CSSValue* consumeImageOrNone(CSSParserTokenRange&, CSSParserContext); | |
| 2320 | |
| 2321 static CSSValue* consumeCrossFade(CSSParserTokenRange& args, CSSParserContext co
ntext) | |
| 2322 { | |
| 2323 CSSValue* fromImageValue = consumeImageOrNone(args, context); | |
| 2324 if (!fromImageValue || !consumeCommaIncludingWhitespace(args)) | |
| 2325 return nullptr; | |
| 2326 CSSValue* toImageValue = consumeImageOrNone(args, context); | |
| 2327 if (!toImageValue || !consumeCommaIncludingWhitespace(args)) | |
| 2328 return nullptr; | |
| 2329 | |
| 2330 CSSPrimitiveValue* percentage = nullptr; | |
| 2331 const CSSParserToken& percentageArg = args.consumeIncludingWhitespace(); | |
| 2332 if (percentageArg.type() == PercentageToken) | |
| 2333 percentage = CSSPrimitiveValue::create(clampTo<double>(percentageArg.num
ericValue() / 100, 0, 1), CSSPrimitiveValue::UnitType::Number); | |
| 2334 else if (percentageArg.type() == NumberToken) | |
| 2335 percentage = CSSPrimitiveValue::create(clampTo<double>(percentageArg.num
ericValue(), 0, 1), CSSPrimitiveValue::UnitType::Number); | |
| 2336 | |
| 2337 if (!percentage) | |
| 2338 return nullptr; | |
| 2339 return CSSCrossfadeValue::create(fromImageValue, toImageValue, percentage); | |
| 2340 } | |
| 2341 | |
| 2342 static CSSValue* consumePaint(CSSParserTokenRange& args, CSSParserContext contex
t) | |
| 2343 { | |
| 2344 ASSERT(RuntimeEnabledFeatures::cssPaintAPIEnabled()); | |
| 2345 | |
| 2346 CSSCustomIdentValue* name = consumeCustomIdent(args); | |
| 2347 if (!name) | |
| 2348 return nullptr; | |
| 2349 | |
| 2350 return CSSPaintValue::create(name); | |
| 2351 } | |
| 2352 | |
| 2353 static CSSValue* consumeGeneratedImage(CSSParserTokenRange& range, CSSParserCont
ext context) | |
| 2354 { | |
| 2355 CSSValueID id = range.peek().functionId(); | |
| 2356 CSSParserTokenRange rangeCopy = range; | |
| 2357 CSSParserTokenRange args = consumeFunction(rangeCopy); | |
| 2358 CSSValue* result = nullptr; | |
| 2359 if (id == CSSValueRadialGradient) { | |
| 2360 result = consumeRadialGradient(args, context.mode(), NonRepeating); | |
| 2361 } else if (id == CSSValueRepeatingRadialGradient) { | |
| 2362 result = consumeRadialGradient(args, context.mode(), Repeating); | |
| 2363 } else if (id == CSSValueWebkitLinearGradient) { | |
| 2364 // FIXME: This should send a deprecation message. | |
| 2365 if (context.useCounter()) | |
| 2366 context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradie
nt); | |
| 2367 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSPr
efixedLinearGradient); | |
| 2368 } else if (id == CSSValueWebkitRepeatingLinearGradient) { | |
| 2369 // FIXME: This should send a deprecation message. | |
| 2370 if (context.useCounter()) | |
| 2371 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLin
earGradient); | |
| 2372 result = consumeLinearGradient(args, context.mode(), Repeating, CSSPrefi
xedLinearGradient); | |
| 2373 } else if (id == CSSValueRepeatingLinearGradient) { | |
| 2374 result = consumeLinearGradient(args, context.mode(), Repeating, CSSLinea
rGradient); | |
| 2375 } else if (id == CSSValueLinearGradient) { | |
| 2376 result = consumeLinearGradient(args, context.mode(), NonRepeating, CSSLi
nearGradient); | |
| 2377 } else if (id == CSSValueWebkitGradient) { | |
| 2378 // FIXME: This should send a deprecation message. | |
| 2379 if (context.useCounter()) | |
| 2380 context.useCounter()->count(UseCounter::DeprecatedWebKitGradient); | |
| 2381 result = consumeDeprecatedGradient(args, context.mode()); | |
| 2382 } else if (id == CSSValueWebkitRadialGradient) { | |
| 2383 // FIXME: This should send a deprecation message. | |
| 2384 if (context.useCounter()) | |
| 2385 context.useCounter()->count(UseCounter::DeprecatedWebKitRadialGradie
nt); | |
| 2386 result = consumeDeprecatedRadialGradient(args, context.mode(), NonRepeat
ing); | |
| 2387 } else if (id == CSSValueWebkitRepeatingRadialGradient) { | |
| 2388 if (context.useCounter()) | |
| 2389 context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingRad
ialGradient); | |
| 2390 result = consumeDeprecatedRadialGradient(args, context.mode(), Repeating
); | |
| 2391 } else if (id == CSSValueWebkitCrossFade) { | |
| 2392 result = consumeCrossFade(args, context); | |
| 2393 } else if (id == CSSValuePaint) { | |
| 2394 result = RuntimeEnabledFeatures::cssPaintAPIEnabled() ? consumePaint(arg
s, context) : nullptr; | |
| 2395 } | |
| 2396 if (!result || !args.atEnd()) | |
| 2397 return nullptr; | |
| 2398 range = rangeCopy; | |
| 2399 return result; | |
| 2400 } | |
| 2401 | |
| 2402 static bool isGeneratedImage(CSSValueID id) | |
| 2403 { | |
| 2404 return id == CSSValueLinearGradient || id == CSSValueRadialGradient | |
| 2405 || id == CSSValueRepeatingLinearGradient || id == CSSValueRepeatingRadia
lGradient | |
| 2406 || id == CSSValueWebkitLinearGradient || id == CSSValueWebkitRadialGradi
ent | |
| 2407 || id == CSSValueWebkitRepeatingLinearGradient || id == CSSValueWebkitRe
peatingRadialGradient | |
| 2408 || id == CSSValueWebkitGradient || id == CSSValueWebkitCrossFade || id =
= CSSValuePaint; | |
| 2409 } | |
| 2410 | |
| 2411 static CSSValue* consumeImage(CSSParserTokenRange& range, CSSParserContext conte
xt) | |
| 2412 { | |
| 2413 AtomicString uri = consumeUrl(range).toAtomicString(); | |
| 2414 if (!uri.isNull()) | |
| 2415 return createCSSImageValueWithReferrer(uri, context); | |
| 2416 if (range.peek().type() == FunctionToken) { | |
| 2417 CSSValueID id = range.peek().functionId(); | |
| 2418 if (id == CSSValueWebkitImageSet) | |
| 2419 return consumeImageSet(range, context); | |
| 2420 if (isGeneratedImage(id)) | |
| 2421 return consumeGeneratedImage(range, context); | |
| 2422 } | |
| 2423 return nullptr; | |
| 2424 } | |
| 2425 | |
| 2426 static CSSValue* consumeImageOrNone(CSSParserTokenRange& range, CSSParserContext
context) | |
| 2427 { | |
| 2428 if (range.peek().id() == CSSValueNone) | |
| 2429 return consumeIdent(range); | |
| 2430 return consumeImage(range, context); | |
| 2431 } | |
| 2432 | |
| 2433 static CSSValue* consumeAttr(CSSParserTokenRange args, CSSParserContext context) | 1964 static CSSValue* consumeAttr(CSSParserTokenRange args, CSSParserContext context) |
| 2434 { | 1965 { |
| 2435 if (args.peek().type() != IdentToken) | 1966 if (args.peek().type() != IdentToken) |
| 2436 return nullptr; | 1967 return nullptr; |
| 2437 | 1968 |
| 2438 String attrName = args.consumeIncludingWhitespace().value().toString(); | 1969 String attrName = args.consumeIncludingWhitespace().value().toString(); |
| 2439 if (!args.atEnd()) | 1970 if (!args.atEnd()) |
| 2440 return nullptr; | 1971 return nullptr; |
| 2441 | 1972 |
| 2442 if (context.isHTMLDocument()) | 1973 if (context.isHTMLDocument()) |
| (...skipping 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5166 case CSSPropertyGridTemplate: | 4697 case CSSPropertyGridTemplate: |
| 5167 return consumeGridTemplateShorthand(CSSPropertyGridTemplate, important); | 4698 return consumeGridTemplateShorthand(CSSPropertyGridTemplate, important); |
| 5168 case CSSPropertyGrid: | 4699 case CSSPropertyGrid: |
| 5169 return consumeGridShorthand(important); | 4700 return consumeGridShorthand(important); |
| 5170 default: | 4701 default: |
| 5171 return false; | 4702 return false; |
| 5172 } | 4703 } |
| 5173 } | 4704 } |
| 5174 | 4705 |
| 5175 } // namespace blink | 4706 } // namespace blink |
| OLD | NEW |