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):
* 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
* 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
#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
// particular side of a border. This helps localize code for figuring
// 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
PRIntn nsCSSRendering::MakeSide(nsPoint aPoints[],
nsIRenderingContext& aContext,
PRIntn whichSide,
const nsRect& outside, const nsRect& inside,
PRIntn aWhichSide,
const nsRect& aOutside, const nsRect& aInside,
PRIntn aSkipSides,
PRIntn borderPart, float borderFrac,
nscoord twipsPerPixel)
PRIntn aBorderPart, float aBorderFrac,
nscoord aTwipsPerPixel)
{
float borderRest = 1.0f - borderFrac;
PRIntn np = 0;
nscoord thickness, outsideEdge, insideEdge, outsideTL, insideTL, outsideBR,
insideBR;
nscoord outsideEdge, insideEdge, outsideTL, insideTL, outsideBR, insideBR;
// Initialize the following six nscoord's:
// 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
// outsideXX to insideXX
switch (whichSide) {
switch (aWhichSide) {
case NS_SIDE_TOP:
// the TL points are the left end; the BR points are the right end
outsideEdge = outside.y;
insideEdge = inside.y;
outsideTL = outside.x;
insideTL = inside.x;
insideBR = inside.XMost();
outsideBR = outside.XMost();
outsideEdge = aOutside.y;
insideEdge = aInside.y;
outsideTL = aOutside.x;
insideTL = aInside.x;
insideBR = aInside.XMost();
outsideBR = aOutside.XMost();
break;
case NS_SIDE_BOTTOM:
// the TL points are the left end; the BR points are the right end
outsideEdge = outside.YMost();
insideEdge = inside.YMost();
outsideTL = outside.x;
insideTL = inside.x;
insideBR = inside.XMost();
outsideBR = outside.XMost();
outsideEdge = aOutside.YMost();
insideEdge = aInside.YMost();
outsideTL = aOutside.x;
insideTL = aInside.x;
insideBR = aInside.XMost();
outsideBR = aOutside.XMost();
break;
case NS_SIDE_LEFT:
// the TL points are the top end; the BR points are the bottom end
outsideEdge = outside.x;
insideEdge = inside.x;
outsideTL = outside.y;
insideTL = inside.y;
insideBR = inside.YMost();
outsideBR = outside.YMost();
outsideEdge = aOutside.x;
insideEdge = aInside.x;
outsideTL = aOutside.y;
insideTL = aInside.y;
insideBR = aInside.YMost();
outsideBR = aOutside.YMost();
break;
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
outsideEdge = outside.XMost();
insideEdge = inside.XMost();
outsideTL = outside.y;
insideTL = inside.y;
insideBR = inside.YMost();
outsideBR = outside.YMost();
outsideEdge = aOutside.XMost();
insideEdge = aInside.XMost();
outsideTL = aOutside.y;
insideTL = aInside.y;
insideBR = aInside.YMost();
outsideBR = aOutside.YMost();
break;
}
// 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
if ((1<<NS_SIDE_LEFT) & aSkipSides) {
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) {
outsideEdge = nscoord(outsideEdge * borderFrac + insideEdge * borderRest);
outsideTL = nscoord(outsideTL * borderFrac + insideTL * borderRest);
outsideBR = nscoord(outsideBR * borderFrac + insideBR * borderRest);
} else if (borderPart == BORDER_OUTSIDE ) {
insideEdge = nscoord(insideEdge * borderFrac + outsideEdge * borderRest);
insideTL = nscoord(insideTL * borderFrac + outsideTL * borderRest);
insideBR = nscoord(insideBR * borderFrac + outsideBR * borderRest);
nscoord thickness = fullThickness;
if (aBorderFrac != 1.0f && fullThickness != 0) {
thickness = aTwipsPerPixel *
NS_MAX(NSToCoordRound(fullThickness * aBorderFrac / aTwipsPerPixel), 1);
if ((aWhichSide == NS_SIDE_TOP) || (aWhichSide == NS_SIDE_LEFT)) {
if (aBorderPart == BORDER_INSIDE)
outsideEdge = insideEdge - thickness;
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
twipsPerPixel += twipsPerPixel >> 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;
}
aTwipsPerPixel += aTwipsPerPixel >> 2;
// 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?)
// XXX The previous version of the code shortened the right border too.
if ( !((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL)) &&
((whichSide == NS_SIDE_BOTTOM) || (whichSide == NS_SIDE_RIGHT))) {
if ( !((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) &&
((aWhichSide == NS_SIDE_BOTTOM) || (aWhichSide == NS_SIDE_RIGHT))) {
outsideEdge = insideEdge;
}
// 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
aPoints[np++].MoveTo(outsideTL,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,
// but will cause problems with table borders. See last and third
// from last tests in test4.htm
// Doing it this way emulates the old behavior. It might be worth
// fixing.
if ((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL) ) {
if ((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) {
aPoints[np++].MoveTo(insideBR,insideEdge);
aPoints[np++].MoveTo(insideTL,insideEdge);
}
} else {
// right and left borders
// XXX Ditto above
if ((thickness >= twipsPerPixel) || (borderPart != BORDER_FULL) ) {
if ((thickness >= aTwipsPerPixel) || (aBorderPart != BORDER_FULL)) {
aPoints[np++].MoveTo(insideEdge,insideBR);
aPoints[np++].MoveTo(insideEdge,insideTL);
}
@ -1803,10 +1824,11 @@ void nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
for (cnt = 0; cnt < 4; cnt++) {
PRUint8 side = sideOrder[cnt];
// If a side needs a double border but will be less than two pixels,
// force it to be solid (see bug 1781).
if (aBorderStyle.GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_DOUBLE) {
// If a side needs a double/groove/ridge border but will be less than two
// pixels, force it to be solid (see bug 1781 and bug 310124).
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 };
forceSolid = (widths[side]/twipsPerPixel < 2);
} else