Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/ed661229272c158e6a04a...
...commit
http://git.netsurf-browser.org/netsurf.git/commit/ed661229272c158e6a04a5d...
...tree
http://git.netsurf-browser.org/netsurf.git/tree/ed661229272c158e6a04a5d64...
The branch, vince/plotctx has been updated
discards a8e1b2a71d7eb435381bb1cbe5be9b15f2ea1705 (commit)
discards 340eb008b7a6d0bce530da85bbd792745146a2dc (commit)
discards daa29dfb99fcdcab037ba4fbf3d287e8954dfb3b (commit)
discards 58bb1df4838e65508d99adcdf401778784e82170 (commit)
discards 0f69df29a75412b3b4e7d6fae4954c5bee789dc9 (commit)
via ed661229272c158e6a04a5d64ff7eacf7e3a8523 (commit)
via c5b530964aaa06c352cf147eb26768c8b438341a (commit)
via 4545083e2b4d173522a2cf3274824e6f0d2564cd (commit)
via 06e8b32dbfac5025053e4902995cd4656111c049 (commit)
via 130e96920942f5fcd63eaf5f676eda0744f83e43 (commit)
via 9cc5f5e6069811b2d3800e089a3913d6f0ca10b7 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (a8e1b2a71d7eb435381bb1cbe5be9b15f2ea1705)
\
N -- N -- N (ed661229272c158e6a04a5d64ff7eacf7e3a8523)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=ed661229272c158e6a0...
commit ed661229272c158e6a04a5d64ff7eacf7e3a8523
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
split border drawing out of html redraw
diff --git a/render/Makefile b/render/Makefile
index 148c2c3..dc2e31c 100644
--- a/render/Makefile
+++ b/render/Makefile
@@ -3,7 +3,8 @@
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c imagemap.c layout.c search.c table.c textplain.c \
html.c html_css.c html_css_fetcher.c html_script.c \
- html_interaction.c html_redraw.c html_forms.c html_object.c
+ html_interaction.c html_redraw.c html_redraw_border.c \
+ html_forms.c html_object.c
S_RENDER := $(addprefix render/,$(S_RENDER))
diff --git a/render/html_internal.h b/render/html_internal.h
index fd65707..2f84cf8 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -258,6 +258,15 @@ bool html_begin_conversion(html_content *htmlc);
bool html_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx);
+/* in render/html_redraw_border.c */
+bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
+ int p_width, int p_height, const struct rect *clip, float scale,
+ const struct redraw_context *ctx);
+
+bool html_redraw_inline_borders(struct box *box, struct rect b,
+ const struct rect *clip, float scale, bool first, bool last,
+ const struct redraw_context *ctx);
+
/* in render/html_interaction.c */
void html_mouse_track(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
diff --git a/render/html_redraw.c b/render/html_redraw.c
index e58918d..598e613 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -344,852 +344,6 @@ text_redraw(const char *utf8_text,
return true;
}
-static plot_style_t plot_style_bdr = {
- .stroke_type = PLOT_OP_TYPE_DASH,
-};
-static plot_style_t plot_style_fillbdr = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_light = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_ddark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dlight = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-
-static inline nserror
-plot_clipped_rectangle(const struct redraw_context *ctx,
- const plot_style_t *style,
- const struct rect *clip,
- struct rect *rect)
-{
- nserror res;
-
- rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
- rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
- rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
- rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
- if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
- /* valid clip rectangles only */
- res = ctx->plot->rectangle(ctx, style, rect);
- } else {
- res = NSERROR_OK;
- }
- return res;
-}
-
-/**
- * Draw one border.
- *
- * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
- * \param p array of precomputed border vertices
- * \param c colour for border
- * \param style border line style
- * \param thickness border thickness
- * \param rectangular whether border is rectangular
- * \param clip cliping area for redrawing border.
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static nserror
-html_redraw_border_plot(const int side,
- const int *p,
- colour c,
- enum css_border_style_e style,
- int thickness,
- bool rectangular,
- const struct rect *clip,
- const struct redraw_context *ctx)
-{
- int z[8]; /* Vertices of border part */
- unsigned int light = side;
- plot_style_t *plot_style_bdr_in;
- plot_style_t *plot_style_bdr_out;
- nserror res = NSERROR_OK;
- struct rect rect;
-
- if (c == NS_TRANSPARENT) {
- return res;
- }
-
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
- plot_style_bdr.stroke_colour = c;
- plot_style_bdr.stroke_width = thickness;
- plot_style_fillbdr.fill_colour = c;
- plot_style_fillbdr_dark.fill_colour = darken_colour(c);
- plot_style_fillbdr_light.fill_colour = lighten_colour(c);
- plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
- plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
-
- switch (style) {
- case CSS_BORDER_STYLE_DOTTED:
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
- /* fall through */
- case CSS_BORDER_STYLE_DASHED:
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = (p[4] + p[6]) / 2;
- rect.y1 = (p[5] + p[7]) / 2;
- res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
- break;
-
- case CSS_BORDER_STYLE_SOLID:
- /* fall through to default */
- default:
- if (rectangular || thickness == 1) {
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- if ((side == TOP) &&
- (p[4] - p[6] != 0)) {
- rect.x1 = p[4];
- } else {
- rect.x1 = p[6];
- }
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- if ((side == LEFT) &&
- (p[1] - p[3] != 0)) {
- rect.y1 = p[1];
- } else {
- rect.y1 = p[3];
- }
- }
- res = plot_clipped_rectangle(ctx, &plot_style_fillbdr, clip, &rect);
- } else {
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
- }
- break;
-
- case CSS_BORDER_STYLE_DOUBLE:
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] * 2 + p[2]) / 3;
- z[3] = (p[1] * 2 + p[3]) / 3;
- z[4] = (p[6] * 2 + p[4]) / 3;
- z[5] = (p[7] * 2 + p[5]) / 3;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- if (res == NSERROR_OK) {
- z[0] = p[2];
- z[1] = p[3];
- z[2] = (p[2] * 2 + p[0]) / 3;
- z[3] = (p[3] * 2 + p[1]) / 3;
- z[4] = (p[4] * 2 + p[6]) / 3;
- z[5] = (p[5] * 2 + p[7]) / 3;
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- }
- break;
-
- case CSS_BORDER_STYLE_GROOVE:
- light = 3 - light;
- /* fall through */
- case CSS_BORDER_STYLE_RIDGE:
- /* choose correct colours for each part of the border line */
- if (light <= 1) {
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- } else {
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be
- * plotted with rectangles
- */
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = p[6];
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = (p[0] + p[2]) / 2;
- rect.y1 = (p[1] + p[3]) / 2;
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return res;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = (p[6] + p[4]) / 2;
- rect.y1 = (p[7] + p[5]) / 2;
- } else {
- rect.x0 = (p[6] + p[4]) / 2;
- rect.y0 = (p[7] + p[5]) / 2;
- rect.x1 = p[2];
- rect.y1 = p[3];
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- } else if (thickness == 1) {
- /* Border made up from one part which can be
- * plotted as a rectangle
- */
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = p[6];
- rect.y1 = p[7];
- rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- rect.x1 + p[4] - p[6] : rect.x1;
-
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- rect.y1 = p[3];
- rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- rect.y1 + p[1] - p[3] : rect.y1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- }
- } else {
- /* Border made up from two parts and can't be
- * plotted with rectangles
- */
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
- if (res != NSERROR_OK) {
- return res;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- }
- break;
-
- case CSS_BORDER_STYLE_INSET:
- light = (light + 2) % 4;
- /* fall through */
- case CSS_BORDER_STYLE_OUTSET:
- /* choose correct colours for each part of the border line */
- switch (light) {
- case 0:
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dlight;
- break;
- case 1:
- plot_style_bdr_in = &plot_style_fillbdr_ddark;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- break;
- case 2:
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_ddark;
- break;
- case 3:
- plot_style_bdr_in = &plot_style_fillbdr_dlight;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- break;
- default:
- plot_style_bdr_in = &plot_style_fillbdr;
- plot_style_bdr_out = &plot_style_fillbdr;
- break;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be
- * plotted with rectangles
- */
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = p[6];
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = (p[0] + p[2]) / 2;
- rect.y1 = (p[1] + p[3]) / 2;
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return res;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = (p[6] + p[4]) / 2;
- rect.y1 = (p[7] + p[5]) / 2;
- } else {
- rect.x0 = (p[6] + p[4]) / 2;
- rect.y0 = (p[7] + p[5]) / 2;
- rect.x1 = p[2];
- rect.y1 = p[3];
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- } else if (thickness == 1) {
- /* Border made up from one part which can be
- * plotted as a rectangle
- */
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = p[6];
- rect.y1 = p[7];
- rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- rect.x1 + p[4] - p[6] : rect.x1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- rect.y1 = p[3];
- rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- rect.y1 + p[1] - p[3] : rect.y1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- }
- } else {
- /* Border made up from two parts and can't be
- * plotted with rectangles
- */
-
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
- if (res != NSERROR_OK) {
- return res;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- }
- break;
- }
-
- return res;
-}
-
-
-/**
- * Draw borders for a box.
- *
- * \param box box to draw
- * \param x_parent coordinate of left padding edge of parent of box
- * \param y_parent coordinate of top padding edge of parent of box
- * \param p_width width of padding box
- * \param p_height height of padding box
- * \param clip cliping area for redrawing border.
- * \param scale scale for redraw
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, const struct rect *clip, float scale,
- const struct redraw_context *ctx)
-{
- unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
- int top = box->border[TOP].width;
- int right = box->border[RIGHT].width;
- int bottom = box->border[BOTTOM].width;
- int left = box->border[LEFT].width;
- int x, y;
- unsigned int i, side;
- int p[8]; /* Box border vertices */
- int z[8]; /* Border vertices */
- bool square_end_1 = false;
- bool square_end_2 = false;
- nserror res;
-
- x = x_parent + box->x;
- y = y_parent + box->y;
-
- if (scale != 1.0) {
- top *= scale;
- right *= scale;
- bottom *= scale;
- left *= scale;
- x *= scale;
- y *= scale;
- }
-
- assert(box->style);
-
- /* Calculate border vertices
- *
- * A----------------------+
- * | \ / |
- * | B--------------+ |
- * | | | |
- * | +--------------C |
- * | / \ |
- * +----------------------D
- */
- p[0] = x - left; p[1] = y - top; /* A */
- p[2] = x; p[3] = y; /* B */
- p[4] = x + p_width; p[5] = y + p_height; /* C */
- p[6] = x + p_width + right; p[7] = y + p_height + bottom; /* D */
-
- for (i = 0; i != 4; i++) {
- colour col = 0;
- side = sides[i]; /* plot order */
-
- if (box->border[side].width == 0 ||
- nscss_color_is_transparent(box->border[side].c))
- continue;
-
- switch (side) {
- case LEFT:
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
-
- z[0] = p[0]; z[1] = p[7];
- z[2] = p[2]; z[3] = p[5];
- z[4] = p[2]; z[5] = p[3];
- z[6] = p[0]; z[7] = p[1];
-
- if (nscss_color_is_transparent(box->border[TOP].c) ==
- false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[5] -= top;
- square_end_1 = true;
- }
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[3] += bottom;
- square_end_2 = true;
- }
-
- col = nscss_color_to_ns(box->border[side].c);
-
- res = html_redraw_border_plot(side,
- z,
- col,
- box->border[side].style,
- box->border[side].width * scale,
- square_end_1 && square_end_2,
- clip,
- ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- break;
-
- case RIGHT:
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
-
- z[0] = p[6]; z[1] = p[1];
- z[2] = p[4]; z[3] = p[3];
- z[4] = p[4]; z[5] = p[5];
- z[6] = p[6]; z[7] = p[7];
-
- if (nscss_color_is_transparent(box->border[TOP].c) ==
- false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[3] -= top;
- square_end_1 = true;
- }
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[5] += bottom;
- square_end_2 = true;
- }
-
- col = nscss_color_to_ns(box->border[side].c);
-
- res = html_redraw_border_plot(side,
- z,
- col,
- box->border[side].style,
- box->border[side].width * scale,
- square_end_1 && square_end_2,
- clip,
- ctx);
- if (res != NSERROR_OK) {
- 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);
-
- z[0] = p[2]; z[1] = p[3];
- z[2] = p[0]; z[3] = p[1];
- z[4] = p[6]; z[5] = p[1];
- z[6] = p[4]; z[7] = p[3];
-
- if (box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[2] += left;
- square_end_1 = true;
- }
- if (box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[4] -= right;
- square_end_2 = true;
- }
-
- col = nscss_color_to_ns(box->border[side].c);
-
- res = html_redraw_border_plot(side,
- z,
- col,
- box->border[side].style,
- box->border[side].width * scale,
- square_end_1 && square_end_2,
- clip,
- ctx);
- if (res != NSERROR_OK) {
- 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);
-
- z[0] = p[4]; z[1] = p[5];
- z[2] = p[6]; z[3] = p[7];
- z[4] = p[0]; z[5] = p[7];
- z[6] = p[2]; z[7] = p[5];
-
- if (box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[4] += left;
- square_end_1 = true;
- }
- if (box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[2] -= right;
- square_end_2 = true;
- }
-
- col = nscss_color_to_ns(box->border[side].c);
-
- res = html_redraw_border_plot(side,
- z,
- col,
- box->border[side].style,
- box->border[side].width * scale,
- square_end_1 && square_end_2,
- clip,
- ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- break;
-
- default:
- assert(side == TOP || side == BOTTOM ||
- side == LEFT || side == RIGHT);
- break;
- }
- }
-
- return true;
-}
-
-
-/**
- * Draw an inline's borders.
- *
- * \param box BOX_INLINE which created the border
- * \param b coordinates of border edge rectangle
- * \param clip cliping area for redrawing border.
- * \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
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static bool html_redraw_inline_borders(struct box *box, struct rect b,
- const struct rect *clip, float scale, bool first, bool last,
- const struct redraw_context *ctx)
-{
- int top = box->border[TOP].width;
- int right = box->border[RIGHT].width;
- int bottom = box->border[BOTTOM].width;
- int left = box->border[LEFT].width;
- colour col;
- int p[8]; /* Box border vertices */
- int z[8]; /* Border vertices */
- bool square_end_1;
- bool square_end_2;
- nserror res;
-
- if (scale != 1.0) {
- top *= scale;
- right *= scale;
- bottom *= scale;
- left *= scale;
- }
-
- /* Calculate border vertices
- *
- * A----------------------+
- * | \ / |
- * | B--------------+ |
- * | | | |
- * | +--------------C |
- * | / \ |
- * +----------------------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);
-
- /* Left */
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
- if (left != 0 && first && nscss_color_is_transparent(
- box->border[LEFT].c) == false) {
- col = nscss_color_to_ns(box->border[LEFT].c);
-
- z[0] = p[0]; z[1] = p[7];
- z[2] = p[2]; z[3] = p[5];
- z[4] = p[2]; z[5] = p[3];
- z[6] = p[0]; z[7] = p[1];
-
- if (nscss_color_is_transparent(box->border[TOP].c) == false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[5] -= top;
- square_end_1 = true;
- }
-
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[3] += bottom;
- square_end_2 = true;
- }
-
- res = html_redraw_border_plot(LEFT,
- z,
- col,
- box->border[LEFT].style,
- left,
- square_end_1 && square_end_2,
- clip,
- ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- }
-
- /* Right */
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
- if (right != 0 && last && nscss_color_is_transparent(
- box->border[RIGHT].c) == false) {
- col = nscss_color_to_ns(box->border[RIGHT].c);
-
- z[0] = p[6]; z[1] = p[1];
- z[2] = p[4]; z[3] = p[3];
- z[4] = p[4]; z[5] = p[5];
- z[6] = p[6]; z[7] = p[7];
-
- if (nscss_color_is_transparent(box->border[TOP].c) == false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[3] -= top;
- square_end_1 = true;
- }
-
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[5] += bottom;
- square_end_2 = true;
- }
-
- res = html_redraw_border_plot(RIGHT, z, col,
- box->border[RIGHT].style,
- right, square_end_1 && square_end_2,
- clip, ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- }
-
- /* Top */
- square_end_1 = (left == 0);
- square_end_2 = (right == 0);
- if (top != 0 && nscss_color_is_transparent(
- box->border[TOP].c) == false) {
- col = nscss_color_to_ns(box->border[TOP].c);
-
- z[0] = p[2]; z[1] = p[3];
- z[2] = p[0]; z[3] = p[1];
- z[4] = p[6]; z[5] = p[1];
- z[6] = p[4]; z[7] = p[3];
-
- if (first && box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[2] += left;
- square_end_1 = true;
- }
-
- if (last && box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[4] -= right;
- square_end_2 = true;
- }
-
- res = html_redraw_border_plot(TOP, z, col,
- box->border[TOP].style,
- top, square_end_1 && square_end_2,
- clip, ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- }
-
- /* Bottom */
- square_end_1 = (left == 0);
- square_end_2 = (right == 0);
- if (bottom != 0 && nscss_color_is_transparent(
- box->border[BOTTOM].c) == false) {
- col = nscss_color_to_ns(box->border[BOTTOM].c);
-
- z[0] = p[4]; z[1] = p[5];
- z[2] = p[6]; z[3] = p[7];
- z[4] = p[0]; z[5] = p[7];
- z[6] = p[2]; z[7] = p[5];
-
- if (first && box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[4] += left;
- square_end_1 = true;
- }
-
- if (last && box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[2] -= right;
- square_end_2 = true;
- }
-
- res = html_redraw_border_plot(BOTTOM, z, col,
- box->border[BOTTOM].style,
- bottom, square_end_1 && square_end_2,
- clip, ctx);
- if (res != NSERROR_OK) {
- return false;
- }
- }
-
- return true;
-}
-
/**
* Plot a checkbox.
diff --git a/render/html_redraw_border.c b/render/html_redraw_border.c
new file mode 100644
index 0000000..07c503c
--- /dev/null
+++ b/render/html_redraw_border.c
@@ -0,0 +1,928 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Redrawing CONTENT_HTML borders implementation.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "utils/log.h"
+#include "netsurf/plotters.h"
+#include "netsurf/css.h"
+
+#include "render/box.h"
+#include "render/html_internal.h"
+
+
+static plot_style_t plot_style_bdr = {
+ .stroke_type = PLOT_OP_TYPE_DASH,
+};
+static plot_style_t plot_style_fillbdr = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_light = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_ddark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dlight = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+
+static inline nserror
+plot_clipped_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *clip,
+ struct rect *rect)
+{
+ nserror res;
+
+ rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
+ rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
+ rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
+ rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
+ if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
+ /* valid clip rectangles only */
+ res = ctx->plot->rectangle(ctx, style, rect);
+ } else {
+ res = NSERROR_OK;
+ }
+ return res;
+}
+
+
+/**
+ * Draw one border.
+ *
+ * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
+ * \param p array of precomputed border vertices
+ * \param c colour for border
+ * \param style border line style
+ * \param thickness border thickness
+ * \param rectangular whether border is rectangular
+ * \param clip cliping area for redrawing border.
+ * \param ctx current redraw context
+ * \return NSERROR_OK if successful otherwise appropriate error code
+ */
+static nserror
+html_redraw_border_plot(const int side,
+ const int *p,
+ colour c,
+ enum css_border_style_e style,
+ int thickness,
+ bool rectangular,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ int z[8]; /* Vertices of border part */
+ unsigned int light = side;
+ plot_style_t *plot_style_bdr_in;
+ plot_style_t *plot_style_bdr_out;
+ nserror res = NSERROR_OK;
+ struct rect rect;
+
+ if (c == NS_TRANSPARENT) {
+ return res;
+ }
+
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
+ plot_style_bdr.stroke_colour = c;
+ plot_style_bdr.stroke_width = thickness;
+ plot_style_fillbdr.fill_colour = c;
+ plot_style_fillbdr_dark.fill_colour = darken_colour(c);
+ plot_style_fillbdr_light.fill_colour = lighten_colour(c);
+ plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
+ plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
+
+ switch (style) {
+ case CSS_BORDER_STYLE_DOTTED:
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
+ /* fall through */
+ case CSS_BORDER_STYLE_DASHED:
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = (p[4] + p[6]) / 2;
+ rect.y1 = (p[5] + p[7]) / 2;
+ res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
+ break;
+
+ case CSS_BORDER_STYLE_SOLID:
+ /* fall through to default */
+ default:
+ if (rectangular || thickness == 1) {
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ if ((side == TOP) &&
+ (p[4] - p[6] != 0)) {
+ rect.x1 = p[4];
+ } else {
+ rect.x1 = p[6];
+ }
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ if ((side == LEFT) &&
+ (p[1] - p[3] != 0)) {
+ rect.y1 = p[1];
+ } else {
+ rect.y1 = p[3];
+ }
+ }
+ res = plot_clipped_rectangle(ctx,
+ &plot_style_fillbdr,
+ clip,
+ &rect);
+ } else {
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
+ }
+ break;
+
+ case CSS_BORDER_STYLE_DOUBLE:
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] * 2 + p[2]) / 3;
+ z[3] = (p[1] * 2 + p[3]) / 3;
+ z[4] = (p[6] * 2 + p[4]) / 3;
+ z[5] = (p[7] * 2 + p[5]) / 3;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ if (res == NSERROR_OK) {
+ z[0] = p[2];
+ z[1] = p[3];
+ z[2] = (p[2] * 2 + p[0]) / 3;
+ z[3] = (p[3] * 2 + p[1]) / 3;
+ z[4] = (p[4] * 2 + p[6]) / 3;
+ z[5] = (p[5] * 2 + p[7]) / 3;
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ }
+ break;
+
+ case CSS_BORDER_STYLE_GROOVE:
+ light = 3 - light;
+ /* fall through */
+ case CSS_BORDER_STYLE_RIDGE:
+ /* choose correct colours for each part of the border line */
+ if (light <= 1) {
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ } else {
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be
+ * plotted with rectangles
+ */
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
+ } else {
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ }
+ } else {
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
+ */
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res == NSERROR_OK) {
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx,
+ plot_style_bdr_out,
+ z,
+ 4);
+ }
+ }
+ break;
+
+ case CSS_BORDER_STYLE_INSET:
+ light = (light + 2) % 4;
+ /* fall through */
+ case CSS_BORDER_STYLE_OUTSET:
+ /* choose correct colours for each part of the border line */
+ switch (light) {
+ case 0:
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dlight;
+ break;
+ case 1:
+ plot_style_bdr_in = &plot_style_fillbdr_ddark;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ break;
+ case 2:
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_ddark;
+ break;
+ case 3:
+ plot_style_bdr_in = &plot_style_fillbdr_dlight;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ break;
+ default:
+ plot_style_bdr_in = &plot_style_fillbdr;
+ plot_style_bdr_out = &plot_style_fillbdr;
+ break;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be
+ * plotted with rectangles
+ */
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
+ } else {
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ }
+ } else {
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
+ */
+
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
+ }
+ break;
+ }
+
+ return res;
+}
+
+
+/**
+ * Draw borders for a box.
+ *
+ * \param box box to draw
+ * \param x_parent coordinate of left padding edge of parent of box
+ * \param y_parent coordinate of top padding edge of parent of box
+ * \param p_width width of padding box
+ * \param p_height height of padding box
+ * \param clip cliping area for redrawing border.
+ * \param scale scale for redraw
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+bool
+html_redraw_borders(struct box *box,
+ int x_parent,
+ int y_parent,
+ int p_width,
+ int p_height,
+ const struct rect *clip,
+ float scale,
+ const struct redraw_context *ctx)
+{
+ unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
+ int top = box->border[TOP].width;
+ int right = box->border[RIGHT].width;
+ int bottom = box->border[BOTTOM].width;
+ int left = box->border[LEFT].width;
+ int x, y;
+ unsigned int i, side;
+ int p[8]; /* Box border vertices */
+ int z[8]; /* Border vertices */
+ bool square_end_1 = false;
+ bool square_end_2 = false;
+ nserror res;
+
+ x = x_parent + box->x;
+ y = y_parent + box->y;
+
+ if (scale != 1.0) {
+ top *= scale;
+ right *= scale;
+ bottom *= scale;
+ left *= scale;
+ x *= scale;
+ y *= scale;
+ }
+
+ assert(box->style);
+
+ /* Calculate border vertices
+ *
+ * A----------------------+
+ * | \ / |
+ * | B--------------+ |
+ * | | | |
+ * | +--------------C |
+ * | / \ |
+ * +----------------------D
+ */
+ p[0] = x - left; p[1] = y - top; /* A */
+ p[2] = x; p[3] = y; /* B */
+ p[4] = x + p_width; p[5] = y + p_height; /* C */
+ p[6] = x + p_width + right; p[7] = y + p_height + bottom; /* D */
+
+ for (i = 0; i != 4; i++) {
+ colour col = 0;
+ side = sides[i]; /* plot order */
+
+ if (box->border[side].width == 0 ||
+ nscss_color_is_transparent(box->border[side].c)) {
+ continue;
+ }
+
+ switch (side) {
+ case LEFT:
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+
+ z[0] = p[0]; z[1] = p[7];
+ z[2] = p[2]; z[3] = p[5];
+ z[4] = p[2]; z[5] = p[3];
+ z[6] = p[0]; z[7] = p[1];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[5] -= top;
+ square_end_1 = true;
+ }
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[3] += bottom;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ break;
+
+ case RIGHT:
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+
+ z[0] = p[6]; z[1] = p[1];
+ z[2] = p[4]; z[3] = p[3];
+ z[4] = p[4]; z[5] = p[5];
+ z[6] = p[6]; z[7] = p[7];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[3] -= top;
+ square_end_1 = true;
+ }
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[5] += bottom;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ 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);
+
+ z[0] = p[2]; z[1] = p[3];
+ z[2] = p[0]; z[3] = p[1];
+ z[4] = p[6]; z[5] = p[1];
+ z[6] = p[4]; z[7] = p[3];
+
+ if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[2] += left;
+ square_end_1 = true;
+ }
+ if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[4] -= right;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ 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);
+
+ z[0] = p[4]; z[1] = p[5];
+ z[2] = p[6]; z[3] = p[7];
+ z[4] = p[0]; z[5] = p[7];
+ z[6] = p[2]; z[7] = p[5];
+
+ if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[4] += left;
+ square_end_1 = true;
+ }
+ if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[2] -= right;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ break;
+
+ default:
+ assert(side == TOP || side == BOTTOM ||
+ side == LEFT || side == RIGHT);
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Draw an inline's borders.
+ *
+ * \param box BOX_INLINE which created the border
+ * \param b coordinates of border edge rectangle
+ * \param clip cliping area for redrawing border.
+ * \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
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+bool
+html_redraw_inline_borders(struct box *box,
+ struct rect b,
+ const struct rect *clip,
+ float scale,
+ bool first,
+ bool last,
+ const struct redraw_context *ctx)
+{
+ int top = box->border[TOP].width;
+ int right = box->border[RIGHT].width;
+ int bottom = box->border[BOTTOM].width;
+ int left = box->border[LEFT].width;
+ colour col;
+ int p[8]; /* Box border vertices */
+ int z[8]; /* Border vertices */
+ bool square_end_1;
+ bool square_end_2;
+ nserror res;
+
+ if (scale != 1.0) {
+ top *= scale;
+ right *= scale;
+ bottom *= scale;
+ left *= scale;
+ }
+
+ /* Calculate border vertices
+ *
+ * A----------------------+
+ * | \ / |
+ * | B--------------+ |
+ * | | | |
+ * | +--------------C |
+ * | / \ |
+ * +----------------------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);
+
+ /* Left */
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+ if (left != 0 &&
+ first &&
+ nscss_color_is_transparent(box->border[LEFT].c) == false) {
+ col = nscss_color_to_ns(box->border[LEFT].c);
+
+ z[0] = p[0]; z[1] = p[7];
+ z[2] = p[2]; z[3] = p[5];
+ z[4] = p[2]; z[5] = p[3];
+ z[6] = p[0]; z[7] = p[1];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[5] -= top;
+ square_end_1 = true;
+ }
+
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[3] += bottom;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(LEFT,
+ z,
+ col,
+ box->border[LEFT].style,
+ left,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Right */
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+ if (right != 0 &&
+ last &&
+ nscss_color_is_transparent(box->border[RIGHT].c) == false) {
+ col = nscss_color_to_ns(box->border[RIGHT].c);
+
+ z[0] = p[6]; z[1] = p[1];
+ z[2] = p[4]; z[3] = p[3];
+ z[4] = p[4]; z[5] = p[5];
+ z[6] = p[6]; z[7] = p[7];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[3] -= top;
+ square_end_1 = true;
+ }
+
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[5] += bottom;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(RIGHT,
+ z,
+ col,
+ box->border[RIGHT].style,
+ right,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Top */
+ square_end_1 = (left == 0);
+ square_end_2 = (right == 0);
+ if (top != 0 &&
+ nscss_color_is_transparent(box->border[TOP].c) == false) {
+ col = nscss_color_to_ns(box->border[TOP].c);
+
+ z[0] = p[2]; z[1] = p[3];
+ z[2] = p[0]; z[3] = p[1];
+ z[4] = p[6]; z[5] = p[1];
+ z[6] = p[4]; z[7] = p[3];
+
+ if (first &&
+ box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[2] += left;
+ square_end_1 = true;
+ }
+
+ if (last &&
+ box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[4] -= right;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(TOP,
+ z,
+ col,
+ box->border[TOP].style,
+ top,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Bottom */
+ square_end_1 = (left == 0);
+ square_end_2 = (right == 0);
+ if (bottom != 0 &&
+ nscss_color_is_transparent(box->border[BOTTOM].c) == false) {
+ col = nscss_color_to_ns(box->border[BOTTOM].c);
+
+ z[0] = p[4]; z[1] = p[5];
+ z[2] = p[6]; z[3] = p[7];
+ z[4] = p[0]; z[5] = p[7];
+ z[6] = p[2]; z[7] = p[5];
+
+ if (first &&
+ box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[4] += left;
+ square_end_1 = true;
+ }
+
+ if (last &&
+ box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[2] -= right;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(BOTTOM,
+ z,
+ col,
+ box->border[BOTTOM].style,
+ bottom,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ return true;
+}
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=c5b530964aaa06c352c...
commit c5b530964aaa06c352cf147eb26768c8b438341a
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
simplify html redraw border plotting error handling
diff --git a/render/html_redraw.c b/render/html_redraw.c
index dd63628..e58918d 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -398,7 +398,7 @@ plot_clipped_rectangle(const struct redraw_context *ctx,
* \return true if successful, false otherwise
*/
-static bool
+static nserror
html_redraw_border_plot(const int side,
const int *p,
colour c,
@@ -412,11 +412,12 @@ html_redraw_border_plot(const int side,
unsigned int light = side;
plot_style_t *plot_style_bdr_in;
plot_style_t *plot_style_bdr_out;
- nserror res;
+ nserror res = NSERROR_OK;
struct rect rect;
- if (c == NS_TRANSPARENT)
- return true;
+ if (c == NS_TRANSPARENT) {
+ return res;
+ }
plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
plot_style_bdr.stroke_colour = c;
@@ -437,9 +438,6 @@ html_redraw_border_plot(const int side,
rect.x1 = (p[4] + p[6]) / 2;
rect.y1 = (p[5] + p[7]) / 2;
res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
break;
case CSS_BORDER_STYLE_SOLID:
@@ -469,14 +467,8 @@ html_redraw_border_plot(const int side,
}
}
res = plot_clipped_rectangle(ctx, &plot_style_fillbdr, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
} else {
res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
- if (res != NSERROR_OK) {
- return false;
- }
}
break;
@@ -490,27 +482,22 @@ html_redraw_border_plot(const int side,
z[6] = p[6];
z[7] = p[7];
res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[2] = (p[2] * 2 + p[0]) / 3;
- z[3] = (p[3] * 2 + p[1]) / 3;
- z[4] = (p[4] * 2 + p[6]) / 3;
- z[5] = (p[5] * 2 + p[7]) / 3;
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- if (res != NSERROR_OK) {
- return false;
+ if (res == NSERROR_OK) {
+ z[0] = p[2];
+ z[1] = p[3];
+ z[2] = (p[2] * 2 + p[0]) / 3;
+ z[3] = (p[3] * 2 + p[1]) / 3;
+ z[4] = (p[4] * 2 + p[6]) / 3;
+ z[5] = (p[5] * 2 + p[7]) / 3;
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
}
break;
case CSS_BORDER_STYLE_GROOVE:
light = 3 - light;
/* fall through */
-
case CSS_BORDER_STYLE_RIDGE:
/* choose correct colours for each part of the border line */
if (light <= 1) {
@@ -523,8 +510,8 @@ html_redraw_border_plot(const int side,
/* Render border */
if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles
+ /* Border made up from two parts and can be
+ * plotted with rectangles
*/
/* First part */
@@ -541,7 +528,7 @@ html_redraw_border_plot(const int side,
}
res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
if (res != NSERROR_OK) {
- return false;
+ return res;
}
/* Second part */
@@ -557,12 +544,10 @@ html_redraw_border_plot(const int side,
rect.y1 = p[3];
}
res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
} else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
if (side == TOP || side == RIGHT) {
rect.x0 = p[2];
@@ -573,9 +558,6 @@ html_redraw_border_plot(const int side,
rect.x1 + p[4] - p[6] : rect.x1;
res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
} else {
rect.x0 = p[6];
rect.y0 = p[7];
@@ -584,13 +566,10 @@ html_redraw_border_plot(const int side,
rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
rect.y1 + p[1] - p[3] : rect.y1;
res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
}
} else {
- /* Border made up from two parts and can't be plotted
- * with rectangles
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
*/
z[0] = p[0];
z[1] = p[1];
@@ -602,16 +581,13 @@ html_redraw_border_plot(const int side,
z[7] = p[7];
res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
if (res != NSERROR_OK) {
- return false;
+ return res;
}
z[0] = p[2];
z[1] = p[3];
z[6] = p[4];
z[7] = p[5];
res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
}
break;
@@ -645,8 +621,8 @@ html_redraw_border_plot(const int side,
/* Render border */
if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles
+ /* Border made up from two parts and can be
+ * plotted with rectangles
*/
/* First part */
@@ -663,7 +639,7 @@ html_redraw_border_plot(const int side,
}
res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
if (res != NSERROR_OK) {
- return false;
+ return res;
}
/* Second part */
@@ -679,12 +655,10 @@ html_redraw_border_plot(const int side,
rect.y1 = p[3];
}
res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
} else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
if (side == TOP || side == RIGHT) {
rect.x0 = p[2];
@@ -694,9 +668,6 @@ html_redraw_border_plot(const int side,
rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
rect.x1 + p[4] - p[6] : rect.x1;
res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
} else {
rect.x0 = p[6];
rect.y0 = p[7];
@@ -705,14 +676,12 @@ html_redraw_border_plot(const int side,
rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
rect.y1 + p[1] - p[3] : rect.y1;
res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
}
} else {
- /* Border made up from two parts and can't be plotted
- * with rectangles
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
*/
+
z[0] = p[0];
z[1] = p[1];
z[2] = (p[0] + p[2]) / 2;
@@ -723,21 +692,18 @@ html_redraw_border_plot(const int side,
z[7] = p[7];
res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
if (res != NSERROR_OK) {
- return false;
+ return res;
}
z[0] = p[2];
z[1] = p[3];
z[6] = p[4];
z[7] = p[5];
res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
}
break;
}
- return true;
+ return res;
}
@@ -770,6 +736,7 @@ static bool html_redraw_borders(struct box *box, int x_parent, int
y_parent,
int z[8]; /* Border vertices */
bool square_end_1 = false;
bool square_end_2 = false;
+ nserror res;
x = x_parent + box->x;
y = y_parent + box->y;
@@ -839,13 +806,19 @@ static bool html_redraw_borders(struct box *box, int x_parent, int
y_parent,
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, ctx))
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
+
case RIGHT:
square_end_1 = (top == 0);
square_end_2 = (bottom == 0);
@@ -876,13 +849,19 @@ static bool html_redraw_borders(struct box *box, int x_parent, int
y_parent,
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, ctx))
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
+
case TOP:
if (clip->y0 > p[3])
/* clip rectangle is below border; nothing to
@@ -918,13 +897,19 @@ static bool html_redraw_borders(struct box *box, int x_parent, int
y_parent,
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, ctx))
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
+
case BOTTOM:
if (clip->y1 < p[5])
/* clip rectangle is above border; nothing to
@@ -960,13 +945,19 @@ static bool html_redraw_borders(struct box *box, int x_parent, int
y_parent,
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, ctx))
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
+
default:
assert(side == TOP || side == BOTTOM ||
side == LEFT || side == RIGHT);
@@ -1004,6 +995,7 @@ static bool html_redraw_inline_borders(struct box *box, struct rect
b,
int z[8]; /* Border vertices */
bool square_end_1;
bool square_end_2;
+ nserror res;
if (scale != 1.0) {
top *= scale;
@@ -1060,11 +1052,17 @@ static bool html_redraw_inline_borders(struct box *box, struct
rect b,
square_end_2 = true;
}
- if (!html_redraw_border_plot(LEFT, z, col,
- box->border[LEFT].style,
- left, square_end_1 && square_end_2,
- clip, ctx))
+ res = html_redraw_border_plot(LEFT,
+ z,
+ col,
+ box->border[LEFT].style,
+ left,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
}
/* Right */
@@ -1098,11 +1096,13 @@ static bool html_redraw_inline_borders(struct box *box, struct
rect b,
square_end_2 = true;
}
- if (!html_redraw_border_plot(RIGHT, z, col,
+ res = html_redraw_border_plot(RIGHT, z, col,
box->border[RIGHT].style,
right, square_end_1 && square_end_2,
- clip, ctx))
+ clip, ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
}
/* Top */
@@ -1137,11 +1137,13 @@ static bool html_redraw_inline_borders(struct box *box, struct
rect b,
square_end_2 = true;
}
- if (!html_redraw_border_plot(TOP, z, col,
+ res = html_redraw_border_plot(TOP, z, col,
box->border[TOP].style,
top, square_end_1 && square_end_2,
- clip, ctx))
+ clip, ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
}
/* Bottom */
@@ -1176,11 +1178,13 @@ static bool html_redraw_inline_borders(struct box *box, struct
rect b,
square_end_2 = true;
}
- if (!html_redraw_border_plot(BOTTOM, z, col,
+ res = html_redraw_border_plot(BOTTOM, z, col,
box->border[BOTTOM].style,
bottom, square_end_1 && square_end_2,
- clip, ctx))
+ clip, ctx);
+ if (res != NSERROR_OK) {
return false;
+ }
}
return true;
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=4545083e2b4d173522a...
commit 4545083e2b4d173522a2cf3274824e6f0d2564cd
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
fix up gtk plotters to use new api
diff --git a/frontends/gtk/layout_pango.c b/frontends/gtk/layout_pango.c
index 7c71909..bad57d6 100644
--- a/frontends/gtk/layout_pango.c
+++ b/frontends/gtk/layout_pango.c
@@ -222,7 +222,7 @@ nsfont_split(const plot_font_style_t *fstyle,
* \param fstyle plot style for this text
* \return true on success, false on error and error reported
*/
-bool nsfont_paint(int x, int y, const char *string, size_t length,
+nserror nsfont_paint(int x, int y, const char *string, size_t length,
const plot_font_style_t *fstyle)
{
PangoFontDescription *desc;
@@ -230,7 +230,7 @@ bool nsfont_paint(int x, int y, const char *string, size_t length,
PangoLayoutLine *line;
if (length == 0)
- return true;
+ return NSERROR_OK;
layout = pango_cairo_create_layout(current_cr);
@@ -247,7 +247,7 @@ bool nsfont_paint(int x, int y, const char *string, size_t length,
g_object_unref(layout);
- return true;
+ return NSERROR_OK;
}
diff --git a/frontends/gtk/layout_pango.h b/frontends/gtk/layout_pango.h
index 137cebe..7ce107a 100644
--- a/frontends/gtk/layout_pango.h
+++ b/frontends/gtk/layout_pango.h
@@ -30,7 +30,7 @@ struct plot_font_style;
extern struct gui_layout_table *nsgtk_layout_table;
-bool nsfont_paint(int x, int y, const char *string, size_t length, const struct
plot_font_style *fstyle);
+nserror nsfont_paint(int x, int y, const char *string, size_t length, const struct
plot_font_style *fstyle);
/**
* Convert a plot style to a PangoFontDescription.
diff --git a/frontends/gtk/plotters.c b/frontends/gtk/plotters.c
index 817b728..4d795e5 100644
--- a/frontends/gtk/plotters.c
+++ b/frontends/gtk/plotters.c
@@ -77,8 +77,17 @@ static inline void nsgtk_set_dashed(void)
cairo_set_dash(current_cr, cdashes, 2, 0);
}
-/** Set clipping area for subsequent plot operations. */
-static bool nsgtk_plot_clip(const struct rect *clip)
+
+/**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
cairo_reset_clip(current_cr);
cairo_rectangle(current_cr, clip->x0, clip->y0,
@@ -90,11 +99,24 @@ static bool nsgtk_plot_clip(const struct rect *clip)
cliprect.width = clip->x1 - clip->x0;
cliprect.height = clip->y1 - clip->y0;
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_plot_arc(int x, int y, int radius, int angle1, int angle2, const
plot_style_t *style)
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
nsgtk_set_colour(style->fill_colour);
nsgtk_set_solid();
@@ -105,10 +127,22 @@ static bool nsgtk_plot_arc(int x, int y, int radius, int angle1, int
angle2, con
(angle2 + 90) * (M_PI / 180));
cairo_stroke(current_cr);
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_plot_disc(int x, int y, int radius, const plot_style_t *style)
+/**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the circle plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsgtk_set_colour(style->fill_colour);
@@ -147,11 +181,24 @@ static bool nsgtk_plot_disc(int x, int y, int radius, const
plot_style_t *style)
cairo_stroke(current_cr);
}
- return true;
+ return NSERROR_OK;
}
-static bool
-nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+
+/**
+ * Plots a line
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the line plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
nsgtk_set_colour(style->stroke_colour);
@@ -180,16 +227,20 @@ nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t
*style)
cairo_set_line_width(current_cr, style->stroke_width);
/* core expects horizontal and vertical lines to be on pixels, not
- * between pixels */
- cairo_move_to(current_cr, (x0 == x1) ? x0 + 0.5 : x0,
- (y0 == y1) ? y0 + 0.5 : y0);
- cairo_line_to(current_cr, (x0 == x1) ? x1 + 0.5 : x1,
- (y0 == y1) ? y1 + 0.5 : y1);
+ * between pixels
+ */
+ cairo_move_to(current_cr,
+ (line->x0 == line->x1) ? line->x0 + 0.5 : line->x0,
+ (line->y0 == line->y1) ? line->y0 + 0.5 : line->y0);
+ cairo_line_to(current_cr,
+ (line->x0 == line->x1) ? line->x1 + 0.5 : line->x1,
+ (line->y0 == line->y1) ? line->y1 + 0.5 : line->y1);
cairo_stroke(current_cr);
- return true;
+ return NSERROR_OK;
}
+
/** Plot a caret.
*
* @note It is assumed that the plotters have been set up.
@@ -207,14 +258,34 @@ void nsgtk_plot_caret(int x, int y, int h)
cairo_stroke(current_cr);
}
-static bool nsgtk_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t
*style)
+
+/**
+ * Plots a rectangle.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the rectangle plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsgtk_set_colour(style->fill_colour);
nsgtk_set_solid();
cairo_set_line_width(current_cr, 0);
- cairo_rectangle(current_cr, x0, y0, x1 - x0, y1 - y0);
+ cairo_rectangle(current_cr,
+ rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
cairo_fill(current_cr);
cairo_stroke(current_cr);
}
@@ -242,13 +313,23 @@ static bool nsgtk_plot_rectangle(int x0, int y0, int x1, int y1,
const plot_styl
else
cairo_set_line_width(current_cr, style->stroke_width);
- cairo_rectangle(current_cr, x0 + 0.5, y0 + 0.5, x1 - x0, y1 - y0);
+ cairo_rectangle(current_cr,
+ rect->x0 + 0.5,
+ rect->y0 + 0.5,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
cairo_stroke(current_cr);
}
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+
+
+static nserror
+nsgtk_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
unsigned int i;
@@ -263,22 +344,29 @@ static bool nsgtk_plot_polygon(const int *p, unsigned int n, const
plot_style_t
cairo_fill(current_cr);
cairo_stroke(current_cr);
- return true;
+ return NSERROR_OK;
}
-
-
-static bool nsgtk_plot_text(int x, int y, const char *text, size_t length,
- const struct plot_font_style *fstyle)
+static nserror
+nsgtk_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
return nsfont_paint(x, y, text, length, fstyle);
}
-static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg)
+/**
+ * plot a pixbuf
+ */
+static nserror
+nsgtk_plot_pixbuf(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg)
{
int x0, y0, x1, y1;
int dsrcx, dsrcy, dwidth, dheight;
@@ -289,13 +377,13 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
/* Bail early if we can */
if (width == 0 || height == 0)
/* Nothing to plot */
- return true;
+ return NSERROR_OK;
if ((x > (cliprect.x + cliprect.width)) ||
((x + width) < cliprect.x) ||
(y > (cliprect.y + cliprect.height)) ||
((y + height) < cliprect.y)) {
/* Image completely outside clip region */
- return true;
+ return NSERROR_OK;
}
/* Get clip rectangle / image rectangle edge differences */
@@ -332,7 +420,7 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
if (dwidth == 0 || dheight == 0)
/* Nothing to plot */
- return true;
+ return NSERROR_OK;
bmwidth = cairo_image_surface_get_width(bmsurface);
bmheight = cairo_image_surface_get_height(bmsurface);
@@ -388,12 +476,34 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
}
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+
+/**
+ * Plot a bitmap
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width, int height,
+ colour bg,
+ bitmap_flags_t flags)
{
int doneheight = 0, donewidth = 0;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
@@ -402,7 +512,7 @@ static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
/* Bail early if we can */
if (width == 0 || height == 0)
/* Nothing to plot */
- return true;
+ return NSERROR_OK;
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just pass it on */
@@ -435,21 +545,41 @@ static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
break;
}
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
+
+/**
+ * Plots a path.
+ *
+ * Path plot consisting of cubic Bezier curves. Line and fill colour is
+ * controlled by the plot style.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param width The width of the path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
unsigned int i;
cairo_matrix_t old_ctm, n_ctm;
if (n == 0)
- return true;
+ return NSERROR_OK;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("Path does not start with move");
- return false;
+ return NSERROR_INVALID;
}
@@ -490,7 +620,7 @@ static bool nsgtk_plot_path(const float *p, unsigned int n, colour
fill, float w
LOG("bad path command %f", p[i]);
/* Reset matrix for safety */
cairo_set_matrix(current_cr, &old_ctm);
- return false;
+ return NSERROR_INVALID;
}
}
@@ -498,25 +628,25 @@ static bool nsgtk_plot_path(const float *p, unsigned int n, colour
fill, float w
cairo_set_matrix(current_cr, &old_ctm);
/* Now draw path */
- if (fill != NS_TRANSPARENT) {
- nsgtk_set_colour(fill);
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ nsgtk_set_colour(pstyle->fill_colour);
- if (c != NS_TRANSPARENT) {
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
/* Fill & Stroke */
cairo_fill_preserve(current_cr);
- nsgtk_set_colour(c);
+ nsgtk_set_colour(pstyle->stroke_colour);
cairo_stroke(current_cr);
} else {
/* Fill only */
cairo_fill(current_cr);
}
- } else if (c != NS_TRANSPARENT) {
+ } else if (pstyle->stroke_colour != NS_TRANSPARENT) {
/* Stroke only */
- nsgtk_set_colour(c);
+ nsgtk_set_colour(pstyle->stroke_colour);
cairo_stroke(current_cr);
}
- return true;
+ return NSERROR_OK;
}
/** GTK plotter table */
@@ -532,6 +662,3 @@ const struct plotter_table nsgtk_plotters = {
.text = nsgtk_plot_text,
.option_knockout = true
};
-
-
-
diff --git a/frontends/gtk/scaffolding.c b/frontends/gtk/scaffolding.c
index bbc568e..06b51de 100644
--- a/frontends/gtk/scaffolding.c
+++ b/frontends/gtk/scaffolding.c
@@ -1706,7 +1706,7 @@ nsgtk_history_draw_event(GtkWidget *widget, GdkEventExpose *event,
gpointer g)
clip.y0 = event->area.y;
clip.x1 = event->area.x + event->area.width;
clip.y1 = event->area.y + event->area.height;
- ctx.plot->clip(&clip);
+ ctx.plot->clip(&ctx, &clip);
browser_window_history_redraw(bw, &ctx);
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=06e8b32dbfac5025053...
commit 06e8b32dbfac5025053e4902995cd4656111c049
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Update knockout plotter to use new API
diff --git a/content/content.c b/content/content.c
index 2719db8..70df87e 100644
--- a/content/content.c
+++ b/content/content.c
@@ -628,7 +628,7 @@ bool content_scaled_redraw(struct hlcache_handle *h,
plot_ok &= c->handler->redraw(c, &data, &clip, &new_ctx);
if (ctx->plot->option_knockout) {
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
return plot_ok;
diff --git a/desktop/browser.c b/desktop/browser.c
index 442208c..3a7ac0e 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -238,7 +238,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
*/
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: knockout end */
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
return plot_ok;
@@ -314,7 +314,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: end knockout */
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
return plot_ok;
diff --git a/desktop/knockout.c b/desktop/knockout.c
index bcfc272..96e7b1a 100644
--- a/desktop/knockout.c
+++ b/desktop/knockout.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
- * Knockout rendering (implementation).
+/**
+ * \file
+ * Knockout rendering implementation.
*
* Knockout rendering is an optimisation which is particularly for
* unaccelerated screen redraw. It tries to avoid plotting the same area more
@@ -86,47 +87,6 @@
struct knockout_box;
struct knockout_entry;
-
-static void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box
*box);
-static bool knockout_plot_fill_recursive(struct knockout_box *box, plot_style_t
*plot_style);
-static bool knockout_plot_bitmap_recursive(struct knockout_box *box,
- struct knockout_entry *entry);
-
-static bool knockout_plot_line(int x0, int y0, int x1, int y1, const plot_style_t
*pstyle);
-static bool knockout_plot_polygon(const int *p, unsigned int n, const plot_style_t
*pstyle);
-static bool knockout_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t
*plot_style);
-static bool knockout_plot_clip(const struct rect *clip);
-static bool knockout_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool knockout_plot_disc(int x, int y, int radius, const plot_style_t *pstyle);
-static bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, const
plot_style_t *pstyle);
-static bool knockout_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
-static bool knockout_plot_flush(void);
-static bool knockout_plot_group_start(const char *name);
-static bool knockout_plot_group_end(void);
-static bool knockout_plot_path(const float *p, unsigned int n, colour fill,
- float width, colour c, const float transform[6]);
-
-
-const struct plotter_table knockout_plotters = {
- .rectangle = knockout_plot_rectangle,
- .line = knockout_plot_line,
- .polygon = knockout_plot_polygon,
- .clip = knockout_plot_clip,
- .text = knockout_plot_text,
- .disc = knockout_plot_disc,
- .arc = knockout_plot_arc,
- .bitmap = knockout_plot_bitmap,
- .group_start = knockout_plot_group_start,
- .group_end = knockout_plot_group_end,
- .flush = knockout_plot_flush,
- .path = knockout_plot_path,
- .option_knockout = true,
-};
-
-
typedef enum {
KNOCKOUT_PLOT_RECTANGLE,
KNOCKOUT_PLOT_LINE,
@@ -155,17 +115,11 @@ struct knockout_entry {
struct knockout_box *box; /* relating series of knockout clips */
union {
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect r;
plot_style_t plot_style;
} rectangle;
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect l;
plot_style_t plot_style;
} line;
struct {
@@ -174,10 +128,7 @@ struct knockout_entry {
plot_style_t plot_style;
} polygon;
struct {
- int x0;
- int y0;
- int x1;
- int y1;
+ struct rect r;
plot_style_t plot_style;
} fill;
struct rect clip;
@@ -231,64 +182,88 @@ static struct plotter_table real_plot;
static struct rect clip_cur;
static int nested_depth = 0;
+
/**
- * Start a knockout plotting session
- *
- * \param ctx the redraw context with real plotter table
- * \param knk_ctx updated to copy of ctx, with plotter table replaced
- * \return true on success, false otherwise
+ * fill an area recursively
*/
-bool knockout_plot_start(const struct redraw_context *ctx,
- struct redraw_context *knk_ctx)
+static nserror
+knockout_plot_fill_recursive(const struct redraw_context *ctx,
+ struct knockout_box *box,
+ plot_style_t *plot_style)
{
- /* check if we're recursing */
- if (nested_depth++ > 0) {
- /* we should already have the knockout renderer as default */
- assert(ctx->plot->rectangle == knockout_plotters.rectangle);
- *knk_ctx = *ctx;
- return true;
- }
-
- /* end any previous sessions */
- if (knockout_entry_cur > 0)
- knockout_plot_end();
-
- /* get copy of real plotter table */
- real_plot = *(ctx->plot);
+ struct knockout_box *parent;
+ nserror res;
+ nserror ffres = NSERROR_OK; /* first failing result */
- /* set up knockout rendering context */
- *knk_ctx = *ctx;
- knk_ctx->plot = &knockout_plotters;
- return true;
+ for (parent = box; parent; parent = parent->next) {
+ if (parent->deleted)
+ continue;
+ if (parent->child) {
+ res = knockout_plot_fill_recursive(ctx,
+ parent->child,
+ plot_style);
+ } else {
+ res = real_plot.rectangle(ctx, plot_style, &parent->bbox);
+ }
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ }
+ return ffres;
}
/**
- * End a knockout plotting session
- *
- * \return true on success, false otherwise
+ * bitmap plot recusivley
*/
-bool knockout_plot_end(void)
+static nserror
+knockout_plot_bitmap_recursive(const struct redraw_context *ctx,
+ struct knockout_box *box,
+ struct knockout_entry *entry)
{
- /* only output when we've finished any nesting */
- if (--nested_depth == 0)
- return knockout_plot_flush();
+ nserror res;
+ nserror ffres = NSERROR_OK; /* first failing result */
+ struct knockout_box *parent;
- assert(nested_depth > 0);
- return true;
-}
+ for (parent = box; parent; parent = parent->next) {
+ if (parent->deleted)
+ continue;
+ if (parent->child) {
+ res = knockout_plot_bitmap_recursive(ctx,
+ parent->child,
+ entry);
+ } else {
+ real_plot.clip(ctx, &parent->bbox);
+ res = real_plot.bitmap(ctx,
+ entry->data.bitmap.bitmap,
+ entry->data.bitmap.x,
+ entry->data.bitmap.y,
+ entry->data.bitmap.width,
+ entry->data.bitmap.height,
+ entry->data.bitmap.bg,
+ entry->data.bitmap.flags);
+ }
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ }
+ return ffres;
+}
/**
* Flush the current knockout session to empty the buffers
*
* \return true on success, false otherwise
*/
-bool knockout_plot_flush(void)
+static nserror knockout_plot_flush(const struct redraw_context *ctx)
{
int i;
- bool success = true;
struct knockout_box *box;
+ nserror res; /* operation result */
+ nserror ffres = NSERROR_OK; /* first failing result */
/* debugging information */
#ifdef KNOCKOUT_DEBUG
@@ -298,99 +273,100 @@ bool knockout_plot_flush(void)
for (i = 0; i < knockout_entry_cur; i++) {
switch (knockout_entries[i].type) {
case KNOCKOUT_PLOT_RECTANGLE:
- success &= real_plot.rectangle(
- knockout_entries[i].data.rectangle.x0,
- knockout_entries[i].data.rectangle.y0,
- knockout_entries[i].data.rectangle.x1,
- knockout_entries[i].data.rectangle.y1,
- &knockout_entries[i].data.rectangle.plot_style);
+ res = real_plot.rectangle(ctx,
+ &knockout_entries[i].data.rectangle.plot_style,
+ &knockout_entries[i].data.rectangle.r);
break;
+
case KNOCKOUT_PLOT_LINE:
- success &= real_plot.line(
- knockout_entries[i].data.line.x0,
- knockout_entries[i].data.line.y0,
- knockout_entries[i].data.line.x1,
- knockout_entries[i].data.line.y1,
- &knockout_entries[i].data.line.plot_style);
+ res = real_plot.line(ctx,
+ &knockout_entries[i].data.line.plot_style,
+ &knockout_entries[i].data.line.l);
break;
+
case KNOCKOUT_PLOT_POLYGON:
- success &= real_plot.polygon(
- knockout_entries[i].data.polygon.p,
- knockout_entries[i].data.polygon.n,
- &knockout_entries[i].data.polygon.plot_style);
+ res = real_plot.polygon(ctx,
+ &knockout_entries[i].data.polygon.plot_style,
+ knockout_entries[i].data.polygon.p,
+ knockout_entries[i].data.polygon.n);
break;
+
case KNOCKOUT_PLOT_FILL:
box = knockout_entries[i].box->child;
- if (box)
- success &= knockout_plot_fill_recursive(box,
- &knockout_entries[i].data.fill.plot_style);
- else if (!knockout_entries[i].box->deleted)
- success &= real_plot.rectangle(
- knockout_entries[i].data.fill.x0,
- knockout_entries[i].data.fill.y0,
- knockout_entries[i].data.fill.x1,
- knockout_entries[i].data.fill.y1,
- &knockout_entries[i].data.fill.plot_style);
+ if (box) {
+ res = knockout_plot_fill_recursive(ctx,
+ box,
+ &knockout_entries[i].data.fill.plot_style);
+ } else if (!knockout_entries[i].box->deleted) {
+ res = real_plot.rectangle(ctx,
+ &knockout_entries[i].data.fill.plot_style,
+ &knockout_entries[i].data.fill.r);
+ }
break;
+
case KNOCKOUT_PLOT_CLIP:
- success &= real_plot.clip(
- &knockout_entries[i].data.clip);
+ res = real_plot.clip(ctx, &knockout_entries[i].data.clip);
break;
+
case KNOCKOUT_PLOT_TEXT:
- success &= real_plot.text(
+ res = real_plot.text(ctx,
+ &knockout_entries[i].data.text.font_style,
knockout_entries[i].data.text.x,
knockout_entries[i].data.text.y,
knockout_entries[i].data.text.text,
- knockout_entries[i].data.text.length,
- &knockout_entries[i].data.text.font_style);
+ knockout_entries[i].data.text.length);
break;
+
case KNOCKOUT_PLOT_DISC:
- success &= real_plot.disc(
+ res = real_plot.disc(ctx,
+ &knockout_entries[i].data.disc.plot_style,
knockout_entries[i].data.disc.x,
knockout_entries[i].data.disc.y,
- knockout_entries[i].data.disc.radius,
- &knockout_entries[i].data.disc.plot_style);
+ knockout_entries[i].data.disc.radius);
break;
+
case KNOCKOUT_PLOT_ARC:
- success &= real_plot.arc(
+ res = real_plot.arc(ctx,
+ &knockout_entries[i].data.arc.plot_style,
knockout_entries[i].data.arc.x,
knockout_entries[i].data.arc.y,
knockout_entries[i].data.arc.radius,
knockout_entries[i].data.arc.angle1,
- knockout_entries[i].data.arc.angle2,
- &knockout_entries[i].data.arc.plot_style);
+ knockout_entries[i].data.arc.angle2);
break;
+
case KNOCKOUT_PLOT_BITMAP:
box = knockout_entries[i].box->child;
if (box) {
- success &= knockout_plot_bitmap_recursive(box,
+ res = knockout_plot_bitmap_recursive(ctx,
+ box,
&knockout_entries[i]);
} else if (!knockout_entries[i].box->deleted) {
- success &= real_plot.bitmap(
- knockout_entries[i].data.
- bitmap.x,
- knockout_entries[i].data.
- bitmap.y,
- knockout_entries[i].data.
- bitmap.width,
- knockout_entries[i].data.
- bitmap.height,
- knockout_entries[i].data.
- bitmap.bitmap,
- knockout_entries[i].data.
- bitmap.bg,
- knockout_entries[i].data.
- bitmap.flags);
+ res = real_plot.bitmap(ctx,
+ knockout_entries[i].data.bitmap.bitmap,
+ knockout_entries[i].data.bitmap.x,
+ knockout_entries[i].data.bitmap.y,
+ knockout_entries[i].data.bitmap.width,
+ knockout_entries[i].data.bitmap.height,
+ knockout_entries[i].data.bitmap.bg,
+ knockout_entries[i].data.bitmap.flags);
}
break;
+
case KNOCKOUT_PLOT_GROUP_START:
- success &= real_plot.group_start(
- knockout_entries[i].data.group_start.name);
+ res = real_plot.group_start(ctx,
+ knockout_entries[i].data.group_start.name);
break;
+
case KNOCKOUT_PLOT_GROUP_END:
- success &= real_plot.group_end();
+ res = real_plot.group_end(ctx);
break;
}
+
+ /* remember the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
}
knockout_entry_cur = 0;
@@ -398,7 +374,7 @@ bool knockout_plot_flush(void)
knockout_polygon_cur = 0;
knockout_list = NULL;
- return success;
+ return ffres;
}
@@ -410,8 +386,11 @@ bool knockout_plot_flush(void)
* \param x1 The right edge of the removal box
* \param y1 The top edge of the removal box
* \param owner The parent box set to consider, or NULL for top level
-*/
-void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *owner)
+ */
+static void
+knockout_calculate(const struct redraw_context *ctx,
+ int x0, int y0, int x1, int y1,
+ struct knockout_box *owner)
{
struct knockout_box *box;
struct knockout_box *parent;
@@ -464,11 +443,11 @@ void knockout_calculate(int x0, int y0, int x1, int y1, struct
knockout_box *own
/* has the box been replaced by children? */
if (parent->child) {
- knockout_calculate(x0, y0, x1, y1, parent);
+ knockout_calculate(ctx, x0, y0, x1, y1, parent);
} else {
/* we need a maximum of 4 child boxes */
if (knockout_box_cur + 4 >= KNOCKOUT_BOXES) {
- knockout_plot_flush();
+ knockout_plot_flush(ctx);
return;
}
@@ -527,136 +506,134 @@ void knockout_calculate(int x0, int y0, int x1, int y1, struct
knockout_box *own
}
-bool knockout_plot_fill_recursive(struct knockout_box *box, plot_style_t *plot_style)
-{
- bool success = true;
- struct knockout_box *parent;
-
- for (parent = box; parent; parent = parent->next) {
- if (parent->deleted)
- continue;
- if (parent->child)
- knockout_plot_fill_recursive(parent->child, plot_style);
- else
- success &= real_plot.rectangle(parent->bbox.x0,
- parent->bbox.y0,
- parent->bbox.x1,
- parent->bbox.y1,
- plot_style);
- }
- return success;
-}
-
-
-bool knockout_plot_bitmap_recursive(struct knockout_box *box,
- struct knockout_entry *entry)
-{
- bool success = true;
- struct knockout_box *parent;
-
- for (parent = box; parent; parent = parent->next) {
- if (parent->deleted)
- continue;
- if (parent->child)
- knockout_plot_bitmap_recursive(parent->child, entry);
- else {
- success &= real_plot.clip(&parent->bbox);
- success &= real_plot.bitmap(entry->data.bitmap.x,
- entry->data.bitmap.y,
- entry->data.bitmap.width,
- entry->data.bitmap.height,
- entry->data.bitmap.bitmap,
- entry->data.bitmap.bg,
- entry->data.bitmap.flags);
- }
- }
- return success;
-}
-
-bool knockout_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
+/**
+ * knockout rectangle plotting.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the rectangle plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *rect)
{
int kx0, ky0, kx1, ky1;
+ nserror res = NSERROR_OK;
- if (pstyle->fill_type != PLOT_OP_TYPE_NONE) {
+ if (pstyle->fill_type != PLOT_OP_TYPE_NONE) {
/* filled draw */
/* get our bounds */
- kx0 = (x0 > clip_cur.x0) ? x0 : clip_cur.x0;
- ky0 = (y0 > clip_cur.y0) ? y0 : clip_cur.y0;
- kx1 = (x1 < clip_cur.x1) ? x1 : clip_cur.x1;
- ky1 = (y1 < clip_cur.y1) ? y1 : clip_cur.y1;
+ kx0 = (rect->x0 > clip_cur.x0) ? rect->x0 : clip_cur.x0;
+ ky0 = (rect->y0 > clip_cur.y0) ? rect->y0 : clip_cur.y0;
+ kx1 = (rect->x1 < clip_cur.x1) ? rect->x1 : clip_cur.x1;
+ ky1 = (rect->y1 < clip_cur.y1) ? rect->y1 : clip_cur.y1;
if ((kx0 > clip_cur.x1) || (kx1 < clip_cur.x0) ||
- (ky0 > clip_cur.y1) || (ky1 < clip_cur.y0))
- return true;
+ (ky0 > clip_cur.y1) || (ky1 < clip_cur.y0)) {
+ return NSERROR_OK;
+ }
/* fills both knock out and get knocked out */
- knockout_calculate(kx0, ky0, kx1, ky1, NULL);
- knockout_boxes[knockout_box_cur].bbox.x0 = x0;
- knockout_boxes[knockout_box_cur].bbox.y0 = y0;
- knockout_boxes[knockout_box_cur].bbox.x1 = x1;
- knockout_boxes[knockout_box_cur].bbox.y1 = y1;
+ knockout_calculate(ctx, kx0, ky0, kx1, ky1, NULL);
+ knockout_boxes[knockout_box_cur].bbox = *rect;
knockout_boxes[knockout_box_cur].deleted = false;
knockout_boxes[knockout_box_cur].child = NULL;
knockout_boxes[knockout_box_cur].next = knockout_list;
knockout_list = &knockout_boxes[knockout_box_cur];
knockout_entries[knockout_entry_cur].box = &knockout_boxes[knockout_box_cur];
- knockout_entries[knockout_entry_cur].data.fill.x0 = x0;
- knockout_entries[knockout_entry_cur].data.fill.y0 = y0;
- knockout_entries[knockout_entry_cur].data.fill.x1 = x1;
- knockout_entries[knockout_entry_cur].data.fill.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.fill.r = *rect;
knockout_entries[knockout_entry_cur].data.fill.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].data.fill.plot_style.stroke_type =
PLOT_OP_TYPE_NONE; /* ensure we only plot the fill */
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_FILL;
if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) ||
- (++knockout_box_cur >= KNOCKOUT_BOXES))
- knockout_plot_flush();
- }
+ (++knockout_box_cur >= KNOCKOUT_BOXES)) {
+ res = knockout_plot_flush(ctx);
+ }
+ }
if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) {
/* draw outline */
- knockout_entries[knockout_entry_cur].data.rectangle.x0 = x0;
- knockout_entries[knockout_entry_cur].data.rectangle.y0 = y0;
- knockout_entries[knockout_entry_cur].data.rectangle.x1 = x1;
- knockout_entries[knockout_entry_cur].data.rectangle.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.rectangle.r = *rect;
knockout_entries[knockout_entry_cur].data.fill.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].data.fill.plot_style.fill_type =
PLOT_OP_TYPE_NONE; /* ensure we only plot the outline */
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_RECTANGLE;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- }
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ }
+ return res;
}
-bool knockout_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
+
+/**
+ * Knockout line plotting.
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at centre of
+ * line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the line plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *line)
{
- knockout_entries[knockout_entry_cur].data.line.x0 = x0;
- knockout_entries[knockout_entry_cur].data.line.y0 = y0;
- knockout_entries[knockout_entry_cur].data.line.x1 = x1;
- knockout_entries[knockout_entry_cur].data.line.y1 = y1;
+ knockout_entries[knockout_entry_cur].data.line.l = *line;
knockout_entries[knockout_entry_cur].data.line.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_LINE;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
}
-bool knockout_plot_polygon(const int *p, unsigned int n, const plot_style_t *pstyle)
+/**
+ * Knockout polygon plotting.
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the polygon plot.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const int *p,
+ unsigned int n)
{
- bool success = true;
int *dest;
+ nserror res;
+ nserror ffres = NSERROR_OK;
/* ensure we have sufficient room even when flushed */
if (n * 2 >= KNOCKOUT_POLYGONS) {
- knockout_plot_flush();
- success = real_plot.polygon(p, n, pstyle);
- return success;
+ ffres = knockout_plot_flush(ctx);
+ res = real_plot.polygon(ctx, pstyle, p, n);
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
/* ensure we have enough room right now */
- if (knockout_polygon_cur + n * 2 >= KNOCKOUT_POLYGONS)
- knockout_plot_flush();
+ if (knockout_polygon_cur + n * 2 >= KNOCKOUT_POLYGONS) {
+ ffres = knockout_plot_flush(ctx);
+ }
/* copy our data */
dest = &(knockout_polygons[knockout_polygon_cur]);
@@ -666,27 +643,64 @@ bool knockout_plot_polygon(const int *p, unsigned int n, const
plot_style_t *pst
knockout_entries[knockout_entry_cur].data.polygon.n = n;
knockout_entries[knockout_entry_cur].data.polygon.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_POLYGON;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_path(const float *p, unsigned int n, colour fill,
- float width, colour c, const float transform[6])
+/**
+ * knockout path plotting.
+ *
+ * The knockout implementation simply flushes the queue and plots the path
+ * directly using real plotter.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param width The width of the path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
- knockout_plot_flush();
- return real_plot.path(p, n, fill, width, c, transform);
+ nserror res;
+ nserror ffres;
+
+ ffres = knockout_plot_flush(ctx);
+ res = real_plot.path(ctx, pstyle, p, n, width, transform);
+
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_clip(const struct rect *clip)
+static nserror
+knockout_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
+ nserror res = NSERROR_OK;
+
if (clip->x1 < clip->x0 || clip->y0 > clip->y1) {
#ifdef KNOCKOUT_DEBUG
- LOG("bad clip rectangle %i %i %i %i", clip->x0, clip->y0, clip->x1,
clip->y1);
+ LOG("bad clip rectangle %i %i %i %i",
+ clip->x0, clip->y0, clip->x1, clip->y1);
#endif
- return false;
+ return NSERROR_BAD_SIZE;
}
/* memorise clip for bitmap tiling */
@@ -694,41 +708,97 @@ bool knockout_plot_clip(const struct rect *clip)
knockout_entries[knockout_entry_cur].data.clip = *clip;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_CLIP;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_text(const struct redraw_context *ctx,
+ const plot_font_style_t *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.text.x = x;
knockout_entries[knockout_entry_cur].data.text.y = y;
knockout_entries[knockout_entry_cur].data.text.text = text;
knockout_entries[knockout_entry_cur].data.text.length = length;
knockout_entries[knockout_entry_cur].data.text.font_style = *fstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_TEXT;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_disc(int x, int y, int radius, const plot_style_t *pstyle)
+/**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.disc.x = x;
knockout_entries[knockout_entry_cur].data.disc.y = y;
knockout_entries[knockout_entry_cur].data.disc.radius = radius;
knockout_entries[knockout_entry_cur].data.disc.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_DISC;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, const
plot_style_t *pstyle)
+
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius,
+ int angle1,
+ int angle2)
{
+ nserror res = NSERROR_OK;
+
knockout_entries[knockout_entry_cur].data.arc.x = x;
knockout_entries[knockout_entry_cur].data.arc.y = y;
knockout_entries[knockout_entry_cur].data.arc.radius = radius;
@@ -736,18 +806,41 @@ bool knockout_plot_arc(int x, int y, int radius, int angle1, int
angle2, const p
knockout_entries[knockout_entry_cur].data.arc.angle2 = angle2;
knockout_entries[knockout_entry_cur].data.arc.plot_style = *pstyle;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_ARC;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ res = knockout_plot_flush(ctx);
+ }
+ return res;
}
-
-bool knockout_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+/**
+ * knockout bitmap plotting.
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width, int height,
+ colour bg,
+ bitmap_flags_t flags)
{
int kx0, ky0, kx1, ky1;
+ nserror res;
+ nserror ffres = NSERROR_OK;
/* get our bounds */
kx0 = clip_cur.x0;
@@ -760,7 +853,7 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
if (x + width < kx1)
kx1 = x + width;
if ((kx0 > clip_cur.x1) || (kx1 < clip_cur.x0))
- return true;
+ return NSERROR_OK;
}
if (!(flags & BITMAPF_REPEAT_Y)) {
if (y > ky0)
@@ -768,12 +861,12 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
if (y + height < ky1)
ky1 = y + height;
if ((ky0 > clip_cur.y1) || (ky1 < clip_cur.y0))
- return true;
+ return NSERROR_OK;
}
/* tiled bitmaps both knock out and get knocked out */
if (guit->bitmap->get_opaque(bitmap)) {
- knockout_calculate(kx0, ky0, kx1, ky1, NULL);
+ knockout_calculate(ctx, kx0, ky0, kx1, ky1, NULL);
}
knockout_boxes[knockout_box_cur].bbox.x0 = kx0;
knockout_boxes[knockout_box_cur].bbox.y0 = ky0;
@@ -792,33 +885,111 @@ bool knockout_plot_bitmap(int x, int y, int width, int height,
knockout_entries[knockout_entry_cur].data.bitmap.bg = bg;
knockout_entries[knockout_entry_cur].data.bitmap.flags = flags;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_BITMAP;
+
if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) ||
- (++knockout_box_cur >= KNOCKOUT_BOXES))
- knockout_plot_flush();
- return knockout_plot_clip(&clip_cur);
+ (++knockout_box_cur >= KNOCKOUT_BOXES)) {
+ ffres = knockout_plot_flush(ctx);
+ }
+ res = knockout_plot_clip(ctx, &clip_cur);
+ /* return the first error */
+ if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
+ ffres = res;
+ }
+ return ffres;
}
-bool knockout_plot_group_start(const char *name)
+
+/**
+ * Start of a group of objects.
+ *
+ * Used when plotter implements export to a vector graphics file format.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+knockout_plot_group_start(const struct redraw_context *ctx, const char *name)
{
if (real_plot.group_start == NULL) {
- return true;
+ return NSERROR_OK;
}
knockout_entries[knockout_entry_cur].data.group_start.name = name;
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_START;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
- return true;
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
}
-bool knockout_plot_group_end(void)
+
+static nserror knockout_plot_group_end(const struct redraw_context *ctx)
{
if (real_plot.group_end == NULL) {
- return true;
+ return NSERROR_OK;
}
knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_END;
- if (++knockout_entry_cur >= KNOCKOUT_ENTRIES)
- knockout_plot_flush();
+ if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) {
+ return knockout_plot_flush(ctx);
+ }
+ return NSERROR_OK;
+}
+
+/* exported functions documented in desktop/knockout.h */
+bool knockout_plot_start(const struct redraw_context *ctx,
+ struct redraw_context *knk_ctx)
+{
+ /* check if we're recursing */
+ if (nested_depth++ > 0) {
+ /* we should already have the knockout renderer as default */
+ assert(ctx->plot->rectangle == knockout_plotters.rectangle);
+ *knk_ctx = *ctx;
+ return true;
+ }
+
+ /* end any previous sessions */
+ if (knockout_entry_cur > 0)
+ knockout_plot_end(ctx);
+
+ /* get copy of real plotter table */
+ real_plot = *(ctx->plot);
+
+ /* set up knockout rendering context */
+ *knk_ctx = *ctx;
+ knk_ctx->plot = &knockout_plotters;
return true;
}
+
+
+/* exported functions documented in desktop/knockout.h */
+bool knockout_plot_end(const struct redraw_context *ctx)
+{
+ /* only output when we've finished any nesting */
+ if (--nested_depth == 0) {
+ return knockout_plot_flush(ctx);
+ }
+
+ assert(nested_depth > 0);
+ return true;
+}
+
+
+/**
+ * knockout plotter operation table
+ */
+const struct plotter_table knockout_plotters = {
+ .rectangle = knockout_plot_rectangle,
+ .line = knockout_plot_line,
+ .polygon = knockout_plot_polygon,
+ .clip = knockout_plot_clip,
+ .text = knockout_plot_text,
+ .disc = knockout_plot_disc,
+ .arc = knockout_plot_arc,
+ .bitmap = knockout_plot_bitmap,
+ .group_start = knockout_plot_group_start,
+ .group_end = knockout_plot_group_end,
+ .flush = knockout_plot_flush,
+ .path = knockout_plot_path,
+ .option_knockout = true,
+};
diff --git a/desktop/knockout.h b/desktop/knockout.h
index c4f1245..f7ff045 100644
--- a/desktop/knockout.h
+++ b/desktop/knockout.h
@@ -26,9 +26,21 @@
#include "netsurf/plotters.h"
+/**
+ * Start a knockout plotting session
+ *
+ * \param ctx the redraw context with real plotter table
+ * \param knk_ctx updated to copy of ctx, with plotter table replaced
+ * \return true on success, false otherwise
+ */
bool knockout_plot_start(const struct redraw_context *ctx,
struct redraw_context *knk_ctx);
-bool knockout_plot_end(void);
+/**
+ * End a knockout plotting session
+ *
+ * \return true on success, false otherwise
+ */
+bool knockout_plot_end(const struct redraw_context *ctx);
extern const struct plotter_table knockout_plotters;
diff --git a/desktop/treeview.c b/desktop/treeview.c
index 541852d..75e5c93 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -2042,7 +2042,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
/* Rendering complete */
if (ctx->plot->option_knockout) {
- knockout_plot_end();
+ knockout_plot_end(ctx);
}
}
diff --git a/include/netsurf/plotters.h b/include/netsurf/plotters.h
index 68e1cf7..416c6ff 100644
--- a/include/netsurf/plotters.h
+++ b/include/netsurf/plotters.h
@@ -141,6 +141,7 @@ struct plotter_table {
* centre of line width/thickness.
*
* \param ctx The current redraw context.
+ * \param pstyle Style controlling the line plot.
* \return NSERROR_OK on success else error code.
*/
nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
struct rect *line);
@@ -154,6 +155,7 @@ struct plotter_table {
* width and height.
*
* \param ctx The current redraw context.
+ * \param pstyle Style controlling the rectangle plot.
* \return NSERROR_OK on success else error code.
*/
nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
struct rect *rectangle);
@@ -167,6 +169,7 @@ struct plotter_table {
* rule.
*
* \param ctx The current redraw context.
+ * \param pstyle Style controlling the polygon plot.
* \return NSERROR_OK on success else error code.
*/
nserror (*polygon)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
int *p, unsigned int n);
@@ -178,6 +181,11 @@ struct plotter_table {
* controlled by the plot style.
*
* \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param width The width of the path
+ * \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
nserror (*path)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
float *p, unsigned int n, float width, const float transform[6]);
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=130e96920942f5fcd63...
commit 130e96920942f5fcd63eaf5f676eda0744f83e43
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
update all core uses of plotter API
diff --git a/content/content.c b/content/content.c
index 2eb035c..2719db8 100644
--- a/content/content.c
+++ b/content/content.c
@@ -600,12 +600,12 @@ bool content_scaled_redraw(struct hlcache_handle *h,
clip.x1 = width;
clip.y1 = height;
- new_ctx.plot->clip(&clip);
+ new_ctx.plot->clip(&new_ctx, &clip);
/* Plot white background */
- plot_ok &= new_ctx.plot->rectangle(clip.x0, clip.y0, clip.x1, clip.y1,
- plot_style_fill_white);
-
+ plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
+ plot_style_fill_white,
+ &clip) == NSERROR_OK);
/* Set up content redraw data */
data.x = 0;
diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index 5970f8b..2717874 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -199,8 +199,12 @@ static bool nsbmp_redraw(struct content *c, struct
content_redraw_data *data,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- bmp->bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx,
+ bmp->bitmap,
+ data->x, data->y,
+ data->width, data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
diff --git a/content/handlers/image/image.c b/content/handlers/image/image.c
index e7cc921..675fdd6 100644
--- a/content/handlers/image/image.c
+++ b/content/handlers/image/image.c
@@ -137,9 +137,9 @@ bool image_bitmap_plot(struct bitmap *bitmap,
fill_style.stroke_type = PLOT_OP_TYPE_NONE;
fill_style.fill_type = PLOT_OP_TYPE_SOLID;
- return ctx->plot->rectangle(area.x0, area.y0,
- area.x1, area.y1,
- &fill_style);
+ return (ctx->plot->rectangle(ctx,
+ &fill_style,
+ &area) == NSERROR_OK);
} else if ((fill_style.fill_colour & 0xff000000) == 0) {
/* transparent pixel used as spacer, skip it */
@@ -154,6 +154,10 @@ bool image_bitmap_plot(struct bitmap *bitmap,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx,
+ bitmap,
+ data->x, data->y,
+ data->width, data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
diff --git a/content/handlers/image/nssprite.c b/content/handlers/image/nssprite.c
index c902fc3..247574a 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -16,9 +16,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for image/x-riscos-sprite (librosprite implementation).
- *
+/**
+ * \file
+ * librosprite implementation for content image/x-riscos-sprite
*/
#include <stdbool.h>
@@ -185,19 +185,28 @@ static void nssprite_destroy(struct content *c)
* Redraw a CONTENT_SPRITE.
*/
-static bool nssprite_redraw(struct content *c, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx)
+static bool
+nssprite_redraw(struct content *c,
+ struct content_redraw_data *data,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
{
nssprite_content *nssprite = (nssprite_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
- if (data->repeat_x)
+ if (data->repeat_x) {
flags |= BITMAPF_REPEAT_X;
- if (data->repeat_y)
+ }
+ if (data->repeat_y) {
flags |= BITMAPF_REPEAT_Y;
+ }
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- nssprite->bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx,
+ nssprite->bitmap,
+ data->x, data->y,
+ data->width, data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 1bf4b44..0665f21 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content handler for image/svg using librsvg (implementation).
+/**
+ * \file
+ * implementation of content handler for image/svg using librsvg.
*
* SVG files are rendered to a NetSurf bitmap by creating a Cairo rendering
* surface (content_rsvg_data.cs) over the bitmap's data, creating a Cairo
@@ -234,8 +235,12 @@ static bool rsvg_redraw(struct content *c, struct content_redraw_data
*data,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- rsvgcontent->bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx,
+ rsvgcontent->bitmap,
+ data->x, data->y,
+ data->width, data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
static void rsvg_destroy(struct content *c)
diff --git a/content/handlers/image/svg.c b/content/handlers/image/svg.c
index 94c4858..b34c6b7 100644
--- a/content/handlers/image/svg.c
+++ b/content/handlers/image/svg.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for image/svg (implementation).
+/**
+ * \file
+ * implementation of content for image/svg using libsvgtiny.
*/
#include <assert.h>
@@ -154,18 +155,25 @@ static void svg_reformat(struct content *c, int width, int height)
* Redraw a CONTENT_SVG.
*/
-static bool svg_redraw_internal(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- const struct redraw_context *ctx, float scale,
- colour background_colour)
+static bool
+svg_redraw_internal(struct content *c,
+ int x,
+ int y,
+ int width,
+ int height,
+ const struct rect *clip,
+ const struct redraw_context *ctx,
+ float scale,
+ colour background_colour)
{
svg_content *svg = (svg_content *) c;
float transform[6];
struct svgtiny_diagram *diagram = svg->diagram;
- bool ok;
int px, py;
unsigned int i;
plot_font_style_t fstyle = *plot_style_font;
+ plot_style_t pstyle;
+ nserror res;
assert(diagram);
@@ -183,14 +191,17 @@ static bool svg_redraw_internal(struct content *c, int x, int y,
for (i = 0; i != diagram->shape_count; i++) {
if (diagram->shape[i].path) {
- ok = ctx->plot->path(diagram->shape[i].path,
- diagram->shape[i].path_length,
- BGR(diagram->shape[i].fill),
- diagram->shape[i].stroke_width,
- BGR(diagram->shape[i].stroke),
- transform);
- if (!ok)
+ pstyle.stroke_colour = BGR(diagram->shape[i].stroke);
+ pstyle.fill_colour = BGR(diagram->shape[i].fill);
+ res = ctx->plot->path(ctx,
+ &pstyle,
+ diagram->shape[i].path,
+ diagram->shape[i].path_length,
+ diagram->shape[i].stroke_width,
+ transform);
+ if (res != NSERROR_OK) {
return false;
+ }
} else if (diagram->shape[i].text) {
px = transform[0] * diagram->shape[i].text_x +
@@ -204,12 +215,14 @@ static bool svg_redraw_internal(struct content *c, int x, int y,
fstyle.foreground = 0x000000;
fstyle.size = (8 * FONT_SIZE_SCALE) * scale;
- ok = ctx->plot->text(px, py,
- diagram->shape[i].text,
- strlen(diagram->shape[i].text),
- &fstyle);
- if (!ok)
+ res = ctx->plot->text(ctx,
+ &fstyle,
+ px, py,
+ diagram->shape[i].text,
+ strlen(diagram->shape[i].text));
+ if (res != NSERROR_OK) {
return false;
+ }
}
}
diff --git a/desktop/browser.c b/desktop/browser.c
index d3648d7..442208c 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -170,23 +170,21 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
return false;
}
- if (bw->current_content == NULL && bw->children == NULL) {
+ if ((bw->current_content == NULL) &&
+ (bw->children == NULL)) {
/* Browser window has no content, render blank fill */
- ctx->plot->clip(clip);
- return ctx->plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- plot_style_fill_white);
+ ctx->plot->clip(ctx, clip);
+ return (ctx->plot->rectangle(ctx, plot_style_fill_white, clip) == NSERROR_OK);
}
/* Browser window has content OR children (frames) */
-
if ((bw->window != NULL) &&
(ctx->plot->option_knockout)) {
/* Root browser window: start knockout */
knockout_plot_start(ctx, &new_ctx);
}
- new_ctx.plot->clip(clip);
+ new_ctx.plot->clip(ctx, clip);
/* Handle redraw of any browser window children */
if (bw->children) {
@@ -194,11 +192,12 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
int cur_child;
int children = bw->rows * bw->cols;
- if (bw->window != NULL)
+ if (bw->window != NULL) {
/* Root browser window; start with blank fill */
- plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- plot_style_fill_white);
+ plot_ok &= (new_ctx.plot->rectangle(ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
+ }
/* Loop through all children of bw */
for (cur_child = 0; cur_child < children; cur_child++) {
@@ -225,7 +224,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Skip this frame if it lies outside clip rectangle */
if (content_clip.x0 >= content_clip.x1 ||
- content_clip.y0 >= content_clip.y1)
+ content_clip.y0 >= content_clip.y1)
continue;
/* Redraw frame */
@@ -235,7 +234,8 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
}
/* Nothing else to redraw for browser windows with children;
- * cleanup and return */
+ * cleanup and return
+ */
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: knockout end */
knockout_plot_end();
@@ -254,8 +254,9 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Non-HTML may not fill viewport to extents, so plot white
* background fill */
- plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1, plot_style_fill_white);
+ plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
}
/* Set up content redraw data */
@@ -290,7 +291,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
&content_clip, &new_ctx);
/* Back to full clip rect */
- new_ctx.plot->clip(clip);
+ new_ctx.plot->clip(&new_ctx, clip);
if (!bw->window) {
/* Render scrollbars */
diff --git a/desktop/browser_history.c b/desktop/browser_history.c
index d21c5bc..10154b7 100644
--- a/desktop/browser_history.c
+++ b/desktop/browser_history.c
@@ -287,7 +287,7 @@ static plot_font_style_t pfstyle_node_sel = {
* \param x window x offset
* \param y window y offset
* \param clip clip redraw
- * \param ctx current redraw context
+ * \param ctx current redraw context
*/
static bool
browser_window_history__redraw_entry(struct history *history,
@@ -296,7 +296,6 @@ browser_window_history__redraw_entry(struct history *history,
int x, int y, bool clip,
const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
size_t char_offset;
int actual_x;
struct history_entry *child;
@@ -306,7 +305,7 @@ browser_window_history__redraw_entry(struct history *history,
plot_style_t *pstyle;
plot_font_style_t *pfstyle;
-
+ struct rect rect;
nserror res;
/* setup plot styles */
@@ -320,31 +319,36 @@ browser_window_history__redraw_entry(struct history *history,
/* setup clip area */
if (clip) {
- struct rect rect;
rect.x0 = x0 + xoffset;
rect.y0 = y0 + yoffset;
rect.x1 = x1 + xoffset;
rect.y1 = y1 + yoffset;
- if (!plot->clip(&rect)) {
+ res = ctx->plot->clip(ctx, &rect);
+ if (res != NSERROR_OK) {
return false;
}
}
/* Only attempt to plot bitmap if it is present */
if (entry->bitmap != NULL) {
- plot->bitmap(entry->x + xoffset,
- entry->y + yoffset,
- WIDTH, HEIGHT,
- entry->bitmap,
- 0xffffff,
- 0);
+ res = ctx->plot->bitmap(ctx,
+ entry->bitmap,
+ entry->x + xoffset,
+ entry->y + yoffset,
+ WIDTH, HEIGHT,
+ 0xffffff,
+ 0);
+ if (res != NSERROR_OK) {
+ return false;
+ }
}
- if (!plot->rectangle(entry->x - 1 + xoffset,
- entry->y - 1 + yoffset,
- entry->x + xoffset + WIDTH,
- entry->y + yoffset + HEIGHT,
- pstyle)) {
+ rect.x0 = entry->x - 1 + xoffset;
+ rect.y0 = entry->y - 1 + yoffset;
+ rect.x1 = entry->x + xoffset + WIDTH;
+ rect.y1 = entry->y + yoffset + HEIGHT;
+ res = ctx->plot->rectangle(ctx, pstyle, &rect);
+ if (res != NSERROR_OK) {
return false;
}
@@ -355,38 +359,45 @@ browser_window_history__redraw_entry(struct history *history,
return false;
}
-
- if (!plot->text(entry->x + xoffset,
- entry->y + HEIGHT + 12 + yoffset,
- entry->page.title,
- char_offset,
- pfstyle)) {
+ res = ctx->plot->text(ctx,
+ pfstyle,
+ entry->x + xoffset,
+ entry->y + HEIGHT + 12 + yoffset,
+ entry->page.title,
+ char_offset);
+ if (res != NSERROR_OK) {
return false;
}
/* for each child node draw a line and recurse redraw into it */
for (child = entry->forward; child; child = child->next) {
- if (!plot->line(entry->x + WIDTH + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- entry->x + WIDTH + tailsize + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- &pstyle_line)) {
+ rect.x0 = entry->x + WIDTH + xoffset;
+ rect.y0 = entry->y + HEIGHT / 2 + yoffset;
+ rect.x1 = entry->x + WIDTH + tailsize + xoffset;
+ rect.y1 = entry->y + HEIGHT / 2 + yoffset;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
return false;
}
- if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
- entry->y + HEIGHT / 2 + yoffset,
- child->x - tailsize +xoffset,
- child->y + HEIGHT / 2 + yoffset,
- &pstyle_line)) {
+
+ rect.x0 = entry->x + WIDTH + tailsize + xoffset;
+ rect.y0 = entry->y + HEIGHT / 2 + yoffset;
+ rect.x1 = child->x - tailsize + xoffset;
+ rect.y1 = child->y + HEIGHT / 2 + yoffset;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
return false;
}
- if (!plot->line(child->x - tailsize + xoffset,
- child->y + HEIGHT / 2 + yoffset,
- child->x + xoffset, child->y +
- HEIGHT / 2 + yoffset,
- &pstyle_line)) {
+
+ rect.x0 = child->x - tailsize + xoffset;
+ rect.y0 = child->y + HEIGHT / 2 + yoffset;
+ rect.x1 = child->x + xoffset;
+ rect.y1 = child->y + HEIGHT / 2 + yoffset;
+ res = ctx->plot->line(ctx, &pstyle_line, &rect);
+ if (res != NSERROR_OK) {
return false;
}
+
if (!browser_window_history__redraw_entry(history, child,
x0, y0, x1, y1, x, y, clip, ctx)) {
return false;
diff --git a/desktop/scrollbar.c b/desktop/scrollbar.c
index 9a4d70f..3709af8 100644
--- a/desktop/scrollbar.c
+++ b/desktop/scrollbar.c
@@ -18,8 +18,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
- * Scrollbar widget (implementation).
+/**
+ * \file
+ * implementation of scrollbar widget.
*/
#include <stdbool.h>
@@ -36,10 +37,14 @@
#include "desktop/system_colour.h"
#include "desktop/scrollbar.h"
+/**
+ * Scrollbar context
+ */
struct scrollbar {
- bool horizontal; /* Horizontal scrollbar if true, else vertical
- */
- int length; /* Length of the scrollbar widget */
+ /** Horizontal scrollbar if true, else vertical */
+ bool horizontal;
+ /** Length of the scrollbar widget */
+ int length;
int full_size; /* Length of the full scrollable area */
int visible_size; /* Length visible part of the scrollable area */
@@ -121,24 +126,27 @@ void scrollbar_destroy(struct scrollbar *s)
/**
- * Draw an outline rectangle common to a several scrollbar elements.
+ * Draw an outline rectangle common to several scrollbar elements.
*
* \param x0 left border of the outline
* \param y0 top border of the outline
* \param x1 right border of the outline
* \param y1 bottom border of the outline
* \param c base colour of the outline, the other colours are created by
- * lightening or darkening this one
+ * lightening or darkening this one
* \param ctx current redraw context
* \param inset true for inset outline, false for an outset one
* \return
*/
-static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
- int x1, int y1, colour c, bool inset,
- const struct redraw_context *ctx)
+static inline nserror
+scrollbar_rectangle(const struct redraw_context *ctx,
+ struct rect *area,
+ colour c,
+ bool inset)
{
- const struct plotter_table *plot = ctx->plot;
+ struct rect line;
+ nserror res;
static plot_style_t c0 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
@@ -165,29 +173,63 @@ static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int
y0,
c2.stroke_colour = blend_colour(c0.stroke_colour, c1.stroke_colour);
/* Plot the outline */
- if (!plot->line(x0, y0, x1, y0, &c0)) return false;
- if (!plot->line(x1, y0, x1, y1 + 1, &c1)) return false;
- if (!plot->line(x1, y0, x1, y0 + 1, &c2)) return false;
- if (!plot->line(x1, y1, x0, y1, &c1)) return false;
- if (!plot->line(x0, y1, x0, y0, &c0)) return false;
- if (!plot->line(x0, y1, x0, y1 + 1, &c2)) return false;
- return true;
+ line.x0 = area->x0; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y0;
+ res = ctx->plot->line(ctx, &c0, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y1 + 1;
+ res = ctx->plot->line(ctx, &c1, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y0;
+ line.x1 = area->x1; line.y1 = area->y0 + 1;
+ res = ctx->plot->line(ctx, &c2, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x1; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y1;
+ res = ctx->plot->line(ctx, &c1, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x0; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y0;
+ res = ctx->plot->line(ctx, &c0, &line);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ line.x0 = area->x0; line.y0 = area->y1;
+ line.x1 = area->x0; line.y1 = area->y1 + 1;
+ res = ctx->plot->line(ctx, &c2, &line);
+
+ return res;
}
/*
* Exported function. Documented in scrollbar.h
*/
-bool scrollbar_redraw(struct scrollbar *s, int x, int y,
+bool scrollbar_redraw(struct scrollbar *s, int x, int y,
const struct rect *clip, float scale,
const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
int w = SCROLLBAR_WIDTH;
int bar_pos, bar_c0, bar_c1;
int v[6]; /* array of triangle vertices */
- int x0, y0, x1, y1;
+ struct rect area;
+ struct rect rect;
+ nserror res;
colour bg_fill_colour = ns_system_colour_char("Scrollbar");
colour fg_fill_colour = ns_system_colour_char("ButtonFace");
@@ -206,176 +248,236 @@ bool scrollbar_redraw(struct scrollbar *s, int x, int y,
.fill_colour = arrow_fill_colour
};
- x0 = x;
- y0 = y;
- x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
- y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
+ area.x0 = x;
+ area.y0 = y;
+ area.x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
+ area.y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
bar_pos = s->bar_pos;
- bar_c1 = (s->horizontal ? x0 : y0) + SCROLLBAR_WIDTH +
+ bar_c1 = (s->horizontal ? area.x0 : area.y0) + SCROLLBAR_WIDTH +
s->bar_pos + s->bar_len - 1;
if (scale != 1.0) {
w *= scale;
- x0 *= scale;
- y0 *= scale;
- x1 *= scale;
- y1 *= scale;
+ area.x0 *= scale;
+ area.y0 *= scale;
+ area.x1 *= scale;
+ area.y1 *= scale;
bar_pos *= scale;
bar_c1 *= scale;
}
- bar_c0 = (s->horizontal ? x0 : y0) + w + bar_pos;
+ bar_c0 = (s->horizontal ? area.x0 : area.y0) + w + bar_pos;
- if (x1 < clip->x0 || y1 < clip->y0 || clip->x1 < x0 || clip->y1
< y0)
- /* scrollbar is outside the clipping rectangle, nothing to
- * render */
+ /* if scrollbar is outside the clipping rectangle, nothing to render */
+ if ((area.x1 < clip->x0) ||
+ (area.y1 < clip->y0) ||
+ (clip->x1 < area.x0) ||
+ (clip->y1 < area.y0)) {
return true;
+ }
-
if (s->horizontal) {
/* scrollbar is horizontal */
-
+
/* scrollbar outline */
- if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
- bg_fill_colour, true, ctx))
+ res = scrollbar_rectangle(ctx, &area, bg_fill_colour, true);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* left arrow icon border */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y0 + 1,
- x0 + w - 2,
- y1 - 1,
- fg_fill_colour, false, ctx))
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x0 + w - 2;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* left arrow icon background */
- if (!plot->rectangle(x0 + 2,
- y0 + 2,
- x0 + w - 2,
- y1 - 1,
- &fg_fill_style))
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x0 + w - 2;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* left arrow */
- v[0] = x0 + w / 4;
- v[1] = y0 + w / 2;
- v[2] = x0 + w * 3 / 4;
- v[3] = y0 + w / 4;
- v[4] = x0 + w * 3 / 4;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
+ v[0] = area.x0 + w / 4;
+ v[1] = area.y0 + w / 2;
+ v[2] = area.x0 + w * 3 / 4;
+ v[3] = area.y0 + w / 4;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* scrollbar well background */
- if (!plot->rectangle(x0 + w - 1,
- y0 + 1,
- x1 - w + 2,
- y1,
- &bg_fill_style))
+ rect.x0 = area.x0 + w - 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - w + 2;
+ rect.y1 = area.y1;
+ res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* scrollbar position indicator bar */
- if (!scrollbar_redraw_scrollbar_rectangle(bar_c0,
- y0 + 1,
- bar_c1,
- y1 - 1,
- fg_fill_colour, false, ctx))
+ rect.x0 = bar_c0;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = bar_c1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(bar_c0 + 1,
- y0 + 2,
- bar_c1,
- y1 - 1,
- &fg_fill_style))
+ }
+
+ rect.x0 = bar_c0 + 1;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = bar_c1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* right arrow icon border */
- if (!scrollbar_redraw_scrollbar_rectangle(x1 - w + 2,
- y0 + 1,
- x1 - 1,
- y1 - 1,
- fg_fill_colour, false, ctx))
+ rect.x0 = area.x1 - w + 2;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* right arrow icon background */
- if (!plot->rectangle(x1 - w + 3,
- y0 + 2,
- x1 - 1,
- y1 - 1,
- &fg_fill_style))
+ rect.x0 = area.x1 - w + 3;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* right arrow */
- v[0] = x1 - w / 4 + 1;
- v[1] = y0 + w / 2;
- v[2] = x1 - w * 3 / 4 + 1;
- v[3] = y0 + w / 4;
- v[4] = x1 - w * 3 / 4 + 1;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
+ v[0] = rect.x1 - w / 4 + 1;
+ v[1] = rect.y0 + w / 2;
+ v[2] = rect.x1 - w * 3 / 4 + 1;
+ v[3] = rect.y0 + w / 4;
+ v[4] = rect.x1 - w * 3 / 4 + 1;
+ v[5] = rect.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
return false;
+ }
} else {
/* scrollbar is vertical */
-
+
/* outline */
- if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
- bg_fill_colour, true, ctx))
+ res = scrollbar_rectangle(ctx, &area, bg_fill_colour, true);
+ if (res != NSERROR_OK) {
return false;
- /* top arrow background */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y0 + 1,
- x1 - 1,
- y0 + w - 2,
- fg_fill_colour, false, ctx))
+ }
+
+ /* top arrow border */
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y0 + w - 2;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(x0 + 2,
- y0 + 2,
- x1 - 1,
- y0 + w - 2,
- &fg_fill_style))
+ }
+
+ /* top arrow background */
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y0 + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y0 + w - 2;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* up arrow */
- v[0] = x0 + w / 2;
- v[1] = y0 + w / 4;
- v[2] = x0 + w / 4;
- v[3] = y0 + w * 3 / 4;
- v[4] = x0 + w * 3 / 4;
- v[5] = y0 + w * 3 / 4;
- if (!plot->polygon(v, 3, &arrow_fill_style))
+ v[0] = area.x0 + w / 2;
+ v[1] = area.y0 + w / 4;
+ v[2] = area.x0 + w / 4;
+ v[3] = area.y0 + w * 3 / 4;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y0 + w * 3 / 4;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* scrollbar well background */
- if (!plot->rectangle(x0 + 1,
- y0 + w - 1,
- x1,
- y1 - w + 2,
- &bg_fill_style))
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y0 + w - 1;
+ rect.x1 = area.x1;
+ rect.y1 = area.y1 - w + 2;
+ res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* scrollbar position indicator bar */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- bar_c0,
- x1 - 1,
- bar_c1,
- fg_fill_colour, false, ctx))
+ rect.x0 = area.x0 + 1;
+ rect.y0 = bar_c0;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = bar_c1;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(x0 + 2,
- bar_c0 + 1,
- x1 - 1,
- bar_c1,
- &fg_fill_style))
+ }
+
+ rect.x0 = area.x0 + 2;
+ rect.y0 = bar_c0 + 1;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = bar_c1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
- /* bottom arrow background */
- if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
- y1 - w + 2,
- x1 - 1,
- y1 - 1,
- fg_fill_colour, false, ctx))
+ }
+
+ /* down arrow icon border */
+ rect.x0 = area.x0 + 1;
+ rect.y0 = area.y1 - w + 2;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(x0 + 2,
- y1 - w + 3,
- x1 - 1,
- y1 - 1,
- &fg_fill_style))
+ }
+
+ /* down arrow icon background */
+ rect.x0 = area.x0 + 2;
+ rect.y0 = area.y1 - w + 3;
+ rect.x1 = area.x1 - 1;
+ rect.y1 = area.y1 - 1;
+ res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
/* down arrow */
- v[0] = x0 + w / 2;
- v[1] = y1 - w / 4 + 1;
- v[2] = x0 + w / 4;
- v[3] = y1 - w * 3 / 4 + 1;
- v[4] = x0 + w * 3 / 4;
- v[5] = y1 - w * 3 / 4 + 1;
- if (!plot->polygon(v, 3, &arrow_fill_style))
+ v[0] = area.x0 + w / 2;
+ v[1] = area.y1 - w / 4 + 1;
+ v[2] = area.x0 + w / 4;
+ v[3] = area.y1 - w * 3 / 4 + 1;
+ v[4] = area.x0 + w * 3 / 4;
+ v[5] = area.y1 - w * 3 / 4 + 1;
+ res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
+ if (res != NSERROR_OK) {
return false;
+ }
}
return true;
@@ -568,7 +670,7 @@ bool scrollbar_is_horizontal(struct scrollbar *s)
* \param x the X coordinate of the drag start
* \param y the Y coordinate of the drag start
* \param content_drag whether this should be a reverse drag (used when the
- * user drags the content area, rather than the scrollbar)
+ * user drags the content area, rather than the scrollbar)
* \param pair whether the drag is a '2D' scroll
*/
@@ -682,7 +784,7 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
if (val < SCROLLBAR_WIDTH) {
/* left/up arrow */
-
+
status = h ? SCROLLBAR_MOUSE_LFT : SCROLLBAR_MOUSE_UP;
if (but1)
scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
@@ -721,15 +823,15 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
}
else {
/* scrollbar position indication bar */
-
+
status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT;
}
-
+
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2) &&
- (val >= SCROLLBAR_WIDTH + s->bar_pos
- && val < SCROLLBAR_WIDTH + s->bar_pos +
- s->bar_len))
+ (val >= SCROLLBAR_WIDTH + s->bar_pos
+ && val < SCROLLBAR_WIDTH + s->bar_pos +
+ s->bar_len))
/* The mouse event is a drag start on the scrollbar position
* indication bar. */
scrollbar_drag_start_internal(s, x, y, false,
@@ -857,4 +959,3 @@ void *scrollbar_get_data(struct scrollbar *s)
{
return s->client_data;
}
-
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 203c28e..af1cd80 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -2095,13 +2095,13 @@ bool textarea_set_caret(struct textarea *ta, int caret)
void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
const struct rect *clip, const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
int line0, line1, line, left, right, line_y;
int text_y_offset, text_y_offset_baseline;
unsigned int b_pos, b_len, b_len_part, b_end;
unsigned int sel_start, sel_end;
char *line_text;
struct rect r, s;
+ struct rect rect;
bool selected = false;
plot_font_style_t fstyle;
int fsize = ta->fstyle.size;
@@ -2162,20 +2162,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg,
float scale,
r.y1 = y + ta->vis_height * scale;
}
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
if (ta->border_col != NS_TRANSPARENT &&
ta->border_width > 0) {
/* Plot border */
- plot->rectangle(x, y, x + ta->vis_width, y + ta->vis_height,
- &plot_style_fill_bg);
+ rect.x0 = x;
+ rect.y0 = y;
+ rect.x1 = x + ta->vis_width;
+ rect.y1 = y + ta->vis_height;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (ta->fstyle.background != NS_TRANSPARENT) {
/* Plot background */
plot_style_fill_bg.fill_colour = ta->fstyle.background;
- plot->rectangle(x + ta->border_width, y + ta->border_width,
- x + ta->vis_width - ta->border_width,
- y + ta->vis_height - ta->border_width,
- &plot_style_fill_bg);
+ rect.x0 = x + ta->border_width;
+ rect.y0 = y + ta->border_width;
+ rect.x1 = x + ta->vis_width - ta->border_width;
+ rect.y1 = y + ta->vis_height - ta->border_width;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (scale == 1.0) {
@@ -2223,16 +2227,16 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg,
float scale,
plot_style_fill_bg.fill_colour = ta->sel_fstyle.background;
- for (line = line0; (line <= line1) &&
- (y + line * ta->line_height <= r.y1 + ta->scroll_y);
- line++) {
+ for (line = line0;
+ (line <= line1) && (y + line * ta->line_height <= r.y1 +
ta->scroll_y);
+ line++) {
if (ta->lines[line].b_length == 0) {
b_pos++;
continue;
}
/* reset clip rectangle */
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
b_len = ta->lines[line].b_length;
@@ -2256,12 +2260,12 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg,
float scale,
fstyle = ta->fstyle;
fstyle.size = fsize;
- plot->text(x + ta->border_width + ta->pad_left -
- ta->scroll_x,
+ ctx->plot->text(ctx,
+ &fstyle,
+ x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
- ta->show->data +
- ta->lines[line].b_start,
- ta->lines[line].b_length, &fstyle);
+ ta->show->data + ta->lines[line].b_start,
+ ta->lines[line].b_length);
b_pos += b_len;
@@ -2338,24 +2342,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg,
float scale,
continue;
}
- plot->clip(&s);
+ ctx->plot->clip(ctx, &s);
if (selected) {
/* draw selection fill */
- plot->rectangle(s.x0, y + line_y +
- text_y_offset,
- s.x1, y + line_y + line_height +
- text_y_offset,
- &plot_style_fill_bg);
+ rect.x0 = s.x0;
+ rect.y0 = y + line_y + text_y_offset;
+ rect.x1 = s.x1;
+ rect.y1 = y + line_y + line_height + text_y_offset;
+ ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
/* draw text */
- plot->text(x + ta->border_width + ta->pad_left -
- ta->scroll_x,
+ ctx->plot->text(ctx,
+ &fstyle,
+ x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
- ta->show->data +
- ta->lines[line].b_start,
- ta->lines[line].b_length, &fstyle);
+ ta->show->data + ta->lines[line].b_start,
+ ta->lines[line].b_length);
b_pos += b_len_part;
b_len -= b_len_part;
@@ -2376,16 +2380,17 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg,
float scale,
/* No native caret, there is no selection, and caret visible */
int caret_y = y - ta->scroll_y + ta->caret_y;
- plot->clip(&r);
+ ctx->plot->clip(ctx, &r);
/* Render our own caret */
- plot->line(x - ta->scroll_x + ta->caret_x, caret_y,
- x - ta->scroll_x + ta->caret_x,
- caret_y + ta->line_height,
- &pstyle_stroke_caret);
+ rect.x0 = x - ta->scroll_x + ta->caret_x;
+ rect.y0 = caret_y;
+ rect.x1 = x - ta->scroll_x + ta->caret_x;
+ rect.y1 = caret_y + ta->line_height;
+ ctx->plot->line(ctx, &pstyle_stroke_caret, &rect);
}
- plot->clip(clip);
+ ctx->plot->clip(ctx, clip);
if (ta->bar_x != NULL)
scrollbar_redraw(ta->bar_x,
diff --git a/desktop/treeview.c b/desktop/treeview.c
index 4d8fbaa..541852d 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -1798,10 +1798,11 @@ void treeview_redraw(treeview *tree, const int x, const int y,
struct treeview_node_style *style = &plot_style_odd;
struct content_redraw_data data;
struct rect r;
+ struct rect rect;
uint32_t count = 0;
int render_y = y;
int inset;
- int x0, y0, y1;
+ int x0;
int baseline = (tree_g.line_height * 3 + 2) / 4;
enum treeview_resource_id res = TREE_RES_CONTENT;
plot_style_t *bg_style;
@@ -1833,7 +1834,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
r.y0 = clip->y0 + y;
r.x1 = clip->x1 + x;
r.y1 = clip->y1 + y;
- new_ctx.plot->clip(&r);
+ new_ctx.plot->clip(&new_ctx, &r);
/* Draw the tree */
node = root = tree->root;
@@ -1912,24 +1913,30 @@ void treeview_redraw(treeview *tree, const int x, const int y,
}
/* Render background */
- y0 = render_y;
- y1 = render_y + height;
- new_ctx.plot->rectangle(r.x0, y0, r.x1, y1, bg_style);
+ rect.x0 = r.x0;
+ rect.y0 = render_y;
+ rect.x1 = r.x1;
+ rect.y1 = render_y + height;
+ new_ctx.plot->rectangle(&new_ctx, bg_style, &rect);
/* Render toggle */
- new_ctx.plot->bitmap(inset, render_y + tree_g.line_height / 4,
- style->furn[TREE_FURN_EXPAND].size,
- style->furn[TREE_FURN_EXPAND].size,
- furniture,
- bg_style->fill_colour, BITMAPF_NONE);
+ new_ctx.plot->bitmap(&new_ctx,
+ furniture,
+ inset,
+ render_y + tree_g.line_height / 4,
+ style->furn[TREE_FURN_EXPAND].size,
+ style->furn[TREE_FURN_EXPAND].size,
+ bg_style->fill_colour,
+ BITMAPF_NONE);
/* Render icon */
- if (node->type == TREE_NODE_ENTRY)
+ if (node->type == TREE_NODE_ENTRY) {
res = TREE_RES_CONTENT;
- else if (node->flags & TV_NFLAGS_SPECIAL)
+ } else if (node->flags & TV_NFLAGS_SPECIAL) {
res = TREE_RES_FOLDER_SPECIAL;
- else
+ } else {
res = TREE_RES_FOLDER;
+ }
if (treeview_res[res].ready) {
/* Icon resource is available */
@@ -1944,9 +1951,11 @@ void treeview_redraw(treeview *tree, const int x, const int y,
/* Render text */
x0 = inset + tree_g.step_width + tree_g.icon_step;
- new_ctx.plot->text(x0, render_y + baseline,
- node->text.data, node->text.len,
- text_style);
+ new_ctx.plot->text(&new_ctx,
+ text_style,
+ x0, render_y + baseline,
+ node->text.data,
+ node->text.len);
/* Rendered the node */
render_y += tree_g.line_height;
@@ -1970,25 +1979,25 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (ef->flags & TREE_FLAG_SHOW_NAME) {
int max_width = tree->field_width;
- new_ctx.plot->text(x0 + max_width -
- ef->value.width -
- tree_g.step_width,
- render_y + baseline,
- ef->value.data,
- ef->value.len,
- infotext_style);
-
- new_ctx.plot->text(x0 + max_width,
- render_y + baseline,
- entry->fields[i].value.data,
- entry->fields[i].value.len,
- infotext_style);
+ new_ctx.plot->text(&new_ctx,
+ infotext_style,
+ x0 + max_width - ef->value.width - tree_g.step_width,
+ render_y + baseline,
+ ef->value.data,
+ ef->value.len);
+
+ new_ctx.plot->text(&new_ctx,
+ infotext_style,
+ x0 + max_width,
+ render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
} else {
- new_ctx.plot->text(x0, render_y + baseline,
- entry->fields[i].value.data,
- entry->fields[i].value.len,
- infotext_style);
-
+ new_ctx.plot->text(&new_ctx,
+ infotext_style,
+ x0, render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
}
/* Rendered the expanded entry field */
@@ -2006,21 +2015,22 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (render_y < r.y1) {
/* Fill the blank area at the bottom */
- y0 = render_y;
- new_ctx.plot->rectangle(r.x0, y0, r.x1, r.y1,
- &plot_style_even.bg);
+ rect.x0 = r.x0;
+ rect.y0 = render_y;
+ rect.x1 = r.x1;
+ rect.y1 = r.y1;
+ new_ctx.plot->rectangle(&new_ctx, &plot_style_even.bg, &rect);
}
/* All normal treeview rendering is done; render any overlays */
- if (tree->move.target_pos != TV_TARGET_NONE &&
- treeview_res[TREE_RES_ARROW].ready) {
+ if ((tree->move.target_pos != TV_TARGET_NONE) &&
+ (treeview_res[TREE_RES_ARROW].ready)) {
/* Got a MOVE drag; render move indicator arrow */
data.x = tree->move.target_area.x0 + x;
data.y = tree->move.target_area.y0 + y;
data.background_colour = plot_style_even.bg.fill_colour;
- content_redraw(treeview_res[TREE_RES_ARROW].c,
- &data, &r, &new_ctx);
+ content_redraw(treeview_res[TREE_RES_ARROW].c, &data, &r, &new_ctx);
} else if (tree->edit.textarea != NULL) {
/* Edit in progress; render textarea */
@@ -2031,8 +2041,9 @@ void treeview_redraw(treeview *tree, const int x, const int y,
}
/* Rendering complete */
- if (ctx->plot->option_knockout)
+ if (ctx->plot->option_knockout) {
knockout_plot_end();
+ }
}
struct treeview_selection_walk_data {
diff --git a/include/netsurf/plotters.h b/include/netsurf/plotters.h
index 06fafab..68e1cf7 100644
--- a/include/netsurf/plotters.h
+++ b/include/netsurf/plotters.h
@@ -143,7 +143,7 @@ struct plotter_table {
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
- nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x0,
int y0, int x1, int y1);
+ nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
struct rect *line);
/**
* Plots a rectangle.
@@ -156,7 +156,7 @@ struct plotter_table {
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
- nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, int
x0, int y0, int x1, int y1);
+ nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
struct rect *rectangle);
/**
* Plot a polygon
@@ -175,7 +175,7 @@ struct plotter_table {
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
- * controlle dby the plot style.
+ * controlled by the plot style.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
diff --git a/render/form.c b/render/form.c
index 6eb1b80..be07e80 100644
--- a/render/form.c
+++ b/render/form.c
@@ -1167,7 +1167,6 @@ bool form_redraw_select_menu(struct form_control *control, int x,
int y,
float scale, const struct rect *clip,
const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
struct box *box;
struct form_select_menu *menu = control->data.select.menu;
struct form_option *option;
@@ -1181,7 +1180,9 @@ bool form_redraw_select_menu(struct form_control *control, int x,
int y,
int scroll;
int x_cp, y_cp;
struct rect r;
-
+ struct rect rect;
+ nserror res;
+
box = control->box;
x_cp = x;
@@ -1220,12 +1221,20 @@ bool form_redraw_select_menu(struct form_control *control, int x,
int y,
r.y0 = y0;
r.x1 = x1 + 1;
r.y1 = y1 + 1;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(x0, y0, x1, y1 ,plot_style_stroke_darkwbasec))
+ }
+
+ rect.x0 = x0;
+ rect.y0 = y0;
+ rect.x1 = x1;
+ rect.y1 = y1;
+ res = ctx->plot->rectangle(ctx, plot_style_stroke_darkwbasec, &rect);
+ if (res != NSERROR_OK) {
return false;
-
-
+ }
+
x0 = x0 + SELECT_BORDER_WIDTH;
y0 = y0 + SELECT_BORDER_WIDTH;
x1 = x1 - SELECT_BORDER_WIDTH;
@@ -1236,11 +1245,16 @@ bool form_redraw_select_menu(struct form_control *control, int x,
int y,
r.y0 = y0;
r.x1 = x1 + 1;
r.y1 = y1 + 1;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
- if (!plot->rectangle(x0, y0, x1 + 1, y1 + 1,
- plot_style_fill_lightwbasec))
+ }
+
+ res = ctx->plot->rectangle(ctx, plot_style_fill_lightwbasec, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
+
option = control->data.select.items;
item_y = line_height_with_spacing;
@@ -1256,32 +1270,40 @@ bool form_redraw_select_menu(struct form_control *control, int x,
int y,
plot_fstyle_entry.size = menu->f_size;
while (option && item_y - scroll < height) {
-
+
if (option->selected) {
y2 = y + item_y - scroll;
y3 = y + item_y + line_height_with_spacing - scroll;
- if (!plot->rectangle(x0, (y0 > y2 ? y0 : y2),
- scrollbar_x + 1,
- (y3 < y1 + 1 ? y3 : y1 + 1),
- &plot_style_fill_selected))
+
+ rect.x0 = x0;
+ rect.y0 = y0 > y2 ? y0 : y2;
+ rect.x1 = scrollbar_x + 1;
+ rect.y1 = y3 < y1 + 1 ? y3 : y1 + 1;
+ res = ctx->plot->rectangle(ctx, &plot_style_fill_selected, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
}
-
+
y2 = text_pos_offset + item_y;
- if (!plot->text(text_x, y2, option->text,
- strlen(option->text), &plot_fstyle_entry))
+ res = ctx->plot->text(ctx,
+ &plot_fstyle_entry,
+ text_x, y2,
+ option->text, strlen(option->text));
+ if (res != NSERROR_OK) {
return false;
-
+ }
+
item_y += line_height_with_spacing;
option = option->next;
}
-
+
if (!scrollbar_redraw(menu->scrollbar,
x_cp + menu->width - SCROLLBAR_WIDTH,
y_cp,
clip, scale, ctx))
return false;
-
+
return true;
}
diff --git a/render/html_redraw.c b/render/html_redraw.c
index ae86756..dd63628 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -150,16 +150,26 @@ static struct box *html_redraw_find_bg_box(struct box *box)
* \return true iff successful and redraw should proceed
*/
-bool text_redraw(const char *utf8_text, size_t utf8_len,
- size_t offset, int space, const plot_font_style_t *fstyle,
- int x, int y, const struct rect *clip, int height,
- float scale, bool excluded, struct content *c,
- const struct selection *sel, struct search_context *search,
- const struct redraw_context *ctx)
+bool
+text_redraw(const char *utf8_text,
+ size_t utf8_len,
+ size_t offset,
+ int space,
+ const plot_font_style_t *fstyle,
+ int x,
+ int y,
+ const struct rect *clip,
+ int height,
+ float scale,
+ bool excluded,
+ struct content *c,
+ const struct selection *sel,
+ struct search_context *search,
+ const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
bool highlighted = false;
plot_font_style_t plot_fstyle = *fstyle;
+ nserror res;
/* Need scaled text size to pass to plotters */
plot_fstyle.size *= scale;
@@ -195,7 +205,6 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
int startx, endx;
plot_style_t pstyle_fill_hback = *plot_style_fill_white;
plot_font_style_t fstyle_hback = plot_fstyle;
- nserror res;
if (end_idx > utf8_len) {
/* adjust for trailing space, not present in
@@ -230,19 +239,26 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
}
/* draw any text preceding highlighted portion */
- if (start_idx > 0 &&
- !plot->text(x, y + (int)(height * 0.75 * scale),
- utf8_text, start_idx,
- &plot_fstyle))
+ if ((start_idx > 0) &&
+ (ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ start_idx) != NSERROR_OK))
return false;
pstyle_fill_hback.fill_colour = fstyle->foreground;
/* highlighted portion */
- if (!plot->rectangle(x + startx, y, x + endx,
- y + height * scale,
- &pstyle_fill_hback))
+ r.x0 = x + startx;
+ r.y0 = y;
+ r.x1 = x + endx;
+ r.y1 = y + height * scale;
+ res = ctx->plot->rectangle(ctx, &pstyle_fill_hback, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
if (start_idx > 0) {
int px0 = max(x + startx, clip->x0);
@@ -253,8 +269,11 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
r.y0 = clip->y0;
r.x1 = px1;
r.y1 = clip->y1;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
+
clip_changed = true;
} else {
text_visible = false;
@@ -267,10 +286,14 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
pstyle_fill_hback.fill_colour);
if (text_visible &&
- !plot->text(x, y + (int)(height * 0.75 * scale),
- utf8_text, endtxt_idx,
- &fstyle_hback))
+ (ctx->plot->text(ctx,
+ &fstyle_hback,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ endtxt_idx) != NSERROR_OK)) {
return false;
+ }
/* draw any text succeeding highlighted portion */
if (endtxt_idx < utf8_len) {
@@ -281,30 +304,42 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
r.y0 = clip->y0;
r.x1 = clip->x1;
r.y1 = clip->y1;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
clip_changed = true;
- if (!plot->text(x, y + (int)
- (height * 0.75 * scale),
- utf8_text, utf8_len,
- &plot_fstyle))
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ utf8_len);
+ if (res != NSERROR_OK) {
return false;
+ }
}
}
if (clip_changed &&
- !plot->clip(clip))
+ (ctx->plot->clip(ctx, clip) != NSERROR_OK)) {
return false;
+ }
}
}
if (!highlighted) {
- if (!plot->text(x, y + (int) (height * 0.75 * scale),
- utf8_text, utf8_len,
- &plot_fstyle))
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int) (height * 0.75 * scale),
+ utf8_text,
+ utf8_len);
+ if (res != NSERROR_OK) {
return false;
+ }
}
return true;
}
@@ -328,6 +363,27 @@ static plot_style_t plot_style_fillbdr_dlight = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
+static inline nserror
+plot_clipped_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *clip,
+ struct rect *rect)
+{
+ nserror res;
+
+ rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
+ rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
+ rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
+ rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
+ if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
+ /* valid clip rectangles only */
+ res = ctx->plot->rectangle(ctx, style, rect);
+ } else {
+ res = NSERROR_OK;
+ }
+ return res;
+}
+
/**
* Draw one border.
*
@@ -342,15 +398,22 @@ static plot_style_t plot_style_fillbdr_dlight = {
* \return true if successful, false otherwise
*/
-static bool html_redraw_border_plot(const int side, const int *p, colour c,
- enum css_border_style_e style, int thickness, bool rectangular,
- const struct rect *clip, const struct redraw_context *ctx)
+static bool
+html_redraw_border_plot(const int side,
+ const int *p,
+ colour c,
+ enum css_border_style_e style,
+ int thickness,
+ bool rectangular,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
int z[8]; /* Vertices of border part */
unsigned int light = side;
plot_style_t *plot_style_bdr_in;
plot_style_t *plot_style_bdr_out;
+ nserror res;
+ struct rect rect;
if (c == NS_TRANSPARENT)
return true;
@@ -369,44 +432,51 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
/* fall through */
case CSS_BORDER_STYLE_DASHED:
- if (!plot->line((p[0] + p[2]) / 2,
- (p[1] + p[3]) / 2,
- (p[4] + p[6]) / 2,
- (p[5] + p[7]) / 2,
- &plot_style_bdr))
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = (p[4] + p[6]) / 2;
+ rect.y1 = (p[5] + p[7]) / 2;
+ res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
case CSS_BORDER_STYLE_SOLID:
/* fall through to default */
default:
if (rectangular || thickness == 1) {
- int x0, y0, x1, y1;
+
if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ if ((side == TOP) &&
+ (p[4] - p[6] != 0)) {
+ rect.x1 = p[4];
+ } else {
+ rect.x1 = p[6];
+ }
+ rect.y1 = p[7];
} 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;
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ if ((side == LEFT) &&
+ (p[1] - p[3] != 0)) {
+ rect.y1 = p[1];
+ } else {
+ rect.y1 = p[3];
+ }
}
- /* 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;
+ res = plot_clipped_rectangle(ctx, &plot_style_fillbdr, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
} else {
- if (!plot->polygon(p, 4, &plot_style_fillbdr))
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
}
break;
@@ -419,8 +489,10 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
z[5] = (p[7] * 2 + p[5]) / 3;
z[6] = p[6];
z[7] = p[7];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
z[0] = p[2];
z[1] = p[3];
z[2] = (p[2] * 2 + p[0]) / 3;
@@ -429,13 +501,16 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
z[5] = (p[5] * 2 + p[7]) / 3;
z[6] = p[4];
z[7] = p[5];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
break;
case CSS_BORDER_STYLE_GROOVE:
light = 3 - light;
/* fall through */
+
case CSS_BORDER_STYLE_RIDGE:
/* choose correct colours for each part of the border line */
if (light <= 1) {
@@ -449,90 +524,74 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
/* Render border */
if ((rectangular || thickness == 2) && thickness != 1) {
/* Border made up from two parts and can be plotted
- * with rectangles */
- int x0, y0, x1, y1;
+ * with rectangles
+ */
/* First part */
if (side == TOP || side == RIGHT) {
- x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
- x1 = p[6]; y1 = p[7];
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
} else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
}
- /* 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;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
/* Second part */
if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
} else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; y1 = p[3];
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
}
- /* 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;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
} else if (thickness == 1) {
/* Border made up from one part which can be plotted
* as a rectangle */
- int x0, y0, x1, y1;
+
if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
- /* 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;
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
+ if (res != NSERROR_OK) {
+ 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;
- /* 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;
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
}
} else {
/* Border made up from two parts and can't be plotted
- * with rectangles */
+ * with rectangles
+ */
z[0] = p[0];
z[1] = p[1];
z[2] = (p[0] + p[2]) / 2;
@@ -541,14 +600,18 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
z[5] = (p[7] + p[5]) / 2;
z[6] = p[6];
z[7] = p[7];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
z[0] = p[2];
z[1] = p[3];
z[6] = p[4];
z[7] = p[5];
- if (!plot->polygon(z, 4, plot_style_bdr_out))
+ res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
}
break;
@@ -583,90 +646,73 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
/* Render border */
if ((rectangular || thickness == 2) && thickness != 1) {
/* Border made up from two parts and can be plotted
- * with rectangles */
- int x0, y0, x1, y1;
+ * with rectangles
+ */
/* First part */
if (side == TOP || side == RIGHT) {
- x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
- x1 = p[6]; y1 = p[7];
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
} else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
}
- /* 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;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
/* Second part */
if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
} else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; y1 = p[3];
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
}
- /* 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;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
} else if (thickness == 1) {
/* Border made up from one part which can be plotted
* as a rectangle */
- int x0, y0, x1, y1;
+
if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
- /* 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;
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
+ if (res != NSERROR_OK) {
+ 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;
- /* 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;
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
+ if (res != NSERROR_OK) {
+ return false;
}
}
} else {
/* Border made up from two parts and can't be plotted
- * with rectangles */
+ * with rectangles
+ */
z[0] = p[0];
z[1] = p[1];
z[2] = (p[0] + p[2]) / 2;
@@ -675,14 +721,18 @@ static bool html_redraw_border_plot(const int side, const int *p,
colour c,
z[5] = (p[7] + p[5]) / 2;
z[6] = p[6];
z[7] = p[7];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
z[0] = p[2];
z[1] = p[3];
z[6] = p[4];
z[7] = p[5];
- if (!plot->polygon(z, 4, plot_style_bdr_out))
+ res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
+ if (res != NSERROR_OK) {
return false;
+ }
}
break;
}
@@ -1152,42 +1202,85 @@ static bool html_redraw_inline_borders(struct box *box, struct
rect b,
static bool html_redraw_checkbox(int x, int y, int width, int height,
bool selected, const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
- double z = width * 0.15;
- if (z == 0)
+ double z;
+ nserror res;
+ struct rect rect;
+
+ z = width * 0.15;
+ if (z == 0) {
z = 1;
+ }
- if (!(plot->rectangle(x, y, x + width, y + height,
- plot_style_fill_wbasec) &&
- plot->line(x, y, x + width, y, plot_style_stroke_darkwbasec) &&
- plot->line(x, y, x, y + height, plot_style_stroke_darkwbasec) &&
- plot->line(x + width, y, x + width, y + height,
- plot_style_stroke_lightwbasec) &&
- plot->line(x, y + height, x + width, y + height,
- plot_style_stroke_lightwbasec)))
+ rect.x0 = x;
+ rect.y0 = y ;
+ rect.x1 = x + width;
+ rect.y1 = y + height;
+ res = ctx->plot->rectangle(ctx, plot_style_fill_wbasec, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
+
+ /* dark line across top */
+ rect.y1 = y;
+ res = ctx->plot->line(ctx, plot_style_stroke_darkwbasec, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ /* dark line across left */
+ rect.x1 = x;
+ rect.y1 = y + height;
+ res = ctx->plot->line(ctx, plot_style_stroke_darkwbasec, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ /* light line across right */
+ rect.x0 = x + width;
+ rect.x1 = x + width;
+ res = ctx->plot->line(ctx, plot_style_stroke_lightwbasec, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ /* light line across bottom */
+ rect.x0 = x;
+ rect.y0 = y + height;
+ res = ctx->plot->line(ctx, plot_style_stroke_lightwbasec, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
if (selected) {
if (width < 12 || height < 12) {
/* render a solid box instead of a tick */
- if (!plot->rectangle(x + z + z, y + z + z,
- x + width - z, y + height - z,
- plot_style_fill_wblobc))
+ rect.x0 = x + z + z;
+ rect.y0 = y + z + z;
+ rect.x1 = x + width - z;
+ rect.y1 = y + height - z;
+ res = ctx->plot->rectangle(ctx, plot_style_fill_wblobc, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
} else {
/* render a tick, as it'll fit comfortably */
- if (!(plot->line(x + width - z,
- y + z,
- x + (z * 3),
- y + height - z,
- plot_style_stroke_wblobc) &&
-
- plot->line(x + (z * 3),
- y + height - z,
- x + z + z,
- y + (height / 2),
- plot_style_stroke_wblobc)))
+ rect.x0 = x + width - z;
+ rect.y0 = y + z;
+ rect.x1 = x + (z * 3);
+ rect.y1 = y + height - z;
+ res = ctx->plot->line(ctx, plot_style_stroke_wblobc, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ rect.x0 = x + (z * 3);
+ rect.y0 = y + height - z;
+ rect.x1 = x + z + z;
+ rect.y1 = y + (height / 2);
+ res = ctx->plot->line(ctx, plot_style_stroke_wblobc, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
}
}
return true;
@@ -1208,40 +1301,52 @@ static bool html_redraw_checkbox(int x, int y, int width, int
height,
static bool html_redraw_radio(int x, int y, int width, int height,
bool selected, const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
+ nserror res;
/* plot background of radio button */
- if (!plot->disc(x + width * 0.5,
- y + height * 0.5,
- width * 0.5 - 1,
- plot_style_fill_wbasec))
+ res = ctx->plot->disc(ctx,
+ plot_style_fill_wbasec,
+ x + width * 0.5,
+ y + height * 0.5,
+ width * 0.5 - 1);
+ if (res != NSERROR_OK) {
return false;
+ }
/* plot dark arc */
- if (!plot->arc(x + width * 0.5,
- y + height * 0.5,
- width * 0.5 - 1,
- 45,
- 225,
- plot_style_fill_darkwbasec))
+ res = ctx->plot->arc(ctx,
+ plot_style_fill_darkwbasec,
+ x + width * 0.5,
+ y + height * 0.5,
+ width * 0.5 - 1,
+ 45,
+ 225);
+ if (res != NSERROR_OK) {
return false;
+ }
/* plot light arc */
- if (!plot->arc(x + width * 0.5,
- y + height * 0.5,
- width * 0.5 - 1,
- 225,
- 45,
- plot_style_fill_lightwbasec))
+ res = ctx->plot->arc(ctx,
+ plot_style_fill_lightwbasec,
+ x + width * 0.5,
+ y + height * 0.5,
+ width * 0.5 - 1,
+ 225,
+ 45);
+ if (res != NSERROR_OK) {
return false;
+ }
if (selected) {
/* plot selection blob */
- if (!plot->disc(x + width * 0.5,
- y + height * 0.5,
- width * 0.3 - 1,
- plot_style_fill_wblobc))
+ res = ctx->plot->disc(ctx,
+ plot_style_fill_wblobc,
+ x + width * 0.5,
+ y + height * 0.5,
+ width * 0.3 - 1);
+ if (res != NSERROR_OK) {
return false;
+ }
}
return true;
@@ -1275,10 +1380,11 @@ static bool html_redraw_file(int x, int y, int width, int height,
font_plot_style_from_css(box->style, &fstyle);
fstyle.background = background_colour;
- if (box->gadget->value)
+ if (box->gadget->value) {
text = box->gadget->value;
- else
+ } else {
text = messages_get("Form_Drop");
+ }
length = strlen(text);
res = guit->layout->width(&fstyle, text, length, &text_width);
@@ -1292,7 +1398,11 @@ static bool html_redraw_file(int x, int y, int width, int height,
x = x + 4;
}
- return ctx->plot->text(x, y + height * 0.75, text, length, &fstyle);
+ res = ctx->plot->text(ctx, &fstyle, x, y + height * 0.75, text, length);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ return true;
}
@@ -1318,7 +1428,6 @@ static bool html_redraw_background(int x, int y, struct box *box,
float scale,
const struct rect *clip, colour *background_colour,
struct box *background, const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
bool repeat_x = false;
bool repeat_y = false;
bool plot_colour = true;
@@ -1336,6 +1445,7 @@ static bool html_redraw_background(int x, int y, struct box *box,
float scale,
.fill_type = PLOT_OP_TYPE_SOLID,
.fill_colour = *background_colour,
};
+ nserror res;
if (ctx->background_images == false)
return true;
@@ -1465,10 +1575,12 @@ static bool html_redraw_background(int x, int y, struct box *box,
float scale,
if (nscss_color_is_transparent(bgcol) == false) {
*background_colour = nscss_color_to_ns(bgcol);
pstyle_fill_bg.fill_colour = *background_colour;
- if (plot_colour)
- if (!plot->rectangle(r.x0, r.y0, r.x1, r.y1,
- &pstyle_fill_bg))
+ if (plot_colour) {
+ res = ctx->plot->rectangle(ctx, &pstyle_fill_bg, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
+ }
}
/* and plot the image */
if (plot_content) {
@@ -1492,8 +1604,10 @@ static bool html_redraw_background(int x, int y, struct box *box,
float scale,
if ((r.x0 < r.x1) && (r.y0 < r.y1)) {
struct content_redraw_data bg_data;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
bg_data.x = x;
bg_data.y = y;
@@ -1539,7 +1653,6 @@ static bool html_redraw_inline_background(int x, int y, struct box
*box,
bool first, bool last, colour *background_colour,
const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
struct rect r = *clip;
bool repeat_x = false;
bool repeat_y = false;
@@ -1552,6 +1665,7 @@ static bool html_redraw_inline_background(int x, int y, struct box
*box,
.fill_type = PLOT_OP_TYPE_SOLID,
.fill_colour = *background_colour,
};
+ nserror res;
plot_content = (box->background != NULL);
@@ -1618,10 +1732,12 @@ static bool html_redraw_inline_background(int x, int y, struct box
*box,
*background_colour = nscss_color_to_ns(bgcol);
pstyle_fill_bg.fill_colour = *background_colour;
- if (plot_colour)
- if (!plot->rectangle(r.x0, r.y0, r.x1, r.y1,
- &pstyle_fill_bg))
+ if (plot_colour) {
+ res = ctx->plot->rectangle(ctx, &pstyle_fill_bg, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
+ }
}
/* and plot the image */
if (plot_content) {
@@ -1644,8 +1760,10 @@ static bool html_redraw_inline_background(int x, int y, struct box
*box,
if ((r.x0 < r.x1) && (r.y0 < r.y1)) {
struct content_redraw_data bg_data;
- if (!plot->clip(&r))
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
return false;
+ }
bg_data.x = x;
bg_data.y = y;
@@ -1678,28 +1796,36 @@ static bool html_redraw_inline_background(int x, int y, struct box
*box,
* \return true if successful, false otherwise
*/
-static bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
- float scale, colour colour, float ratio,
- const struct redraw_context *ctx)
+static bool
+html_redraw_text_decoration_inline(struct box *box,
+ int x, int y,
+ float scale,
+ colour colour,
+ float ratio,
+ const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
struct box *c;
plot_style_t plot_style_box = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = colour,
};
+ nserror res;
+ struct rect rect;
for (c = box->next;
- c && c != box->inline_end;
- c = c->next) {
- if (c->type != BOX_TEXT)
+ c && c != box->inline_end;
+ c = c->next) {
+ if (c->type != BOX_TEXT) {
continue;
- if (!plot->line((x + c->x) * scale,
- (y + c->y + c->height * ratio) * scale,
- (x + c->x + c->width) * scale,
- (y + c->y + c->height * ratio) * scale,
- &plot_style_box))
+ }
+ rect.x0 = (x + c->x) * scale;
+ rect.y0 = (y + c->y + c->height * ratio) * scale;
+ rect.x1 = (x + c->x + c->width) * scale;
+ rect.y1 = (y + c->y + c->height * ratio) * scale;
+ res = ctx->plot->line(ctx, &plot_style_box, &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
}
return true;
}
@@ -1718,28 +1844,34 @@ static bool html_redraw_text_decoration_inline(struct box *box,
int x, int y,
* \return true if successful, false otherwise
*/
-static bool html_redraw_text_decoration_block(struct box *box, int x, int y,
- float scale, colour colour, float ratio,
- const struct redraw_context *ctx)
+static bool
+html_redraw_text_decoration_block(struct box *box,
+ int x, int y,
+ float scale,
+ colour colour,
+ float ratio,
+ const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
struct box *c;
plot_style_t plot_style_box = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = colour,
};
+ nserror res;
+ struct rect rect;
/* draw through text descendants */
for (c = box->children; c; c = c->next) {
if (c->type == BOX_TEXT) {
- if (!plot->line((x + c->x) * scale,
- (y + c->y + c->height * ratio) * scale,
- (x + c->x + c->width) * scale,
- (y + c->y + c->height * ratio) * scale,
- &plot_style_box))
+ rect.x0 = (x + c->x) * scale;
+ rect.y0 = (y + c->y + c->height * ratio) * scale;
+ rect.x1 = (x + c->x + c->width) * scale;
+ rect.y1 = (y + c->y + c->height * ratio) * scale;
+ res = ctx->plot->line(ctx, &plot_style_box, &rect);
+ if (res != NSERROR_OK) {
return false;
- } else if (c->type == BOX_INLINE_CONTAINER ||
- c->type == BOX_BLOCK) {
+ }
+ } else if ((c->type == BOX_INLINE_CONTAINER) || (c->type == BOX_BLOCK)) {
if (!html_redraw_text_decoration_block(c,
x + c->x, y + c->y,
scale, colour, ratio, ctx))
@@ -1924,6 +2056,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
int padding_left, padding_top, padding_width, padding_height;
int border_left, border_top, border_right, border_bottom;
struct rect r;
+ struct rect rect;
int x_scrolled, y_scrolled;
struct box *bg_box = NULL;
bool has_x_scroll, has_y_scroll;
@@ -2069,17 +2202,19 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* if visibility is hidden render children only */
if (box->style && css_computed_visibility(box->style) ==
CSS_VISIBILITY_HIDDEN) {
- if ((plot->group_start) && (!plot->group_start("hidden box")))
+ if ((ctx->plot->group_start) &&
+ (ctx->plot->group_start(ctx, "hidden box") != NSERROR_OK))
return false;
if (!html_redraw_box_children(html, box, x_parent, y_parent,
&r, scale, current_background_color, ctx))
return false;
- return ((!plot->group_end) || (plot->group_end()));
+ return ((!ctx->plot->group_end) || (ctx->plot->group_end(ctx) ==
NSERROR_OK));
}
- if ((plot->group_start) && (!plot->group_start("vis box")))
+ if ((ctx->plot->group_start) &&
+ (ctx->plot->group_start(ctx,"vis box") != NSERROR_OK)) {
return false;
-
+ }
if (box->style != NULL &&
css_computed_position(box->style) ==
@@ -2115,9 +2250,10 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* Nothing to do for invalid rectangles */
if (r.x0 >= r.x1 || r.y0 >= r.y1)
/* not an error */
- return ((!plot->group_end) || (plot->group_end()));
+ return ((!ctx->plot->group_end) ||
+ (ctx->plot->group_end(ctx) == NSERROR_OK));
/* clip to it */
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
} else if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
@@ -2130,14 +2266,15 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* no point trying to draw 0-width/height boxes */
if (r.x0 == r.x1 || r.y0 == r.y1)
/* not an error */
- return ((!plot->group_end) || (plot->group_end()));
+ return ((!ctx->plot->group_end) ||
+ (ctx->plot->group_end(ctx) == NSERROR_OK));
/* clip to it */
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
} else {
/* clip box is fine, clip to it */
r = *clip;
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
}
@@ -2194,22 +2331,22 @@ bool html_redraw_box(const html_content *html, struct box *box,
¤t_background_color, bg_box, ctx))
return false;
/* restore previous graphics window */
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
}
}
/* borders for block level content and replaced inlines */
- if (box->style && box->type != BOX_TEXT &&
- box->type != BOX_INLINE_END &&
- (box->type != BOX_INLINE || box->object ||
- box->flags & IFRAME || box->flags & REPLACE_DIM ||
- (box->gadget != NULL &&
- (box->gadget->type == GADGET_TEXTAREA ||
- box->gadget->type == GADGET_TEXTBOX ||
- box->gadget->type == GADGET_PASSWORD))) &&
- (border_top || border_right ||
- border_bottom || border_left)) {
+ if (box->style &&
+ box->type != BOX_TEXT &&
+ box->type != BOX_INLINE_END &&
+ (box->type != BOX_INLINE || box->object ||
+ box->flags & IFRAME || box->flags & REPLACE_DIM ||
+ (box->gadget != NULL &&
+ (box->gadget->type == GADGET_TEXTAREA ||
+ box->gadget->type == GADGET_TEXTBOX ||
+ box->gadget->type == GADGET_PASSWORD))) &&
+ (border_top || border_right || border_bottom || border_left)) {
if (!html_redraw_borders(box, x_parent, y_parent,
padding_width, padding_height, &r,
scale, ctx))
@@ -2273,7 +2410,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
¤t_background_color, ctx))
return false;
/* restore previous graphics window */
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
if (!html_redraw_inline_borders(box, b, &r,
scale, first, false, ctx))
@@ -2305,7 +2442,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
first, true, ¤t_background_color, ctx))
return false;
/* restore previous graphics window */
- if (!plot->clip(&r))
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
if (!html_redraw_inline_borders(box, b, &r, scale, first, true,
ctx))
@@ -2330,26 +2467,27 @@ bool html_redraw_box(const html_content *html, struct box *box,
margin_bottom = box->margin[BOTTOM] * scale;
}
/* Content edge -- blue */
- if (!plot->rectangle(x + padding_left,
- y + padding_top,
- x + padding_left + width,
- y + padding_top + height,
- plot_style_content_edge))
+ rect.x0 = x + padding_left;
+ rect.y0 = y + padding_top;
+ rect.x1 = x + padding_left + width;
+ rect.y1 = y + padding_top + height;
+ if (ctx->plot->rectangle(ctx, plot_style_content_edge, &rect) != NSERROR_OK)
return false;
+
/* Padding edge -- red */
- if (!plot->rectangle(x, y,
- x + padding_width, y + padding_height,
- plot_style_padding_edge))
+ rect.x0 = x;
+ rect.y0 = y;
+ rect.x1 = x + padding_width;
+ rect.y1 = y + padding_height;
+ if (ctx->plot->rectangle(ctx, plot_style_padding_edge, &rect) != NSERROR_OK)
return false;
+
/* Margin edge -- yellow */
- if (!plot->rectangle(
- x - border_left - margin_left,
- y - border_top - margin_top,
- x + padding_width + border_right +
- margin_right,
- y + padding_height + border_bottom +
- margin_bottom,
- plot_style_margin_edge))
+ rect.x0 = x - border_left - margin_left;
+ rect.y0 = y - border_top - margin_top;
+ rect.x1 = x + padding_width + border_right + margin_right;
+ rect.y1 = y + padding_height + border_bottom + margin_bottom;
+ if (ctx->plot->rectangle(ctx, plot_style_margin_edge, &rect) != NSERROR_OK)
return false;
}
@@ -2368,8 +2506,10 @@ bool html_redraw_box(const html_content *html, struct box *box,
if (r.y0 < clip->y0) r.y0 = clip->y0;
if (clip->x1 < r.x1) r.x1 = clip->x1;
if (clip->y1 < r.y1) r.y1 = clip->y1;
- if (r.x1 <= r.x0 || r.y1 <= r.y0)
- return (!plot->group_end || plot->group_end());
+ if (r.x1 <= r.x0 || r.y1 <= r.y0) {
+ return (!ctx->plot->group_end ||
+ (ctx->plot->group_end(ctx) == NSERROR_OK));
+ }
need_clip = true;
} else if (overflow_x != CSS_OVERFLOW_VISIBLE) {
@@ -2379,8 +2519,10 @@ bool html_redraw_box(const html_content *html, struct box *box,
r.y1 = clip->y1;
if (r.x0 < clip->x0) r.x0 = clip->x0;
if (clip->x1 < r.x1) r.x1 = clip->x1;
- if (r.x1 <= r.x0)
- return (!plot->group_end || plot->group_end());
+ if (r.x1 <= r.x0) {
+ return (!ctx->plot->group_end ||
+ (ctx->plot->group_end(ctx) == NSERROR_OK));
+ }
need_clip = true;
} else if (overflow_y != CSS_OVERFLOW_VISIBLE) {
@@ -2390,26 +2532,30 @@ bool html_redraw_box(const html_content *html, struct box *box,
r.y1 = y + padding_height;
if (r.y0 < clip->y0) r.y0 = clip->y0;
if (clip->y1 < r.y1) r.y1 = clip->y1;
- if (r.y1 <= r.y0)
- return (!plot->group_end || plot->group_end());
+ if (r.y1 <= r.y0) {
+ return (!ctx->plot->group_end ||
+ (ctx->plot->group_end(ctx) == NSERROR_OK));
+ }
need_clip = true;
}
- if (need_clip && (box->type == BOX_BLOCK ||
- box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->object)) {
- if (!plot->clip(&r))
+ if (need_clip &&
+ (box->type == BOX_BLOCK ||
+ box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_TABLE_CELL || box->object)) {
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
}
}
/* text decoration */
- if (box->type != BOX_TEXT && box->style &&
- css_computed_text_decoration(box->style) !=
- CSS_TEXT_DECORATION_NONE)
+ if ((box->type != BOX_TEXT) &&
+ box->style &&
+ css_computed_text_decoration(box->style) != CSS_TEXT_DECORATION_NONE) {
if (!html_redraw_text_decoration(box, x_parent, y_parent,
scale, current_background_color, ctx))
return false;
+ }
if (box->object && width != 0 && height != 0) {
struct content_redraw_data obj_data;
@@ -2439,11 +2585,12 @@ bool html_redraw_box(const html_content *html, struct box *box,
int obj_x = x + padding_left;
nserror res;
- if (!plot->rectangle(x + padding_left,
- y + padding_top,
- x + padding_left + width - 1,
- y + padding_top + height - 1,
- plot_style_broken_object)) {
+ rect.x0 = x + padding_left;
+ rect.y0 = y + padding_top;
+ rect.x1 = x + padding_left + width - 1;
+ rect.y1 = y + padding_top + height - 1;
+ res = ctx->plot->rectangle(ctx, plot_style_broken_object, &rect);
+ if (res != NSERROR_OK) {
return false;
}
@@ -2457,10 +2604,10 @@ bool html_redraw_box(const html_content *html, struct box *box,
obj_x += width / 2 - obj_width / 2;
}
- if (!plot->text(obj_x, y + padding_top + (int)
- (height * 0.75),
- obj, sizeof(obj) - 1,
- plot_fstyle_broken_object))
+ if (ctx->plot->text(ctx,
+ plot_fstyle_broken_object,
+ obj_x, y + padding_top + (int)(height * 0.75),
+ obj, sizeof(obj) - 1) != NSERROR_OK)
return false;
}
@@ -2507,11 +2654,11 @@ bool html_redraw_box(const html_content *html, struct box *box,
if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
- if (!plot->clip(clip))
+ if (ctx->plot->clip(ctx, clip) != NSERROR_OK)
return false;
/* list marker */
- if (box->list_marker)
+ if (box->list_marker) {
if (!html_redraw_box(html, box->list_marker,
x_parent + box->x -
scrollbar_get_offset(box->scroll_x),
@@ -2519,6 +2666,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
scrollbar_get_offset(box->scroll_y),
clip, scale, current_background_color, ctx))
return false;
+ }
/* scrollbars */
if (((box->style && box->type != BOX_BR &&
@@ -2552,11 +2700,12 @@ bool html_redraw_box(const html_content *html, struct box *box,
}
if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
- if (!plot->clip(clip))
+ box->type == BOX_TABLE_CELL || box->type == BOX_INLINE) {
+ if (ctx->plot->clip(ctx, clip) != NSERROR_OK)
return false;
+ }
- return ((!plot->group_end) || (plot->group_end()));
+ return ((!plot->group_end) || (ctx->plot->group_end(ctx) == NSERROR_OK));
}
/**
@@ -2602,14 +2751,12 @@ bool html_redraw(struct content *c, struct content_redraw_data
*data,
if (!select_only) {
/* clear to background colour */
- result = ctx->plot->clip(clip);
+ result = (ctx->plot->clip(ctx, clip) == NSERROR_OK);
if (html->background_colour != NS_TRANSPARENT)
pstyle_fill_bg.fill_colour = html->background_colour;
-
- result &= ctx->plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- &pstyle_fill_bg);
+
+ result &= (ctx->plot->rectangle(ctx, &pstyle_fill_bg, clip) ==
NSERROR_OK);
result &= html_redraw_box(html, box, data->x, data->y, clip,
data->scale, pstyle_fill_bg.fill_colour, ctx);
diff --git a/render/textplain.c b/render/textplain.c
index ae14869..d376888 100644
--- a/render/textplain.c
+++ b/render/textplain.c
@@ -865,7 +865,6 @@ bool textplain_redraw(struct content *c, struct content_redraw_data
*data,
{
textplain_content *text = (textplain_content *) c;
struct browser_window *bw = text->bw;
- const struct plotter_table *plot = ctx->plot;
char *utf8_data = text->utf8_data;
long lineno;
int x = data->x;
@@ -878,6 +877,7 @@ bool textplain_redraw(struct content *c, struct content_redraw_data
*data,
struct textplain_line *line = text->physical_line;
size_t length;
plot_style_t *plot_style_highlight;
+ nserror res;
if (line0 < 0)
line0 = 0;
@@ -890,9 +890,10 @@ bool textplain_redraw(struct content *c, struct content_redraw_data
*data,
if (line1 < line0)
line1 = line0;
- if (!plot->rectangle(clip->x0, clip->y0, clip->x1, clip->y1,
- plot_style_fill_white))
+ res = ctx->plot->rectangle(ctx, plot_style_fill_white, clip);
+ if (res != NSERROR_OK) {
return false;
+ }
if (!line)
return true;
@@ -979,11 +980,17 @@ bool textplain_redraw(struct content *c, struct content_redraw_data
*data,
}
if (highlighted) {
- int sy = y + (lineno * scaled_line_height);
- if (!plot->rectangle(tx, sy,
- ntx, sy + scaled_line_height,
- plot_style_highlight))
+ struct rect rect;
+ rect.x0 = tx;
+ rect.y0 = y + (lineno * scaled_line_height);
+ rect.x1 = ntx;
+ rect.y1 = rect.y0 + scaled_line_height;
+ res = ctx->plot->rectangle(ctx,
+ plot_style_highlight,
+ &rect);
+ if (res != NSERROR_OK) {
return false;
+ }
}
}
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=9cc5f5e6069811b2d38...
commit 9cc5f5e6069811b2d3800e089a3913d6f0ca10b7
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
update plotter API to pass context
diff --git a/include/netsurf/plotters.h b/include/netsurf/plotters.h
index 88cbbe5..06fafab 100644
--- a/include/netsurf/plotters.h
+++ b/include/netsurf/plotters.h
@@ -31,6 +31,7 @@
struct bitmap;
struct rect;
+struct plotter_table;
typedef unsigned long bitmap_flags_t;
#define BITMAPF_NONE 0
@@ -44,50 +45,45 @@ enum path_command {
PLOTTER_PATH_BEZIER,
};
-/** Set of target specific plotting functions.
- *
- * The functions are:
- * arc - Plots an arc, around (x,y), from anticlockwise from angle1 to
- * angle2. Angles are measured anticlockwise from horizontal, in
- * degrees.
- * disc - Plots a circle, centered on (x,y), which is optionally filled.
- * line - Plots a line from (x0,y0) to (x1,y1). Coordinates are at
- * centre of line width/thickness.
- * path - Plots a path consisting of cubic Bezier curves. Line colour is
- * given by c and fill colour is given by fill.
- * polygon - Plots a filled polygon with straight lines between points.
- * The lines around the edge of the ploygon are not plotted. The
- * polygon is filled with the non-zero winding rule.
- * rectangle - Plots a rectangle outline. The line can be solid, dotted or
- * dashed. Top left corner at (x0,y0) and rectangle has given
- * width and height.
- * fill - Plots a filled rectangle. Top left corner at (x0,y0), bottom
- * right corner at (x1,y1). Note: (x0,y0) is inside filled area,
- * but (x1,y1) is below and to the right. See diagram below.
- * clip - Sets a clip rectangle for subsequent plots.
- * text - Plots text. (x,y) is the coordinate of the left hand side of
- * the text's baseline. The text is UTF-8 encoded. The colour, c,
- * is the colour of the text. Background colour, bg, may be used
- * optionally to attempt to provide anti-aliased text without
- * screen reads. Font information is provided in the style.
- * bitmap - Tiled plot of a bitmap image. (x,y) gives the top left
- * coordinate of an explicitly placed tile. From this tile the
- * image can repeat in all four directions -- up, down, left and
- * right -- to the extents given by the current clip rectangle.
- * The bitmap_flags say whether to tile in the x and y
- * directions. If not tiling in x or y directions, the single
- * image is plotted. The width and height give the dimensions
- * the image is to be scaled to.
- * group_start - Start of a group of objects. Used when plotter implements
- * export to a vector graphics file format. (Optional.)
- * group_end - End of the most recently started group. (Optional.)
- * flush - Only used internally by the knockout code. Should be NULL in
- * any front end display plotters or export plotters.
- *
- * Plotter options:
- * option_knockout - Optimisation particularly for unaccelerated screen
- * redraw. It tries to avoid plotting to the same area
- * more than once. See desktop/knockout.c
+/**
+ * Redraw context
+ */
+struct redraw_context {
+ /**
+ * Redraw to show interactive features.
+ *
+ * Active features include selections etc.
+ *
+ * \note Should be off for printing.
+ */
+ bool interactive;
+
+ /**
+ * Render background images.
+ *
+ * \note May want it off for printing.
+ */
+ bool background_images;
+
+ /**
+ * Current plot operation table
+ *
+ * \warning must be assigned before use.
+ */
+ const struct plotter_table *plot;
+
+ /**
+ * Private context.
+ *
+ * Private context allows callers to pass context through to
+ * plot operations without using a global.
+ */
+ void *priv;
+};
+
+
+/**
+ * Plotter operations table.
*
* Coordinates are from top left of canvas and (0,0) is the top left grid
* denomination. If a "fill" is drawn from (0,0) to (4,3), the result is:
@@ -101,61 +97,162 @@ enum path_command {
* 2 |#|#|#|#| |
* +-+-+-+-+-+-
* 3 | | | | | |
+ *
*/
struct plotter_table {
- /* clipping operations */
- bool (*clip)(const struct rect *clip);
+ /**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*clip)(const struct redraw_context *ctx, const struct rect *clip);
+
+ /**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the arc plot.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*arc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int
y, int radius, int angle1, int angle2);
+
+ /**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the circle plot.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*disc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int
y, int radius);
- /* shape primatives */
- bool (*arc)(int x, int y, int radius, int angle1, int angle2, const plot_style_t
*pstyle);
- bool (*disc)(int x, int y, int radius, const plot_style_t *pstyle);
- bool (*line)(int x0, int y0, int x1, int y1, const plot_style_t *pstyle);
- bool (*rectangle)(int x0, int y0, int x1, int y1, const plot_style_t *pstyle);
- bool (*polygon)(const int *p, unsigned int n, const plot_style_t *pstyle);
+ /**
+ * Plots a line
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x0,
int y0, int x1, int y1);
- /* complex path (for SVG) */
- bool (*path)(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6]);
+ /**
+ * Plots a rectangle.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, int
x0, int y0, int x1, int y1);
- /* Image */
- bool (*bitmap)(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
+ /**
+ * Plot a polygon
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*polygon)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
int *p, unsigned int n);
/**
- * Text.
+ * Plots a path.
+ *
+ * Path plot consisting of cubic Bezier curves. Line and fill colour is
+ * controlle dby the plot style.
*
- * \param x x coordinate
- * \param y y coordinate
- * \param text UTF-8 string to plot
- * \param length length of string, in bytes
- * \param fstyle plot style for this text
- * \return true on success, false on error and error reported
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
*/
- bool (*text)(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
+ nserror (*path)(const struct redraw_context *ctx, const plot_style_t *pstyle, const
float *p, unsigned int n, float width, const float transform[6]);
- /* optional callbacks */
- bool (*group_start)(const char *name); /**< optional, may be NULL */
- bool (*group_end)(void); /**< optional, may be NULL */
- bool (*flush)(void); /**< optional, may be NULL */
+ /**
+ * Plot a bitmap
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*bitmap)(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y,
int width, int height, colour bg, bitmap_flags_t flags);
- /* flags */
- bool option_knockout; /**< set if knockout rendering is required */
-};
+ /**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*text)(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int
x, int y, const char *text, size_t length);
+ /**
+ * Start of a group of objects.
+ *
+ * optional, may be NULL. Used when plotter implements export
+ * to a vector graphics file format.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*group_start)(const struct redraw_context *ctx, const char *name);
-/* Redraw context */
-struct redraw_context {
- /** Redraw to show interactive features, such as active selections
- * etc. Should be off for printing. */
- bool interactive;
+ /**
+ * End of the most recently started group.
+ *
+ * optional, may be NULL
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*group_end)(const struct redraw_context *ctx);
- /** Render background images. May want it off for printing. */
- bool background_images;
+ /**
+ * Only used internally by the knockout code. Must be NULL in
+ * any front end display plotters or export plotters.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*flush)(const struct redraw_context *ctx);
- /** Current plotters, must be assigned before use. */
- const struct plotter_table *plot;
+ /* flags */
+ /**
+ * flag to enable knockout rendering.
+ *
+ * Optimisation particularly for unaccelerated screen
+ * redraw. It tries to avoid plotting to the same area more
+ * than once. See desktop/knockout.c
+ */
+ bool option_knockout;
};
#endif
-----------------------------------------------------------------------
Summary of changes:
render/Makefile | 3 +-
render/html_internal.h | 9 +
render/html_redraw.c | 850 +--------------------------------------
render/html_redraw_border.c | 928 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 945 insertions(+), 845 deletions(-)
create mode 100644 render/html_redraw_border.c
diff --git a/render/Makefile b/render/Makefile
index 148c2c3..dc2e31c 100644
--- a/render/Makefile
+++ b/render/Makefile
@@ -3,7 +3,8 @@
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c imagemap.c layout.c search.c table.c textplain.c \
html.c html_css.c html_css_fetcher.c html_script.c \
- html_interaction.c html_redraw.c html_forms.c html_object.c
+ html_interaction.c html_redraw.c html_redraw_border.c \
+ html_forms.c html_object.c
S_RENDER := $(addprefix render/,$(S_RENDER))
diff --git a/render/html_internal.h b/render/html_internal.h
index fd65707..2f84cf8 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -258,6 +258,15 @@ bool html_begin_conversion(html_content *htmlc);
bool html_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx);
+/* in render/html_redraw_border.c */
+bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
+ int p_width, int p_height, const struct rect *clip, float scale,
+ const struct redraw_context *ctx);
+
+bool html_redraw_inline_borders(struct box *box, struct rect b,
+ const struct rect *clip, float scale, bool first, bool last,
+ const struct redraw_context *ctx);
+
/* in render/html_interaction.c */
void html_mouse_track(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
diff --git a/render/html_redraw.c b/render/html_redraw.c
index 6ef27c3..598e613 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -344,848 +344,6 @@ text_redraw(const char *utf8_text,
return true;
}
-static plot_style_t plot_style_bdr = {
- .stroke_type = PLOT_OP_TYPE_DASH,
-};
-static plot_style_t plot_style_fillbdr = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_light = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_ddark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dlight = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-
-static inline nserror
-plot_clipped_rectangle(const struct redraw_context *ctx,
- const plot_style_t *style,
- const struct rect *clip,
- struct rect *rect)
-{
- nserror res;
-
- rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
- rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
- rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
- rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
- if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
- /* valid clip rectangles only */
- res = ctx->plot->rectangle(ctx, style, rect);
- } else {
- res = NSERROR_OK;
- }
- return res;
-}
-
-/**
- * Draw one border.
- *
- * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
- * \param p array of precomputed border vertices
- * \param c colour for border
- * \param style border line style
- * \param thickness border thickness
- * \param rectangular whether border is rectangular
- * \param clip cliping area for redrawing border.
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static bool
-html_redraw_border_plot(const int side,
- const int *p,
- colour c,
- enum css_border_style_e style,
- int thickness,
- bool rectangular,
- const struct rect *clip,
- const struct redraw_context *ctx)
-{
- int z[8]; /* Vertices of border part */
- unsigned int light = side;
- plot_style_t *plot_style_bdr_in;
- plot_style_t *plot_style_bdr_out;
- nserror res;
- struct rect rect;
-
- if (c == NS_TRANSPARENT)
- return true;
-
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
- plot_style_bdr.stroke_colour = c;
- plot_style_bdr.stroke_width = thickness;
- plot_style_fillbdr.fill_colour = c;
- plot_style_fillbdr_dark.fill_colour = darken_colour(c);
- plot_style_fillbdr_light.fill_colour = lighten_colour(c);
- plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
- plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
-
- switch (style) {
- case CSS_BORDER_STYLE_DOTTED:
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
- /* fall through */
- case CSS_BORDER_STYLE_DASHED:
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = (p[4] + p[6]) / 2;
- rect.y1 = (p[5] + p[7]) / 2;
- res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- break;
-
- case CSS_BORDER_STYLE_SOLID:
- /* fall through to default */
- default:
- if (rectangular || thickness == 1) {
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- if ((side == TOP) &&
- (p[4] - p[6] != 0)) {
- rect.x1 = p[4];
- } else {
- rect.x1 = p[6];
- }
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- if ((side == LEFT) &&
- (p[1] - p[3] != 0)) {
- rect.y1 = p[1];
- } else {
- rect.y1 = p[3];
- }
- }
- res = plot_clipped_rectangle(ctx, &plot_style_fillbdr, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- } else {
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- }
- break;
-
- case CSS_BORDER_STYLE_DOUBLE:
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] * 2 + p[2]) / 3;
- z[3] = (p[1] * 2 + p[3]) / 3;
- z[4] = (p[6] * 2 + p[4]) / 3;
- z[5] = (p[7] * 2 + p[5]) / 3;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[2] = (p[2] * 2 + p[0]) / 3;
- z[3] = (p[3] * 2 + p[1]) / 3;
- z[4] = (p[4] * 2 + p[6]) / 3;
- z[5] = (p[5] * 2 + p[7]) / 3;
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- break;
-
- case CSS_BORDER_STYLE_GROOVE:
- light = 3 - light;
- /* fall through */
-
- case CSS_BORDER_STYLE_RIDGE:
- /* choose correct colours for each part of the border line */
- if (light <= 1) {
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- } else {
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles
- */
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = p[6];
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = (p[0] + p[2]) / 2;
- rect.y1 = (p[1] + p[3]) / 2;
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = (p[6] + p[4]) / 2;
- rect.y1 = (p[7] + p[5]) / 2;
- } else {
- rect.x0 = (p[6] + p[4]) / 2;
- rect.y0 = (p[7] + p[5]) / 2;
- rect.x1 = p[2];
- rect.y1 = p[3];
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- } else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = p[6];
- rect.y1 = p[7];
- rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- rect.x1 + p[4] - p[6] : rect.x1;
-
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- rect.y1 = p[3];
- rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- rect.y1 + p[1] - p[3] : rect.y1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- }
- } else {
- /* Border made up from two parts and can't be plotted
- * with rectangles
- */
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- }
- break;
-
- case CSS_BORDER_STYLE_INSET:
- light = (light + 2) % 4;
- /* fall through */
- case CSS_BORDER_STYLE_OUTSET:
- /* choose correct colours for each part of the border line */
- switch (light) {
- case 0:
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dlight;
- break;
- case 1:
- plot_style_bdr_in = &plot_style_fillbdr_ddark;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- break;
- case 2:
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_ddark;
- break;
- case 3:
- plot_style_bdr_in = &plot_style_fillbdr_dlight;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- break;
- default:
- plot_style_bdr_in = &plot_style_fillbdr;
- plot_style_bdr_out = &plot_style_fillbdr;
- break;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles
- */
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = (p[0] + p[2]) / 2;
- rect.y0 = (p[1] + p[3]) / 2;
- rect.x1 = p[6];
- rect.y1 = p[7];
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = (p[0] + p[2]) / 2;
- rect.y1 = (p[1] + p[3]) / 2;
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = (p[6] + p[4]) / 2;
- rect.y1 = (p[7] + p[5]) / 2;
- } else {
- rect.x0 = (p[6] + p[4]) / 2;
- rect.y0 = (p[7] + p[5]) / 2;
- rect.x1 = p[2];
- rect.y1 = p[3];
- }
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- } else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
-
- if (side == TOP || side == RIGHT) {
- rect.x0 = p[2];
- rect.y0 = p[3];
- rect.x1 = p[6];
- rect.y1 = p[7];
- rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- rect.x1 + p[4] - p[6] : rect.x1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_in, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- } else {
- rect.x0 = p[6];
- rect.y0 = p[7];
- rect.x1 = p[2];
- rect.y1 = p[3];
- rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- rect.y1 + p[1] - p[3] : rect.y1;
- res = plot_clipped_rectangle(ctx, plot_style_bdr_out, clip, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- }
- } else {
- /* Border made up from two parts and can't be plotted
- * with rectangles
- */
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
- if (res != NSERROR_OK) {
- return false;
- }
- }
- break;
- }
-
- return true;
-}
-
-
-/**
- * Draw borders for a box.
- *
- * \param box box to draw
- * \param x_parent coordinate of left padding edge of parent of box
- * \param y_parent coordinate of top padding edge of parent of box
- * \param p_width width of padding box
- * \param p_height height of padding box
- * \param clip cliping area for redrawing border.
- * \param scale scale for redraw
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, const struct rect *clip, float scale,
- const struct redraw_context *ctx)
-{
- unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
- int top = box->border[TOP].width;
- int right = box->border[RIGHT].width;
- int bottom = box->border[BOTTOM].width;
- int left = box->border[LEFT].width;
- int x, y;
- unsigned int i, side;
- int p[8]; /* Box border vertices */
- int z[8]; /* Border vertices */
- bool square_end_1 = false;
- bool square_end_2 = false;
-
- x = x_parent + box->x;
- y = y_parent + box->y;
-
- if (scale != 1.0) {
- top *= scale;
- right *= scale;
- bottom *= scale;
- left *= scale;
- x *= scale;
- y *= scale;
- }
-
- assert(box->style);
-
- /* Calculate border vertices
- *
- * A----------------------+
- * | \ / |
- * | B--------------+ |
- * | | | |
- * | +--------------C |
- * | / \ |
- * +----------------------D
- */
- p[0] = x - left; p[1] = y - top; /* A */
- p[2] = x; p[3] = y; /* B */
- p[4] = x + p_width; p[5] = y + p_height; /* C */
- p[6] = x + p_width + right; p[7] = y + p_height + bottom; /* D */
-
- for (i = 0; i != 4; i++) {
- colour col = 0;
- side = sides[i]; /* plot order */
-
- if (box->border[side].width == 0 ||
- nscss_color_is_transparent(box->border[side].c))
- continue;
-
- switch (side) {
- case LEFT:
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
-
- z[0] = p[0]; z[1] = p[7];
- z[2] = p[2]; z[3] = p[5];
- z[4] = p[2]; z[5] = p[3];
- z[6] = p[0]; z[7] = p[1];
-
- if (nscss_color_is_transparent(box->border[TOP].c) ==
- false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[5] -= top;
- square_end_1 = true;
- }
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- 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, ctx))
- return false;
- break;
- case RIGHT:
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
-
- z[0] = p[6]; z[1] = p[1];
- z[2] = p[4]; z[3] = p[3];
- z[4] = p[4]; z[5] = p[5];
- z[6] = p[6]; z[7] = p[7];
-
- if (nscss_color_is_transparent(box->border[TOP].c) ==
- false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[3] -= top;
- square_end_1 = true;
- }
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- 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, ctx))
- 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);
-
- z[0] = p[2]; z[1] = p[3];
- z[2] = p[0]; z[3] = p[1];
- z[4] = p[6]; z[5] = p[1];
- z[6] = p[4]; z[7] = p[3];
-
- if (box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[2] += left;
- square_end_1 = true;
- }
- if (box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- 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, ctx))
- 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);
-
- z[0] = p[4]; z[1] = p[5];
- z[2] = p[6]; z[3] = p[7];
- z[4] = p[0]; z[5] = p[7];
- z[6] = p[2]; z[7] = p[5];
-
- if (box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[4] += left;
- square_end_1 = true;
- }
- if (box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- 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, ctx))
- return false;
- break;
- default:
- assert(side == TOP || side == BOTTOM ||
- side == LEFT || side == RIGHT);
- break;
- }
- }
-
- return true;
-}
-
-
-/**
- * Draw an inline's borders.
- *
- * \param box BOX_INLINE which created the border
- * \param b coordinates of border edge rectangle
- * \param clip cliping area for redrawing border.
- * \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
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-static bool html_redraw_inline_borders(struct box *box, struct rect b,
- const struct rect *clip, float scale, bool first, bool last,
- const struct redraw_context *ctx)
-{
- int top = box->border[TOP].width;
- int right = box->border[RIGHT].width;
- int bottom = box->border[BOTTOM].width;
- int left = box->border[LEFT].width;
- colour col;
- int p[8]; /* Box border vertices */
- int z[8]; /* Border vertices */
- bool square_end_1;
- bool square_end_2;
-
- if (scale != 1.0) {
- top *= scale;
- right *= scale;
- bottom *= scale;
- left *= scale;
- }
-
- /* Calculate border vertices
- *
- * A----------------------+
- * | \ / |
- * | B--------------+ |
- * | | | |
- * | +--------------C |
- * | / \ |
- * +----------------------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);
-
- /* Left */
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
- if (left != 0 && first && nscss_color_is_transparent(
- box->border[LEFT].c) == false) {
- col = nscss_color_to_ns(box->border[LEFT].c);
-
- z[0] = p[0]; z[1] = p[7];
- z[2] = p[2]; z[3] = p[5];
- z[4] = p[2]; z[5] = p[3];
- z[6] = p[0]; z[7] = p[1];
-
- if (nscss_color_is_transparent(box->border[TOP].c) == false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[5] -= top;
- square_end_1 = true;
- }
-
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[3] += bottom;
- square_end_2 = true;
- }
-
- if (!html_redraw_border_plot(LEFT, z, col,
- box->border[LEFT].style,
- left, square_end_1 && square_end_2,
- clip, ctx))
- return false;
- }
-
- /* Right */
- square_end_1 = (top == 0);
- square_end_2 = (bottom == 0);
- if (right != 0 && last && nscss_color_is_transparent(
- box->border[RIGHT].c) == false) {
- col = nscss_color_to_ns(box->border[RIGHT].c);
-
- z[0] = p[6]; z[1] = p[1];
- z[2] = p[4]; z[3] = p[3];
- z[4] = p[4]; z[5] = p[5];
- z[6] = p[6]; z[7] = p[7];
-
- if (nscss_color_is_transparent(box->border[TOP].c) == false &&
- box->border[TOP].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang top corner fully,
- * if top border is opaque */
- z[3] -= top;
- square_end_1 = true;
- }
-
- if (nscss_color_is_transparent(box->border[BOTTOM].c) ==
- false &&
- box->border[BOTTOM].style !=
- CSS_BORDER_STYLE_DOUBLE) {
- /* make border overhang bottom corner fully,
- * if bottom border is opaque */
- z[5] += bottom;
- square_end_2 = true;
- }
-
- if (!html_redraw_border_plot(RIGHT, z, col,
- box->border[RIGHT].style,
- right, square_end_1 && square_end_2,
- clip, ctx))
- return false;
- }
-
- /* Top */
- square_end_1 = (left == 0);
- square_end_2 = (right == 0);
- if (top != 0 && nscss_color_is_transparent(
- box->border[TOP].c) == false) {
- col = nscss_color_to_ns(box->border[TOP].c);
-
- z[0] = p[2]; z[1] = p[3];
- z[2] = p[0]; z[3] = p[1];
- z[4] = p[6]; z[5] = p[1];
- z[6] = p[4]; z[7] = p[3];
-
- if (first && box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[2] += left;
- square_end_1 = true;
- }
-
- if (last && box->border[TOP].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[TOP].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[4] -= right;
- square_end_2 = true;
- }
-
- if (!html_redraw_border_plot(TOP, z, col,
- box->border[TOP].style,
- top, square_end_1 && square_end_2,
- clip, ctx))
- return false;
- }
-
- /* Bottom */
- square_end_1 = (left == 0);
- square_end_2 = (right == 0);
- if (bottom != 0 && nscss_color_is_transparent(
- box->border[BOTTOM].c) == false) {
- col = nscss_color_to_ns(box->border[BOTTOM].c);
-
- z[0] = p[4]; z[1] = p[5];
- z[2] = p[6]; z[3] = p[7];
- z[4] = p[0]; z[5] = p[7];
- z[6] = p[2]; z[7] = p[5];
-
- if (first && box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[LEFT].c) {
- /* don't bother overlapping left corner if
- * it's the same colour anyway */
- z[4] += left;
- square_end_1 = true;
- }
-
- if (last && box->border[BOTTOM].style ==
- CSS_BORDER_STYLE_SOLID &&
- box->border[BOTTOM].c ==
- box->border[RIGHT].c) {
- /* don't bother overlapping right corner if
- * it's the same colour anyway */
- z[2] -= right;
- square_end_2 = true;
- }
-
- if (!html_redraw_border_plot(BOTTOM, z, col,
- box->border[BOTTOM].style,
- bottom, square_end_1 && square_end_2,
- clip, ctx))
- return false;
- }
-
- return true;
-}
-
/**
* Plot a checkbox.
@@ -1398,7 +556,11 @@ static bool html_redraw_file(int x, int y, int width, int height,
x = x + 4;
}
- return ctx->plot->text(ctx, &fstyle, x, y + height * 0.75, text, length);
+ res = ctx->plot->text(ctx, &fstyle, x, y + height * 0.75, text, length);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ return true;
}
@@ -2265,7 +1427,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
return ((!ctx->plot->group_end) ||
(ctx->plot->group_end(ctx) == NSERROR_OK));
/* clip to it */
- if (ctx->plot->clip(ctx, &r) == NSERROR_OK)
+ if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
return false;
} else {
/* clip box is fine, clip to it */
diff --git a/render/html_redraw_border.c b/render/html_redraw_border.c
new file mode 100644
index 0000000..07c503c
--- /dev/null
+++ b/render/html_redraw_border.c
@@ -0,0 +1,928 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Redrawing CONTENT_HTML borders implementation.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "utils/log.h"
+#include "netsurf/plotters.h"
+#include "netsurf/css.h"
+
+#include "render/box.h"
+#include "render/html_internal.h"
+
+
+static plot_style_t plot_style_bdr = {
+ .stroke_type = PLOT_OP_TYPE_DASH,
+};
+static plot_style_t plot_style_fillbdr = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_light = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_ddark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dlight = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+
+static inline nserror
+plot_clipped_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *clip,
+ struct rect *rect)
+{
+ nserror res;
+
+ rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
+ rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
+ rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
+ rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
+ if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
+ /* valid clip rectangles only */
+ res = ctx->plot->rectangle(ctx, style, rect);
+ } else {
+ res = NSERROR_OK;
+ }
+ return res;
+}
+
+
+/**
+ * Draw one border.
+ *
+ * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
+ * \param p array of precomputed border vertices
+ * \param c colour for border
+ * \param style border line style
+ * \param thickness border thickness
+ * \param rectangular whether border is rectangular
+ * \param clip cliping area for redrawing border.
+ * \param ctx current redraw context
+ * \return NSERROR_OK if successful otherwise appropriate error code
+ */
+static nserror
+html_redraw_border_plot(const int side,
+ const int *p,
+ colour c,
+ enum css_border_style_e style,
+ int thickness,
+ bool rectangular,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ int z[8]; /* Vertices of border part */
+ unsigned int light = side;
+ plot_style_t *plot_style_bdr_in;
+ plot_style_t *plot_style_bdr_out;
+ nserror res = NSERROR_OK;
+ struct rect rect;
+
+ if (c == NS_TRANSPARENT) {
+ return res;
+ }
+
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
+ plot_style_bdr.stroke_colour = c;
+ plot_style_bdr.stroke_width = thickness;
+ plot_style_fillbdr.fill_colour = c;
+ plot_style_fillbdr_dark.fill_colour = darken_colour(c);
+ plot_style_fillbdr_light.fill_colour = lighten_colour(c);
+ plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
+ plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
+
+ switch (style) {
+ case CSS_BORDER_STYLE_DOTTED:
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
+ /* fall through */
+ case CSS_BORDER_STYLE_DASHED:
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = (p[4] + p[6]) / 2;
+ rect.y1 = (p[5] + p[7]) / 2;
+ res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
+ break;
+
+ case CSS_BORDER_STYLE_SOLID:
+ /* fall through to default */
+ default:
+ if (rectangular || thickness == 1) {
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ if ((side == TOP) &&
+ (p[4] - p[6] != 0)) {
+ rect.x1 = p[4];
+ } else {
+ rect.x1 = p[6];
+ }
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ if ((side == LEFT) &&
+ (p[1] - p[3] != 0)) {
+ rect.y1 = p[1];
+ } else {
+ rect.y1 = p[3];
+ }
+ }
+ res = plot_clipped_rectangle(ctx,
+ &plot_style_fillbdr,
+ clip,
+ &rect);
+ } else {
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
+ }
+ break;
+
+ case CSS_BORDER_STYLE_DOUBLE:
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] * 2 + p[2]) / 3;
+ z[3] = (p[1] * 2 + p[3]) / 3;
+ z[4] = (p[6] * 2 + p[4]) / 3;
+ z[5] = (p[7] * 2 + p[5]) / 3;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ if (res == NSERROR_OK) {
+ z[0] = p[2];
+ z[1] = p[3];
+ z[2] = (p[2] * 2 + p[0]) / 3;
+ z[3] = (p[3] * 2 + p[1]) / 3;
+ z[4] = (p[4] * 2 + p[6]) / 3;
+ z[5] = (p[5] * 2 + p[7]) / 3;
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
+ }
+ break;
+
+ case CSS_BORDER_STYLE_GROOVE:
+ light = 3 - light;
+ /* fall through */
+ case CSS_BORDER_STYLE_RIDGE:
+ /* choose correct colours for each part of the border line */
+ if (light <= 1) {
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ } else {
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be
+ * plotted with rectangles
+ */
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
+ } else {
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ }
+ } else {
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
+ */
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res == NSERROR_OK) {
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx,
+ plot_style_bdr_out,
+ z,
+ 4);
+ }
+ }
+ break;
+
+ case CSS_BORDER_STYLE_INSET:
+ light = (light + 2) % 4;
+ /* fall through */
+ case CSS_BORDER_STYLE_OUTSET:
+ /* choose correct colours for each part of the border line */
+ switch (light) {
+ case 0:
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dlight;
+ break;
+ case 1:
+ plot_style_bdr_in = &plot_style_fillbdr_ddark;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ break;
+ case 2:
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_ddark;
+ break;
+ case 3:
+ plot_style_bdr_in = &plot_style_fillbdr_dlight;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ break;
+ default:
+ plot_style_bdr_in = &plot_style_fillbdr;
+ plot_style_bdr_out = &plot_style_fillbdr;
+ break;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be
+ * plotted with rectangles
+ */
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = (p[0] + p[2]) / 2;
+ rect.y0 = (p[1] + p[3]) / 2;
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = (p[0] + p[2]) / 2;
+ rect.y1 = (p[1] + p[3]) / 2;
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = (p[6] + p[4]) / 2;
+ rect.y1 = (p[7] + p[5]) / 2;
+ } else {
+ rect.x0 = (p[6] + p[4]) / 2;
+ rect.y0 = (p[7] + p[5]) / 2;
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ }
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be
+ * plotted as a rectangle
+ */
+
+ if (side == TOP || side == RIGHT) {
+ rect.x0 = p[2];
+ rect.y0 = p[3];
+ rect.x1 = p[6];
+ rect.y1 = p[7];
+ rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ rect.x1 + p[4] - p[6] : rect.x1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_in,
+ clip,
+ &rect);
+ } else {
+ rect.x0 = p[6];
+ rect.y0 = p[7];
+ rect.x1 = p[2];
+ rect.y1 = p[3];
+ rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ rect.y1 + p[1] - p[3] : rect.y1;
+ res = plot_clipped_rectangle(ctx,
+ plot_style_bdr_out,
+ clip,
+ &rect);
+ }
+ } else {
+ /* Border made up from two parts and can't be
+ * plotted with rectangles
+ */
+
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
+ }
+ break;
+ }
+
+ return res;
+}
+
+
+/**
+ * Draw borders for a box.
+ *
+ * \param box box to draw
+ * \param x_parent coordinate of left padding edge of parent of box
+ * \param y_parent coordinate of top padding edge of parent of box
+ * \param p_width width of padding box
+ * \param p_height height of padding box
+ * \param clip cliping area for redrawing border.
+ * \param scale scale for redraw
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+bool
+html_redraw_borders(struct box *box,
+ int x_parent,
+ int y_parent,
+ int p_width,
+ int p_height,
+ const struct rect *clip,
+ float scale,
+ const struct redraw_context *ctx)
+{
+ unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
+ int top = box->border[TOP].width;
+ int right = box->border[RIGHT].width;
+ int bottom = box->border[BOTTOM].width;
+ int left = box->border[LEFT].width;
+ int x, y;
+ unsigned int i, side;
+ int p[8]; /* Box border vertices */
+ int z[8]; /* Border vertices */
+ bool square_end_1 = false;
+ bool square_end_2 = false;
+ nserror res;
+
+ x = x_parent + box->x;
+ y = y_parent + box->y;
+
+ if (scale != 1.0) {
+ top *= scale;
+ right *= scale;
+ bottom *= scale;
+ left *= scale;
+ x *= scale;
+ y *= scale;
+ }
+
+ assert(box->style);
+
+ /* Calculate border vertices
+ *
+ * A----------------------+
+ * | \ / |
+ * | B--------------+ |
+ * | | | |
+ * | +--------------C |
+ * | / \ |
+ * +----------------------D
+ */
+ p[0] = x - left; p[1] = y - top; /* A */
+ p[2] = x; p[3] = y; /* B */
+ p[4] = x + p_width; p[5] = y + p_height; /* C */
+ p[6] = x + p_width + right; p[7] = y + p_height + bottom; /* D */
+
+ for (i = 0; i != 4; i++) {
+ colour col = 0;
+ side = sides[i]; /* plot order */
+
+ if (box->border[side].width == 0 ||
+ nscss_color_is_transparent(box->border[side].c)) {
+ continue;
+ }
+
+ switch (side) {
+ case LEFT:
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+
+ z[0] = p[0]; z[1] = p[7];
+ z[2] = p[2]; z[3] = p[5];
+ z[4] = p[2]; z[5] = p[3];
+ z[6] = p[0]; z[7] = p[1];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[5] -= top;
+ square_end_1 = true;
+ }
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[3] += bottom;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ break;
+
+ case RIGHT:
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+
+ z[0] = p[6]; z[1] = p[1];
+ z[2] = p[4]; z[3] = p[3];
+ z[4] = p[4]; z[5] = p[5];
+ z[6] = p[6]; z[7] = p[7];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[3] -= top;
+ square_end_1 = true;
+ }
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[5] += bottom;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ 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);
+
+ z[0] = p[2]; z[1] = p[3];
+ z[2] = p[0]; z[3] = p[1];
+ z[4] = p[6]; z[5] = p[1];
+ z[6] = p[4]; z[7] = p[3];
+
+ if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[2] += left;
+ square_end_1 = true;
+ }
+ if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[4] -= right;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ 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);
+
+ z[0] = p[4]; z[1] = p[5];
+ z[2] = p[6]; z[3] = p[7];
+ z[4] = p[0]; z[5] = p[7];
+ z[6] = p[2]; z[7] = p[5];
+
+ if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[4] += left;
+ square_end_1 = true;
+ }
+ if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[2] -= right;
+ square_end_2 = true;
+ }
+
+ col = nscss_color_to_ns(box->border[side].c);
+
+ res = html_redraw_border_plot(side,
+ z,
+ col,
+ box->border[side].style,
+ box->border[side].width * scale,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ break;
+
+ default:
+ assert(side == TOP || side == BOTTOM ||
+ side == LEFT || side == RIGHT);
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Draw an inline's borders.
+ *
+ * \param box BOX_INLINE which created the border
+ * \param b coordinates of border edge rectangle
+ * \param clip cliping area for redrawing border.
+ * \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
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+bool
+html_redraw_inline_borders(struct box *box,
+ struct rect b,
+ const struct rect *clip,
+ float scale,
+ bool first,
+ bool last,
+ const struct redraw_context *ctx)
+{
+ int top = box->border[TOP].width;
+ int right = box->border[RIGHT].width;
+ int bottom = box->border[BOTTOM].width;
+ int left = box->border[LEFT].width;
+ colour col;
+ int p[8]; /* Box border vertices */
+ int z[8]; /* Border vertices */
+ bool square_end_1;
+ bool square_end_2;
+ nserror res;
+
+ if (scale != 1.0) {
+ top *= scale;
+ right *= scale;
+ bottom *= scale;
+ left *= scale;
+ }
+
+ /* Calculate border vertices
+ *
+ * A----------------------+
+ * | \ / |
+ * | B--------------+ |
+ * | | | |
+ * | +--------------C |
+ * | / \ |
+ * +----------------------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);
+
+ /* Left */
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+ if (left != 0 &&
+ first &&
+ nscss_color_is_transparent(box->border[LEFT].c) == false) {
+ col = nscss_color_to_ns(box->border[LEFT].c);
+
+ z[0] = p[0]; z[1] = p[7];
+ z[2] = p[2]; z[3] = p[5];
+ z[4] = p[2]; z[5] = p[3];
+ z[6] = p[0]; z[7] = p[1];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[5] -= top;
+ square_end_1 = true;
+ }
+
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[3] += bottom;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(LEFT,
+ z,
+ col,
+ box->border[LEFT].style,
+ left,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Right */
+ square_end_1 = (top == 0);
+ square_end_2 = (bottom == 0);
+ if (right != 0 &&
+ last &&
+ nscss_color_is_transparent(box->border[RIGHT].c) == false) {
+ col = nscss_color_to_ns(box->border[RIGHT].c);
+
+ z[0] = p[6]; z[1] = p[1];
+ z[2] = p[4]; z[3] = p[3];
+ z[4] = p[4]; z[5] = p[5];
+ z[6] = p[6]; z[7] = p[7];
+
+ if (nscss_color_is_transparent(box->border[TOP].c) == false &&
+ box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang top corner fully,
+ * if top border is opaque
+ */
+ z[3] -= top;
+ square_end_1 = true;
+ }
+
+ if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
+ box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
+ /* make border overhang bottom corner fully,
+ * if bottom border is opaque
+ */
+ z[5] += bottom;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(RIGHT,
+ z,
+ col,
+ box->border[RIGHT].style,
+ right,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Top */
+ square_end_1 = (left == 0);
+ square_end_2 = (right == 0);
+ if (top != 0 &&
+ nscss_color_is_transparent(box->border[TOP].c) == false) {
+ col = nscss_color_to_ns(box->border[TOP].c);
+
+ z[0] = p[2]; z[1] = p[3];
+ z[2] = p[0]; z[3] = p[1];
+ z[4] = p[6]; z[5] = p[1];
+ z[6] = p[4]; z[7] = p[3];
+
+ if (first &&
+ box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[2] += left;
+ square_end_1 = true;
+ }
+
+ if (last &&
+ box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[TOP].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[4] -= right;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(TOP,
+ z,
+ col,
+ box->border[TOP].style,
+ top,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ /* Bottom */
+ square_end_1 = (left == 0);
+ square_end_2 = (right == 0);
+ if (bottom != 0 &&
+ nscss_color_is_transparent(box->border[BOTTOM].c) == false) {
+ col = nscss_color_to_ns(box->border[BOTTOM].c);
+
+ z[0] = p[4]; z[1] = p[5];
+ z[2] = p[6]; z[3] = p[7];
+ z[4] = p[0]; z[5] = p[7];
+ z[6] = p[2]; z[7] = p[5];
+
+ if (first &&
+ box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[LEFT].c) {
+ /* don't bother overlapping left corner if
+ * it's the same colour anyway
+ */
+ z[4] += left;
+ square_end_1 = true;
+ }
+
+ if (last &&
+ box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
+ box->border[BOTTOM].c == box->border[RIGHT].c) {
+ /* don't bother overlapping right corner if
+ * it's the same colour anyway
+ */
+ z[2] -= right;
+ square_end_2 = true;
+ }
+
+ res = html_redraw_border_plot(BOTTOM,
+ z,
+ col,
+ box->border[BOTTOM].style,
+ bottom,
+ square_end_1 && square_end_2,
+ clip,
+ ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ return true;
+}
--
NetSurf Browser