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 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 ParsePaint(nsCSSProperty aPropID) { nsCSSValue x = new nsCSSValue(), y = new nsCSSValue(); if (!ParseVariant(ref x, VARIANT_HCK | VARIANT_NONE | VARIANT_URL, nsCSSProps.kObjectPatternKTable)) { return false; } bool canHaveFallback = x.GetUnit() == nsCSSUnit.Url || x.GetUnit() == nsCSSUnit.Enumerated; if (canHaveFallback) { if (!ParseVariant(ref y, VARIANT_COLOR | VARIANT_NONE, null)) y.SetNoneValue(); } if (!ExpectEndProperty()) return false; if (!canHaveFallback) { AppendValue(aPropID, x); } else { var val = new nsCSSValue(); val.SetPairValue(x, y); AppendValue(aPropID, val); } return true; }
// flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] internal bool ParseFlex() { // First check for inherit / initial var tmpVal = new nsCSSValue(); if (ParseVariant(ref tmpVal, VARIANT_INHERIT, null)) { AppendValue(nsCSSProperty.FlexGrow, tmpVal); AppendValue(nsCSSProperty.FlexShrink, tmpVal); AppendValue(nsCSSProperty.FlexBasis, tmpVal); return true; } // Next, check for 'none' == '0 0 auto' if (ParseVariant(ref tmpVal, VARIANT_NONE, null)) { AppendValue(nsCSSProperty.FlexGrow, new nsCSSValue(0.0f, nsCSSUnit.Number)); AppendValue(nsCSSProperty.FlexShrink, new nsCSSValue(0.0f, nsCSSUnit.Number)); AppendValue(nsCSSProperty.FlexBasis, new nsCSSValue(nsCSSUnit.Auto)); return true; } // OK, try parsing our value as individual per-subproperty components: // [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] // Each subproperty has a default value that it takes when it's omitted in a // "flex" shorthand value. These default values are *only* for the shorthand // syntax -- they're distinct from the subproperties' own initial values. We // start with each subproperty at its default, as if we had "flex: 1 1 0%". var flexGrow = new nsCSSValue(1.0f, nsCSSUnit.Number); var flexShrink = new nsCSSValue(1.0f, nsCSSUnit.Number); var flexBasis = new nsCSSValue(0.0f, nsCSSUnit.Percent); // OVERVIEW OF PARSING STRATEGY: // ============================= // a) Parse the first component as either flex-basis or flex-grow. // b) If it wasn't flex-grow, parse the _next_ component as flex-grow. // c) Now we've just parsed flex-grow -- so try parsing the next thing as // flex-shrink. // d) Finally: If we didn't get flex-basis at the beginning, try to parse // it now, at the end. // // More details in each section below. uint32_t flexBasisVariantMask = (nsCSSProps.ParserVariant(nsCSSProperty.FlexBasis) & ~(VARIANT_INHERIT)); // (a) Parse first component. It can be either be a 'flex-basis' value or a // 'flex-grow' value, so we use the flex-basis-specific variant mask, along // with VARIANT_NUMBER to accept 'flex-grow' values. // // NOTE: if we encounter unitless 0 here, we *must* interpret it as a // 'flex-grow' value (a number), *not* as a 'flex-basis' value (a length). // Conveniently, that's the behavior this combined variant-mask gives us -- // it'll treat unitless 0 as a number. The flexbox spec requires this: // "a unitless zero that is not already preceded by two flex factors must be // interpreted as a flex factor. if (!ParseNonNegativeVariant(ref tmpVal, flexBasisVariantMask | VARIANT_NUMBER, nsCSSProps.kWidthKTable)) { // First component was not a valid flex-basis or flex-grow value. Fail. return false; } // Record what we just parsed as either flex-basis or flex-grow: bool wasFirstComponentFlexBasis = (tmpVal.GetUnit() != nsCSSUnit.Number); if (wasFirstComponentFlexBasis) flexBasis = tmpVal; else flexGrow = tmpVal; // (b) If we didn't get flex-grow yet, parse _next_ component as flex-grow. bool doneParsing = false; if (wasFirstComponentFlexBasis) { if (ParseNonNegativeVariant(ref tmpVal, VARIANT_NUMBER, null)) { flexGrow = tmpVal; } else { // Failed to parse anything after our flex-basis -- that's fine. We can // skip the remaining parsing. doneParsing = true; } } if (!doneParsing) { // (c) OK -- the last thing we parsed was flex-grow, so look for a // flex-shrink in the next position. if (ParseNonNegativeVariant(ref tmpVal, VARIANT_NUMBER, null)) { flexShrink = tmpVal; } // d) Finally: If we didn't get flex-basis at the beginning, try to parse // it now, at the end. // // NOTE: If we encounter unitless 0 in this final position, we'll parse it // as a 'flex-basis' value. That's OK, because we know it must have // been "preceded by 2 flex factors" (justification below), which gets us // out of the spec's requirement of otherwise having to treat unitless 0 // as a flex factor. // // JUSTIFICATION: How do we know that a unitless 0 here must have been // preceded by 2 flex factors? Well, suppose we had a unitless 0 that // was preceded by only 1 flex factor. Then, we would have already // accepted this unitless 0 as the 'flex-shrink' value, up above (since // it's a valid flex-shrink value), and we'd have moved on to the next // token (if any). And of course, if we instead had a unitless 0 preceded // by *no* flex factors (if it were the first token), we would've already // parsed it in our very first call to ParseNonNegativeVariant(). So, any // unitless 0 encountered here *must* have been preceded by 2 flex factors. if (!wasFirstComponentFlexBasis && ParseNonNegativeVariant(ref tmpVal, flexBasisVariantMask, nsCSSProps.kWidthKTable)) { flexBasis = tmpVal; } } AppendValue(nsCSSProperty.FlexGrow, flexGrow); AppendValue(nsCSSProperty.FlexShrink, flexShrink); AppendValue(nsCSSProperty.FlexBasis, flexBasis); return true; }
public float ComputeNumber(CssValue aValue) { Debug.Assert(aValue.GetUnit() == CssUnit.Number, "unexpected unit"); return aValue.GetFloatValue(); }
internal bool ParseSize() { nsCSSValue width = new nsCSSValue(), height = new nsCSSValue(); if (!ParseVariant(ref width, VARIANT_AHKL, nsCSSProps.kPageSizeKTable)) { return false; } if (width.IsLengthUnit()) { ParseVariant(ref height, VARIANT_LENGTH, null); } if (!ExpectEndProperty()) { return false; } if (width == height || height.GetUnit() == nsCSSUnit.Null) { AppendValue(nsCSSProperty.Size, width); } else { var pair = new nsCSSValue(); pair.SetPairValue(width, height); AppendValue(nsCSSProperty.Size, pair); } return true; }
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; }
// * If aVariantMask is VARIANT_NUMBER, this function parses the // <number-term> production. // * If aVariantMask does not contain VARIANT_NUMBER, this function // parses the <value-term> production. // * Otherwise (VARIANT_NUMBER and other bits) this function parses // whichever one of the productions matches ***and modifies // aVariantMask*** to reflect which one it has parsed by either // removing VARIANT_NUMBER or removing all other bits. internal bool ParseCalcTerm(ref nsCSSValue aValue, ref int32_t aVariantMask) { Debug.Assert(aVariantMask != 0, "unexpected variant mask"); if (!GetToken(true)) return false; // Either an additive expression in parentheses... if (mToken.IsSymbol('(')) { if (!ParseCalcAdditiveExpression(ref aValue, ref aVariantMask) || !ExpectSymbol(')', true)) { SkipUntil(')'); return false; } return true; } // ... or just a value UngetToken(); // Always pass VARIANT_NUMBER to ParseVariant so that unitless zero // always gets picked up if (!ParseVariant(ref aValue, aVariantMask | VARIANT_NUMBER, null)) { return false; } // ...and do the VARIANT_NUMBER check ourselves. if (!((aVariantMask & VARIANT_NUMBER) != 0) && aValue.GetUnit() == nsCSSUnit.Number) { return false; } // If we did the value parsing, we need to adjust aVariantMask to // reflect which option we took (see above). if ((aVariantMask & VARIANT_NUMBER) != 0) { if (aValue.GetUnit() == nsCSSUnit.Number) { aVariantMask = VARIANT_NUMBER; } else { aVariantMask &= ~((int32_t)(VARIANT_NUMBER)); } } return true; }
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; } }
internal bool ParseBorderSpacing() { nsCSSValue xValue = new nsCSSValue(), yValue = new nsCSSValue(); if (!ParseNonNegativeVariant(ref xValue, VARIANT_HL | VARIANT_CALC, null)) { return false; } // If we have one length, get the optional second length. // set the second value equal to the first. if (xValue.IsLengthUnit() || xValue.IsCalcUnit()) { ParseNonNegativeVariant(ref yValue, VARIANT_LENGTH | VARIANT_CALC, null); } if (!ExpectEndProperty()) { return false; } if (yValue == xValue || yValue.GetUnit() == nsCSSUnit.Null) { AppendValue(nsCSSProperty.BorderSpacing, xValue); } else { var pair = new nsCSSValue(); pair.SetPairValue(xValue, yValue); AppendValue(nsCSSProperty.BorderSpacing, pair); } return true; }
internal bool ParseBoxCornerRadius(nsCSSProperty aPropID) { nsCSSValue dimenX = new nsCSSValue(), dimenY = new nsCSSValue(); // required first value if (! ParseNonNegativeVariant(ref dimenX, VARIANT_HLP | VARIANT_CALC, null)) return false; // optional second value (forbidden if first value is inherit/initial) if (dimenX.GetUnit() != nsCSSUnit.Inherit && dimenX.GetUnit() != nsCSSUnit.Initial) { ParseNonNegativeVariant(ref dimenY, VARIANT_LP | VARIANT_CALC, null); } if (dimenX == dimenY || dimenY.GetUnit() == nsCSSUnit.Null) { AppendValue(aPropID, dimenX); } else { var value = new nsCSSValue(); value.SetPairValue(dimenX, dimenY); AppendValue(aPropID, value); } return true; }
internal bool ParseBackground() { using (/*var compound = */new nsAutoParseCompoundProperty(this)) { // background-color can only be set once, so it's not a list. var color = new nsCSSValue(); // Check first for inherit/initial. if (ParseVariant(ref color, VARIANT_INHERIT, null)) { // must be alone if (!ExpectEndProperty()) { return false; } AppendValues(nsCSSProps.SubpropertyEntryFor(nsCSSProperty.Background), color); return true; } nsCSSValue image = new nsCSSValue(), repeat = new nsCSSValue(), attachment = new nsCSSValue(), clip = new nsCSSValue(), origin = new nsCSSValue(), position = new nsCSSValue(), size = new nsCSSValue(); var state = new BackgroundParseState(color, image.SetListValue(), repeat.SetPairListValue(), attachment.SetListValue(), clip.SetListValue(), origin.SetListValue(), position.SetListValue(), size.SetPairListValue()); for (;;) { if (!ParseBackgroundItem(state)) { return false; } if (CheckEndProperty()) { break; } // If we saw a color, this must be the last item. if (color.GetUnit() != nsCSSUnit.Null) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectEndValue", mToken); }; return false; } // Otherwise, a comma is mandatory. if (!ExpectSymbol(',', true)) { return false; } // Chain another entry on all the lists. state.mImage.mNext = new nsCSSValueList(); state.mImage = state.mImage.mNext; state.mRepeat.mNext = new nsCSSValuePairList(); state.mRepeat = state.mRepeat.mNext; state.mAttachment.mNext = new nsCSSValueList(); state.mAttachment = state.mAttachment.mNext; state.mClip.mNext = new nsCSSValueList(); state.mClip = state.mClip.mNext; state.mOrigin.mNext = new nsCSSValueList(); state.mOrigin = state.mOrigin.mNext; state.mPosition.mNext = new nsCSSValueList(); state.mPosition = state.mPosition.mNext; state.mSize.mNext = new nsCSSValuePairList(); state.mSize = state.mSize.mNext; } // If we get to this point without seeing a color, provide a default. if (color.GetUnit() == nsCSSUnit.Null) { color.SetColorValue(nscolor.RGBA(0,0,0,0)); } AppendValue(nsCSSProperty.BackgroundImage, image); AppendValue(nsCSSProperty.BackgroundRepeat, repeat); AppendValue(nsCSSProperty.BackgroundAttachment, attachment); AppendValue(nsCSSProperty.BackgroundClip, clip); AppendValue(nsCSSProperty.BackgroundOrigin, origin); AppendValue(nsCSSProperty.BackgroundPosition, position); AppendValue(nsCSSProperty.BackgroundSize, size); AppendValue(nsCSSProperty.BackgroundColor, color); return true; } }
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; }
internal bool ParseQuotes() { var value = new nsCSSValue(); if (!ParseVariant(ref value, VARIANT_HOS, null)) { return false; } if (value.GetUnit() != nsCSSUnit.String) { if (!ExpectEndProperty()) { return false; } } else { nsCSSValue open = value; nsCSSValuePairList quotes = value.SetPairListValue(); for (;;) { quotes.mXValue = open; // get mandatory close if (!ParseVariant(ref quotes.mYValue, VARIANT_STRING, null)) { return false; } if (CheckEndProperty()) { break; } // look for another open if (!ParseVariant(ref open, VARIANT_STRING, null)) { return false; } quotes.mNext = new nsCSSValuePairList(); quotes = quotes.mNext; } } AppendValue(nsCSSProperty.Quotes, value); 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; }
internal bool ParseShadowItem(ref nsCSSValue aValue, bool aIsBoxShadow) { // A shadow list item is an array, with entries in this sequence: const int IndexX = 0; const int IndexY = 1; const int IndexRadius = 2; const int IndexSpread = 3; const int IndexColor = 4; const int IndexInset = 5; nsCSSValue[] val = new nsCSSValue[6]; if (aIsBoxShadow) { // Optional inset keyword (ignore errors) ParseVariant(ref val[IndexInset], VARIANT_KEYWORD, nsCSSProps.kBoxShadowTypeKTable); } var xOrColor = new nsCSSValue(); bool haveColor = false; if (!ParseVariant(ref xOrColor, VARIANT_COLOR | VARIANT_LENGTH | VARIANT_CALC, null)) { return false; } if (xOrColor.IsLengthUnit() || xOrColor.IsCalcUnit()) { val[IndexX] = xOrColor; } else { // Must be a color (as string or color value) Debug.Assert(xOrColor.GetUnit() == nsCSSUnit.Ident || xOrColor.GetUnit() == nsCSSUnit.Color || xOrColor.GetUnit() == nsCSSUnit.EnumColor, "Must be a color value"); val[IndexColor] = xOrColor; haveColor = true; // X coordinate mandatory after color if (!ParseVariant(ref val[IndexX], VARIANT_LENGTH | VARIANT_CALC, null)) { return false; } } // Y coordinate; mandatory if (!ParseVariant(ref val[IndexY], VARIANT_LENGTH | VARIANT_CALC, null)) { return false; } // Optional radius. Ignore errors except if they pass a negative // value which we must reject. If we use ParseNonNegativeVariant // we can't tell the difference between an unspecified radius // and a negative radius. if (ParseVariant(ref val[IndexRadius], VARIANT_LENGTH | VARIANT_CALC, null) && val[IndexRadius].IsLengthUnit() && val[IndexRadius].GetFloatValue() < 0) { return false; } if (aIsBoxShadow) { // Optional spread ParseVariant(ref val[IndexSpread], VARIANT_LENGTH | VARIANT_CALC, null); } if (!haveColor) { // Optional color ParseVariant(ref val[IndexColor], VARIANT_COLOR, null); } if (aIsBoxShadow && val[IndexInset].GetUnit() == nsCSSUnit.Null) { // Optional inset keyword ParseVariant(ref val[IndexInset], VARIANT_KEYWORD, nsCSSProps.kBoxShadowTypeKTable); } aValue.SetArrayValue(val, nsCSSUnit.Array); return true; }
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; }
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; }
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; }
static nsCSSValueList AppendValueToList(ref nsCSSValue aContainer, nsCSSValueList aTail, nsCSSValue aValue) { nsCSSValueList entry; if (aContainer.GetUnit() == nsCSSUnit.Null) { Debug.Assert(aTail == null, "should not have an entry"); entry = aContainer.SetListValue(); } else { Debug.Assert(aTail.mNext == null, "should not have a next entry"); Debug.Assert(aContainer.GetUnit() == nsCSSUnit.List, "not a list"); entry = new nsCSSValueList(); aTail.mNext = entry; } entry.mValue = aValue; return entry; }
// 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; }
//typedef nsCSSValue input_type; //typedef nsCSSValue::Array input_array_type; public static CssUnit GetUnit(CssValue aValue) { return aValue.GetUnit(); }
//typedef nsCSSValue input_type; //typedef nsCSSValue::Array input_array_type; public static CssUnit GetUnit(CssValue aValue) { return(aValue.GetUnit()); }