Bug 1321022 pt 4 - Implement CSS parsing of the font-variations-setting property, storing the value into nsFont. r=dholbert

This commit is contained in:
Jonathan Kew 2016-12-03 12:18:36 +00:00
Родитель 9edd951825
Коммит cd6fcd068a
11 изменённых файлов: 239 добавлений и 0 удалений

Просмотреть файл

@ -1056,6 +1056,7 @@ protected:
bool ParseOneFamily(nsAString& aFamily, bool& aOneKeyword, bool& aQuoted);
bool ParseFamily(nsCSSValue& aValue);
bool ParseFontFeatureSettings(nsCSSValue& aValue);
bool ParseFontVariationSettings(nsCSSValue& aValue);
bool ParseFontSrc(nsCSSValue& aValue);
bool ParseFontSrcFormat(InfallibleTArray<nsCSSValue>& values);
bool ParseFontRanges(nsCSSValue& aValue);
@ -12099,6 +12100,8 @@ CSSParserImpl::ParseSingleValuePropertyByFunction(nsCSSValue& aValue,
return ParseFontVariantNumeric(aValue);
case eCSSProperty_font_feature_settings:
return ParseFontFeatureSettings(aValue);
case eCSSProperty_font_variation_settings:
return ParseFontVariationSettings(aValue);
case eCSSProperty_font_weight:
return ParseFontWeight(aValue);
case eCSSProperty_image_orientation:
@ -15354,6 +15357,55 @@ CSSParserImpl::ParseFontFeatureSettings(nsCSSValue& aValue)
return true;
}
bool
CSSParserImpl::ParseFontVariationSettings(nsCSSValue& aValue)
{
if (ParseSingleTokenVariant(aValue, VARIANT_INHERIT | VARIANT_NORMAL,
nullptr)) {
return true;
}
auto resultHead = MakeUnique<nsCSSValuePairList>();
nsCSSValuePairList* cur = resultHead.get();
for (;;) {
// variation tag
if (!GetToken(true)) {
return false;
}
// variation tags are subject to the same validation as feature tags
if (mToken.mType != eCSSToken_String ||
!ValidFontFeatureTag(mToken.mIdent)) {
UngetToken();
return false;
}
cur->mXValue.SetStringValue(mToken.mIdent, eCSSUnit_String);
if (!GetToken(true)) {
return false;
}
if (mToken.mType == eCSSToken_Number) {
cur->mYValue.SetFloatValue(mToken.mNumber, eCSSUnit_Number);
} else {
UngetToken();
return false;
}
if (!ExpectSymbol(',', true)) {
break;
}
cur->mNext = new nsCSSValuePairList;
cur = cur->mNext;
}
aValue.AdoptPairListValue(Move(resultHead));
return true;
}
bool
CSSParserImpl::ParseListStyle()
{

Просмотреть файл

@ -2036,6 +2036,20 @@ CSS_PROP_FONT(
kFontVariantPositionKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_Discrete)
CSS_PROP_FONT(
font-variation-settings,
font_variation_settings,
FontVariationSettings,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-variations.enabled",
0,
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_Discrete)
CSS_PROP_FONT(
font-weight,
font_weight,

Просмотреть файл

@ -1588,6 +1588,23 @@ nsComputedDOMStyle::DoGetFontFeatureSettings()
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetFontVariationSettings()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
const nsStyleFont* font = StyleFont();
if (font->mFont.fontVariationSettings.IsEmpty()) {
val->SetIdent(eCSSKeyword_normal);
} else {
nsAutoString result;
nsStyleUtil::AppendFontVariationSettings(font->mFont.fontVariationSettings,
result);
val->SetString(result);
}
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetFontKerning()
{

Просмотреть файл

@ -256,6 +256,7 @@ private:
already_AddRefed<CSSValue> DoGetColor();
already_AddRefed<CSSValue> DoGetFontFamily();
already_AddRefed<CSSValue> DoGetFontFeatureSettings();
already_AddRefed<CSSValue> DoGetFontVariationSettings();
already_AddRefed<CSSValue> DoGetFontKerning();
already_AddRefed<CSSValue> DoGetFontLanguageOverride();
already_AddRefed<CSSValue> DoGetFontSize();

Просмотреть файл

@ -144,6 +144,7 @@ COMPUTED_STYLE_PROP(font_variant_east_asian, FontVariantEastAsian)
COMPUTED_STYLE_PROP(font_variant_ligatures, FontVariantLigatures)
COMPUTED_STYLE_PROP(font_variant_numeric, FontVariantNumeric)
COMPUTED_STYLE_PROP(font_variant_position, FontVariantPosition)
COMPUTED_STYLE_PROP(font_variation_settings, FontVariationSettings)
COMPUTED_STYLE_PROP(font_weight, FontWeight)
COMPUTED_STYLE_PROP(grid_auto_columns, GridAutoColumns)
COMPUTED_STYLE_PROP(grid_auto_flow, GridAutoFlow)

Просмотреть файл

@ -3994,6 +3994,41 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
break;
}
// font-variation-settings
const nsCSSValue* variationSettingsValue =
aRuleData->ValueForFontVariationSettings();
switch (variationSettingsValue->GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Normal:
case eCSSUnit_Initial:
aFont->mFont.fontVariationSettings.Clear();
break;
case eCSSUnit_Inherit:
case eCSSUnit_Unset:
aConditions.SetUncacheable();
aFont->mFont.fontVariationSettings =
aParentFont->mFont.fontVariationSettings;
break;
case eCSSUnit_System_Font:
aFont->mFont.fontVariationSettings = systemFont.fontVariationSettings;
break;
case eCSSUnit_PairList:
case eCSSUnit_PairListDep:
ComputeFontVariations(variationSettingsValue->GetPairListValue(),
aFont->mFont.fontVariationSettings);
break;
default:
MOZ_ASSERT(false, "unexpected value unit");
break;
}
// font-language-override
const nsCSSValue* languageOverrideValue =
aRuleData->ValueForFontLanguageOverride();
@ -4126,6 +4161,18 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
SETFCT_NONE | SETFCT_UNSET_INHERIT);
}
static inline void
AssertValidFontTag(const nsString& aString)
{
// To be valid as a font feature tag, a string MUST be:
MOZ_ASSERT(aString.Length() == 4 && // (1) exactly 4 chars long
NS_IsAscii(aString.BeginReading()) && // (2) entirely ASCII
isprint(aString[0]) && // (3) all printable chars
isprint(aString[1]) &&
isprint(aString[2]) &&
isprint(aString[3]));
}
/* static */ void
nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList,
nsTArray<gfxFontFeature>& aFeatureSettings)
@ -4156,6 +4203,37 @@ nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList,
}
}
/* static */ void
nsRuleNode::ComputeFontVariations(const nsCSSValuePairList* aVariationsList,
nsTArray<gfxFontVariation>& aVariationSettings)
{
aVariationSettings.Clear();
for (const nsCSSValuePairList* p = aVariationsList; p; p = p->mNext) {
gfxFontVariation var;
MOZ_ASSERT(aVariationsList->mXValue.GetUnit() == eCSSUnit_String,
"unexpected value unit");
// tag is a 4-byte ASCII sequence
nsAutoString tag;
p->mXValue.GetStringValue(tag);
AssertValidFontTag(tag);
if (tag.Length() != 4) {
continue;
}
// parsing validates that these are ASCII chars
// tags are always big-endian
var.mTag = (tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
// value
NS_ASSERTION(p->mYValue.GetUnit() == eCSSUnit_Number,
"should have found a number unit");
var.mValue = p->mYValue.GetFloatValue();
aVariationSettings.AppendElement(var);
}
}
// This should die (bug 380915).
//
// SetGenericFont:

Просмотреть файл

@ -1025,6 +1025,9 @@ public:
static void ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList,
nsTArray<gfxFontFeature>& aFeatureSettings);
static void ComputeFontVariations(const nsCSSValuePairList* aVariationsList,
nsTArray<gfxFontVariation>& aVariationSettings);
static nscoord CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize,
nsPresContext* aPresContext,
nsFontSizeType aFontSizeType = eFontSize_HTML);

