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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/css/parser/CSSPropertyParser.h ('k') | Source/core/css/parser/LegacyCSSPropertyParser.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/parser/CSSPropertyParser.cpp
diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp
index 2344e5bd7981234feaa353bd3d811bc36d9c2bb2..398fc32aa9145d8d53f1ecdfafc86f894af3a645 100644
--- a/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/Source/core/css/parser/CSSPropertyParser.cpp
@@ -7,10 +7,14 @@
#include "core/StylePropertyShorthand.h"
#include "core/css/CSSCalculationValue.h"
+#include "core/css/CSSFontFaceSrcValue.h"
+#include "core/css/CSSFontFeatureValue.h"
+#include "core/css/CSSUnicodeRangeValue.h"
#include "core/css/CSSValuePool.h"
#include "core/css/parser/CSSParserFastPaths.h"
#include "core/css/parser/CSSParserValues.h"
#include "core/frame/UseCounter.h"
+#include "wtf/text/StringBuilder.h"
namespace blink {
@@ -91,6 +95,42 @@ static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan
return cssValuePool().createValue(range.consumeIncludingWhitespace().value(), CSSPrimitiveValue::UnitType::String);
}
+static String consumeUrl(CSSParserTokenRange& range)
+{
+ const CSSParserToken& token = range.peek();
+ if (token.type() == UrlToken) {
+ range.consumeIncludingWhitespace();
+ return token.value();
+ }
+ if (token.functionId() == CSSValueUrl) {
+ CSSParserTokenRange urlRange = range;
+ CSSParserTokenRange urlArgs = urlRange.consumeBlock();
+ const CSSParserToken& next = urlArgs.consumeIncludingWhitespace();
+ if (next.type() == BadStringToken || !urlArgs.atEnd())
+ return String();
+ ASSERT(next.type() == StringToken);
+ range = urlRange;
+ range.consumeWhitespace();
+ return next.value();
+ }
+
+ return String();
+}
+
+static CSSParserTokenRange consumeFunction(CSSParserTokenRange& range)
+{
+ ASSERT(range.peek().type() == FunctionToken);
+ CSSParserTokenRange contents = range.consumeBlock();
+ range.consumeWhitespace();
+ contents.consumeWhitespace();
+ return contents;
+}
+
+static inline bool isCSSWideKeyword(const CSSValueID& id)
+{
+ return id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset || id == CSSValueDefault;
+}
+
// Methods for consuming non-shorthand properties starts here.
static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& range)
{
@@ -142,6 +182,51 @@ static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r
return values.release();
}
+static PassRefPtrWillBeRawPtr<CSSFontFeatureValue> consumeFontFeatureTag(CSSParserTokenRange& range)
+{
+ // Feature tag name consists of 4-letter characters.
+ static const unsigned tagNameLength = 4;
+
+ const CSSParserToken& token = range.consumeIncludingWhitespace();
+ // Feature tag name comes first
+ if (token.type() != StringToken)
+ return nullptr;
+ if (token.value().length() != tagNameLength)
+ return nullptr;
+ AtomicString tag = token.value();
+ for (unsigned i = 0; i < tagNameLength; ++i) {
+ // Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
+ UChar character = tag[i];
+ if (character < 0x20 || character > 0x7E)
+ return nullptr;
+ }
+
+ int tagValue = 1;
+ // Feature tag values could follow: <integer> | on | off
+ if (range.peek().type() == NumberToken && range.peek().numericValueType() == IntegerValueType && range.peek().numericValue() >= 0) {
+ tagValue = clampTo<int>(range.consumeIncludingWhitespace().numericValue());
+ if (tagValue < 0)
+ return nullptr;
+ } else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSValueOff) {
+ tagValue = range.consumeIncludingWhitespace().id() == CSSValueOn;
+ }
+ return CSSFontFeatureValue::create(tag, tagValue);
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeFontFeatureSettings(CSSParserTokenRange& range)
+{
+ if (range.peek().id() == CSSValueNormal)
+ return consumeIdent(range);
+ RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparated();
+ do {
+ RefPtrWillBeRawPtr<CSSFontFeatureValue> fontFeatureValue = consumeFontFeatureTag(range);
+ if (!fontFeatureValue)
+ return nullptr;
+ settings->append(fontFeatureValue);
+ } while (consumeCommaIncludingWhitespace(range));
+ return settings.release();
+}
+
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange& range)
{
if (range.peek().id() == CSSValueAuto)
@@ -149,7 +234,6 @@ static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange
return consumeCustomIdent(range);
}
-// [ <string> <string> ]+ | none
static PassRefPtrWillBeRawPtr<CSSValue> consumeQuotes(CSSParserTokenRange& range)
{
if (range.peek().id() == CSSValueNone)
@@ -218,6 +302,48 @@ static PassRefPtrWillBeRawPtr<CSSValue> consumeFontVariantLigatures(CSSParserTok
return ligatureValues.release();
}
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontVariant()
+{
+ if (m_ruleType != StyleRule::FontFace) {
+ if (m_range.peek().id() != CSSValueNormal && m_range.peek().id() != CSSValueSmallCaps)
+ return nullptr;
+ return consumeIdent(m_range);
+ }
+ RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
+ do {
+ if (m_range.peek().id() == CSSValueAll) {
+ // FIXME: CSSPropertyParser::parseFontVariant() implements
+ // the old css3 draft:
+ // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-variant
+ // 'all' is only allowed in @font-face and with no other values.
+ if (values->length())
+ return nullptr;
+ return consumeIdent(m_range);
+ }
+ if (m_range.peek().id() == CSSValueNormal || m_range.peek().id() == CSSValueSmallCaps)
+ values->append(consumeIdent(m_range));
+ } while (consumeCommaIncludingWhitespace(m_range));
+
+ if (values->length())
+ return values.release();
+
+ return nullptr;
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeFontWeight(CSSParserTokenRange& range)
+{
+ const CSSParserToken& token = range.peek();
+ if (token.id() >= CSSValueNormal && token.id() <= CSSValueLighter)
+ return consumeIdent(range);
+ if (token.type() != NumberToken || token.numericValueType() != IntegerValueType)
+ return nullptr;
+ int weight = static_cast<int>(token.numericValue());
+ if ((weight % 100) || weight < 100 || weight > 900)
+ return nullptr;
+ range.consumeIncludingWhitespace();
+ return cssValuePool().createIdentifierValue(static_cast<CSSValueID>(CSSValue100 + weight / 100 - 1));
+}
+
PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID propId)
{
m_range.consumeWhitespace();
@@ -232,11 +358,190 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty
return consumeWebkitHighlight(m_range);
case CSSPropertyFontVariantLigatures:
return consumeFontVariantLigatures(m_range);
+ case CSSPropertyWebkitFontFeatureSettings:
+ return consumeFontFeatureSettings(m_range);
+ case CSSPropertyFontVariant:
+ return consumeFontVariant();
+ case CSSPropertyFontFamily:
+ return consumeFontFamily();
+ case CSSPropertyFontWeight:
+ return consumeFontWeight(m_range);
default:
return nullptr;
}
}
+static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParserTokenRange& range)
+{
+ RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
+
+ do {
+ const CSSParserToken& token = range.consumeIncludingWhitespace();
+ if (token.type() != UnicodeRangeToken)
+ return nullptr;
+
+ UChar32 start = token.unicodeRangeStart();
+ UChar32 end = token.unicodeRangeEnd();
+ if (start > end)
+ return nullptr;
+ values->append(CSSUnicodeRangeValue::create(start, end));
+ } while (consumeCommaIncludingWhitespace(range));
+
+ return values.release();
+}
+
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontFaceSrcURI()
+{
+ String url = consumeUrl(m_range);
+ if (url.isNull())
+ return nullptr;
+ RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(url), m_context.shouldCheckContentSecurityPolicy()));
+ uriValue->setReferrer(m_context.referrer());
+
+ if (m_range.peek().functionId() != CSSValueFormat)
+ return uriValue.release();
+
+ // FIXME: https://drafts.csswg.org/css-fonts says that format() contains a comma-separated list of strings,
+ // but CSSFontFaceSrcValue stores only one format. Allowing one format for now.
+ // FIXME: IdentToken should not be supported here.
+ CSSParserTokenRange args = consumeFunction(m_range);
+ const CSSParserToken& arg = args.consumeIncludingWhitespace();
+ if ((arg.type() != StringToken && arg.type() != IdentToken) || !args.atEnd())
+ return nullptr;
+ uriValue->setFormat(arg.value());
+ return uriValue.release();
+}
+
+static String concatenateFamilyName(CSSParserTokenRange& range)
+{
+ StringBuilder builder;
+ bool addedSpace = false;
+ const CSSParserToken& firstToken = range.peek();
+ while (range.peek().type() == IdentToken) {
+ if (!builder.isEmpty()) {
+ builder.append(' ');
+ addedSpace = true;
+ }
+ builder.append(range.consumeIncludingWhitespace().value());
+ }
+ if (!addedSpace && isCSSWideKeyword(firstToken.id())) {
+ return String();
+}
+ return builder.toString();
+}
+
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontFaceSrcLocal()
+{
+ CSSParserTokenRange args = consumeFunction(m_range);
+ ContentSecurityPolicyDisposition shouldCheckContentSecurityPolicy = m_context.shouldCheckContentSecurityPolicy();
+ if (args.peek().type() == StringToken) {
+ const CSSParserToken& arg = args.consumeIncludingWhitespace();
+ if (!args.atEnd())
+ return nullptr;
+ return CSSFontFaceSrcValue::createLocal(arg.value(), shouldCheckContentSecurityPolicy);
+ }
+ if (args.peek().type() == IdentToken) {
+ String familyName = concatenateFamilyName(args);
+ if (!args.atEnd())
+ return nullptr;
+ return CSSFontFaceSrcValue::createLocal(familyName, shouldCheckContentSecurityPolicy);
+ }
+ return nullptr;
+}
+
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFaceSrc()
+{
+ RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
+
+ do {
+ const CSSParserToken& token = m_range.peek();
+ RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
+ if (token.functionId() == CSSValueLocal)
+ parsedValue = consumeFontFaceSrcLocal();
+ else
+ parsedValue = consumeFontFaceSrcURI();
+ if (!parsedValue)
+ return nullptr;
+ values->append(parsedValue);
+ } while (consumeCommaIncludingWhitespace(m_range));
+ return values.release();
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeFamilyName(CSSParserTokenRange& range)
+{
+ if (range.peek().type() == StringToken)
+ return cssValuePool().createFontFamilyValue(range.consumeIncludingWhitespace().value());
+ if (range.peek().type() != IdentToken)
+ return nullptr;
+ String familyName = concatenateFamilyName(range);
+ if (familyName.isNull())
+ return nullptr;
+ return cssValuePool().createFontFamilyValue(familyName);
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeGenericFamily(CSSParserTokenRange& range)
+{
+ if (range.peek().id() >= CSSValueSerif && range.peek().id() <= CSSValueWebkitBody)
+ return consumeIdent(range);
+ return nullptr;
+}
+
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFamily()
+{
+ RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ do {
+ RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
+ if ((parsedValue = consumeGenericFamily(m_range))) {
+ list->append(parsedValue);
+ } else if ((parsedValue = consumeFamilyName(m_range))) {
+ list->append(parsedValue);
+ } else {
+ return nullptr;
+ }
+ } while (consumeCommaIncludingWhitespace(m_range));
+ if (m_ruleType == StyleRule::FontFace && list->length() > 1)
+ return nullptr;
+ return list.release();
+}
+
+bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId)
+{
+ RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
+
+ m_range.consumeWhitespace();
+ switch (propId) {
+ case CSSPropertySrc: // This is a list of urls or local references.
+ parsedValue = consumeFontFaceSrc();
+ break;
+ case CSSPropertyUnicodeRange:
+ parsedValue = consumeFontFaceUnicodeRange(m_range);
+ break;
+ case CSSPropertyFontStretch:
+ case CSSPropertyFontStyle: {
+ CSSValueID id = m_range.consumeIncludingWhitespace().id();
+ if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id))
+ return false;
+ parsedValue = cssValuePool().createIdentifierValue(id);
+ break;
+ }
+ // TODO(rwlbuis): check there is only one family-name in font-face descriptor case
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontVariant:
+ case CSSPropertyFontWeight:
+ case CSSPropertyWebkitFontFeatureSettings:
+ parsedValue = parseSingleValue(propId);
+ break;
+ default:
+ break;
+ }
+
+ if (!parsedValue || !m_range.atEnd())
+ return false;
+
+ addProperty(propId, parsedValue.release(), false);
+ return true;
+}
+
bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important)
{
m_range.consumeWhitespace();
« 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