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" |
| 14 | 17 |
| 15 namespace blink { | 18 namespace blink { |
| 16 | 19 |
| 17 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, | 20 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, |
| 18 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, | 21 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, |
| 19 StyleRule::Type ruleType) | 22 StyleRule::Type ruleType) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::CustomIdentifier); | 87 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::CustomIdentifier); |
| 85 } | 88 } |
| 86 | 89 |
| 87 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan ge& range) | 90 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan ge& range) |
| 88 { | 91 { |
| 89 if (range.peek().type() != StringToken) | 92 if (range.peek().type() != StringToken) |
| 90 return nullptr; | 93 return nullptr; |
| 91 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::String); | 94 return cssValuePool().createValue(range.consumeIncludingWhitespace().value() , CSSPrimitiveValue::UnitType::String); |
| 92 } | 95 } |
| 93 | 96 |
| 97 static String consumeUrl(CSSParserTokenRange& range) | |
| 98 { | |
| 99 const CSSParserToken& token = range.peek(); | |
| 100 if (token.type() == UrlToken) { | |
| 101 range.consumeIncludingWhitespace(); | |
| 102 return token.value(); | |
| 103 } | |
| 104 if (token.functionId() == CSSValueUrl) { | |
| 105 CSSParserTokenRange urlRange = range; | |
| 106 CSSParserTokenRange urlArgs = urlRange.consumeBlock(); | |
| 107 const CSSParserToken& next = urlArgs.consumeIncludingWhitespace(); | |
| 108 if (next.type() == BadStringToken || !urlArgs.atEnd()) | |
| 109 return String(); | |
| 110 ASSERT(next.type() == StringToken); | |
| 111 range = urlRange; | |
| 112 range.consumeWhitespace(); | |
| 113 return next.value(); | |
| 114 } | |
| 115 | |
| 116 return String(); | |
| 117 } | |
| 118 | |
| 119 static CSSParserTokenRange consumeFunction(CSSParserTokenRange& range) | |
| 120 { | |
| 121 ASSERT(range.peek().type() == FunctionToken); | |
| 122 CSSParserTokenRange contens = range.consumeBlock(); | |
|
Timothy Loh
2015/09/16 03:22:28
contens -> contents? :-)
| |
| 123 range.consumeWhitespace(); | |
| 124 return contens; | |
| 125 } | |
| 126 | |
| 127 static inline bool isComma(const CSSParserToken& value) | |
| 128 { | |
| 129 return value.type() == CommaToken; | |
| 130 } | |
| 131 | |
| 94 // Methods for consuming non-shorthand properties starts here. | 132 // Methods for consuming non-shorthand properties starts here. |
| 95 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange) | 133 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange) |
| 96 { | 134 { |
| 97 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); | 135 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); |
| 98 if (range.peek().id() == CSSValueAuto) { | 136 if (range.peek().id() == CSSValueAuto) { |
| 99 // FIXME: This will be read back as an empty string instead of auto | 137 // FIXME: This will be read back as an empty string instead of auto |
| 100 return values.release(); | 138 return values.release(); |
| 101 } | 139 } |
| 102 | 140 |
| 103 // Every comma-separated list of identifiers is a valid will-change value, | 141 // 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 | 173 |
| 136 if (range.atEnd()) | 174 if (range.atEnd()) |
| 137 break; | 175 break; |
| 138 if (!consumeCommaIncludingWhitespace(range)) | 176 if (!consumeCommaIncludingWhitespace(range)) |
| 139 return nullptr; | 177 return nullptr; |
| 140 } | 178 } |
| 141 | 179 |
| 142 return values.release(); | 180 return values.release(); |
| 143 } | 181 } |
| 144 | 182 |
| 183 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontVariantLigatures(CSSParserTok enRange& range) | |
|
Timothy Loh
2015/09/16 03:22:28
Can we move the properties which are not @font-fac
| |
| 184 { | |
| 185 if (range.peek().id() == CSSValueNormal) | |
| 186 return consumeIdent(range); | |
| 187 RefPtrWillBeRawPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceS eparated(); | |
| 188 bool sawCommonLigaturesValue = false; | |
| 189 bool sawDiscretionaryLigaturesValue = false; | |
| 190 bool sawHistoricalLigaturesValue = false; | |
| 191 bool sawContextualLigaturesValue = false; | |
| 192 do { | |
| 193 CSSValueID id = range.peek().id(); | |
| 194 switch (id) { | |
| 195 case CSSValueNoCommonLigatures: | |
| 196 case CSSValueCommonLigatures: | |
| 197 if (sawCommonLigaturesValue) | |
| 198 return nullptr; | |
| 199 sawCommonLigaturesValue = true; | |
| 200 break; | |
| 201 case CSSValueNoDiscretionaryLigatures: | |
| 202 case CSSValueDiscretionaryLigatures: | |
| 203 if (sawDiscretionaryLigaturesValue) | |
| 204 return nullptr; | |
| 205 sawDiscretionaryLigaturesValue = true; | |
| 206 break; | |
| 207 case CSSValueNoHistoricalLigatures: | |
| 208 case CSSValueHistoricalLigatures: | |
| 209 if (sawHistoricalLigaturesValue) | |
| 210 return nullptr; | |
| 211 sawHistoricalLigaturesValue = true; | |
| 212 break; | |
| 213 case CSSValueNoContextual: | |
| 214 case CSSValueContextual: | |
| 215 if (sawContextualLigaturesValue) | |
| 216 return nullptr; | |
| 217 sawContextualLigaturesValue = true; | |
| 218 break; | |
| 219 default: | |
| 220 return nullptr; | |
| 221 } | |
| 222 ligatureValues->append(consumeIdent(range)); | |
| 223 } while (!range.atEnd()); | |
| 224 | |
| 225 if (!ligatureValues->length()) | |
|
Timothy Loh
2015/09/16 03:22:28
The list will never be empty here
| |
| 226 return nullptr; | |
| 227 | |
| 228 return ligatureValues.release(); | |
| 229 } | |
| 230 | |
| 231 static bool consumeFontFeatureTag(CSSParserTokenRange& range, CSSValueList* sett ings) | |
|
Timothy Loh
2015/09/16 03:22:28
should probably just return a CSSFontFeatureValue
| |
| 232 { | |
| 233 // Feature tag name consists of 4-letter characters. | |
| 234 static const unsigned tagNameLength = 4; | |
| 235 | |
| 236 CSSParserToken token = range.peek(); | |
|
Timothy Loh
2015/09/16 03:22:28
const CSSParserToken&. Also maybe easier if this i
| |
| 237 // Feature tag name comes first | |
| 238 if (token.type() != StringToken) | |
| 239 return false; | |
| 240 if (token.value().length() != tagNameLength) | |
| 241 return false; | |
| 242 AtomicString tag = token.value(); | |
| 243 for (unsigned i = 0; i < tagNameLength; ++i) { | |
| 244 // Limits the range of characters to 0x20-0x7E, following the tag name r ules defiend in the OpenType specification. | |
| 245 UChar character = tag[i]; | |
| 246 if (character < 0x20 || character > 0x7E) | |
| 247 return false; | |
| 248 } | |
| 249 | |
| 250 int tagValue = 1; | |
| 251 // Feature tag values could follow: <integer> | on | off | |
| 252 range.consumeIncludingWhitespace(); | |
| 253 if (!range.atEnd()) { | |
|
Timothy Loh
2015/09/16 03:22:28
don't need this check, peek() will just return EOF
| |
| 254 if (range.peek().type() == NumberToken && range.peek().numericValueType( ) == IntegerValueType && range.peek().numericValue() >= 0) { | |
| 255 tagValue = clampTo<int>(range.peek().numericValue()); | |
|
Timothy Loh
2015/09/16 03:22:28
range.consumeIncludingWhitespace().numericValue()?
| |
| 256 if (tagValue < 0) | |
| 257 return false; | |
|
Timothy Loh
2015/09/16 03:22:28
does this ever get hit?
| |
| 258 range.consumeIncludingWhitespace(); | |
| 259 } else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSVa lueOff) { | |
| 260 tagValue = range.peek().id() == CSSValueOn; | |
|
Timothy Loh
2015/09/16 03:22:28
range.consumeIncludingWhitespace().id()
| |
| 261 range.consumeIncludingWhitespace(); | |
| 262 } | |
| 263 } | |
| 264 settings->append(CSSFontFeatureValue::create(tag, tagValue)); | |
| 265 return true; | |
| 266 } | |
| 267 | |
| 268 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontFeatureSettings(CSSParserToke nRange& range) | |
|
Timothy Loh
2015/09/16 03:22:28
this one too, separate patch
| |
| 269 { | |
| 270 if (range.peek().id() == CSSValueNormal) | |
| 271 return consumeIdent(range); | |
| 272 RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparat ed(); | |
| 273 do { | |
| 274 if (!consumeFontFeatureTag(range, settings.get())) | |
| 275 return nullptr; | |
| 276 if (range.atEnd()) | |
|
Timothy Loh
2015/09/16 03:22:28
I think just return the value outside the loop and
| |
| 277 return settings.release(); | |
| 278 } while (consumeCommaIncludingWhitespace(range)); | |
| 279 return nullptr; | |
| 280 } | |
| 281 | |
| 145 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range) | 282 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range) |
| 146 { | 283 { |
| 147 if (range.peek().id() == CSSValueAuto) | 284 if (range.peek().id() == CSSValueAuto) |
| 148 return consumeIdent(range); | 285 return consumeIdent(range); |
| 149 return consumeCustomIdent(range); | 286 return consumeCustomIdent(range); |
| 150 } | 287 } |
| 151 | 288 |
| 152 // [ <string> <string> ]+ | none | 289 // [ <string> <string> ]+ | none |
| 153 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range ) | 290 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range ) |
| 154 { | 291 { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 166 return nullptr; | 303 return nullptr; |
| 167 } | 304 } |
| 168 | 305 |
| 169 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitHighlight(CSSParserTokenRan ge& range) | 306 static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitHighlight(CSSParserTokenRan ge& range) |
| 170 { | 307 { |
| 171 if (range.peek().id() == CSSValueNone) | 308 if (range.peek().id() == CSSValueNone) |
| 172 return consumeIdent(range); | 309 return consumeIdent(range); |
| 173 return consumeString(range); | 310 return consumeString(range); |
| 174 } | 311 } |
| 175 | 312 |
| 313 // normal | small-caps | inherit | |
|
Timothy Loh
2015/09/16 03:22:28
Comment is wrong, let's just drop these (as well a
| |
| 314 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontVariant() | |
|
Timothy Loh
2015/09/16 03:22:28
static for consistency?
| |
| 315 { | |
| 316 RefPtrWillBeRawPtr<CSSValueList> values = nullptr; | |
|
Timothy Loh
2015/09/16 03:22:28
Can we rewrite this function so it isn't super com
| |
| 317 bool expectComma = false; | |
| 318 while (!m_range.atEnd()) { | |
| 319 RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = nullptr; | |
| 320 if (!expectComma) { | |
| 321 expectComma = true; | |
| 322 if (m_range.peek().id() == CSSValueNormal || m_range.peek().id() == CSSValueSmallCaps) { | |
| 323 parsedValue = consumeIdent(m_range); | |
| 324 } else if (m_range.peek().id() == CSSValueAll && !values) { | |
| 325 // FIXME: CSSPropertyParser::parseFontVariant() implements | |
| 326 // the old css3 draft: | |
| 327 // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-var iant | |
| 328 // 'all' is only allowed in @font-face and with no other values. Make a value list to | |
| 329 // indicate that we are in the @font-face case. | |
| 330 values = CSSValueList::createCommaSeparated(); | |
| 331 parsedValue = consumeIdent(m_range); | |
| 332 } | |
| 333 } else if (consumeCommaIncludingWhitespace(m_range)) { | |
| 334 expectComma = false; | |
| 335 continue; | |
| 336 } | |
| 337 | |
| 338 if (!parsedValue) | |
| 339 return nullptr; | |
| 340 | |
| 341 if (isComma(m_range.peek())) | |
| 342 values = CSSValueList::createCommaSeparated(); | |
| 343 | |
| 344 if (values) | |
| 345 values->append(parsedValue.release()); | |
| 346 else | |
| 347 return parsedValue.release(); | |
| 348 } | |
| 349 | |
| 350 if (values && values->length()) { | |
| 351 if (m_ruleType != StyleRule::FontFace) | |
| 352 return nullptr; | |
| 353 return values.release(); | |
| 354 } | |
| 355 | |
| 356 return nullptr; | |
| 357 } | |
| 358 | |
| 176 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId) | 359 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId) |
| 177 { | 360 { |
| 178 m_range.consumeWhitespace(); | 361 m_range.consumeWhitespace(); |
| 179 switch (propId) { | 362 switch (propId) { |
| 180 case CSSPropertyWillChange: | 363 case CSSPropertyWillChange: |
| 181 return consumeWillChange(m_range); | 364 return consumeWillChange(m_range); |
| 182 case CSSPropertyPage: | 365 case CSSPropertyPage: |
| 183 return consumePage(m_range); | 366 return consumePage(m_range); |
| 184 case CSSPropertyQuotes: | 367 case CSSPropertyQuotes: |
| 185 return consumeQuotes(m_range); | 368 return consumeQuotes(m_range); |
| 186 case CSSPropertyWebkitHighlight: | 369 case CSSPropertyWebkitHighlight: |
| 187 return consumeWebkitHighlight(m_range); | 370 return consumeWebkitHighlight(m_range); |
| 371 case CSSPropertyFontVariantLigatures: | |
| 372 return consumeFontVariantLigatures(m_range); | |
| 373 case CSSPropertyWebkitFontFeatureSettings: | |
| 374 return consumeFontFeatureSettings(m_range); | |
| 375 case CSSPropertyFontVariant: | |
| 376 return consumeFontVariant(); | |
| 377 case CSSPropertyFontFamily: | |
| 378 // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-fa mily>] | inherit | |
| 379 return consumeFontFamily(); | |
| 188 default: | 380 default: |
| 189 return nullptr; | 381 return nullptr; |
| 190 } | 382 } |
| 191 } | 383 } |
| 192 | 384 |
| 385 static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParse rTokenRange& range) | |
| 386 { | |
| 387 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); | |
| 388 | |
| 389 do { | |
| 390 const CSSParserToken& token = range.consumeIncludingWhitespace(); | |
| 391 if (token.type() != UnicodeRangeToken) | |
| 392 return nullptr; | |
| 393 | |
| 394 UChar32 start = token.unicodeRangeStart(); | |
| 395 UChar32 end = token.unicodeRangeEnd(); | |
| 396 if (start > end) | |
| 397 return nullptr; | |
| 398 values->append(CSSUnicodeRangeValue::create(start, end)); | |
| 399 } while (consumeCommaIncludingWhitespace(range)); | |
| 400 | |
| 401 return values.release(); | |
| 402 } | |
| 403 | |
| 404 bool CSSPropertyParser::consumeFontFaceSrcURI(CSSValueList* valueList) | |
|
Timothy Loh
2015/09/16 03:22:28
return a CSSValue instead of updating a CSSValueLi
| |
| 405 { | |
| 406 String url = consumeUrl(m_range); | |
| 407 if (url.isNull()) | |
| 408 return false; | |
| 409 RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create (completeURL(url), m_context.shouldCheckContentSecurityPolicy())); | |
| 410 uriValue->setReferrer(m_context.referrer()); | |
| 411 | |
| 412 if (m_range.peek().functionId() != CSSValueFormat) { | |
| 413 valueList->append(uriValue.release()); | |
| 414 return true; | |
| 415 } | |
| 416 | |
| 417 // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format () contains a comma-separated list of strings, | |
|
Timothy Loh
2015/09/16 03:22:28
Should update the URL (https://drafts.csswg.org/cs
| |
| 418 // but CSSFontFaceSrcValue stores only one format. Allowing one format for n ow. | |
| 419 CSSParserTokenRange args = consumeFunction(m_range); | |
| 420 if (args.peek().type() != StringToken && args.peek().type() != IdentToken) | |
| 421 return false; | |
| 422 uriValue->setFormat(args.consumeIncludingWhitespace().value()); | |
|
Timothy Loh
2015/09/16 03:22:28
need to check for any tokens after the string?
| |
| 423 valueList->append(uriValue.release()); | |
| 424 return true; | |
| 425 } | |
| 426 | |
| 427 bool CSSPropertyParser::consumeFontFaceSrcLocal(CSSValueList* valueList) | |
|
Timothy Loh
2015/09/16 03:22:28
return a CSSValue
| |
| 428 { | |
| 429 CSSParserTokenRange args = consumeFunction(m_range); | |
| 430 if (args.atEnd()) | |
| 431 return false; | |
| 432 | |
| 433 const CSSParserToken& arg = args.consumeIncludingWhitespace(); | |
|
Timothy Loh
2015/09/16 03:22:28
This is just <family-name>, right? We should share
| |
| 434 ContentSecurityPolicyDisposition shouldCheckContentSecurityPolicy = m_contex t.shouldCheckContentSecurityPolicy(); | |
| 435 if (arg.type() == StringToken) { | |
| 436 if (!args.atEnd()) | |
| 437 return false; | |
| 438 valueList->append(CSSFontFaceSrcValue::createLocal(arg.value(), shouldCh eckContentSecurityPolicy)); | |
| 439 } else if (arg.type() == IdentToken) { | |
| 440 StringBuilder builder; | |
| 441 builder.append(arg.value()); | |
| 442 while (!args.atEnd()) { | |
| 443 CSSParserToken localValue = args.consumeIncludingWhitespace(); | |
| 444 if (localValue.type() != IdentToken) | |
| 445 return false; | |
| 446 if (!builder.isEmpty()) | |
| 447 builder.append(' '); | |
| 448 builder.append(localValue.value()); | |
| 449 } | |
| 450 valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString(), s houldCheckContentSecurityPolicy)); | |
| 451 } else { | |
| 452 return false; | |
| 453 } | |
| 454 | |
| 455 return true; | |
| 456 } | |
| 457 | |
| 458 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFaceSrc() | |
| 459 { | |
| 460 RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated() ); | |
| 461 | |
| 462 do { | |
| 463 const CSSParserToken& token = m_range.peek(); | |
| 464 if (token.functionId() == CSSValueLocal) { | |
| 465 if (!consumeFontFaceSrcLocal(values.get())) | |
| 466 return nullptr; | |
| 467 } else if (!consumeFontFaceSrcURI(values.get())) { | |
| 468 return nullptr; | |
| 469 } | |
| 470 | |
| 471 if (m_range.atEnd()) | |
| 472 return values.release(); | |
| 473 } while (consumeCommaIncludingWhitespace(m_range)); | |
| 474 return nullptr; | |
| 475 } | |
| 476 | |
| 477 static inline bool isCSSWideKeyword(const CSSParserToken& token) | |
| 478 { | |
| 479 return token.id() == CSSValueInitial || token.id() == CSSValueInherit || tok en.id() == CSSValueUnset || token.id() == CSSValueDefault; | |
|
Timothy Loh
2015/09/16 03:22:28
I know id() has a cache but can we pull the value
| |
| 480 } | |
| 481 | |
| 482 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFamily() | |
| 483 { | |
| 484 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated() ; | |
| 485 CSSParserToken token = m_range.consumeIncludingWhitespace(); | |
| 486 | |
| 487 FontFamilyValueBuilder familyBuilder(list.get()); | |
| 488 bool inFamily = false; | |
| 489 | |
| 490 while (token.type() != EOFToken) { | |
| 491 const CSSParserToken& nextToken = m_range.consumeIncludingWhitespace(); | |
| 492 bool nextValBreaksFont = nextToken.type() == EOFToken || isComma(nextTok en); | |
| 493 bool nextValIsFontName = ((nextToken.id() >= CSSValueSerif && nextToken. id() <= CSSValueWebkitBody) | |
| 494 || (nextToken.type() == StringToken || nextToken.type() == IdentToke n)); | |
| 495 | |
| 496 if (isCSSWideKeyword(token) && !inFamily) { | |
| 497 if (nextValBreaksFont) | |
| 498 return nullptr; | |
| 499 if (nextValIsFontName) | |
| 500 token = nextToken; | |
| 501 continue; | |
| 502 } | |
| 503 | |
| 504 if (token.id() >= CSSValueSerif && token.id() <= CSSValueWebkitBody) { | |
| 505 if (inFamily) { | |
| 506 familyBuilder.add(token.value()); | |
| 507 } else if (nextValBreaksFont || !nextValIsFontName) { | |
| 508 list->append(cssValuePool().createIdentifierValue(token.id())); | |
| 509 } else { | |
| 510 familyBuilder.commit(); | |
| 511 familyBuilder.add(token.value()); | |
| 512 inFamily = true; | |
| 513 } | |
| 514 } else if (token.type() == StringToken) { | |
| 515 // Strings never share in a family name. | |
| 516 inFamily = false; | |
| 517 familyBuilder.commit(); | |
| 518 list->append(cssValuePool().createFontFamilyValue(token.value())); | |
| 519 } else if (token.type() == IdentToken) { | |
| 520 if (inFamily) { | |
| 521 familyBuilder.add(token.value()); | |
| 522 } else if (nextValBreaksFont || !nextValIsFontName) { | |
| 523 list->append(cssValuePool().createFontFamilyValue(token.value()) ); | |
| 524 } else { | |
| 525 familyBuilder.commit(); | |
| 526 familyBuilder.add(token.value()); | |
| 527 inFamily = true; | |
| 528 } | |
| 529 } else { | |
| 530 break; | |
| 531 } | |
| 532 | |
| 533 if (nextToken.type() == EOFToken) | |
| 534 break; | |
| 535 | |
| 536 if (nextValBreaksFont) { | |
| 537 token = m_range.consumeIncludingWhitespace(); | |
| 538 familyBuilder.commit(); | |
| 539 inFamily = false; | |
| 540 } else if (nextValIsFontName) { | |
| 541 token = nextToken; | |
| 542 } else { | |
| 543 break; | |
| 544 } | |
| 545 } | |
| 546 familyBuilder.commit(); | |
| 547 if (!list->length() || (m_ruleType == StyleRule::FontFace && list->length() > 1)) | |
| 548 list = nullptr; | |
| 549 return list.release(); | |
| 550 } | |
| 551 | |
| 552 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontWeight(CSSParserTokenRange& r ange) | |
| 553 { | |
| 554 const CSSParserToken& token = range.peek(); | |
| 555 if (token.id() >= CSSValueNormal && token.id() <= CSSValueLighter) | |
| 556 return consumeIdent(range); | |
| 557 if (token.type() != NumberToken) | |
|
Timothy Loh
2015/09/16 03:22:28
|| token.numericValueType() != IntegerValueType?
| |
| 558 return nullptr; | |
| 559 int weight = static_cast<int>(token.numericValue()); | |
| 560 if ((weight % 100) || weight < 100 || weight > 900) | |
| 561 return nullptr; | |
| 562 range.consumeIncludingWhitespace(); | |
| 563 return cssValuePool().createIdentifierValue(static_cast<CSSValueID>(CSSValue 100 + weight / 100 - 1)); | |
| 564 } | |
| 565 | |
| 566 bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId) | |
|
Timothy Loh
2015/09/16 03:22:28
I think we decided a while ago to split this into
| |
| 567 { | |
| 568 RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; | |
| 569 | |
| 570 m_range.consumeWhitespace(); | |
| 571 switch (propId) { | |
| 572 case CSSPropertyFontFamily: | |
| 573 // <family-name> | |
| 574 // TODO(rwlbuis): check there is only one family-name | |
| 575 parsedValue = consumeFontFamily(); | |
| 576 break; | |
| 577 case CSSPropertySrc: // This is a list of urls or local references. | |
| 578 parsedValue = consumeFontFaceSrc(); | |
| 579 break; | |
| 580 case CSSPropertyUnicodeRange: | |
| 581 parsedValue = consumeFontFaceUnicodeRange(m_range); | |
| 582 break; | |
| 583 case CSSPropertyFontWeight: // normal | bold | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | |
| 584 parsedValue = consumeFontWeight(m_range); | |
| 585 break; | |
| 586 case CSSPropertyFontStretch: | |
| 587 case CSSPropertyFontStyle: { | |
| 588 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | |
| 589 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id)) | |
| 590 return false; | |
| 591 addProperty(propId, cssValuePool().createIdentifierValue(id), false); | |
|
Timothy Loh
2015/09/16 03:22:28
parsedValue = ?
| |
| 592 return true; | |
| 593 } | |
| 594 case CSSPropertyFontVariant: // normal | small-caps | inherit | |
| 595 parsedValue = consumeFontVariant(); | |
| 596 break; | |
| 597 case CSSPropertyWebkitFontFeatureSettings: | |
| 598 parsedValue = parseSingleValue(propId); | |
| 599 break; | |
| 600 default: | |
| 601 break; | |
| 602 } | |
| 603 | |
| 604 if (!parsedValue || !m_range.atEnd()) | |
| 605 return false; | |
| 606 | |
| 607 addProperty(propId, parsedValue.release(), false); | |
| 608 return true; | |
| 609 } | |
| 610 | |
| 193 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) | 611 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) |
| 194 { | 612 { |
| 195 m_range.consumeWhitespace(); | 613 m_range.consumeWhitespace(); |
| 196 switch (propId) { | 614 switch (propId) { |
| 197 case CSSPropertyWebkitMarginCollapse: { | 615 case CSSPropertyWebkitMarginCollapse: { |
| 198 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | 616 CSSValueID id = m_range.consumeIncludingWhitespace().id(); |
| 199 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) | 617 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) |
| 200 return false; | 618 return false; |
| 201 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); | 619 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); |
| 202 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); | 620 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 231 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); | 649 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); |
| 232 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); | 650 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); |
| 233 return true; | 651 return true; |
| 234 } | 652 } |
| 235 default: | 653 default: |
| 236 return false; | 654 return false; |
| 237 } | 655 } |
| 238 } | 656 } |
| 239 | 657 |
| 240 } // namespace blink | 658 } // namespace blink |
| OLD | NEW |