예제 #1
0
        /**
         * BoxPositionMaskToCSSValue and ParseBoxPositionValues are used
         * for parsing the CSS 2.1 background-position syntax (which has at
         * most two values).  (Compare to the css3-background syntax which
         * takes up to four values.)  Some current CSS specifications that
         * use background-position-like syntax still use this old syntax.
         **
         * Parses two values that correspond to positions in a box.  These can be
         * values corresponding to percentages of the box, raw offsets, or keywords
         * like "top," "left center," etc.
         *
         * @param aOut The nsCSSValuePair in which to place the result.
         * @param aAcceptsInherit If true, 'inherit' and 'initial' are legal values
         * @param aAllowExplicitCenter If true, 'center' is a legal value
         * @return Whether or not the operation succeeded.
         */
        bool ParseBoxPositionValues(ref nsCSSValuePair aOut,
                                                   bool aAcceptsInherit,
                                                   bool aAllowExplicitCenter = true)
        {
            // First try a percentage or a length value
              nsCSSValue xValue = aOut.mXValue,
                     yValue = aOut.mYValue;
              int32_t variantMask =
            (aAcceptsInherit ? VARIANT_INHERIT : 0) | VARIANT_LP | VARIANT_CALC;
              if (ParseVariant(ref xValue, variantMask, null)) {
            if (nsCSSUnit.Inherit == xValue.GetUnit() ||
                nsCSSUnit.Initial == xValue.GetUnit()) {  // both are inherited or both are set to initial
              yValue = xValue;
              return true;
            }
            // We have one percentage/length/calc. Get the optional second
            // percentage/length/calc/keyword.
            if (ParseVariant(ref yValue, VARIANT_LP | VARIANT_CALC, null)) {
              // We have two numbers
              return true;
            }

            if (ParseEnum(ref yValue, nsCSSProps.kBackgroundPositionKTable)) {
              int32_t yVal = yValue.GetIntValue();
              if (!((yVal & BG_CTB) != 0)) {
                // The second keyword can only be 'center', 'top', or 'bottom'
                return false;
              }
              yValue = BoxPositionMaskToCSSValue(yVal, false);
              return true;
            }

            // If only one percentage or length value is given, it sets the
            // horizontal position only, and the vertical position will be 50%.
            yValue.SetPercentValue(0.5f);
            return true;
              }

              // Now try keywords. We do this manually to allow for the first
              // appearance of "center" to apply to the either the x or y
              // position (it's ambiguous so we have to disambiguate). Each
              // allowed keyword value is assigned it's own bit. We don't allow
              // any duplicate keywords other than center. We try to get two
              // keywords but it's okay if there is only one.
              int32_t mask = 0;
              if (ParseEnum(ref xValue, nsCSSProps.kBackgroundPositionKTable)) {
            int32_t bit = xValue.GetIntValue();
            mask |= bit;
            if (ParseEnum(ref xValue, nsCSSProps.kBackgroundPositionKTable)) {
              bit = xValue.GetIntValue();
              if ((mask & (bit & ~BG_CENTER)) != 0) {
                // Only the 'center' keyword can be duplicated.
                return false;
              }
              mask |= bit;
            }
            else {
              // Only one keyword.  See if we have a length, percentage, or calc.
              if (ParseVariant(ref yValue, VARIANT_LP | VARIANT_CALC, null)) {
                if (!((mask & BG_CLR) != 0)) {
                  // The first keyword can only be 'center', 'left', or 'right'
                  return false;
                }

                xValue = BoxPositionMaskToCSSValue(mask, true);
                return true;
              }
            }
              }

              // Check for bad input. Bad input consists of no matching keywords,
              // or pairs of x keywords or pairs of y keywords.
              if ((mask == 0) || (mask == (BG_TOP | BG_BOTTOM)) ||
              (mask == (BG_LEFT | BG_RIGHT)) ||
              (!aAllowExplicitCenter && ((mask & BG_CENTER) != 0))) {
            return false;
              }

              // Create style values
              xValue = BoxPositionMaskToCSSValue(mask, true);
              yValue = BoxPositionMaskToCSSValue(mask, false);
              return true;
        }
