// Assigns to aValue iff it returns true. internal bool ParseVariant(ref nsCSSValue aValue, int32_t aVariantMask, int32_t[] aKeywordTable) { Debug.Assert(!(mHashlessColorQuirk && ((aVariantMask & VARIANT_COLOR) != 0)) || !((aVariantMask & VARIANT_NUMBER) != 0), "can't distinguish colors from numbers"); Debug.Assert(!(mHashlessColorQuirk && ((aVariantMask & VARIANT_COLOR) != 0)) || !(mUnitlessLengthQuirk && ((aVariantMask & VARIANT_LENGTH) != 0)), "can't distinguish colors from lengths"); Debug.Assert(!(mUnitlessLengthQuirk && ((aVariantMask & VARIANT_LENGTH) != 0)) || !((aVariantMask & VARIANT_NUMBER) != 0), "can't distinguish lengths from numbers"); Debug.Assert(!((aVariantMask & VARIANT_IDENTIFIER) != 0) || !((aVariantMask & VARIANT_IDENTIFIER_NO_INHERIT) != 0), "must not set both VARIANT_IDENTIFIER and VARIANT_IDENTIFIER_NO_INHERIT"); if (!GetToken(true)) { return false; } nsCSSToken tk = mToken; if (((aVariantMask & (VARIANT_AHK | VARIANT_NORMAL | VARIANT_NONE | VARIANT_ALL)) != 0) && (nsCSSTokenType.Ident == tk.mType)) { nsCSSKeyword keyword = nsCSSKeywords.LookupKeyword(tk.mIdentStr); if (nsCSSKeyword.UNKNOWN < keyword) { // known keyword if ((aVariantMask & VARIANT_AUTO) != 0) { if (nsCSSKeyword.auto == keyword) { aValue.SetAutoValue(); return true; } } if ((aVariantMask & VARIANT_INHERIT) != 0) { // XXX Should we check IsParsingCompoundProperty, or do all // callers handle it? (Not all callers set it, though, since // they want the quirks that are disabled by setting it.) if (nsCSSKeyword.inherit == keyword) { aValue.SetInheritValue(); return true; } else if (nsCSSKeyword._moz_initial == keyword || nsCSSKeyword.initial == keyword) { // anything that can inherit can also take an initial val. aValue.SetInitialValue(); return true; } } if ((aVariantMask & VARIANT_NONE) != 0) { if (nsCSSKeyword.none == keyword) { aValue.SetNoneValue(); return true; } } if ((aVariantMask & VARIANT_ALL) != 0) { if (nsCSSKeyword.all == keyword) { aValue.SetAllValue(); return true; } } if ((aVariantMask & VARIANT_NORMAL) != 0) { if (nsCSSKeyword.normal == keyword) { aValue.SetNormalValue(); return true; } } if ((aVariantMask & VARIANT_SYSFONT) != 0) { if (nsCSSKeyword._moz_use_system_font == keyword && !IsParsingCompoundProperty()) { aValue.SetSystemFontValue(); return true; } } if ((aVariantMask & VARIANT_KEYWORD) != 0) { int32_t value = 0; if (nsCSSProps.FindKeyword(keyword, aKeywordTable, ref value)) { aValue.SetIntValue(value, nsCSSUnit.Enumerated); return true; } } } } // Check VARIANT_NUMBER and VARIANT_INTEGER before VARIANT_LENGTH or // VARIANT_ZERO_ANGLE. if (((aVariantMask & VARIANT_NUMBER) != 0) && (nsCSSTokenType.Number == tk.mType)) { aValue.SetFloatValue(tk.mNumber, nsCSSUnit.Number); return true; } if (((aVariantMask & VARIANT_INTEGER) != 0) && (nsCSSTokenType.Number == tk.mType) && tk.mIntegerValid) { aValue.SetIntValue(tk.mInteger, nsCSSUnit.Integer); return true; } if (((aVariantMask & (VARIANT_LENGTH | VARIANT_ANGLE | VARIANT_FREQUENCY | VARIANT_TIME)) != 0 && nsCSSTokenType.Dimension == tk.mType) || ((aVariantMask & (VARIANT_LENGTH | VARIANT_ZERO_ANGLE)) != 0 && nsCSSTokenType.Number == tk.mType && tk.mNumber == 0.0f)) { if (((aVariantMask & VARIANT_POSITIVE_DIMENSION) != 0 && tk.mNumber <= 0.0) || ((aVariantMask & VARIANT_NONNEGATIVE_DIMENSION) != 0 && tk.mNumber < 0.0)) { UngetToken(); return false; } if (TranslateDimension(ref aValue, aVariantMask, tk.mNumber, tk.mIdentStr)) { return true; } // Put the token back; we didn't parse it, so we shouldn't consume it UngetToken(); return false; } if (((aVariantMask & VARIANT_PERCENT) != 0) && (nsCSSTokenType.Percentage == tk.mType)) { aValue.SetPercentValue(tk.mNumber); return true; } if (mUnitlessLengthQuirk) { // NONSTANDARD: Nav interprets unitless numbers as px if (((aVariantMask & VARIANT_LENGTH) != 0) && (nsCSSTokenType.Number == tk.mType)) { aValue.SetFloatValue(tk.mNumber, nsCSSUnit.Pixel); return true; } } if (IsSVGMode() && !IsParsingCompoundProperty()) { // STANDARD: SVG Spec states that lengths and coordinates can be unitless // in which case they default to user-units (1 px = 1 user unit) if (((aVariantMask & VARIANT_LENGTH) != 0) && (nsCSSTokenType.Number == tk.mType)) { aValue.SetFloatValue(tk.mNumber, nsCSSUnit.Pixel); return true; } } if (((aVariantMask & VARIANT_URL) != 0) && nsCSSTokenType.URL == tk.mType) { SetValueToURL(ref aValue, tk.mIdentStr); return true; } if ((aVariantMask & VARIANT_GRADIENT) != 0 && nsCSSTokenType.Function == tk.mType) { // a generated gradient string tmp = tk.mIdentStr; bool isLegacy = false; if (StringBeginsWith(tmp, "-moz-")) { tmp = tmp.Substring(5); isLegacy = true; } bool isRepeating = false; if (StringBeginsWith(tmp, "repeating-")) { tmp = tmp.Substring(10); isRepeating = true; } if (tmp.LowerCaseEqualsLiteral("linear-gradient")) { return ParseLinearGradient(ref aValue, isRepeating, isLegacy); } if (tmp.LowerCaseEqualsLiteral("radial-gradient")) { return ParseRadialGradient(ref aValue, isRepeating, isLegacy); } } if ((aVariantMask & VARIANT_IMAGE_RECT) != 0 && nsCSSTokenType.Function == tk.mType && tk.mIdentStr.LowerCaseEqualsLiteral("-moz-image-rect")) { return ParseImageRect(ref aValue); } if ((aVariantMask & VARIANT_ELEMENT) != 0 && nsCSSTokenType.Function == tk.mType && tk.mIdentStr.LowerCaseEqualsLiteral("-moz-element")) { return ParseElement(ref aValue); } if ((aVariantMask & VARIANT_COLOR) != 0) { if (mHashlessColorQuirk || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix (nsCSSTokenType.ID == tk.mType) || (nsCSSTokenType.Hash == tk.mType) || (nsCSSTokenType.Ident == tk.mType) || ((nsCSSTokenType.Function == tk.mType) && (tk.mIdentStr.LowerCaseEqualsLiteral("rgb") || tk.mIdentStr.LowerCaseEqualsLiteral("hsl") || tk.mIdentStr.LowerCaseEqualsLiteral("-moz-rgba") || tk.mIdentStr.LowerCaseEqualsLiteral("-moz-hsla") || tk.mIdentStr.LowerCaseEqualsLiteral("rgba") || tk.mIdentStr.LowerCaseEqualsLiteral("hsla")))) { // Put token back so that parse color can get it UngetToken(); if (ParseColor(ref aValue)) { return true; } return false; } } if (((aVariantMask & VARIANT_STRING) != 0) && (nsCSSTokenType.String == tk.mType)) { string buffer; buffer = tk.mIdentStr; aValue.SetStringValue(buffer, nsCSSUnit.String); return true; } if (((aVariantMask & (VARIANT_IDENTIFIER | VARIANT_IDENTIFIER_NO_INHERIT)) != 0) && (nsCSSTokenType.Ident == tk.mType) && ((aVariantMask & VARIANT_IDENTIFIER) != 0 || !(tk.mIdentStr.LowerCaseEqualsLiteral("inherit") || tk.mIdentStr.LowerCaseEqualsLiteral("initial")))) { aValue.SetStringValue(tk.mIdentStr, nsCSSUnit.Ident); return true; } if (((aVariantMask & VARIANT_COUNTER) != 0) && (nsCSSTokenType.Function == tk.mType) && (tk.mIdentStr.LowerCaseEqualsLiteral("counter") || tk.mIdentStr.LowerCaseEqualsLiteral("counters"))) { return ParseCounter(ref aValue); } if (((aVariantMask & VARIANT_ATTR) != 0) && (nsCSSTokenType.Function == tk.mType) && tk.mIdentStr.LowerCaseEqualsLiteral("attr")) { if (!ParseAttr(ref aValue)) { SkipUntil(')'); return false; } return true; } if (((aVariantMask & VARIANT_TIMING_FUNCTION) != 0) && (nsCSSTokenType.Function == tk.mType)) { if (tk.mIdentStr.LowerCaseEqualsLiteral("cubic-bezier")) { if (!ParseTransitionTimingFunctionValues(ref aValue)) { SkipUntil(')'); return false; } return true; } if (tk.mIdentStr.LowerCaseEqualsLiteral("steps")) { if (!ParseTransitionStepTimingFunctionValues(ref aValue)) { SkipUntil(')'); return false; } return true; } } if (((aVariantMask & VARIANT_CALC) != 0) && (nsCSSTokenType.Function == tk.mType) && (tk.mIdentStr.LowerCaseEqualsLiteral("calc") || tk.mIdentStr.LowerCaseEqualsLiteral("-moz-calc"))) { // calc() currently allows only lengths and percents inside it. return ParseCalc(ref aValue, aVariantMask & VARIANT_LP); } UngetToken(); return false; }