| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/CSSPropertyParserHelpers.h" | 5 #include "core/css/parser/CSSPropertyParserHelpers.h" |
| 6 | 6 |
| 7 #include "core/css/CSSCalculationValue.h" | 7 #include "core/css/CSSCalculationValue.h" |
| 8 #include "core/css/CSSStringValue.h" | 8 #include "core/css/CSSStringValue.h" |
| 9 #include "core/css/CSSValuePair.h" | 9 #include "core/css/CSSValuePair.h" |
| 10 // TODO(timloh): Remove this dependency | 10 // TODO(timloh): Remove this dependency |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 explicit CalcParser(CSSParserTokenRange& range, ValueRange valueRange = Valu
eRangeAll) | 49 explicit CalcParser(CSSParserTokenRange& range, ValueRange valueRange = Valu
eRangeAll) |
| 50 : m_sourceRange(range) | 50 : m_sourceRange(range) |
| 51 , m_range(range) | 51 , m_range(range) |
| 52 { | 52 { |
| 53 const CSSParserToken& token = range.peek(); | 53 const CSSParserToken& token = range.peek(); |
| 54 if (token.functionId() == CSSValueCalc || token.functionId() == CSSValue
WebkitCalc) | 54 if (token.functionId() == CSSValueCalc || token.functionId() == CSSValue
WebkitCalc) |
| 55 m_calcValue = CSSCalcValue::create(consumeFunction(m_range), valueRa
nge); | 55 m_calcValue = CSSCalcValue::create(consumeFunction(m_range), valueRa
nge); |
| 56 } | 56 } |
| 57 | 57 |
| 58 const CSSCalcValue* value() const { return m_calcValue.get(); } | 58 const CSSCalcValue* value() const { return m_calcValue.get(); } |
| 59 RawPtr<CSSPrimitiveValue> consumeValue() | 59 CSSPrimitiveValue* consumeValue() |
| 60 { | 60 { |
| 61 if (!m_calcValue) | 61 if (!m_calcValue) |
| 62 return nullptr; | 62 return nullptr; |
| 63 m_sourceRange = m_range; | 63 m_sourceRange = m_range; |
| 64 return CSSPrimitiveValue::create(m_calcValue.release()); | 64 return CSSPrimitiveValue::create(m_calcValue.release()); |
| 65 } | 65 } |
| 66 RawPtr<CSSPrimitiveValue> consumeNumber() | 66 CSSPrimitiveValue* consumeNumber() |
| 67 { | 67 { |
| 68 if (!m_calcValue) | 68 if (!m_calcValue) |
| 69 return nullptr; | 69 return nullptr; |
| 70 m_sourceRange = m_range; | 70 m_sourceRange = m_range; |
| 71 CSSPrimitiveValue::UnitType unitType = m_calcValue->isInt() ? CSSPrimiti
veValue::UnitType::Integer : CSSPrimitiveValue::UnitType::Number; | 71 CSSPrimitiveValue::UnitType unitType = m_calcValue->isInt() ? CSSPrimiti
veValue::UnitType::Integer : CSSPrimitiveValue::UnitType::Number; |
| 72 return cssValuePool().createValue(m_calcValue->doubleValue(), unitType); | 72 return cssValuePool().createValue(m_calcValue->doubleValue(), unitType); |
| 73 } | 73 } |
| 74 | 74 |
| 75 bool consumeNumberRaw(double& result) | 75 bool consumeNumberRaw(double& result) |
| 76 { | 76 { |
| 77 if (!m_calcValue || m_calcValue->category() != CalcNumber) | 77 if (!m_calcValue || m_calcValue->category() != CalcNumber) |
| 78 return false; | 78 return false; |
| 79 m_sourceRange = m_range; | 79 m_sourceRange = m_range; |
| 80 result = m_calcValue->doubleValue(); | 80 result = m_calcValue->doubleValue(); |
| 81 return true; | 81 return true; |
| 82 } | 82 } |
| 83 | 83 |
| 84 private: | 84 private: |
| 85 CSSParserTokenRange& m_sourceRange; | 85 CSSParserTokenRange& m_sourceRange; |
| 86 CSSParserTokenRange m_range; | 86 CSSParserTokenRange m_range; |
| 87 Member<CSSCalcValue> m_calcValue; | 87 Member<CSSCalcValue> m_calcValue; |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 RawPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double mini
mumValue) | 90 CSSPrimitiveValue* consumeInteger(CSSParserTokenRange& range, double minimumValu
e) |
| 91 { | 91 { |
| 92 const CSSParserToken& token = range.peek(); | 92 const CSSParserToken& token = range.peek(); |
| 93 if (token.type() == NumberToken) { | 93 if (token.type() == NumberToken) { |
| 94 if (token.numericValueType() == NumberValueType || token.numericValue()
< minimumValue) | 94 if (token.numericValueType() == NumberValueType || token.numericValue()
< minimumValue) |
| 95 return nullptr; | 95 return nullptr; |
| 96 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), CSSPrimitiveValue::UnitType::Integer); | 96 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), CSSPrimitiveValue::UnitType::Integer); |
| 97 } | 97 } |
| 98 CalcParser calcParser(range); | 98 CalcParser calcParser(range); |
| 99 if (const CSSCalcValue* calculation = calcParser.value()) { | 99 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 100 if (calculation->category() != CalcNumber || !calculation->isInt()) | 100 if (calculation->category() != CalcNumber || !calculation->isInt()) |
| 101 return nullptr; | 101 return nullptr; |
| 102 double value = calculation->doubleValue(); | 102 double value = calculation->doubleValue(); |
| 103 if (value < minimumValue) | 103 if (value < minimumValue) |
| 104 return nullptr; | 104 return nullptr; |
| 105 return calcParser.consumeNumber(); | 105 return calcParser.consumeNumber(); |
| 106 } | 106 } |
| 107 return nullptr; | 107 return nullptr; |
| 108 } | 108 } |
| 109 | 109 |
| 110 RawPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange& range) | 110 CSSPrimitiveValue* consumePositiveInteger(CSSParserTokenRange& range) |
| 111 { | 111 { |
| 112 return consumeInteger(range, 1); | 112 return consumeInteger(range, 1); |
| 113 } | 113 } |
| 114 | 114 |
| 115 bool consumeNumberRaw(CSSParserTokenRange& range, double& result) | 115 bool consumeNumberRaw(CSSParserTokenRange& range, double& result) |
| 116 { | 116 { |
| 117 if (range.peek().type() == NumberToken) { | 117 if (range.peek().type() == NumberToken) { |
| 118 result = range.consumeIncludingWhitespace().numericValue(); | 118 result = range.consumeIncludingWhitespace().numericValue(); |
| 119 return true; | 119 return true; |
| 120 } | 120 } |
| 121 CalcParser calcParser(range, ValueRangeAll); | 121 CalcParser calcParser(range, ValueRangeAll); |
| 122 return calcParser.consumeNumberRaw(result); | 122 return calcParser.consumeNumberRaw(result); |
| 123 } | 123 } |
| 124 | 124 |
| 125 // TODO(timloh): Work out if this can just call consumeNumberRaw | 125 // TODO(timloh): Work out if this can just call consumeNumberRaw |
| 126 RawPtr<CSSPrimitiveValue> consumeNumber(CSSParserTokenRange& range, ValueRange v
alueRange) | 126 CSSPrimitiveValue* consumeNumber(CSSParserTokenRange& range, ValueRange valueRan
ge) |
| 127 { | 127 { |
| 128 const CSSParserToken& token = range.peek(); | 128 const CSSParserToken& token = range.peek(); |
| 129 if (token.type() == NumberToken) { | 129 if (token.type() == NumberToken) { |
| 130 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) | 130 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) |
| 131 return nullptr; | 131 return nullptr; |
| 132 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), token.unitType()); | 132 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), token.unitType()); |
| 133 } | 133 } |
| 134 CalcParser calcParser(range, ValueRangeAll); | 134 CalcParser calcParser(range, ValueRangeAll); |
| 135 if (const CSSCalcValue* calculation = calcParser.value()) { | 135 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 136 // TODO(rwlbuis) Calcs should not be subject to parse time range checks. | 136 // TODO(rwlbuis) Calcs should not be subject to parse time range checks. |
| 137 // spec: https://drafts.csswg.org/css-values-3/#calc-range | 137 // spec: https://drafts.csswg.org/css-values-3/#calc-range |
| 138 if (calculation->category() != CalcNumber || (valueRange == ValueRangeNo
nNegative && calculation->isNegative())) | 138 if (calculation->category() != CalcNumber || (valueRange == ValueRangeNo
nNegative && calculation->isNegative())) |
| 139 return nullptr; | 139 return nullptr; |
| 140 return calcParser.consumeNumber(); | 140 return calcParser.consumeNumber(); |
| 141 } | 141 } |
| 142 return nullptr; | 142 return nullptr; |
| 143 } | 143 } |
| 144 | 144 |
| 145 inline bool shouldAcceptUnitlessLength(double value, CSSParserMode cssParserMode
, UnitlessQuirk unitless) | 145 inline bool shouldAcceptUnitlessLength(double value, CSSParserMode cssParserMode
, UnitlessQuirk unitless) |
| 146 { | 146 { |
| 147 // TODO(timloh): Presentational HTML attributes shouldn't use the CSS parser
for lengths | 147 // TODO(timloh): Presentational HTML attributes shouldn't use the CSS parser
for lengths |
| 148 return value == 0 | 148 return value == 0 |
| 149 || isUnitLessLengthParsingEnabledForMode(cssParserMode) | 149 || isUnitLessLengthParsingEnabledForMode(cssParserMode) |
| 150 || (cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow)
; | 150 || (cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow)
; |
| 151 } | 151 } |
| 152 | 152 |
| 153 RawPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMod
e cssParserMode, ValueRange valueRange, UnitlessQuirk unitless) | 153 CSSPrimitiveValue* consumeLength(CSSParserTokenRange& range, CSSParserMode cssPa
rserMode, ValueRange valueRange, UnitlessQuirk unitless) |
| 154 { | 154 { |
| 155 const CSSParserToken& token = range.peek(); | 155 const CSSParserToken& token = range.peek(); |
| 156 if (token.type() == DimensionToken) { | 156 if (token.type() == DimensionToken) { |
| 157 switch (token.unitType()) { | 157 switch (token.unitType()) { |
| 158 case CSSPrimitiveValue::UnitType::QuirkyEms: | 158 case CSSPrimitiveValue::UnitType::QuirkyEms: |
| 159 if (cssParserMode != UASheetMode) | 159 if (cssParserMode != UASheetMode) |
| 160 return nullptr; | 160 return nullptr; |
| 161 /* fallthrough intentional */ | 161 /* fallthrough intentional */ |
| 162 case CSSPrimitiveValue::UnitType::Ems: | 162 case CSSPrimitiveValue::UnitType::Ems: |
| 163 case CSSPrimitiveValue::UnitType::Rems: | 163 case CSSPrimitiveValue::UnitType::Rems: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 192 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), unitType); | 192 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), unitType); |
| 193 } | 193 } |
| 194 if (cssParserMode == SVGAttributeMode) | 194 if (cssParserMode == SVGAttributeMode) |
| 195 return nullptr; | 195 return nullptr; |
| 196 CalcParser calcParser(range, valueRange); | 196 CalcParser calcParser(range, valueRange); |
| 197 if (calcParser.value() && calcParser.value()->category() == CalcLength) | 197 if (calcParser.value() && calcParser.value()->category() == CalcLength) |
| 198 return calcParser.consumeValue(); | 198 return calcParser.consumeValue(); |
| 199 return nullptr; | 199 return nullptr; |
| 200 } | 200 } |
| 201 | 201 |
| 202 RawPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange& range, ValueRange
valueRange) | 202 CSSPrimitiveValue* consumePercent(CSSParserTokenRange& range, ValueRange valueRa
nge) |
| 203 { | 203 { |
| 204 const CSSParserToken& token = range.peek(); | 204 const CSSParserToken& token = range.peek(); |
| 205 if (token.type() == PercentageToken) { | 205 if (token.type() == PercentageToken) { |
| 206 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) | 206 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) |
| 207 return nullptr; | 207 return nullptr; |
| 208 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), CSSPrimitiveValue::UnitType::Percentage); | 208 return cssValuePool().createValue(range.consumeIncludingWhitespace().num
ericValue(), CSSPrimitiveValue::UnitType::Percentage); |
| 209 } | 209 } |
| 210 CalcParser calcParser(range, valueRange); | 210 CalcParser calcParser(range, valueRange); |
| 211 if (const CSSCalcValue* calculation = calcParser.value()) { | 211 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 212 if (calculation->category() == CalcPercent) | 212 if (calculation->category() == CalcPercent) |
| 213 return calcParser.consumeValue(); | 213 return calcParser.consumeValue(); |
| 214 } | 214 } |
| 215 return nullptr; | 215 return nullptr; |
| 216 } | 216 } |
| 217 | 217 |
| 218 RawPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSS
ParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless) | 218 CSSPrimitiveValue* consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserM
ode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless) |
| 219 { | 219 { |
| 220 const CSSParserToken& token = range.peek(); | 220 const CSSParserToken& token = range.peek(); |
| 221 if (token.type() == DimensionToken || token.type() == NumberToken) | 221 if (token.type() == DimensionToken || token.type() == NumberToken) |
| 222 return consumeLength(range, cssParserMode, valueRange, unitless); | 222 return consumeLength(range, cssParserMode, valueRange, unitless); |
| 223 if (token.type() == PercentageToken) | 223 if (token.type() == PercentageToken) |
| 224 return consumePercent(range, valueRange); | 224 return consumePercent(range, valueRange); |
| 225 CalcParser calcParser(range, valueRange); | 225 CalcParser calcParser(range, valueRange); |
| 226 if (const CSSCalcValue* calculation = calcParser.value()) { | 226 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 227 if (calculation->category() == CalcLength || calculation->category() ==
CalcPercent || calculation->category() == CalcPercentLength) | 227 if (calculation->category() == CalcLength || calculation->category() ==
CalcPercent || calculation->category() == CalcPercentLength) |
| 228 return calcParser.consumeValue(); | 228 return calcParser.consumeValue(); |
| 229 } | 229 } |
| 230 return nullptr; | 230 return nullptr; |
| 231 } | 231 } |
| 232 | 232 |
| 233 RawPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range) | 233 CSSPrimitiveValue* consumeAngle(CSSParserTokenRange& range) |
| 234 { | 234 { |
| 235 const CSSParserToken& token = range.peek(); | 235 const CSSParserToken& token = range.peek(); |
| 236 if (token.type() == DimensionToken) { | 236 if (token.type() == DimensionToken) { |
| 237 switch (token.unitType()) { | 237 switch (token.unitType()) { |
| 238 case CSSPrimitiveValue::UnitType::Degrees: | 238 case CSSPrimitiveValue::UnitType::Degrees: |
| 239 case CSSPrimitiveValue::UnitType::Radians: | 239 case CSSPrimitiveValue::UnitType::Radians: |
| 240 case CSSPrimitiveValue::UnitType::Gradians: | 240 case CSSPrimitiveValue::UnitType::Gradians: |
| 241 case CSSPrimitiveValue::UnitType::Turns: | 241 case CSSPrimitiveValue::UnitType::Turns: |
| 242 return cssValuePool().createValue(range.consumeIncludingWhitespace()
.numericValue(), token.unitType()); | 242 return cssValuePool().createValue(range.consumeIncludingWhitespace()
.numericValue(), token.unitType()); |
| 243 default: | 243 default: |
| 244 return nullptr; | 244 return nullptr; |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 if (token.type() == NumberToken && token.numericValue() == 0) { | 247 if (token.type() == NumberToken && token.numericValue() == 0) { |
| 248 range.consumeIncludingWhitespace(); | 248 range.consumeIncludingWhitespace(); |
| 249 return cssValuePool().createValue(0, CSSPrimitiveValue::UnitType::Degree
s); | 249 return cssValuePool().createValue(0, CSSPrimitiveValue::UnitType::Degree
s); |
| 250 } | 250 } |
| 251 CalcParser calcParser(range, ValueRangeAll); | 251 CalcParser calcParser(range, ValueRangeAll); |
| 252 if (const CSSCalcValue* calculation = calcParser.value()) { | 252 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 253 if (calculation->category() == CalcAngle) | 253 if (calculation->category() == CalcAngle) |
| 254 return calcParser.consumeValue(); | 254 return calcParser.consumeValue(); |
| 255 } | 255 } |
| 256 return nullptr; | 256 return nullptr; |
| 257 } | 257 } |
| 258 | 258 |
| 259 RawPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange& range, ValueRange val
ueRange) | 259 CSSPrimitiveValue* consumeTime(CSSParserTokenRange& range, ValueRange valueRange
) |
| 260 { | 260 { |
| 261 const CSSParserToken& token = range.peek(); | 261 const CSSParserToken& token = range.peek(); |
| 262 if (token.type() == DimensionToken) { | 262 if (token.type() == DimensionToken) { |
| 263 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) | 263 if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) |
| 264 return nullptr; | 264 return nullptr; |
| 265 CSSPrimitiveValue::UnitType unit = token.unitType(); | 265 CSSPrimitiveValue::UnitType unit = token.unitType(); |
| 266 if (unit == CSSPrimitiveValue::UnitType::Milliseconds || unit == CSSPrim
itiveValue::UnitType::Seconds) | 266 if (unit == CSSPrimitiveValue::UnitType::Milliseconds || unit == CSSPrim
itiveValue::UnitType::Seconds) |
| 267 return cssValuePool().createValue(range.consumeIncludingWhitespace()
.numericValue(), token.unitType()); | 267 return cssValuePool().createValue(range.consumeIncludingWhitespace()
.numericValue(), token.unitType()); |
| 268 return nullptr; | 268 return nullptr; |
| 269 } | 269 } |
| 270 CalcParser calcParser(range, valueRange); | 270 CalcParser calcParser(range, valueRange); |
| 271 if (const CSSCalcValue* calculation = calcParser.value()) { | 271 if (const CSSCalcValue* calculation = calcParser.value()) { |
| 272 if (calculation->category() == CalcTime) | 272 if (calculation->category() == CalcTime) |
| 273 return calcParser.consumeValue(); | 273 return calcParser.consumeValue(); |
| 274 } | 274 } |
| 275 return nullptr; | 275 return nullptr; |
| 276 } | 276 } |
| 277 | 277 |
| 278 RawPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange& range) | 278 CSSPrimitiveValue* consumeIdent(CSSParserTokenRange& range) |
| 279 { | 279 { |
| 280 if (range.peek().type() != IdentToken) | 280 if (range.peek().type() != IdentToken) |
| 281 return nullptr; | 281 return nullptr; |
| 282 return cssValuePool().createIdentifierValue(range.consumeIncludingWhitespace
().id()); | 282 return cssValuePool().createIdentifierValue(range.consumeIncludingWhitespace
().id()); |
| 283 } | 283 } |
| 284 | 284 |
| 285 RawPtr<CSSPrimitiveValue> consumeIdentRange(CSSParserTokenRange& range, CSSValue
ID lower, CSSValueID upper) | 285 CSSPrimitiveValue* consumeIdentRange(CSSParserTokenRange& range, CSSValueID lowe
r, CSSValueID upper) |
| 286 { | 286 { |
| 287 if (range.peek().id() < lower || range.peek().id() > upper) | 287 if (range.peek().id() < lower || range.peek().id() > upper) |
| 288 return nullptr; | 288 return nullptr; |
| 289 return consumeIdent(range); | 289 return consumeIdent(range); |
| 290 } | 290 } |
| 291 | 291 |
| 292 RawPtr<CSSCustomIdentValue> consumeCustomIdent(CSSParserTokenRange& range) | 292 CSSCustomIdentValue* consumeCustomIdent(CSSParserTokenRange& range) |
| 293 { | 293 { |
| 294 if (range.peek().type() != IdentToken || isCSSWideKeyword(range.peek().id())
) | 294 if (range.peek().type() != IdentToken || isCSSWideKeyword(range.peek().id())
) |
| 295 return nullptr; | 295 return nullptr; |
| 296 return CSSCustomIdentValue::create(range.consumeIncludingWhitespace().value(
)); | 296 return CSSCustomIdentValue::create(range.consumeIncludingWhitespace().value(
)); |
| 297 } | 297 } |
| 298 | 298 |
| 299 RawPtr<CSSStringValue> consumeString(CSSParserTokenRange& range) | 299 CSSStringValue* consumeString(CSSParserTokenRange& range) |
| 300 { | 300 { |
| 301 if (range.peek().type() != StringToken) | 301 if (range.peek().type() != StringToken) |
| 302 return nullptr; | 302 return nullptr; |
| 303 return CSSStringValue::create(range.consumeIncludingWhitespace().value()); | 303 return CSSStringValue::create(range.consumeIncludingWhitespace().value()); |
| 304 } | 304 } |
| 305 | 305 |
| 306 String consumeUrl(CSSParserTokenRange& range) | 306 String consumeUrl(CSSParserTokenRange& range) |
| 307 { | 307 { |
| 308 const CSSParserToken& token = range.peek(); | 308 const CSSParserToken& token = range.peek(); |
| 309 if (token.type() == UrlToken) { | 309 if (token.type() == UrlToken) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 331 // TODO(timloh): Multiply by 2.55 and round instead of floor. | 331 // TODO(timloh): Multiply by 2.55 and round instead of floor. |
| 332 if (value.isPercentage()) | 332 if (value.isPercentage()) |
| 333 result *= 2.56; | 333 result *= 2.56; |
| 334 return clampTo<int>(result, 0, 255); | 334 return clampTo<int>(result, 0, 255); |
| 335 } | 335 } |
| 336 | 336 |
| 337 static bool parseRGBParameters(CSSParserTokenRange& range, RGBA32& result, bool
parseAlpha) | 337 static bool parseRGBParameters(CSSParserTokenRange& range, RGBA32& result, bool
parseAlpha) |
| 338 { | 338 { |
| 339 ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId()
== CSSValueRgba); | 339 ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId()
== CSSValueRgba); |
| 340 CSSParserTokenRange args = consumeFunction(range); | 340 CSSParserTokenRange args = consumeFunction(range); |
| 341 RawPtr<CSSPrimitiveValue> colorParameter = consumeInteger(args); | 341 CSSPrimitiveValue* colorParameter = consumeInteger(args); |
| 342 if (!colorParameter) | 342 if (!colorParameter) |
| 343 colorParameter = consumePercent(args, ValueRangeAll); | 343 colorParameter = consumePercent(args, ValueRangeAll); |
| 344 if (!colorParameter) | 344 if (!colorParameter) |
| 345 return false; | 345 return false; |
| 346 const bool isPercent = colorParameter->isPercentage(); | 346 const bool isPercent = colorParameter->isPercentage(); |
| 347 int colorArray[3]; | 347 int colorArray[3]; |
| 348 colorArray[0] = clampRGBComponent(*colorParameter); | 348 colorArray[0] = clampRGBComponent(*colorParameter); |
| 349 for (int i = 1; i < 3; i++) { | 349 for (int i = 1; i < 3; i++) { |
| 350 if (!consumeCommaIncludingWhitespace(args)) | 350 if (!consumeCommaIncludingWhitespace(args)) |
| 351 return false; | 351 return false; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 367 } else { | 367 } else { |
| 368 result = makeRGB(colorArray[0], colorArray[1], colorArray[2]); | 368 result = makeRGB(colorArray[0], colorArray[1], colorArray[2]); |
| 369 } | 369 } |
| 370 return args.atEnd(); | 370 return args.atEnd(); |
| 371 } | 371 } |
| 372 | 372 |
| 373 static bool parseHSLParameters(CSSParserTokenRange& range, RGBA32& result, bool
parseAlpha) | 373 static bool parseHSLParameters(CSSParserTokenRange& range, RGBA32& result, bool
parseAlpha) |
| 374 { | 374 { |
| 375 ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId()
== CSSValueHsla); | 375 ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId()
== CSSValueHsla); |
| 376 CSSParserTokenRange args = consumeFunction(range); | 376 CSSParserTokenRange args = consumeFunction(range); |
| 377 RawPtr<CSSPrimitiveValue> hslValue = consumeNumber(args, ValueRangeAll); | 377 CSSPrimitiveValue* hslValue = consumeNumber(args, ValueRangeAll); |
| 378 if (!hslValue) | 378 if (!hslValue) |
| 379 return false; | 379 return false; |
| 380 double colorArray[3]; | 380 double colorArray[3]; |
| 381 colorArray[0] = (((hslValue->getIntValue() % 360) + 360) % 360) / 360.0; | 381 colorArray[0] = (((hslValue->getIntValue() % 360) + 360) % 360) / 360.0; |
| 382 for (int i = 1; i < 3; i++) { | 382 for (int i = 1; i < 3; i++) { |
| 383 if (!consumeCommaIncludingWhitespace(args)) | 383 if (!consumeCommaIncludingWhitespace(args)) |
| 384 return false; | 384 return false; |
| 385 hslValue = consumePercent(args, ValueRangeAll); | 385 hslValue = consumePercent(args, ValueRangeAll); |
| 386 if (!hslValue) | 386 if (!hslValue) |
| 387 return false; | 387 return false; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 if (functionId < CSSValueRgb || functionId > CSSValueHsla) | 433 if (functionId < CSSValueRgb || functionId > CSSValueHsla) |
| 434 return false; | 434 return false; |
| 435 CSSParserTokenRange colorRange = range; | 435 CSSParserTokenRange colorRange = range; |
| 436 if ((functionId <= CSSValueRgba && !parseRGBParameters(colorRange, result, f
unctionId == CSSValueRgba)) | 436 if ((functionId <= CSSValueRgba && !parseRGBParameters(colorRange, result, f
unctionId == CSSValueRgba)) |
| 437 || (functionId >= CSSValueHsl && !parseHSLParameters(colorRange, result,
functionId == CSSValueHsla))) | 437 || (functionId >= CSSValueHsl && !parseHSLParameters(colorRange, result,
functionId == CSSValueHsla))) |
| 438 return false; | 438 return false; |
| 439 range = colorRange; | 439 range = colorRange; |
| 440 return true; | 440 return true; |
| 441 } | 441 } |
| 442 | 442 |
| 443 RawPtr<CSSValue> consumeColor(CSSParserTokenRange& range, CSSParserMode cssParse
rMode, bool acceptQuirkyColors) | 443 CSSValue* consumeColor(CSSParserTokenRange& range, CSSParserMode cssParserMode,
bool acceptQuirkyColors) |
| 444 { | 444 { |
| 445 CSSValueID id = range.peek().id(); | 445 CSSValueID id = range.peek().id(); |
| 446 if (CSSPropertyParser::isColorKeyword(id)) { | 446 if (CSSPropertyParser::isColorKeyword(id)) { |
| 447 if (!isValueAllowedInMode(id, cssParserMode)) | 447 if (!isValueAllowedInMode(id, cssParserMode)) |
| 448 return nullptr; | 448 return nullptr; |
| 449 return consumeIdent(range); | 449 return consumeIdent(range); |
| 450 } | 450 } |
| 451 RGBA32 color = Color::transparent; | 451 RGBA32 color = Color::transparent; |
| 452 if (!parseHexColor(range, color, acceptQuirkyColors) && !parseColorFunction(
range, color)) | 452 if (!parseHexColor(range, color, acceptQuirkyColors) && !parseColorFunction(
range, color)) |
| 453 return nullptr; | 453 return nullptr; |
| 454 return cssValuePool().createColorValue(color); | 454 return cssValuePool().createColorValue(color); |
| 455 } | 455 } |
| 456 | 456 |
| 457 static RawPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& r
ange, CSSParserMode cssParserMode, UnitlessQuirk unitless) | 457 static CSSPrimitiveValue* consumePositionComponent(CSSParserTokenRange& range, C
SSParserMode cssParserMode, UnitlessQuirk unitless) |
| 458 { | 458 { |
| 459 if (range.peek().type() == IdentToken) | 459 if (range.peek().type() == IdentToken) |
| 460 return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueR
ight, CSSValueCenter>(range); | 460 return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueR
ight, CSSValueCenter>(range); |
| 461 return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless)
; | 461 return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless)
; |
| 462 } | 462 } |
| 463 | 463 |
| 464 static bool isHorizontalPositionKeywordOnly(const CSSPrimitiveValue& value) | 464 static bool isHorizontalPositionKeywordOnly(const CSSPrimitiveValue& value) |
| 465 { | 465 { |
| 466 return value.isValueID() && (value.getValueID() == CSSValueLeft || value.get
ValueID() == CSSValueRight); | 466 return value.isValueID() && (value.getValueID() == CSSValueLeft || value.get
ValueID() == CSSValueRight); |
| 467 } | 467 } |
| 468 | 468 |
| 469 static bool isVerticalPositionKeywordOnly(const CSSPrimitiveValue& value) | 469 static bool isVerticalPositionKeywordOnly(const CSSPrimitiveValue& value) |
| 470 { | 470 { |
| 471 return value.isValueID() && (value.getValueID() == CSSValueTop || value.getV
alueID() == CSSValueBottom); | 471 return value.isValueID() && (value.getValueID() == CSSValueTop || value.getV
alueID() == CSSValueBottom); |
| 472 } | 472 } |
| 473 | 473 |
| 474 static void positionFromOneValue(RawPtr<CSSPrimitiveValue> value, RawPtr<CSSValu
e>& resultX, RawPtr<CSSValue>& resultY) | 474 static void positionFromOneValue(CSSPrimitiveValue* value, CSSValue*& resultX, C
SSValue*& resultY) |
| 475 { | 475 { |
| 476 bool valueAppliesToYAxisOnly = isVerticalPositionKeywordOnly(*value); | 476 bool valueAppliesToYAxisOnly = isVerticalPositionKeywordOnly(*value); |
| 477 resultX = value; | 477 resultX = value; |
| 478 resultY = cssValuePool().createIdentifierValue(CSSValueCenter); | 478 resultY = cssValuePool().createIdentifierValue(CSSValueCenter); |
| 479 if (valueAppliesToYAxisOnly) | 479 if (valueAppliesToYAxisOnly) |
| 480 swap(resultX, resultY); | 480 std::swap(resultX, resultY); |
| 481 } | 481 } |
| 482 | 482 |
| 483 static bool positionFromTwoValues(RawPtr<CSSPrimitiveValue> value1, RawPtr<CSSPr
imitiveValue> value2, | 483 static bool positionFromTwoValues(CSSPrimitiveValue* value1, CSSPrimitiveValue*
value2, |
| 484 RawPtr<CSSValue>& resultX, RawPtr<CSSValue>& resultY) | 484 CSSValue*& resultX, CSSValue*& resultY) |
| 485 { | 485 { |
| 486 bool mustOrderAsXY = isHorizontalPositionKeywordOnly(*value1) || isVerticalP
ositionKeywordOnly(*value2) | 486 bool mustOrderAsXY = isHorizontalPositionKeywordOnly(*value1) || isVerticalP
ositionKeywordOnly(*value2) |
| 487 || !value1->isValueID() || !value2->isValueID(); | 487 || !value1->isValueID() || !value2->isValueID(); |
| 488 bool mustOrderAsYX = isVerticalPositionKeywordOnly(*value1) || isHorizontalP
ositionKeywordOnly(*value2); | 488 bool mustOrderAsYX = isVerticalPositionKeywordOnly(*value1) || isHorizontalP
ositionKeywordOnly(*value2); |
| 489 if (mustOrderAsXY && mustOrderAsYX) | 489 if (mustOrderAsXY && mustOrderAsYX) |
| 490 return false; | 490 return false; |
| 491 resultX = value1; | 491 resultX = value1; |
| 492 resultY = value2; | 492 resultY = value2; |
| 493 if (mustOrderAsYX) | 493 if (mustOrderAsYX) |
| 494 swap(resultX, resultY); | 494 std::swap(resultX, resultY); |
| 495 return true; | 495 return true; |
| 496 } | 496 } |
| 497 | 497 |
| 498 static bool positionFromThreeOrFourValues(CSSPrimitiveValue** values, RawPtr<CSS
Value>& resultX, RawPtr<CSSValue>& resultY) | 498 static bool positionFromThreeOrFourValues(CSSPrimitiveValue** values, CSSValue*&
resultX, CSSValue*& resultY) |
| 499 { | 499 { |
| 500 CSSPrimitiveValue* center = nullptr; | 500 CSSPrimitiveValue* center = nullptr; |
| 501 for (int i = 0; values[i]; i++) { | 501 for (int i = 0; values[i]; i++) { |
| 502 CSSPrimitiveValue* currentValue = values[i]; | 502 CSSPrimitiveValue* currentValue = values[i]; |
| 503 if (!currentValue->isValueID()) | 503 if (!currentValue->isValueID()) |
| 504 return false; | 504 return false; |
| 505 CSSValueID id = currentValue->getValueID(); | 505 CSSValueID id = currentValue->getValueID(); |
| 506 | 506 |
| 507 if (id == CSSValueCenter) { | 507 if (id == CSSValueCenter) { |
| 508 if (center) | 508 if (center) |
| 509 return false; | 509 return false; |
| 510 center = currentValue; | 510 center = currentValue; |
| 511 continue; | 511 continue; |
| 512 } | 512 } |
| 513 | 513 |
| 514 RawPtr<CSSValue> result = nullptr; | 514 CSSValue* result = nullptr; |
| 515 if (values[i + 1] && !values[i + 1]->isValueID()) { | 515 if (values[i + 1] && !values[i + 1]->isValueID()) { |
| 516 result = CSSValuePair::create(currentValue, values[++i], CSSValuePai
r::KeepIdenticalValues); | 516 result = CSSValuePair::create(currentValue, values[++i], CSSValuePai
r::KeepIdenticalValues); |
| 517 } else { | 517 } else { |
| 518 result = currentValue; | 518 result = currentValue; |
| 519 } | 519 } |
| 520 | 520 |
| 521 if (id == CSSValueLeft || id == CSSValueRight) { | 521 if (id == CSSValueLeft || id == CSSValueRight) { |
| 522 if (resultX) | 522 if (resultX) |
| 523 return false; | 523 return false; |
| 524 resultX = result.release(); | 524 resultX = result; |
| 525 } else { | 525 } else { |
| 526 ASSERT(id == CSSValueTop || id == CSSValueBottom); | 526 ASSERT(id == CSSValueTop || id == CSSValueBottom); |
| 527 if (resultY) | 527 if (resultY) |
| 528 return false; | 528 return false; |
| 529 resultY = result.release(); | 529 resultY = result; |
| 530 } | 530 } |
| 531 } | 531 } |
| 532 | 532 |
| 533 if (center) { | 533 if (center) { |
| 534 ASSERT(resultX || resultY); | 534 ASSERT(resultX || resultY); |
| 535 if (resultX && resultY) | 535 if (resultX && resultY) |
| 536 return false; | 536 return false; |
| 537 if (!resultX) | 537 if (!resultX) |
| 538 resultX = center; | 538 resultX = center; |
| 539 else | 539 else |
| 540 resultY = center; | 540 resultY = center; |
| 541 } | 541 } |
| 542 | 542 |
| 543 ASSERT(resultX && resultY); | 543 ASSERT(resultX && resultY); |
| 544 return true; | 544 return true; |
| 545 } | 545 } |
| 546 | 546 |
| 547 // TODO(timloh): This may consume from the range upon failure. The background | 547 // TODO(timloh): This may consume from the range upon failure. The background |
| 548 // shorthand works around it, but we should just fix it here. | 548 // shorthand works around it, but we should just fix it here. |
| 549 bool consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, Un
itlessQuirk unitless, RawPtr<CSSValue>& resultX, RawPtr<CSSValue>& resultY) | 549 bool consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, Un
itlessQuirk unitless, CSSValue*& resultX, CSSValue*& resultY) |
| 550 { | 550 { |
| 551 RawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParser
Mode, unitless); | 551 CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 552 if (!value1) | 552 if (!value1) |
| 553 return false; | 553 return false; |
| 554 | 554 |
| 555 RawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParser
Mode, unitless); | 555 CSSPrimitiveValue* value2 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 556 if (!value2) { | 556 if (!value2) { |
| 557 positionFromOneValue(value1.release(), resultX, resultY); | 557 positionFromOneValue(value1, resultX, resultY); |
| 558 return true; | 558 return true; |
| 559 } | 559 } |
| 560 | 560 |
| 561 RawPtr<CSSPrimitiveValue> value3 = consumePositionComponent(range, cssParser
Mode, unitless); | 561 CSSPrimitiveValue* value3 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 562 if (!value3) | 562 if (!value3) |
| 563 return positionFromTwoValues(value1.release(), value2.release(), resultX
, resultY); | 563 return positionFromTwoValues(value1, value2, resultX, resultY); |
| 564 | 564 |
| 565 RawPtr<CSSPrimitiveValue> value4 = consumePositionComponent(range, cssParser
Mode, unitless); | 565 CSSPrimitiveValue* value4 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 566 CSSPrimitiveValue* values[5]; | 566 CSSPrimitiveValue* values[5]; |
| 567 values[0] = value1.get(); | 567 values[0] = value1; |
| 568 values[1] = value2.get(); | 568 values[1] = value2; |
| 569 values[2] = value3.get(); | 569 values[2] = value3; |
| 570 values[3] = value4.get(); | 570 values[3] = value4; |
| 571 values[4] = nullptr; | 571 values[4] = nullptr; |
| 572 return positionFromThreeOrFourValues(values, resultX, resultY); | 572 return positionFromThreeOrFourValues(values, resultX, resultY); |
| 573 } | 573 } |
| 574 | 574 |
| 575 RawPtr<CSSValuePair> consumePosition(CSSParserTokenRange& range, CSSParserMode c
ssParserMode, UnitlessQuirk unitless) | 575 CSSValuePair* consumePosition(CSSParserTokenRange& range, CSSParserMode cssParse
rMode, UnitlessQuirk unitless) |
| 576 { | 576 { |
| 577 RawPtr<CSSValue> resultX = nullptr; | 577 CSSValue* resultX = nullptr; |
| 578 RawPtr<CSSValue> resultY = nullptr; | 578 CSSValue* resultY = nullptr; |
| 579 if (consumePosition(range, cssParserMode, unitless, resultX, resultY)) | 579 if (consumePosition(range, cssParserMode, unitless, resultX, resultY)) |
| 580 return CSSValuePair::create(resultX.release(), resultY.release(), CSSVal
uePair::KeepIdenticalValues); | 580 return CSSValuePair::create(resultX, resultY, CSSValuePair::KeepIdentica
lValues); |
| 581 return nullptr; | 581 return nullptr; |
| 582 } | 582 } |
| 583 | 583 |
| 584 bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserMode css
ParserMode, UnitlessQuirk unitless, RawPtr<CSSValue>& resultX, RawPtr<CSSValue>&
resultY) | 584 bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserMode css
ParserMode, UnitlessQuirk unitless, CSSValue*& resultX, CSSValue*& resultY) |
| 585 { | 585 { |
| 586 RawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParser
Mode, unitless); | 586 CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 587 if (!value1) | 587 if (!value1) |
| 588 return false; | 588 return false; |
| 589 RawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParser
Mode, unitless); | 589 CSSPrimitiveValue* value2 = consumePositionComponent(range, cssParserMode, u
nitless); |
| 590 if (!value2) { | 590 if (!value2) { |
| 591 positionFromOneValue(value1.release(), resultX, resultY); | 591 positionFromOneValue(value1, resultX, resultY); |
| 592 return true; | 592 return true; |
| 593 } | 593 } |
| 594 return positionFromTwoValues(value1.release(), value2.release(), resultX, re
sultY); | 594 return positionFromTwoValues(value1, value2, resultX, resultY); |
| 595 } | 595 } |
| 596 | 596 |
| 597 } // namespace CSSPropertyParserHelpers | 597 } // namespace CSSPropertyParserHelpers |
| 598 | 598 |
| 599 } // namespace blink | 599 } // namespace blink |
| OLD | NEW |