// src: ( uri-src | local-src ) (',' ( uri-src | local-src ) )* // uri-src: uri [ 'format(' string ( ',' string )* ')' ] // local-src: 'local(' ( string | ident ) ')' internal bool ParseFontSrc(ref nsCSSValue aValue) { // could we maybe turn nsCSSValue[] into List<nsCSSValue>? var values = new List<nsCSSValue>(); var cur = new nsCSSValue(); for (;;) { if (!GetToken(true)) break; if (mToken.mType == nsCSSTokenType.URL) { SetValueToURL(ref cur, mToken.mIdentStr); values.AppendElement(cur); if (!ParseFontSrcFormat(values)) return false; } else if (mToken.mType == nsCSSTokenType.Function && mToken.mIdentStr.LowerCaseEqualsLiteral("local")) { // css3-fonts does not specify a formal grammar for local(). // The text permits both unquoted identifiers and quoted // strings. We resolve this ambiguity in the spec by // assuming that the appropriate production is a single // <family-name>, possibly surrounded by whitespace. var family = new StringBuilder(); bool single = false; if (!ParseOneFamily(family, ref single)) { SkipUntil(')'); return false; } if (!ExpectSymbol(')', true)) { SkipUntil(')'); return false; } // the style parameters to the nsFont constructor are ignored, // because it's only being used to call EnumerateFamilies var font = new nsFont(family, 0, 0, 0, 0, 0, 0); var dat = new ExtractFirstFamilyData(); font.EnumerateFamilies(ExtractFirstFamily, (object) dat); if (!dat.mGood) return false; cur.SetStringValue(dat.mFamilyName, nsCSSUnit.LocalFont); values.AppendElement(cur); } else { // We don't know what to do with this token; unget it and error out UngetToken(); return false; } if (!ExpectSymbol(',', true)) break; } if (values.Length() == 0) return false; nsCSSValue[] srcVals = new nsCSSValue[values.Length()]; uint32_t i = 0; for (i = 0; i < values.Length(); i++) srcVals[i] = values[i]; aValue.SetArrayValue(srcVals, nsCSSUnit.Array); return true; }
// font-descriptor: descriptor ':' value ';' // caller has advanced mToken to point at the descriptor internal bool ParseFontDescriptorValue(nsCSSFontDesc aDescID, ref nsCSSValue aValue) { switch (aDescID) { // These four are similar to the properties of the same name, // possibly with more restrictions on the values they can take. case nsCSSFontDesc.Family: { if (!ParseFamily(ref aValue) || aValue.GetUnit() != nsCSSUnit.Families) return false; // the style parameters to the nsFont constructor are ignored, // because it's only being used to call EnumerateFamilies string valueStr = ""; aValue.GetStringValue(ref valueStr); var font = new nsFont(valueStr, 0, 0, 0, 0, 0, 0); var dat = new ExtractFirstFamilyData(); font.EnumerateFamilies(ExtractFirstFamily, (object) dat); if (!dat.mGood) return false; aValue.SetStringValue(dat.mFamilyName, nsCSSUnit.String); return true; } goto case nsCSSFontDesc.Style; case nsCSSFontDesc.Style: // property is VARIANT_HMK|VARIANT_SYSFONT return ParseVariant(ref aValue, VARIANT_KEYWORD | VARIANT_NORMAL, nsCSSProps.kFontStyleKTable); case nsCSSFontDesc.Weight: return (ParseFontWeight(ref aValue) && aValue.GetUnit() != nsCSSUnit.Inherit && aValue.GetUnit() != nsCSSUnit.Initial && (aValue.GetUnit() != nsCSSUnit.Enumerated || (aValue.GetIntValue() != nsStyle.FONT_WEIGHT_BOLDER && aValue.GetIntValue() != nsStyle.FONT_WEIGHT_LIGHTER))); case nsCSSFontDesc.Stretch: // property is VARIANT_HK|VARIANT_SYSFONT return ParseVariant(ref aValue, VARIANT_KEYWORD, nsCSSProps.kFontStretchKTable); // These two are unique to @font-face and have their own special grammar. goto case nsCSSFontDesc.Src; case nsCSSFontDesc.Src: return ParseFontSrc(ref aValue); case nsCSSFontDesc.UnicodeRange: return ParseFontRanges(ref aValue); case nsCSSFontDesc.FontFeatureSettings: return ParseFontFeatureSettings(ref aValue); case nsCSSFontDesc.FontLanguageOverride: return ParseVariant(ref aValue, VARIANT_NORMAL | VARIANT_STRING, null); case nsCSSFontDesc.UNKNOWN: case nsCSSFontDesc.COUNT: Debug.Fail("bad nsCSSFontDesc code"); break; } // explicitly do NOT have a default case to let the compiler // help find missing descriptors return false; }