internal bool ParseTextDecorationLine(ref nsCSSValue aValue) { if (ParseVariant(ref aValue, VARIANT_HK, nsCSSProps.kTextDecorationLineKTable)) { if (nsCSSUnit.Enumerated == aValue.GetUnit()) { int32_t intValue = aValue.GetIntValue(); if (intValue != nsStyle.TEXT_DECORATION_LINE_NONE) { // look for more keywords var keyword = new nsCSSValue(); int32_t index = 0; for (index = 0; index < 2; index++) { if (ParseEnum(ref keyword, nsCSSProps.kTextDecorationLineKTable)) { int32_t newValue = keyword.GetIntValue(); if (newValue == nsStyle.TEXT_DECORATION_LINE_NONE || ((newValue & intValue) != 0)) { // 'none' keyword in conjuction with others is not allowed, and // duplicate keyword is not allowed. return false; } intValue |= newValue; } else { break; } } aValue.SetIntValue(intValue, nsCSSUnit.Enumerated); } } return true; } return false; }
internal bool ParsePaintOrder() { /*TODO: static*/ int32_t[] kPaintOrderKTable = { (int32_t)nsCSSKeyword.normal, nsStyle.PAINT_ORDER_NORMAL, (int32_t)nsCSSKeyword.fill, nsStyle.PAINT_ORDER_FILL, (int32_t)nsCSSKeyword.stroke, nsStyle.PAINT_ORDER_STROKE, (int32_t)nsCSSKeyword.markers, nsStyle.PAINT_ORDER_MARKERS, (int32_t)nsCSSKeyword.UNKNOWN,-1 }; var value = new nsCSSValue(); if (!ParseVariant(ref value, VARIANT_HK, kPaintOrderKTable)) { return false; } uint32_t seen = 0; uint32_t order = 0; uint32_t position = 0; // Ensure that even cast to a signed int32_t when stored in CSSValue, // we have enough space for the entire paint-order value. if (value.GetUnit() == nsCSSUnit.Enumerated) { uint32_t component = ((uint32_t)(value.GetIntValue())); if (component != nsStyle.PAINT_ORDER_NORMAL) { bool parsedOK = true; for (;;) { if (((seen & (1 << component)) != 0)) { // Already seen this component. UngetToken(); parsedOK = false; break; } seen |= (1 << component); order |= (component << position); position += nsStyle.PAINT_ORDER_BITWIDTH; if (!ParseEnum(ref value, kPaintOrderKTable)) { break; } component = value.GetIntValue(); if (component == nsStyle.PAINT_ORDER_NORMAL) { // Can't have "normal" in the middle of the list of paint components. UngetToken(); parsedOK = false; break; } } // Fill in the remaining paint-order components in the order of their // constant values. if (parsedOK) { for (component = 1; component <= nsStyle.PAINT_ORDER_LAST_VALUE; component++) { if (!(((seen & (1 << component)) != 0))) { order |= (component << position); position += nsStyle.PAINT_ORDER_BITWIDTH; } } } } value.SetIntValue(((int32_t)(order)), nsCSSUnit.Enumerated); } if (!ExpectEndProperty()) { return false; } AppendValue(nsCSSProperty.PaintOrder, value); return true; }
internal bool ParseTextDecoration() { const int eDecorationNone = nsStyle.TEXT_DECORATION_LINE_NONE; const int eDecorationUnderline = nsStyle.TEXT_DECORATION_LINE_UNDERLINE; const int eDecorationOverline = nsStyle.TEXT_DECORATION_LINE_OVERLINE; const int eDecorationLineThrough = nsStyle.TEXT_DECORATION_LINE_LINE_THROUGH; const int eDecorationBlink = nsStyle.TEXT_DECORATION_LINE_BLINK; const int eDecorationPrefAnchors = nsStyle.TEXT_DECORATION_LINE_PREF_ANCHORS; /*TODO: static*/ int32_t[] kTextDecorationKTable = { (int32_t)nsCSSKeyword.none, eDecorationNone, (int32_t)nsCSSKeyword.underline, eDecorationUnderline, (int32_t)nsCSSKeyword.overline, eDecorationOverline, (int32_t)nsCSSKeyword.line_through, eDecorationLineThrough, (int32_t)nsCSSKeyword.blink, eDecorationBlink, (int32_t)nsCSSKeyword._moz_anchor_decoration, eDecorationPrefAnchors, (int32_t)nsCSSKeyword.UNKNOWN,-1 }; var value = new nsCSSValue(); if (!ParseVariant(ref value, VARIANT_HK, kTextDecorationKTable)) { return false; } nsCSSValue blink = new nsCSSValue(), line = new nsCSSValue(), style = new nsCSSValue(), color = new nsCSSValue(); switch (value.GetUnit()) { case nsCSSUnit.Enumerated: { // We shouldn't accept decoration line style and color via // text-decoration. color.SetIntValue(nsStyle.COLOR_MOZ_USE_TEXT_COLOR, nsCSSUnit.Enumerated); style.SetIntValue(nsStyle.TEXT_DECORATION_STYLE_SOLID, nsCSSUnit.Enumerated); int32_t intValue = value.GetIntValue(); if (intValue == eDecorationNone) { blink.SetIntValue(nsStyle.TEXT_BLINK_NONE, nsCSSUnit.Enumerated); line.SetIntValue(nsStyle.TEXT_DECORATION_LINE_NONE, nsCSSUnit.Enumerated); break; } // look for more keywords var keyword = new nsCSSValue(); int32_t index = 0; for (index = 0; index < 3; index++) { if (!ParseEnum(ref keyword, kTextDecorationKTable)) { break; } int32_t newValue = keyword.GetIntValue(); if (newValue == eDecorationNone || ((newValue & intValue) != 0)) { // 'none' keyword in conjuction with others is not allowed, and // duplicate keyword is not allowed. return false; } intValue |= newValue; } blink.SetIntValue((intValue & eDecorationBlink) != 0 ? nsStyle.TEXT_BLINK_BLINK : nsStyle.TEXT_BLINK_NONE, nsCSSUnit.Enumerated); line.SetIntValue((intValue & ~eDecorationBlink), nsCSSUnit.Enumerated); break; } goto default; default: blink = line = color = style = value; break; } AppendValue(nsCSSProperty.TextBlink, blink); AppendValue(nsCSSProperty.TextDecorationLine, line); AppendValue(nsCSSProperty.TextDecorationColor, color); AppendValue(nsCSSProperty.TextDecorationStyle, style); return true; }
// Note that callers passing VARIANT_CALC in aVariantMask will get // full-range parsing inside the calc() expression, and the code that // computes the calc will be required to clamp the resulting value to an // appropriate range. internal bool ParseOneOrLargerVariant(ref nsCSSValue aValue, int32_t aVariantMask, int32_t[] aKeywordTable) { // The variant mask must only contain non-numeric variants or the ones // that we specifically handle. Debug.Assert((aVariantMask & ~(VARIANT_ALL_NONNUMERIC | VARIANT_NUMBER | VARIANT_INTEGER)) == 0, "need to update code below to handle additional variants"); if (ParseVariant(ref aValue, aVariantMask, aKeywordTable)) { if (aValue.GetUnit() == nsCSSUnit.Integer) { if (aValue.GetIntValue() < 1) { UngetToken(); return false; } } else if (nsCSSUnit.Number == aValue.GetUnit()) { if (aValue.GetFloatValue() < 1.0f) { UngetToken(); return false; } } return true; } return false; }
internal bool ParseOverflow() { var overflow = new nsCSSValue(); if (!ParseVariant(ref overflow, VARIANT_HK, nsCSSProps.kOverflowKTable) || !ExpectEndProperty()) return false; var overflowX = new nsCSSValue(overflow); var overflowY = new nsCSSValue(overflow); if (nsCSSUnit.Enumerated == overflow.GetUnit()) switch(overflow.GetIntValue()) { case nsStyle.OVERFLOW_SCROLLBARS_HORIZONTAL: overflowX.SetIntValue(nsStyle.OVERFLOW_SCROLL, nsCSSUnit.Enumerated); overflowY.SetIntValue(nsStyle.OVERFLOW_HIDDEN, nsCSSUnit.Enumerated); break; case nsStyle.OVERFLOW_SCROLLBARS_VERTICAL: overflowX.SetIntValue(nsStyle.OVERFLOW_HIDDEN, nsCSSUnit.Enumerated); overflowY.SetIntValue(nsStyle.OVERFLOW_SCROLL, nsCSSUnit.Enumerated); break; } AppendValue(nsCSSProperty.OverflowX, overflowX); AppendValue(nsCSSProperty.OverflowY, overflowY); return true; }
internal bool ParseMarks(ref nsCSSValue aValue) { if (ParseVariant(ref aValue, VARIANT_HK, nsCSSProps.kPageMarksKTable)) { if (nsCSSUnit.Enumerated == aValue.GetUnit()) { if (nsStyle.PAGE_MARKS_NONE != aValue.GetIntValue() && false == CheckEndProperty()) { var second = new nsCSSValue(); if (ParseEnum(ref second, nsCSSProps.kPageMarksKTable)) { // 'none' keyword in conjuction with others is not allowed if (nsStyle.PAGE_MARKS_NONE != second.GetIntValue()) { aValue.SetIntValue(aValue.GetIntValue() | second.GetIntValue(), nsCSSUnit.Enumerated); return true; } } return false; } } return true; } return false; }
internal bool ParseFontWeight(ref nsCSSValue aValue) { if (ParseVariant(ref aValue, VARIANT_HKI | VARIANT_SYSFONT, nsCSSProps.kFontWeightKTable)) { if (nsCSSUnit.Integer == aValue.GetUnit()) { // ensure unit value int32_t intValue = aValue.GetIntValue(); if ((100 <= intValue) && (intValue <= 900) && (0 == (intValue % 100))) { return true; } else { UngetToken(); return false; } } return true; } return false; }
// 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; }
internal bool ParseTextDecoration() { const int eDecorationNone = nsStyle.TextDecorationLineNone; const int eDecorationUnderline = nsStyle.TextDecorationLineUnderline; const int eDecorationOverline = nsStyle.TextDecorationLineOverline; const int eDecorationLineThrough = nsStyle.TextDecorationLineLineThrough; const int eDecorationBlink = nsStyle.TextDecorationLineBlink; const int eDecorationPrefAnchors = nsStyle.TextDecorationLinePrefAnchors; /*TODO: static*/ int32_t[] kTextDecorationKTable = { (int32_t)nsCSSKeyword.None, eDecorationNone, (int32_t)nsCSSKeyword.Underline, eDecorationUnderline, (int32_t)nsCSSKeyword.Overline, eDecorationOverline, (int32_t)nsCSSKeyword.LineThrough, eDecorationLineThrough, (int32_t)nsCSSKeyword.Blink, eDecorationBlink, (int32_t)nsCSSKeyword.MozAnchorDecoration, eDecorationPrefAnchors, (int32_t)nsCSSKeyword.Unknown,-1 }; var value = new nsCSSValue(); if (!ParseVariant(ref value, VARIANT_HK, kTextDecorationKTable)) { return false; } nsCSSValue blink = new nsCSSValue(), line = new nsCSSValue(), style = new nsCSSValue(), color = new nsCSSValue(); switch (value.GetUnit()) { case nsCSSUnit.Enumerated: { // We shouldn't accept decoration line style and color via // text-decoration. color.SetIntValue(nsStyle.ColorMozUseTextColor, nsCSSUnit.Enumerated); style.SetIntValue(nsStyle.TextDecorationStyleSolid, nsCSSUnit.Enumerated); int32_t intValue = value.GetIntValue(); if (intValue == eDecorationNone) { blink.SetIntValue(nsStyle.TextBlinkNone, nsCSSUnit.Enumerated); line.SetIntValue(nsStyle.TextDecorationLineNone, nsCSSUnit.Enumerated); break; } // look for more keywords var keyword = new nsCSSValue(); int32_t index = 0; for (index = 0; index < 3; index++) { if (!ParseEnum(ref keyword, kTextDecorationKTable)) { break; } int32_t newValue = keyword.GetIntValue(); if (newValue == eDecorationNone || ((newValue & intValue) != 0)) { // 'none' keyword in conjuction with others is not allowed, and // duplicate keyword is not allowed. return false; } intValue |= newValue; } blink.SetIntValue((intValue & eDecorationBlink) != 0 ? nsStyle.TextBlinkBlink : nsStyle.TextBlinkNone, nsCSSUnit.Enumerated); line.SetIntValue((intValue & ~eDecorationBlink), nsCSSUnit.Enumerated); break; } goto default; default: blink = line = color = style = value; break; } AppendValue(nsCSSProperty.TextBlink, blink); AppendValue(nsCSSProperty.TextDecorationLine, line); AppendValue(nsCSSProperty.TextDecorationColor, color); AppendValue(nsCSSProperty.TextDecorationStyle, style); return true; }
internal bool ParseOverflow() { var overflow = new nsCSSValue(); if (!ParseVariant(ref overflow, VARIANT_HK, nsCSSProps.kOverflowKTable) || !ExpectEndProperty()) return false; var overflowX = new nsCSSValue(overflow); var overflowY = new nsCSSValue(overflow); if (nsCSSUnit.Enumerated == overflow.GetUnit()) switch(overflow.GetIntValue()) { case nsStyle.OverflowScrollbarsHorizontal: overflowX.SetIntValue(nsStyle.OverflowScroll, nsCSSUnit.Enumerated); overflowY.SetIntValue(nsStyle.OverflowHidden, nsCSSUnit.Enumerated); break; case nsStyle.OverflowScrollbarsVertical: overflowX.SetIntValue(nsStyle.OverflowHidden, nsCSSUnit.Enumerated); overflowY.SetIntValue(nsStyle.OverflowScroll, nsCSSUnit.Enumerated); break; } AppendValue(nsCSSProperty.OverflowX, overflowX); AppendValue(nsCSSProperty.OverflowY, overflowY); return true; }