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 |