Bug 921731 - Part 2: Parse "unset" in property values whereever "inherit" and "initial" are allowed. r=bzbarsky

This commit is contained in:
Cameron McCormack 2013-10-04 04:49:17 +10:00
parent eb835df7de
commit 8752ad5edf
3 changed files with 117 additions and 54 deletions

View File

@ -533,6 +533,7 @@ CSS_KEY(ultra-condensed, ultra_condensed)
CSS_KEY(ultra-expanded, ultra_expanded)
CSS_KEY(underline, underline)
CSS_KEY(unicase, unicase)
CSS_KEY(unset, unset)
CSS_KEY(upper-alpha, upper_alpha)
CSS_KEY(upper-latin, upper_latin)
CSS_KEY(upper-roman, upper_roman)

View File

@ -5086,10 +5086,15 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
aValue.SetInheritValue();
return true;
}
else if (eCSSKeyword_initial == keyword) { // anything that can inherit can also take an initial val.
else if (eCSSKeyword_initial == keyword) {
aValue.SetInitialValue();
return true;
}
else if (eCSSKeyword_unset == keyword &&
nsLayoutUtils::UnsetValueEnabled()) {
aValue.SetUnsetValue();
return true;
}
}
if ((aVariantMask & VARIANT_NONE) != 0) {
if (eCSSKeyword_none == keyword) {
@ -5260,7 +5265,9 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
(eCSSToken_Ident == tk->mType) &&
((aVariantMask & VARIANT_IDENTIFIER) != 0 ||
!(tk->mIdent.LowerCaseEqualsLiteral("inherit") ||
tk->mIdent.LowerCaseEqualsLiteral("initial")))) {
tk->mIdent.LowerCaseEqualsLiteral("initial") ||
(tk->mIdent.LowerCaseEqualsLiteral("unset") &&
nsLayoutUtils::UnsetValueEnabled())))) {
aValue.SetStringValue(tk->mIdent, eCSSUnit_Ident);
return true;
}
@ -5466,7 +5473,7 @@ bool
CSSParserImpl::ParseImageOrientation(nsCSSValue& aValue)
{
if (ParseVariant(aValue, VARIANT_INHERIT, nullptr)) {
// 'inherit' and 'initial' must be alone
// 'inherit', 'initial' and 'unset' must be alone
return true;
}
@ -5578,7 +5585,7 @@ CSSParserImpl::ParseElement(nsCSSValue& aValue)
bool
CSSParserImpl::ParseFlex()
{
// First check for inherit / initial
// First check for inherit / initial / unset
nsCSSValue tmpVal;
if (ParseVariant(tmpVal, VARIANT_INHERIT, nullptr)) {
AppendValue(eCSSProperty_flex_grow, tmpVal);
@ -6081,8 +6088,14 @@ CSSParserImpl::ParseChoice(nsCSSValue aValues[],
}
found = ((1 << aNumIDs) - 1);
}
else if (eCSSUnit_Unset == aValues[0].GetUnit()) { // one unset, all unset
for (loop = 1; loop < aNumIDs; loop++) {
aValues[loop].SetUnsetValue();
}
found = ((1 << aNumIDs) - 1);
}
}
else { // more than one value, verify no inherits or initials
else { // more than one value, verify no inherits, initials or unsets
for (loop = 0; loop < aNumIDs; loop++) {
if (eCSSUnit_Inherit == aValues[loop].GetUnit()) {
found = -1;
@ -6092,6 +6105,10 @@ CSSParserImpl::ParseChoice(nsCSSValue aValues[],
found = -1;
break;
}
else if (eCSSUnit_Unset == aValues[loop].GetUnit()) {
found = -1;
break;
}
}
}
}
@ -6126,10 +6143,12 @@ CSSParserImpl::ParseBoxProperties(const nsCSSProperty aPropIDs[])
return false;
}
if (1 < count) { // verify no more than single inherit or initial
if (1 < count) { // verify no more than single inherit, initial or unset
NS_FOR_CSS_SIDES (index) {
nsCSSUnit unit = (result.*(nsCSSRect::sides[index])).GetUnit();
if (eCSSUnit_Inherit == unit || eCSSUnit_Initial == unit) {
if (eCSSUnit_Inherit == unit ||
eCSSUnit_Initial == unit ||
eCSSUnit_Unset == unit) {
return false;
}
}
@ -6212,9 +6231,10 @@ CSSParserImpl::ParseBoxCornerRadius(nsCSSProperty aPropID)
if (! ParseNonNegativeVariant(dimenX, VARIANT_HLP | VARIANT_CALC, nullptr))
return false;
// optional second value (forbidden if first value is inherit/initial)
// optional second value (forbidden if first value is inherit/initial/unset)
if (dimenX.GetUnit() != eCSSUnit_Inherit &&
dimenX.GetUnit() != eCSSUnit_Initial) {
dimenX.GetUnit() != eCSSUnit_Initial &&
dimenX.GetUnit() != eCSSUnit_Unset) {
ParseNonNegativeVariant(dimenY, VARIANT_LP | VARIANT_CALC, nullptr);
}
@ -6261,10 +6281,12 @@ CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[])
if (!ExpectEndProperty())
return false;
// if 'initial' or 'inherit' was used, it must be the only value
// if 'initial', 'inherit' or 'unset' was used, it must be the only value
if (countX > 1 || countY > 0) {
nsCSSUnit unit = dimenX.mTop.GetUnit();
if (eCSSUnit_Inherit == unit || eCSSUnit_Initial == unit)
if (eCSSUnit_Inherit == unit ||
eCSSUnit_Initial == unit ||
eCSSUnit_Unset == unit)
return false;
}
@ -6741,6 +6763,7 @@ CSSParserImpl::ParseFontDescriptorValue(nsCSSFontDesc aDescID,
return (ParseFontWeight(aValue) &&
aValue.GetUnit() != eCSSUnit_Inherit &&
aValue.GetUnit() != eCSSUnit_Initial &&
aValue.GetUnit() != eCSSUnit_Unset &&
(aValue.GetUnit() != eCSSUnit_Enumerated ||
(aValue.GetIntValue() != NS_STYLE_FONT_WEIGHT_BOLDER &&
aValue.GetIntValue() != NS_STYLE_FONT_WEIGHT_LIGHTER)));
@ -6814,7 +6837,7 @@ CSSParserImpl::ParseBackground()
// background-color can only be set once, so it's not a list.
nsCSSValue color;
// Check first for inherit/initial.
// Check first for inherit/initial/unset.
if (ParseVariant(color, VARIANT_INHERIT, nullptr)) {
// must be alone
if (!ExpectEndProperty()) {
@ -6929,7 +6952,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundParseState& aState)
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
int32_t dummy;
if (keyword == eCSSKeyword_inherit ||
keyword == eCSSKeyword_initial) {
keyword == eCSSKeyword_initial ||
keyword == eCSSKeyword_unset) {
return false;
} else if (keyword == eCSSKeyword_none) {
if (haveImage)
@ -7066,7 +7090,7 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundParseState& aState)
if (haveColor)
return false;
haveColor = true;
// Note: This parses 'inherit' and 'initial', but
// Note: This parses 'inherit', 'initial' and 'unset', but
// we've already checked for them, so it's ok.
if (!ParseSingleValueProperty(aState.mColor,
eCSSProperty_background_color)) {
@ -7087,7 +7111,7 @@ CSSParserImpl::ParseValueList(nsCSSProperty aPropID)
// aPropID is a single value prop-id
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// 'initial' and 'inherit' stand alone, no list permitted.
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ExpectEndProperty()) {
return false;
}
@ -7116,7 +7140,7 @@ CSSParserImpl::ParseBackgroundRepeat()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// 'initial' and 'inherit' stand alone, no list permitted.
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ExpectEndProperty()) {
return false;
}
@ -7175,7 +7199,7 @@ CSSParserImpl::ParseBackgroundPosition()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// 'initial' and 'inherit' stand alone, no list permitted.
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ExpectEndProperty()) {
return false;
}
@ -7216,7 +7240,8 @@ CSSParserImpl::ParseBackgroundPosition()
* like "top," "left center," etc.
*
* @param aOut The nsCSSValuePair in which to place the result.
* @param aAcceptsInherit If true, 'inherit' and 'initial' are legal values
* @param aAcceptsInherit If true, 'inherit', 'initial' and 'unset' are
* legal values
* @param aAllowExplicitCenter If true, 'center' is a legal value
* @return Whether or not the operation succeeded.
*/
@ -7231,7 +7256,8 @@ bool CSSParserImpl::ParseBoxPositionValues(nsCSSValuePair &aOut,
(aAcceptsInherit ? VARIANT_INHERIT : 0) | VARIANT_LP | VARIANT_CALC;
if (ParseVariant(xValue, variantMask, nullptr)) {
if (eCSSUnit_Inherit == xValue.GetUnit() ||
eCSSUnit_Initial == xValue.GetUnit()) { // both are inherited or both are set to initial
eCSSUnit_Initial == xValue.GetUnit() ||
eCSSUnit_Unset == xValue.GetUnit()) { // both are inherit, initial or unset
yValue = xValue;
return true;
}
@ -7493,7 +7519,7 @@ CSSParserImpl::ParseBackgroundSize()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// 'initial' and 'inherit' stand alone, no list permitted.
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ExpectEndProperty()) {
return false;
}
@ -7527,8 +7553,8 @@ CSSParserImpl::ParseBackgroundSize()
* Parses two values that correspond to lengths for the background-size
* property. These can be one or two lengths (or the 'auto' keyword) or
* percentages corresponding to the element's dimensions or the single keywords
* 'contain' or 'cover'. 'initial' and 'inherit' must be handled by the caller
* if desired.
* 'contain' or 'cover'. 'initial', 'inherit' and 'unset' must be handled by
* the caller if desired.
*
* @param aOut The nsCSSValuePair in which to place the result.
* @return Whether or not the operation succeeded.
@ -7627,7 +7653,8 @@ CSSParserImpl::ParseBorderImageSlice(bool aAcceptsInherit,
}
if (aAcceptsInherit && ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// Keyword "inherit" can not be mixed, so we are done.
// Keywords "inherit", "initial" and "unset" can not be mixed, so we
// are done.
AppendValue(eCSSProperty_border_image_slice, value);
return true;
}
@ -7675,7 +7702,8 @@ CSSParserImpl::ParseBorderImageWidth(bool aAcceptsInherit)
nsCSSValue value;
if (aAcceptsInherit && ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// Keyword "inherit" can no be mixed, so we are done.
// Keywords "inherit", "initial" and "unset" can not be mixed, so we
// are done.
AppendValue(eCSSProperty_border_image_width, value);
return true;
}
@ -7696,7 +7724,8 @@ CSSParserImpl::ParseBorderImageOutset(bool aAcceptsInherit)
nsCSSValue value;
if (aAcceptsInherit && ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// Keyword "inherit" can not be mixed, so we are done.
// Keywords "inherit", "initial" and "unset" can not be mixed, so we
// are done.
AppendValue(eCSSProperty_border_image_outset, value);
return true;
}
@ -7715,7 +7744,8 @@ CSSParserImpl::ParseBorderImageRepeat(bool aAcceptsInherit)
{
nsCSSValue value;
if (aAcceptsInherit && ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// Keyword "inherit" can not be mixed, so we are done.
// Keywords "inherit", "initial" and "unset" can not be mixed, so we
// are done.
AppendValue(eCSSProperty_border_image_repeat, value);
return true;
}
@ -7754,7 +7784,7 @@ CSSParserImpl::ParseBorderImage()
AppendValue(eCSSProperty_border_image_width, value);
AppendValue(eCSSProperty_border_image_outset, value);
AppendValue(eCSSProperty_border_image_repeat, value);
// Keyword "inherit" (and "initial") can't be mixed, so we are done.
// Keywords "inherit", "initial" and "unset" can't be mixed, so we are done.
return true;
}
@ -7919,8 +7949,9 @@ CSSParserImpl::ParseBorderSide(const nsCSSProperty aPropIDs[],
switch (values[0].GetUnit()) {
case eCSSUnit_Inherit:
case eCSSUnit_Initial:
case eCSSUnit_Unset:
extraValue = values[0];
// Set value of border-image properties to initial/inherit
// Set value of border-image properties to initial/inherit/unset
AppendValue(eCSSProperty_border_image_source, extraValue);
AppendValue(eCSSProperty_border_image_slice, extraValue);
AppendValue(eCSSProperty_border_image_width, extraValue);
@ -8016,7 +8047,7 @@ CSSParserImpl::ParseBorderColors(nsCSSProperty aProperty)
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
// 'inherit', 'initial', and 'none' are only allowed on their own
// 'inherit', 'initial', 'unset' and 'none' are only allowed on their own
if (!ExpectEndProperty()) {
return false;
}
@ -8330,6 +8361,15 @@ CSSParserImpl::ParseRect(nsCSSProperty aPropID)
}
val.SetInitialValue();
break;
case eCSSKeyword_unset:
if (nsLayoutUtils::UnsetValueEnabled()) {
if (!ExpectEndProperty()) {
return false;
}
val.SetUnsetValue();
break;
}
// fall through
default:
UngetToken();
return false;
@ -8444,7 +8484,8 @@ CSSParserImpl::ParseContent()
nsCSSValue value;
if (ParseVariant(value, VARIANT_HMK | VARIANT_NONE,
kContentSolitaryKWs)) {
// 'inherit', 'initial', 'normal', 'none', and 'alt-content' must be alone
// 'inherit', 'initial', 'unset', 'normal', 'none', and 'alt-content' must
// be alone
if (!ExpectEndProperty()) {
return false;
}
@ -8504,7 +8545,7 @@ CSSParserImpl::ParseCursor()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
// 'inherit' and 'initial' must be alone
// 'inherit', 'initial' and 'unset' must be alone
if (!ExpectEndProperty()) {
return false;
}
@ -8562,7 +8603,8 @@ CSSParserImpl::ParseFont()
if (ParseVariant(family, VARIANT_HK, nsCSSProps::kFontKTable)) {
if (ExpectEndProperty()) {
if (eCSSUnit_Inherit == family.GetUnit() ||
eCSSUnit_Initial == family.GetUnit()) {
eCSSUnit_Initial == family.GetUnit() ||
eCSSUnit_Unset == family.GetUnit()) {
AppendValue(eCSSProperty__x_system_font, nsCSSValue(eCSSUnit_None));
AppendValue(eCSSProperty_font_family, family);
AppendValue(eCSSProperty_font_style, family);
@ -8618,8 +8660,10 @@ CSSParserImpl::ParseFont()
const int32_t numProps = 3;
nsCSSValue values[numProps];
int32_t found = ParseChoice(values, fontIDs, numProps);
if ((found < 0) || (eCSSUnit_Inherit == values[0].GetUnit()) ||
(eCSSUnit_Initial == values[0].GetUnit())) { // illegal data
if (found < 0 ||
eCSSUnit_Inherit == values[0].GetUnit() ||
eCSSUnit_Initial == values[0].GetUnit() ||
eCSSUnit_Unset == values[0].GetUnit()) { // illegal data
return false;
}
if ((found & 1) == 0) {
@ -8658,7 +8702,9 @@ CSSParserImpl::ParseFont()
// Get final mandatory font-family
nsAutoParseCompoundProperty compound(this);
if (ParseFamily(family)) {
if ((eCSSUnit_Inherit != family.GetUnit()) && (eCSSUnit_Initial != family.GetUnit()) &&
if (eCSSUnit_Inherit != family.GetUnit() &&
eCSSUnit_Initial != family.GetUnit() &&
eCSSUnit_Unset != family.GetUnit() &&
ExpectEndProperty()) {
AppendValue(eCSSProperty__x_system_font, nsCSSValue(eCSSUnit_None));
AppendValue(eCSSProperty_font_family, family);
@ -8707,7 +8753,8 @@ CSSParserImpl::ParseFontSynthesis(nsCSSValue& aValue)
// first value 'none' ==> done
if (eCSSUnit_None == aValue.GetUnit() ||
eCSSUnit_Initial == aValue.GetUnit() ||
eCSSUnit_Inherit == aValue.GetUnit())
eCSSUnit_Inherit == aValue.GetUnit() ||
eCSSUnit_Unset == aValue.GetUnit())
{
return true;
}
@ -8857,10 +8904,11 @@ CSSParserImpl::ParseBitmaskValues(nsCSSValue& aValue,
return false;
}
// first value 'normal', 'inherit', 'initial' ==> done
// first value 'normal', 'inherit', 'unset', 'initial', 'unset' ==> done
if (eCSSUnit_Normal == aValue.GetUnit() ||
eCSSUnit_Initial == aValue.GetUnit() ||
eCSSUnit_Inherit == aValue.GetUnit())
eCSSUnit_Inherit == aValue.GetUnit() ||
eCSSUnit_Unset == aValue.GetUnit())
{
return true;
}
@ -9048,6 +9096,11 @@ CSSParserImpl::ParseFamily(nsCSSValue& aValue)
aValue.SetInitialValue();
return true;
}
if (keyword == eCSSKeyword_unset &&
nsLayoutUtils::UnsetValueEnabled()) {
aValue.SetUnsetValue();
return true;
}
if (keyword == eCSSKeyword__moz_use_system_font &&
!IsParsingCompoundProperty()) {
aValue.SetSystemFontValue();
@ -9075,6 +9128,11 @@ CSSParserImpl::ParseFamily(nsCSSValue& aValue)
case eCSSKeyword_default:
case eCSSKeyword__moz_use_system_font:
return false;
case eCSSKeyword_unset:
if (nsLayoutUtils::UnsetValueEnabled()) {
return false;
}
// fall through
default:
break;
}
@ -9690,7 +9748,7 @@ bool
CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue)
{
if (ParseVariant(aValue, VARIANT_INHERIT, nullptr)) {
// 'inherit' and 'initial' must be alone
// 'inherit', 'initial' and 'unset' must be alone
return true;
}
@ -10074,7 +10132,7 @@ bool CSSParserImpl::ParseTransform(bool aIsPrefixed)
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
// 'inherit', 'initial', and 'none' must be alone
// 'inherit', 'initial', 'unset' and 'none' must be alone
if (!ExpectEndProperty()) {
return false;
}
@ -10113,9 +10171,10 @@ bool CSSParserImpl::ParseTransformOrigin(bool aPerspective)
// as a pair, even if the values are the same, so it always serializes as
// a pair, and to keep the computation code simple.
if (position.mXValue.GetUnit() == eCSSUnit_Inherit ||
position.mXValue.GetUnit() == eCSSUnit_Initial) {
position.mXValue.GetUnit() == eCSSUnit_Initial ||
position.mXValue.GetUnit() == eCSSUnit_Unset) {
NS_ABORT_IF_FALSE(position.mXValue == position.mYValue,
"inherit/initial only half?");
"inherit/initial/unset only half?");
AppendValue(prop, position.mXValue);
} else {
nsCSSValue value;
@ -10288,7 +10347,7 @@ CSSParserImpl::ParseFilter()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
// 'inherit', 'initial', and 'none' must be alone
// 'inherit', 'initial', 'unset' and 'none' must be alone
if (!ExpectEndProperty()) {
return false;
}
@ -10320,7 +10379,7 @@ CSSParserImpl::ParseTransitionProperty()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
// 'inherit', 'initial', and 'none' must be alone
// 'inherit', 'initial', 'unset' and 'none' must be alone
if (!ExpectEndProperty()) {
return false;
}
@ -10336,11 +10395,13 @@ CSSParserImpl::ParseTransitionProperty()
}
if (cur->mValue.GetUnit() == eCSSUnit_Ident) {
nsDependentString str(cur->mValue.GetStringBufferValue());
// Exclude 'none' and 'inherit' and 'initial' according to the
// Exclude 'none', 'inherit', 'initial' and 'unset' according to the
// same rules as for 'counter-reset' in CSS 2.1.
if (str.LowerCaseEqualsLiteral("none") ||
str.LowerCaseEqualsLiteral("inherit") ||
str.LowerCaseEqualsLiteral("initial")) {
str.LowerCaseEqualsLiteral("initial") ||
(str.LowerCaseEqualsLiteral("unset") &&
nsLayoutUtils::UnsetValueEnabled())) {
return false;
}
}
@ -10478,7 +10539,7 @@ CSSParserImpl::ParseAnimationOrTransitionShorthand(
size_t aNumProperties)
{
nsCSSValue tempValue;
// first see if 'inherit' or 'initial' is specified. If one is,
// first see if 'inherit', 'initial' or 'unset' is specified. If one is,
// it can be the only thing specified, so don't attempt to parse any
// additional properties
if (ParseVariant(tempValue, VARIANT_INHERIT, nullptr)) {
@ -10593,9 +10654,7 @@ CSSParserImpl::ParseTransition()
// Make two checks on the list for 'transition-property':
// + If there is more than one item, then none of the items can be
// 'none' or 'all'.
// + None of the items can be 'inherit' or 'initial' (this is the case,
// like with counter-reset &c., where CSS 2.1 specifies 'initial', so
// we should check it without the -moz- prefix).
// + None of the items can be 'inherit', 'initial' or 'unset'.
{
NS_ABORT_IF_FALSE(kTransitionProperties[3] ==
eCSSProperty_transition_property,
@ -10616,7 +10675,10 @@ CSSParserImpl::ParseTransition()
}
if (val.GetUnit() == eCSSUnit_Ident) {
nsDependentString str(val.GetStringBufferValue());
if (str.EqualsLiteral("inherit") || str.EqualsLiteral("initial")) {
if (str.EqualsLiteral("inherit") ||
str.EqualsLiteral("initial") ||
(str.EqualsLiteral("unset") &&
nsLayoutUtils::UnsetValueEnabled())) {
return false;
}
}
@ -10771,7 +10833,7 @@ CSSParserImpl::ParseShadowList(nsCSSProperty aProperty)
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
// 'inherit', 'initial', and 'none' must be alone
// 'inherit', 'initial', 'unset' and 'none' must be alone
if (!ExpectEndProperty()) {
return false;
}
@ -10866,7 +10928,7 @@ CSSParserImpl::ParseDasharray()
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE |
VARIANT_OPENTYPE_SVG_KEYWORD,
nsCSSProps::kStrokeContextValueKTable)) {
// 'inherit', 'initial', and 'none' are only allowed on their own
// 'inherit', 'initial', 'unset' and 'none' are only allowed on their own
if (!ExpectEndProperty()) {
return false;
}

View File

@ -34,7 +34,7 @@
#define VARIANT_IDENTIFIER_NO_INHERIT 0x004000 // like above, but excluding
// 'inherit' and 'initial'
#define VARIANT_AUTO 0x010000 // A
#define VARIANT_INHERIT 0x020000 // H eCSSUnit_Initial, eCSSUnit_Inherit
#define VARIANT_INHERIT 0x020000 // H eCSSUnit_Initial, eCSSUnit_Inherit, eCSSUnit_Unset
#define VARIANT_NONE 0x040000 // O
#define VARIANT_NORMAL 0x080000 // M
#define VARIANT_SYSFONT 0x100000 // eCSSUnit_System_Font