Просмотреть файл

@ -390,6 +390,45 @@ nsStyleUtil::AppendFontFeatureSettings(const nsCSSValue& aSrc,
AppendFontFeatureSettings(featureSettings, aResult);
}
/* static */ void
nsStyleUtil::AppendFontVariationSettings(const nsTArray<gfxFontVariation>& aVariations,
nsAString& aResult)
{
for (uint32_t i = 0, numVars = aVariations.Length(); i < numVars; i++) {
const gfxFontVariation& var = aVariations[i];
if (i != 0) {
aResult.AppendLiteral(", ");
}
// output tag
AppendFontTagAsString(var.mTag, aResult);
// output value
aResult.Append(' ');
aResult.AppendFloat(var.mValue);
}
}
/* static */ void
nsStyleUtil::AppendFontVariationSettings(const nsCSSValue& aSrc,
nsAString& aResult)
{
nsCSSUnit unit = aSrc.GetUnit();
if (unit == eCSSUnit_Normal) {
aResult.AppendLiteral("normal");
return;
}
NS_PRECONDITION(unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep,
"improper value unit for font-variation-settings:");
nsTArray<gfxFontVariation> variationSettings;
nsRuleNode::ComputeFontVariations(aSrc.GetPairListValue(), variationSettings);
AppendFontVariationSettings(variationSettings, aResult);
}
/* static */ void
nsStyleUtil::GetFunctionalAlternatesName(int32_t aFeature,
nsAString& aFeatureName)