예제 #2
0
        bool ParseTransformOrigin(bool aPerspective)
        {
            var position = new nsCSSValuePair();
              if (!ParseBoxPositionValues(ref position, true))
            return false;

              nsCSSProperty prop = nsCSSProperty.TransformOrigin;
              if (aPerspective) {
            if (!ExpectEndProperty()) {
              return false;
            }
            prop = nsCSSProperty.PerspectiveOrigin;
              }

              // Unlike many other uses of pairs, this position should always be stored
              // as a pair, even if the values are the same, so it always serializes as
              // a pair, and to keep the computation code simple.
              if (position.mXValue.GetUnit() == nsCSSUnit.Inherit ||
              position.mXValue.GetUnit() == nsCSSUnit.Initial) {
            Debug.Assert(position.mXValue == position.mYValue,
                              "inherit/initial only half?");
            AppendValue(prop, position.mXValue);
              } else {
            var value = new nsCSSValue();
            if (aPerspective) {
              value.SetPairValue(position.mXValue, position.mYValue);
            } else {
              var depth = new nsCSSValue();
              if (!nsLayoutUtils.Are3DTransformsEnabled() ||
                  // only try parsing if 3-D transforms are enabled
                  !ParseVariant(ref depth, VARIANT_LENGTH | VARIANT_CALC, null)) {
                depth.SetFloatValue(0.0f, nsCSSUnit.Pixel);
              }
              value.SetTripletValue(position.mXValue, position.mYValue, depth);
            }

            AppendValue(prop, value);
              }
              return true;
        }
예제 #3
0
        internal void SetBorderImageInitialValues()
        {
            // border-image-source: none
              var source = new nsCSSValue();
              source.SetNoneValue();
              AppendValue(nsCSSProperty.BorderImageSource, source);

              // border-image-slice: 100%
              var sliceBoxValue = new nsCSSValue();
              nsCSSRect sliceBox = sliceBoxValue.SetRectValue();
              sliceBox.SetAllSidesTo(new nsCSSValue(1.0f, nsCSSUnit.Percent));
              var slice = new nsCSSValue();
              nsCSSValueList sliceList = slice.SetListValue();
              sliceList.mValue = sliceBoxValue;
              AppendValue(nsCSSProperty.BorderImageSlice, slice);

              // border-image-width: 1
              var width = new nsCSSValue();
              nsCSSRect widthBox = width.SetRectValue();
              widthBox.SetAllSidesTo(new nsCSSValue(1.0f, nsCSSUnit.Number));
              AppendValue(nsCSSProperty.BorderImageWidth, width);

              // border-image-outset: 0
              var outset = new nsCSSValue();
              nsCSSRect outsetBox = outset.SetRectValue();
              outsetBox.SetAllSidesTo(new nsCSSValue(0.0f, nsCSSUnit.Number));
              AppendValue(nsCSSProperty.BorderImageOutset, outset);

              // border-image-repeat: repeat
              var repeat = new nsCSSValue();
              var repeatPair = new nsCSSValuePair();
              repeatPair.SetBothValuesTo(new nsCSSValue(nsStyle.BORDER_IMAGE_REPEAT_STRETCH,
                                                nsCSSUnit.Enumerated));
              repeat.SetPairValue(repeatPair);
              AppendValue(nsCSSProperty.BorderImageRepeat, repeat);
        }
