From 6e984b2b288a5f4acde4a90efd6e26a38592db75 Mon Sep 17 00:00:00 2001 From: "disttsc%bart.nl" Date: Thu, 15 Feb 2001 03:25:22 +0000 Subject: [PATCH] ``background-position not relative to padding edge when background-repeat is not 'no-repeat' [BG]''. bug=7039, author=Hixie,jag, r=jag,Hixie,dcone, moa=dcone, sr=buster --- layout/base/nsCSSRendering.cpp | 194 +++++++++++++++-------- layout/html/style/src/nsCSSRendering.cpp | 194 +++++++++++++++-------- 2 files changed, 260 insertions(+), 128 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index ae93759c22ce..a61f89a592e6 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2249,6 +2249,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } } + // Compute the anchor point. If it's a fixed background attachment, then // the image is placed relative to the viewport; otherwise, it's placed // relative to the element's padding area. @@ -2261,7 +2262,8 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, tileWidth, tileHeight, anchor); // If it's a fixed background attachment, then convert the anchor point - // to aForFrame's coordinate space + // to aForFrame's coordinate space, and move the padding area so that + // we can use the same logic for both the fixed and scrolling cases. if (NS_STYLE_BG_ATTACHMENT_FIXED == aColor.mBackgroundAttachment) { nsIView* view; @@ -2274,7 +2276,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, NS_ASSERTION(view, "expected a view"); while (view && (view != viewportView)) { nscoord x, y; - + view->GetPosition(&x, &y); anchor.x -= x; anchor.y -= y; @@ -2282,6 +2284,8 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, // Get the parent view view->GetParent(view); } + paddingArea.x = 0; + paddingArea.y = 0; } #if !defined(XP_UNIX) && !defined(XP_BEOS) @@ -2294,76 +2298,138 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, #endif // Compute the x and y starting points and limits for tiling + + /* An Overview Of The Following Logic + + A........ . . . . . . . . . . . . . . + : +---:-------.-------.-------.---- /|\ + : | : . . . | nh + :.......: . . . x . . . . . . . . . . \|/ + . | . . . . + . | . . ########### . + . . . . . . . . . .#. . . . .#. . . . + . | . . ########### . /|\ + . | . . . . | h + . . | . . . . . . . . . . . . . z . . \|/ + . | . . . . + |<-----nw------>| |<--w-->| + + ---- = the paddingArea edge. The padding is done relative to this + area. Outside the padding is the border. If the background + is positioned relative to the viewport ('fixed') then this + is the viewport edge. + + .... = the primary tile. + + . . = the other tiles. + + #### = the dirtyRect. This is the minimum region we want to cover. + + A = The anchor point. This is the point at which the tile should + start. Always negative or zero. + + x = x0 and y0 in the code. The point at which tiling must start + so that the fewest tiles are laid out while completly + covering the dirtyRect area. + + z = x1 and y1 in the code. The point at which tiling must end so + that the fewest tiles are laid out while completly covering + the dirtyRect area. + + w = the width of the tile (tileWidth). + + h = the height of the tile (tileHeight). + + n = the number of whole tiles that fit between 'A' and 'x'. + (the vertical n and the horizontal n are different) + + + Therefore, + + x0 = paddingArea.x + anchor.x + n * tileWidth; + + ...where n is an integer greater or equal to 0 fitting: + + n * tileWidth <= + dirtyRect.x - (paddingArea.x + anchor.x) <= + (n+1) * tileWidth + + ...i.e., + + n <= (dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth < n + 1 + + ...which, treating the division as an integer divide rounding down, gives: + + n = (dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth + + Substituting into the original expression for x0: + + x0 = paddingArea.x + anchor.x + + ((dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth) * + tileWidth; + + From this x1 is determined, + + x1 = x0 + m * tileWidth; + + ...where m is an integer greater than 0 fitting: + + (m - 1) * tileWidth < + dirtyRect.x + dirtyRect.width - x0 <= + m * tileWidth + + ...i.e., + + m - 1 < (dirtyRect.x + dirtyRect.width - x0) / tileWidth <= m + + ...which, treating the division as an integer divide, and making it + round up, gives: + + m = (dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth + + Substituting into the original expression for x1: + + x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / + tileWidth) * tileWidth + + The vertical case is analogous. If the background is fixed, then + paddingArea.x and paddingArea.y are set to zero when finding the parent + viewport, above. + + */ + + // first do the horizontal case nscoord x0, x1; - if (NS_STYLE_BG_ATTACHMENT_FIXED == aColor.mBackgroundAttachment) { - if (NS_STYLE_BG_REPEAT_X & repeat) { - x0 = ((dirtyRect.x - anchor.x) / tileWidth) * tileWidth + anchor.x; - x1 = x0 + xDistance + tileWidth; - if (0 != anchor.x) { - x1 += tileWidth; - } - } - else { - // For fixed attachment, the anchor is relative to the nearest scrolling - // ancestor (or the viewport) - x0 = anchor.x; - x1 = x0 + tileWidth; - } + if (repeat & NS_STYLE_BG_REPEAT_X) { + // When tiling in the x direction, adjust the starting position of the + // tile to account for dirtyRect.x. When tiling in x, the anchor.x value + // will be a negative value used to adjust the starting coordinate. + x0 = paddingArea.x + anchor.x + ((dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth) * tileWidth; + x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth) * tileWidth; } else { - if (NS_STYLE_BG_REPEAT_X & repeat) { - // When tiling in the x direction, adjust the starting position of the - // tile to account for dirtyRect.x. When tiling in x, the anchor.x value - // will be a negative value used to adjust the starting coordinate. - x0 = (dirtyRect.x / tileWidth) * tileWidth + anchor.x; - if(x0+tileWidthGetPosition(&x, &y); anchor.x -= x; anchor.y -= y; @@ -2282,6 +2284,8 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, // Get the parent view view->GetParent(view); } + paddingArea.x = 0; + paddingArea.y = 0; } #if !defined(XP_UNIX) && !defined(XP_BEOS) @@ -2294,76 +2298,138 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, #endif // Compute the x and y starting points and limits for tiling + + /* An Overview Of The Following Logic + + A........ . . . . . . . . . . . . . . + : +---:-------.-------.-------.---- /|\ + : | : . . . | nh + :.......: . . . x . . . . . . . . . . \|/ + . | . . . . + . | . . ########### . + . . . . . . . . . .#. . . . .#. . . . + . | . . ########### . /|\ + . | . . . . | h + . . | . . . . . . . . . . . . . z . . \|/ + . | . . . . + |<-----nw------>| |<--w-->| + + ---- = the paddingArea edge. The padding is done relative to this + area. Outside the padding is the border. If the background + is positioned relative to the viewport ('fixed') then this + is the viewport edge. + + .... = the primary tile. + + . . = the other tiles. + + #### = the dirtyRect. This is the minimum region we want to cover. + + A = The anchor point. This is the point at which the tile should + start. Always negative or zero. + + x = x0 and y0 in the code. The point at which tiling must start + so that the fewest tiles are laid out while completly + covering the dirtyRect area. + + z = x1 and y1 in the code. The point at which tiling must end so + that the fewest tiles are laid out while completly covering + the dirtyRect area. + + w = the width of the tile (tileWidth). + + h = the height of the tile (tileHeight). + + n = the number of whole tiles that fit between 'A' and 'x'. + (the vertical n and the horizontal n are different) + + + Therefore, + + x0 = paddingArea.x + anchor.x + n * tileWidth; + + ...where n is an integer greater or equal to 0 fitting: + + n * tileWidth <= + dirtyRect.x - (paddingArea.x + anchor.x) <= + (n+1) * tileWidth + + ...i.e., + + n <= (dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth < n + 1 + + ...which, treating the division as an integer divide rounding down, gives: + + n = (dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth + + Substituting into the original expression for x0: + + x0 = paddingArea.x + anchor.x + + ((dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth) * + tileWidth; + + From this x1 is determined, + + x1 = x0 + m * tileWidth; + + ...where m is an integer greater than 0 fitting: + + (m - 1) * tileWidth < + dirtyRect.x + dirtyRect.width - x0 <= + m * tileWidth + + ...i.e., + + m - 1 < (dirtyRect.x + dirtyRect.width - x0) / tileWidth <= m + + ...which, treating the division as an integer divide, and making it + round up, gives: + + m = (dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth + + Substituting into the original expression for x1: + + x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / + tileWidth) * tileWidth + + The vertical case is analogous. If the background is fixed, then + paddingArea.x and paddingArea.y are set to zero when finding the parent + viewport, above. + + */ + + // first do the horizontal case nscoord x0, x1; - if (NS_STYLE_BG_ATTACHMENT_FIXED == aColor.mBackgroundAttachment) { - if (NS_STYLE_BG_REPEAT_X & repeat) { - x0 = ((dirtyRect.x - anchor.x) / tileWidth) * tileWidth + anchor.x; - x1 = x0 + xDistance + tileWidth; - if (0 != anchor.x) { - x1 += tileWidth; - } - } - else { - // For fixed attachment, the anchor is relative to the nearest scrolling - // ancestor (or the viewport) - x0 = anchor.x; - x1 = x0 + tileWidth; - } + if (repeat & NS_STYLE_BG_REPEAT_X) { + // When tiling in the x direction, adjust the starting position of the + // tile to account for dirtyRect.x. When tiling in x, the anchor.x value + // will be a negative value used to adjust the starting coordinate. + x0 = paddingArea.x + anchor.x + ((dirtyRect.x - (paddingArea.x + anchor.x)) / tileWidth) * tileWidth; + x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth) * tileWidth; } else { - if (NS_STYLE_BG_REPEAT_X & repeat) { - // When tiling in the x direction, adjust the starting position of the - // tile to account for dirtyRect.x. When tiling in x, the anchor.x value - // will be a negative value used to adjust the starting coordinate. - x0 = (dirtyRect.x / tileWidth) * tileWidth + anchor.x; - if(x0+tileWidth