b=382613, moz-border-radius of background color isn't clamped to 50%, r+sr=roc

This commit is contained in:
vladimir@pobox.com 2007-07-18 07:14:53 -07:00
parent 2c5bdcd53e
commit 66b946a260
2 changed files with 77 additions and 153 deletions

View File

@ -2174,6 +2174,64 @@ DrawBorderSides(gfxContext *ctx, // The content to render to
#endif
}
/*
* Compute the float-pixel radii that should be used for drawing
* this border/outline, given the various input bits.
*
* If a side is skipped via skipSides, its corners are forced to 0,
* otherwise the resulting radius is the smaller of the specified
* radius and half of each adjacent side's length.
*/
static void
ComputePixelRadii(const nscoord *aTwipsRadii,
const nsRect& outerRect,
const nsMargin& borderMargin,
PRIntn skipSides,
nscoord twipsPerPixel,
gfxFloat *oBorderRadii)
{
nscoord twipsRadii[4] = { aTwipsRadii[0], aTwipsRadii[1], aTwipsRadii[2], aTwipsRadii[3] };
nsMargin border(borderMargin);
if (skipSides & SIDE_BIT_TOP) {
border.top = 0;
twipsRadii[C_TL] = 0;
twipsRadii[C_TR] = 0;
}
if (skipSides & SIDE_BIT_RIGHT) {
border.right = 0;
twipsRadii[C_TR] = 0;
twipsRadii[C_BR] = 0;
}
if (skipSides & SIDE_BIT_BOTTOM) {
border.bottom = 0;
twipsRadii[C_BR] = 0;
twipsRadii[C_BL] = 0;
}
if (skipSides & SIDE_BIT_LEFT) {
border.left = 0;
twipsRadii[C_BL] = 0;
twipsRadii[C_TL] = 0;
}
nsRect innerRect(outerRect);
innerRect.Deflate(border);
// make sure the corner radii don't get too big
nsMargin maxRadiusSize(innerRect.width/2 + border.left,
innerRect.height/2 + border.top,
innerRect.width/2 + border.right,
innerRect.height/2 + border.bottom);
oBorderRadii[C_TL] = gfxFloat(PR_MIN(twipsRadii[C_TL], PR_MIN(maxRadiusSize.top, maxRadiusSize.left))) / twipsPerPixel;
oBorderRadii[C_TR] = gfxFloat(PR_MIN(twipsRadii[C_TR], PR_MIN(maxRadiusSize.top, maxRadiusSize.right))) / twipsPerPixel;
oBorderRadii[C_BL] = gfxFloat(PR_MIN(twipsRadii[C_BL], PR_MIN(maxRadiusSize.bottom, maxRadiusSize.left))) / twipsPerPixel;
oBorderRadii[C_BR] = gfxFloat(PR_MIN(twipsRadii[C_BR], PR_MIN(maxRadiusSize.bottom, maxRadiusSize.right))) / twipsPerPixel;
}
static void
DrawDashedSide(gfxContext *ctx,
PRUint8 side,
@ -2620,34 +2678,10 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
}
// Turn off rendering for all of the zero sized sides
if (border.top == 0) aSkipSides |= SIDE_BIT_TOP;
if (border.right == 0) aSkipSides |= SIDE_BIT_RIGHT;
if (border.bottom == 0) aSkipSides |= SIDE_BIT_BOTTOM;
if (border.left == 0) aSkipSides |= SIDE_BIT_LEFT;
if (aSkipSides & SIDE_BIT_TOP) {
border.top = 0;
twipsRadii[C_TL] = 0;
twipsRadii[C_TR] = 0;
}
if (aSkipSides & SIDE_BIT_RIGHT) {
border.right = 0;
twipsRadii[C_TR] = 0;
twipsRadii[C_BR] = 0;
}
if (aSkipSides & SIDE_BIT_BOTTOM) {
border.bottom = 0;
twipsRadii[C_BR] = 0;
twipsRadii[C_BL] = 0;
}
if (aSkipSides & SIDE_BIT_LEFT) {
border.left = 0;
twipsRadii[C_BL] = 0;
twipsRadii[C_TL] = 0;
}
if (aSkipSides & SIDE_BIT_TOP) border.top = 0;
if (aSkipSides & SIDE_BIT_RIGHT) border.right = 0;
if (aSkipSides & SIDE_BIT_BOTTOM) border.bottom = 0;
if (aSkipSides & SIDE_BIT_LEFT) border.left = 0;
// get the inside and outside parts of the border
nsRect outerRect(aBorderArea), innerRect(aBorderArea);
@ -2678,19 +2712,6 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
return;
}
// make sure the corner radii don't get too big
nsMargin maxRadiusSize(innerRect.width/2 + border.left,
innerRect.height/2 + border.top,
innerRect.width/2 + border.right,
innerRect.height/2 + border.bottom);
twipsRadii[C_TL] = PR_MIN(twipsRadii[C_TL], PR_MIN(maxRadiusSize.top, maxRadiusSize.left));
twipsRadii[C_TR] = PR_MIN(twipsRadii[C_TR], PR_MIN(maxRadiusSize.top, maxRadiusSize.right));
twipsRadii[C_BL] = PR_MIN(twipsRadii[C_BL], PR_MIN(maxRadiusSize.bottom, maxRadiusSize.left));
twipsRadii[C_BR] = PR_MIN(twipsRadii[C_BR], PR_MIN(maxRadiusSize.bottom, maxRadiusSize.right));
SF(" borderRadii: %d %d %d %d\n", twipsRadii[0], twipsRadii[1], twipsRadii[2], twipsRadii[3]);
// we can assume that we're already clipped to aDirtyRect -- I think? (!?)
// Get our conversion values
@ -2707,10 +2728,8 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
border.left / twipsPerPixel };
// convert the radii
gfxFloat borderRadii[4] = { gfxFloat(twipsRadii[0]) / twipsPerPixel,
gfxFloat(twipsRadii[1]) / twipsPerPixel,
gfxFloat(twipsRadii[2]) / twipsPerPixel,
gfxFloat(twipsRadii[3]) / twipsPerPixel };
gfxFloat borderRadii[4];
ComputePixelRadii(twipsRadii, outerRect, border, aSkipSides, twipsPerPixel, borderRadii);
PRUint8 borderStyles[4];
nscolor borderColors[4];
@ -2823,9 +2842,6 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
default:
break;
}
if (twipsRadii[i])
twipsRadii[i] = PR_MIN(twipsRadii[i], PR_MIN(aBorderArea.width / 2, aBorderArea.height / 2));
}
nsRect overflowArea = aForFrame->GetOverflowRect();
@ -2865,10 +2881,9 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
gfxRect iRect(RectToGfxRect(innerRect, twipsPerPixel));
// convert the radii
gfxFloat outlineRadii[4] = { gfxFloat(twipsRadii[0]) / twipsPerPixel,
gfxFloat(twipsRadii[1]) / twipsPerPixel,
gfxFloat(twipsRadii[2]) / twipsPerPixel,
gfxFloat(twipsRadii[3]) / twipsPerPixel };
nsMargin outlineMargin(width, width, width, width);
gfxFloat outlineRadii[4];
ComputePixelRadii(twipsRadii, outerRect, outlineMargin, 0, twipsPerPixel, outlineRadii);
PRUint8 outlineStyle = aOutlineStyle.GetOutlineStyle();
PRUint8 outlineStyles[4] = { outlineStyle,
@ -3817,7 +3832,7 @@ nsCSSRendering::PaintBackgroundColor(nsPresContext* aPresContext,
}
nsStyleCoord bordStyleRadius[4];
PRInt16 borderRadii[4];
nscoord borderRadii[4];
nsRect bgClipArea(aBgClipArea);
// get the radius for our border
@ -3887,7 +3902,7 @@ nsCSSRendering::PaintRoundedBackground(nsPresContext* aPresContext,
const nsRect& aBgClipArea,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
PRInt16 aTheRadius[4],
nscoord aTheRadius[4],
PRBool aCanPaintNonWhite)
{
nsRefPtr<gfxContext> ctx = (gfxContext*)
@ -3921,10 +3936,13 @@ nsCSSRendering::PaintRoundedBackground(nsPresContext* aPresContext,
if (oRect.IsEmpty())
return;
gfxFloat radii[4] = { gfxFloat(aTheRadius[0]) / appUnitsPerPixel,
gfxFloat(aTheRadius[1]) / appUnitsPerPixel,
gfxFloat(aTheRadius[2]) / appUnitsPerPixel,
gfxFloat(aTheRadius[3]) / appUnitsPerPixel };
// convert the radii
gfxFloat radii[4];
nsMargin border = aBorder.GetBorder();
ComputePixelRadii(aTheRadius, aBgClipArea, border,
aForFrame ? aForFrame->GetSkipSides() : 0,
appUnitsPerPixel, radii);
// Add 1.0 to any border radii; if we don't, the border and background
// curves will combine to have fringing at the rounded corners. Since

View File

@ -215,7 +215,7 @@ protected:
const nsRect& aBorderArea,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
PRInt16 aTheRadius[4],
nscoord aTheRadius[4],
PRBool aCanPaintNonWhite);
static nscolor MakeBevelColor(PRIntn whichSide, PRUint8 style,
@ -234,98 +234,4 @@ protected:
};
/** ---------------------------------------------------
* Class QBCurve, a quadratic bezier curve, used to implement the rounded rectangles
* @update 3/26/99 dwc
*/
class QBCurve
{
public:
nsFloatPoint mAnc1;
nsFloatPoint mCon;
nsFloatPoint mAnc2;
QBCurve() {mAnc1.x=0;mAnc1.y=0;mCon=mAnc2=mAnc1;}
void SetControls(nsFloatPoint &aAnc1,nsFloatPoint &aCon,nsFloatPoint &aAnc2) { mAnc1 = aAnc1; mCon = aCon; mAnc2 = aAnc2;}
void SetPoints(float a1x,float a1y,float acx,float acy,float a2x,float a2y) {mAnc1.MoveTo(a1x,a1y),mCon.MoveTo(acx,acy),mAnc2.MoveTo(a2x,a2y);}
/** ---------------------------------------------------
* Divide a Quadratic curve into line segments if it is not smaller than a certain size
* else it is so small that it can be approximated by 2 lineto calls
* @param aRenderingContext -- The RenderingContext to use to draw with
* @param aPointArray[] -- A list of points we can put line calls into instead of drawing. If null, lines are drawn
* @param aCurInex -- a pointer to an Integer that tells were to put the points into the array, incremented when finished
* @update 3/26/99 dwc
*/
void SubDivide(nsIRenderingContext *aRenderingContext,nsPoint aPointArray[],PRInt32 *aCurIndex);
/** ---------------------------------------------------
* Divide a Quadratic Bezier curve at the mid-point
* @update 3/26/99 dwc
* @param aCurve1 -- Curve 1 as a result of the division
* @param aCurve2 -- Curve 2 as a result of the division
*/
void MidPointDivide(QBCurve *A,QBCurve *B);
};
/** ---------------------------------------------------
* Class RoundedRect, A class to encapsulate all the rounded rect functionality,
* which are based on the QBCurve
* @update 4/13/99 dwc
*/
class RoundedRect
{
public:
PRInt32 mRoundness[4];
PRBool mDoRound;
PRInt32 mLeft;
PRInt32 mRight;
PRInt32 mTop;
PRInt32 mBottom;
/**
* Construct a rounded rectangle object
* @update 4/19/99
*/
void RoundRect() {mRoundness[0]=0;}
/**
* Set the curves boundaries and then break it up into the curve pieces for rendering
* @update 4/13/99 dwc
* @param aLeft -- Left side of bounding box
* @param aTop -- Top side of bounding box
* @param aWidth -- Width of bounding box
* @param aHeight -- Height of bounding box
* @param aRadius -- radius for the rounding
*/
void Set(nscoord aLeft,nscoord aTop,PRInt32 aWidth,PRInt32 aHeight,PRInt16 aRadius[4],PRInt16 aNumTwipPerPix);
/**
* Calculate the inset of a curve based on a border
* @update 4/13/99 dwc
* @param aLeft -- Left side of bounding box
* @param aTop -- Top side of bounding box
*/
void CalcInsetCurves(QBCurve &aULCurve,QBCurve &aURCurve,QBCurve &aLLCurve,QBCurve &aLRCurve,nsMargin &aBorder);
/** ---------------------------------------------------
* set the passed in curves to the rounded borders of the rectangle
* @update 4/13/99 dwc
* @param aULCurve -- upperleft curve
* @param aURCurve -- upperright curve
* @param aLRCurve -- lowerright curve
* @param aLLCurve -- lowerleft curve
*/
void GetRoundedBorders(QBCurve &aULCurve,QBCurve &aURCurve,QBCurve &aLLCurve,QBCurve &aLRCurve);
};
#endif /* nsCSSRendering_h___ */