// 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; }
internal bool ParseFont() { /*TODO: static*/ nsCSSProperty[] fontIDs = { nsCSSProperty.FontStyle, nsCSSProperty.FontVariant, nsCSSProperty.FontWeight }; var family = new nsCSSValue(); if (ParseVariant(ref family, VARIANT_HK, nsCSSProps.kFontKTable)) { if (ExpectEndProperty()) { if (nsCSSUnit.Inherit == family.GetUnit() || nsCSSUnit.Initial == family.GetUnit()) { AppendValue(nsCSSProperty.XSystemFont, new nsCSSValue(nsCSSUnit.None)); AppendValue(nsCSSProperty.FontFamily, family); AppendValue(nsCSSProperty.FontStyle, family); AppendValue(nsCSSProperty.FontVariant, family); AppendValue(nsCSSProperty.FontWeight, family); AppendValue(nsCSSProperty.FontSize, family); AppendValue(nsCSSProperty.LineHeight, family); AppendValue(nsCSSProperty.FontStretch, family); AppendValue(nsCSSProperty.FontSizeAdjust, family); AppendValue(nsCSSProperty.FontFeatureSettings, family); AppendValue(nsCSSProperty.FontLanguageOverride, family); } else { AppendValue(nsCSSProperty.XSystemFont, family); var systemFont = new nsCSSValue(nsCSSUnit.SystemFont); AppendValue(nsCSSProperty.FontFamily, systemFont); AppendValue(nsCSSProperty.FontStyle, systemFont); AppendValue(nsCSSProperty.FontVariant, systemFont); AppendValue(nsCSSProperty.FontWeight, systemFont); AppendValue(nsCSSProperty.FontSize, systemFont); AppendValue(nsCSSProperty.LineHeight, systemFont); AppendValue(nsCSSProperty.FontStretch, systemFont); AppendValue(nsCSSProperty.FontSizeAdjust, systemFont); AppendValue(nsCSSProperty.FontFeatureSettings, systemFont); AppendValue(nsCSSProperty.FontLanguageOverride, systemFont); } return true; } return false; } // Get optional font-style, font-variant and font-weight (in any order) uint32_t numProps = 3; var values = new nsCSSValue[numProps]; int32_t found = ParseChoice(ref values, fontIDs, numProps); if ((found < 0) || (nsCSSUnit.Inherit == values[0].GetUnit()) || (nsCSSUnit.Initial == values[0].GetUnit())) { // illegal data return false; } if ((found & 1) == 0) { // Provide default font-style values[0].SetIntValue(nsFont.STYLE_NORMAL, nsCSSUnit.Enumerated); } if ((found & 2) == 0) { // Provide default font-variant values[1].SetIntValue(nsFont.VARIANT_NORMAL, nsCSSUnit.Enumerated); } if ((found & 4) == 0) { // Provide default font-weight values[2].SetIntValue(nsFont.WEIGHT_NORMAL, nsCSSUnit.Enumerated); } // Get mandatory font-size var size = new nsCSSValue(); if (! ParseVariant(ref size, VARIANT_KEYWORD | VARIANT_LP, nsCSSProps.kFontSizeKTable)) { return false; } // Get optional "/" line-height var lineHeight = new nsCSSValue(); if (ExpectSymbol('/', true)) { if (! ParseNonNegativeVariant(ref lineHeight, VARIANT_NUMBER | VARIANT_LP | VARIANT_NORMAL, null)) { return false; } } else { lineHeight.SetNormalValue(); } // Get final mandatory font-family using (/*var compound = */new nsAutoParseCompoundProperty(this)) { if (ParseFamily(ref family)) { if ((nsCSSUnit.Inherit != family.GetUnit()) && (nsCSSUnit.Initial != family.GetUnit()) && ExpectEndProperty()) { AppendValue(nsCSSProperty.XSystemFont, new nsCSSValue(nsCSSUnit.None)); AppendValue(nsCSSProperty.FontFamily, family); AppendValue(nsCSSProperty.FontStyle, values[0]); AppendValue(nsCSSProperty.FontVariant, values[1]); AppendValue(nsCSSProperty.FontWeight, values[2]); AppendValue(nsCSSProperty.FontSize, size); AppendValue(nsCSSProperty.LineHeight, lineHeight); AppendValue(nsCSSProperty.FontStretch, new nsCSSValue(nsFont.STRETCH_NORMAL, nsCSSUnit.Enumerated)); AppendValue(nsCSSProperty.FontSizeAdjust, new nsCSSValue(nsCSSUnit.None)); AppendValue(nsCSSProperty.FontFeatureSettings, new nsCSSValue(nsCSSUnit.Normal)); AppendValue(nsCSSProperty.FontLanguageOverride, new nsCSSValue(nsCSSUnit.Normal)); return true; } } return false; } }