Commit 8b4edde0 authored by Dominik Röttsches's avatar Dominik Röttsches Committed by Commit Bot

Parse ranges for font-style in @font-face

Allow ranges for font-style in @font-face, compare
https://drafts.csswg.org/css-fonts-4/#font-prop-desc and support the
oblique <angle> style property of CSS Fonts Level 4.

Bug: 749091
Change-Id: I7888f2f01f3cda8ec1b8d5c13b884f75b1790e50
Reviewed-on: https://chromium-review.googlesource.com/600228
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarBugs Nash <bugsnash@chromium.org>
Reviewed-by: default avatarRune Lillesveen <rune@opera.com>
Cr-Commit-Position: refs/heads/master@{#491978}
parent 943ec8a0
...@@ -21,12 +21,15 @@ var styleValidTests = { ...@@ -21,12 +21,15 @@ var styleValidTests = {
'calc(100 + 300)', 'calc(100 + 300)',
'calc(0.2 + 205.5)', 'calc(0.2 + 205.5)',
], ],
'stretch': ['51%', '199%', 'calc(10% + 20%)'] 'stretch': ['51%', '199%', 'calc(10% + 20%)'],
'style' : [ 'normal', 'italic', 'oblique', 'oblique 50deg', 'oblique -90deg', 'oblique 90deg',
'oblique calc(30deg + 20deg)' ]
}; };
var styleInvalidTests = { var styleInvalidTests = {
'weight': ['100 400', 'calc(0 - 100)', 'calc(200 + 801)'], 'weight': ['100 400', 'calc(0 - 100)', 'calc(200 + 801)'],
'stretch': ['100% 110%', '0%', '100% 150%', 'calc(1 + 10%)'] 'stretch': ['100% 110%', '0%', '100% 150%', 'calc(1 + 10%)'],
'style' : [ 'normal 10deg', 'italic 10deg', 'oblique -91deg', 'oblique 91deg', 'oblique calc(90deg + 20deg)']
}; };
function testParseStyle() { function testParseStyle() {
...@@ -70,6 +73,13 @@ var faceTests = { ...@@ -70,6 +73,13 @@ var faceTests = {
['ultra-condensed', 'ultra-condensed'], ['ultra-condensed', 'ultra-condensed'],
['ultra-expanded', 'ultra-expanded'], ['ultra-expanded', 'ultra-expanded'],
], ],
'style' : [
[ "normal", "normal" ],
[ "italic", "italic" ],
[ "oblique", "oblique" ],
[ "oblique 10deg", "oblique 10deg" ],
[ "oblique 10deg 20deg", "oblique 10deg 20deg" ]
]
}; };
var faceInvalidTests = { var faceInvalidTests = {
...@@ -90,6 +100,8 @@ var faceInvalidTests = { ...@@ -90,6 +100,8 @@ var faceInvalidTests = {
'-0.5%', '-1%', '0%', 'calc(0% - 10%)', '60% 70% 80%', 'a%', 'a b c', '0.1', '-0.5%', '-1%', '0%', 'calc(0% - 10%)', '60% 70% 80%', 'a%', 'a b c', '0.1',
'-60% 80%', 'ultra-expannnned', '50% 0' '-60% 80%', 'ultra-expannnned', '50% 0'
], ],
'style' : [ 'oblique 100deg', 'oblique italic', 'oblique -91deg', 'oblique 0',
'oblique 10', 'iiitalic', '90deg', '11', 'italic 90deg' ]
}; };
function testParseFace() { function testParseFace() {
......
...@@ -166,7 +166,7 @@ const CSSValue* ConsumeSingleType(const CSSSyntaxComponent& syntax, ...@@ -166,7 +166,7 @@ const CSSValue* ConsumeSingleType(const CSSSyntaxComponent& syntax,
case CSSSyntaxType::kInteger: case CSSSyntaxType::kInteger:
return ConsumeInteger(range); return ConsumeInteger(range);
case CSSSyntaxType::kAngle: case CSSSyntaxType::kAngle:
return ConsumeAngle(range, *context, WTF::Optional<WebFeature>()); return ConsumeAngle(range, context, WTF::Optional<WebFeature>());
case CSSSyntaxType::kTime: case CSSSyntaxType::kTime:
return ConsumeTime(range, ValueRange::kValueRangeAll); return ConsumeTime(range, ValueRange::kValueRangeAll);
case CSSSyntaxType::kResolution: case CSSSyntaxType::kResolution:
......
...@@ -588,7 +588,8 @@ bool CSSPropertyParser::ParseFontFaceDescriptor(CSSPropertyID prop_id) { ...@@ -588,7 +588,8 @@ bool CSSPropertyParser::ParseFontFaceDescriptor(CSSPropertyID prop_id) {
range_, kCSSFontFaceRuleMode); range_, kCSSFontFaceRuleMode);
break; break;
case CSSPropertyFontStyle: case CSSPropertyFontStyle:
parsed_value = CSSPropertyFontUtils::ConsumeFontStyle(range_); parsed_value =
CSSPropertyFontUtils::ConsumeFontStyle(range_, kCSSFontFaceRuleMode);
break; break;
case CSSPropertyFontVariant: case CSSPropertyFontVariant:
parsed_value = ConsumeFontVariantList(range_); parsed_value = ConsumeFontVariantList(range_);
......
...@@ -338,8 +338,11 @@ CSSPrimitiveValue* ConsumeGradientLengthOrPercent( ...@@ -338,8 +338,11 @@ CSSPrimitiveValue* ConsumeGradientLengthOrPercent(
} }
CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange& range, CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange& range,
const CSSParserContext& context, const CSSParserContext* context,
WTF::Optional<WebFeature> unitlessZeroFeature) { WTF::Optional<WebFeature> unitlessZeroFeature) {
// Ensure that we have a context for counting the unitlessZeroFeature if it is
// requested.
DCHECK(context || !unitlessZeroFeature);
const CSSParserToken& token = range.Peek(); const CSSParserToken& token = range.Peek();
if (token.GetType() == kDimensionToken) { if (token.GetType() == kDimensionToken) {
switch (token.GetUnitType()) { switch (token.GetUnitType()) {
...@@ -357,7 +360,7 @@ CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange& range, ...@@ -357,7 +360,7 @@ CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange& range,
if (token.GetType() == kNumberToken && token.NumericValue() == 0 && if (token.GetType() == kNumberToken && token.NumericValue() == 0 &&
unitlessZeroFeature) { unitlessZeroFeature) {
range.ConsumeIncludingWhitespace(); range.ConsumeIncludingWhitespace();
context.Count(*unitlessZeroFeature); context->Count(*unitlessZeroFeature);
return CSSPrimitiveValue::Create(0, CSSPrimitiveValue::UnitType::kDegrees); return CSSPrimitiveValue::Create(0, CSSPrimitiveValue::UnitType::kDegrees);
} }
CalcParser calc_parser(range, kValueRangeAll); CalcParser calc_parser(range, kValueRangeAll);
...@@ -982,7 +985,7 @@ static CSSPrimitiveValue* ConsumeGradientAngleOrPercent( ...@@ -982,7 +985,7 @@ static CSSPrimitiveValue* ConsumeGradientAngleOrPercent(
UnitlessQuirk) { UnitlessQuirk) {
const CSSParserToken& token = range.Peek(); const CSSParserToken& token = range.Peek();
if (token.GetType() == kDimensionToken || token.GetType() == kNumberToken) { if (token.GetType() == kDimensionToken || token.GetType() == kNumberToken) {
return ConsumeAngle(range, context, WTF::Optional<WebFeature>()); return ConsumeAngle(range, &context, WTF::Optional<WebFeature>());
} }
if (token.GetType() == kPercentageToken) if (token.GetType() == kPercentageToken)
return ConsumePercent(range, value_range); return ConsumePercent(range, value_range);
...@@ -1185,7 +1188,7 @@ static CSSValue* ConsumeLinearGradient(CSSParserTokenRange& args, ...@@ -1185,7 +1188,7 @@ static CSSValue* ConsumeLinearGradient(CSSParserTokenRange& args,
CSSGradientType gradient_type) { CSSGradientType gradient_type) {
bool expect_comma = true; bool expect_comma = true;
const CSSPrimitiveValue* angle = const CSSPrimitiveValue* angle =
ConsumeAngle(args, context, WebFeature::kUnitlessZeroAngleGradient); ConsumeAngle(args, &context, WebFeature::kUnitlessZeroAngleGradient);
const CSSIdentifierValue* end_x = nullptr; const CSSIdentifierValue* end_x = nullptr;
const CSSIdentifierValue* end_y = nullptr; const CSSIdentifierValue* end_y = nullptr;
if (!angle) { if (!angle) {
...@@ -1226,7 +1229,7 @@ static CSSValue* ConsumeConicGradient(CSSParserTokenRange& args, ...@@ -1226,7 +1229,7 @@ static CSSValue* ConsumeConicGradient(CSSParserTokenRange& args,
const CSSPrimitiveValue* from_angle = nullptr; const CSSPrimitiveValue* from_angle = nullptr;
if (ConsumeIdent<CSSValueFrom>(args)) { if (ConsumeIdent<CSSValueFrom>(args)) {
if (!(from_angle = if (!(from_angle =
ConsumeAngle(args, context, WTF::Optional<WebFeature>()))) ConsumeAngle(args, &context, WTF::Optional<WebFeature>())))
return nullptr; return nullptr;
} }
......
...@@ -59,7 +59,7 @@ CSSPrimitiveValue* ConsumeLengthOrPercent( ...@@ -59,7 +59,7 @@ CSSPrimitiveValue* ConsumeLengthOrPercent(
UnitlessQuirk = UnitlessQuirk::kForbid); UnitlessQuirk = UnitlessQuirk::kForbid);
CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange&, CSSPrimitiveValue* ConsumeAngle(CSSParserTokenRange&,
const CSSParserContext&, const CSSParserContext*,
WTF::Optional<WebFeature> unitlessZeroFeature); WTF::Optional<WebFeature> unitlessZeroFeature);
CSSPrimitiveValue* ConsumeTime(CSSParserTokenRange&, ValueRange); CSSPrimitiveValue* ConsumeTime(CSSParserTokenRange&, ValueRange);
CSSPrimitiveValue* ConsumeResolution(CSSParserTokenRange&); CSSPrimitiveValue* ConsumeResolution(CSSParserTokenRange&);
......
...@@ -45,7 +45,7 @@ static CSSFunctionValue* ConsumeFilterFunction( ...@@ -45,7 +45,7 @@ static CSSFunctionValue* ConsumeFilterFunction(
} }
} else if (filter_type == CSSValueHueRotate) { } else if (filter_type == CSSValueHueRotate) {
parsed_value = CSSPropertyParserHelpers::ConsumeAngle( parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
args, context, WebFeature::kUnitlessZeroAngleFilter); args, &context, WebFeature::kUnitlessZeroAngleFilter);
} else if (filter_type == CSSValueBlur) { } else if (filter_type == CSSValueBlur) {
parsed_value = CSSPropertyParserHelpers::ConsumeLength( parsed_value = CSSPropertyParserHelpers::ConsumeLength(
args, kHTMLStandardMode, kValueRangeNonNegative); args, kHTMLStandardMode, kValueRangeNonNegative);
......
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
#include "core/css/properties/CSSPropertyAPIFontStyle.h" #include "core/css/properties/CSSPropertyAPIFontStyle.h"
#include "core/css/parser/CSSParserContext.h"
#include "core/css/properties/CSSPropertyFontUtils.h" #include "core/css/properties/CSSPropertyFontUtils.h"
namespace blink { namespace blink {
const CSSValue* CSSPropertyAPIFontStyle::parseSingleValue( const CSSValue* CSSPropertyAPIFontStyle::parseSingleValue(
CSSParserTokenRange& range, CSSParserTokenRange& range,
const CSSParserContext&, const CSSParserContext& context,
const CSSParserLocalContext&) { const CSSParserLocalContext&) {
return CSSPropertyFontUtils::ConsumeFontStyle(range); return CSSPropertyFontUtils::ConsumeFontStyle(range, context.Mode());
} }
} // namespace blink } // namespace blink
...@@ -21,7 +21,7 @@ const CSSValue* CSSPropertyAPIImageOrientation::parseSingleValue( ...@@ -21,7 +21,7 @@ const CSSValue* CSSPropertyAPIImageOrientation::parseSingleValue(
return CSSPropertyParserHelpers::ConsumeIdent(range); return CSSPropertyParserHelpers::ConsumeIdent(range);
if (range.Peek().GetType() != kNumberToken) { if (range.Peek().GetType() != kNumberToken) {
CSSPrimitiveValue* angle = CSSPropertyParserHelpers::ConsumeAngle( CSSPrimitiveValue* angle = CSSPropertyParserHelpers::ConsumeAngle(
range, context, WTF::Optional<WebFeature>()); range, &context, WTF::Optional<WebFeature>());
if (angle && angle->GetDoubleValue() == 0) if (angle && angle->GetDoubleValue() == 0)
return angle; return angle;
} }
......
...@@ -36,7 +36,7 @@ const CSSValue* CSSPropertyAPIRotate::parseSingleValue( ...@@ -36,7 +36,7 @@ const CSSValue* CSSPropertyAPIRotate::parseSingleValue(
} }
CSSValue* rotation = CSSPropertyParserHelpers::ConsumeAngle( CSSValue* rotation = CSSPropertyParserHelpers::ConsumeAngle(
range, context, WTF::Optional<WebFeature>()); range, &context, WTF::Optional<WebFeature>());
if (!rotation) if (!rotation)
return nullptr; return nullptr;
list->Append(*rotation); list->Append(*rotation);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "core/css/CSSFontFamilyValue.h" #include "core/css/CSSFontFamilyValue.h"
#include "core/css/CSSFontFeatureValue.h" #include "core/css/CSSFontFeatureValue.h"
#include "core/css/CSSFontStyleRangeValue.h"
#include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSValueList.h" #include "core/css/CSSValueList.h"
#include "core/css/CSSValuePair.h" #include "core/css/CSSValuePair.h"
...@@ -95,14 +96,60 @@ String CSSPropertyFontUtils::ConcatenateFamilyName(CSSParserTokenRange& range) { ...@@ -95,14 +96,60 @@ String CSSPropertyFontUtils::ConcatenateFamilyName(CSSParserTokenRange& range) {
return builder.ToString(); return builder.ToString();
} }
// TODO(drott) crbug.com/739139: In a subsequent stage, make these three methods static CSSValueList* CombineToRangeListOrNull(
// understand ranges. const CSSPrimitiveValue* range_start,
CSSValue* CSSPropertyFontUtils::ConsumeFontStyle(CSSParserTokenRange& range) { const CSSPrimitiveValue* range_end) {
const CSSParserToken& token = range.Peek(); DCHECK(range_start);
if (token.Id() == CSSValueNormal || token.Id() == CSSValueItalic || DCHECK(range_end);
token.Id() == CSSValueOblique) if (range_end->GetFloatValue() < range_start->GetFloatValue())
return nullptr;
CSSValueList* value_list = CSSValueList::CreateSpaceSeparated();
value_list->Append(*range_start);
value_list->Append(*range_end);
return value_list;
}
static bool IsAngleWithinLimits(CSSPrimitiveValue* angle) {
constexpr float kMaxAngle = 90.0f;
return angle->GetFloatValue() >= -kMaxAngle &&
angle->GetFloatValue() <= kMaxAngle;
}
CSSValue* CSSPropertyFontUtils::ConsumeFontStyle(
CSSParserTokenRange& range,
const CSSParserMode& parser_mode) {
if (range.Peek().Id() == CSSValueNormal ||
range.Peek().Id() == CSSValueItalic)
return CSSPropertyParserHelpers::ConsumeIdent(range); return CSSPropertyParserHelpers::ConsumeIdent(range);
return nullptr;
if (range.Peek().Id() != CSSValueOblique)
return nullptr;
CSSIdentifierValue* oblique_identifier =
CSSPropertyParserHelpers::ConsumeIdent<CSSValueOblique>(range);
CSSPrimitiveValue* start_angle =
CSSPropertyParserHelpers::ConsumeAngle(range, nullptr, WTF::nullopt);
if (!start_angle)
return oblique_identifier;
if (!IsAngleWithinLimits(start_angle))
return nullptr;
if (parser_mode != kCSSFontFaceRuleMode || range.AtEnd()) {
CSSValueList* value_list = CSSValueList::CreateSpaceSeparated();
value_list->Append(*start_angle);
return CSSFontStyleRangeValue::Create(*oblique_identifier, *value_list);
}
CSSPrimitiveValue* end_angle =
CSSPropertyParserHelpers::ConsumeAngle(range, nullptr, WTF::nullopt);
if (!end_angle || !IsAngleWithinLimits(end_angle))
return nullptr;
CSSValueList* range_list = CombineToRangeListOrNull(start_angle, end_angle);
if (!range_list)
return nullptr;
return CSSFontStyleRangeValue::Create(*oblique_identifier, *range_list);
} }
CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontStretchKeywordOnly( CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontStretchKeywordOnly(
...@@ -114,18 +161,6 @@ CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontStretchKeywordOnly( ...@@ -114,18 +161,6 @@ CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontStretchKeywordOnly(
return nullptr; return nullptr;
} }
static CSSValue* CombineToRangeListOrNull(const CSSPrimitiveValue* range_start,
const CSSPrimitiveValue* range_end) {
DCHECK(range_start);
DCHECK(range_end);
if (range_end->GetFloatValue() < range_start->GetFloatValue())
return nullptr;
CSSValueList* value_list = CSSValueList::CreateSpaceSeparated();
value_list->Append(*range_start);
value_list->Append(*range_end);
return value_list;
}
CSSValue* CSSPropertyFontUtils::ConsumeFontStretch( CSSValue* CSSPropertyFontUtils::ConsumeFontStretch(
CSSParserTokenRange& range, CSSParserTokenRange& range,
const CSSParserMode& parser_mode) { const CSSParserMode& parser_mode) {
......
...@@ -37,7 +37,7 @@ class CSSPropertyFontUtils { ...@@ -37,7 +37,7 @@ class CSSPropertyFontUtils {
CSSParserTokenRange&); CSSParserTokenRange&);
static CSSValue* ConsumeFontStretch(CSSParserTokenRange&, static CSSValue* ConsumeFontStretch(CSSParserTokenRange&,
const CSSParserMode&); const CSSParserMode&);
static CSSValue* ConsumeFontStyle(CSSParserTokenRange&); static CSSValue* ConsumeFontStyle(CSSParserTokenRange&, const CSSParserMode&);
static CSSValue* ConsumeFontWeight(CSSParserTokenRange&, static CSSValue* ConsumeFontWeight(CSSParserTokenRange&,
const CSSParserMode&); const CSSParserMode&);
......
...@@ -57,7 +57,7 @@ CSSValue* ConsumeRay(CSSParserTokenRange& range, ...@@ -57,7 +57,7 @@ CSSValue* ConsumeRay(CSSParserTokenRange& range,
while (!function_args.AtEnd()) { while (!function_args.AtEnd()) {
if (!angle) { if (!angle) {
angle = CSSPropertyParserHelpers::ConsumeAngle( angle = CSSPropertyParserHelpers::ConsumeAngle(
function_args, context, WTF::Optional<WebFeature>()); function_args, &context, WTF::Optional<WebFeature>());
if (angle) if (angle)
continue; continue;
} }
......
...@@ -12,7 +12,7 @@ CSSValue* CSSPropertyOffsetRotateUtils::ConsumeOffsetRotate( ...@@ -12,7 +12,7 @@ CSSValue* CSSPropertyOffsetRotateUtils::ConsumeOffsetRotate(
CSSParserTokenRange& range, CSSParserTokenRange& range,
const CSSParserContext& context) { const CSSParserContext& context) {
CSSValue* angle = CSSPropertyParserHelpers::ConsumeAngle( CSSValue* angle = CSSPropertyParserHelpers::ConsumeAngle(
range, context, Optional<WebFeature>()); range, &context, Optional<WebFeature>());
CSSValue* keyword = CSSValue* keyword =
CSSPropertyParserHelpers::ConsumeIdent<CSSValueAuto, CSSValueReverse>( CSSPropertyParserHelpers::ConsumeIdent<CSSValueAuto, CSSValueReverse>(
range); range);
...@@ -20,7 +20,7 @@ CSSValue* CSSPropertyOffsetRotateUtils::ConsumeOffsetRotate( ...@@ -20,7 +20,7 @@ CSSValue* CSSPropertyOffsetRotateUtils::ConsumeOffsetRotate(
return nullptr; return nullptr;
if (!angle) { if (!angle) {
angle = CSSPropertyParserHelpers::ConsumeAngle(range, context, angle = CSSPropertyParserHelpers::ConsumeAngle(range, &context,
Optional<WebFeature>()); Optional<WebFeature>());
} }
......
...@@ -96,14 +96,14 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range, ...@@ -96,14 +96,14 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
case CSSValueSkewY: case CSSValueSkewY:
case CSSValueSkew: case CSSValueSkew:
parsed_value = CSSPropertyParserHelpers::ConsumeAngle( parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
args, context, WebFeature::kUnitlessZeroAngleTransform); args, &context, WebFeature::kUnitlessZeroAngleTransform);
if (!parsed_value) if (!parsed_value)
return nullptr; return nullptr;
if (function_id == CSSValueSkew && if (function_id == CSSValueSkew &&
CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) { CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
transform_value->Append(*parsed_value); transform_value->Append(*parsed_value);
parsed_value = CSSPropertyParserHelpers::ConsumeAngle( parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
args, context, WebFeature::kUnitlessZeroAngleTransform); args, &context, WebFeature::kUnitlessZeroAngleTransform);
if (!parsed_value) if (!parsed_value)
return nullptr; return nullptr;
} }
...@@ -168,7 +168,7 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range, ...@@ -168,7 +168,7 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
return nullptr; return nullptr;
} }
parsed_value = CSSPropertyParserHelpers::ConsumeAngle( parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
args, context, WebFeature::kUnitlessZeroAngleTransform); args, &context, WebFeature::kUnitlessZeroAngleTransform);
if (!parsed_value) if (!parsed_value)
return nullptr; return nullptr;
break; break;
......
...@@ -102,7 +102,8 @@ bool ConsumeFont(bool important, ...@@ -102,7 +102,8 @@ bool ConsumeFont(bool important,
CSSValueID id = range.Peek().Id(); CSSValueID id = range.Peek().Id();
if (!font_style && (id == CSSValueNormal || id == CSSValueItalic || if (!font_style && (id == CSSValueNormal || id == CSSValueItalic ||
id == CSSValueOblique)) { id == CSSValueOblique)) {
font_style = CSSPropertyFontUtils::ConsumeFontStyle(range); font_style =
CSSPropertyFontUtils::ConsumeFontStyle(range, context.Mode());
continue; continue;
} }
if (!font_variant_caps && if (!font_variant_caps &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment