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

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