Bug 686281 - Integrate nsStyleImageLayers with nsStyleBackground; r?:dbaron draft
authorCJKu <cku@mozilla.com>
Thu, 12 Nov 2015 17:04:49 +0800
changeset 308384 a329a6fea0d2ea235eaf51c25ca644fa2732163f
parent 308383 087a535782746f9734dd68001c613031accc59b8
child 308385 ef7476050a22f8ccb57212b0f830a1109604327b
push id7465
push usercku@mozilla.com
push dateThu, 12 Nov 2015 09:05:57 +0000
bugs686281
milestone45.0a1
Bug 686281 - Integrate nsStyleImageLayers with nsStyleBackground; r?:dbaron
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/style/StyleAnimationValue.cpp
layout/style/nsCSSParser.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/nsStyleUtil.cpp
layout/tables/nsTablePainter.cpp
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1000,17 +1000,17 @@ nsCSSRendering::PaintFocus(nsPresContext
 
 //----------------------------------------------------------------------
 
 /**
  * Helper for ComputeObjectAnchorPoint; parameters are the same as for
  * that function, except they're for a single coordinate / a single size
  * dimension. (so, x/width vs. y/height)
  */
-typedef nsStyleBackground::Position::PositionCoord PositionCoord;
+typedef nsStyleImageLayers::Position::PositionCoord PositionCoord;
 static void
 ComputeObjectAnchorCoord(const PositionCoord& aCoord,
                          const nscoord aOriginBounds,
                          const nscoord aImageSize,
                          nscoord* aTopLeftCoord,
                          nscoord* aAnchorPointCoord)
 {
   *aAnchorPointCoord = aCoord.mLength;
@@ -1024,17 +1024,17 @@ ComputeObjectAnchorCoord(const PositionC
     // The anchor-point doesn't care about our image's size; just the size
     // of the region we're rendering into.
     *aAnchorPointCoord += NSToCoordRound(aCoord.mPercent * aOriginBounds);
   }
 }
 
 void
 nsImageRenderer::ComputeObjectAnchorPoint(
-  const nsStyleBackground::Position& aPos,
+  const nsStyleImageLayers::Position& aPos,
   const nsSize& aOriginBounds,
   const nsSize& aImageSize,
   nsPoint* aTopLeft,
   nsPoint* aAnchorPoint)
 {
   ComputeObjectAnchorCoord(aPos.mXPosition,
                            aOriginBounds.width, aImageSize.width,
                            &aTopLeft->x, &aAnchorPoint->x);
@@ -1741,20 +1741,23 @@ SetupDirtyRects(const nsRect& aBGClipAre
   *aDirtyRectGfx = nsLayoutUtils::RectToGfxRect(*aDirtyRect, aAppUnitsPerPixel);
   NS_WARN_IF_FALSE(aDirtyRect->IsEmpty() || !aDirtyRectGfx->IsEmpty(),
                    "converted dirty rect should not be empty");
   MOZ_ASSERT(!aDirtyRect->IsEmpty() || aDirtyRectGfx->IsEmpty(),
              "second should be empty if first is");
 }
 
 /* static */ void
-nsCSSRendering::GetBackgroundClip(const nsStyleBackground::Layer& aLayer,
-                                  nsIFrame* aForFrame, const nsStyleBorder& aBorder,
-                                  const nsRect& aBorderArea, const nsRect& aCallerDirtyRect,
-                                  bool aWillPaintBorder, nscoord aAppUnitsPerPixel,
+nsCSSRendering::GetBackgroundClip(const nsStyleImageLayers::Layer& aLayer,
+                                  nsIFrame* aForFrame,
+                                  const nsStyleBorder& aBorder,
+                                  const nsRect& aBorderArea,
+                                  const nsRect& aCallerDirtyRect,
+                                  bool aWillPaintBorder,
+                                  nscoord aAppUnitsPerPixel,
                                   /* out */ BackgroundClipState* aClipState)
 {
   // Compute the outermost boundary of the area that might be painted.
   // Same coordinate space as aBorderArea.
   Sides skipSides = aForFrame->GetSkipSides();
   nsRect clipBorderArea =
     ::BoxDecorationRectForBorder(aForFrame, aBorderArea, skipSides, &aBorder);
 
@@ -2892,19 +2895,19 @@ nsCSSRendering::PaintBackgroundWithSC(ns
   bool drawBackgroundColor;
 
   nscolor bgColor = DetermineBackgroundColor(aPresContext,
                                              aBackgroundSC,
                                              aForFrame,
                                              drawBackgroundImage,
                                              drawBackgroundColor);
 
+  const nsStyleImageLayers& layers = aBackgroundSC->StyleBackground()->mLayers;
   // If we're drawing a specific layer, we don't want to draw the
   // background color.
-  const nsStyleBackground *bg = aBackgroundSC->StyleBackground();
   if (drawBackgroundColor && aLayer >= 0) {
     drawBackgroundColor = false;
   }
 
   // At this point, drawBackgroundImage and drawBackgroundColor are
   // true if and only if we are actually supposed to paint an image or
   // color into aDirtyRect, respectively.
   if (!drawBackgroundImage && !drawBackgroundColor)
@@ -2929,17 +2932,17 @@ nsCSSRendering::PaintBackgroundWithSC(ns
   BackgroundClipState clipState;
   if (aBGClipRect) {
     clipState.mBGClipArea = *aBGClipRect;
     clipState.mCustomClip = true;
     clipState.mHasRoundedCorners = false;
     SetupDirtyRects(clipState.mBGClipArea, aDirtyRect, appUnitsPerPixel,
                     &clipState.mDirtyRect, &clipState.mDirtyRectGfx);
   } else {
-    GetBackgroundClip(bg->BottomLayer(),
+    GetBackgroundClip(layers.BottomLayer(),
                       aForFrame, aBorder, aBorderArea,
                       aDirtyRect, (aFlags & PAINTBG_WILL_PAINT_BORDER), appUnitsPerPixel,
                       &clipState);
   }
 
   // If we might be using a background color, go ahead and set it now.
   if (drawBackgroundColor && !isCanvasFrame)
     ctx->SetColor(Color::FromABGR(bgColor));
@@ -2953,52 +2956,52 @@ nsCSSRendering::PaintBackgroundWithSC(ns
   // this far.)
   if (!drawBackgroundImage) {
     if (!isCanvasFrame) {
       DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
     }
     return DrawResult::SUCCESS;
   }
 
-  if (bg->mImageCount < 1) {
+  if (layers.mImageCount < 1) {
     // Return if there are no background layers, all work from this point
     // onwards happens iteratively on these.
     return DrawResult::SUCCESS;
   }
 
   // Validate the layer range before we start iterating.
   int32_t startLayer = aLayer;
   int32_t nLayers = 1;
   if (startLayer < 0) {
-    startLayer = (int32_t)bg->mImageCount - 1;
-    nLayers = bg->mImageCount;
+    startLayer = (int32_t)layers.mImageCount - 1;
+    nLayers = layers.mImageCount;
   }
 
   // Ensure we get invalidated for loads of the image.  We need to do
   // this here because this might be the only code that knows about the
   // association of the style data with the frame.
   if (aBackgroundSC != aForFrame->StyleContext()) {
-    NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, bg, startLayer, nLayers) {
-      aForFrame->AssociateImage(bg->mLayers[i].mImage, aPresContext);
+    NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT_WITH_RANGE(i, layers, startLayer, nLayers) {
+      aForFrame->AssociateImage(layers.mLayers[i].mImage, aPresContext);
     }
   }
 
   // The background color is rendered over the entire dirty area,
   // even if the image isn't.
   if (drawBackgroundColor && !isCanvasFrame) {
     DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
   }
 
   if (drawBackgroundImage) {
     bool clipSet = false;
     uint8_t currentBackgroundClip = NS_STYLE_BG_CLIP_BORDER;
-    NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, bg, bg->mImageCount - 1,
-                                                              nLayers + (bg->mImageCount -
-                                                                         startLayer - 1)) {
-      const nsStyleBackground::Layer &layer = bg->mLayers[i];
+    NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT_WITH_RANGE(i, layers, layers.mImageCount - 1,
+                                                       nLayers + (layers.mImageCount -
+                                                       startLayer - 1)) {
+      const nsStyleImageLayers::Layer& layer = layers.mLayers[i];
       if (!aBGClipRect) {
         if (currentBackgroundClip != layer.mClip || !clipSet) {
           currentBackgroundClip = layer.mClip;
           // If clipSet is false that means this is the bottom layer and we
           // already called GetBackgroundClip above and it stored its results
           // in clipState.
           if (clipSet) {
             autoSR.Restore(); // reset the previous one
@@ -3060,17 +3063,17 @@ IsTransformed(nsIFrame* aForFrame, nsIFr
   }
   return false;
 }
 
 nsRect
 nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
                                                  nsIFrame* aForFrame,
                                                  const nsRect& aBorderArea,
-                                                 const nsStyleBackground::Layer& aLayer,
+                                                 const nsStyleImageLayers::Layer& aLayer,
                                                  nsIFrame** aAttachedToFrame)
 {
   // Compute background origin area relative to aBorderArea now as we may need
   // it to compute the effective image size for a CSS gradient.
   nsRect bgPositioningArea;
 
   nsIAtom* frameType = aForFrame->GetType();
   nsIFrame* geometryFrame = aForFrame;
@@ -3165,53 +3168,53 @@ nsCSSRendering::ComputeBackgroundPositio
 
 // Apply the CSS image sizing algorithm as it applies to background images.
 // See http://www.w3.org/TR/css3-background/#the-background-size .
 // aIntrinsicSize is the size that the background image 'would like to be'.
 // It can be found by calling nsImageRenderer::ComputeIntrinsicSize.
 static nsSize
 ComputeDrawnSizeForBackground(const CSSSizeOrRatio& aIntrinsicSize,
                               const nsSize& aBgPositioningArea,
-                              const nsStyleBackground::Size& aLayerSize)
+                              const nsStyleImageLayers::Size& aLayerSize)
 {
   // Size is dictated by cover or contain rules.
-  if (aLayerSize.mWidthType == nsStyleBackground::Size::eContain ||
-      aLayerSize.mWidthType == nsStyleBackground::Size::eCover) {
+  if (aLayerSize.mWidthType == nsStyleImageLayers::Size::eContain ||
+      aLayerSize.mWidthType == nsStyleImageLayers::Size::eCover) {
     nsImageRenderer::FitType fitType =
-      aLayerSize.mWidthType == nsStyleBackground::Size::eCover
+      aLayerSize.mWidthType == nsStyleImageLayers::Size::eCover
         ? nsImageRenderer::COVER
         : nsImageRenderer::CONTAIN;
     return nsImageRenderer::ComputeConstrainedSize(aBgPositioningArea,
                                                    aIntrinsicSize.mRatio,
                                                    fitType);
   }
 
   // No cover/contain constraint, use default algorithm.
   CSSSizeOrRatio specifiedSize;
-  if (aLayerSize.mWidthType == nsStyleBackground::Size::eLengthPercentage) {
+  if (aLayerSize.mWidthType == nsStyleImageLayers::Size::eLengthPercentage) {
     specifiedSize.SetWidth(
       aLayerSize.ResolveWidthLengthPercentage(aBgPositioningArea));
   }
-  if (aLayerSize.mHeightType == nsStyleBackground::Size::eLengthPercentage) {
+  if (aLayerSize.mHeightType == nsStyleImageLayers::Size::eLengthPercentage) {
     specifiedSize.SetHeight(
       aLayerSize.ResolveHeightLengthPercentage(aBgPositioningArea));
   }
 
   return nsImageRenderer::ComputeConcreteSize(specifiedSize,
                                               aIntrinsicSize,
                                               aBgPositioningArea);
 }
 
 nsBackgroundLayerState
 nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
                                        nsIFrame* aForFrame,
                                        uint32_t aFlags,
                                        const nsRect& aBorderArea,
                                        const nsRect& aBGClipRect,
-                                       const nsStyleBackground::Layer& aLayer)
+                                       const nsStyleImageLayers::Layer& aLayer)
 {
   /*
    * The properties we need to keep in mind when drawing background
    * layers are:
    *
    *   background-image
    *   background-repeat
    *   background-attachment
@@ -3349,17 +3352,17 @@ nsCSSRendering::PrepareBackgroundLayer(n
   return state;
 }
 
 nsRect
 nsCSSRendering::GetBackgroundLayerRect(nsPresContext* aPresContext,
                                        nsIFrame* aForFrame,
                                        const nsRect& aBorderArea,
                                        const nsRect& aClipRect,
-                                       const nsStyleBackground::Layer& aLayer,
+                                       const nsStyleImageLayers::Layer& aLayer,
                                        uint32_t aFlags)
 {
   Sides skipSides = aForFrame->GetSkipSides();
   nsRect borderArea =
     ::BoxDecorationRectForBackground(aForFrame, aBorderArea, skipSides);
   nsBackgroundLayerState state =
       PrepareBackgroundLayer(aPresContext, aForFrame, aFlags, borderArea,
                              aClipRect, aLayer);
@@ -4832,17 +4835,17 @@ nsImageRenderer::ComputeIntrinsicSize()
       break;
     }
     case eStyleImageType_Element:
     {
       // XXX element() should have the width/height of the referenced element,
       //     and that element's ratio, if it matches.  If it doesn't match, it
       //     should have no width/height or ratio.  See element() in CSS images:
       //     <http://dev.w3.org/csswg/css-images-4/#element-notation>.
-      //     Make sure to change nsStyleBackground::Size::DependsOnFrameSize
+      //     Make sure to change nsStyleImageLayers::Size::DependsOnFrameSize
       //     when fixing this!
       if (mPaintServerFrame) {
         // SVG images have no intrinsic size
         if (!mPaintServerFrame->IsFrameOfType(nsIFrame::eSVG)) {
           // The intrinsic image size for a generic nsIFrame paint server is
           // the union of the border-box rects of all of its continuations,
           // rounded to device pixels.
           int32_t appUnitsPerDevPixel =
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -170,17 +170,17 @@ public:
    * @param aAnchorPoint [out] A point which should be pixel-aligned by
    *          nsLayoutUtils::DrawImage. This is the same as aTopLeft, unless
    *          CSS specifies a percentage (including 'right' or 'bottom'), in
    *          which case it's that percentage within of aOriginBounds. So
    *          'right' would set aAnchorPoint.x to aOriginBounds.XMost().
    *
    * Points are returned relative to aOriginBounds.
    */
-  static void ComputeObjectAnchorPoint(const nsStyleBackground::Position& aPos,
+  static void ComputeObjectAnchorPoint(const nsStyleImageLayers::Position& aPos,
                                        const nsSize& aOriginBounds,
                                        const nsSize& aImageSize,
                                        nsPoint* aTopLeft,
                                        nsPoint* aAnchorPoint);
 
   /**
    * Compute the size of the rendered image using either the 'cover' or
    * 'contain' constraints (aFitType).
@@ -529,26 +529,26 @@ struct nsCSSRendering {
                            nsIFrame* aFrame,
                            bool& aDrawBackgroundImage,
                            bool& aDrawBackgroundColor);
 
   static nsRect
   ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
                                    nsIFrame* aForFrame,
                                    const nsRect& aBorderArea,
-                                   const nsStyleBackground::Layer& aLayer,
+                                   const nsStyleImageLayers::Layer& aLayer,
                                    nsIFrame** aAttachedToFrame);
 
   static nsBackgroundLayerState
   PrepareBackgroundLayer(nsPresContext* aPresContext,
                          nsIFrame* aForFrame,
                          uint32_t aFlags,
                          const nsRect& aBorderArea,
                          const nsRect& aBGClipRect,
-                         const nsStyleBackground::Layer& aLayer);
+                         const nsStyleImageLayers::Layer& aLayer);
 
   struct BackgroundClipState {
     nsRect mBGClipArea;  // Affected by mClippedRadii
     nsRect mAdditionalBGClipArea;  // Not affected by mClippedRadii
     nsRect mDirtyRect;
     gfxRect mDirtyRectGfx;
 
     nscoord mRadii[8];
@@ -557,17 +557,17 @@ struct nsCSSRendering {
     bool mHasAdditionalBGClipArea;
 
     // Whether we are being asked to draw with a caller provided background
     // clipping area. If this is true we also disable rounded corners.
     bool mCustomClip;
   };
 
   static void
-  GetBackgroundClip(const nsStyleBackground::Layer& aLayer,
+  GetBackgroundClip(const nsStyleImageLayers::Layer& aLayer,
                     nsIFrame* aForFrame, const nsStyleBorder& aBorder, const nsRect& aBorderArea,
                     const nsRect& aCallerDirtyRect, bool aWillPaintBorder,
                     nscoord aAppUnitsPerPixel,
                     /* out */ BackgroundClipState* aClipState);
 
   /**
    * Render the background for an element using css rendering rules
    * for backgrounds.
@@ -621,17 +621,17 @@ struct nsCSSRendering {
    * Returns the rectangle covered by the given background layer image, taking
    * into account background positioning, sizing, and repetition, but not
    * clipping.
    */
   static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext,
                                        nsIFrame* aForFrame,
                                        const nsRect& aBorderArea,
                                        const nsRect& aClipRect,
-                                       const nsStyleBackground::Layer& aLayer,
+                                       const nsStyleImageLayers::Layer& aLayer,
                                        uint32_t aFlags);
 
   /**
    * Called when we start creating a display list. The frame tree will not
    * change until a matching EndFrameTreeLocked is called.
    */
   static void BeginFrameTreesLocked();
   /**
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2157,17 +2157,17 @@ nsDisplayBackgroundImage::GetDestAreaInt
 {
   if (!mBackgroundStyle) {
     return nsRect();
   }
 
   nsPresContext* presContext = mFrame->PresContext();
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
-  const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
+  const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mLayers.mLayers[mLayer];
 
   nsBackgroundLayerState state =
     nsCSSRendering::PrepareBackgroundLayer(presContext, mFrame, flags,
                                            borderArea, borderArea, layer);
   return state.mDestArea;
 }
 
 nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
@@ -2198,17 +2198,17 @@ static nsStyleContext* GetBackgroundStyl
     sc = aFrame->StyleContext();
   }
   return sc;
 }
 
 /* static */ void
 SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
                         nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
-                        const nsStyleBackground::Layer& aLayer,
+                        const nsStyleImageLayers::Layer& aLayer,
                         bool aWillPaintBorder)
 {
   nsRect borderBox = nsRect(aToReferenceFrame, aFrame->GetSize());
 
   nsCSSRendering::BackgroundClipState clip;
   nsCSSRendering::GetBackgroundClip(aLayer, aFrame, *aFrame->StyleBorder(),
                                     borderBox, borderBox, aWillPaintBorder,
                                     aFrame->PresContext()->AppUnitsPerDevPixel(),
@@ -2304,28 +2304,28 @@ nsDisplayBackgroundImage::AppendBackgrou
     aList->AppendToTop(&bgItemList);
     return false;
   }
  
   bool needBlendContainer = false;
 
   // Passing bg == nullptr in this macro will result in one iteration with
   // i = 0.
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
-    if (bg->mLayers[i].mImage.IsEmpty()) {
+  NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, bg->mLayers) {
+    if (bg->mLayers.mLayers[i].mImage.IsEmpty()) {
       continue;
     }
 
-    if (bg->mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
+    if (bg->mLayers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
       needBlendContainer = true;
     }
 
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     if (!aBuilder->IsForEventDelivery()) {
-      const nsStyleBackground::Layer& layer = bg->mLayers[i];
+      const nsStyleImageLayers::Layer& layer = bg->mLayers.mLayers[i];
       SetBackgroundClipRegion(clipState, aFrame, toRef,
                               layer, willPaintBorder);
     }
 
     nsDisplayBackgroundImage* bgItem =
       new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bg);
     bgItemList.AppendNewToTop(bgItem);
   }
@@ -2373,23 +2373,23 @@ static bool RoundedRectContainsRect(cons
 bool
 nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
                                                      const nsRect& aClipRect,
                                                      gfxRect* aDestRect)
 {
   if (!mBackgroundStyle)
     return false;
 
-  if (mBackgroundStyle->mLayers.Length() != 1)
+  if (mBackgroundStyle->mLayers.mLayers.Length() != 1)
     return false;
 
   nsPresContext* presContext = mFrame->PresContext();
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
-  const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
+  const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mLayers.mLayers[mLayer];
 
   if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED)
     return false;
 
   nsBackgroundLayerState state =
     nsCSSRendering::PrepareBackgroundLayer(presContext, mFrame, flags,
                                            borderArea, aClipRect, layer);
   nsImageRenderer* imageRenderer = &state.mImageRenderer;
@@ -2401,18 +2401,18 @@ nsDisplayBackgroundImage::IsSingleFixedP
   *aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
 
   return true;
 }
 
 bool
 nsDisplayBackgroundImage::IsNonEmptyFixedImage() const
 {
-  return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
-         !mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
+  return mBackgroundStyle->mLayers.mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
+         !mBackgroundStyle->mLayers.mLayers[mLayer].mImage.IsEmpty();
 }
 
 bool
 nsDisplayBackgroundImage::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
 {
   // APZ needs background-attachment:fixed images layerized for correctness.
   RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager();
   if (!nsLayoutUtils::UsesAsyncScrolling(mFrame) &&
@@ -2431,17 +2431,17 @@ nsDisplayBackgroundImage::CanOptimizeToI
 {
   if (!mBackgroundStyle) {
     return false;
   }
 
   nsPresContext* presContext = mFrame->PresContext();
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
-  const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
+  const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mLayers.mLayers[mLayer];
 
   nsBackgroundLayerState state =
     nsCSSRendering::PrepareBackgroundLayer(presContext, mFrame, flags,
                                            borderArea, borderArea, layer);
   nsImageRenderer* imageRenderer = &state.mImageRenderer;
   // We only care about images here, not gradients.
   if (!imageRenderer->IsRasterImage()) {
     return false;
@@ -2501,17 +2501,17 @@ nsDisplayBackgroundImage::ShouldCreateOw
 {
   nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame);
   if (ActiveLayerTracker::IsStyleAnimated(aBuilder, backgroundStyleFrame,
                                           eCSSProperty_background_position)) {
     return WHENEVER_POSSIBLE;
   }
 
   if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
-    const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
+    const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mLayers.mLayers[mLayer];
     const nsStyleImage* image = &layer.mImage;
     if (image->GetType() == eStyleImageType_Image) {
       imgIRequest* imgreq = image->GetImageData();
       nsCOMPtr<imgIContainer> image;
       if (NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) && image) {
         bool animated = false;
         if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
           return WHENEVER_POSSIBLE;
@@ -2699,17 +2699,17 @@ nsDisplayBackgroundImage::GetOpaqueRegio
   // For NS_STYLE_BOX_DECORATION_BREAK_SLICE, don't try to optimize here, since
   // this could easily lead to O(N^2) behavior inside InlineBackgroundData,
   // which expects frames to be sent to it in content order, not reverse
   // content order which we'll produce here.
   // Of course, if there's only one frame in the flow, it doesn't matter.
   if (mFrame->StyleBorder()->mBoxDecorationBreak ==
         NS_STYLE_BOX_DECORATION_BREAK_CLONE ||
       (!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
-    const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
+    const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mLayers.mLayers[mLayer];
     if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL) {
       nsPresContext* presContext = mFrame->PresContext();
       result = GetInsideClipRegion(this, presContext, layer.mClip, mBounds, aSnap);
     }
   }
 
   return result;
 }
@@ -2728,34 +2728,34 @@ nsDisplayBackgroundImage::GetPositioning
 {
   if (!mBackgroundStyle) {
     return nsRect();
   }
   nsIFrame* attachedToFrame;
   return nsCSSRendering::ComputeBackgroundPositioningArea(
       mFrame->PresContext(), mFrame,
       nsRect(ToReferenceFrame(), mFrame->GetSize()),
-      mBackgroundStyle->mLayers[mLayer],
+      mBackgroundStyle->mLayers.mLayers[mLayer],
       &attachedToFrame) + ToReferenceFrame();
 }
 
 bool
 nsDisplayBackgroundImage::RenderingMightDependOnPositioningAreaSizeChange()
 {
   if (!mBackgroundStyle)
     return false;
 
   nscoord radii[8];
   if (mFrame->GetBorderRadii(radii)) {
     // A change in the size of the positioning area might change the position
     // of the rounded corners.
     return true;
   }
 
-  const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
+  const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mLayers.mLayers[mLayer];
   if (layer.RenderingMightDependOnPositioningAreaSizeChange()) {
     return true;
   }
   return false;
 }
 
 static void CheckForBorderItem(nsDisplayItem *aItem, uint32_t& aFlags)
 {
@@ -2821,17 +2821,17 @@ void nsDisplayBackgroundImage::ComputeIn
   if (!mDestArea.IsEqualInterior(geometry->mDestArea)) {
     // Dest area changed in a way that could cause everything to change,
     // so invalidate everything (both old and new painting areas).
     aInvalidRegion->Or(bounds, geometry->mBounds);
     NotifyRenderingChanged();
     return;
   }
   if (aBuilder->ShouldSyncDecodeImages()) {
-    const nsStyleImage& image = mBackgroundStyle->mLayers[mLayer].mImage;
+    const nsStyleImage& image = mBackgroundStyle->mLayers.mLayers[mLayer].mImage;
     if (image.GetType() == eStyleImageType_Image &&
         geometry->ShouldInvalidateToSyncDecodeImages()) {
       aInvalidRegion->Or(*aInvalidRegion, bounds);
 
       NotifyRenderingChanged();
     }
   }
   if (!bounds.IsEqualInterior(geometry->mBounds)) {
@@ -2867,17 +2867,17 @@ nsDisplayBackgroundImage::GetBoundsInter
     // async scrolling could reveal additional areas of the image, so don't
     // clip it beyond clipping to the document's viewport.
     nsIFrame* rootFrame = presContext->PresShell()->GetRootFrame();
     nsRect rootRect = rootFrame->GetRectRelativeToSelf();
     if (nsLayoutUtils::TransformRect(rootFrame, mFrame, rootRect) == nsLayoutUtils::TRANSFORM_SUCCEEDED) {
       clipRect = rootRect + aBuilder->ToReferenceFrame(mFrame);
     }
   }
-  const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
+  const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mLayers.mLayers[mLayer];
   return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
                                                 borderBox, clipRect, layer,
                                                 aBuilder->GetBackgroundPaintFlags());
 }
 
 uint32_t
 nsDisplayBackgroundImage::GetPerFrameKey()
 {
@@ -3107,17 +3107,17 @@ nsDisplayBackgroundColor::GetOpaqueRegio
     return nsRegion();
   }
 
   if (!mBackgroundStyle)
     return nsRegion();
 
   *aSnap = true;
 
-  const nsStyleBackground::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
+  const nsStyleImageLayers::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
   nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
   nsPresContext* presContext = mFrame->PresContext();
   return nsDisplayBackgroundImage::GetInsideClipRegion(this, presContext, bottomLayer.mClip, borderBox, aSnap);
 }
 
 bool
 nsDisplayBackgroundColor::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
 {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4018,31 +4018,31 @@ ComputeConcreteObjectSize(const nsSize& 
     default:
       MOZ_ASSERT_UNREACHABLE("Unexpected enum value for 'object-fit'");
       return aConstraintSize; // fall back to (default) 'fill' behavior
   }
 }
 
 // (Helper for HasInitialObjectFitAndPosition, to check
 // each "object-position" coord.)
-typedef nsStyleBackground::Position::PositionCoord PositionCoord;
+typedef nsStyleImageLayers::Position::PositionCoord PositionCoord;
 static bool
 IsCoord50Pct(const PositionCoord& aCoord)
 {
   return (aCoord.mLength == 0 &&
           aCoord.mHasPercent &&
           aCoord.mPercent == 0.5f);
 }
 
 // Indicates whether the given nsStylePosition has the initial values
 // for the "object-fit" and "object-position" properties.
 static bool
 HasInitialObjectFitAndPosition(const nsStylePosition* aStylePos)
 {
-  const nsStyleBackground::Position& objectPos = aStylePos->mObjectPosition;
+  const nsStyleImageLayers::Position& objectPos = aStylePos->mObjectPosition;
 
   return aStylePos->mObjectFit == NS_STYLE_OBJECT_FIT_FILL &&
     IsCoord50Pct(objectPos.mXPosition) &&
     IsCoord50Pct(objectPos.mYPosition);
 }
 
 /* static */ nsRect
 nsLayoutUtils::ComputeObjectDestRect(const nsRect& aConstraintRect,
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -495,21 +495,22 @@ nsCanvasFrame::BuildDisplayList(nsDispla
 
     if (!bg) {
       return;
     }
 
     bool needBlendContainer = false;
 
     // Create separate items for each background layer.
-    NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
-      if (bg->mLayers[i].mImage.IsEmpty()) {
+    const nsStyleImageLayers& layers = bg->mLayers;
+    NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, layers) {
+      if (layers.mLayers[i].mImage.IsEmpty()) {
         continue;
       }
-      if (bg->mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
+      if (layers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
         needBlendContainer = true;
       }
       aLists.BorderBackground()->AppendNewToTop(
         new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, i, bg));
     }
 
     if (needBlendContainer) {
       aLists.BorderBackground()->AppendNewToTop(
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -254,18 +254,18 @@ public:
   }
 
   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override
   {
     // Put background-attachment:fixed canvas background images in their own
     // compositing layer. Since we know their background painting area can't
     // change (unless the viewport size itself changes), async scrolling
     // will work well.
-    return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
-           !mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
+    return mBackgroundStyle->mLayers.mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
+           !mBackgroundStyle->mLayers.mLayers[mLayer].mImage.IsEmpty();
   }
  
   // We still need to paint a background color as well as an image for this item, 
   // so we can't support this yet.
   virtual bool SupportsOptimizingToImage() override { return false; }
   
   
   NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -764,37 +764,39 @@ nsFrame::DidSetStyleContext(nsStyleConte
   // backgrounds from some other frame's style data, and we don't want
   // to clear those notifiers unless we have to.  (They'll be reset
   // when we paint, although we could miss a notification in that
   // interval.)
   const nsStyleBackground *oldBG = aOldStyleContext ?
                                    aOldStyleContext->StyleBackground() :
                                    nullptr;
   const nsStyleBackground *newBG = StyleBackground();
+  const nsStyleImageLayers& oldBGLayers = oldBG->mLayers;
+  const nsStyleImageLayers& newBGLayers = newBG->mLayers;
   if (oldBG) {
-    NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
+    NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, oldBGLayers) {
       // If there is an image in oldBG that's not in newBG, drop it.
-      if (i >= newBG->mImageCount ||
-          !oldBG->mLayers[i].mImage.ImageDataEquals(newBG->mLayers[i].mImage)) {
-        const nsStyleImage& oldImage = oldBG->mLayers[i].mImage;
+      if (i >= newBGLayers.mImageCount ||
+          !oldBGLayers.mLayers[i].mImage.ImageDataEquals(newBGLayers.mLayers[i].mImage)) {
+        const nsStyleImage& oldImage = oldBGLayers.mLayers[i].mImage;
         if (oldImage.GetType() != eStyleImageType_Image) {
           continue;
         }
 
         imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
                                                   this);
       }          
     }
   }
 
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, newBG) {
+  NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, newBGLayers) {
     // If there is an image in newBG that's not in oldBG, add it.
-    if (!oldBG || i >= oldBG->mImageCount ||
-        !newBG->mLayers[i].mImage.ImageDataEquals(oldBG->mLayers[i].mImage)) {
-      const nsStyleImage& newImage = newBG->mLayers[i].mImage;
+    if (!oldBG || i >= oldBGLayers.mImageCount ||
+        !newBGLayers.mLayers[i].mImage.ImageDataEquals(oldBGLayers.mLayers[i].mImage)) {
+      const nsStyleImage& newImage = newBGLayers.mLayers[i].mImage;
       if (newImage.GetType() != eStyleImageType_Image) {
         continue;
       }
 
       imageLoader->AssociateRequestToFrame(newImage.GetImageData(), this);
     }          
   }
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -5712,17 +5712,17 @@ ScrollSnapHelper(SnappingEdgeCallback& a
       const nsStyleDisplay* styleDisplay = f->StyleDisplay();
       size_t coordCount = styleDisplay->mScrollSnapCoordinate.Length();
 
       if (coordCount) {
         nsRect frameRect = f->GetRect();
         nsPoint offset = f->GetOffsetTo(aScrolledFrame);
         nsRect edgesRect = nsRect(offset, frameRect.Size());
         for (size_t coordNum = 0; coordNum < coordCount; coordNum++) {
-          const nsStyleBackground::Position &coordPosition =
+          const nsStyleImageLayers::Position &coordPosition =
             f->StyleDisplay()->mScrollSnapCoordinate[coordNum];
           nsPoint coordPoint = edgesRect.TopLeft() - aScrollSnapDestination;
           coordPoint += nsPoint(coordPosition.mXPosition.mLength,
                                 coordPosition.mYPosition.mLength);
           if (coordPosition.mXPosition.mHasPercent) {
             coordPoint.x += NSToCoordRound(coordPosition.mXPosition.mPercent *
                                            frameRect.width);
           }
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -2914,17 +2914,17 @@ StyleCoordToCSSValue(const nsStyleCoord&
     default:
       MOZ_ASSERT(false, "unexpected unit");
       return false;
   }
   return true;
 }
 
 static void
-SetPositionValue(const nsStyleBackground::Position& aPos, nsCSSValue& aCSSValue)
+SetPositionValue(const nsStyleImageLayers::Position& aPos, nsCSSValue& aCSSValue)
 {
   RefPtr<nsCSSValue::Array> posArray = nsCSSValue::Array::Create(4);
   aCSSValue.SetArrayValue(posArray.get(), eCSSUnit_Array);
 
   // NOTE: Array entries #0 and #2 here are intentionally left untouched, with
   // eCSSUnit_Null.  The purpose of these entries in our specified-style
   // <position> representation is to store edge names.  But for values
   // extracted from computed style (which is what we're dealing with here),
@@ -3275,51 +3275,51 @@ StyleAnimationValue::ExtractComputedValu
           break;
         }
 
         case eCSSProperty_background_position: {
           const nsStyleBackground *bg =
             static_cast<const nsStyleBackground*>(styleStruct);
           nsAutoPtr<nsCSSValueList> result;
           nsCSSValueList **resultTail = getter_Transfers(result);
-          MOZ_ASSERT(bg->mPositionCount > 0, "unexpected count");
-          for (uint32_t i = 0, i_end = bg->mPositionCount; i != i_end; ++i) {
+          MOZ_ASSERT(bg->mLayers.mPositionCount > 0, "unexpected count");
+          for (uint32_t i = 0, i_end = bg->mLayers.mPositionCount; i != i_end; ++i) {
             nsCSSValueList *item = new nsCSSValueList;
             *resultTail = item;
             resultTail = &item->mNext;
-            SetPositionValue(bg->mLayers[i].mPosition, item->mValue);
+            SetPositionValue(bg->mLayers.mLayers[i].mPosition, item->mValue);
           }
 
           aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
                                                       eUnit_BackgroundPosition);
           break;
         }
 
         case eCSSProperty_background_size: {
           const nsStyleBackground *bg =
             static_cast<const nsStyleBackground*>(styleStruct);
           nsAutoPtr<nsCSSValuePairList> result;
           nsCSSValuePairList **resultTail = getter_Transfers(result);
-          MOZ_ASSERT(bg->mSizeCount > 0, "unexpected count");
-          for (uint32_t i = 0, i_end = bg->mSizeCount; i != i_end; ++i) {
+          MOZ_ASSERT(bg->mLayers.mSizeCount > 0, "unexpected count");
+          for (uint32_t i = 0, i_end = bg->mLayers.mSizeCount; i != i_end; ++i) {
             nsCSSValuePairList *item = new nsCSSValuePairList;
             *resultTail = item;
             resultTail = &item->mNext;
 
-            const nsStyleBackground::Size &size = bg->mLayers[i].mSize;
+            const nsStyleImageLayers::Size &size = bg->mLayers.mLayers[i].mSize;
             switch (size.mWidthType) {
-              case nsStyleBackground::Size::eContain:
-              case nsStyleBackground::Size::eCover:
+              case nsStyleImageLayers::Size::eContain:
+              case nsStyleImageLayers::Size::eCover:
                 item->mXValue.SetIntValue(size.mWidthType,
                                           eCSSUnit_Enumerated);
                 break;
-              case nsStyleBackground::Size::eAuto:
+              case nsStyleImageLayers::Size::eAuto:
                 item->mXValue.SetAutoValue();
                 break;
-              case nsStyleBackground::Size::eLengthPercentage:
+              case nsStyleImageLayers::Size::eLengthPercentage:
                 // XXXbz is there a good reason we can't just
                 // SetCalcValue(&size.mWidth, item->mXValue) here?
                 if (!size.mWidth.mHasPercent &&
                     // negative values must have come from calc()
                     size.mWidth.mLength >= 0) {
                   MOZ_ASSERT(size.mWidth.mPercent == 0.0f,
                              "Shouldn't have mPercent");
                   nscoordToCSSValue(size.mWidth.mLength, item->mXValue);
@@ -3329,24 +3329,24 @@ StyleAnimationValue::ExtractComputedValu
                   item->mXValue.SetPercentValue(size.mWidth.mPercent);
                 } else {
                   SetCalcValue(&size.mWidth, item->mXValue);
                 }
                 break;
             }
 
             switch (size.mHeightType) {
-              case nsStyleBackground::Size::eContain:
-              case nsStyleBackground::Size::eCover:
+              case nsStyleImageLayers::Size::eContain:
+              case nsStyleImageLayers::Size::eCover:
                 // leave it null
                 break;
-              case nsStyleBackground::Size::eAuto:
+              case nsStyleImageLayers::Size::eAuto:
                 item->mYValue.SetAutoValue();
                 break;
-              case nsStyleBackground::Size::eLengthPercentage:
+              case nsStyleImageLayers::Size::eLengthPercentage:
                 // XXXbz is there a good reason we can't just
                 // SetCalcValue(&size.mHeight, item->mYValue) here?
                 if (!size.mHeight.mHasPercent &&
                     // negative values must have come from calc()
                     size.mHeight.mLength >= 0) {
                   MOZ_ASSERT(size.mHeight.mPercent == 0.0f,
                              "Shouldn't have mPercent");
                   nscoordToCSSValue(size.mHeight.mLength, item->mYValue);
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -816,45 +816,49 @@ protected:
     nsCSSValue&  mColor;
     nsCSSValueList* mImage;
     nsCSSValuePairList* mRepeat;
     nsCSSValueList* mAttachment;
     nsCSSValueList* mClip;
     nsCSSValueList* mOrigin;
     nsCSSValueList* mPosition;
     nsCSSValuePairList* mSize;
+    nsCSSValueList* mComposite;
+    nsCSSValueList* mMode;
     BackgroundParseState(
         nsCSSValue& aColor, nsCSSValueList* aImage, nsCSSValuePairList* aRepeat,
         nsCSSValueList* aAttachment, nsCSSValueList* aClip,
         nsCSSValueList* aOrigin, nsCSSValueList* aPosition,
-        nsCSSValuePairList* aSize) :
+        nsCSSValuePairList* aSize, nsCSSValueList* aComposite,
+        nsCSSValueList* aMode) :
         mColor(aColor), mImage(aImage), mRepeat(aRepeat),
         mAttachment(aAttachment), mClip(aClip), mOrigin(aOrigin),
-        mPosition(aPosition), mSize(aSize) {};
+        mPosition(aPosition), mSize(aSize), mComposite(aComposite),
+        mMode(aMode) {};
   };
 
   bool IsFunctionTokenValidForBackgroundImage(const nsCSSToken& aToken) const;
   bool ParseBackgroundItem(BackgroundParseState& aState);
 
   bool ParseValueList(nsCSSProperty aPropID); // a single value prop-id
-  bool ParseBackgroundRepeat();
+  bool ParseBackgroundRepeat(nsCSSProperty aPropID);
   bool ParseBackgroundRepeatValues(nsCSSValuePair& aValue);
-  bool ParseBackgroundPosition();
+  bool ParseBackgroundPosition(nsCSSProperty aPropID);
 
   // ParseBoxPositionValues parses the CSS 2.1 background-position syntax,
   // which is still used by some properties. See ParsePositionValue
   // for the css3-background syntax.
   bool ParseBoxPositionValues(nsCSSValuePair& aOut, bool aAcceptsInherit,
                               bool aAllowExplicitCenter = true); // deprecated
 
   // ParsePositionValue parses a CSS <position> value, which is used by
   // the 'background-position' property.
   bool ParsePositionValue(nsCSSValue& aOut);
 
-  bool ParseBackgroundSize();
+  bool ParseBackgroundSize(nsCSSProperty aPropID);
   bool ParseBackgroundSizeValues(nsCSSValuePair& aOut);
   bool ParseBorderColor();
   bool ParseBorderColors(nsCSSProperty aProperty);
   void SetBorderImageInitialValues();
   bool ParseBorderImageRepeat(bool aAcceptsInherit);
   // If ParseBorderImageSlice returns false, aConsumedTokens indicates
   // whether or not any tokens were consumed (in other words, was the property
   // in error or just not present).  If ParseBorderImageSlice returns true
@@ -10513,21 +10517,21 @@ CSSParserImpl::ParseProperty(nsCSSProper
 
 bool
 CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
 {
   switch (aPropID) {  // handle shorthand or multiple properties
   case eCSSProperty_background:
     return ParseBackground();
   case eCSSProperty_background_repeat:
-    return ParseBackgroundRepeat();
+    return ParseBackgroundRepeat(eCSSProperty_background_repeat);
   case eCSSProperty_background_position:
-    return ParseBackgroundPosition();
+    return ParseBackgroundPosition(eCSSProperty_background_position);
   case eCSSProperty_background_size:
-    return ParseBackgroundSize();
+    return ParseBackgroundSize(eCSSProperty_background_size);
   case eCSSProperty_border:
     return ParseBorderSide(kBorderTopIDs, true);
   case eCSSProperty_border_color:
     return ParseBorderColor();
   case eCSSProperty_border_spacing:
     return ParseBorderSpacing();
   case eCSSProperty_border_style:
     return ParseBorderStyle();
@@ -10954,22 +10958,23 @@ CSSParserImpl::ParseBackground()
     for (const nsCSSProperty* subprops =
            nsCSSProps::SubpropertyEntryFor(eCSSProperty_background);
          *subprops != eCSSProperty_UNKNOWN; ++subprops) {
       AppendValue(*subprops, color);
     }
     return true;
   }
 
-  nsCSSValue image, repeat, attachment, clip, origin, position, size;
-  BackgroundParseState state(color, image.SetListValue(), 
-                             repeat.SetPairListValue(),
-                             attachment.SetListValue(), clip.SetListValue(),
-                             origin.SetListValue(), position.SetListValue(),
-                             size.SetPairListValue());
+  nsCSSValue image, repeat, attachment, clip, origin, position, size, composite, mode;
+  BackgroundParseState state(color, image.SetListValue(),
+                              repeat.SetPairListValue(),
+                              attachment.SetListValue(), clip.SetListValue(),
+                              origin.SetListValue(), position.SetListValue(),
+                              size.SetPairListValue(), composite.SetListValue(),
+                              mode.SetListValue());
 
   for (;;) {
     if (!ParseBackgroundItem(state)) {
       return false;
     }
     // If we saw a color, this must be the last item.
     if (color.GetUnit() != eCSSUnit_Null) {
       break;
@@ -11260,17 +11265,17 @@ CSSParserImpl::ParseValueList(nsCSSPrope
       item = item->mNext;
     }
   }
   AppendValue(aPropID, value);
   return true;
 }
 
 bool
-CSSParserImpl::ParseBackgroundRepeat()
+CSSParserImpl::ParseBackgroundRepeat(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValuePair valuePair;
     if (!ParseBackgroundRepeatValues(valuePair)) {
       return false;
     }
@@ -11284,17 +11289,17 @@ CSSParserImpl::ParseBackgroundRepeat()
       if (!ParseBackgroundRepeatValues(valuePair)) {
         return false;
       }
       item->mNext = new nsCSSValuePairList;
       item = item->mNext;
     }
   }
 
-  AppendValue(eCSSProperty_background_repeat, value);
+  AppendValue(aPropID, value);
   return true;
 }
 
 bool
 CSSParserImpl::ParseBackgroundRepeatValues(nsCSSValuePair& aValue) 
 {
   nsCSSValue& xValue = aValue.mXValue;
   nsCSSValue& yValue = aValue.mYValue;
@@ -11313,17 +11318,17 @@ CSSParserImpl::ParseBackgroundRepeatValu
   }
   
   return false;
 }
 
 // This function is very similar to ParseScrollSnapCoordinate,
 // ParseBackgroundList, and ParseBackgroundSize.
 bool
-CSSParserImpl::ParseBackgroundPosition()
+CSSParserImpl::ParseBackgroundPosition(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValue itemValue;
     if (!ParsePositionValue(itemValue)) {
       return false;
     }
@@ -11335,17 +11340,17 @@ CSSParserImpl::ParseBackgroundPosition()
       }
       if (!ParsePositionValue(itemValue)) {
         return false;
       }
       item->mNext = new nsCSSValueList;
       item = item->mNext;
     }
   }
-  AppendValue(eCSSProperty_background_position, value);
+  AppendValue(aPropID, value);
   return true;
 }
 
 /**
  * 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
@@ -11631,17 +11636,17 @@ CSSParserImpl::ParsePositionValue(nsCSSV
   }
 
   return true;
 }
 
 // This function is very similar to ParseScrollSnapCoordinate,
 // ParseBackgroundList, and ParseBackgroundPosition.
 bool
-CSSParserImpl::ParseBackgroundSize()
+CSSParserImpl::ParseBackgroundSize(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValuePair valuePair;
     if (!ParseBackgroundSizeValues(valuePair)) {
       return false;
     }
@@ -11654,17 +11659,17 @@ CSSParserImpl::ParseBackgroundSize()
       }
       if (!ParseBackgroundSizeValues(valuePair)) {
         return false;
       }
       item->mNext = new nsCSSValuePairList;
       item = item->mNext;
     }
   }
-  AppendValue(eCSSProperty_background_size, value);
+  AppendValue(aPropID, value);
   return true;
 }
 
 /**
  * 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', 'inherit' and 'unset' must be handled by
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1784,47 +1784,48 @@ nsComputedDOMStyle::DoGetFontVariantPosi
       nsCSSProps::ValueToKeywordEnum(intValue,
                                      nsCSSProps::kFontVariantPositionKTable));
   }
 
   return val;
 }
 
 CSSValue*
-nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
-                                      uint32_t nsStyleBackground::* aCount,
+nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleImageLayers::Layer::* aMember,
+                                      uint32_t nsStyleImageLayers::* aCount,
+                                      const nsStyleImageLayers& aLayers,
                                       const KTableValue aTable[])
 {
-  const nsStyleBackground* bg = StyleBackground();
-
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0, i_end = bg->*aCount; i < i_end; ++i) {
+  for (uint32_t i = 0, i_end = aLayers.*aCount; i < i_end; ++i) {
     nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
     valueList->AppendCSSValue(val);
-    val->SetIdent(nsCSSProps::ValueToKeywordEnum(bg->mLayers[i].*aMember,
+    val->SetIdent(nsCSSProps::ValueToKeywordEnum(aLayers.mLayers[i].*aMember,
                                                  aTable));
   }
 
   return valueList;
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundAttachment()
 {
-  return GetBackgroundList(&nsStyleBackground::Layer::mAttachment,
-                           &nsStyleBackground::mAttachmentCount,
+  return GetBackgroundList(&nsStyleImageLayers::Layer::mAttachment,
+                           &nsStyleImageLayers::mAttachmentCount,
+                           StyleBackground()->mLayers,
                            nsCSSProps::kBackgroundAttachmentKTable);
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundClip()
 {
-  return GetBackgroundList(&nsStyleBackground::Layer::mClip,
-                           &nsStyleBackground::mClipCount,
+  return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
+                           &nsStyleImageLayers::mClipCount,
+                           StyleBackground()->mLayers,
                            nsCSSProps::kBackgroundOriginKTable);
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundColor()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
   SetToRGBAColor(val, StyleBackground()->mBackgroundColor);
@@ -2117,62 +2118,64 @@ nsComputedDOMStyle::SetValueToStyleImage
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundImage()
 {
   const nsStyleBackground* bg = StyleBackground();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0, i_end = bg->mImageCount; i < i_end; ++i) {
+  for (uint32_t i = 0, i_end = bg->mLayers.mImageCount; i < i_end; ++i) {
     nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
     valueList->AppendCSSValue(val);
 
-    const nsStyleImage& image = bg->mLayers[i].mImage;
+    const nsStyleImage& image = bg->mLayers.mLayers[i].mImage;
     SetValueToStyleImage(image, val);
   }
 
   return valueList;
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundBlendMode()
 {
-  return GetBackgroundList(&nsStyleBackground::Layer::mBlendMode,
-                           &nsStyleBackground::mBlendModeCount,
+  return GetBackgroundList(&nsStyleImageLayers::Layer::mBlendMode,
+                           &nsStyleImageLayers::mBlendModeCount,
+                           StyleBackground()->mLayers,
                            nsCSSProps::kBlendModeKTable);
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundOrigin()
 {
-  return GetBackgroundList(&nsStyleBackground::Layer::mOrigin,
-                           &nsStyleBackground::mOriginCount,
+  return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
+                           &nsStyleImageLayers::mOriginCount,
+                           StyleBackground()->mLayers,
                            nsCSSProps::kBackgroundOriginKTable);
 }
 
 void
 nsComputedDOMStyle::SetValueToPositionCoord(
-    const nsStyleBackground::Position::PositionCoord& aCoord,
+    const nsStyleImageLayers::Position::PositionCoord& aCoord,
     nsROCSSPrimitiveValue* aValue)
 {
   if (!aCoord.mHasPercent) {
     MOZ_ASSERT(aCoord.mPercent == 0.0f,
                "Shouldn't have mPercent!");
     aValue->SetAppUnits(aCoord.mLength);
   } else if (aCoord.mLength == 0) {
     aValue->SetPercent(aCoord.mPercent);
   } else {
     SetValueToCalc(&aCoord, aValue);
   }
 }
 
 void
 nsComputedDOMStyle::SetValueToPosition(
-    const nsStyleBackground::Position& aPosition,
+    const nsStyleImageLayers::Position& aPosition,
     nsDOMCSSValueList* aValueList)
 {
   nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
   aValueList->AppendCSSValue(valX);
   SetValueToPositionCoord(aPosition.mXPosition, valX);
 
   nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
   aValueList->AppendCSSValue(valY);
@@ -2181,42 +2184,42 @@ nsComputedDOMStyle::SetValueToPosition(
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundPosition()
 {
   const nsStyleBackground* bg = StyleBackground();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0, i_end = bg->mPositionCount; i < i_end; ++i) {
+  for (uint32_t i = 0, i_end = bg->mLayers.mPositionCount; i < i_end; ++i) {
     nsDOMCSSValueList *itemList = GetROCSSValueList(false);
     valueList->AppendCSSValue(itemList);
 
-    SetValueToPosition(bg->mLayers[i].mPosition, itemList);
+    SetValueToPosition(bg->mLayers.mLayers[i].mPosition, itemList);
   }
 
   return valueList;
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundRepeat()
 {
   const nsStyleBackground* bg = StyleBackground();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0, i_end = bg->mRepeatCount; i < i_end; ++i) {
+  for (uint32_t i = 0, i_end = bg->mLayers.mRepeatCount; i < i_end; ++i) {
     nsDOMCSSValueList *itemList = GetROCSSValueList(false);
     valueList->AppendCSSValue(itemList);
 
     nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
     itemList->AppendCSSValue(valX);
 
-    const uint8_t& xRepeat = bg->mLayers[i].mRepeat.mXRepeat;
-    const uint8_t& yRepeat = bg->mLayers[i].mRepeat.mYRepeat;
+    const uint8_t& xRepeat = bg->mLayers.mLayers[i].mRepeat.mXRepeat;
+    const uint8_t& yRepeat = bg->mLayers.mLayers[i].mRepeat.mYRepeat;
 
     bool hasContraction = true;
     unsigned contraction;
     if (xRepeat == yRepeat) {
       contraction = xRepeat;
     } else if (xRepeat == NS_STYLE_BG_REPEAT_REPEAT &&
                yRepeat == NS_STYLE_BG_REPEAT_NO_REPEAT) {
       contraction = NS_STYLE_BG_REPEAT_REPEAT_X;
@@ -2246,67 +2249,67 @@ nsComputedDOMStyle::DoGetBackgroundRepea
 
 CSSValue*
 nsComputedDOMStyle::DoGetBackgroundSize()
 {
   const nsStyleBackground* bg = StyleBackground();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0, i_end = bg->mSizeCount; i < i_end; ++i) {
-    const nsStyleBackground::Size &size = bg->mLayers[i].mSize;
+  for (uint32_t i = 0, i_end = bg->mLayers.mSizeCount; i < i_end; ++i) {
+    const nsStyleImageLayers::Size &size = bg->mLayers.mLayers[i].mSize;
 
     switch (size.mWidthType) {
-      case nsStyleBackground::Size::eContain:
-      case nsStyleBackground::Size::eCover: {
+      case nsStyleImageLayers::Size::eContain:
+      case nsStyleImageLayers::Size::eCover: {
         MOZ_ASSERT(size.mWidthType == size.mHeightType,
                    "unsynced types");
-        nsCSSKeyword keyword = size.mWidthType == nsStyleBackground::Size::eContain
+        nsCSSKeyword keyword = size.mWidthType == nsStyleImageLayers::Size::eContain
                              ? eCSSKeyword_contain
                              : eCSSKeyword_cover;
         nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
         valueList->AppendCSSValue(val);
         val->SetIdent(keyword);
         break;
       }
       default: {
         nsDOMCSSValueList *itemList = GetROCSSValueList(false);
         valueList->AppendCSSValue(itemList);
 
         nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
         itemList->AppendCSSValue(valX);
         nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
         itemList->AppendCSSValue(valY);
 
-        if (size.mWidthType == nsStyleBackground::Size::eAuto) {
+        if (size.mWidthType == nsStyleImageLayers::Size::eAuto) {
           valX->SetIdent(eCSSKeyword_auto);
         } else {
           MOZ_ASSERT(size.mWidthType ==
-                       nsStyleBackground::Size::eLengthPercentage,
+                       nsStyleImageLayers::Size::eLengthPercentage,
                      "bad mWidthType");
           if (!size.mWidth.mHasPercent &&
               // negative values must have come from calc()
               size.mWidth.mLength >= 0) {
             MOZ_ASSERT(size.mWidth.mPercent == 0.0f,
                        "Shouldn't have mPercent");
             valX->SetAppUnits(size.mWidth.mLength);
           } else if (size.mWidth.mLength == 0 &&
                      // negative values must have come from calc()
                      size.mWidth.mPercent >= 0.0f) {
             valX->SetPercent(size.mWidth.mPercent);
           } else {
             SetValueToCalc(&size.mWidth, valX);
           }
         }
 
-        if (size.mHeightType == nsStyleBackground::Size::eAuto) {
+        if (size.mHeightType == nsStyleImageLayers::Size::eAuto) {
           valY->SetIdent(eCSSKeyword_auto);
         } else {
           MOZ_ASSERT(size.mHeightType ==
-                       nsStyleBackground::Size::eLengthPercentage,
+                       nsStyleImageLayers::Size::eLengthPercentage,
                      "bad mHeightType");
           if (!size.mHeight.mHasPercent &&
               // negative values must have come from calc()
               size.mHeight.mLength >= 0) {
             MOZ_ASSERT(size.mHeight.mPercent == 0.0f,
                        "Shouldn't have mPercent");
             valY->SetAppUnits(size.mHeight.mLength);
           } else if (size.mHeight.mLength == 0 &&
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -31,16 +31,17 @@ class Element;
 
 struct nsComputedStyleMap;
 class nsIFrame;
 class nsIPresShell;
 class nsDOMCSSValueList;
 struct nsMargin;
 class nsROCSSPrimitiveValue;
 struct nsStyleBackground;
+struct nsStyleImageLayers;
 class nsStyleCoord;
 class nsStyleCorners;
 struct nsStyleFilter;
 class nsStyleGradient;
 struct nsStyleImage;
 class nsStyleSides;
 struct nsTimingFunction;
 
@@ -183,18 +184,19 @@ private:
   mozilla::dom::CSSValue* GetGridLine(const nsStyleGridLine& aGridLine);
 
   bool GetLineHeightCoord(nscoord& aCoord);
 
   mozilla::dom::CSSValue* GetCSSShadowArray(nsCSSShadowArray* aArray,
                                             const nscolor& aDefaultColor,
                                             bool aIsBoxShadow);
 
-  mozilla::dom::CSSValue* GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
-                                            uint32_t nsStyleBackground::* aCount,
+  mozilla::dom::CSSValue* GetBackgroundList(uint8_t nsStyleImageLayers::Layer::* aMember,
+                                            uint32_t nsStyleImageLayers::* aCount,
+                                            const nsStyleImageLayers& aLayers,
                                             const KTableValue aTable[]);
 
   void GetCSSGradientString(const nsStyleGradient* aGradient,
                             nsAString& aString);
   void GetImageRectString(nsIURI* aURI,
                           const nsStyleSides& aCropRect,
                           nsString& aString);
   mozilla::dom::CSSValue* GetScrollSnapPoints(const nsStyleCoord& aCoord);
@@ -532,19 +534,19 @@ private:
 
   nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
 
   /* Helper functions */
   void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
   void SetValueToStyleImage(const nsStyleImage& aStyleImage,
                             nsROCSSPrimitiveValue* aValue);
   void SetValueToPositionCoord(
-    const nsStyleBackground::Position::PositionCoord& aCoord,
+    const nsStyleImageLayers::Position::PositionCoord& aCoord,
     nsROCSSPrimitiveValue* aValue);
-  void SetValueToPosition(const nsStyleBackground::Position& aPosition,
+  void SetValueToPosition(const nsStyleImageLayers::Position& aPosition,
                           nsDOMCSSValueList* aValueList);
 
   /**
    * A method to get a percentage base for a percentage value.  Returns true
    * if a percentage base value was determined, false otherwise.
    */
   typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&);
 
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -107,17 +107,17 @@ nsConditionalResetStyleData::GetConditio
     NS_SET_IMAGE_REQUEST(method_, context_, requestgetter_(doc))              \
   }
 
 /* Helper function to convert a CSS <position> specified value into its
  * computed-style form. */
 static void
   ComputePositionValue(nsStyleContext* aStyleContext,
                        const nsCSSValue& aValue,
-                       nsStyleBackground::Position& aComputedValue,
+                       nsStyleImageLayers::Position& aComputedValue,
                        RuleNodeCacheConditions& aConditions);
 
 /*
  * For storage of an |nsRuleNode|'s children in a PLDHashTable.
  */
 
 struct ChildrenHashEntry : public PLDHashEntryHdr {
   // key is |mRuleNode->GetKey()|
@@ -5492,17 +5492,17 @@ nsRuleNode::ComputeDisplayData(void* aSt
       break;
     default: {
         ComputePositionValue(aContext, snapDestination,
                              display->mScrollSnapDestination, conditions);
       }
   }
 
   // scroll-snap-coordinate: none, inherit, initial
-  typedef nsStyleBackground::Position Position;
+  typedef nsStyleImageLayers::Position Position;
 
   const nsCSSValue& snapCoordinate = *aRuleData->ValueForScrollSnapCoordinate();
   switch (snapCoordinate.GetUnit()) {
     case eCSSUnit_Null:
       break;
     case eCSSUnit_Initial:
     case eCSSUnit_Unset:
     case eCSSUnit_None:
@@ -6208,51 +6208,51 @@ struct BackgroundItemComputer<nsCSSValue
                            RuleNodeCacheConditions& aConditions)
   {
     SetDiscrete(aSpecifiedValue->mValue, aComputedValue, aConditions,
                 SETDSC_ENUMERATED, uint8_t(0), 0, 0, 0, 0, 0);
   }
 };
 
 template <>
-struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Repeat>
+struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Repeat>
 {
   static void ComputeValue(nsStyleContext* aStyleContext,
                            const nsCSSValuePairList* aSpecifiedValue,
-                           nsStyleBackground::Repeat& aComputedValue,
+                           nsStyleImageLayers::Repeat& aComputedValue,
                            RuleNodeCacheConditions& aConditions)
   {
     NS_ASSERTION(aSpecifiedValue->mXValue.GetUnit() == eCSSUnit_Enumerated &&
                  (aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Enumerated ||
                   aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null),
                  "Invalid unit");
-    
+
     bool hasContraction = true;
     uint8_t value = aSpecifiedValue->mXValue.GetIntValue();
     switch (value) {
     case NS_STYLE_BG_REPEAT_REPEAT_X:
       aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
       aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT;
       break;
     case NS_STYLE_BG_REPEAT_REPEAT_Y:
       aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT;
       aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
       break;
     default:
       aComputedValue.mXRepeat = value;
       hasContraction = false;
       break;
     }
-    
+
     if (hasContraction) {
       NS_ASSERTION(aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null,
                    "Invalid unit.");
       return;
     }
-    
+
     switch (aSpecifiedValue->mYValue.GetUnit()) {
     case eCSSUnit_Null:
       aComputedValue.mYRepeat = aComputedValue.mXRepeat;
       break;
     case eCSSUnit_Enumerated:
       value = aSpecifiedValue->mYValue.GetIntValue();
       NS_ASSERTION(value == NS_STYLE_BG_REPEAT_NO_REPEAT ||
                    value == NS_STYLE_BG_REPEAT_REPEAT, "Unexpected value");
@@ -6277,17 +6277,17 @@ struct BackgroundItemComputer<nsCSSValue
                   aConditions);
   }
 };
 
 /* Helper function for ComputePositionValue.
  * This function computes a single PositionCoord from two nsCSSValue objects,
  * which represent an edge and an offset from that edge.
  */
-typedef nsStyleBackground::Position::PositionCoord PositionCoord;
+typedef nsStyleImageLayers::Position::PositionCoord PositionCoord;
 static void
 ComputePositionCoord(nsStyleContext* aStyleContext,
                      const nsCSSValue& aEdge,
                      const nsCSSValue& aOffset,
                      PositionCoord* aResult,
                      RuleNodeCacheConditions& aConditions)
 {
   if (eCSSUnit_Percent == aOffset.GetUnit()) {
@@ -6332,17 +6332,17 @@ ComputePositionCoord(nsStyleContext* aSt
   }
 }
 
 /* Helper function to convert a CSS <position> specified value into its
  * computed-style form. */
 static void
 ComputePositionValue(nsStyleContext* aStyleContext,
                      const nsCSSValue& aValue,
-                     nsStyleBackground::Position& aComputedValue,
+                     nsStyleImageLayers::Position& aComputedValue,
                      RuleNodeCacheConditions& aConditions)
 {
   NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
                "unexpected unit for CSS <position> value");
 
   RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
   const nsCSSValue &xEdge   = positionArray->Item(0);
   const nsCSSValue &xOffset = positionArray->Item(1);
@@ -6362,64 +6362,64 @@ ComputePositionValue(nsStyleContext* aSt
                        aConditions);
 
   ComputePositionCoord(aStyleContext, yEdge, yOffset,
                        &aComputedValue.mYPosition,
                        aConditions);
 }
 
 template <>
-struct BackgroundItemComputer<nsCSSValueList, nsStyleBackground::Position>
+struct BackgroundItemComputer<nsCSSValueList, nsStyleImageLayers::Position>
 {
   static void ComputeValue(nsStyleContext* aStyleContext,
                            const nsCSSValueList* aSpecifiedValue,
-                           nsStyleBackground::Position& aComputedValue,
+                           nsStyleImageLayers::Position& aComputedValue,
                            RuleNodeCacheConditions& aConditions)
   {
     ComputePositionValue(aStyleContext, aSpecifiedValue->mValue,
                          aComputedValue, aConditions);
   }
 };
 
 
 struct BackgroundSizeAxis {
   nsCSSValue nsCSSValuePairList::* specified;
-  nsStyleBackground::Size::Dimension nsStyleBackground::Size::* result;
-  uint8_t nsStyleBackground::Size::* type;
+  nsStyleImageLayers::Size::Dimension nsStyleImageLayers::Size::* result;
+  uint8_t nsStyleImageLayers::Size::* type;
 };
 
 static const BackgroundSizeAxis gBGSizeAxes[] = {
   { &nsCSSValuePairList::mXValue,
-    &nsStyleBackground::Size::mWidth,
-    &nsStyleBackground::Size::mWidthType },
+    &nsStyleImageLayers::Size::mWidth,
+    &nsStyleImageLayers::Size::mWidthType },
   { &nsCSSValuePairList::mYValue,
-    &nsStyleBackground::Size::mHeight,
-    &nsStyleBackground::Size::mHeightType }
+    &nsStyleImageLayers::Size::mHeight,
+    &nsStyleImageLayers::Size::mHeightType }
 };
 
 template <>
-struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Size>
+struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Size>
 {
   static void ComputeValue(nsStyleContext* aStyleContext,
                            const nsCSSValuePairList* aSpecifiedValue,
-                           nsStyleBackground::Size& aComputedValue,
+                           nsStyleImageLayers::Size& aComputedValue,
                            RuleNodeCacheConditions& aConditions)
   {
-    nsStyleBackground::Size &size = aComputedValue;
+    nsStyleImageLayers::Size &size = aComputedValue;
     for (const BackgroundSizeAxis *axis = gBGSizeAxes,
                         *axis_end = ArrayEnd(gBGSizeAxes);
          axis < axis_end; ++axis) {
       const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
       if (eCSSUnit_Auto == specified.GetUnit()) {
-        size.*(axis->type) = nsStyleBackground::Size::eAuto;
+        size.*(axis->type) = nsStyleImageLayers::Size::eAuto;
       }
       else if (eCSSUnit_Enumerated == specified.GetUnit()) {
-        static_assert(nsStyleBackground::Size::eContain ==
+        static_assert(nsStyleImageLayers::Size::eContain ==
                       NS_STYLE_BG_SIZE_CONTAIN &&
-                      nsStyleBackground::Size::eCover ==
+                      nsStyleImageLayers::Size::eCover ==
                       NS_STYLE_BG_SIZE_COVER,
                       "background size constants out of sync");
         MOZ_ASSERT(specified.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN ||
                    specified.GetIntValue() == NS_STYLE_BG_SIZE_COVER,
                    "invalid enumerated value for size coordinate");
         size.*(axis->type) = specified.GetIntValue();
       }
       else if (eCSSUnit_Null == specified.GetUnit()) {
@@ -6441,56 +6441,56 @@ struct BackgroundItemComputer<nsCSSValue
         }
 #endif
         size.*(axis->type) = size.mWidthType;
       }
       else if (eCSSUnit_Percent == specified.GetUnit()) {
         (size.*(axis->result)).mLength = 0;
         (size.*(axis->result)).mPercent = specified.GetPercentValue();
         (size.*(axis->result)).mHasPercent = true;
-        size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
+        size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
       }
       else if (specified.IsLengthUnit()) {
         (size.*(axis->result)).mLength =
           CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
                      aConditions);
         (size.*(axis->result)).mPercent = 0.0f;
         (size.*(axis->result)).mHasPercent = false;
-        size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
+        size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
       } else {
         MOZ_ASSERT(specified.IsCalcUnit(), "unexpected unit");
         LengthPercentPairCalcOps ops(aStyleContext,
                                      aStyleContext->PresContext(),
                                      aConditions);
         nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops);
         (size.*(axis->result)).mLength = vals.mLength;
         (size.*(axis->result)).mPercent = vals.mPercent;
         (size.*(axis->result)).mHasPercent = ops.mHasPercent;
-        size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
-      }
-    }
-
-    MOZ_ASSERT(size.mWidthType < nsStyleBackground::Size::eDimensionType_COUNT,
+        size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
+      }
+    }
+
+    MOZ_ASSERT(size.mWidthType < nsStyleImageLayers::Size::eDimensionType_COUNT,
                "bad width type");
-    MOZ_ASSERT(size.mHeightType < nsStyleBackground::Size::eDimensionType_COUNT,
+    MOZ_ASSERT(size.mHeightType < nsStyleImageLayers::Size::eDimensionType_COUNT,
                "bad height type");
-    MOZ_ASSERT((size.mWidthType != nsStyleBackground::Size::eContain &&
-                size.mWidthType != nsStyleBackground::Size::eCover) ||
+    MOZ_ASSERT((size.mWidthType != nsStyleImageLayers::Size::eContain &&
+                size.mWidthType != nsStyleImageLayers::Size::eCover) ||
                size.mWidthType == size.mHeightType,
                "contain/cover apply to both dimensions or to neither");
   }
 };
 
 template <class ComputedValueItem>
 static void
 SetBackgroundList(nsStyleContext* aStyleContext,
                   const nsCSSValue& aValue,
-                  nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
-                  const nsAutoTArray<nsStyleBackground::Layer, 1> &aParentLayers,
-                  ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
+                  nsAutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
+                  const nsAutoTArray<nsStyleImageLayers::Layer, 1> &aParentLayers,
+                  ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
                   ComputedValueItem aInitialValue,
                   uint32_t aParentItemCount,
                   uint32_t& aItemCount,
                   uint32_t& aMaxItemCount,
                   bool& aRebuild,
                   RuleNodeCacheConditions& aConditions)
 {
   switch (aValue.GetUnit()) {
@@ -6543,20 +6543,20 @@ SetBackgroundList(nsStyleContext* aStyle
   if (aItemCount > aMaxItemCount)
     aMaxItemCount = aItemCount;
 }
 
 template <class ComputedValueItem>
 static void
 SetBackgroundPairList(nsStyleContext* aStyleContext,
                       const nsCSSValue& aValue,
-                      nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
-                      const nsAutoTArray<nsStyleBackground::Layer, 1>
+                      nsAutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
+                      const nsAutoTArray<nsStyleImageLayers::Layer, 1>
                                                                  &aParentLayers,
-                      ComputedValueItem nsStyleBackground::Layer::*
+                      ComputedValueItem nsStyleImageLayers::Layer::*
                                                                 aResultLocation,
                       ComputedValueItem aInitialValue,
                       uint32_t aParentItemCount,
                       uint32_t& aItemCount,
                       uint32_t& aMaxItemCount,
                       bool& aRebuild,
                       RuleNodeCacheConditions& aConditions)
 {
@@ -6610,18 +6610,18 @@ SetBackgroundPairList(nsStyleContext* aS
   }
 
   if (aItemCount > aMaxItemCount)
     aMaxItemCount = aItemCount;
 }
 
 template <class ComputedValueItem>
 static void
-FillBackgroundList(nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
-    ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
+FillBackgroundList(nsAutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
+    ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
     uint32_t aItemCount, uint32_t aFillCount)
 {
   NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
   for (uint32_t sourceLayer = 0, destLayer = aItemCount;
        destLayer < aFillCount;
        ++sourceLayer, ++destLayer) {
     aLayers[destLayer].*aResultLocation =
       aLayers[sourceLayer].*aResultLocation;
@@ -6651,110 +6651,109 @@ nsRuleNode::ComputeBackgroundData(void* 
   }
 
   uint32_t maxItemCount = 1;
   bool rebuild = false;
 
   // background-image: url (stored as image), none, inherit [list]
   nsStyleImage initialImage;
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundImage(),
-                    bg->mLayers,
-                    parentBG->mLayers, &nsStyleBackground::Layer::mImage,
-                    initialImage, parentBG->mImageCount, bg->mImageCount,
+                    bg->mLayers.mLayers,
+                    parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mImage,
+                    initialImage, parentBG->mLayers.mImageCount, bg->mLayers.mImageCount,
                     maxItemCount, rebuild, conditions);
 
   // background-repeat: enum, inherit, initial [pair list]
-  nsStyleBackground::Repeat initialRepeat;
+  nsStyleImageLayers::Repeat initialRepeat;
   initialRepeat.SetInitialValues();
   SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundRepeat(),
-                        bg->mLayers,
-                        parentBG->mLayers, &nsStyleBackground::Layer::mRepeat,
-                        initialRepeat, parentBG->mRepeatCount,
-                        bg->mRepeatCount, maxItemCount, rebuild, 
+                        bg->mLayers.mLayers,
+                        parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mRepeat,
+                        initialRepeat, parentBG->mLayers.mRepeatCount,
+                        bg->mLayers.mRepeatCount, maxItemCount, rebuild,
                         conditions);
 
   // background-attachment: enum, inherit, initial [list]
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundAttachment(),
-                    bg->mLayers, parentBG->mLayers,
-                    &nsStyleBackground::Layer::mAttachment,
+                    bg->mLayers.mLayers, parentBG->mLayers.mLayers,
+                    &nsStyleImageLayers::Layer::mAttachment,
                     uint8_t(NS_STYLE_BG_ATTACHMENT_SCROLL),
-                    parentBG->mAttachmentCount,
-                    bg->mAttachmentCount, maxItemCount, rebuild,
+                    parentBG->mLayers.mAttachmentCount,
+                    bg->mLayers.mAttachmentCount, maxItemCount, rebuild,
                     conditions);
 
   // background-clip: enum, inherit, initial [list]
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundClip(),
-                    bg->mLayers,
-                    parentBG->mLayers, &nsStyleBackground::Layer::mClip,
-                    uint8_t(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount,
-                    bg->mClipCount, maxItemCount, rebuild, conditions);
+                    bg->mLayers.mLayers,
+                    parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mClip,
+                    uint8_t(NS_STYLE_BG_CLIP_BORDER), parentBG->mLayers.mClipCount,
+                    bg->mLayers.mClipCount, maxItemCount, rebuild, conditions);
 
   // background-blend-mode: enum, inherit, initial [list]
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
-                    bg->mLayers,
-                    parentBG->mLayers, &nsStyleBackground::Layer::mBlendMode,
-                    uint8_t(NS_STYLE_BLEND_NORMAL), parentBG->mBlendModeCount,
-                    bg->mBlendModeCount, maxItemCount, rebuild,
+                    bg->mLayers.mLayers,
+                    parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mBlendMode,
+                    uint8_t(NS_STYLE_BLEND_NORMAL), parentBG->mLayers.mBlendModeCount,
+                    bg->mLayers.mBlendModeCount, maxItemCount, rebuild,
                     conditions);
 
   // background-origin: enum, inherit, initial [list]
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundOrigin(),
-                    bg->mLayers,
-                    parentBG->mLayers, &nsStyleBackground::Layer::mOrigin,
-                    uint8_t(NS_STYLE_BG_ORIGIN_PADDING), parentBG->mOriginCount,
-                    bg->mOriginCount, maxItemCount, rebuild,
+                    bg->mLayers.mLayers,
+                    parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mOrigin,
+                    uint8_t(NS_STYLE_BG_ORIGIN_PADDING), parentBG->mLayers.mOriginCount,
+                    bg->mLayers.mOriginCount, maxItemCount, rebuild,
                     conditions);
 
   // background-position: enum, length, percent (flags), inherit [pair list]
-  nsStyleBackground::Position initialPosition;
+  nsStyleImageLayers::Position initialPosition;
   initialPosition.SetInitialPercentValues(0.0f);
   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundPosition(),
-                    bg->mLayers,
-                    parentBG->mLayers, &nsStyleBackground::Layer::mPosition,
-                    initialPosition, parentBG->mPositionCount,
-                    bg->mPositionCount, maxItemCount, rebuild,
+                    bg->mLayers.mLayers,
+                    parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mPosition,
+                    initialPosition, parentBG->mLayers.mPositionCount,
+                    bg->mLayers.mPositionCount, maxItemCount, rebuild,
                     conditions);
 
   // background-size: enum, length, auto, inherit, initial [pair list]
-  nsStyleBackground::Size initialSize;
+  nsStyleImageLayers::Size initialSize;
   initialSize.SetInitialValues();
   SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundSize(),
-                        bg->mLayers,
-                        parentBG->mLayers, &nsStyleBackground::Layer::mSize,
-                        initialSize, parentBG->mSizeCount,
-                        bg->mSizeCount, maxItemCount, rebuild,
+                        bg->mLayers.mLayers,
+                        parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mSize,
+                        initialSize, parentBG->mLayers.mSizeCount,
+                        bg->mLayers.mSizeCount, maxItemCount, rebuild,
                         conditions);
 
   if (rebuild) {
     // Delete any extra items.  We need to keep layers in which any
     // property was specified.
-    bg->mLayers.TruncateLength(maxItemCount);
-
-    uint32_t fillCount = bg->mImageCount;
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mImage,
-                       bg->mImageCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mRepeat,
-                       bg->mRepeatCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mAttachment,
-                       bg->mAttachmentCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mClip,
-                       bg->mClipCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mBlendMode,
-                       bg->mBlendModeCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mOrigin,
-                       bg->mOriginCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mPosition,
-                       bg->mPositionCount, fillCount);
-    FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mSize,
-                       bg->mSizeCount, fillCount);
+    bg->mLayers.mLayers.TruncateLength(maxItemCount);
+
+    uint32_t fillCount = bg->mLayers.mImageCount;
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mImage,
+                       bg->mLayers.mImageCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mRepeat,
+                       bg->mLayers.mRepeatCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mAttachment,
+                       bg->mLayers.mAttachmentCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mClip,
+                       bg->mLayers.mClipCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mBlendMode,
+                       bg->mLayers.mBlendModeCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mOrigin,
+                       bg->mLayers.mOriginCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mPosition,
+                       bg->mLayers.mPositionCount, fillCount);
+    FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mSize,
+                       bg->mLayers.mSizeCount, fillCount);
   }
 
   // Now that the dust has settled, register the images with the document
-  for (uint32_t i = 0; i < bg->mImageCount; ++i)
-    bg->mLayers[i].TrackImages(aContext->PresContext());
+  bg->mLayers.TrackImages(aContext->PresContext());
 
   COMPUTE_END_RESET(Background, bg)
 }
 
 const void*
 nsRuleNode::ComputeMarginData(void* aStartStruct,
                               const nsRuleData* aRuleData,
                               nsStyleContext* aContext,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1270,31 +1270,31 @@ nsStyleFilter::SetDropShadow(nsCSSShadow
   mDropShadow = aDropShadow;
   mDropShadow->AddRef();
   mType = NS_STYLE_FILTER_DROP_SHADOW;
 }
 
 // --------------------
 // nsStyleSVGReset
 //
-nsStyleSVGReset::nsStyleSVGReset() 
+nsStyleSVGReset::nsStyleSVGReset()
 {
     MOZ_COUNT_CTOR(nsStyleSVGReset);
     mStopColor               = NS_RGB(0,0,0);
     mFloodColor              = NS_RGB(0,0,0);
     mLightingColor           = NS_RGB(255,255,255);
     mMask                    = nullptr;
     mStopOpacity             = 1.0f;
     mFloodOpacity            = 1.0f;
     mDominantBaseline        = NS_STYLE_DOMINANT_BASELINE_AUTO;
     mVectorEffect            = NS_STYLE_VECTOR_EFFECT_NONE;
     mMaskType                = NS_STYLE_MASK_TYPE_LUMINANCE;
 }
 
-nsStyleSVGReset::~nsStyleSVGReset() 
+nsStyleSVGReset::~nsStyleSVGReset()
 {
   MOZ_COUNT_DTOR(nsStyleSVGReset);
 }
 
 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
 {
   MOZ_COUNT_CTOR(nsStyleSVGReset);
   mStopColor = aSource.mStopColor;
@@ -2540,339 +2540,114 @@ nsStyleImageLayers::Layer::CalcDifferenc
   return hint;
 }
 
 // --------------------
 // nsStyleBackground
 //
 
 nsStyleBackground::nsStyleBackground()
-  : mAttachmentCount(1)
-  , mClipCount(1)
-  , mOriginCount(1)
-  , mRepeatCount(1)
-  , mPositionCount(1)
-  , mImageCount(1)
-  , mSizeCount(1)
-  , mBlendModeCount(1)
-  , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
+  : mBackgroundColor(NS_RGBA(0, 0, 0, 0))
 {
   MOZ_COUNT_CTOR(nsStyleBackground);
-  Layer *onlyLayer = mLayers.AppendElement();
-  NS_ASSERTION(onlyLayer, "auto array must have room for 1 element");
-  onlyLayer->SetInitialValues();
 }
 
 nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
-  : mAttachmentCount(aSource.mAttachmentCount)
-  , mClipCount(aSource.mClipCount)
-  , mOriginCount(aSource.mOriginCount)
-  , mRepeatCount(aSource.mRepeatCount)
-  , mPositionCount(aSource.mPositionCount)
-  , mImageCount(aSource.mImageCount)
-  , mSizeCount(aSource.mSizeCount)
-  , mBlendModeCount(aSource.mBlendModeCount)
-  , mLayers(aSource.mLayers) // deep copy
+  : mLayers(aSource.mLayers)
   , mBackgroundColor(aSource.mBackgroundColor)
 {
   MOZ_COUNT_CTOR(nsStyleBackground);
-  // If the deep copy of mLayers failed, truncate the counts.
-  uint32_t count = mLayers.Length();
-  if (count != aSource.mLayers.Length()) {
-    NS_WARNING("truncating counts due to out-of-memory");
-    mAttachmentCount = std::max(mAttachmentCount, count);
-    mClipCount = std::max(mClipCount, count);
-    mOriginCount = std::max(mOriginCount, count);
-    mRepeatCount = std::max(mRepeatCount, count);
-    mPositionCount = std::max(mPositionCount, count);
-    mImageCount = std::max(mImageCount, count);
-    mSizeCount = std::max(mSizeCount, count);
-    mBlendModeCount = std::max(mSizeCount, count);
-  }
+
 }
 
 nsStyleBackground::~nsStyleBackground()
 {
   MOZ_COUNT_DTOR(nsStyleBackground);
 }
 
 void
 nsStyleBackground::Destroy(nsPresContext* aContext)
 {
   // Untrack all the images stored in our layers
-  for (uint32_t i = 0; i < mImageCount; ++i)
-    mLayers[i].UntrackImages(aContext);
+  mLayers.UntrackImages(aContext);
 
   this->~nsStyleBackground();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
 }
 
 nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
 {
-  const nsStyleBackground* moreLayers =
-    mImageCount > aOther.mImageCount ? this : &aOther;
-  const nsStyleBackground* lessLayers =
-    mImageCount > aOther.mImageCount ? &aOther : this;
+  const nsStyleImageLayers& moreLayers =
+    mLayers.mImageCount > aOther.mLayers.mImageCount ?
+      this->mLayers : aOther.mLayers;
+  const nsStyleImageLayers& lessLayers =
+    mLayers.mImageCount > aOther.mLayers.mImageCount ?
+      aOther.mLayers : this->mLayers;
 
   nsChangeHint hint = nsChangeHint(0);
 
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) {
-    if (i < lessLayers->mImageCount) {
-      nsChangeHint layerDifference = moreLayers->mLayers[i].CalcDifference(lessLayers->mLayers[i]);
+  NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, moreLayers) {
+    if (i < lessLayers.mImageCount) {
+      nsChangeHint layerDifference = moreLayers.mLayers[i].
+                                       CalcDifference(lessLayers.mLayers[i]);
       hint |= layerDifference;
       if (layerDifference &&
-          ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
-           (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
+          ((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
+           (lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
         hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
       }
     } else {
       hint |= nsChangeHint_RepaintFrame;
-      if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) {
+      if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
         hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
       }
     }
   }
 
   if (mBackgroundColor != aOther.mBackgroundColor) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (hint) {
     return hint;
   }
 
-  if (mAttachmentCount != aOther.mAttachmentCount ||
-      mClipCount != aOther.mClipCount ||
-      mOriginCount != aOther.mOriginCount ||
-      mRepeatCount != aOther.mRepeatCount ||
-      mPositionCount != aOther.mPositionCount ||
-      mSizeCount != aOther.mSizeCount) {
+  if (mLayers.mAttachmentCount != aOther.mLayers.mAttachmentCount ||
+      mLayers.mClipCount != aOther.mLayers.mClipCount ||
+      mLayers.mOriginCount != aOther.mLayers.mOriginCount ||
+      mLayers.mRepeatCount != aOther.mLayers.mRepeatCount ||
+      mLayers.mPositionCount != aOther.mLayers.mPositionCount ||
+      mLayers.mSizeCount != aOther.mLayers.mSizeCount) {
     return nsChangeHint_NeutralChange;
   }
 
+
   return NS_STYLE_HINT_NONE;
 }
 
 bool nsStyleBackground::HasFixedBackground() const
 {
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
-    const Layer &layer = mLayers[i];
+  NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, mLayers) {
+    const nsStyleImageLayers::Layer &layer = mLayers.mLayers[i];
     if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
         !layer.mImage.IsEmpty()) {
       return true;
     }
   }
   return false;
 }
 
 bool nsStyleBackground::IsTransparent() const
 {
   return BottomLayer().mImage.IsEmpty() &&
-         mImageCount == 1 &&
+         mLayers.mImageCount == 1 &&
          NS_GET_A(mBackgroundColor) == 0;
 }
 
-void
-nsStyleBackground::Position::SetInitialPercentValues(float aPercentVal)
-{
-  mXPosition.mPercent = aPercentVal;
-  mXPosition.mLength = 0;
-  mXPosition.mHasPercent = true;
-  mYPosition.mPercent = aPercentVal;
-  mYPosition.mLength = 0;
-  mYPosition.mHasPercent = true;
-}
-
-void
-nsStyleBackground::Position::SetInitialZeroValues()
-{
-  mXPosition.mPercent = 0;
-  mXPosition.mLength = 0;
-  mXPosition.mHasPercent = false;
-  mYPosition.mPercent = 0;
-  mYPosition.mLength = 0;
-  mYPosition.mHasPercent = false;
-}
-
-bool
-nsStyleBackground::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
-{
-  MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
-             "caller should have handled this");
-
-  // If either dimension contains a non-zero percentage, rendering for that
-  // dimension straightforwardly depends on frame size.
-  if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
-      (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
-    return true;
-  }
-
-  // So too for contain and cover.
-  if (mWidthType == eContain || mWidthType == eCover) {
-    return true;
-  }
-
-  // If both dimensions are fixed lengths, there's no dependency.
-  if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
-    return false;
-  }
-
-  MOZ_ASSERT((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
-             (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
-             (mWidthType == eAuto && mHeightType == eAuto),
-             "logic error");
-
-  nsStyleImageType type = aImage.GetType();
-
-  // Gradient rendering depends on frame size when auto is involved because
-  // gradients have no intrinsic ratio or dimensions, and therefore the relevant
-  // dimension is "treat[ed] as 100%".
-  if (type == eStyleImageType_Gradient) {
-    return true;
-  }
-
-  // XXX Element rendering for auto or fixed length doesn't depend on frame size
-  //     according to the spec.  However, we don't implement the spec yet, so
-  //     for now we bail and say element() plus auto affects ultimate size.
-  if (type == eStyleImageType_Element) {
-    return true;
-  }
-
-  if (type == eStyleImageType_Image) {
-    nsCOMPtr<imgIContainer> imgContainer;
-    aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
-    if (imgContainer) {
-      CSSIntSize imageSize;
-      nsSize imageRatio;
-      bool hasWidth, hasHeight;
-      nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
-                                           hasWidth, hasHeight);
-
-      // If the image has a fixed width and height, rendering never depends on
-      // the frame size.
-      if (hasWidth && hasHeight) {
-        return false;
-      }
-
-      // If the image has an intrinsic ratio, rendering will depend on frame
-      // size when background-size is all auto.
-      if (imageRatio != nsSize(0, 0)) {
-        return mWidthType == mHeightType;
-      }
-
-      // Otherwise, rendering depends on frame size when the image dimensions
-      // and background-size don't complement each other.
-      return !(hasWidth && mHeightType == eLengthPercentage) &&
-             !(hasHeight && mWidthType == eLengthPercentage);
-    }
-  } else {
-    NS_NOTREACHED("missed an enum value");
-  }
-
-  // Passed the gauntlet: no dependency.
-  return false;
-}
-
-void
-nsStyleBackground::Size::SetInitialValues()
-{
-  mWidthType = mHeightType = eAuto;
-}
-
-bool
-nsStyleBackground::Size::operator==(const Size& aOther) const
-{
-  MOZ_ASSERT(mWidthType < eDimensionType_COUNT,
-             "bad mWidthType for this");
-  MOZ_ASSERT(mHeightType < eDimensionType_COUNT,
-             "bad mHeightType for this");
-  MOZ_ASSERT(aOther.mWidthType < eDimensionType_COUNT,
-             "bad mWidthType for aOther");
-  MOZ_ASSERT(aOther.mHeightType < eDimensionType_COUNT,
-             "bad mHeightType for aOther");
-
-  return mWidthType == aOther.mWidthType &&
-         mHeightType == aOther.mHeightType &&
-         (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
-         (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
-}
-
-void
-nsStyleBackground::Repeat::SetInitialValues() 
-{
-  mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
-  mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
-}
-
-nsStyleBackground::Layer::Layer()
-{
-}
-
-nsStyleBackground::Layer::~Layer()
-{
-}
-
-void
-nsStyleBackground::Layer::SetInitialValues()
-{
-  mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
-  mClip = NS_STYLE_BG_CLIP_BORDER;
-  mOrigin = NS_STYLE_BG_ORIGIN_PADDING;
-  mRepeat.SetInitialValues();
-  mBlendMode = NS_STYLE_BLEND_NORMAL;
-  mPosition.SetInitialPercentValues(0.0f); // Initial value is "0% 0%"
-  mSize.SetInitialValues();
-  mImage.SetNull();
-}
-
-bool
-nsStyleBackground::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
-{
-  // Do we even have an image?
-  if (mImage.IsEmpty()) {
-    return false;
-  }
-
-  return mPosition.DependsOnPositioningAreaSize() ||
-      mSize.DependsOnPositioningAreaSize(mImage);
-}
-
-bool
-nsStyleBackground::Layer::operator==(const Layer& aOther) const
-{
-  return mAttachment == aOther.mAttachment &&
-         mClip == aOther.mClip &&
-         mOrigin == aOther.mOrigin &&
-         mRepeat == aOther.mRepeat &&
-         mBlendMode == aOther.mBlendMode &&
-         mPosition == aOther.mPosition &&
-         mSize == aOther.mSize &&
-         mImage == aOther.mImage;
-}
-
-nsChangeHint
-nsStyleBackground::Layer::CalcDifference(const Layer& aOther) const
-{
-  nsChangeHint hint = nsChangeHint(0);
-  if (mAttachment != aOther.mAttachment ||
-      mClip != aOther.mClip ||
-      mOrigin != aOther.mOrigin ||
-      mRepeat != aOther.mRepeat ||
-      mBlendMode != aOther.mBlendMode ||
-      mSize != aOther.mSize ||
-      mImage != aOther.mImage) {
-    hint |= nsChangeHint_RepaintFrame;
-  }
-  if (mPosition != aOther.mPosition) {
-    hint |= nsChangeHint_SchedulePaint;
-  }
-  return hint;
-}
-
 // --------------------
 // nsStyleDisplay
 //
 void nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
 {
   switch (aTimingFunctionType) {
     case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
       mType = Type::StepStart;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -495,17 +495,17 @@ struct nsStyleImageLayers {
     bool operator!=(const Repeat& aOther) const {
       return !(*this == aOther);
     }
   };
 
   struct Layer;
   friend struct Layer;
   struct Layer {
-    nsStyleImage  mImage;         // [reset]
+   nsStyleImage  mImage;         // [reset]
     Position      mPosition;      // [reset] See nsStyleConsts.h
     Size          mSize;          // [reset]
     uint8_t       mClip;          // [reset] See nsStyleConsts.h
     uint8_t       mOrigin;        // [reset] See nsStyleConsts.h
     uint8_t       mAttachment;    // [reset] See nsStyleConsts.h
                                   // background-only property
                                   // This property is used for background layer
                                   // only. For a mask layer, it should always
@@ -603,225 +603,40 @@ struct nsStyleBackground {
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
   static nsChangeHint MaxDifference() {
-    return nsChangeHint_UpdateEffects |
+     return nsChangeHint_UpdateEffects |
            nsChangeHint_RepaintFrame |
            nsChangeHint_SchedulePaint |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants at all.
     return nsChangeHint(0);
   }
 
-  struct Position;
-  friend struct Position;
-  struct Position {
-    typedef nsStyleCoord::CalcValue PositionCoord;
-    PositionCoord mXPosition, mYPosition;
-
-    // Initialize nothing
-    Position() {}
-
-    // Sets both mXPosition and mYPosition to the given percent value for the
-    // initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
-    void SetInitialPercentValues(float aPercentVal);
-
-    // Sets both mXPosition and mYPosition to 0 (app units) for the
-    // initial property-value as a length with no percentage component.
-    void SetInitialZeroValues();
-
-    // True if the effective background image position described by this depends
-    // on the size of the corresponding frame.
-    bool DependsOnPositioningAreaSize() const {
-      return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
-    }
-
-    bool operator==(const Position& aOther) const {
-      return mXPosition == aOther.mXPosition &&
-             mYPosition == aOther.mYPosition;
-    }
-    bool operator!=(const Position& aOther) const {
-      return !(*this == aOther);
-    }
-  };
-
-  struct Size;
-  friend struct Size;
-  struct Size {
-    struct Dimension : public nsStyleCoord::CalcValue {
-      nscoord ResolveLengthPercentage(nscoord aAvailable) const {
-        double d = double(mPercent) * double(aAvailable) + double(mLength);
-        if (d < 0.0)
-          return 0;
-        return NSToCoordRoundWithClamp(float(d));
-      }
-    };
-    Dimension mWidth, mHeight;
-
-    nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
-      MOZ_ASSERT(mWidthType == eLengthPercentage,
-                 "resolving non-length/percent dimension!");
-      return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
-    }
-
-    nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
-      MOZ_ASSERT(mHeightType == eLengthPercentage,
-                 "resolving non-length/percent dimension!");
-      return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
-    }
-
-    // Except for eLengthPercentage, Dimension types which might change
-    // how a layer is painted when the corresponding frame's dimensions
-    // change *must* precede all dimension types which are agnostic to
-    // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
-    enum DimensionType {
-      // If one of mWidth and mHeight is eContain or eCover, then both are.
-      // NOTE: eContain and eCover *must* be equal to NS_STYLE_BG_SIZE_CONTAIN
-      // and NS_STYLE_BG_SIZE_COVER (in kBackgroundSizeKTable).
-      eContain, eCover,
-
-      eAuto,
-      eLengthPercentage,
-      eDimensionType_COUNT
-    };
-    uint8_t mWidthType, mHeightType;
-
-    // True if the effective image size described by this depends on the size of
-    // the corresponding frame, when aImage (which must not have null type) is
-    // the background image.
-    bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
-
-    // Initialize nothing
-    Size() {}
-
-    // Initialize to initial values
-    void SetInitialValues();
-
-    bool operator==(const Size& aOther) const;
-    bool operator!=(const Size& aOther) const {
-      return !(*this == aOther);
-    }
-  };
-
-  struct Repeat;
-  friend struct Repeat;
-  struct Repeat {
-    uint8_t mXRepeat, mYRepeat;
-
-    // Initialize nothing
-    Repeat() {}
-
-    // Initialize to initial values
-    void SetInitialValues();
-
-    bool operator==(const Repeat& aOther) const {
-      return mXRepeat == aOther.mXRepeat &&
-             mYRepeat == aOther.mYRepeat;
-    }
-    bool operator!=(const Repeat& aOther) const {
-      return !(*this == aOther);
-    }
-  };
-
-  struct Layer;
-  friend struct Layer;
-  struct Layer {
-    uint8_t mAttachment;                // [reset] See nsStyleConsts.h
-    uint8_t mClip;                      // [reset] See nsStyleConsts.h
-    uint8_t mOrigin;                    // [reset] See nsStyleConsts.h
-    uint8_t mBlendMode;                 // [reset] See nsStyleConsts.h
-    Repeat mRepeat;                     // [reset] See nsStyleConsts.h
-    Position mPosition;                 // [reset]
-    nsStyleImage mImage;                // [reset]
-    Size mSize;                         // [reset]
-
-    // Initializes only mImage
-    Layer();
-    ~Layer();
-
-    // Register/unregister images with the document. We do this only
-    // after the dust has settled in ComputeBackgroundData.
-    void TrackImages(nsPresContext* aContext) {
-      if (mImage.GetType() == eStyleImageType_Image)
-        mImage.TrackImage(aContext);
-    }
-    void UntrackImages(nsPresContext* aContext) {
-      if (mImage.GetType() == eStyleImageType_Image)
-        mImage.UntrackImage(aContext);
-    }
-
-    void SetInitialValues();
-
-    // True if the rendering of this layer might change when the size
-    // of the background positioning area changes.  This is true for any
-    // non-solid-color background whose position or size depends on
-    // the size of the positioning area.  It's also true for SVG images
-    // whose root <svg> node has a viewBox.
-    bool RenderingMightDependOnPositioningAreaSizeChange() const;
-
-    // Compute the change hint required by changes in just this layer.
-    nsChangeHint CalcDifference(const Layer& aOther) const;
-
-    // An equality operator that compares the images using URL-equality
-    // rather than pointer-equality.
-    bool operator==(const Layer& aOther) const;
-    bool operator!=(const Layer& aOther) const {
-      return !(*this == aOther);
-    }
-  };
-
-  // The (positive) number of computed values of each property, since
-  // the lengths of the lists are independent.
-  uint32_t mAttachmentCount,
-           mClipCount,
-           mOriginCount,
-           mRepeatCount,
-           mPositionCount,
-           mImageCount,
-           mSizeCount,
-           mBlendModeCount;
-  // Layers are stored in an array, matching the top-to-bottom order in
-  // which they are specified in CSS.  The number of layers to be used
-  // should come from the background-image property.  We create
-  // additional |Layer| objects for *any* property, not just
-  // background-image.  This means that the bottommost layer that
-  // callers in layout care about (which is also the one whose
-  // background-clip applies to the background-color) may not be last
-  // layer.  In layers below the bottom layer, properties will be
-  // uninitialized unless their count, above, indicates that they are
-  // present.
-  nsAutoTArray<Layer, 1> mLayers;
-
-  const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
-
-  #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \
-    for (uint32_t var_ = (stylebg_) ? (stylebg_)->mImageCount : 1; var_-- != 0; )
-  #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, stylebg_, start_, count_) \
-    NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < ((stylebg_) ? (stylebg_)->mImageCount : 1), "Invalid layer start!"); \
-    NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
-    for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
-
-  nscolor mBackgroundColor;       // [reset]
-
   // True if this background is completely transparent.
   bool IsTransparent() const;
 
   // We have to take slower codepaths for fixed background attachment,
   // but we don't want to do that when there's no image.
   // Not inline because it uses an nsCOMPtr<imgIRequest>
   // FIXME: Should be in nsStyleStructInlines.h.
   bool HasFixedBackground() const;
+
+  const nsStyleImageLayers::Layer& BottomLayer() const { return mLayers.BottomLayer(); }
+
+  nsStyleImageLayers mLayers;
+  nscolor mBackgroundColor;       // [reset]
 };
 
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
 // this is hard to replace with 'currentColor'.
 #define BORDER_COLOR_FOREGROUND   0x20
 #define OUTLINE_COLOR_INITIAL     0x80
 // FOREGROUND | INITIAL(OUTLINE)
 #define BORDER_COLOR_SPECIAL      0xA0
@@ -1599,19 +1414,19 @@ struct nsStylePosition {
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference can return all of the reflow hints that are
     // sometimes handled for descendants as hints not handled for
     // descendants.
     return nsChangeHint(0);
   }
 
-  // XXXdholbert nsStyleBackground::Position should probably be moved to a
+  // XXXdholbert nsStyleImageLayers::Position should probably be moved to a
   // different scope, since we're now using it in multiple style structs.
-  typedef nsStyleBackground::Position Position;
+  typedef nsStyleImageLayers::Position Position;
 
   /**
    * Return the computed value for 'align-content' given our 'display' value in
    * aDisplay.
    */
   uint16_t ComputedAlignContent(const nsStyleDisplay* aDisplay) const;
 
   /**
@@ -2397,20 +2212,20 @@ struct nsStyleDisplay {
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference can return all of the reflow hints that are
     // sometimes handled for descendants as hints not handled for
     // descendants.
     return nsChangeHint(0);
   }
 
-  // XXXdholbert, XXXkgilbert nsStyleBackground::Position should probably be
+  // XXXdholbert, XXXkgilbert nsStyleImageLayers::Position should probably be
   // moved to a different scope, since we're now using it in multiple style
   // structs.
-  typedef nsStyleBackground::Position Position;
+  typedef nsStyleImageLayers::Position Position;
 
   // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
   // mBinding->mOriginPrincipal.
   RefPtr<mozilla::css::URLValue> mBinding;    // [reset]
   nsRect  mClip;                // [reset] offsets from upper-left border edge
   float   mOpacity;             // [reset]
   uint8_t mDisplay;             // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
   uint8_t mOriginalDisplay;     // [reset] saved mDisplay for position:absolute/fixed
@@ -3308,17 +3123,17 @@ public:
 
   int32_t GetFillRule() const { return mFillRule; }
   void SetFillRule(int32_t aFillRule)
   {
     NS_ASSERTION(mType == ePolygon, "expected polygon");
     mFillRule = aFillRule;
   }
 
-  typedef nsStyleBackground::Position Position;
+  typedef nsStyleImageLayers::Position Position;
   Position& GetPosition() {
     NS_ASSERTION(mType == eCircle || mType == eEllipse,
                  "expected circle or ellipse");
     return mPosition;
   }
   const Position& GetPosition() const {
     NS_ASSERTION(mType == eCircle || mType == eEllipse,
                  "expected circle or ellipse");
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -672,17 +672,17 @@ nsStyleUtil::IsSignificantChild(nsIConte
   return aTextIsSignificant && isText && aChild->TextLength() != 0 &&
          (aWhitespaceIsSignificant ||
           !aChild->TextIsOnlyWhitespace());
 }
 
 // For a replaced element whose concrete object size is no larger than the
 // element's content-box, this method checks whether the given
 // "object-position" coordinate might cause overflow in its dimension.
-typedef nsStyleBackground::Position::PositionCoord PositionCoord;
+typedef nsStyleImageLayers::Position::PositionCoord PositionCoord;
 static bool
 ObjectPositionCoordMightCauseOverflow(const PositionCoord& aCoord)
 {
   // Any nonzero length in "object-position" can push us to overflow
   // (particularly if our concrete object size is exactly the same size as the
   // replaced element's content-box).
   if (aCoord.mLength != 0) {
     return true;
@@ -710,17 +710,17 @@ nsStyleUtil::ObjectPropsMightCauseOverfl
       objectFit == NS_STYLE_OBJECT_FIT_NONE) {
     return true;
   }
   // (All other object-fit values produce a concrete object size that's no larger
   // than the constraint region.)
 
   // Check each of our "object-position" coords to see if it could cause
   // overflow in its dimension:
-  const nsStyleBackground::Position& objectPosistion = aStylePos->mObjectPosition;
+  const nsStyleImageLayers::Position& objectPosistion = aStylePos->mObjectPosition;
   if (ObjectPositionCoordMightCauseOverflow(objectPosistion.mXPosition) ||
       ObjectPositionCoordMightCauseOverflow(objectPosistion.mYPosition)) {
     return true;
   }
 
   return false;
 }
 
--- a/layout/tables/nsTablePainter.cpp
+++ b/layout/tables/nsTablePainter.cpp
@@ -117,19 +117,19 @@ TableBackgroundPainter::TableBackgroundD
 inline bool
 TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder() const
 {
   /* we only need accurate border data when positioning background images*/
   if (!mVisible) {
     return false;
   }
 
-  const nsStyleBackground *bg = mFrame->StyleBackground();
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
-    if (!bg->mLayers[i].mImage.IsEmpty())
+  const nsStyleImageLayers& layers = mFrame->StyleBackground()->mLayers;
+  NS_FOR_VISIBLE_IMAGELAYER_BACK_TO_FRONT(i, layers) {
+    if (!layers.mLayers[i].mImage.IsEmpty())
       return true;
   }
   return false;
 }
 
 void
 TableBackgroundPainter::TableBackgroundData::SetBCBorder(const nsMargin& aBorder)
 {