diff --git a/render/html_redraw.c b/render/html_redraw.c
index 78c369b82..4398fdbdc 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -65,11 +65,12 @@ static bool html_redraw_text_box(struct box *box, int x, int y,
static bool html_redraw_caret(struct caret *caret,
colour current_background_color, float scale);
static bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, float scale);
-static bool html_redraw_inline_borders(struct box *box, int x0, int y0,
- int x1, int y1, float scale, bool first, bool last);
+ int p_width, int p_height, struct rect clip, float scale);
+static bool html_redraw_inline_borders(struct box *box, struct rect b,
+ struct rect clip, float scale, bool first, bool last);
static bool html_redraw_border_plot(const int side, const int *p, colour c,
- enum css_border_style_e style, int thickness, bool rectangular);
+ enum css_border_style_e style, int thickness, bool rectangular,
+ struct rect clip);
static bool html_redraw_checkbox(int x, int y, int width, int height,
bool selected);
static bool html_redraw_radio(int x, int y, int width, int height,
@@ -80,8 +81,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
struct rect clip, colour *background_colour,
struct box *background);
static bool html_redraw_inline_background(int x, int y, struct box *box,
- float scale, struct rect clip,
- int px0, int py0, int px1, int py1,
+ float scale, struct rect clip, struct rect b,
bool first, bool last, colour *background_colour);
static bool html_redraw_text_decoration(struct box *box,
int x_parent, int y_parent, float scale,
@@ -481,11 +481,12 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent,
box->type != BOX_INLINE_END &&
(box->type != BOX_INLINE || box->object) &&
(border_top || border_right ||
- border_bottom || border_left))
+ border_bottom || border_left)) {
if (!html_redraw_borders(box, x_parent, y_parent,
- padding_width, padding_height,
+ padding_width, padding_height, r,
scale))
return false;
+ }
/* backgrounds and borders for non-replaced inlines */
if (box->style && box->type == BOX_INLINE && box->inline_end &&
@@ -496,20 +497,23 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent,
/* inline backgrounds and borders span other boxes and may
* wrap onto separate lines */
struct box *ib;
- struct rect p;
+ struct rect b; /* border edge rectangle */
+ struct rect p; /* clipped rect */
bool first = true;
int ib_x;
int ib_y = y;
int ib_p_width;
int ib_b_left, ib_b_right;
- int xmin = x - border_left;
- int xmax = x + padding_width + border_right;
- int ymin = y - border_top;
- int ymax = y + padding_height + border_bottom;
- p.x0 = xmin < r.x0 ? r.x0 : xmin;
- p.x1 = xmax < r.x1 ? xmax : r.x1;
- p.y0 = ymin < r.y0 ? r.y0 : ymin;
- p.y1 = ymax < r.y1 ? ymax : r.y1;
+
+ b.x0 = x - border_left;
+ b.x1 = x + padding_width + border_right;
+ b.y0 = y - border_top;
+ b.y1 = y + padding_height + border_bottom;
+
+ p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
+ p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
+ p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
+ p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
for (ib = box; ib; ib = ib->next) {
/* to get extents of rectangle(s) associated with
* inline, cycle though all boxes in inline, skipping
@@ -537,34 +541,32 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent,
/* inline element has wrapped, plot background
* and borders */
if (!html_redraw_inline_background(
- x, y, box, scale, p,
- xmin, ymin, xmax, ymax,
+ x, y, box, scale, p, b,
first, false,
¤t_background_color))
return false;
/* restore previous graphics window */
if (!plot.clip(r.x0, r.y0, r.x1, r.y1))
return false;
- if (!html_redraw_inline_borders(box,
- xmin, ymin, xmax, ymax,
+ if (!html_redraw_inline_borders(box, b, r,
scale, first, false))
return false;
/* reset coords */
- xmin = ib_x - ib_b_left;
- ymin = ib_y - border_top - padding_top;
- ymax = ib_y + padding_height - padding_top +
+ b.x0 = ib_x - ib_b_left;
+ b.y0 = ib_y - border_top - padding_top;
+ b.y1 = ib_y + padding_height - padding_top +
border_bottom;
- p.x0 = xmin < r.x0 ? r.x0 : xmin;
- p.y0 = ymin < r.y0 ? r.y0 : ymin;
- p.y1 = ymax < r.y1 ? ymax : r.y1;
+ p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
+ p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
+ p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
first = false;
}
/* increase width for current box */
- xmax = ib_x + ib_p_width + ib_b_right;
- p.x1 = xmax < r.x1 ? xmax : r.x1;
+ b.x1 = ib_x + ib_p_width + ib_b_right;
+ p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
if (ib == box->inline_end)
/* reached end of BOX_INLINE span */
@@ -572,15 +574,13 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent,
}
/* plot background and borders for last rectangle of
* the inline */
- if (!html_redraw_inline_background(x, ib_y, box, scale, p,
- xmin, ymin, xmax, ymax, first, true,
- ¤t_background_color))
+ if (!html_redraw_inline_background(x, ib_y, box, scale, p, b,
+ first, true, ¤t_background_color))
return false;
/* restore previous graphics window */
if (!plot.clip(r.x0, r.y0, r.x1, r.y1))
return false;
- if (!html_redraw_inline_borders(box, xmin, ymin, xmax, ymax,
- scale, first, true))
+ if (!html_redraw_inline_borders(box, b, r, scale, first, true))
return false;
}
@@ -1037,7 +1037,7 @@ bool html_redraw_caret(struct caret *c, colour current_background_color,
*/
bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, float scale)
+ int p_width, int p_height, struct rect clip, float scale)
{
unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
int top = box->border[TOP].width;
@@ -1116,6 +1116,14 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
z[3] += bottom;
square_end_2 = true;
}
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ if (!html_redraw_border_plot(side, z, col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2, clip))
+ return false;
break;
case RIGHT:
square_end_1 = (top == 0);
@@ -1144,8 +1152,21 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
z[5] += bottom;
square_end_2 = true;
}
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ if (!html_redraw_border_plot(side, z, col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2, clip))
+ return false;
break;
case TOP:
+ if (clip.y0 > p[3])
+ /* clip rectangle is below border; nothing to
+ * plot */
+ continue;
+
square_end_1 = (left == 0);
square_end_2 = (right == 0);
@@ -1172,8 +1193,21 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
z[4] -= right;
square_end_2 = true;
}
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ if (!html_redraw_border_plot(side, z, col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2, clip))
+ return false;
break;
case BOTTOM:
+ if (clip.y1 < p[5])
+ /* clip rectangle is above border; nothing to
+ * plot */
+ continue;
+
square_end_1 = (left == 0);
square_end_2 = (right == 0);
@@ -1200,20 +1234,20 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
z[2] -= right;
square_end_2 = true;
}
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ if (!html_redraw_border_plot(side, z, col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2, clip))
+ return false;
break;
default:
assert(side == TOP || side == BOTTOM ||
side == LEFT || side == RIGHT);
break;
}
-
- col = nscss_color_to_ns(box->border[side].c);
-
- if (!html_redraw_border_plot(side, z, col,
- box->border[side].style,
- box->border[side].width * scale,
- square_end_1 && square_end_2))
- return false;
}
return true;
@@ -1224,18 +1258,15 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
* Draw an inline's borders.
*
* \param box BOX_INLINE which created the border
- * \param x0 coordinate of border edge rectangle
- * \param y0 coordinate of border edge rectangle
- * \param x1 coordinate of border edge rectangle
- * \param y1 coordinate of border edge rectangle
+ * \param b coordinates of border edge rectangle
* \param scale scale for redraw
* \param first true if this is the first rectangle associated with the inline
* \param last true if this is the last rectangle associated with the inline
* \return true if successful, false otherwise
*/
-bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
- float scale, bool first, bool last)
+bool html_redraw_inline_borders(struct box *box, struct rect b,
+ struct rect clip, float scale, bool first, bool last)
{
int top = box->border[TOP].width;
int right = box->border[RIGHT].width;
@@ -1264,10 +1295,10 @@ bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
* | / \ |
* +----------------------D
*/
- p[0] = x0; p[1] = y0; /* A */
- p[2] = first ? x0 + left : x0; p[3] = y0 + top; /* B */
- p[4] = last ? x1 - right : x1; p[5] = y1 - bottom; /* C */
- p[6] = x1; p[7] = y1; /* D */
+ p[0] = b.x0; p[1] = b.y0; /* A */
+ p[2] = first ? b.x0 + left : b.x0; p[3] = b.y0 + top; /* B */
+ p[4] = last ? b.x1 - right : b.x1; p[5] = b.y1 - bottom; /* C */
+ p[6] = b.x1; p[7] = b.y1; /* D */
assert(box->style);
@@ -1304,7 +1335,7 @@ bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
if (!html_redraw_border_plot(LEFT, z, col,
box->border[LEFT].style,
- left, square_end_1 && square_end_2))
+ left, square_end_1 && square_end_2, clip))
return false;
}
@@ -1341,7 +1372,7 @@ bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
if (!html_redraw_border_plot(RIGHT, z, col,
box->border[RIGHT].style,
- right, square_end_1 && square_end_2))
+ right, square_end_1 && square_end_2, clip))
return false;
}
@@ -1378,7 +1409,7 @@ bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
if (!html_redraw_border_plot(TOP, z, col,
box->border[TOP].style,
- top, square_end_1 && square_end_2))
+ top, square_end_1 && square_end_2, clip))
return false;
}
@@ -1415,7 +1446,7 @@ bool html_redraw_inline_borders(struct box *box, int x0, int y0, int x1, int y1,
if (!html_redraw_border_plot(BOTTOM, z, col,
box->border[BOTTOM].style,
- bottom, square_end_1 && square_end_2))
+ bottom, square_end_1 && square_end_2, clip))
return false;
}
@@ -1454,7 +1485,8 @@ static plot_style_t plot_style_fillbdr_dlight = {
*/
bool html_redraw_border_plot(const int side, const int *p, colour c,
- enum css_border_style_e style, int thickness, bool rectangular)
+ enum css_border_style_e style, int thickness, bool rectangular,
+ struct rect clip)
{
int z[8]; /* Vertices of border part */
unsigned int light = side;
@@ -1502,9 +1534,17 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
y1 + p[1] - p[3] : y1;
}
- if (!plot.rectangle(x0, y0, x1, y1,
- &plot_style_fillbdr))
- return false;
+ /* find intersection of clip rectangle and border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ &plot_style_fillbdr))
+ return false;
+ }
} else {
if (!plot.polygon(p, 4, &plot_style_fillbdr))
return false;
@@ -1561,9 +1601,17 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x0 = p[6]; y0 = p[7];
x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
}
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
+ /* find intersection of clip rectangle and border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
/* Second part */
if (side == TOP || side == RIGHT) {
@@ -1573,9 +1621,17 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
x1 = p[2]; y1 = p[3];
}
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
+ /* find intersection of clip rectangle and border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
} else if (thickness == 1) {
/* Border made up from one part which can be plotted
* as a rectangle */
@@ -1585,17 +1641,35 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x1 = p[6]; y1 = p[7];
x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
x1 + p[4] - p[6] : x1;
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
} else {
x0 = p[6]; y0 = p[7];
x1 = p[2]; y1 = p[3];
y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
y1 + p[1] - p[3] : y1;
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
}
} else {
/* Border made up from two parts and can't be plotted
@@ -1661,9 +1735,17 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x0 = p[6]; y0 = p[7];
x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
}
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
+ /* find intersection of clip rectangle and border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
/* Second part */
if (side == TOP || side == RIGHT) {
@@ -1673,9 +1755,17 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
x1 = p[2]; y1 = p[3];
}
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
+ /* find intersection of clip rectangle and border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
} else if (thickness == 1) {
/* Border made up from one part which can be plotted
* as a rectangle */
@@ -1685,17 +1775,35 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
x1 = p[6]; y1 = p[7];
x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
x1 + p[4] - p[6] : x1;
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
} else {
x0 = p[6]; y0 = p[7];
x1 = p[2]; y1 = p[3];
y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
y1 + p[1] - p[3] : y1;
- if (!plot.rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip.x0 > x0) ? clip.x0 : x0;
+ y0 = (clip.y0 > y0) ? clip.y0 : y0;
+ x1 = (clip.x1 < x1) ? clip.x1 : x1;
+ y1 = (clip.y1 < y1) ? clip.y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot.rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
}
} else {
/* Border made up from two parts and can't be plotted
@@ -2095,10 +2203,7 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
* \param box BOX_INLINE which created the background
* \param scale scale for redraw
* \param clip coordinates of clip rectangle
- * \param px0 coordinate of border edge rectangle
- * \param py0 coordinate of border edge rectangle
- * \param px1 coordinate of border edge rectangle
- * \param py1 coordinate of border edge rectangle
+ * \param b coordinates of border edge rectangle
* \param first true if this is the first rectangle associated with the inline
* \param last true if this is the last rectangle associated with the inline
* \param background_colour updated to current background colour if plotted
@@ -2106,8 +2211,8 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
*/
bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
- struct rect clip, int px0, int py0, int px1, int py1,
- bool first, bool last, colour *background_colour)
+ struct rect clip, struct rect b, bool first, bool last,
+ colour *background_colour)
{
bool repeat_x = false;
bool repeat_y = false;
@@ -2156,7 +2261,8 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
css_computed_background_position(box->style,
&hpos, &hunit, &vpos, &vunit);
if (hunit == CSS_UNIT_PCT) {
- x += (px1 - px0 - content_get_width(box->background) *
+ x += (b.x1 - b.x0 -
+ content_get_width(box->background) *
scale) * FIXTOFLT(hpos) / 100.;
if (!repeat_x && ((hpos < 2 && !first) ||
@@ -2169,7 +2275,8 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
}
if (vunit == CSS_UNIT_PCT) {
- y += (py1 - py0 - content_get_height(box->background) *
+ y += (b.y1 - b.y0 -
+ content_get_height(box->background) *
scale) * FIXTOFLT(vpos) / 100.;
} else {
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit,