From 71db1509d5ab7d74626b7ca13511fece50f7d0ec Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Fri, 20 Feb 2009 16:33:30 +1300 Subject: [PATCH] Bug 477732: fix scaling of border-image side tiles with 'repeat'. r+sr=roc --- layout/base/nsCSSRendering.cpp | 102 ++++++++++-------- layout/reftests/border-image/reftest.list | 2 + .../reftests/border-image/roundrectbutton.png | Bin 0 -> 188 bytes .../border-image/side-scaling-1h-ref.html | 28 +++++ .../border-image/side-scaling-1h.html | 28 +++++ .../border-image/side-scaling-1v-ref.html | 28 +++++ .../border-image/side-scaling-1v.html | 28 +++++ 7 files changed, 171 insertions(+), 45 deletions(-) create mode 100644 layout/reftests/border-image/roundrectbutton.png create mode 100644 layout/reftests/border-image/side-scaling-1h-ref.html create mode 100644 layout/reftests/border-image/side-scaling-1h.html create mode 100644 layout/reftests/border-image/side-scaling-1v-ref.html create mode 100644 layout/reftests/border-image/side-scaling-1v.html diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 7723c3078168..54ae91257c40 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -1802,33 +1802,6 @@ DrawBorderImage(nsPresContext* aPresContext, nsMargin border(aBorderStyle.GetActualBorder()); - // Compute the special scale factors for the middle component. - // Step 1 of the scaling algorithm in css3-background section 4.4, - // fourth bullet point: - // The middle image's width is scaled by the same factor as - // the top image unless that factor is zero or infinity, in - // which case the scaling factor of the bottom is substituted, - // and failing that, the width is not scaled. The height of - // the middle image is scaled by the same factor as the left - // image unless that factor is zero or infinity, in which case - // the scaling factor of the right image is substituted, and - // failing that, the height is not scaled. - gfxFloat hFactor, vFactor; - - if (0 < border.left && 0 < split.left) - vFactor = gfxFloat(border.left)/split.left; - else if (0 < border.right && 0 < split.right) - vFactor = gfxFloat(border.right)/split.right; - else - vFactor = 1.0; - - if (0 < border.top && 0 < split.top) - hFactor = gfxFloat(border.top)/split.top; - else if (0 < border.bottom && 0 < split.bottom) - hFactor = gfxFloat(border.bottom)/split.bottom; - else - hFactor = 1.0; - // These helper tables recharacterize the 'split' and 'border' margins // in a more convenient form: they are the x/y/width/height coords // required for various bands of the border, and they have been transformed @@ -1884,31 +1857,68 @@ DrawBorderImage(nsPresContext* aPresContext, nsRect destArea(borderX[i], borderY[j], borderWidth[i], borderHeight[j]); nsIntRect subArea(splitX[i], splitY[j], splitWidth[i], splitHeight[j]); - // Corners are always stretched to fit the corner. - // Sides are always stretched to the thickness of their border. - PRUint8 fillStyleH = (i == 1 - ? aBorderStyle.mBorderImageHFill - : NS_STYLE_BORDER_IMAGE_STRETCH); - PRUint8 fillStyleV = (j == 1 - ? aBorderStyle.mBorderImageVFill - : NS_STYLE_BORDER_IMAGE_STRETCH); - - // For everything except the middle, whichever axis is always - // stretched determines the size of the 'unit square' for tiling. - // The middle uses the special scale factors calculated above. + PRUint8 fillStyleH, fillStyleV; nsSize unitSize; + if (i == MIDDLE && j == MIDDLE) { + // css-background: + // The middle image's width is scaled by the same factor as + // the top image unless that factor is zero or infinity, in + // which case the scaling factor of the bottom is substituted, + // and failing that, the width is not scaled. The height of + // the middle image is scaled by the same factor as the left + // image unless that factor is zero or infinity, in which case + // the scaling factor of the right image is substituted, and + // failing that, the height is not scaled. + gfxFloat hFactor, vFactor; + + if (0 < border.left && 0 < split.left) + vFactor = gfxFloat(border.left)/split.left; + else if (0 < border.right && 0 < split.right) + vFactor = gfxFloat(border.right)/split.right; + else + vFactor = 1.0; + + if (0 < border.top && 0 < split.top) + hFactor = gfxFloat(border.top)/split.top; + else if (0 < border.bottom && 0 < split.bottom) + hFactor = gfxFloat(border.bottom)/split.bottom; + else + hFactor = 1.0; + unitSize.width = splitWidth[i]*hFactor; unitSize.height = splitHeight[j]*vFactor; - } else if (i == MIDDLE) { - unitSize.width = borderHeight[j]; + fillStyleH = aBorderStyle.mBorderImageHFill; + fillStyleV = aBorderStyle.mBorderImageVFill; + + } else if (i == MIDDLE) { // top, bottom + // Sides are always stretched to the thickness of their border, + // and stretched proportionately on the other axis. + gfxFloat factor = 1.0; + if (0 < borderHeight[j] && 0 < splitHeight[j]) + factor = gfxFloat(borderHeight[j])/splitHeight[j]; + + unitSize.width = splitWidth[i]*factor; unitSize.height = borderHeight[j]; - } else if (j == MIDDLE) { + fillStyleH = aBorderStyle.mBorderImageHFill; + fillStyleV = NS_STYLE_BORDER_IMAGE_STRETCH; + + } else if (j == MIDDLE) { // left, right + gfxFloat factor = 1.0; + if (0 < borderWidth[i] && 0 < splitWidth[i]) + factor = gfxFloat(borderWidth[i])/splitWidth[i]; + unitSize.width = borderWidth[i]; - unitSize.height = borderWidth[i]; + unitSize.height = splitHeight[j]*factor; + fillStyleH = NS_STYLE_BORDER_IMAGE_STRETCH; + fillStyleV = aBorderStyle.mBorderImageVFill; + } else { + // Corners are always stretched to fit the corner. unitSize.width = borderWidth[i]; unitSize.height = borderHeight[j]; + fillStyleH = NS_STYLE_BORDER_IMAGE_STRETCH; + fillStyleV = NS_STYLE_BORDER_IMAGE_STRETCH; } DrawBorderImageComponent(aRenderingContext, img, aDirtyRect, @@ -1937,8 +1947,10 @@ DrawBorderImageComponent(nsIRenderingContext& aRenderingContext, // If we have no tiling in either direction, we can skip the intermediate // scaling step. - if (aHFill == NS_STYLE_BORDER_IMAGE_STRETCH && - aVFill == NS_STYLE_BORDER_IMAGE_STRETCH) { + if ((aHFill == NS_STYLE_BORDER_IMAGE_STRETCH && + aVFill == NS_STYLE_BORDER_IMAGE_STRETCH) || + (aUnitSize.width == aFill.width && + aUnitSize.height == aFill.height)) { nsLayoutUtils::DrawSingleImage(&aRenderingContext, subImage, aFill, aDirtyRect); return; diff --git a/layout/reftests/border-image/reftest.list b/layout/reftests/border-image/reftest.list index d91162765bf4..fbf5f63b10cc 100644 --- a/layout/reftests/border-image/reftest.list +++ b/layout/reftests/border-image/reftest.list @@ -14,3 +14,5 @@ == center-scaling-1.html center-scaling-1-ref.html == center-scaling-2.html center-scaling-2-ref.html == center-scaling-3.html center-scaling-3-ref.html +== side-scaling-1h.html side-scaling-1h-ref.html +== side-scaling-1v.html side-scaling-1v-ref.html diff --git a/layout/reftests/border-image/roundrectbutton.png b/layout/reftests/border-image/roundrectbutton.png new file mode 100644 index 0000000000000000000000000000000000000000..c194fdc5fbcbb8107bc39c6158bce40f9018a82e GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp@KrF!lBp6s`YjgmqW=|K#5Q)plKhHO?L`X>Jy{qCC zNfIf&%>GF)k1seeCE-VXx@fZ<_u+Q|OY0Rvy%x@H+!J0@uQ2OL9AoIe|Ln$(?N3ax z*GT*4_VDi^BO}OJp00i_>zopr0MIi;lK=n! literal 0 HcmV?d00001 diff --git a/layout/reftests/border-image/side-scaling-1h-ref.html b/layout/reftests/border-image/side-scaling-1h-ref.html new file mode 100644 index 000000000000..3bf2b64e0d32 --- /dev/null +++ b/layout/reftests/border-image/side-scaling-1h-ref.html @@ -0,0 +1,28 @@ + + +border-image: repeat with zero-height top and bottom +<style> +span { + display: inline-block; + margin: 10px; + -moz-box-sizing: border-box; + height: 24px; + border-style: solid; + border-color: transparent; + border-width: 0 6px; + -moz-border-image: url("roundrectbutton.png") 0 6 repeat stretch; +} +</style> +</head><body> +<p> +<span style="width:12px"></span> +<span style="width:13px"></span> +<span style="width:14px"></span> +<span style="width:16px"></span> +<span style="width:18px"></span> +<span style="width:20px"></span> +<span style="width:25px"></span> +<span style="width:30px"></span> +<span style="width:40px"></span> +</p> +</body></html> diff --git a/layout/reftests/border-image/side-scaling-1h.html b/layout/reftests/border-image/side-scaling-1h.html new file mode 100644 index 000000000000..453ab9b7fabf --- /dev/null +++ b/layout/reftests/border-image/side-scaling-1h.html @@ -0,0 +1,28 @@ +<!doctype html> +<html><head> +<title>border-image: repeat with zero-height top and bottom +<style> +span { + display: inline-block; + margin: 10px; + -moz-box-sizing: border-box; + height: 24px; + border-style: solid; + border-color: transparent; + border-width: 0 6px; + -moz-border-image: url("roundrectbutton.png") 0 6 repeat; +} +</style> +</head><body> +<p> +<span style="width:12px"></span> +<span style="width:13px"></span> +<span style="width:14px"></span> +<span style="width:16px"></span> +<span style="width:18px"></span> +<span style="width:20px"></span> +<span style="width:25px"></span> +<span style="width:30px"></span> +<span style="width:40px"></span> +</p> +</body></html> diff --git a/layout/reftests/border-image/side-scaling-1v-ref.html b/layout/reftests/border-image/side-scaling-1v-ref.html new file mode 100644 index 000000000000..577be6e7af67 --- /dev/null +++ b/layout/reftests/border-image/side-scaling-1v-ref.html @@ -0,0 +1,28 @@ +<!doctype html> +<html><head> +<title>border-image: repeat with zero-width left and right +<style> +span { + display: inline-block; + margin: 5px; + -moz-box-sizing: border-box; + width: 13px; + border-style: solid; + border-color: transparent; + border-width: 10px 0; + -moz-border-image: url("roundrectbutton.png") 10 0 stretch repeat; +} +</style> +</head><body> +<p> +<span style="height:24px"></span> +<span style="height:25px"></span> +<span style="height:26px"></span> +<span style="height:27px"></span> +<span style="height:28px"></span> +<span style="height:30px"></span> +<span style="height:35px"></span> +<span style="height:40px"></span> +<span style="height:50px"></span> +</p> +</body></html> diff --git a/layout/reftests/border-image/side-scaling-1v.html b/layout/reftests/border-image/side-scaling-1v.html new file mode 100644 index 000000000000..79e9b3737f8c --- /dev/null +++ b/layout/reftests/border-image/side-scaling-1v.html @@ -0,0 +1,28 @@ +<!doctype html> +<html><head> +<title>border-image: repeat with zero-width left and right +<style> +span { + display: inline-block; + margin: 5px; + -moz-box-sizing: border-box; + width: 13px; + border-style: solid; + border-color: transparent; + border-width: 10px 0; + -moz-border-image: url("roundrectbutton.png") 10 0 repeat; +} +</style> +</head><body> +<p> +<span style="height:24px"></span> +<span style="height:25px"></span> +<span style="height:26px"></span> +<span style="height:27px"></span> +<span style="height:28px"></span> +<span style="height:30px"></span> +<span style="height:35px"></span> +<span style="height:40px"></span> +<span style="height:50px"></span> +</p> +</body></html>