Bug 310124 Double border is incorrectly compressed when rendered; regression. original idea by Takeshi Ichimaru <ayakawa.m@gmail.com> r+sr=roc

This commit is contained in:
masayuki%d-toybox.com 2005-11-30 13:26:34 +00:00
parent 856897abff
commit a3cbff90e5

View File

@ -22,6 +22,8 @@
* *
* Contributor(s): * Contributor(s):
* Mats Palmgren <mats.palmgren@bredband.net> * Mats Palmgren <mats.palmgren@bredband.net>
* Takeshi Ichimaru <ayakawa.m@gmail.com>
* Masayuki Nakano <masayuki@d-toybox.com>
* *
* Alternatively, the contents of this file may be used under the terms of * Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"), * either of the GNU General Public License Version 2 or later (the "GPL"),
@ -341,6 +343,9 @@ nscolor nsCSSRendering::MakeBevelColor(PRIntn whichSide, PRUint8 style,
// Maximum poly points in any of the polygons we generate below // Maximum poly points in any of the polygons we generate below
#define MAX_POLY_POINTS 4 #define MAX_POLY_POINTS 4
#define ACTUAL_THICKNESS(outside, inside, frac, tpp) \
(NSToCoordRound(((outside) - (inside)) * (frac) / (tpp)) * (tpp))
// a nifty helper function to create a polygon representing a // a nifty helper function to create a polygon representing a
// particular side of a border. This helps localize code for figuring // particular side of a border. This helps localize code for figuring
// mitered edges. It is mainly used by the solid, inset, and outset // mitered edges. It is mainly used by the solid, inset, and outset
@ -350,17 +355,13 @@ nscolor nsCSSRendering::MakeBevelColor(PRIntn whichSide, PRUint8 style,
// is one pixel), then a line with two endpoints is returned // is one pixel), then a line with two endpoints is returned
PRIntn nsCSSRendering::MakeSide(nsPoint aPoints[], PRIntn nsCSSRendering::MakeSide(nsPoint aPoints[],
nsIRenderingContext& aContext, nsIRenderingContext& aContext,
PRIntn whichSide, PRIntn aWhichSide,
const nsRect& outside, const nsRect& inside, const nsRect& aOutside, const nsRect& aInside,
PRIntn aSkipSides, PRIntn aSkipSides,
PRIntn borderPart, float borderFrac, PRIntn aBorderPart, float aBorderFrac,
nscoord twipsPerPixel) nscoord aTwipsPerPixel)
{ {
float borderRest = 1.0f - borderFrac; nscoord outsideEdge, insideEdge, outsideTL, insideTL, outsideBR, insideBR;
PRIntn np = 0;
nscoord thickness, outsideEdge, insideEdge, outsideTL, insideTL, outsideBR,
insideBR;
// Initialize the following six nscoord's: // Initialize the following six nscoord's:
// outsideEdge, insideEdge, outsideTL, insideTL, outsideBR, insideBR // outsideEdge, insideEdge, outsideTL, insideTL, outsideBR, insideBR
@ -378,52 +379,52 @@ PRIntn nsCSSRendering::MakeSide(nsPoint aPoints[],
// if we don't want the bevel, we'll get rid of it later by setting // if we don't want the bevel, we'll get rid of it later by setting
// outsideXX to insideXX // outsideXX to insideXX
switch (whichSide) { switch (aWhichSide) {
case NS_SIDE_TOP: case NS_SIDE_TOP:
// the TL points are the left end; the BR points are the right end // the TL points are the left end; the BR points are the right end
outsideEdge = outside.y; outsideEdge = aOutside.y;
insideEdge = inside.y; insideEdge = aInside.y;
outsideTL = outside.x; outsideTL = aOutside.x;
insideTL = inside.x; insideTL = aInside.x;
insideBR = inside.XMost(); insideBR = aInside.XMost();
outsideBR = outside.XMost(); outsideBR = aOutside.XMost();
break; break;
case NS_SIDE_BOTTOM: case NS_SIDE_BOTTOM:
// the TL points are the left end; the BR points are the right end // the TL points are the left end; the BR points are the right end
outsideEdge = outside.YMost(); outsideEdge = aOutside.YMost();
insideEdge = inside.YMost(); insideEdge = aInside.YMost();
outsideTL = outside.x; outsideTL = aOutside.x;
insideTL = inside.x; insideTL = aInside.x;
insideBR = inside.XMost(); insideBR = aInside.XMost();
outsideBR = outside.XMost(); outsideBR = aOutside.XMost();
break; break;
case NS_SIDE_LEFT: case NS_SIDE_LEFT:
// the TL points are the top end; the BR points are the bottom end // the TL points are the top end; the BR points are the bottom end
outsideEdge = outside.x; outsideEdge = aOutside.x;
insideEdge = inside.x; insideEdge = aInside.x;
outsideTL = outside.y; outsideTL = aOutside.y;
insideTL = inside.y; insideTL = aInside.y;
insideBR = inside.YMost(); insideBR = aInside.YMost();
outsideBR = outside.YMost(); outsideBR = aOutside.YMost();
break; break;
default: default:
NS_ASSERTION(whichSide == NS_SIDE_RIGHT, "whichSide is not a valid side"); NS_ASSERTION(aWhichSide == NS_SIDE_RIGHT, "aWhichSide is not a valid side");
// the TL points are the top end; the BR points are the bottom end // the TL points are the top end; the BR points are the bottom end
outsideEdge = outside.XMost(); outsideEdge = aOutside.XMost();
insideEdge = inside.XMost(); insideEdge = aInside.XMost();
outsideTL = outside.y; outsideTL = aOutside.y;
insideTL = inside.y; insideTL = aInside.y;
insideBR = inside.YMost(); insideBR = aInside.YMost();
outsideBR = outside.YMost(); outsideBR = aOutside.YMost();
break; break;
} }
// Don't draw the bevels if an adjacent side is skipped // Don't draw the bevels if an adjacent side is skipped
if ( (whichSide == NS_SIDE_TOP) || (whichSide == NS_SIDE_BOTTOM) ) { if ( (aWhichSide == NS_SIDE_TOP) || (aWhichSide == NS_SIDE_BOTTOM) ) {
// a top or bottom side // a top or bottom side
if ((1<<NS_SIDE_LEFT) & aSkipSides) { if ((1<<NS_SIDE_LEFT) & aSkipSides) {
insideTL = outsideTL; insideTL = outsideTL;
@ -441,55 +442,75 @@ PRIntn nsCSSRendering::MakeSide(nsPoint aPoints[],
} }
} }
// move things around when only drawing part of the border nscoord fullThickness;
if (aWhichSide == NS_SIDE_TOP || aWhichSide == NS_SIDE_LEFT)
fullThickness = insideEdge - outsideEdge;
else
fullThickness = outsideEdge - insideEdge;
if (fullThickness != 0)
fullThickness = NS_MAX(fullThickness, aTwipsPerPixel);
if (borderPart == BORDER_INSIDE) { nscoord thickness = fullThickness;
outsideEdge = nscoord(outsideEdge * borderFrac + insideEdge * borderRest); if (aBorderFrac != 1.0f && fullThickness != 0) {
outsideTL = nscoord(outsideTL * borderFrac + insideTL * borderRest); thickness = aTwipsPerPixel *
outsideBR = nscoord(outsideBR * borderFrac + insideBR * borderRest); NS_MAX(NSToCoordRound(fullThickness * aBorderFrac / aTwipsPerPixel), 1);
} else if (borderPart == BORDER_OUTSIDE ) { if ((aWhichSide == NS_SIDE_TOP) || (aWhichSide == NS_SIDE_LEFT)) {
insideEdge = nscoord(insideEdge * borderFrac + outsideEdge * borderRest); if (aBorderPart == BORDER_INSIDE)
insideTL = nscoord(insideTL * borderFrac + outsideTL * borderRest); outsideEdge = insideEdge - thickness;
insideBR = nscoord(insideBR * borderFrac + outsideBR * borderRest); else if (aBorderPart == BORDER_OUTSIDE)
insideEdge = outsideEdge + thickness;
} else {
if (aBorderPart == BORDER_INSIDE)
outsideEdge = insideEdge + thickness;
else if (aBorderPart == BORDER_OUTSIDE)
insideEdge = outsideEdge - thickness;
}
float actualFrac = (float)thickness / (float)fullThickness;
if (aBorderPart == BORDER_INSIDE) {
outsideTL = insideTL +
ACTUAL_THICKNESS(outsideTL, insideTL, actualFrac, aTwipsPerPixel);
outsideBR = insideBR +
ACTUAL_THICKNESS(outsideBR, insideBR, actualFrac, aTwipsPerPixel);
} else if (aBorderPart == BORDER_OUTSIDE) {
insideTL = outsideTL -
ACTUAL_THICKNESS(outsideTL, insideTL, actualFrac, aTwipsPerPixel);
insideBR = outsideBR -
ACTUAL_THICKNESS(outsideBR, insideBR, actualFrac, aTwipsPerPixel);
}
} }
// Base our thickness check on the segment being less than a pixel and 1/2 // Base our thickness check on the segment being less than a pixel and 1/2
twipsPerPixel += twipsPerPixel >> 2; aTwipsPerPixel += aTwipsPerPixel >> 2;
// find the thickness of the piece being drawn
if ((whichSide == NS_SIDE_TOP) || (whichSide == NS_SIDE_LEFT)) {
thickness = insideEdge - outsideEdge;
} else {
thickness = outsideEdge - insideEdge;
}
// if returning a line, do it along inside edge for bottom or right borders // if returning a line, do it along inside edge for bottom or right borders
// so that it's in the same place as it would be with polygons (why?) // so that it's in the same place as it would be with polygons (why?)
// XXX The previous version of the code shortened the right border too. // XXX The previous version of the code shortened the right border too.
if ( !((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL)) && if ( !((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) &&
((whichSide == NS_SIDE_BOTTOM) || (whichSide == NS_SIDE_RIGHT))) { ((aWhichSide == NS_SIDE_BOTTOM) || (aWhichSide == NS_SIDE_RIGHT))) {
outsideEdge = insideEdge; outsideEdge = insideEdge;
} }
// return the appropriate line or trapezoid // return the appropriate line or trapezoid
if ((whichSide == NS_SIDE_TOP) || (whichSide == NS_SIDE_BOTTOM)) { PRIntn np = 0;
if ((aWhichSide == NS_SIDE_TOP) || (aWhichSide == NS_SIDE_BOTTOM)) {
// top and bottom borders // top and bottom borders
aPoints[np++].MoveTo(outsideTL,outsideEdge); aPoints[np++].MoveTo(outsideTL,outsideEdge);
aPoints[np++].MoveTo(outsideBR,outsideEdge); aPoints[np++].MoveTo(outsideBR,outsideEdge);
// XXX Making this condition only (thickness >= twipsPerPixel) will // XXX Making this condition only (thickness >= aTwipsPerPixel) will
// improve double borders and some cases of groove/ridge, // improve double borders and some cases of groove/ridge,
// but will cause problems with table borders. See last and third // but will cause problems with table borders. See last and third
// from last tests in test4.htm // from last tests in test4.htm
// Doing it this way emulates the old behavior. It might be worth // Doing it this way emulates the old behavior. It might be worth
// fixing. // fixing.
if ((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL) ) { if ((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) {
aPoints[np++].MoveTo(insideBR,insideEdge); aPoints[np++].MoveTo(insideBR,insideEdge);
aPoints[np++].MoveTo(insideTL,insideEdge); aPoints[np++].MoveTo(insideTL,insideEdge);
} }
} else { } else {
// right and left borders // right and left borders
// XXX Ditto above // XXX Ditto above
if ((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL) ) { if ((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) {
aPoints[np++].MoveTo(insideEdge,insideBR); aPoints[np++].MoveTo(insideEdge,insideBR);
aPoints[np++].MoveTo(insideEdge,insideTL); aPoints[np++].MoveTo(insideEdge,insideTL);
} }
@ -1803,10 +1824,11 @@ void nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
for (cnt = 0; cnt < 4; cnt++) { for (cnt = 0; cnt < 4; cnt++) {
PRUint8 side = sideOrder[cnt]; PRUint8 side = sideOrder[cnt];
// If a side needs a double/groove/ridge border but will be less than two
// If a side needs a double border but will be less than two pixels, // pixels, force it to be solid (see bug 1781 and bug 310124).
// force it to be solid (see bug 1781). if (aBorderStyle.GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_DOUBLE ||
if (aBorderStyle.GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_DOUBLE) { aBorderStyle.GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_GROOVE ||
aBorderStyle.GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_RIDGE) {
nscoord widths[] = { border.top, border.right, border.bottom, border.left }; nscoord widths[] = { border.top, border.right, border.bottom, border.left };
forceSolid = (widths[side]/twipsPerPixel < 2); forceSolid = (widths[side]/twipsPerPixel < 2);
} else } else