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

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: Patch for review 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 2e6c483da002877dc8980b5b0be85f790357171b..974a0b660bc3532a5d439263b2a0560786cbf3e8 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,44 @@ static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeString(CSSParserTokenRan
return cssValuePool().createValue(range.consumeIncludingWhitespace().value(), CSSPrimitiveValue::UnitType::String);
}
+static bool tryConsumeUrl(CSSParserTokenRange& valueList, String& urlValue)
Timothy Loh 2015/09/15 02:01:05 "consumeUrl" is fine I think. Also maybe we can re
+{
+ const CSSParserToken& token = valueList.peek();
+ if (token.type() == FunctionToken) {
+ if (!token.valueEqualsIgnoringCase("url"))
Timothy Loh 2015/09/15 02:01:05 functionId?
+ return false;
+
+ CSSParserTokenRange urlArgs = valueList.consumeBlock();
+ const CSSParserToken& next = urlArgs.consumeIncludingWhitespace();
+ if (next.type() == BadStringToken)
Timothy Loh 2015/09/15 02:01:05 || EOFToken I think? (i.e. "url()")
Timothy Loh 2015/09/15 03:05:04 Whoops, url() makes a UrlToken.
+ return false;
+ ASSERT(next.type() == StringToken);
+ urlValue = next.value();
+ valueList.consumeWhitespace();
Timothy Loh 2015/09/15 02:01:05 Should check whether the inner range is atEnd()
+ return true;
+ }
+ if (token.type() == UrlToken) {
Timothy Loh 2015/09/15 02:01:05 I think it'd be nicer if this check was before the
+ urlValue = token.value();
+ valueList.consumeIncludingWhitespace();
+ return true;
+ }
+
+ return false;
+}
+
+static CSSParserTokenRange consumeFunction(CSSParserTokenRange& valueList)
+{
+ ASSERT(valueList.peek().type() == FunctionToken);
+ CSSParserTokenRange ret = valueList.consumeBlock();
Timothy Loh 2015/09/15 02:01:05 ret -> result? contents?
+ valueList.consumeWhitespace();
+ return ret;
+}
+
+static inline bool isComma(const CSSParserToken& value)
+{
+ return value.type() == CommaToken;
+}
+
// Methods for consuming non-shorthand properties starts here.
static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& range)
{
@@ -142,6 +184,114 @@ static PassRefPtrWillBeRawPtr<CSSValue> consumeWillChange(CSSParserTokenRange& r
return values.release();
}
+static PassRefPtrWillBeRawPtr<CSSValue> consumeFontVariantLigatures(CSSParserTokenRange& range)
+{
+ if (range.peek().id() == CSSValueNormal)
+ return consumeIdent(range);
+ RefPtrWillBeRawPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated();
+ bool sawCommonLigaturesValue = false;
+ bool sawDiscretionaryLigaturesValue = false;
+ bool sawHistoricalLigaturesValue = false;
+ bool sawContextualLigaturesValue = false;
+
+ while (!range.atEnd()) {
Timothy Loh 2015/09/15 02:01:05 do { } while (!range.atEnd()); return ligatureVa
+ if (range.peek().type() != IdentToken)
Timothy Loh 2015/09/15 02:01:05 No need to check this since id() will just return
+ return nullptr;
+
+ CSSValueID id = range.peek().id();
+ switch (id) {
+ case CSSValueNoCommonLigatures:
+ case CSSValueCommonLigatures:
+ if (sawCommonLigaturesValue)
+ return nullptr;
+ sawCommonLigaturesValue = true;
+ ligatureValues->append(consumeIdent(range));
Timothy Loh 2015/09/15 02:01:05 Probably nicer outside of the switch statement so
+ break;
+ case CSSValueNoDiscretionaryLigatures:
+ case CSSValueDiscretionaryLigatures:
+ if (sawDiscretionaryLigaturesValue)
+ return nullptr;
+ sawDiscretionaryLigaturesValue = true;
+ ligatureValues->append(consumeIdent(range));
+ break;
+ case CSSValueNoHistoricalLigatures:
+ case CSSValueHistoricalLigatures:
+ if (sawHistoricalLigaturesValue)
+ return nullptr;
+ sawHistoricalLigaturesValue = true;
+ ligatureValues->append(consumeIdent(range));
+ break;
+ case CSSValueNoContextual:
+ case CSSValueContextual:
+ if (sawContextualLigaturesValue)
+ return nullptr;
+ sawContextualLigaturesValue = true;
+ ligatureValues->append(consumeIdent(range));
+ break;
+ default:
+ return nullptr;
+ }
+ }
+
+ if (!ligatureValues->length())
+ return nullptr;
+
+ return ligatureValues.release();
+}
+
+static bool consumeFontFeatureTag(CSSParserTokenRange& range, CSSValueList* settings)
+{
+ // Feature tag name consists of 4-letter characters.
+ static const unsigned tagNameLength = 4;
+
+ CSSParserToken token = range.peek();
+ // Feature tag name comes first
+ if (token.type() != StringToken)
+ return false;
+ if (token.value().length() != tagNameLength)
+ return false;
+ 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 false;
+ }
+
+ int tagValue = 1;
+ // Feature tag values could follow: <integer> | on | off
+ range.consumeIncludingWhitespace();
+ if (!range.atEnd()) {
+ if (range.peek().type() == NumberToken && range.peek().numericValueType() == IntegerValueType && range.peek().numericValue() >= 0) {
+ tagValue = clampTo<int>(range.peek().numericValue());
+ if (tagValue < 0)
+ return false;
+ range.consumeIncludingWhitespace();
+ } else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSValueOff) {
+ tagValue = range.peek().id() == CSSValueOn;
+ range.consumeIncludingWhitespace();
+ }
+ }
+ settings->append(CSSFontFeatureValue::create(tag, tagValue));
+ return true;
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeFontFeatureSettings(CSSParserTokenRange& range)
+{
+ if (range.peek().id() == CSSValueNormal)
+ return consumeIdent(range);
+ RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparated();
+ while (true) {
+ if (range.atEnd() || !consumeFontFeatureTag(range, settings.get()))
+ return nullptr;
+ if (range.atEnd())
+ break;
+ if (!consumeCommaIncludingWhitespace(range))
+ return nullptr;
+ }
+ return settings.release();
+}
+
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePage(CSSParserTokenRange& range)
{
if (range.peek().id() == CSSValueAuto)
@@ -173,6 +323,82 @@ static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitHighlight(CSSParserTokenRan
return consumeString(range);
}
+// normal | small-caps | inherit
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeFontVariant()
+{
+ RefPtrWillBeRawPtr<CSSValueList> values = nullptr;
+ bool expectComma = false;
+ while (!m_range.atEnd()) {
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = nullptr;
+ if (!expectComma) {
+ expectComma = true;
+ if (m_range.peek().id() == CSSValueNormal || m_range.peek().id() == CSSValueSmallCaps) {
+ parsedValue = consumeIdent(m_range);
+ } else if (m_range.peek().id() == CSSValueAll && !values) {
+ // 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. Make a value list to
+ // indicate that we are in the @font-face case.
+ values = CSSValueList::createCommaSeparated();
+ parsedValue = consumeIdent(m_range);
+ }
+ } else if (consumeCommaIncludingWhitespace(m_range)) {
+ expectComma = false;
+ continue;
+ }
+
+ if (!parsedValue)
+ return nullptr;
+
+ if (isComma(m_range.peek()))
+ values = CSSValueList::createCommaSeparated();
+
+ if (values)
+ values->append(parsedValue.release());
+ else
+ return parsedValue.release();
+ }
+
+ if (values && values->length()) {
+ if (m_ruleType != StyleRule::FontFace)
+ return nullptr;
+ return values.release();
+ }
+
+ return nullptr;
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitLocale(CSSParserTokenRange& range)
+{
+ if (range.peek().id() == CSSValueAuto)
+ return consumeIdent(range);
+ return consumeString(range);
+}
+
+// none | all | 1 (will be dropped in the unprefixed property)
+static PassRefPtrWillBeRawPtr<CSSValue> consumeWebkitColumnSpan(CSSParserTokenRange& range)
+{
+ if (range.peek().id() == CSSValueAll || range.peek().id() == CSSValueNone)
+ return consumeIdent(range);
+ if (range.peek().type() == NumberToken && range.peek().numericValue() == 1) {
+ const CSSParserToken& columnSpan = range.consumeIncludingWhitespace();
+ return cssValuePool().createValue(columnSpan.numericValue(), columnSpan.unitType());
+ }
+ return nullptr;
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeTextAlign(CSSParserTokenRange& range)
+{
+ // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent
+ // | start | end | <string> | inherit | -webkit-auto (converted to start)
+ // FIXME: <string> not supported right now
+ CSSValueID id = range.peek().id();
+ if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd)
+ return consumeIdent(range);
+ return nullptr;
+}
+
PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID propId)
{
m_range.consumeWhitespace();
@@ -185,11 +411,177 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty
return consumeQuotes(m_range);
case CSSPropertyWebkitHighlight:
return consumeWebkitHighlight(m_range);
+ case CSSPropertyFontVariantLigatures:
+ return consumeFontVariantLigatures(m_range);
+ case CSSPropertyWebkitFontFeatureSettings:
+ return consumeFontFeatureSettings(m_range);
+ case CSSPropertyFontVariant:
+ return consumeFontVariant();
+ case CSSPropertyWebkitHyphenateCharacter:
+ case CSSPropertyWebkitLocale:
+ return consumeWebkitLocale(m_range);
+ case CSSPropertyWebkitColumnSpan:
Timothy Loh 2015/09/15 02:01:05 let's leave the properties which aren't font-face
+ return consumeWebkitColumnSpan(m_range);
+ case CSSPropertyTextAlign:
+ return consumeTextAlign(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));
Timothy Loh 2015/09/15 02:01:05 I like this comma-separated-list pattern, can we d
+
+ return values.release();
+}
+
+bool CSSPropertyParser::consumeFontFaceSrcURI(CSSValueList* valueList)
+{
+ String url;
+ if (!tryConsumeUrl(m_range, url))
+ return false;
+ RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(url), m_context.shouldCheckContentSecurityPolicy()));
+ uriValue->setReferrer(m_context.referrer());
+
+ if (m_range.atEnd() || m_range.peek().type() != FunctionToken || m_range.peek().functionId() != CSSValueFormat) {
Timothy Loh 2015/09/15 02:01:05 No need to check atEnd() or type() here, functionI
+ valueList->append(uriValue.release());
+ return true;
+ }
+
+ // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format() contains a comma-separated list of strings,
+ // but CSSFontFaceSrcValue stores only one format. Allowing one format for now.
+ CSSParserTokenRange args = consumeFunction(m_range);
+ if (args.atEnd() || (args.peek().type() != StringToken && args.peek().type() != IdentToken))
Timothy Loh 2015/09/15 02:01:05 No need for atEnd() here.
+ return false;
+ uriValue->setFormat(args.consumeIncludingWhitespace().value());
+ valueList->append(uriValue.release());
+ return true;
+}
+
+bool CSSPropertyParser::consumeFontFaceSrcLocal(CSSValueList* valueList)
+{
+ CSSParserTokenRange args = consumeFunction(m_range);
+ if (args.atEnd())
+ return false;
+
+ const CSSParserToken& arg = args.consumeIncludingWhitespace();
+ ContentSecurityPolicyDisposition shouldCheckContentSecurityPolicy = m_context.shouldCheckContentSecurityPolicy();
+ if (arg.type() == StringToken) {
+ if (!args.atEnd())
+ return false;
+ valueList->append(CSSFontFaceSrcValue::createLocal(arg.value(), shouldCheckContentSecurityPolicy));
+ } else if (arg.type() == IdentToken) {
+ StringBuilder builder;
+ builder.append(arg.value());
+ while (!args.atEnd()) {
+ CSSParserToken localValue = args.consumeIncludingWhitespace();
+ if (localValue.type() != IdentToken)
+ return false;
+ if (!builder.isEmpty())
+ builder.append(' ');
+ builder.append(localValue.value());
+ }
+ valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString(), shouldCheckContentSecurityPolicy));
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::consumeFontFaceSrc()
+{
+ RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
+
+ while (true) {
+ const CSSParserToken& token = m_range.peek();
+ if (token.type() == FunctionToken && token.functionId() == CSSValueLocal) {
+ if (!consumeFontFaceSrcLocal(values.get()))
+ return nullptr;
+ } else if (!consumeFontFaceSrcURI(values.get())) {
+ return nullptr;
+ }
+
+ if (m_range.atEnd())
+ return values.release();
+ if (!consumeCommaIncludingWhitespace(m_range))
+ return nullptr;
+ }
+}
+
+bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId)
+{
+ RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr;
+
+ m_range.consumeWhitespace();
+ switch (propId) {
+ case CSSPropertyFontFamily:
+ // <family-name>
+ // TODO(rwlbuis): check there is only one family-name
+ parsedValue = parseFontFamily();
+ break;
+ case CSSPropertySrc: // This is a list of urls or local references.
+ parsedValue = consumeFontFaceSrc();
+ if (parsedValue && m_range.atEnd()) {
+ addProperty(CSSPropertySrc, parsedValue.release(), false);
+ return true;
+ }
+ break;
+ case CSSPropertyUnicodeRange:
+ parsedValue = consumeFontFaceUnicodeRange(m_range);
+ if (parsedValue && m_range.atEnd()) {
+ addProperty(CSSPropertyUnicodeRange, parsedValue.release(), false);
+ return true;
+ }
+ break;
+ case CSSPropertyFontWeight: // normal | bold | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
+ return parseFontWeight(false) && !m_valueList->next();
+ case CSSPropertyFontStretch:
+ case CSSPropertyFontStyle: {
+ CSSValueID id = m_range.consumeIncludingWhitespace().id();
+ if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id))
+ return false;
+ addProperty(propId, cssValuePool().createIdentifierValue(id), false);
+ return true;
+ }
+ case CSSPropertyFontVariant: // normal | small-caps | inherit
+ parsedValue = consumeFontVariant();
+ if (parsedValue && m_range.atEnd()) {
+ addProperty(CSSPropertyFontVariant, parsedValue.release(), false);
+ return true;
+ }
+ break;
+ case CSSPropertyWebkitFontFeatureSettings:
+ parsedValue = parseSingleValue(propId);
+ if (parsedValue && m_range.atEnd()) {
+ addProperty(CSSPropertyWebkitFontFeatureSettings, parsedValue.release(), false);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!parsedValue || m_valueList->current())
+ 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