diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index 6774984c69b..efc53ff6d09 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -86,6 +86,12 @@ struct THEBES_API gfxRect { gfxPoint TopRight() const { return pos + gfxSize(size.width, 0.0); } gfxPoint BottomLeft() const { return pos + gfxSize(0.0, size.height); } gfxPoint BottomRight() const { return pos + size; } + + /* Conditions this border to Cairo's max coordinate space. + * The caller can check IsEmpty() after Condition() -- if it's TRUE, + * the caller can possibly avoid doing any extra rendering. + */ + void Condition(); }; #endif /* GFX_RECT_H */ diff --git a/gfx/thebes/src/gfxRect.cpp b/gfx/thebes/src/gfxRect.cpp index cdabcabbf83..7282be218e8 100644 --- a/gfx/thebes/src/gfxRect.cpp +++ b/gfx/thebes/src/gfxRect.cpp @@ -87,3 +87,48 @@ gfxRect::Round() size.width = x1 - x0; size.height = y1 - y0; } + +/* Clamp r to CAIRO_COORD_MIN .. CAIRO_COORD_MAX + * these are to be device coordinates. + */ + +#define CAIRO_COORD_MAX (16382.0) +#define CAIRO_COORD_MIN (-16383.0) + +void +gfxRect::Condition() +{ + // if either x or y is way out of bounds; + // note that we don't handle negative w/h here + if (pos.x > CAIRO_COORD_MAX) { + pos.x = CAIRO_COORD_MAX; + size.width = 0.0; + } + + if (pos.y > CAIRO_COORD_MAX) { + pos.y = CAIRO_COORD_MAX; + size.height = 0.0; + } + + if (pos.x < CAIRO_COORD_MIN) { + size.width += pos.x - CAIRO_COORD_MIN; + if (size.width < 0.0) + size.width = 0.0; + pos.x = CAIRO_COORD_MIN; + } + + if (pos.y < CAIRO_COORD_MIN) { + size.height += pos.y - CAIRO_COORD_MIN; + if (size.height < 0.0) + size.height = 0.0; + pos.y = CAIRO_COORD_MIN; + } + + if (pos.x + size.width > CAIRO_COORD_MAX) { + size.width = CAIRO_COORD_MAX - pos.x; + } + + if (pos.y + size.height > CAIRO_COORD_MAX) { + size.height = CAIRO_COORD_MAX - pos.y; + } +} diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index f0d24201d82..e5f7c2adeac 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2261,11 +2261,19 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext, oRect.size.width - (border.left + border.right) / (2.0 * twipsPerPixel), oRect.size.height - (border.top + border.bottom) / (2.0 * twipsPerPixel)); - S(" oRect: "), S(oRect), SN(); S(" iRect: "), S(iRect), SN(); S(" lRect: "), S(lRect), SN(); + // if conditioning the outside rect failed, then ail -- the outside + // rect is supposed to enclose the entire border + oRect.Condition(); + if (oRect.IsEmpty()) + return; + + iRect.Condition(); + lRect.Condition(); + ctx->Save(); #if 0 @@ -2539,6 +2547,15 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext, oRect.size.width - (2*width) / (2.0 * twipsPerPixel), oRect.size.height - (2*width) / (2.0 * twipsPerPixel)); + // if conditioning the outside rect failed, then bail -- the outside + // rect is supposed to enclose the entire outline + oRect.Condition(); + if (oRect.IsEmpty()) + return; + + iRect.Condition(); + lRect.Condition(); + nscolor outlineColor; // PR_FALSE means use the initial color; PR_TRUE means a color was