예제 #4
0
        /**
         * Parses two values that correspond to lengths for the background-size
         * property.  These can be one or two lengths (or the 'auto' keyword) or
         * percentages corresponding to the element's dimensions or the single keywords
         * 'contain' or 'cover'.  'initial' and 'inherit' must be handled by the caller
         * if desired.
         *
         * @param aOut The nsCSSValuePair in which to place the result.
         * @return Whether or not the operation succeeded.
         */
        bool ParseBackgroundSizeValues(ref nsCSSValuePair aOut)
        {
            // First try a percentage or a length value
              nsCSSValue xValue = aOut.mXValue,
                     yValue = aOut.mYValue;
              if (ParseNonNegativeVariant(ref xValue, BG_SIZE_VARIANT, null)) {
            // We have one percentage/length/calc/auto. Get the optional second
            // percentage/length/calc/keyword.
            if (ParseNonNegativeVariant(ref yValue, BG_SIZE_VARIANT, null)) {
              // We have a second percentage/length/calc/auto.
              return true;
            }

            // If only one percentage or length value is given, it sets the
            // horizontal size only, and the vertical size will be as if by 'auto'.
            yValue.SetAutoValue();
            return true;
              }

              // Now address 'contain' and 'cover'.
              if (!ParseEnum(ref xValue, nsCSSProps.kBackgroundSizeKTable))
            return false;
              yValue.Reset();
              return true;
        }
예제 #5
0
        internal bool ParseBorderImageRepeat(bool aAcceptsInherit)
        {
            var value = new nsCSSValue();
              if (aAcceptsInherit && ParseVariant(ref value, VARIANT_INHERIT, null)) {
            // Keyword "inherit" can not be mixed, so we are done.
            AppendValue(nsCSSProperty.BorderImageRepeat, value);
            return true;
              }

              var result = new nsCSSValuePair();
              if (!ParseEnum(ref result.mXValue, nsCSSProps.kBorderImageRepeatKTable)) {
            return false;
              }

              // optional second keyword, defaults to first
              if (!ParseEnum(ref result.mYValue, nsCSSProps.kBorderImageRepeatKTable)) {
            result.mYValue = result.mXValue;
              }

              value.SetPairValue(result);
              AppendValue(nsCSSProperty.BorderImageRepeat, value);
              return true;
        }
예제 #6
0
 // This function is very similar to ParseBackgroundList and
 // ParseBackgroundPosition.
 internal bool ParseBackgroundSize()
 {
     var value = new nsCSSValue();
       if (ParseVariant(ref value, VARIANT_INHERIT, null)) {
     // 'initial' and 'inherit' stand alone, no list permitted.
     if (!ExpectEndProperty()) {
       return false;
     }
       } else {
     var valuePair = new nsCSSValuePair();
     if (!ParseBackgroundSizeValues(ref valuePair)) {
       return false;
     }
     nsCSSValuePairList item = value.SetPairListValue();
     for (;;) {
       item.mXValue = valuePair.mXValue;
       item.mYValue = valuePair.mYValue;
       if (CheckEndProperty()) {
         break;
       }
       if (!ExpectSymbol(',', true)) {
         return false;
       }
       if (!ParseBackgroundSizeValues(ref valuePair)) {
         return false;
       }
       item.mNext = new nsCSSValuePairList();
       item = item.mNext;
     }
       }
       AppendValue(nsCSSProperty.BackgroundSize, value);
       return true;
 }
예제 #7
0
        internal bool ParseBackgroundRepeatValues(ref nsCSSValuePair aValue)
        {
            nsCSSValue xValue = aValue.mXValue;
              nsCSSValue yValue = aValue.mYValue;

              if (ParseEnum(ref xValue, nsCSSProps.kBackgroundRepeatKTable)) {
            int32_t value = xValue.GetIntValue();
            // For single values set yValue as nsCSSUnit.Null.
            if (value == nsStyle.BG_REPEAT_REPEAT_X ||
                value == nsStyle.BG_REPEAT_REPEAT_Y ||
                !ParseEnum(ref yValue, nsCSSProps.kBackgroundRepeatPartKTable)) {
              // the caller will fail cases like "repeat-x no-repeat"
              // by expecting a list separator or an end property.
              yValue.Reset();
            }
            return true;
              }

              return false;
        }
