Bug 477732: fix scaling of border-image side tiles with 'repeat'. r+sr=roc

This commit is contained in:
Zack Weinberg 2009-02-20 16:33:30 +13:00
parent 1612056e74
commit 71db1509d5
7 changed files with 171 additions and 45 deletions

View File

@ -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;

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

View File

@ -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 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>