diff options
author | Vincent Sanders <vince@kyllikki.org> | 2017-02-12 20:01:05 +0000 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2017-02-12 20:01:05 +0000 |
commit | 1666944c7e5c7a300ad0658b9654464ff2c11495 (patch) | |
tree | 8b40a9c13e28cc67135cb75ded1f3477390039cc /desktop | |
parent | 703fd10400f83bd136acf46162fe109f87d5e538 (diff) | |
parent | 513366a7a22dfeafc6a79814701ba62210ad5040 (diff) | |
download | netsurf-1666944c7e5c7a300ad0658b9654464ff2c11495.tar.gz netsurf-1666944c7e5c7a300ad0658b9654464ff2c11495.tar.bz2 |
Merge branch 'vince/plotctx'
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/browser.c | 37 | ||||
-rw-r--r-- | desktop/browser_history.c | 85 | ||||
-rw-r--r-- | desktop/knockout.c | 745 | ||||
-rw-r--r-- | desktop/knockout.h | 14 | ||||
-rw-r--r-- | desktop/scrollbar.c | 399 | ||||
-rw-r--r-- | desktop/textarea.c | 73 | ||||
-rw-r--r-- | desktop/treeview.c | 97 |
7 files changed, 881 insertions, 569 deletions
diff --git a/desktop/browser.c b/desktop/browser.c index d3648d76a..3a7ac0ecc 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,10 +234,11 @@ 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(); + knockout_plot_end(ctx); } return plot_ok; @@ -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 */ @@ -313,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/browser_history.c b/desktop/browser_history.c index d21c5bc25..10154b780 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/knockout.c b/desktop/knockout.c index bcfc272eb..96e7b1a45 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 c4f1245fc..f7ff04553 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/scrollbar.c b/desktop/scrollbar.c index 9a4d70fe4..3709af8b4 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 203c28e93..af1cd80be 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 4d8fbaaeb..75e5c93e0 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) - knockout_plot_end(); + if (ctx->plot->option_knockout) { + knockout_plot_end(ctx); + } } struct treeview_selection_walk_data { |