Chromium Code Reviews| 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/css/parser/CSSPropertyParser.h" | 6 #include "core/css/parser/CSSPropertyParser.h" |
| 7 | 7 |
| 8 #include "core/StylePropertyShorthand.h" | 8 #include "core/StylePropertyShorthand.h" |
| 9 #include "core/css/CSSCalculationValue.h" | 9 #include "core/css/CSSCalculationValue.h" |
| 10 #include "core/css/CSSFontFaceSrcValue.h" | |
| 11 #include "core/css/CSSFontFeatureValue.h" | |
| 12 #include "core/css/CSSUnicodeRangeValue.h" | |
| 10 #include "core/css/CSSValuePool.h" | 13 #include "core/css/CSSValuePool.h" |
| 11 #include "core/css/parser/CSSParserFastPaths.h" | 14 #include "core/css/parser/CSSParserFastPaths.h" |
| 12 #include "core/css/parser/CSSParserValues.h" | 15 #include "core/css/parser/CSSParserValues.h" |
| 13 #include "core/frame/UseCounter.h" | 16 #include "core/frame/UseCounter.h" |
| 17 #include "wtf/text/StringBuilder.h" | |
| 14 | 18 |
| 15 namespace blink { | 19 namespace blink { |
| 16 | 20 |
| 17 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, | 21 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, |
| 18 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, | 22 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, |
| 19 StyleRule::Type ruleType) | 23 StyleRule::Type ruleType) |
| 20 : m_valueList(valueList) | 24 : m_valueList(valueList) |
| 21 , m_range(range) | 25 , m_range(range) |
| 22 , m_context(context) | 26 , m_context(context) |
| 23 , m_parsedProperties(parsedProperties) | 27 , m_parsedProperties(parsedProperties) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::CustomIdentifier); | 88 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::CustomIdentifier); |
| 85 } | 89 } |
| 86 | 90 |
| 87 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan ge& range) | 91 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan ge& range) |
| 88 { | 92 { |
| 89 if (range.peek().type() != StringToken) | 93 if (range.peek().type() != StringToken) |
| 90 return nullptr; | 94 return nullptr; |
| 91 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::String); | 95 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::String); |
| 92 } | 96 } |
| 93 | 97 |
| 98 static bool tryConsumeUrl(CSSParserTokenRange& valueList, String& urlValue) | |
|
Timothy Loh
2015/09/15 02:01:05
"consumeUrl" is fine I think. Also maybe we can re
| |
| 99 { | |
| 100 const CSSParserToken& token = valueList.peek(); | |
| 101 if (token.type() == FunctionToken) { | |
| 102 if (!token.valueEqualsIgnoringCase("url")) | |
|
Timothy Loh
2015/09/15 02:01:05
functionId?
| |
| 103 return false; | |
| 104 | |
| 105 CSSParserTokenRange urlArgs = valueList.consumeBlock(); | |
| 106 const CSSParserToken& next = urlArgs.consumeIncludingWhitespace(); | |
| 107 if (next.type() == BadStringToken) | |
|
Timothy Loh
2015/09/15 02:01:05
|| EOFToken I think? (i.e. "url()")
Timothy Loh
2015/09/15 03:05:04
Whoops, url() makes a UrlToken.
| |
| 108 return false; | |
| 109 ASSERT(next.type() == StringToken); | |
| 110 urlValue = next.value(); | |
| 111 valueList.consumeWhitespace(); | |
|
Timothy Loh
2015/09/15 02:01:05
Should check whether the inner range is atEnd()
| |
| 112 return true; | |
| 113 } | |
| 114 if (token.type() == UrlToken) { | |
|
Timothy Loh
2015/09/15 02:01:05
I think it'd be nicer if this check was before the
| |
| 115 urlValue = token.value(); | |
| 116 valueList.consumeIncludingWhitespace(); | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 static CSSParserTokenRange consumeFunction(CSSParserTokenRange& valueList) | |
| 124 { | |
| 125 ASSERT(valueList.peek().type() == FunctionToken); | |
| 126 CSSParserTokenRange ret = valueList.consumeBlock(); | |
|
Timothy Loh
2015/09/15 02:01:05
ret -> result? contents?
| |
| 127 valueList.consumeWhitespace(); | |
| 128 return ret; | |
| 129 } | |
| 130 | |
| 131 static inline bool isComma(const CSSParserToken& value) | |
| 132 { | |
| 133 return value.type() == CommaToken; | |
| 134 } | |
| 135 | |
| 94 // Methods for consuming non-shorthand properties starts here. | 136 // Methods for consuming non-shorthand properties starts here. |
| 95 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange) | 137 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange) |
| 96 { | 138 { |
| 97 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); | 139 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); |
| 98 if (range.peek().id() == CSSValueAuto) { | 140 if (range.peek().id() == CSSValueAuto) { |
| 99 // FIXME: This will be read back as an empty string instead of auto | 141 // FIXME: This will be read back as an empty string instead of auto |
| 100 return values.release(); | 142 return values.release(); |
| 101 } | 143 } |
| 102 | 144 |
| 103 // Every comma-separated list of identifiers is a valid will-change value, | 145 // Every comma-separated list of identifiers is a valid will-change value, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 177 |
| 136 if (range.atEnd()) | 178 if (range.atEnd()) |
| 137 break; | 179 break; |
| 138 if (!consumeCommaIncludingWhitespace(range)) | 180 if (!consumeCommaIncludingWhitespace(range)) |
| 139 return nullptr; | 181 return nullptr; |
| 140 } | 182 } |
| 141 | 183 |
| 142 return values.release(); | 184 return values.release(); |
| 143 } | 185 } |
| 144 | 186 |
| 187 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontVariantLigatures(CSSParserTok enRange& range) | |
| 188 { | |
| 189 if (range.peek().id() == CSSValueNormal) | |
| 190 return consumeIdent(range); | |
| 191 RefPtrWillBeRawPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceS eparated(); | |
| 192 bool sawCommonLigaturesValue = false; | |
| 193 bool sawDiscretionaryLigaturesValue = false; | |
| 194 bool sawHistoricalLigaturesValue = false; | |
| 195 bool sawContextualLigaturesValue = false; | |
| 196 | |
| 197 while (!range.atEnd()) { | |
|
Timothy Loh
2015/09/15 02:01:05
do {
} while (!range.atEnd());
return ligatureVa
| |
| 198 if (range.peek().type() != IdentToken) | |
|
Timothy Loh
2015/09/15 02:01:05
No need to check this since id() will just return
| |
| 199 return nullptr; | |
| 200 | |
| 201 CSSValueID id = range.peek().id(); | |
| 202 switch (id) { | |
| 203 case CSSValueNoCommonLigatures: | |
| 204 case CSSValueCommonLigatures: | |
| 205 if (sawCommonLigaturesValue) | |
| 206 return nullptr; | |
| 207 sawCommonLigaturesValue = true; | |
| 208 ligatureValues->append(consumeIdent(range)); | |
|
Timothy Loh
2015/09/15 02:01:05
Probably nicer outside of the switch statement so
| |
| 209 break; | |
| 210 case CSSValueNoDiscretionaryLigatures: | |
| 211 case CSSValueDiscretionaryLigatures: | |
| 212 if (sawDiscretionaryLigaturesValue) | |
| 213 return nullptr; | |
| 214 sawDiscretionaryLigaturesValue = true; | |
| 215 ligatureValues->append(consumeIdent(range)); | |
| 216 break; | |
| 217 case CSSValueNoHistoricalLigatures: | |
| 218 case CSSValueHistoricalLigatures: | |
| 219 if (sawHistoricalLigaturesValue) | |
| 220 return nullptr; | |
| 221 sawHistoricalLigaturesValue = true; | |
| 222 ligatureValues->append(consumeIdent(range)); | |
| 223 break; | |
| 224 case CSSValueNoContextual: | |
| 225 case CSSValueContextual: | |
| 226 if (sawContextualLigaturesValue) | |
| 227 return nullptr; | |
| 228 sawContextualLigaturesValue = true; | |
| 229 ligatureValues->append(consumeIdent(range)); | |
| 230 break; | |
| 231 default: | |
| 232 return nullptr; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 if (!ligatureValues->length()) | |
| 237 return nullptr; | |
| 238 | |
| 239 return ligatureValues.release(); | |
| 240 } | |
| 241 | |
| 242 static bool consumeFontFeatureTag(CSSParserTokenRange& range, CSSValueList* sett ings) | |
| 243 { | |
| 244 // Feature tag name consists of 4-letter characters. | |
| 245 static const unsigned tagNameLength = 4; | |
| 246 | |
| 247 CSSParserToken token = range.peek(); | |
| 248 // Feature tag name comes first | |
| 249 if (token.type() != StringToken) | |
| 250 return false; | |
| 251 if (token.value().length() != tagNameLength) | |
| 252 return false; | |
| 253 AtomicString tag = token.value(); | |
| 254 for (unsigned i = 0; i < tagNameLength; ++i) { | |
| 255 // Limits the range of characters to 0x20-0x7E, following the tag name r ules defiend in the OpenType specification. | |
| 256 UChar character = tag[i]; | |
| 257 if (character < 0x20 || character > 0x7E) | |
| 258 return false; | |
| 259 } | |
| 260 | |
| 261 int tagValue = 1; | |
| 262 // Feature tag values could follow: <integer> | on | off | |
| 263 range.consumeIncludingWhitespace(); | |
| 264 if (!range.atEnd()) { | |
| 265 if (range.peek().type() == NumberToken && range.peek().numericValueType( ) == IntegerValueType && range.peek().numericValue() >= 0) { | |
| 266 tagValue = clampTo<int>(range.peek().numericValue()); | |
| 267 if (tagValue < 0) | |
| 268 return false; | |
| 269 range.consumeIncludingWhitespace(); | |
| 270 } else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSVa lueOff) { | |
| 271 tagValue = range.peek().id() == CSSValueOn; | |
| 272 range.consumeIncludingWhitespace(); | |
| 273 } | |
| 274 } | |
| 275 settings->append(CSSFontFeatureValue::create(tag, tagValue)); | |
| 276 return true; | |
| 277 } | |
| 278 | |
| 279 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontFeatureSettings(CSSParserToke nRange& range) | |
| 280 { | |
| 281 if (range.peek().id() == CSSValueNormal) | |
| 282 return consumeIdent(range); | |
| 283 RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparat ed(); | |
| 284 while (true) { | |
| 285 if (range.atEnd() || !consumeFontFeatureTag(range, settings.get())) | |
| 286 return nullptr; | |
| 287 if (range.atEnd()) | |
| 288 break; | |
| 289 if (!consumeCommaIncludingWhitespace(range)) | |
| 290 return nullptr; | |
| 291 } | |
| 292 return settings.release(); | |
| 293 } | |
| 294 | |
| 145 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range) | 295 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range) |
| 146 { | 296 { |
| 147 if (range.peek().id() == CSSValueAuto) | 297 if (range.peek().id() == CSSValueAuto) |
| 148 return consumeIdent(range); | 298 return consumeIdent(range); |
| 149 return consumeCustomIdent(range); | 299 return consumeCustomIdent(range); |
| 150 } | 300 } |
| 151 | 301 |
| 152 // [ <string> <string> ]+ | none | 302 // [ <string> <string> ]+ | none |
| 153 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range ) | 303 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range ) |
| 154 { | 304 { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 166 return nullptr; | 316 return nullptr; |
| 167 } | 317 } |
| 168 | 318 |
| 169 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitHighlight(CSSParserTokenRan ge& range) | 319 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitHighlight(CSSParserTokenRan ge& range) |
| 170 { | 320 { |
| 171 if (range.peek().id() == CSSValueNone) | 321 if (range.peek().id() == CSSValueNone) |
| 172 return consumeIdent(range); | 322 return consumeIdent(range); |
| 173 return consumeString(range); | 323 return consumeString(range); |
| 174 } | 324 } |
| 175 | 325 |
| 326 // normal | small-caps | inherit | |
| 327 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontVariant() | |
| 328 { | |
| 329 RefPtrWillBeRawPtr<CSSValueList> values = nullptr; | |
| 330 bool expectComma = false; | |
| 331 while (!m_range.atEnd()) { | |
| 332 RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = nullptr; | |
| 333 if (!expectComma) { | |
| 334 expectComma = true; | |
| 335 if (m_range.peek().id() == CSSValueNormal || m_range.peek().id() == CSSValueSmallCaps) { | |
| 336 parsedValue = consumeIdent(m_range); | |
| 337 } else if (m_range.peek().id() == CSSValueAll && !values) { | |
| 338 // FIXME: CSSPropertyParser::parseFontVariant() implements | |
| 339 // the old css3 draft: | |
| 340 // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-var iant | |
| 341 // 'all' is only allowed in @font-face and with no other values. Make a value list to | |
| 342 // indicate that we are in the @font-face case. | |
| 343 values = CSSValueList::createCommaSeparated(); | |
| 344 parsedValue = consumeIdent(m_range); | |
| 345 } | |
| 346 } else if (consumeCommaIncludingWhitespace(m_range)) { | |
| 347 expectComma = false; | |
| 348 continue; | |
| 349 } | |
| 350 | |
| 351 if (!parsedValue) | |
| 352 return nullptr; | |
| 353 | |
| 354 if (isComma(m_range.peek())) | |
| 355 values = CSSValueList::createCommaSeparated(); | |
| 356 | |
| 357 if (values) | |
| 358 values->append(parsedValue.release()); | |
| 359 else | |
| 360 return parsedValue.release(); | |
| 361 } | |
| 362 | |
| 363 if (values && values->length()) { | |
| 364 if (m_ruleType != StyleRule::FontFace) | |
| 365 return nullptr; | |
| 366 return values.release(); | |
| 367 } | |
| 368 | |
| 369 return nullptr; | |
| 370 } | |
| 371 | |
| 372 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitLocale(CSSParserTokenRange& range) | |
| 373 { | |
| 374 if (range.peek().id() == CSSValueAuto) | |
| 375 return consumeIdent(range); | |
| 376 return consumeString(range); | |
| 377 } | |
| 378 | |
| 379 // none | all | 1 (will be dropped in the unprefixed property) | |
| 380 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitColumnSpan(CSSParserTokenRa nge& range) | |
| 381 { | |
| 382 if (range.peek().id() == CSSValueAll || range.peek().id() == CSSValueNone) | |
| 383 return consumeIdent(range); | |
| 384 if (range.peek().type() == NumberToken && range.peek().numericValue() == 1) { | |
| 385 const CSSParserToken& columnSpan = range.consumeIncludingWhitespace(); | |
| 386 return cssValuePool().createValue(columnSpan.numericValue(), columnSpan. unitType()); | |
| 387 } | |
| 388 return nullptr; | |
| 389 } | |
| 390 | |
| 391 static PassRefPtrWillBeRawPtr<CSSValue> consumeTextAlign(CSSParserTokenRange& ra nge) | |
| 392 { | |
| 393 // left | right | center | justify | -webkit-left | -webkit-right | -webkit- center | -webkit-match-parent | |
| 394 // | start | end | <string> | inherit | -webkit-auto (converted to start) | |
| 395 // FIXME: <string> not supported right now | |
| 396 CSSValueID id = range.peek().id(); | |
| 397 if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == C SSValueStart || id == CSSValueEnd) | |
| 398 return consumeIdent(range); | |
| 399 return nullptr; | |
| 400 } | |
| 401 | |
| 176 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId) | 402 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId) |
| 177 { | 403 { |
| 178 m_range.consumeWhitespace(); | 404 m_range.consumeWhitespace(); |
| 179 switch (propId) { | 405 switch (propId) { |
| 180 case CSSPropertyWillChange: | 406 case CSSPropertyWillChange: |
| 181 return consumeWillChange(m_range); | 407 return consumeWillChange(m_range); |
| 182 case CSSPropertyPage: | 408 case CSSPropertyPage: |
| 183 return consumePage(m_range); | 409 return consumePage(m_range); |
| 184 case CSSPropertyQuotes: | 410 case CSSPropertyQuotes: |
| 185 return consumeQuotes(m_range); | 411 return consumeQuotes(m_range); |
| 186 case CSSPropertyWebkitHighlight: | 412 case CSSPropertyWebkitHighlight: |
| 187 return consumeWebkitHighlight(m_range); | 413 return consumeWebkitHighlight(m_range); |
| 414 case CSSPropertyFontVariantLigatures: | |
| 415 return consumeFontVariantLigatures(m_range); | |
| 416 case CSSPropertyWebkitFontFeatureSettings: | |
| 417 return consumeFontFeatureSettings(m_range); | |
| 418 case CSSPropertyFontVariant: | |
| 419 return consumeFontVariant(); | |
| 420 case CSSPropertyWebkitHyphenateCharacter: | |
| 421 case CSSPropertyWebkitLocale: | |
| 422 return consumeWebkitLocale(m_range); | |
| 423 case CSSPropertyWebkitColumnSpan: | |
|
Timothy Loh
2015/09/15 02:01:05
let's leave the properties which aren't font-face
| |
| 424 return consumeWebkitColumnSpan(m_range); | |
| 425 case CSSPropertyTextAlign: | |
| 426 return consumeTextAlign(m_range); | |
| 188 default: | 427 default: |
| 189 return nullptr; | 428 return nullptr; |
| 190 } | 429 } |
| 191 } | 430 } |
| 192 | 431 |
| 432 static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParse rTokenRange& range) | |
| 433 { | |
| 434 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); | |
| 435 | |
| 436 do { | |
| 437 const CSSParserToken& token = range.consumeIncludingWhitespace(); | |
| 438 if (token.type() != UnicodeRangeToken) | |
| 439 return nullptr; | |
| 440 | |
| 441 UChar32 start = token.unicodeRangeStart(); | |
| 442 UChar32 end = token.unicodeRangeEnd(); | |
| 443 if (start > end) | |
| 444 return nullptr; | |
| 445 values->append(CSSUnicodeRangeValue::create(start, end)); | |
| 446 } while (consumeCommaIncludingWhitespace(range)); | |
|
Timothy Loh
2015/09/15 02:01:05
I like this comma-separated-list pattern, can we d
| |
| 447 | |
| 448 return values.release(); | |
| 449 } | |
| 450 | |
| 451 bool CSSPropertyParser::consumeFontFaceSrcURI(CSSValueList* valueList) | |
| 452 { | |
| 453 String url; | |
| 454 if (!tryConsumeUrl(m_range, url)) | |
| 455 return false; | |
| 456 RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create (completeURL(url), m_context.shouldCheckContentSecurityPolicy())); | |
| 457 uriValue->setReferrer(m_context.referrer()); | |
| 458 | |
| 459 if (m_range.atEnd() || m_range.peek().type() != FunctionToken || m_range.pee k().functionId() != CSSValueFormat) { | |
|
Timothy Loh
2015/09/15 02:01:05
No need to check atEnd() or type() here, functionI
| |
| 460 valueList->append(uriValue.release()); | |
| 461 return true; | |
| 462 } | |
| 463 | |
| 464 // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format () contains a comma-separated list of strings, | |
| 465 // but CSSFontFaceSrcValue stores only one format. Allowing one format for n ow. | |
| 466 CSSParserTokenRange args = consumeFunction(m_range); | |
| 467 if (args.atEnd() || (args.peek().type() != StringToken && args.peek().type() != IdentToken)) | |
|
Timothy Loh
2015/09/15 02:01:05
No need for atEnd() here.
| |
| 468 return false; | |
| 469 uriValue->setFormat(args.consumeIncludingWhitespace().value()); | |
| 470 valueList->append(uriValue.release()); | |
| 471 return true; | |
| 472 } | |
| 473 | |
| 474 bool CSSPropertyParser::consumeFontFaceSrcLocal(CSSValueList* valueList) | |
| 475 { | |
| 476 CSSParserTokenRange args = consumeFunction(m_range); | |
| 477 if (args.atEnd()) | |
| 478 return false; | |
| 479 | |
| 480 const CSSParserToken& arg = args.consumeIncludingWhitespace(); | |
| 481 ContentSecurityPolicyDisposition shouldCheckContentSecurityPolicy = m_contex t.shouldCheckContentSecurityPolicy(); | |
| 482 if (arg.type() == StringToken) { | |
| 483 if (!args.atEnd()) | |
| 484 return false; | |
| 485 valueList->append(CSSFontFaceSrcValue::createLocal(arg.value(), shouldCh eckContentSecurityPolicy)); | |
| 486 } else if (arg.type() == IdentToken) { | |
| 487 StringBuilder builder; | |
| 488 builder.append(arg.value()); | |
| 489 while (!args.atEnd()) { | |
| 490 CSSParserToken localValue = args.consumeIncludingWhitespace(); | |
| 491 if (localValue.type() != IdentToken) | |
| 492 return false; | |
| 493 if (!builder.isEmpty()) | |
| 494 builder.append(' '); | |
| 495 builder.append(localValue.value()); | |
| 496 } | |
| 497 valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString(), s houldCheckContentSecurityPolicy)); | |
| 498 } else { | |
| 499 return false; | |
| 500 } | |
| 501 | |
| 502 return true; | |
| 503 } | |
| 504 | |
| 505 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFaceSrc() | |
| 506 { | |
| 507 RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated() ); | |
| 508 | |
| 509 while (true) { | |
| 510 const CSSParserToken& token = m_range.peek(); | |
| 511 if (token.type() == FunctionToken && token.functionId() == CSSValueLocal ) { | |
| 512 if (!consumeFontFaceSrcLocal(values.get())) | |
| 513 return nullptr; | |
| 514 } else if (!consumeFontFaceSrcURI(values.get())) { | |
| 515 return nullptr; | |
| 516 } | |
| 517 | |
| 518 if (m_range.atEnd()) | |
| 519 return values.release(); | |
| 520 if (!consumeCommaIncludingWhitespace(m_range)) | |
| 521 return nullptr; | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId) | |
| 526 { | |
| 527 RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; | |
| 528 | |
| 529 m_range.consumeWhitespace(); | |
| 530 switch (propId) { | |
| 531 case CSSPropertyFontFamily: | |
| 532 // <family-name> | |
| 533 // TODO(rwlbuis): check there is only one family-name | |
| 534 parsedValue = parseFontFamily(); | |
| 535 break; | |
| 536 case CSSPropertySrc: // This is a list of urls or local references. | |
| 537 parsedValue = consumeFontFaceSrc(); | |
| 538 if (parsedValue && m_range.atEnd()) { | |
| 539 addProperty(CSSPropertySrc, parsedValue.release(), false); | |
| 540 return true; | |
| 541 } | |
| 542 break; | |
| 543 case CSSPropertyUnicodeRange: | |
| 544 parsedValue = consumeFontFaceUnicodeRange(m_range); | |
| 545 if (parsedValue && m_range.atEnd()) { | |
| 546 addProperty(CSSPropertyUnicodeRange, parsedValue.release(), false); | |
| 547 return true; | |
| 548 } | |
| 549 break; | |
| 550 case CSSPropertyFontWeight: // normal | bold | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | |
| 551 return parseFontWeight(false) && !m_valueList->next(); | |
| 552 case CSSPropertyFontStretch: | |
| 553 case CSSPropertyFontStyle: { | |
| 554 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | |
| 555 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id)) | |
| 556 return false; | |
| 557 addProperty(propId, cssValuePool().createIdentifierValue(id), false); | |
| 558 return true; | |
| 559 } | |
| 560 case CSSPropertyFontVariant: // normal | small-caps | inherit | |
| 561 parsedValue = consumeFontVariant(); | |
| 562 if (parsedValue && m_range.atEnd()) { | |
| 563 addProperty(CSSPropertyFontVariant, parsedValue.release(), false); | |
| 564 return true; | |
| 565 } | |
| 566 break; | |
| 567 case CSSPropertyWebkitFontFeatureSettings: | |
| 568 parsedValue = parseSingleValue(propId); | |
| 569 if (parsedValue && m_range.atEnd()) { | |
| 570 addProperty(CSSPropertyWebkitFontFeatureSettings, parsedValue.releas e(), false); | |
| 571 return true; | |
| 572 } | |
| 573 break; | |
| 574 default: | |
| 575 break; | |
| 576 } | |
| 577 | |
| 578 if (!parsedValue || m_valueList->current()) | |
| 579 return false; | |
| 580 | |
| 581 addProperty(propId, parsedValue.release(), false); | |
| 582 return true; | |
| 583 } | |
| 584 | |
| 193 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) | 585 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) |
| 194 { | 586 { |
| 195 m_range.consumeWhitespace(); | 587 m_range.consumeWhitespace(); |
| 196 switch (propId) { | 588 switch (propId) { |
| 197 case CSSPropertyWebkitMarginCollapse: { | 589 case CSSPropertyWebkitMarginCollapse: { |
| 198 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | 590 CSSValueID id = m_range.consumeIncludingWhitespace().id(); |
| 199 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) | 591 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) |
| 200 return false; | 592 return false; |
| 201 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); | 593 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); |
| 202 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); | 594 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 231 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); | 623 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); |
| 232 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); | 624 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); |
| 233 return true; | 625 return true; |
| 234 } | 626 } |
| 235 default: | 627 default: |
| 236 return false; | 628 return false; |
| 237 } | 629 } |
| 238 } | 630 } |
| 239 | 631 |
| 240 } // namespace blink | 632 } // namespace blink |
| OLD | NEW |