Bug 549861. Implement CSS parsing of font-variant-alternates. r=dbaron

This commit is contained in:
John Daggett 2013-05-13 18:45:37 +09:00
parent c18a21b5f6
commit 57964002fe
17 changed files with 421 additions and 13 deletions

View File

@ -541,6 +541,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
*data->ValueFor(eCSSProperty_font_kerning);
const nsCSSValue &fontSynthesis =
*data->ValueFor(eCSSProperty_font_synthesis);
const nsCSSValue &fontVariantAlternates =
*data->ValueFor(eCSSProperty_font_variant_alternates);
const nsCSSValue &fontVariantCaps =
*data->ValueFor(eCSSProperty_font_variant_caps);
const nsCSSValue &fontVariantEastAsian =
@ -567,6 +569,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
languageOverride.GetUnit() != eCSSUnit_System_Font ||
fontKerning.GetUnit() != eCSSUnit_System_Font ||
fontSynthesis.GetUnit() != eCSSUnit_System_Font ||
fontVariantAlternates.GetUnit() != eCSSUnit_System_Font ||
fontVariantCaps.GetUnit() != eCSSUnit_System_Font ||
fontVariantEastAsian.GetUnit() != eCSSUnit_System_Font ||
fontVariantLigatures.GetUnit() != eCSSUnit_System_Font ||
@ -590,6 +593,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
fontKerning.GetIntValue() != NS_FONT_KERNING_AUTO ||
fontSynthesis.GetIntValue() !=
(NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE) ||
fontVariantAlternates.GetUnit() != eCSSUnit_Normal ||
fontVariantCaps.GetUnit() != eCSSUnit_Normal ||
fontVariantEastAsian.GetUnit() != eCSSUnit_Normal ||
fontVariantLigatures.GetUnit() != eCSSUnit_Normal ||

View File

@ -170,6 +170,7 @@ CSS_KEY(alpha, alpha)
CSS_KEY(alternate, alternate)
CSS_KEY(alternate-reverse, alternate_reverse)
CSS_KEY(always, always)
CSS_KEY(annotation, annotation)
CSS_KEY(appworkspace, appworkspace)
CSS_KEY(armenian, armenian)
CSS_KEY(auto, auto)
@ -202,6 +203,7 @@ CSS_KEY(captiontext, captiontext)
CSS_KEY(cell, cell)
CSS_KEY(center, center)
CSS_KEY(ch, ch)
CSS_KEY(character-variant, character_variant)
CSS_KEY(circle, circle)
CSS_KEY(cjk-ideographic, cjk_ideographic)
CSS_KEY(clip, clip)
@ -279,6 +281,7 @@ CSS_KEY(highlight, highlight)
CSS_KEY(highlighttext, highlighttext)
CSS_KEY(hiragana, hiragana)
CSS_KEY(hiragana-iroha, hiragana_iroha)
CSS_KEY(historical-forms, historical_forms)
CSS_KEY(historical-ligatures, historical_ligatures)
CSS_KEY(horizontal, horizontal)
CSS_KEY(hz, hz)
@ -367,6 +370,7 @@ CSS_KEY(oblique, oblique)
CSS_KEY(oldstyle-nums, oldstyle_nums)
CSS_KEY(open-quote, open_quote)
CSS_KEY(ordinal, ordinal)
CSS_KEY(ornaments, ornaments)
CSS_KEY(outset, outset)
CSS_KEY(outside, outside)
CSS_KEY(overline, overline)
@ -455,9 +459,12 @@ CSS_KEY(stretch, stretch)
CSS_KEY(stretch-to-fit, stretch_to_fit)
CSS_KEY(stroke, stroke)
CSS_KEY(style, style)
CSS_KEY(styleset, styleset)
CSS_KEY(stylistic, stylistic)
CSS_KEY(sub, sub)
CSS_KEY(super, super)
CSS_KEY(sw-resize, sw_resize)
CSS_KEY(swash, swash)
CSS_KEY(table, table)
CSS_KEY(table-caption, table_caption)
CSS_KEY(table-cell, table_cell)

View File

@ -563,6 +563,8 @@ protected:
bool ParseCursor();
bool ParseFont();
bool ParseFontSynthesis(nsCSSValue& aValue);
bool ParseSingleAlternate(int32_t& aWhichFeature, nsCSSValue& aValue);
bool ParseFontVariantAlternates(nsCSSValue& aValue);
bool ParseBitmaskValues(nsCSSValue& aValue, const int32_t aKeywordTable[],
const int32_t aMasks[]);
bool ParseFontVariantEastAsian(nsCSSValue& aValue);
@ -671,12 +673,13 @@ protected:
/* Functions for transform Parsing */
bool ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue, bool& aIs3D);
bool ParseFunction(const nsString &aFunction, const int32_t aAllowedTypes[],
uint16_t aMinElems, uint16_t aMaxElems,
nsCSSValue &aValue);
int32_t aVariantMaskAll, uint16_t aMinElems,
uint16_t aMaxElems, nsCSSValue &aValue);
bool ParseFunctionInternals(const int32_t aVariantMask[],
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue>& aOutput);
int32_t aVariantMaskAll,
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue>& aOutput);
/* Functions for transform-origin/perspective-origin Parsing */
bool ParseTransformOrigin(bool aPerspective);
@ -6378,6 +6381,8 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
return ParseFamily(aValue);
case eCSSProperty_font_synthesis:
return ParseFontSynthesis(aValue);
case eCSSProperty_font_variant_alternates:
return ParseFontVariantAlternates(aValue);
case eCSSProperty_font_variant_east_asian:
return ParseFontVariantEastAsian(aValue);
case eCSSProperty_font_variant_ligatures:
@ -8319,6 +8324,7 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_language_override, family);
AppendValue(eCSSProperty_font_kerning, family);
AppendValue(eCSSProperty_font_synthesis, family);
AppendValue(eCSSProperty_font_variant_alternates, family);
AppendValue(eCSSProperty_font_variant_caps, family);
AppendValue(eCSSProperty_font_variant_east_asian, family);
AppendValue(eCSSProperty_font_variant_ligatures, family);
@ -8340,6 +8346,7 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_language_override, systemFont);
AppendValue(eCSSProperty_font_kerning, systemFont);
AppendValue(eCSSProperty_font_synthesis, systemFont);
AppendValue(eCSSProperty_font_variant_alternates, systemFont);
AppendValue(eCSSProperty_font_variant_caps, systemFont);
AppendValue(eCSSProperty_font_variant_east_asian, systemFont);
AppendValue(eCSSProperty_font_variant_ligatures, systemFont);
@ -8413,6 +8420,8 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_synthesis,
nsCSSValue(NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE,
eCSSUnit_Enumerated));
AppendValue(eCSSProperty_font_variant_alternates,
nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_caps, nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_east_asian,
nsCSSValue(eCSSUnit_Normal));
@ -8459,6 +8468,111 @@ CSSParserImpl::ParseFontSynthesis(nsCSSValue& aValue)
return true;
}
// font-variant-alternates allows for a multiple number of
// both simple enumerated values and functional values with
// parameter lists with one or more idents (these are resolved
// later based on values defined in @font-feature-value rules).
//
// font-variant-alternates: swash(flowing), historical-forms, styleset(alt-g, alt-m);
//
// So for this the nsCSSValue is set to a pair value, with one
// value for a bitmap of both simple and functional property values
// and another value containing a valuelist with lists of idents
// for each functional property value.
//
// pairValue
// o intValue
// NS_FONT_VARIANT_ALTERNATES_SWASH |
// NS_FONT_VARIANT_ALTERNATES_STYLESET
// o valuePairList, each element with
// - intValue - indicates which alternate
// - string or valueList of strings
#define MAX_ALLOWED_FEATURES 512
bool
CSSParserImpl::ParseSingleAlternate(int32_t& aWhichFeature,
nsCSSValue& aValue)
{
if (!GetToken(true)) {
return false;
}
bool isIdent = (mToken.mType == eCSSToken_Ident);
if (mToken.mType != eCSSToken_Function && !isIdent) {
UngetToken();
return false;
}
// ident ==> simple enumerated prop val (e.g. historical-forms)
// function ==> e.g. swash(flowing) styleset(alt-g, alt-m)
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (eCSSKeyword_UNKNOWN < keyword &&
nsCSSProps::FindKeyword(keyword,
(isIdent ?
nsCSSProps::kFontVariantAlternatesKTable :
nsCSSProps::kFontVariantAlternatesFuncsKTable),
aWhichFeature))
{
if (isIdent) {
aValue.SetIntValue(aWhichFeature, eCSSUnit_Enumerated);
return true;
} else {
uint16_t maxElems = 1;
if (keyword == eCSSKeyword_styleset ||
keyword == eCSSKeyword_character_variant) {
maxElems = MAX_ALLOWED_FEATURES;
}
return ParseFunction(mToken.mIdent, nullptr, VARIANT_IDENTIFIER,
1, maxElems, aValue);
}
}
// failed, pop token
UngetToken();
return false;
}
bool
CSSParserImpl::ParseFontVariantAlternates(nsCSSValue& aValue)
{
if (ParseVariant(aValue, VARIANT_INHERIT | VARIANT_NORMAL, nullptr)) {
if (!ExpectEndProperty()) {
return false;
}
return true;
}
// iterate through parameters
nsCSSValue listValue;
int32_t feature, featureFlags = 0;
nsCSSValueList* cur = listValue.SetListValue();
while (ParseSingleAlternate(feature, cur->mValue)) {
// check to make sure value not normal and not already set
if (feature == 0 ||
feature & featureFlags) {
return false;
}
featureFlags |= feature;
if (cur->mValue.GetUnit() == eCSSUnit_Function) {
cur->mNext = new nsCSSValueList;
cur = cur->mNext;
}
}
nsCSSValue featureValue;
featureValue.SetIntValue(featureFlags, eCSSUnit_Enumerated);
aValue.SetPairValue(featureValue, listValue);
return true;
}
#define MASK_END_VALUE -1
// aMasks - array of masks for mutually-exclusive property values,
@ -9343,14 +9457,17 @@ CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue)
*/
bool
CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
int32_t aVariantMaskAll,
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue> &aOutput)
{
for (uint16_t index = 0; index < aMaxElems; ++index) {
nsCSSValue newValue;
if (!ParseVariant(newValue, aVariantMask[index], nullptr))
int32_t m = aVariantMaskAll ? aVariantMaskAll : aVariantMask[index];
if (!ParseVariant(newValue, m, nullptr)) {
return false;
}
aOutput.AppendElement(newValue);
@ -9379,6 +9496,7 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
* array corresponds to the first function parameter, etc. The length
* of this array _must_ be greater than or equal to aMaxElems or the
* behavior is undefined.
* @param aAllowTypeAll If set, all elements tested for these types
* @param aMinElems Minimum number of elements to read. Reading fewer than
* this many elements will result in the function failing.
* @param aMaxElems Maximum number of elements to read. Reading more than
@ -9388,6 +9506,7 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
bool
CSSParserImpl::ParseFunction(const nsString &aFunction,
const int32_t aAllowedTypes[],
int32_t aAllowedTypesAll,
uint16_t aMinElems, uint16_t aMaxElems,
nsCSSValue &aValue)
{
@ -9408,9 +9527,10 @@ CSSParserImpl::ParseFunction(const nsString &aFunction,
* it's out of bounds.
*/
InfallibleTArray<nsCSSValue> foundValues;
if (!ParseFunctionInternals(aAllowedTypes, aMinElems, aMaxElems,
foundValues))
if (!ParseFunctionInternals(aAllowedTypes, aAllowedTypesAll, aMinElems,
aMaxElems, foundValues)) {
return false;
}
/* Now, convert this array into an nsCSSValue::Array object.
* We'll need N + 1 spots, one for the function name and the rest for the
@ -9685,7 +9805,8 @@ CSSParserImpl::ParseSingleTransform(bool aIsPrefixed,
break;
}
return ParseFunction(mToken.mIdent, variantMask, minElems, maxElems, aValue);
return ParseFunction(mToken.mIdent, variantMask, 0, minElems,
maxElems, aValue);
}
/* Parses a transform property list by continuously reading in properties

View File

@ -1811,6 +1811,19 @@ CSS_PROP_FONT(
kFontVariantKTable,
offsetof(nsStyleFont, mFont.variant),
eStyleAnimType_EnumU8)
CSS_PROP_FONT(
font-variant-alternates,
font_variant_alternates,
FontVariantAlternates,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
VARIANT_HK,
kFontVariantAlternatesKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-caps,
font_variant_caps,

View File

@ -1066,6 +1066,21 @@ const int32_t nsCSSProps::kFontVariantKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantAlternatesKTable[] = {
eCSSKeyword_historical_forms, NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantAlternatesFuncsKTable[] = {
eCSSKeyword_stylistic, NS_FONT_VARIANT_ALTERNATES_STYLISTIC,
eCSSKeyword_styleset, NS_FONT_VARIANT_ALTERNATES_STYLESET,
eCSSKeyword_character_variant, NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT,
eCSSKeyword_swash, NS_FONT_VARIANT_ALTERNATES_SWASH,
eCSSKeyword_ornaments, NS_FONT_VARIANT_ALTERNATES_ORNAMENTS,
eCSSKeyword_annotation, NS_FONT_VARIANT_ALTERNATES_ANNOTATION,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantCapsKTable[] = {
eCSSKeyword_small_caps, NS_FONT_VARIANT_CAPS_SMALLCAPS,
eCSSKeyword_all_small_caps, NS_FONT_VARIANT_CAPS_ALLSMALL,
@ -2146,6 +2161,7 @@ static const nsCSSProperty gFontSubpropTable[] = {
eCSSProperty_font_language_override,
eCSSProperty_font_kerning,
eCSSProperty_font_synthesis,
eCSSProperty_font_variant_alternates,
eCSSProperty_font_variant_caps,
eCSSProperty_font_variant_east_asian,
eCSSProperty_font_variant_ligatures,

View File

@ -404,6 +404,8 @@ public:
static const int32_t kFontStyleKTable[];
static const int32_t kFontSynthesisKTable[];
static const int32_t kFontVariantKTable[];
static const int32_t kFontVariantAlternatesKTable[];
static const int32_t kFontVariantAlternatesFuncsKTable[];
static const int32_t kFontVariantCapsKTable[];
static const int32_t kFontVariantEastAsianKTable[];
static const int32_t kFontVariantLigaturesKTable[];

View File

@ -1095,7 +1095,27 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
aResult.AppendLiteral(")");
} else if (eCSSUnit_Pair == unit) {
GetPairValue().AppendToString(aProperty, aResult);
if (eCSSProperty_font_variant_alternates == aProperty) {
int32_t intValue = GetPairValue().mXValue.GetIntValue();
nsAutoString out;
// simple, enumerated values
nsStyleUtil::AppendBitmaskCSSValue(aProperty,
intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
out);
// functional values
const nsCSSValueList *list = GetPairValue().mYValue.GetListValue();
nsAutoTArray<gfxAlternateValue,8> altValues;
nsStyleUtil::AppendAlternateValues(list, altValues);
nsStyleUtil::AppendFunctionalAlternates(altValues, out);
aResult.Append(out);
} else {
GetPairValue().AppendToString(aProperty, aResult);
}
} else if (eCSSUnit_Triplet == unit) {
GetTripletValue().AppendToString(aProperty, aResult);
} else if (eCSSUnit_Rect == unit) {

View File

@ -1379,6 +1379,37 @@ nsComputedDOMStyle::DoGetFontSynthesis()
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantAlternates()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantAlternates;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
return val;
}
// first, include enumerated values
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_alternates,
intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL, valueStr);
// next, include functional values if present
if (intValue & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
nsStyleUtil::AppendFunctionalAlternates(StyleFont()->mFont.alternateValues,
valueStr);
}
val->SetString(valueStr);
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantCaps()
{
@ -4898,6 +4929,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(uint32_t* aLength)
COMPUTED_STYLE_MAP_ENTRY(font_style, FontStyle),
COMPUTED_STYLE_MAP_ENTRY(font_synthesis, FontSynthesis),
COMPUTED_STYLE_MAP_ENTRY(font_variant, FontVariant),
COMPUTED_STYLE_MAP_ENTRY(font_variant_alternates, FontVariantAlternates),
COMPUTED_STYLE_MAP_ENTRY(font_variant_caps, FontVariantCaps),
COMPUTED_STYLE_MAP_ENTRY(font_variant_east_asian, FontVariantEastAsian),
COMPUTED_STYLE_MAP_ENTRY(font_variant_ligatures, FontVariantLigatures),

View File

@ -196,6 +196,7 @@ private:
mozilla::dom::CSSValue* DoGetFontStyle();
mozilla::dom::CSSValue* DoGetFontSynthesis();
mozilla::dom::CSSValue* DoGetFontVariant();
mozilla::dom::CSSValue* DoGetFontVariantAlternates();
mozilla::dom::CSSValue* DoGetFontVariantCaps();
mozilla::dom::CSSValue* DoGetFontVariantEastAsian();
mozilla::dom::CSSValue* DoGetFontVariantLigatures();

View File

@ -39,6 +39,7 @@
#include "CSSCalc.h"
#include "nsPrintfCString.h"
#include "nsRenderingContext.h"
#include "nsStyleUtil.h"
#include "mozilla/LookAndFeel.h"
@ -3289,6 +3290,49 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
defaultVariableFont->synthesis,
0, 0, 0, systemFont.synthesis);
// font-variant-alternates: enum (bit field) + functions, inherit, initial
const nsCSSValue* variantAlternatesValue =
aRuleData->ValueForFontVariantAlternates();
int32_t variantAlternates = 0;
switch (variantAlternatesValue->GetUnit()) {
case eCSSUnit_Initial:
aFont->mFont.CopyAlternates(*defaultVariableFont);
break;
case eCSSUnit_Inherit:
aFont->mFont.CopyAlternates(aParentFont->mFont);
aCanStoreInRuleTree = false;
break;
case eCSSUnit_Normal:
aFont->mFont.variantAlternates = 0;
aFont->mFont.alternateValues.Clear();
aFont->mFont.featureValueLookup = nullptr;
break;
case eCSSUnit_Pair:
NS_ASSERTION(variantAlternatesValue->GetPairValue().mXValue.GetUnit() ==
eCSSUnit_Enumerated, "strange unit for variantAlternates");
variantAlternates =
variantAlternatesValue->GetPairValue().mXValue.GetIntValue();
aFont->mFont.variantAlternates = variantAlternates;
if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
// fetch the feature lookup object from the styleset
aFont->mFont.featureValueLookup =
aPresContext->StyleSet()->GetFontFeatureValuesLookup();
nsStyleUtil::AppendAlternateValues(
variantAlternatesValue->GetPairValue().mYValue.GetListValue(),
aFont->mFont.alternateValues);
}
break;
default:
break;
}
// font-variant-caps: enum, inherit, initial
SetDiscrete(*aRuleData->ValueForFontVariantCaps(),
aFont->mFont.variantCaps, aCanStoreInRuleTree,

View File

@ -23,7 +23,7 @@
#include "nsAutoPtr.h"
#include "nsIStyleRule.h"
#include "nsCSSPseudoElements.h"
#include "mozilla/Attributes.h"
#include "gfxFontFeatures.h"
class nsIURI;
class nsCSSFontFaceRule;
@ -164,6 +164,12 @@ class nsStyleSet
bool AppendKeyframesRules(nsPresContext* aPresContext,
nsTArray<nsCSSKeyframesRule*>& aArray);
already_AddRefed<gfxFontFeatureValueSet>
GetFontFeatureValuesLookup()
{
return nullptr; // not implemented yet
}
// Append all the currently-active page rules to aArray. Return
// true for success and false for failure.
bool AppendPageRules(nsPresContext* aPresContext,

View File

@ -194,6 +194,9 @@ nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont&
(aFont1.name == aFont2.name) &&
(aFont1.kerning == aFont2.kerning) &&
(aFont1.synthesis == aFont2.synthesis) &&
(aFont1.variantAlternates == aFont2.variantAlternates) &&
(aFont1.alternateValues == aFont2.alternateValues) &&
(aFont1.featureValueLookup == aFont2.featureValueLookup) &&
(aFont1.variantCaps == aFont2.variantCaps) &&
(aFont1.variantEastAsian == aFont2.variantEastAsian) &&
(aFont1.variantLigatures == aFont2.variantLigatures) &&

View File

@ -269,6 +269,118 @@ nsStyleUtil::AppendFontFeatureSettings(const nsCSSValue& aSrc,
AppendFontFeatureSettings(featureSettings, aResult);
}
/* static */ void
nsStyleUtil::GetFunctionalAlternatesName(int32_t aFeature,
nsAString& aFeatureName)
{
aFeatureName.Truncate();
nsCSSKeyword key =
nsCSSProps::ValueToKeywordEnum(aFeature,
nsCSSProps::kFontVariantAlternatesFuncsKTable);
NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "bad alternate feature type");
AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(key), aFeatureName);
}
/* static */ void
nsStyleUtil::AppendFunctionalAlternates(
const nsTArray<gfxAlternateValue>& aAlternates,
nsAString& aResult)
{
nsAutoString funcName, funcParams;
uint32_t numValues = aAlternates.Length();
uint32_t feature = 0;
for (uint32_t i = 0; i < numValues; i++) {
const gfxAlternateValue& v = aAlternates.ElementAt(i);
if (feature != v.alternate) {
feature = v.alternate;
if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
if (!aResult.IsEmpty()) {
aResult.Append(PRUnichar(' '));
}
// append the previous functional value
aResult.Append(funcName);
aResult.Append(PRUnichar('('));
aResult.Append(funcParams);
aResult.Append(PRUnichar(')'));
}
// function name
GetFunctionalAlternatesName(v.alternate, funcName);
NS_ASSERTION(!funcName.IsEmpty(), "unknown property value name");
// function params
funcParams.Assign(v.value);
} else {
if (!funcParams.IsEmpty()) {
funcParams.Append(NS_LITERAL_STRING(", "));
}
funcParams.Append(v.value);
}
}
// append the previous functional value
if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
if (!aResult.IsEmpty()) {
aResult.Append(PRUnichar(' '));
}
aResult.Append(funcName);
aResult.Append(PRUnichar('('));
aResult.Append(funcParams);
aResult.Append(PRUnichar(')'));
}
}
/* static */ void
nsStyleUtil::AppendAlternateValues(const nsCSSValueList* aList,
nsTArray<gfxAlternateValue>& aAlternateValues)
{
gfxAlternateValue v;
aAlternateValues.Clear();
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
// list contains function units
if (curr->mValue.GetUnit() != eCSSUnit_Function) {
continue;
}
// element 0 is the propval in ident form
const nsCSSValue::Array *func = curr->mValue.GetArrayValue();
// lookup propval
nsAutoString keywordStr;
func->Item(0).GetStringValue(keywordStr);
nsCSSKeyword key = nsCSSKeywords::LookupKeyword(keywordStr);
NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "unknown alternate property value");
int32_t alternate;
if (key == eCSSKeyword_UNKNOWN ||
!nsCSSProps::FindKeyword(key,
nsCSSProps::kFontVariantAlternatesFuncsKTable,
alternate)) {
continue;
}
v.alternate = alternate;
// other elements are the idents associated with the propval
// append one alternate value for each one
uint32_t numElems = func->Count();
for (uint32_t i = 1; i < numElems; i++) {
const nsCSSValue& value = func->Item(i);
NS_ASSERTION(value.GetUnit() == eCSSUnit_Ident,
"weird unit found in variant alternate");
if (value.GetUnit() != eCSSUnit_Ident) {
continue;
}
value.GetStringValue(v.value);
aAlternateValues.AppendElement(v);
}
}
}
/* static */ float
nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
{

View File

@ -7,11 +7,13 @@
#include "nsCoord.h"
#include "nsCSSProperty.h"
#include "gfxFontFeatures.h"
class nsCSSValue;
class nsStringComparator;
class nsIContent;
struct gfxFontFeature;
class nsCSSValueList;
template <class E> class nsTArray;
// Style utility functions
@ -49,6 +51,20 @@ public:
static void AppendFontFeatureSettings(const nsCSSValue& src,
nsAString& aResult);
// convert bitmask value to keyword name for a functional alternate
static void GetFunctionalAlternatesName(int32_t aFeature,
nsAString& aFeatureName);
// Append functional font-variant-alternates values to string
static void
AppendFunctionalAlternates(const nsTArray<gfxAlternateValue>& aAlternates,
nsAString& aResult);
// List of functional font-variant-alternates values to feature/value pairs
static void
AppendAlternateValues(const nsCSSValueList* aList,
nsTArray<gfxAlternateValue>& aAlternateValues);
/*
* Convert an author-provided floating point number to an integer (0
* ... 255) appropriate for use in the alpha component of a color.

View File

@ -4267,6 +4267,16 @@ if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
other_values: [ "normal", "none" ],
invalid_values: [ "on" ]
},
"font-variant-alternates": {
domProp: "fontVariantAlternates",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "historical-forms",
"styleset(alt-a, alt-b)", "character-variant(a, b, c)", "annotation(circled)" ],
invalid_values: [ "historical-forms normal", "historical-forms historical-forms",
"swash", "swash(3)", "annotation(a, b)", "ornaments(a,b)" ]
},
"font-variant-caps": {
domProp: "fontVariantCaps",
inherited: true,
@ -4332,7 +4342,7 @@ if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
for (var prop in fontFeatureProperties) {
gCSSProperties[prop] = fontFeatureProperties[prop];
}
var fontAdditions = [ "font-kerning", "font-synthesis", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position" ];
var fontAdditions = [ "font-kerning", "font-synthesis", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position" ];
gCSSProperties["font"].subproperties = gCSSProperties["font"].subproperties.concat(fontAdditions);
}

View File

@ -65,6 +65,7 @@ if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
var featureDefs = {
"font-kerning": "auto", // has to be default value
"font-synthesis": "weight style", // has to be default value
"font-variant-alternates": "normal", // has to be default value
"font-variant-caps": "normal", // has to be default value
"font-variant-east-asian": "normal", // has to be default value
"font-variant-ligatures": "normal", // has to be default value

View File

@ -50,7 +50,7 @@ e.setAttribute("style", "font: inherit; font-family: Helvetica;");
var cssTextStr = "font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: inherit; line-height: inherit; font-size-adjust: inherit; font-stretch: inherit; -moz-font-feature-settings: inherit; -moz-font-language-override: inherit;";
if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
cssTextStr += " font-kerning: inherit; font-synthesis: inherit; font-variant-caps: inherit; font-variant-east-asian: inherit; font-variant-ligatures: inherit; font-variant-numeric: inherit; font-variant-position: inherit;"
cssTextStr += " font-kerning: inherit; font-synthesis: inherit; font-variant-alternates: inherit; font-variant-caps: inherit; font-variant-east-asian: inherit; font-variant-ligatures: inherit; font-variant-numeric: inherit; font-variant-position: inherit;"
}
is(e.style.cssText, cssTextStr + " font-family: Helvetica;", "don't serialize system font for font:inherit");