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

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