Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(521)

Side by Side Diff: Source/core/css/parser/CSSPropertyParser.cpp

Issue 1331233003: Move parseFontFaceDescriptor to CSSPropertyParser.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Simplify font family parsing Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 String consumeUrl(CSSParserTokenRange& range)
99 {
100 const CSSParserToken& token = range.peek();
101 if (token.type() == UrlToken) {
102 range.consumeIncludingWhitespace();
103 return token.value();
104 }
105 if (token.functionId() == CSSValueUrl) {
106 CSSParserTokenRange urlRange = range;
107 CSSParserTokenRange urlArgs = urlRange.consumeBlock();
108 const CSSParserToken& next = urlArgs.consumeIncludingWhitespace();
109 if (next.type() == BadStringToken || !urlArgs.atEnd())
110 return String();
111 ASSERT(next.type() == StringToken);
112 range = urlRange;
113 range.consumeWhitespace();
114 return next.value();
115 }
116
117 return String();
118 }
119
120 static CSSParserTokenRange consumeFunction(CSSParserTokenRange& range)
121 {
122 ASSERT(range.peek().type() == FunctionToken);
123 CSSParserTokenRange contents = range.consumeBlock();
124 range.consumeWhitespace();
125 return contents;
126 }
127
128 static inline bool isComma(const CSSParserToken& value)
Timothy Loh 2015/09/18 03:49:18 not used now, not sure if we'll actually need it :
129 {
130 return value.type() == CommaToken;
131 }
132
133 static inline bool isCSSWideKeyword(const CSSValueID& id)
134 {
135 return id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset || id == CSSValueDefault;
136 }
137
94 // Methods for consuming non-shorthand properties starts here. 138 // Methods for consuming non-shorthand properties starts here.
95 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange) 139 static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r ange)
96 { 140 {
97 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated (); 141 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated ();
98 if (range.peek().id() == CSSValueAuto) { 142 if (range.peek().id() == CSSValueAuto) {
99 // FIXME: This will be read back as an empty string instead of auto 143 // FIXME: This will be read back as an empty string instead of auto
100 return values.release(); 144 return values.release();
101 } 145 }
102 146
103 // Every comma-separated list of identifiers is a valid will-change value, 147 // Every comma-separated list of identifiers is a valid will-change value,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 179
136 if (range.atEnd()) 180 if (range.atEnd())
137 break; 181 break;
138 if (!consumeCommaIncludingWhitespace(range)) 182 if (!consumeCommaIncludingWhitespace(range))
139 return nullptr; 183 return nullptr;
140 } 184 }
141 185
142 return values.release(); 186 return values.release();
143 } 187 }
144 188
189 static PassRefPtrWillBeRawPtr<CSSFontFeatureValue> consumeFontFeatureTag(CSSPars erTokenRange& range)
190 {
191 // Feature tag name consists of 4-letter characters.
192 static const unsigned tagNameLength = 4;
193
194 const CSSParserToken& token = range.consumeIncludingWhitespace();
195 // Feature tag name comes first
196 if (token.type() != StringToken)
197 return nullptr;
198 if (token.value().length() != tagNameLength)
199 return nullptr;
200 AtomicString tag = token.value();
201 for (unsigned i = 0; i < tagNameLength; ++i) {
202 // Limits the range of characters to 0x20-0x7E, following the tag name r ules defiend in the OpenType specification.
203 UChar character = tag[i];
204 if (character < 0x20 || character > 0x7E)
205 return nullptr;
206 }
207
208 int tagValue = 1;
209 // Feature tag values could follow: <integer> | on | off
210 if (range.peek().type() == NumberToken && range.peek().numericValueType() == IntegerValueType && range.peek().numericValue() >= 0) {
211 tagValue = clampTo<int>(range.consumeIncludingWhitespace().numericValue( ));
212 if (tagValue < 0)
213 return nullptr;
214 } else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSValueO ff) {
215 tagValue = range.consumeIncludingWhitespace().id() == CSSValueOn;
216 }
217 return CSSFontFeatureValue::create(tag, tagValue);
218 }
219
220 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontFeatureSettings(CSSParserToke nRange& range)
221 {
222 if (range.peek().id() == CSSValueNormal)
223 return consumeIdent(range);
224 RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparat ed();
225 do {
226 RefPtrWillBeRawPtr<CSSFontFeatureValue> fontFeatureValue = consumeFontFe atureTag(range);
227 if (!fontFeatureValue)
228 return nullptr;
229 settings->append(fontFeatureValue);
230 } while (consumeCommaIncludingWhitespace(range));
231 return settings.release();
232 }
233
145 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range) 234 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange & range)
146 { 235 {
147 if (range.peek().id() == CSSValueAuto) 236 if (range.peek().id() == CSSValueAuto)
148 return consumeIdent(range); 237 return consumeIdent(range);
149 return consumeCustomIdent(range); 238 return consumeCustomIdent(range);
150 } 239 }
151 240
152 // [ <string> <string> ]+ | none
153 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range ) 241 static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range )
154 { 242 {
155 if (range.peek().id() == CSSValueNone) 243 if (range.peek().id() == CSSValueNone)
156 return consumeIdent(range); 244 return consumeIdent(range);
157 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated (); 245 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated ();
158 while (!range.atEnd()) { 246 while (!range.atEnd()) {
159 RefPtrWillBeRawPtr<CSSValue> parsedValue = consumeString(range); 247 RefPtrWillBeRawPtr<CSSValue> parsedValue = consumeString(range);
160 if (!parsedValue) 248 if (!parsedValue)
161 return nullptr; 249 return nullptr;
162 values->append(parsedValue.release()); 250 values->append(parsedValue.release());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 break; 299 break;
212 default: 300 default:
213 return nullptr; 301 return nullptr;
214 } 302 }
215 ligatureValues->append(consumeIdent(range)); 303 ligatureValues->append(consumeIdent(range));
216 } while (!range.atEnd()); 304 } while (!range.atEnd());
217 305
218 return ligatureValues.release(); 306 return ligatureValues.release();
219 } 307 }
220 308
309 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontVariant()
310 {
311 if (m_ruleType != StyleRule::FontFace) {
312 if (m_range.peek().id() != CSSValueNormal && m_range.peek().id() != CSSV alueSmallCaps)
313 return nullptr;
314 return consumeIdent(m_range);
315 }
316 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated ();
317 do {
318 if (m_range.peek().id() == CSSValueAll) {
319 // FIXME: CSSPropertyParser::parseFontVariant() implements
320 // the old css3 draft:
321 // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-variant
322 // 'all' is only allowed in @font-face and with no other values.
323 if (values->length())
324 return nullptr;
325 return consumeIdent(m_range);
326 }
327 if (m_range.peek().id() == CSSValueNormal || m_range.peek().id() == CSSV alueSmallCaps)
328 values->append(consumeIdent(m_range));
329 } while (consumeCommaIncludingWhitespace(m_range));
330
331 if (values->length())
332 return values.release();
333
334 return nullptr;
335 }
336
337 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontWeight(CSSParserTokenRange& r ange)
338 {
339 const CSSParserToken& token = range.peek();
340 if (token.id() >= CSSValueNormal && token.id() <= CSSValueLighter)
341 return consumeIdent(range);
342 if (token.type() != NumberToken || token.numericValueType() != IntegerValueT ype)
343 return nullptr;
344 int weight = static_cast<int>(token.numericValue());
345 if ((weight % 100) || weight < 100 || weight > 900)
346 return nullptr;
347 range.consumeIncludingWhitespace();
348 return cssValuePool().createIdentifierValue(static_cast<CSSValueID>(CSSValue 100 + weight / 100 - 1));
349 }
350
221 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId) 351 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty ID propId)
222 { 352 {
223 m_range.consumeWhitespace(); 353 m_range.consumeWhitespace();
224 switch (propId) { 354 switch (propId) {
225 case CSSPropertyWillChange: 355 case CSSPropertyWillChange:
226 return consumeWillChange(m_range); 356 return consumeWillChange(m_range);
227 case CSSPropertyPage: 357 case CSSPropertyPage:
228 return consumePage(m_range); 358 return consumePage(m_range);
229 case CSSPropertyQuotes: 359 case CSSPropertyQuotes:
230 return consumeQuotes(m_range); 360 return consumeQuotes(m_range);
231 case CSSPropertyWebkitHighlight: 361 case CSSPropertyWebkitHighlight:
232 return consumeWebkitHighlight(m_range); 362 return consumeWebkitHighlight(m_range);
233 case CSSPropertyFontVariantLigatures: 363 case CSSPropertyFontVariantLigatures:
234 return consumeFontVariantLigatures(m_range); 364 return consumeFontVariantLigatures(m_range);
365 case CSSPropertyWebkitFontFeatureSettings:
366 return consumeFontFeatureSettings(m_range);
367 case CSSPropertyFontVariant:
368 return consumeFontVariant();
369 case CSSPropertyFontFamily:
370 return consumeFontFamily();
371 case CSSPropertyFontWeight:
372 return consumeFontWeight(m_range);
235 default: 373 default:
236 return nullptr; 374 return nullptr;
237 } 375 }
238 } 376 }
239 377
378 static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParse rTokenRange& range)
379 {
380 RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated ();
381
382 do {
383 const CSSParserToken& token = range.consumeIncludingWhitespace();
384 if (token.type() != UnicodeRangeToken)
385 return nullptr;
386
387 UChar32 start = token.unicodeRangeStart();
388 UChar32 end = token.unicodeRangeEnd();
389 if (start > end)
390 return nullptr;
391 values->append(CSSUnicodeRangeValue::create(start, end));
392 } while (consumeCommaIncludingWhitespace(range));
393
394 return values.release();
395 }
396
397 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontFaceSrcURI()
398 {
399 String url = consumeUrl(m_range);
400 if (url.isNull())
401 return nullptr;
402 RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create (completeURL(url), m_context.shouldCheckContentSecurityPolicy()));
403 uriValue->setReferrer(m_context.referrer());
404
405 if (m_range.peek().functionId() != CSSValueFormat)
406 return uriValue.release();
407
408 // FIXME: https://drafts.csswg.org/css-fonts says that format() contains a c omma-separated list of strings,
409 // but CSSFontFaceSrcValue stores only one format. Allowing one format for n ow.
410 // FIXME: IdentToken should not be supported here.
411 CSSParserTokenRange args = consumeFunction(m_range);
412 const CSSParserToken& arg = args.consumeIncludingWhitespace();
413 if ((arg.type() != StringToken && arg.type() != IdentToken) || !args.atEnd() )
414 return nullptr;
415 uriValue->setFormat(arg.value());
416 return uriValue.release();
417 }
418
419 static String concatenateFamilyName(CSSParserTokenRange& range)
420 {
421 StringBuilder builder;
422 CSSParserToken token = range.peek();
Timothy Loh 2015/09/18 03:49:18 Copying CSSParserTokens is a bit dodgy, I've been
423 bool addedSpace = false;
424 while (range.peek().type() == IdentToken) {
425 token = range.consumeIncludingWhitespace();
426 if (!builder.isEmpty()) {
427 builder.append(' ');
428 addedSpace = true;
429 }
430 builder.append(token.value());
431 }
432 if (!addedSpace && isCSSWideKeyword(token.id())) {
433 return String();
434 }
435 return builder.toString();
436 }
437
438 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontFaceSrcLocal()
439 {
440 CSSParserTokenRange args = consumeFunction(m_range);
441 if (args.atEnd())
Timothy Loh 2015/09/18 03:49:18 No need to check this I guess. I think the only pl
442 return nullptr;
443
444 ContentSecurityPolicyDisposition shouldCheckContentSecurityPolicy = m_contex t.shouldCheckContentSecurityPolicy();
445 if (args.peek().type() == StringToken) {
446 const CSSParserToken& arg = args.consumeIncludingWhitespace();
447 if (!args.atEnd())
448 return nullptr;
449 return CSSFontFaceSrcValue::createLocal(arg.value(), shouldCheckContentS ecurityPolicy);
450 }
451 if (args.peek().type() == IdentToken) {
452 String familyName = concatenateFamilyName(args);
453 if (!args.atEnd())
454 return nullptr;
455 return CSSFontFaceSrcValue::createLocal(familyName, shouldCheckContentSe curityPolicy);
456 }
457 return nullptr;
458 }
459
460 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFaceSrc()
461 {
462 RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated() );
463
464 do {
465 const CSSParserToken& token = m_range.peek();
466 RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
467 if (token.functionId() == CSSValueLocal)
468 parsedValue = consumeFontFaceSrcLocal();
469 else
470 parsedValue = consumeFontFaceSrcURI();
471 if (!parsedValue)
472 return nullptr;
473 values->append(parsedValue);
474 } while (consumeCommaIncludingWhitespace(m_range));
475 return values.release();
476 }
477
478 static PassRefPtrWillBeRawPtr<CSSValue> consumeFamilyName(CSSParserTokenRange& r ange)
479 {
480 if (range.peek().type() == StringToken)
481 return cssValuePool().createFontFamilyValue(range.consumeIncludingWhites pace().value());
482 if (range.peek().type() != IdentToken)
483 return nullptr;
484 String familyName = concatenateFamilyName(range);
485 if (familyName.isNull())
486 return nullptr;
487 return cssValuePool().createFontFamilyValue(familyName);
488 }
489
490 static PassRefPtrWillBeRawPtr<CSSValue> consumeGenericFamily(CSSParserTokenRange & range)
491 {
492 if (range.peek().id() >= CSSValueSerif && range.peek().id() <= CSSValueWebki tBody)
493 return consumeIdent(range);
494 return nullptr;
495 }
496
497 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFamily()
498 {
499 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated() ;
500 do {
501 RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
502 if (parsedValue = consumeGenericFamily(m_range)) {
503 list->append(parsedValue);
504 } else if (parsedValue = consumeFamilyName(m_range)) {
505 list->append(parsedValue);
506 } else {
507 return nullptr;
508 }
509 } while (consumeCommaIncludingWhitespace(m_range));
510 if (!list->length() || (m_ruleType == StyleRule::FontFace && list->length() > 1))
Timothy Loh 2015/09/18 03:49:18 list is never empty here. Also how about just retu
511 list = nullptr;
512 return list.release();
513 }
514
515 bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId)
516 {
517 RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
518
519 m_range.consumeWhitespace();
520 switch (propId) {
521 case CSSPropertySrc: // This is a list of urls or local references.
522 parsedValue = consumeFontFaceSrc();
523 break;
524 case CSSPropertyUnicodeRange:
525 parsedValue = consumeFontFaceUnicodeRange(m_range);
526 break;
527 case CSSPropertyFontStretch:
528 case CSSPropertyFontStyle: {
529 CSSValueID id = m_range.consumeIncludingWhitespace().id();
530 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id))
531 return false;
532 parsedValue = cssValuePool().createIdentifierValue(id);
533 break;
534 }
535 // TODO(rwlbuis): check there is only one family-name in font-face descripto r case
536 case CSSPropertyFontFamily:
537 case CSSPropertyFontVariant:
538 case CSSPropertyFontWeight:
539 case CSSPropertyWebkitFontFeatureSettings:
540 parsedValue = parseSingleValue(propId);
541 break;
542 default:
543 break;
544 }
545
546 if (!parsedValue || !m_range.atEnd())
547 return false;
548
549 addProperty(propId, parsedValue.release(), false);
550 return true;
551 }
552
240 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) 553 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important)
241 { 554 {
242 m_range.consumeWhitespace(); 555 m_range.consumeWhitespace();
243 switch (propId) { 556 switch (propId) {
244 case CSSPropertyWebkitMarginCollapse: { 557 case CSSPropertyWebkitMarginCollapse: {
245 CSSValueID id = m_range.consumeIncludingWhitespace().id(); 558 CSSValueID id = m_range.consumeIncludingWhitespace().id();
246 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) 559 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id))
247 return false; 560 return false;
248 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); 561 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id);
249 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); 562 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant);
(...skipping 28 matching lines...) Expand all
278 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); 591 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important);
279 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); 592 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important);
280 return true; 593 return true;
281 } 594 }
282 default: 595 default:
283 return false; 596 return false;
284 } 597 }
285 } 598 }
286 599
287 } // namespace blink 600 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/css/parser/CSSPropertyParser.h ('k') | Source/core/css/parser/LegacyCSSPropertyParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698