--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2169,16 +2169,74 @@ DrawBorderSides(gfxContext *ctx,
ctx->Rectangle(oRect);
ctx->Stroke();
ctx->NewPath();
ctx->Rectangle(iRect);
ctx->Stroke();
#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,
const gfxRect& iRect,
const gfxRect& oRect,
PRUint8 style,
gfxFloat borderWidth,
nscolor borderColor,
@@ -2615,44 +2673,20 @@ nsCSSRendering::PaintBorder(nsPresContex
break;
default:
break;
}
}
// 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);
innerRect.Deflate(border);
SF(" innerRect: %d %d %d %d\n", innerRect.x, innerRect.y, innerRect.width, innerRect.height);
SF(" outerRect: %d %d %d %d\n", outerRect.x, outerRect.y, outerRect.width, outerRect.height);
@@ -2673,49 +2707,34 @@ nsCSSRendering::PaintBorder(nsPresContex
// content is being painted), then we can skip out now
// XXX this isn't exactly true for rounded borders, where the inner curves may
// encroach into the content area. A safer calculation would be to
// shorten innerRect by the radius one each side before performing this test.
if (innerRect.Contains(aDirtyRect)) {
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
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
// convert outer and inner rects
gfxRect oRect(RectToGfxRect(outerRect, twipsPerPixel));
gfxRect iRect(RectToGfxRect(innerRect, twipsPerPixel));
// convert the border widths
gfxFloat borderWidths[4] = { border.top / twipsPerPixel,
border.right / twipsPerPixel,
border.bottom / twipsPerPixel,
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];
nsBorderColors *compositeColors[4];
// pull out styles, colors, composite colors
for (int i = 0; i < 4; i++) {
PRBool transparent, foreground;
@@ -2818,19 +2837,16 @@ nsCSSRendering::PaintOutline(nsPresConte
case eStyleUnit_Coord:
twipsRadii[i] = bordStyleRadius[i].GetCoordValue();
break;
default:
break;
}
-
- if (twipsRadii[i])
- twipsRadii[i] = PR_MIN(twipsRadii[i], PR_MIN(aBorderArea.width / 2, aBorderArea.height / 2));
}
nsRect overflowArea = aForFrame->GetOverflowRect();
// get the offset for our outline
aOutlineStyle.GetOutlineOffset(offset);
nsRect outerRect(overflowArea + aBorderArea.TopLeft());
nsRect innerRect(outerRect);
@@ -2860,20 +2876,19 @@ nsCSSRendering::PaintOutline(nsPresConte
// Get our conversion values
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
// get the inner and outer rectangles
gfxRect oRect(RectToGfxRect(outerRect, twipsPerPixel));
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,
outlineStyle,
outlineStyle,
outlineStyle };
nscolor outlineColor;
@@ -3812,17 +3827,17 @@ nsCSSRendering::PaintBackgroundColor(nsP
// PaintBackgroundWithSC before the first call to PaintBackgroundColor.
if ((aColor.mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
(aCanPaintNonWhite || aColor.IsTransparent())) {
// nothing to paint
return;
}
nsStyleCoord bordStyleRadius[4];
- PRInt16 borderRadii[4];
+ nscoord borderRadii[4];
nsRect bgClipArea(aBgClipArea);
// get the radius for our border
aBorder.mBorderRadius.GetTop(bordStyleRadius[NS_SIDE_TOP]); // topleft
aBorder.mBorderRadius.GetRight(bordStyleRadius[NS_SIDE_RIGHT]); // topright
aBorder.mBorderRadius.GetBottom(bordStyleRadius[NS_SIDE_BOTTOM]); // bottomright
aBorder.mBorderRadius.GetLeft(bordStyleRadius[NS_SIDE_LEFT]); // bottomleft
@@ -3882,17 +3897,17 @@ nsCSSRendering::PaintBackgroundColor(nsP
*/
void
nsCSSRendering::PaintRoundedBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aBgClipArea,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
- PRInt16 aTheRadius[4],
+ nscoord aTheRadius[4],
PRBool aCanPaintNonWhite)
{
nsRefPtr<gfxContext> ctx = (gfxContext*)
aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
// needed for our border thickness
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
@@ -3916,20 +3931,23 @@ nsCSSRendering::PaintRoundedBackground(n
// the bgClipArea is the outside
gfxRect oRect(RectToGfxRect(aBgClipArea, appUnitsPerPixel));
oRect.Round();
oRect.Condition();
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
// alpha is used for coverage, we have problems because the border and
// background should have identical coverage, and the border should
// overlay the background exactly. The way to avoid this is by using
// a supersampling scheme, but we don't have the mechanism in place to do
// this. So, this will do for now.
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -210,17 +210,17 @@ protected:
PRBool aCanPaintNonWhite);
static void PaintRoundedBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aBorderArea,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
- PRInt16 aTheRadius[4],
+ nscoord aTheRadius[4],
PRBool aCanPaintNonWhite);
static nscolor MakeBevelColor(PRIntn whichSide, PRUint8 style,
nscolor aBackgroundColor,
nscolor aBorderColor);
static void DrawLine (nsIRenderingContext& aContext,
nscoord aX1, nscoord aY1, nscoord aX2, nscoord aY2,
@@ -229,103 +229,9 @@ protected:
static void FillPolygon (nsIRenderingContext& aContext,
const nsPoint aPoints[],
PRInt32 aNumPoints,
nsRect* aGap);
};
-
-/** ---------------------------------------------------
- * 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___ */