Просмотреть файл

@ -71,6 +71,12 @@ public:
static void AppendFontFeatureSettings(const nsCSSValue& src,
nsAString& aResult);
static void AppendFontVariationSettings(const nsTArray<gfxFontVariation>& aVariations,
nsAString& aResult);
static void AppendFontVariationSettings(const nsCSSValue& src,
nsAString& aResult);
static void AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult);
static void AppendCSSNumber(float aNumber, nsAString& aResult)

Просмотреть файл

@ -5687,6 +5687,31 @@ if (IsCSSPropertyPrefEnabled("layout.css.text-combine-upright.enabled")) {
}
}
if (IsCSSPropertyPrefEnabled("layout.css.font-variations.enabled")) {
gCSSProperties["font-variation-settings"] = {
domProp: "fontVariationSettings",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [
"'wdth' 0", "'wdth' -.1", "\"wdth\" 1", "'wdth' 2, 'wght' 3", "\"XXXX\" 0"
],
invalid_values: [
"wdth", "wdth 1", // unquoted tags
"'wdth'", "'wdth' 'wght'", "'wdth', 'wght'", // missing values
"'' 1", "'wid' 1", "'width' 1", // incorrect tag lengths
"'wd\th' 1", // non-graphic character in tag
"'wdth' 1 'wght' 2", // missing comma between pairs
"'wdth' 1,", // trailing comma
"'wdth' 1 , , 'wght' 2", // extra comma
"'wdth', 1" // comma within pair
],
unbalanced_values: [
"'wdth\" 1", "\"wdth' 1" // mismatched quotes
]
}
}
if (IsCSSPropertyPrefEnabled("svg.paint-order.enabled")) {
gCSSProperties["paint-order"] = {
domProp: "paintOrder",

Просмотреть файл

@ -2547,6 +2547,9 @@ pref("layout.css.image-orientation.enabled", true);
// Is support for the font-display @font-face descriptor enabled?
pref("layout.css.font-display.enabled", false);
// Is support for variation fonts enabled?
pref("layout.css.font-variations.enabled", false);
// Are sets of prefixed properties supported?
pref("layout.css.prefixes.border-image", true);
pref("layout.css.prefixes.transforms", true);