예제 #8
0
        // Parse one item of the background shorthand property.
        internal bool ParseBackgroundItem(BackgroundParseState aState)
        {
            // Fill in the values that the shorthand will set if we don't find
              // other values.
              aState.mImage.mValue.SetNoneValue();
              aState.mRepeat.mXValue.SetIntValue(nsStyle.BG_REPEAT_REPEAT,
                                              nsCSSUnit.Enumerated);
              aState.mRepeat.mYValue.Reset();
              aState.mAttachment.mValue.SetIntValue(nsStyle.BG_ATTACHMENT_SCROLL,
                                                 nsCSSUnit.Enumerated);
              aState.mClip.mValue.SetIntValue(nsStyle.BG_CLIP_BORDER,
                                           nsCSSUnit.Enumerated);
              aState.mOrigin.mValue.SetIntValue(nsStyle.BG_ORIGIN_PADDING,
                                             nsCSSUnit.Enumerated);
              nsCSSValue[] positionArr = new nsCSSValue[4];
              aState.mPosition.mValue.SetArrayValue(positionArr, nsCSSUnit.Array);
              positionArr[1].SetPercentValue(0.0f);
              positionArr[3].SetPercentValue(0.0f);
              aState.mSize.mXValue.SetAutoValue();
              aState.mSize.mYValue.SetAutoValue();

              bool haveColor = false,
               haveImage = false,
               haveRepeat = false,
               haveAttach = false,
               havePositionAndSize = false,
               haveOrigin = false,
               haveSomething = false;

              while (GetToken(true)) {
            nsCSSTokenType tt = mToken.mType;
            UngetToken(); // ...but we'll still cheat and use mToken
            if (tt == nsCSSTokenType.Symbol) {
              // ExpectEndProperty only looks for symbols, and nothing else will
              // show up as one.
              break;
            }

            if (tt == nsCSSTokenType.Ident) {
              nsCSSKeyword keyword = nsCSSKeywords.LookupKeyword(mToken.mIdentStr);
              int32_t dummy = 0;
              if (keyword == nsCSSKeyword.inherit ||
                  keyword == nsCSSKeyword._moz_initial ||
                  keyword == nsCSSKeyword.initial) {
                return false;
              } else if (keyword == nsCSSKeyword.none) {
                if (haveImage)
                  return false;
                haveImage = true;
                if (!ParseSingleValueProperty(ref aState.mImage.mValue,
                                              nsCSSProperty.BackgroundImage)) {
                  Debug.Fail("should be able to parse");
                  return false;
                }
              } else if (nsCSSProps.FindKeyword(keyword,
                           nsCSSProps.kBackgroundAttachmentKTable, ref dummy)) {
                if (haveAttach)
                  return false;
                haveAttach = true;
                if (!ParseSingleValueProperty(ref aState.mAttachment.mValue,
                                              nsCSSProperty.BackgroundAttachment)) {
                  Debug.Fail("should be able to parse");
                  return false;
                }
              } else if (nsCSSProps.FindKeyword(keyword,
                           nsCSSProps.kBackgroundRepeatKTable, ref dummy)) {
                if (haveRepeat)
                  return false;
                haveRepeat = true;
                var scratch = new nsCSSValuePair();
                if (!ParseBackgroundRepeatValues(ref scratch)) {
                  Debug.Fail("should be able to parse");
                  return false;
                }
                aState.mRepeat.mXValue = scratch.mXValue;
                aState.mRepeat.mYValue = scratch.mYValue;
              } else if (nsCSSProps.FindKeyword(keyword,
                           nsCSSProps.kBackgroundPositionKTable, ref dummy)) {
                if (havePositionAndSize)
                  return false;
                havePositionAndSize = true;
                if (!ParseBackgroundPositionValues(ref aState.mPosition.mValue, false)) {
                  return false;
                }
                if (ExpectSymbol('/', true)) {
                  var scratch = new nsCSSValuePair();
                  if (!ParseBackgroundSizeValues(ref scratch)) {
                    return false;
                  }
                  aState.mSize.mXValue = scratch.mXValue;
                  aState.mSize.mYValue = scratch.mYValue;
                }
              } else if (nsCSSProps.FindKeyword(keyword,
                           nsCSSProps.kBackgroundOriginKTable, ref dummy)) {
                if (haveOrigin)
                  return false;
                haveOrigin = true;
                if (!ParseSingleValueProperty(ref aState.mOrigin.mValue,
                                              nsCSSProperty.BackgroundOrigin)) {
                  Debug.Fail("should be able to parse");
                  return false;
                }

                // The spec allows a second box value (for background-clip),
                // immediately following the first one (for background-origin).

                // 'background-clip' and 'background-origin' use the same keyword table
                Debug.Assert(nsCSSProps.kKeywordTableTable[
                             (int)nsCSSProperty.BackgroundOrigin] ==
                           nsCSSProps.kBackgroundOriginKTable);
                Debug.Assert(nsCSSProps.kKeywordTableTable[
                             (int)nsCSSProperty.BackgroundClip] ==
                           nsCSSProps.kBackgroundOriginKTable);

                if (!ParseSingleValueProperty(ref aState.mClip.mValue,
                                              nsCSSProperty.BackgroundClip)) {
                  // When exactly one <box> value is set, it is used for both
                  // 'background-origin' and 'background-clip'.
                  // See assertions above showing these values are compatible.
                  aState.mClip.mValue = aState.mOrigin.mValue;
                }
              } else {
                if (haveColor)
                  return false;
                haveColor = true;
                if (!ParseSingleValueProperty(ref aState.mColor,
                                              nsCSSProperty.BackgroundColor)) {
                  return false;
                }
              }
            } else if (tt == nsCSSTokenType.URL ||
                       (tt == nsCSSTokenType.Function &&
                        (mToken.mIdentStr.LowerCaseEqualsLiteral("linear-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("radial-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("repeating-linear-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("repeating-radial-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-linear-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-radial-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-image-rect") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-element")))) {
              if (haveImage)
                return false;
              haveImage = true;
              if (!ParseSingleValueProperty(ref aState.mImage.mValue,
                                            nsCSSProperty.BackgroundImage)) {
                return false;
              }
            } else if (tt == nsCSSTokenType.Dimension ||
                       tt == nsCSSTokenType.Number ||
                       tt == nsCSSTokenType.Percentage ||
                       (tt == nsCSSTokenType.Function &&
                        (mToken.mIdentStr.LowerCaseEqualsLiteral("calc") ||
                         mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-calc")))) {
              if (havePositionAndSize)
                return false;
              havePositionAndSize = true;
              if (!ParseBackgroundPositionValues(ref aState.mPosition.mValue, false)) {
                return false;
              }
              if (ExpectSymbol('/', true)) {
                var scratch = new nsCSSValuePair();
                if (!ParseBackgroundSizeValues(ref scratch)) {
                  return false;
                }
                aState.mSize.mXValue = scratch.mXValue;
                aState.mSize.mYValue = scratch.mYValue;
              }
            } else {
              if (haveColor)
                return false;
              haveColor = true;
              // Note: This parses 'inherit' and 'initial', but
              // we've already checked for them, so it's ok.
              if (!ParseSingleValueProperty(ref aState.mColor,
                                            nsCSSProperty.BackgroundColor)) {
                return false;
              }
            }
            haveSomething = true;
              }

              return haveSomething;
        }
예제 #9
0
 internal void SetPairValue(CssValuePair aValue)
 {
     mUnit  = CssUnit.Pair;
     mValue = aValue;
 }