netsurf: branch master updated. release/3.6-252-g1666944
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/1666944c7e5c7a300ad06...
...commit http://git.netsurf-browser.org/netsurf.git/commit/1666944c7e5c7a300ad0658...
...tree http://git.netsurf-browser.org/netsurf.git/tree/1666944c7e5c7a300ad0658b9...
The branch, master has been updated
via 1666944c7e5c7a300ad0658b9654464ff2c11495 (commit)
via 513366a7a22dfeafc6a79814701ba62210ad5040 (commit)
via 4361bfeace6f3f184e871f5598138f3f36994e99 (commit)
via a3a7cbf06a1d841dd6dee415fb196040c453567a (commit)
via 320c0e1a75106a74280410ce23db8a308f44193b (commit)
via 386951ecfc220748b81c53f3c736f2fc08686b78 (commit)
via 0f43b2327063af238ab1eb5f94c3235f4c9347f6 (commit)
via 3ea137ca3d9b0f996493bb33289d9ab3fc2881bc (commit)
via 78d601eb76c796c038f42c2b9f10e4e591272271 (commit)
via 7d660561cc9562731429ca06904b5e5711e90e27 (commit)
via 18abdadac83789019ae1a36a1e1cad2e98601efa (commit)
via 30df27c3babe188cc553df77e84a36b4db84bd47 (commit)
via 3722ff8d867db506c68e5467bbcdb6012e384fc8 (commit)
via 98ccc9fe1836c59f7eff43f45ac2323798ee785a (commit)
from 703fd10400f83bd136acf46162fe109f87d5e538 (commit)
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=1666944c7e5c7a300ad...
commit 1666944c7e5c7a300ad0658b9654464ff2c11495
Merge: 703fd10 513366a
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Merge branch 'vince/plotctx'
-----------------------------------------------------------------------
Summary of changes:
content/content.c | 10 +-
content/handlers/image/bmp.c | 8 +-
content/handlers/image/image.c | 14 +-
content/handlers/image/nssprite.c | 27 +-
content/handlers/image/rsvg.c | 13 +-
content/handlers/image/svg.c | 51 +-
desktop/browser.c | 37 +-
desktop/browser_history.c | 85 +-
desktop/knockout.c | 745 +++++----
desktop/knockout.h | 14 +-
desktop/scrollbar.c | 399 +++--
desktop/textarea.c | 73 +-
desktop/treeview.c | 97 +-
frontends/amiga/dt_anim.c | 7 +-
frontends/amiga/dt_sound.c | 19 +-
frontends/amiga/icon.c | 13 +-
frontends/amiga/plotters.c | 852 ++++++----
frontends/amiga/plugin_hack.c | 23 +-
frontends/atari/gui.c | 8 +-
frontends/atari/plot/plot.c | 2270 ++++++++++++++------------
frontends/atari/plot/plot.h | 26 +-
frontends/atari/rootwin.c | 22 +-
frontends/atari/toolbar.c | 2 +-
frontends/atari/treeview.c | 6 +-
frontends/beos/plotters.cpp | 1126 +++++++------
frontends/framebuffer/fbtk/text.c | 28 +-
frontends/framebuffer/framebuffer.c | 606 ++++---
frontends/gtk/layout_pango.c | 6 +-
frontends/gtk/layout_pango.h | 2 +-
frontends/gtk/plotters.c | 409 +++--
frontends/gtk/print.c | 197 ++-
frontends/gtk/scaffolding.c | 2 +-
frontends/monkey/plot.c | 258 ++-
frontends/riscos/content-handlers/artworks.c | 2 +-
frontends/riscos/content-handlers/draw.c | 2 +-
frontends/riscos/content-handlers/sprite.c | 2 +-
frontends/riscos/gui/progress_bar.c | 15 +-
frontends/riscos/gui/status_bar.c | 25 +-
frontends/riscos/plotters.c | 784 +++++----
frontends/riscos/print.c | 242 +--
frontends/riscos/save_draw.c | 633 ++++---
frontends/riscos/save_draw.h | 7 +
frontends/windows/plot.c | 1176 +++++++------
include/netsurf/plotters.h | 292 +++-
render/Makefile | 3 +-
render/form.c | 62 +-
render/html_internal.h | 9 +
render/html_redraw.c | 1317 ++++-----------
render/html_redraw_border.c | 928 +++++++++++
render/textplain.c | 21 +-
50 files changed, 7802 insertions(+), 5173 deletions(-)
create mode 100644 render/html_redraw_border.c
diff --git a/content/content.c b/content/content.c
index 2eb035c..70df87e 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;
@@ -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/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..3a7ac0e 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 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/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/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..75e5c93 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 {
diff --git a/frontends/amiga/dt_anim.c b/frontends/amiga/dt_anim.c
index a486334..2f998d2 100644
--- a/frontends/amiga/dt_anim.c
+++ b/frontends/amiga/dt_anim.c
@@ -270,8 +270,11 @@ bool amiga_dt_anim_redraw(struct content *c,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- plugin->bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx, plugin->bitmap,
+ data->x, data->y,
+ data->width, data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
/**
diff --git a/frontends/amiga/dt_sound.c b/frontends/amiga/dt_sound.c
index 55fc60d..eda60ed 100644
--- a/frontends/amiga/dt_sound.c
+++ b/frontends/amiga/dt_sound.c
@@ -197,18 +197,25 @@ bool amiga_dt_sound_redraw(struct content *c,
.stroke_colour = 0x000000,
.stroke_width = 1,
};
+ struct rect rect;
LOG("amiga_dt_sound_redraw");
+ rect.x0 = data->x;
+ rect.y0 = data->y;
+ rect.x1 = data->x + data->width;
+ rect.y1 = data->y + data->height;
+
/* this should be some sort of play/stop control */
- ctx->plot->rectangle(data->x, data->y, data->x + data->width,
- data->y + data->height, &pstyle);
+ ctx->plot->rectangle(ctx, &pstyle, &rect);
- return ctx->plot->text(data->x, data->y+20,
- lwc_string_data(content__get_mime_type(c)),
- lwc_string_length(content__get_mime_type(c)),
- plot_style_font);
+ return (ctx->plot->text(ctx,
+ plot_style_font,
+ data->x,
+ data->y+20,
+ lwc_string_data(content__get_mime_type(c)),
+ lwc_string_length(content__get_mime_type(c))) == NSERROR_OK);
}
diff --git a/frontends/amiga/icon.c b/frontends/amiga/icon.c
index 3f597a1..a92b867 100644
--- a/frontends/amiga/icon.c
+++ b/frontends/amiga/icon.c
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Content for image/x-amiga-icon (icon.library implementation).
*
*/
@@ -273,8 +274,14 @@ bool amiga_icon_redraw(struct content *c,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- icon_c->bitmap, data->background_colour, flags);
+ return (ctx->plot->bitmap(ctx,
+ icon_c->bitmap,
+ data->x,
+ data->y,
+ data->width,
+ data->height,
+ data->background_colour,
+ flags) == NSERROR_OK);
}
diff --git a/frontends/amiga/plotters.c b/frontends/amiga/plotters.c
index 6bae634..e871715 100644
--- a/frontends/amiga/plotters.c
+++ b/frontends/amiga/plotters.c
@@ -51,8 +51,15 @@
#include "amiga/rtg.h"
#include "amiga/utf8.h"
+/* set AMI_PLOTTER_DEBUG to 0 for no debugging, 1 for debugging */
//#define AMI_PLOTTER_DEBUG 1
+#ifdef AMI_PLOTTER_DEBUG
+#define PLOT_LOG(x...) LOG(x)
+#else
+#define PLOT_LOG(x...) ((void) 0)
+#endif
+
HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage *);
struct bfbitmap {
@@ -336,171 +343,6 @@ void ami_plot_clear_bbox(struct RastPort *rp, struct IBox *bbox)
}
-static bool ami_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_rectangle()");
- #endif
-
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- ami_plot_setapen(glob->rp, style->fill_colour);
- RectFill(glob->rp, x0, y0, x1-1, y1-1);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- glob->rp->PenWidth = style->stroke_width;
- glob->rp->PenHeight = style->stroke_width;
-
- switch (style->stroke_type) {
- case PLOT_OP_TYPE_SOLID: /**< Solid colour */
- default:
- glob->rp->LinePtrn = PATT_LINE;
- break;
-
- case PLOT_OP_TYPE_DOT: /**< Dotted plot */
- glob->rp->LinePtrn = PATT_DOT;
- break;
-
- case PLOT_OP_TYPE_DASH: /**< dashed plot */
- glob->rp->LinePtrn = PATT_DASH;
- break;
- }
-
- ami_plot_setapen(glob->rp, style->stroke_colour);
- Move(glob->rp, x0,y0);
- Draw(glob->rp, x1, y0);
- Draw(glob->rp, x1, y1);
- Draw(glob->rp, x0, y1);
- Draw(glob->rp, x0, y0);
-
- glob->rp->PenWidth = 1;
- glob->rp->PenHeight = 1;
- glob->rp->LinePtrn = PATT_LINE;
- }
-
- return true;
-}
-
-static bool ami_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_line()");
- #endif
-
- glob->rp->PenWidth = style->stroke_width;
- glob->rp->PenHeight = style->stroke_width;
-
- switch (style->stroke_type) {
- case PLOT_OP_TYPE_SOLID: /**< Solid colour */
- default:
- glob->rp->LinePtrn = PATT_LINE;
- break;
-
- case PLOT_OP_TYPE_DOT: /**< Doted plot */
- glob->rp->LinePtrn = PATT_DOT;
- break;
-
- case PLOT_OP_TYPE_DASH: /**< dashed plot */
- glob->rp->LinePtrn = PATT_DASH;
- break;
- }
-
- ami_plot_setapen(glob->rp, style->stroke_colour);
- Move(glob->rp,x0,y0);
- Draw(glob->rp,x1,y1);
-
- glob->rp->PenWidth = 1;
- glob->rp->PenHeight = 1;
- glob->rp->LinePtrn = PATT_LINE;
-
- return true;
-}
-
-static bool ami_polygon(const int *p, unsigned int n, const plot_style_t *style)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_polygon()");
- #endif
-
- ami_plot_setapen(glob->rp, style->fill_colour);
-
- if(AreaMove(glob->rp,p[0],p[1]) == -1)
- LOG("AreaMove: vector list full");
-
- for(uint32 k = 1; k < n; k++) {
- if(AreaDraw(glob->rp,p[k*2],p[(k*2)+1]) == -1)
- LOG("AreaDraw: vector list full");
- }
-
- if(AreaEnd(glob->rp) == -1)
- LOG("AreaEnd: error");
-
- return true;
-}
-
-
-static bool ami_clip(const struct rect *clip)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_clip()");
- #endif
-
- struct Region *reg = NULL;
-
- if(glob->rp->Layer)
- {
- reg = NewRegion();
-
- glob->rect.MinX = clip->x0;
- glob->rect.MinY = clip->y0;
- glob->rect.MaxX = clip->x1-1;
- glob->rect.MaxY = clip->y1-1;
-
- OrRectRegion(reg,&glob->rect);
-
- reg = InstallClipRegion(glob->rp->Layer,reg);
-
- if(reg) DisposeRegion(reg);
- }
-
- return true;
-}
-
-static bool ami_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_text()");
- #endif
-
- if(__builtin_expect(ami_nsfont == NULL, 0)) return false;
-
- ami_plot_setapen(glob->rp, fstyle->foreground);
- ami_nsfont->text(glob->rp, text, length, fstyle, x, y, nsoption_bool(font_antialiasing));
-
- return true;
-}
-
-static bool ami_disc(int x, int y, int radius, const plot_style_t *style)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_disc()");
- #endif
-
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- ami_plot_setapen(glob->rp, style->fill_colour);
- AreaCircle(glob->rp,x,y,radius);
- AreaEnd(glob->rp);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- ami_plot_setapen(glob->rp, style->stroke_colour);
- DrawEllipse(glob->rp,x,y,radius,radius);
- }
-
- return true;
-}
-
static void ami_arc_gfxlib(int x, int y, int radius, int angle1, int angle2)
{
double angle1_r = (double)(angle1) * (M_PI / 180.0);
@@ -526,46 +368,37 @@ static void ami_arc_gfxlib(int x, int y, int radius, int angle1, int angle2)
}
}
-static bool ami_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_arc()");
- #endif
-
- if (angle2 < angle1) angle2 += 360;
-
- ami_plot_setapen(glob->rp, style->fill_colour);
- ami_arc_gfxlib(x, y, radius, angle1, angle2);
-
- return true;
-}
-
-static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitmap)
+/**
+ */
+static nserror
+ami_bitmap(int x, int y, int width, int height, struct bitmap *bitmap)
{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_bitmap()");
- #endif
+ PLOT_LOG("[ami_plotter] Entered ami_bitmap()");
struct BitMap *tbm;
- if(!width || !height) return true;
+ if (!width || !height) {
+ return NSERROR_OK;
+ }
- if(((x + width) < glob->rect.MinX) ||
- ((y + height) < glob->rect.MinY) ||
- (x > glob->rect.MaxX) ||
- (y > glob->rect.MaxY))
- return true;
+ if (((x + width) < glob->rect.MinX) ||
+ ((y + height) < glob->rect.MinY) ||
+ (x > glob->rect.MaxX) ||
+ (y > glob->rect.MaxY)) {
+ return NSERROR_OK;
+ }
tbm = ami_bitmap_get_native(bitmap, width, height, glob->rp->BitMap);
- if(!tbm) return true;
+ if (!tbm) {
+ return NSERROR_OK;
+ }
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] ami_bitmap() got native bitmap");
- #endif
+ PLOT_LOG("[ami_plotter] ami_bitmap() got native bitmap");
#ifdef __amigaos4__
- if(__builtin_expect((GfxBase->LibNode.lib_Version >= 53) && (glob->palette_mapped == false) &&
- (nsoption_bool(direct_render) == false), 1)) {
+ if (__builtin_expect((GfxBase->LibNode.lib_Version >= 53) &&
+ (glob->palette_mapped == false) &&
+ (nsoption_bool(direct_render) == false), 1)) {
uint32 comptype = COMPOSITE_Src_Over_Dest;
uint32 compflags = COMPFLAG_IgnoreDestAlpha;
if(amiga_bitmap_get_opaque(bitmap)) {
@@ -585,19 +418,18 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
COMPTAG_OffsetY,y,
COMPTAG_FriendBitMap, scrn->RastPort.BitMap,
TAG_DONE);
- }
- else
+ } else
#endif
{
ULONG tag, tag_data, minterm = 0xc0;
- if(glob->palette_mapped == false) {
+ if (glob->palette_mapped == false) {
tag = BLITA_UseSrcAlpha;
tag_data = !amiga_bitmap_get_opaque(bitmap);
minterm = 0xc0;
} else {
tag = BLITA_MaskPlane;
- if((tag_data = (ULONG)ami_bitmap_get_mask(bitmap, width, height, tbm)))
+ if ((tag_data = (ULONG)ami_bitmap_get_mask(bitmap, width, height, tbm)))
minterm = MINTERM_SRCMASK;
}
#ifdef __amigaos4__
@@ -613,7 +445,7 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
tag, tag_data,
TAG_DONE);
#else
- if(tag_data) {
+ if (tag_data) {
BltMaskBitMapRastPort(tbm, 0, 0, glob->rp, x, y, width, height, minterm, tag_data);
} else {
BltBitMapRastPort(tbm, 0, 0, glob->rp, x, y, width, height, 0xc0);
@@ -621,118 +453,13 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
#endif
}
- if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
+ if ((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
ami_rtg_freebitmap(tbm);
}
- return true;
+ return NSERROR_OK;
}
-static bool ami_bitmap_tile(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
-{
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_bitmap_tile()");
- #endif
-
- int xf,yf,xm,ym,oy,ox;
- struct BitMap *tbm = NULL;
- struct Hook *bfh = NULL;
- struct bfbitmap bfbm;
- bool repeat_x = (flags & BITMAPF_REPEAT_X);
- bool repeat_y = (flags & BITMAPF_REPEAT_Y);
-
- if((width == 0) || (height == 0)) return true;
-
- if(!(repeat_x || repeat_y))
- return ami_bitmap(x, y, width, height, bitmap);
-
- /* If it is a one pixel transparent image, we are wasting our time */
- if((amiga_bitmap_get_opaque(bitmap) == false) &&
- (bitmap_get_width(bitmap) == 1) && (bitmap_get_height(bitmap) == 1))
- return true;
-
- tbm = ami_bitmap_get_native(bitmap,width,height,glob->rp->BitMap);
- if(!tbm) return true;
-
- ox = x;
- oy = y;
-
- /* get left most tile position */
- for (; ox > 0; ox -= width)
- ;
-
- /* get top most tile position */
- for (; oy > 0; oy -= height)
- ;
-
- if(ox<0) ox = -ox;
- if(oy<0) oy = -oy;
-
- if(repeat_x)
- {
- xf = glob->rect.MaxX;
- xm = glob->rect.MinX;
- }
- else
- {
- xf = x + width;
- xm = x;
- }
-
- if(repeat_y)
- {
- yf = glob->rect.MaxY;
- ym = glob->rect.MinY;
- }
- else
- {
- yf = y + height;
- ym = y;
- }
-#ifdef __amigaos4__
- if(amiga_bitmap_get_opaque(bitmap))
- {
- bfh = CreateBackFillHook(BFHA_BitMap,tbm,
- BFHA_Width,width,
- BFHA_Height,height,
- BFHA_OffsetX,ox,
- BFHA_OffsetY,oy,
- TAG_DONE);
- }
- else
-#endif
- {
- bfbm.bm = tbm;
- bfbm.width = width;
- bfbm.height = height;
- bfbm.offsetx = ox;
- bfbm.offsety = oy;
- bfbm.mask = ami_bitmap_get_mask(bitmap, width, height, tbm);
- bfh = calloc(1, sizeof(struct Hook));
- bfh->h_Entry = (HOOKFUNC)ami_bitmap_tile_hook;
- bfh->h_SubEntry = 0;
- bfh->h_Data = &bfbm;
- }
-
- InstallLayerHook(glob->rp->Layer,bfh);
- EraseRect(glob->rp,xm,ym,xf,yf);
- InstallLayerHook(glob->rp->Layer,LAYERS_NOBACKFILL);
-
-#ifdef __amigaos4__
- if(amiga_bitmap_get_opaque(bitmap)) DeleteBackFillHook(bfh);
- else
-#endif
- free(bfh);
-
- if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
- /**\todo is this logic logical? */
- ami_rtg_freebitmap(tbm);
- }
-
- return true;
-}
HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage *)
{
@@ -757,8 +484,7 @@ HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage
COMPTAG_OffsetY, yf,
COMPTAG_FriendBitMap, scrn->RastPort.BitMap,
TAG_DONE);
- }
- else
+ } else
#endif
{
ULONG tag, tag_data, minterm = 0xc0;
@@ -805,42 +531,323 @@ static void ami_bezier(struct bez_point *restrict a, struct bez_point *restrict
p->y = pow((1 - t), 3) * a->y + 3 * t * pow((1 -t), 2) * b->y + 3 * (1-t) * pow(t, 2)* c->y + pow (t, 3)* d->y;
}
-static bool ami_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
+
+bool ami_plot_screen_is_palettemapped(void)
+{
+ return glob->palette_mapped;
+}
+
+
+/**
+ * \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
+ami_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ struct Region *reg = NULL;
+
+ PLOT_LOG("[ami_plotter] Entered ami_clip()");
+
+ if (glob->rp->Layer) {
+ reg = NewRegion();
+
+ glob->rect.MinX = clip->x0;
+ glob->rect.MinY = clip->y0;
+ glob->rect.MaxX = clip->x1-1;
+ glob->rect.MaxY = clip->y1-1;
+
+ OrRectRegion(reg,&glob->rect);
+
+ reg = InstallClipRegion(glob->rp->Layer,reg);
+
+ if(reg) {
+ DisposeRegion(reg);
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_arc()");
+
+ if (angle2 < angle1) {
+ angle2 += 360;
+ }
+
+ ami_plot_setapen(glob->rp, style->fill_colour);
+ ami_arc_gfxlib(x, y, radius, angle1, angle2);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_disc()");
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ ami_plot_setapen(glob->rp, style->fill_colour);
+ AreaCircle(glob->rp,x,y,radius);
+ AreaEnd(glob->rp);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ ami_plot_setapen(glob->rp, style->stroke_colour);
+ DrawEllipse(glob->rp,x,y,radius,radius);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_line()");
+
+ glob->rp->PenWidth = style->stroke_width;
+ glob->rp->PenHeight = style->stroke_width;
+
+ switch (style->stroke_type) {
+ case PLOT_OP_TYPE_SOLID: /**< Solid colour */
+ default:
+ glob->rp->LinePtrn = PATT_LINE;
+ break;
+
+ case PLOT_OP_TYPE_DOT: /**< Doted plot */
+ glob->rp->LinePtrn = PATT_DOT;
+ break;
+
+ case PLOT_OP_TYPE_DASH: /**< dashed plot */
+ glob->rp->LinePtrn = PATT_DASH;
+ break;
+ }
+
+ ami_plot_setapen(glob->rp, style->stroke_colour);
+ Move(glob->rp, line->x0, line->y0);
+ Draw(glob->rp, line->x1, line->y1);
+
+ glob->rp->PenWidth = 1;
+ glob->rp->PenHeight = 1;
+ glob->rp->LinePtrn = PATT_LINE;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_rectangle()");
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ ami_plot_setapen(glob->rp, style->fill_colour);
+ RectFill(glob->rp, rect->x0, rect->y0, rect->x1- 1 , rect->y1 - 1);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ glob->rp->PenWidth = style->stroke_width;
+ glob->rp->PenHeight = style->stroke_width;
+
+ switch (style->stroke_type) {
+ case PLOT_OP_TYPE_SOLID: /**< Solid colour */
+ default:
+ glob->rp->LinePtrn = PATT_LINE;
+ break;
+
+ case PLOT_OP_TYPE_DOT: /**< Dotted plot */
+ glob->rp->LinePtrn = PATT_DOT;
+ break;
+
+ case PLOT_OP_TYPE_DASH: /**< dashed plot */
+ glob->rp->LinePtrn = PATT_DASH;
+ break;
+ }
+
+ ami_plot_setapen(glob->rp, style->stroke_colour);
+ Move(glob->rp, rect->x0, rect->y0);
+ Draw(glob->rp, rect->x1, rect->y0);
+ Draw(glob->rp, rect->x1, rect->y1);
+ Draw(glob->rp, rect->x0, rect->y1);
+ Draw(glob->rp, rect->x0, rect->y0);
+
+ glob->rp->PenWidth = 1;
+ glob->rp->PenHeight = 1;
+ glob->rp->LinePtrn = PATT_LINE;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_polygon()");
+
+ ami_plot_setapen(glob->rp, style->fill_colour);
+
+ if (AreaMove(glob->rp,p[0],p[1]) == -1) {
+ LOG("AreaMove: vector list full");
+ }
+
+ for (uint32 k = 1; k < n; k++) {
+ if (AreaDraw(glob->rp,p[k*2],p[(k*2)+1]) == -1) {
+ LOG("AreaDraw: vector list full");
+ }
+ }
+
+ if (AreaEnd(glob->rp) == -1) {
+ LOG("AreaEnd: error");
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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
+ami_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;
struct bez_point start_p = {0, 0}, cur_p = {0, 0}, p_a, p_b, p_c, p_r;
- #ifdef AMI_PLOTTER_DEBUG
- LOG("[ami_plotter] Entered ami_path()");
- #endif
+ PLOT_LOG("[ami_plotter] Entered ami_path()");
- if (n == 0)
- return true;
+ if (n == 0) {
+ return NSERROR_OK;
+ }
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("Path does not start with move");
- return false;
+ return NSERROR_INVALID;
}
- if (fill != NS_TRANSPARENT) {
- ami_plot_setapen(glob->rp, fill);
- if (c != NS_TRANSPARENT)
- ami_plot_setopen(glob->rp, c);
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ ami_plot_setapen(glob->rp, pstyle->fill_colour);
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ ami_plot_setopen(glob->rp, pstyle->stroke_colour);
+ }
} else {
- if (c != NS_TRANSPARENT) {
- ami_plot_setapen(glob->rp, c);
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ ami_plot_setapen(glob->rp, pstyle->stroke_colour);
} else {
- return true; /* wholly transparent */
+ return NSERROR_OK; /* wholly transparent */
}
}
/* Construct path */
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
- if (fill != NS_TRANSPARENT) {
- if(AreaMove(glob->rp, p[i+1], p[i+2]) == -1)
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ if (AreaMove(glob->rp, p[i+1], p[i+2]) == -1) {
LOG("AreaMove: vector list full");
+ }
} else {
Move(glob->rp, p[i+1], p[i+2]);
}
@@ -851,17 +858,19 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
cur_p.y = start_p.y;
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
- if (fill != NS_TRANSPARENT) {
- if(AreaEnd(glob->rp) == -1)
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ if (AreaEnd(glob->rp) == -1) {
LOG("AreaEnd: error");
+ }
} else {
Draw(glob->rp, start_p.x, start_p.y);
}
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
- if (fill != NS_TRANSPARENT) {
- if(AreaDraw(glob->rp, p[i+1], p[i+2]) == -1)
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ if (AreaDraw(glob->rp, p[i+1], p[i+2]) == -1) {
LOG("AreaDraw: vector list full");
+ }
} else {
Draw(glob->rp, p[i+1], p[i+2]);
}
@@ -876,11 +885,12 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
p_c.x = p[i+5];
p_c.y = p[i+6];
- for(double t = 0.0; t <= 1.0; t += 0.1) {
+ for (double t = 0.0; t <= 1.0; t += 0.1) {
ami_bezier(&cur_p, &p_a, &p_b, &p_c, t, &p_r);
- if (fill != NS_TRANSPARENT) {
- if(AreaDraw(glob->rp, p_r.x, p_r.y) == -1)
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ if (AreaDraw(glob->rp, p_r.x, p_r.y) == -1) {
LOG("AreaDraw: vector list full");
+ }
} else {
Draw(glob->rp, p_r.x, p_r.y);
}
@@ -891,25 +901,187 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
} else {
LOG("bad path command %f", p[i]);
/* End path for safety if using Area commands */
- if (fill != NS_TRANSPARENT) {
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
AreaEnd(glob->rp);
BNDRYOFF(glob->rp);
}
- return false;
+ return NSERROR_INVALID;
}
}
- if (fill != NS_TRANSPARENT)
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
BNDRYOFF(glob->rp);
+ }
- return true;
+ return NSERROR_OK;
}
-bool ami_plot_screen_is_palettemapped(void)
+
+/**
+ * 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ami_bitmap_tile(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
- return glob->palette_mapped;
+ int xf,yf,xm,ym,oy,ox;
+ struct BitMap *tbm = NULL;
+ struct Hook *bfh = NULL;
+ struct bfbitmap bfbm;
+ bool repeat_x = (flags & BITMAPF_REPEAT_X);
+ bool repeat_y = (flags & BITMAPF_REPEAT_Y);
+
+ PLOT_LOG("[ami_plotter] Entered ami_bitmap_tile()");
+
+ if ((width == 0) || (height == 0)) {
+ return NSERROR_OK;
+ }
+
+ if (!(repeat_x || repeat_y)) {
+ return ami_bitmap(x, y, width, height, bitmap);
+ }
+
+ /* If it is a one pixel transparent image, we are wasting our time */
+ if ((amiga_bitmap_get_opaque(bitmap) == false) &&
+ (bitmap_get_width(bitmap) == 1) &&
+ (bitmap_get_height(bitmap) == 1)) {
+ return NSERROR_OK;
+ }
+
+ tbm = ami_bitmap_get_native(bitmap,width,height,glob->rp->BitMap);
+ if (!tbm) {
+ return NSERROR_OK;
+ }
+
+ ox = x;
+ oy = y;
+
+ /* get left most tile position */
+ for (; ox > 0; ox -= width)
+
+ /* get top most tile position */
+ for (; oy > 0; oy -= height);
+
+ if (ox < 0) {
+ ox = -ox;
+ }
+ if (oy < 0) {
+ oy = -oy;
+ }
+ if (repeat_x) {
+ xf = glob->rect.MaxX;
+ xm = glob->rect.MinX;
+ } else {
+ xf = x + width;
+ xm = x;
+ }
+
+ if (repeat_y) {
+ yf = glob->rect.MaxY;
+ ym = glob->rect.MinY;
+ } else {
+ yf = y + height;
+ ym = y;
+ }
+#ifdef __amigaos4__
+ if(amiga_bitmap_get_opaque(bitmap)) {
+ bfh = CreateBackFillHook(BFHA_BitMap,tbm,
+ BFHA_Width,width,
+ BFHA_Height,height,
+ BFHA_OffsetX,ox,
+ BFHA_OffsetY,oy,
+ TAG_DONE);
+ } else
+#endif
+ {
+ bfbm.bm = tbm;
+ bfbm.width = width;
+ bfbm.height = height;
+ bfbm.offsetx = ox;
+ bfbm.offsety = oy;
+ bfbm.mask = ami_bitmap_get_mask(bitmap, width, height, tbm);
+ bfh = calloc(1, sizeof(struct Hook));
+ bfh->h_Entry = (HOOKFUNC)ami_bitmap_tile_hook;
+ bfh->h_SubEntry = 0;
+ bfh->h_Data = &bfbm;
+ }
+
+ InstallLayerHook(glob->rp->Layer,bfh);
+ EraseRect(glob->rp,xm,ym,xf,yf);
+ InstallLayerHook(glob->rp->Layer,LAYERS_NOBACKFILL);
+
+#ifdef __amigaos4__
+ if (amiga_bitmap_get_opaque(bitmap)) {
+ DeleteBackFillHook(bfh);
+ } else
+#endif
+ free(bfh);
+
+ if ((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
+ /**\todo is this logic logical? */
+ ami_rtg_freebitmap(tbm);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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
+ami_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ PLOT_LOG("[ami_plotter] Entered ami_text()");
+
+ if (__builtin_expect(ami_nsfont == NULL, 0)) {
+ return NSERROR_OK;
+ }
+ ami_plot_setapen(glob->rp, fstyle->foreground);
+ ami_nsfont->text(glob->rp, text, length, fstyle, x, y, nsoption_bool(font_antialiasing));
+
+ return NSERROR_OK;
}
-struct plotter_table plot;
+
const struct plotter_table amiplot = {
.rectangle = ami_rectangle,
.line = ami_line,
diff --git a/frontends/amiga/plugin_hack.c b/frontends/amiga/plugin_hack.c
index 7fe78b9..2327f91 100644
--- a/frontends/amiga/plugin_hack.c
+++ b/frontends/amiga/plugin_hack.c
@@ -152,16 +152,27 @@ bool amiga_plugin_hack_redraw(struct content *c,
.stroke_colour = 0x000000,
.stroke_width = 1,
};
+ struct rect rect;
+ nserror res;
LOG("amiga_plugin_hack_redraw");
- ctx->plot->rectangle(data->x, data->y, data->x + data->width,
- data->y + data->height, &pstyle);
+ rect.x0 = data->x;
+ rect.y0 = data->y;
+ rect.x1 = data->x + data->width;
+ rect.y1 = data->y + data->height;
- return ctx->plot->text(data->x, data->y+20,
- lwc_string_data(content__get_mime_type(c)),
- lwc_string_length(content__get_mime_type(c)),
- plot_style_font);
+ ctx->plot->rectangle(ctx, &pstyle, &rect);
+
+ res = ctx->plot->text(ctx,
+ plot_style_font,
+ data->x, data->y+20,
+ lwc_string_data(content__get_mime_type(c)),
+ lwc_string_length(content__get_mime_type(c)));
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ return true;
}
/**
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c
index d4a6915..1287b47 100644
--- a/frontends/atari/gui.c
+++ b/frontends/atari/gui.c
@@ -39,6 +39,7 @@
#include "netsurf/content.h"
#include "netsurf/cookie_db.h"
#include "netsurf/url_db.h"
+#include "netsurf/plotters.h"
#include "content/backing_store.h"
#include "atari/gemtk/gemtk.h"
@@ -1019,7 +1020,12 @@ static void gui_init(int argc, char** argv)
nkc_init();
LOG("Initializing plotters...");
- plot_init(nsoption_charp(atari_font_driver));
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &atari_plotters
+ };
+ plot_init(&ctx, nsoption_charp(atari_font_driver));
aes_event_in.emi_m1leave = MO_LEAVE;
aes_event_in.emi_m1.g_w = 1;
diff --git a/frontends/atari/plot/plot.c b/frontends/atari/plot/plot.c
index 0a0d7a4..0917428 100644
--- a/frontends/atari/plot/plot.c
+++ b/frontends/atari/plot/plot.c
@@ -45,38 +45,31 @@
void vq_scrninfo(VdiHdl handle, short *work_out);
struct s_view {
- short x; /* drawing (screen) offset x */
- short y; /* drawing (screen) offset y */
- short w; /* width of buffer, not in sync with vis_w */
- short h; /* height of buffer, not in sync with vis_w */
- short vis_x; /* visible rectangle of the screen buffer */
- short vis_y; /* coords are relative to plot location */
- short vis_w; /* clipped to screen dimensions */
- short vis_h; /* visible width */
- struct rect abs_clipping; /* The toplevel clipping rectangle */
- struct rect clipping; /* actual clipping rectangle */
+ short x; /**< drawing (screen) offset x */
+ short y; /**< drawing (screen) offset y */
+ short w; /**< width of buffer, not in sync with vis_w */
+ short h; /**< height of buffer, not in sync with vis_w */
+ short vis_x; /**< visible rectangle of the screen buffer */
+ short vis_y; /**< coords are relative to plot location */
+ short vis_w; /**< clipped to screen dimensions */
+ short vis_h; /**< visible width */
+ struct rect abs_clipping; /**< The toplevel clipping rectangle */
+ struct rect clipping; /**< actual clipping rectangle */
float scale;
};
-/*
- * Capture the screen at x,y location
- * param self instance
- * param x absolute screen coords
- * param y absolute screen coords
- * param w width
- * param h height
- *
- * This creates an snapshot in RGBA format (NetSurf's native format)
+/**
+ * Garbage collection of the snapshot routine
*
+ * this should be called after you are done with the data returned by
+ * snapshot_create don't access the screenshot after you called this
+ * function
*/
-static struct bitmap * snapshot_create(int x, int y, int w, int h);
-
-/* Garbage collection of the snapshot routine */
-/* this should be called after you are done with the data returned by snapshot_create */
-/* don't access the screenshot after you called this function */
static void snapshot_suspend(void);
-/* destroy memory used by screenshot */
+/**
+ * destroy memory used by screenshot
+ */
static void snapshot_destroy(void);
#ifdef WITH_8BPP_SUPPORT
@@ -86,42 +79,78 @@ static char rgb_lookup[256][4];
short web_std_colors[6] = {0, 51, 102, 153, 204, 255};
unsigned short vdi_web_pal[216][3] = {
- {0x000,0x000,0x000}, {0x0c8,0x000,0x000}, {0x190,0x000,0x000}, {0x258,0x000,0x000}, {0x320,0x000,0x000}, {0x3e8,0x000,0x000},
- {0x000,0x0c8,0x000}, {0x0c8,0x0c8,0x000}, {0x190,0x0c8,0x000}, {0x258,0x0c8,0x000}, {0x320,0x0c8,0x000}, {0x3e8,0x0c8,0x000},
- {0x000,0x190,0x000}, {0x0c8,0x190,0x000}, {0x190,0x190,0x000}, {0x258,0x190,0x000}, {0x320,0x190,0x000}, {0x3e8,0x190,0x000},
- {0x000,0x258,0x000}, {0x0c8,0x258,0x000}, {0x190,0x258,0x000}, {0x258,0x258,0x000}, {0x320,0x258,0x000}, {0x3e8,0x258,0x000},
- {0x000,0x320,0x000}, {0x0c8,0x320,0x000}, {0x190,0x320,0x000}, {0x258,0x320,0x000}, {0x320,0x320,0x000}, {0x3e8,0x320,0x000},
- {0x000,0x3e8,0x000}, {0x0c8,0x3e8,0x000}, {0x190,0x3e8,0x000}, {0x258,0x3e8,0x000}, {0x320,0x3e8,0x000}, {0x3e8,0x3e8,0x000},
- {0x000,0x000,0x0c8}, {0x0c8,0x000,0x0c8}, {0x190,0x000,0x0c8}, {0x258,0x000,0x0c8}, {0x320,0x000,0x0c8}, {0x3e8,0x000,0x0c8},
- {0x000,0x0c8,0x0c8}, {0x0c8,0x0c8,0x0c8}, {0x190,0x0c8,0x0c8}, {0x258,0x0c8,0x0c8}, {0x320,0x0c8,0x0c8}, {0x3e8,0x0c8,0x0c8},
- {0x000,0x190,0x0c8}, {0x0c8,0x190,0x0c8}, {0x190,0x190,0x0c8}, {0x258,0x190,0x0c8}, {0x320,0x190,0x0c8}, {0x3e8,0x190,0x0c8},
- {0x000,0x258,0x0c8}, {0x0c8,0x258,0x0c8}, {0x190,0x258,0x0c8}, {0x258,0x258,0x0c8}, {0x320,0x258,0x0c8}, {0x3e8,0x258,0x0c8},
- {0x000,0x320,0x0c8}, {0x0c8,0x320,0x0c8}, {0x190,0x320,0x0c8}, {0x258,0x320,0x0c8}, {0x320,0x320,0x0c8}, {0x3e8,0x320,0x0c8},
- {0x000,0x3e8,0x0c8}, {0x0c8,0x3e8,0x0c8}, {0x190,0x3e8,0x0c8}, {0x258,0x3e8,0x0c8}, {0x320,0x3e8,0x0c8}, {0x3e8,0x3e8,0x0c8},
- {0x000,0x000,0x190}, {0x0c8,0x000,0x190}, {0x190,0x000,0x190}, {0x258,0x000,0x190}, {0x320,0x000,0x190}, {0x3e8,0x000,0x190},
- {0x000,0x0c8,0x190}, {0x0c8,0x0c8,0x190}, {0x190,0x0c8,0x190}, {0x258,0x0c8,0x190}, {0x320,0x0c8,0x190}, {0x3e8,0x0c8,0x190},
- {0x000,0x190,0x190}, {0x0c8,0x190,0x190}, {0x190,0x190,0x190}, {0x258,0x190,0x190}, {0x320,0x190,0x190}, {0x3e8,0x190,0x190},
- {0x000,0x258,0x190}, {0x0c8,0x258,0x190}, {0x190,0x258,0x190}, {0x258,0x258,0x190}, {0x320,0x258,0x190}, {0x3e8,0x258,0x190},
- {0x000,0x320,0x190}, {0x0c8,0x320,0x190}, {0x190,0x320,0x190}, {0x258,0x320,0x190}, {0x320,0x320,0x190}, {0x3e8,0x320,0x190},
- {0x000,0x3e8,0x190}, {0x0c8,0x3e8,0x190}, {0x190,0x3e8,0x190}, {0x258,0x3e8,0x190}, {0x320,0x3e8,0x190}, {0x3e8,0x3e8,0x190},
- {0x000,0x000,0x258}, {0x0c8,0x000,0x258}, {0x190,0x000,0x258}, {0x258,0x000,0x258}, {0x320,0x000,0x258}, {0x3e8,0x000,0x258},
- {0x000,0x0c8,0x258}, {0x0c8,0x0c8,0x258}, {0x190,0x0c8,0x258}, {0x258,0x0c8,0x258}, {0x320,0x0c8,0x258}, {0x3e8,0x0c8,0x258},
- {0x000,0x190,0x258}, {0x0c8,0x190,0x258}, {0x190,0x190,0x258}, {0x258,0x190,0x258}, {0x320,0x190,0x258}, {0x3e8,0x190,0x258},
- {0x000,0x258,0x258}, {0x0c8,0x258,0x258}, {0x190,0x258,0x258}, {0x258,0x258,0x258}, {0x320,0x258,0x258}, {0x3e8,0x258,0x258},
- {0x000,0x320,0x258}, {0x0c8,0x320,0x258}, {0x190,0x320,0x258}, {0x258,0x320,0x258}, {0x320,0x320,0x258}, {0x3e8,0x320,0x258},
- {0x000,0x3e8,0x258}, {0x0c8,0x3e8,0x258}, {0x190,0x3e8,0x258}, {0x258,0x3e8,0x258}, {0x320,0x3e8,0x258}, {0x3e8,0x3e8,0x258},
- {0x000,0x000,0x320}, {0x0c8,0x000,0x320}, {0x190,0x000,0x320}, {0x258,0x000,0x320}, {0x320,0x000,0x320}, {0x3e8,0x000,0x320},
- {0x000,0x0c8,0x320}, {0x0c8,0x0c8,0x320}, {0x190,0x0c8,0x320}, {0x258,0x0c8,0x320}, {0x320,0x0c8,0x320}, {0x3e8,0x0c8,0x320},
- {0x000,0x190,0x320}, {0x0c8,0x190,0x320}, {0x190,0x190,0x320}, {0x258,0x190,0x320}, {0x320,0x190,0x320}, {0x3e8,0x190,0x320},
- {0x000,0x258,0x320}, {0x0c8,0x258,0x320}, {0x190,0x258,0x320}, {0x258,0x258,0x320}, {0x320,0x258,0x320}, {0x3e8,0x258,0x320},
- {0x000,0x320,0x320}, {0x0c8,0x320,0x320}, {0x190,0x320,0x320}, {0x258,0x320,0x320}, {0x320,0x320,0x320}, {0x3e8,0x320,0x320},
- {0x000,0x3e8,0x320}, {0x0c8,0x3e8,0x320}, {0x190,0x3e8,0x320}, {0x258,0x3e8,0x320}, {0x320,0x3e8,0x320}, {0x3e8,0x3e8,0x320},
- {0x000,0x000,0x3e8}, {0x0c8,0x000,0x3e8}, {0x190,0x000,0x3e8}, {0x258,0x000,0x3e8}, {0x320,0x000,0x3e8}, {0x3e8,0x000,0x3e8},
- {0x000,0x0c8,0x3e8}, {0x0c8,0x0c8,0x3e8}, {0x190,0x0c8,0x3e8}, {0x258,0x0c8,0x3e8}, {0x320,0x0c8,0x3e8}, {0x3e8,0x0c8,0x3e8},
- {0x000,0x190,0x3e8}, {0x0c8,0x190,0x3e8}, {0x190,0x190,0x3e8}, {0x258,0x190,0x3e8}, {0x320,0x190,0x3e8}, {0x3e8,0x190,0x3e8},
- {0x000,0x258,0x3e8}, {0x0c8,0x258,0x3e8}, {0x190,0x258,0x3e8}, {0x258,0x258,0x3e8}, {0x320,0x258,0x3e8}, {0x3e8,0x258,0x3e8},
- {0x000,0x320,0x3e8}, {0x0c8,0x320,0x3e8}, {0x190,0x320,0x3e8}, {0x258,0x320,0x3e8}, {0x320,0x320,0x3e8}, {0x3e8,0x320,0x3e8},
- {0x000,0x3e8,0x3e8}, {0x0c8,0x3e8,0x3e8}, {0x190,0x3e8,0x3e8}, {0x258,0x3e8,0x3e8}, {0x320,0x3e8,0x3e8}, {0x3e8,0x3e8,0x3e8}
+ {0x000,0x000,0x000}, {0x0c8,0x000,0x000}, {0x190,0x000,0x000},
+ {0x258,0x000,0x000}, {0x320,0x000,0x000}, {0x3e8,0x000,0x000},
+ {0x000,0x0c8,0x000}, {0x0c8,0x0c8,0x000}, {0x190,0x0c8,0x000},
+ {0x258,0x0c8,0x000}, {0x320,0x0c8,0x000}, {0x3e8,0x0c8,0x000},
+ {0x000,0x190,0x000}, {0x0c8,0x190,0x000}, {0x190,0x190,0x000},
+ {0x258,0x190,0x000}, {0x320,0x190,0x000}, {0x3e8,0x190,0x000},
+ {0x000,0x258,0x000}, {0x0c8,0x258,0x000}, {0x190,0x258,0x000},
+ {0x258,0x258,0x000}, {0x320,0x258,0x000}, {0x3e8,0x258,0x000},
+ {0x000,0x320,0x000}, {0x0c8,0x320,0x000}, {0x190,0x320,0x000},
+ {0x258,0x320,0x000}, {0x320,0x320,0x000}, {0x3e8,0x320,0x000},
+ {0x000,0x3e8,0x000}, {0x0c8,0x3e8,0x000}, {0x190,0x3e8,0x000},
+ {0x258,0x3e8,0x000}, {0x320,0x3e8,0x000}, {0x3e8,0x3e8,0x000},
+ {0x000,0x000,0x0c8}, {0x0c8,0x000,0x0c8}, {0x190,0x000,0x0c8},
+ {0x258,0x000,0x0c8}, {0x320,0x000,0x0c8}, {0x3e8,0x000,0x0c8},
+ {0x000,0x0c8,0x0c8}, {0x0c8,0x0c8,0x0c8}, {0x190,0x0c8,0x0c8},
+ {0x258,0x0c8,0x0c8}, {0x320,0x0c8,0x0c8}, {0x3e8,0x0c8,0x0c8},
+ {0x000,0x190,0x0c8}, {0x0c8,0x190,0x0c8}, {0x190,0x190,0x0c8},
+ {0x258,0x190,0x0c8}, {0x320,0x190,0x0c8}, {0x3e8,0x190,0x0c8},
+ {0x000,0x258,0x0c8}, {0x0c8,0x258,0x0c8}, {0x190,0x258,0x0c8},
+ {0x258,0x258,0x0c8}, {0x320,0x258,0x0c8}, {0x3e8,0x258,0x0c8},
+ {0x000,0x320,0x0c8}, {0x0c8,0x320,0x0c8}, {0x190,0x320,0x0c8},
+ {0x258,0x320,0x0c8}, {0x320,0x320,0x0c8}, {0x3e8,0x320,0x0c8},
+ {0x000,0x3e8,0x0c8}, {0x0c8,0x3e8,0x0c8}, {0x190,0x3e8,0x0c8},
+ {0x258,0x3e8,0x0c8}, {0x320,0x3e8,0x0c8}, {0x3e8,0x3e8,0x0c8},
+ {0x000,0x000,0x190}, {0x0c8,0x000,0x190}, {0x190,0x000,0x190},
+ {0x258,0x000,0x190}, {0x320,0x000,0x190}, {0x3e8,0x000,0x190},
+ {0x000,0x0c8,0x190}, {0x0c8,0x0c8,0x190}, {0x190,0x0c8,0x190},
+ {0x258,0x0c8,0x190}, {0x320,0x0c8,0x190}, {0x3e8,0x0c8,0x190},
+ {0x000,0x190,0x190}, {0x0c8,0x190,0x190}, {0x190,0x190,0x190},
+ {0x258,0x190,0x190}, {0x320,0x190,0x190}, {0x3e8,0x190,0x190},
+ {0x000,0x258,0x190}, {0x0c8,0x258,0x190}, {0x190,0x258,0x190},
+ {0x258,0x258,0x190}, {0x320,0x258,0x190}, {0x3e8,0x258,0x190},
+ {0x000,0x320,0x190}, {0x0c8,0x320,0x190}, {0x190,0x320,0x190},
+ {0x258,0x320,0x190}, {0x320,0x320,0x190}, {0x3e8,0x320,0x190},
+ {0x000,0x3e8,0x190}, {0x0c8,0x3e8,0x190}, {0x190,0x3e8,0x190},
+ {0x258,0x3e8,0x190}, {0x320,0x3e8,0x190}, {0x3e8,0x3e8,0x190},
+ {0x000,0x000,0x258}, {0x0c8,0x000,0x258}, {0x190,0x000,0x258},
+ {0x258,0x000,0x258}, {0x320,0x000,0x258}, {0x3e8,0x000,0x258},
+ {0x000,0x0c8,0x258}, {0x0c8,0x0c8,0x258}, {0x190,0x0c8,0x258},
+ {0x258,0x0c8,0x258}, {0x320,0x0c8,0x258}, {0x3e8,0x0c8,0x258},
+ {0x000,0x190,0x258}, {0x0c8,0x190,0x258}, {0x190,0x190,0x258},
+ {0x258,0x190,0x258}, {0x320,0x190,0x258}, {0x3e8,0x190,0x258},
+ {0x000,0x258,0x258}, {0x0c8,0x258,0x258}, {0x190,0x258,0x258},
+ {0x258,0x258,0x258}, {0x320,0x258,0x258}, {0x3e8,0x258,0x258},
+ {0x000,0x320,0x258}, {0x0c8,0x320,0x258}, {0x190,0x320,0x258},
+ {0x258,0x320,0x258}, {0x320,0x320,0x258}, {0x3e8,0x320,0x258},
+ {0x000,0x3e8,0x258}, {0x0c8,0x3e8,0x258}, {0x190,0x3e8,0x258},
+ {0x258,0x3e8,0x258}, {0x320,0x3e8,0x258}, {0x3e8,0x3e8,0x258},
+ {0x000,0x000,0x320}, {0x0c8,0x000,0x320}, {0x190,0x000,0x320},
+ {0x258,0x000,0x320}, {0x320,0x000,0x320}, {0x3e8,0x000,0x320},
+ {0x000,0x0c8,0x320}, {0x0c8,0x0c8,0x320}, {0x190,0x0c8,0x320},
+ {0x258,0x0c8,0x320}, {0x320,0x0c8,0x320}, {0x3e8,0x0c8,0x320},
+ {0x000,0x190,0x320}, {0x0c8,0x190,0x320}, {0x190,0x190,0x320},
+ {0x258,0x190,0x320}, {0x320,0x190,0x320}, {0x3e8,0x190,0x320},
+ {0x000,0x258,0x320}, {0x0c8,0x258,0x320}, {0x190,0x258,0x320},
+ {0x258,0x258,0x320}, {0x320,0x258,0x320}, {0x3e8,0x258,0x320},
+ {0x000,0x320,0x320}, {0x0c8,0x320,0x320}, {0x190,0x320,0x320},
+ {0x258,0x320,0x320}, {0x320,0x320,0x320}, {0x3e8,0x320,0x320},
+ {0x000,0x3e8,0x320}, {0x0c8,0x3e8,0x320}, {0x190,0x3e8,0x320},
+ {0x258,0x3e8,0x320}, {0x320,0x3e8,0x320}, {0x3e8,0x3e8,0x320},
+ {0x000,0x000,0x3e8}, {0x0c8,0x000,0x3e8}, {0x190,0x000,0x3e8},
+ {0x258,0x000,0x3e8}, {0x320,0x000,0x3e8}, {0x3e8,0x000,0x3e8},
+ {0x000,0x0c8,0x3e8}, {0x0c8,0x0c8,0x3e8}, {0x190,0x0c8,0x3e8},
+ {0x258,0x0c8,0x3e8}, {0x320,0x0c8,0x3e8}, {0x3e8,0x0c8,0x3e8},
+ {0x000,0x190,0x3e8}, {0x0c8,0x190,0x3e8}, {0x190,0x190,0x3e8},
+ {0x258,0x190,0x3e8}, {0x320,0x190,0x3e8}, {0x3e8,0x190,0x3e8},
+ {0x000,0x258,0x3e8}, {0x0c8,0x258,0x3e8}, {0x190,0x258,0x3e8},
+ {0x258,0x258,0x3e8}, {0x320,0x258,0x3e8}, {0x3e8,0x258,0x3e8},
+ {0x000,0x320,0x3e8}, {0x0c8,0x320,0x3e8}, {0x190,0x320,0x3e8},
+ {0x258,0x320,0x3e8}, {0x320,0x320,0x3e8}, {0x3e8,0x320,0x3e8},
+ {0x000,0x3e8,0x3e8}, {0x0c8,0x3e8,0x3e8}, {0x190,0x3e8,0x3e8},
+ {0x258,0x3e8,0x3e8}, {0x320,0x3e8,0x3e8}, {0x3e8,0x3e8,0x3e8}
};
#endif
@@ -180,15 +209,16 @@ VdiHdl atari_plot_vdi_handle = -1;
unsigned long atari_plot_flags;
unsigned long atari_font_flags;
-typedef bool (*bitmap_convert_fnc)( struct bitmap * img, int x, int y,
- GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out );
+typedef bool (*bitmap_convert_fnc)(struct bitmap * img, int x, int y, GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out );
static bitmap_convert_fnc bitmap_convert;
+/* exported interface documented in atari/plot.h */
const char* plot_err_str(int i)
{
- return(plot_error_codes[abs(i)]);
+ return (plot_error_codes[abs(i)]);
}
+
/**
* Set line drawing color by passing netsurf XBGR "colour" type.
*
@@ -200,21 +230,22 @@ inline static void vsl_rgbcolor(short vdih, colour cin)
#ifdef WITH_8BPP_SUPPORT
if( vdi_sysinfo.scr_bpp > 8 ) {
#endif
- RGB1000 c; /* a struct with three (RGB) shorts */
- rgb_to_vdi1000( (unsigned char*)&cin, &c);
- vs_color(vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
- vsl_color(vdih, OFFSET_CUSTOM_COLOR);
+ RGB1000 c; /* a struct with three (RGB) shorts */
+ rgb_to_vdi1000( (unsigned char*)&cin, &c);
+ vs_color(vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
+ vsl_color(vdih, OFFSET_CUSTOM_COLOR);
#ifdef WITH_8BPP_SUPPORT
} else {
- if( vdi_sysinfo.scr_bpp >= 4 ){
- vsl_color(vdih, RGB_TO_VDI(cin));
- }
- else
- vsl_color(vdih, BLACK);
+ if( vdi_sysinfo.scr_bpp >= 4 ){
+ vsl_color(vdih, RGB_TO_VDI(cin));
+ }
+ else
+ vsl_color(vdih, BLACK);
}
#endif
}
+
/**
* Set fill color by passing netsurf XBGR "colour" type.
*
@@ -226,23 +257,22 @@ inline static void vsf_rgbcolor(short vdih, colour cin)
#ifdef WITH_8BPP_SUPPORT
if( vdi_sysinfo.scr_bpp > 8 ) {
#endif
- RGB1000 c; /* a struct with three (RGB) shorts */
- rgb_to_vdi1000( (unsigned char*)&cin, &c);
- vs_color( vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
- vsf_color( vdih, OFFSET_CUSTOM_COLOR );
+ RGB1000 c; /* a struct with three (RGB) shorts */
+ rgb_to_vdi1000( (unsigned char*)&cin, &c);
+ vs_color( vdih, OFFSET_CUSTOM_COLOR, (short *)&c);
+ vsf_color( vdih, OFFSET_CUSTOM_COLOR );
#ifdef WITH_8BPP_SUPPORT
} else {
- if( vdi_sysinfo.scr_bpp >= 4 ){
- vsf_color( vdih, RGB_TO_VDI(cin) );
- }
- else
- vsf_color( vdih, WHITE );
+ if( vdi_sysinfo.scr_bpp >= 4 ){
+ vsf_color( vdih, RGB_TO_VDI(cin) );
+ }
+ else
+ vsf_color( vdih, WHITE );
}
#endif
}
-
/**
* Get current visible coords
*/
@@ -255,7 +285,6 @@ inline static void plot_get_visible_grect(GRECT * out)
}
-
/* calculate visible area of framebuffer in coords relative to framebuffer */
/* position */
/* result: */
@@ -280,24 +309,29 @@ inline static void update_visible_rect(void)
common.g_h = frame.g_h = view.h;
if (rc_intersect(&screen, &common)) {
- view.vis_w = common.g_w;
- view.vis_h = common.g_h;
- if (view.x < screen.g_x)
- view.vis_x = frame.g_w - common.g_w;
- else
- view.vis_x = 0;
- if (view.y <screen.g_y)
- view.vis_y = frame.g_h - common.g_h;
- else
- view.vis_y = 0;
+ view.vis_w = common.g_w;
+ view.vis_h = common.g_h;
+ if (view.x < screen.g_x)
+ view.vis_x = frame.g_w - common.g_w;
+ else
+ view.vis_x = 0;
+ if (view.y <screen.g_y)
+ view.vis_y = frame.g_h - common.g_h;
+ else
+ view.vis_y = 0;
} else {
- view.vis_w = view.vis_h = 0;
- view.vis_x = view.vis_y = 0;
+ view.vis_w = view.vis_h = 0;
+ view.vis_x = view.vis_y = 0;
}
}
-/* Returns the visible parts of the box (relative coords within framebuffer),*/
-/* relative to screen coords (normally starting at 0,0 ) */
+
+/**
+ * Returns the visible parts of the box
+ *
+ * The returned values are relative coords within framebuffer,
+ * relative to screen coords (normally starting at 0,0 )
+ */
inline static bool fbrect_to_screen(GRECT box, GRECT * ret)
{
GRECT out, vis, screen;
@@ -314,14 +348,14 @@ inline static bool fbrect_to_screen(GRECT box, GRECT * ret)
vis.g_h = view.h;
if ( !rc_intersect( &screen, &vis ) ) {
- return( false );
+ return( false );
}
vis.g_x = view.w - vis.g_w;
vis.g_y = view.h - vis.g_h;
/* clip box to visible region: */
if( !rc_intersect(&vis, &box) ) {
- return( false );
+ return( false );
}
out.g_x = box.g_x + view.x;
out.g_y = box.g_y + view.y;
@@ -331,8 +365,12 @@ inline static bool fbrect_to_screen(GRECT box, GRECT * ret)
return ( true );
}
-/* copy an rectangle from the plot buffer to screen */
-/* because this is an on-screen plotter, this is an screen to screen copy. */
+
+/**
+ * copy an rectangle from the plot buffer to screen
+ *
+ * because this is an on-screen plotter, this is an screen to screen copy.
+ */
bool plot_copy_rect(GRECT src, GRECT dst)
{
MFDB devmf;
@@ -344,9 +382,9 @@ bool plot_copy_rect(GRECT src, GRECT dst)
plot_get_visible_grect(&vis );
if( !rc_intersect(&vis, &src) )
- return(true);
+ return(true);
if( !rc_intersect(&vis, &dst) )
- return(true);
+ return(true);
src.g_x = view.x + src.g_x;
src.g_y = view.y + src.g_y;
@@ -384,23 +422,25 @@ bool plot_copy_rect(GRECT src, GRECT dst)
return(true);
}
+
/**
* Fill the screen info structure.
*
* \param vdih The handle
* \param[out] info The infor structure to fill.
*/
-static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) {
-
- unsigned long cookie_EdDI=0; /** \todo this long is being cast to a pointer */
+static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info)
+{
+ /** \todo this long is being cast to a pointer */
+ unsigned long cookie_EdDI=0;
short out[300];
memset( info, 0, sizeof(struct s_vdi_sysinfo) );
info->vdi_handle = vdih;
if ( tos_getcookie(C_EdDI, (long *)&cookie_EdDI) == C_NOTFOUND ) {
- info->EdDiVersion = 0;
+ info->EdDiVersion = 0;
} else {
- info->EdDiVersion = EdDI_version( (void *)cookie_EdDI );
+ info->EdDiVersion = EdDI_version( (void *)cookie_EdDI );
}
memset( &out, 0, sizeof(short)*300 );
@@ -408,10 +448,10 @@ static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) {
info->scr_w = out[0]+1;
info->scr_h = out[1]+1;
if( out[39] == 2 ) {
- info->scr_bpp = 1;
- info->colors = out[39];
+ info->scr_bpp = 1;
+ info->colors = out[39];
} else {
- info->colors = out[39];
+ info->colors = out[39];
}
memset( &out, 0, sizeof(short)*300 );
@@ -420,31 +460,31 @@ static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) {
info->maxpolycoords = out[14];
info->maxintin = out[15];
if( out[30] & 1 ) {
- info->rasterscale = true;
+ info->rasterscale = true;
} else {
- info->rasterscale = false;
+ info->rasterscale = false;
}
switch( info->scr_bpp ) {
case 8:
- info->pixelsize=1;
- break;
+ info->pixelsize=1;
+ break;
case 15:
case 16:
- info->pixelsize=2;
- break;
+ info->pixelsize=2;
+ break;
case 24:
- info->pixelsize=3;
- break;
+ info->pixelsize=3;
+ break;
case 32:
- info->pixelsize=4;
- break;
+ info->pixelsize=4;
+ break;
case 64:
- info->pixelsize=8;
- break;
+ info->pixelsize=8;
+ break;
default:
- info->pixelsize=1;
- break;
+ info->pixelsize=1;
+ break;
}
info->pitch = info->scr_w * info->pixelsize;
@@ -452,75 +492,75 @@ static void read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info) {
info->screensize = ( info->scr_w * info->pixelsize ) * info->scr_h;
if( info->EdDiVersion >= EDDI_10 ) {
- memset( &out, 0, sizeof(short)*300 );
- vq_scrninfo(vdih, (short*)&out);
- info->vdiformat = out[0];
- info->clut = out[1];
- info->scr_bpp = out[2];
- info->hicolors = *((unsigned long*) &out[3]);
- if( info->EdDiVersion >= EDDI_11 ) {
- info->pitch = out[5];
- info->screen = (void *) *((unsigned long *) &out[6]);
- }
-
- switch( info->clut ) {
-
- case VDI_CLUT_HARDWARE: {
-
- }
- break;
-
- case VDI_CLUT_SOFTWARE: {
- int component; /* red, green, blue, alpha, overlay */
- int num_bit;
- unsigned short *tmp_p;
-
- /* We can build masks with info here */
- tmp_p = (unsigned short *) &out[16];
- for (component=0; component<5; component++) {
- for (num_bit=0; num_bit<16; num_bit++) {
- unsigned short val;
-
- val = *tmp_p++;
-
- if (val == 0xffff) {
- continue;
- }
-
- switch(component) {
- case 0:
- info->mask_r |= 1<< val;
- break;
- case 1:
- info->mask_g |= 1<< val;
- break;
- case 2:
- info->mask_b |= 1<< val;
- break;
- case 3:
- info->mask_a |= 1<< val;
- break;
- }
- }
- }
- }
-
- /* Remove lower green bits for Intel endian screen */
- if ((info->mask_g == ((7<<13)|3)) || (info->mask_g == ((7<<13)|7))) {
- info->mask_g &= ~(7<<13);
- }
- break;
-
- case VDI_CLUT_NONE:
- break;
- }
+ memset( &out, 0, sizeof(short)*300 );
+ vq_scrninfo(vdih, (short*)&out);
+ info->vdiformat = out[0];
+ info->clut = out[1];
+ info->scr_bpp = out[2];
+ info->hicolors = *((unsigned long*) &out[3]);
+ if( info->EdDiVersion >= EDDI_11 ) {
+ info->pitch = out[5];
+ info->screen = (void *) *((unsigned long *) &out[6]);
+ }
+
+ switch( info->clut ) {
+
+ case VDI_CLUT_HARDWARE:
+ break;
+
+ case VDI_CLUT_SOFTWARE:
+ {
+ int component; /* red, green, blue, alpha, overlay */
+ int num_bit;
+ unsigned short *tmp_p;
+
+ /* We can build masks with info here */
+ tmp_p = (unsigned short *) &out[16];
+ for (component=0; component<5; component++) {
+ for (num_bit=0; num_bit<16; num_bit++) {
+ unsigned short val;
+
+ val = *tmp_p++;
+
+ if (val == 0xffff) {
+ continue;
+ }
+
+ switch(component) {
+ case 0:
+ info->mask_r |= 1<< val;
+ break;
+ case 1:
+ info->mask_g |= 1<< val;
+ break;
+ case 2:
+ info->mask_b |= 1<< val;
+ break;
+ case 3:
+ info->mask_a |= 1<< val;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Remove lower green bits for Intel endian screen */
+ if ((info->mask_g == ((7<<13)|3)) ||
+ (info->mask_g == ((7<<13)|7))) {
+ info->mask_g &= ~(7<<13);
+ }
+ break;
+
+ case VDI_CLUT_NONE:
+ break;
+ }
}
}
-/*
- Convert an RGB color to an VDI Color
-*/
+/**
+ * Convert an RGB color to an VDI Color
+ */
inline void rgb_to_vdi1000(unsigned char * in, RGB1000 *out)
{
double r = ((double)in[3]/255); /* prozentsatz red */
@@ -532,6 +572,7 @@ inline void rgb_to_vdi1000(unsigned char * in, RGB1000 *out)
return;
}
+
inline void vdi1000_to_rgb(unsigned short * in, unsigned char * out)
{
double r = ((double)in[0]/1000); /* prozentsatz red */
@@ -548,7 +589,8 @@ inline void vdi1000_to_rgb(unsigned short * in, unsigned char * out)
/**
* Set pixel within an 8 bit VDI standard bitmap.
*/
-inline static void set_stdpx( MFDB * dst, int wdplanesz, int x, int y, unsigned char val )
+inline static void
+set_stdpx( MFDB * dst, int wdplanesz, int x, int y, unsigned char val )
{
short * buf;
short whichbit = (1<<(15-(x%16)));
@@ -580,6 +622,7 @@ inline static void set_stdpx( MFDB * dst, int wdplanesz, int x, int y, unsigned
*buf = (val&(1<<7)) ? ((*buf)|(whichbit)) : ((*buf)&~(whichbit));
}
+
/**
* Read pixel from an 8 bit VDI standard bitmap.
*/
@@ -593,42 +636,42 @@ inline static unsigned char get_stdpx(MFDB * dst, int wdplanesz, int x, int y)
buf += ((dst->fd_wdwidth*(y))+(x>>4));
if( *buf & whichbit )
- ret |= 1;
+ ret |= 1;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 2;
+ ret |= 2;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 4;
+ ret |= 4;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 8;
+ ret |= 8;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 16;
+ ret |= 16;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 32;
+ ret |= 32;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 64;
+ ret |= 64;
buf += wdplanesz;
if( *buf & whichbit )
- ret |= 128;
+ ret |= 128;
return( ret );
}
-/*
- Convert an RGB color into an index into the 216 colors web pallette
-*/
+/**
+ * Convert an RGB color into an index into the 216 colors web pallette
+ */
inline short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
{
short i;
@@ -640,24 +683,24 @@ inline short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
diff_b = abs(r-b);
diff_c = abs(r-b);
if( diff_a < 2 && diff_b < 2 && diff_c < 2 ) {
- if( (r!=0XFF) && (g!=0XFF) && (b!=0XFF) ) {
- if( ((r&0xF0)>>4) != 0 )
- //printf("conv gray: %x -> %d\n", ((r&0xF0)>>4) , (OFFSET_CUST_PAL) + ((r&0xF0)>>4) );
- return( (OFFSET_CUST_PAL - OFFSET_WEB_PAL) + ((r&0xF0)>>4) );
- }
+ if( (r!=0XFF) && (g!=0XFF) && (b!=0XFF) ) {
+ if( ((r&0xF0)>>4) != 0 )
+ //printf("conv gray: %x -> %d\n", ((r&0xF0)>>4) , (OFFSET_CUST_PAL) + ((r&0xF0)>>4) );
+ return( (OFFSET_CUST_PAL - OFFSET_WEB_PAL) + ((r&0xF0)>>4) );
+ }
}
/* convert each 8bit color to 6bit web color: */
for( i=0; i<3; i++) {
- if(0 == rgb[i] % web_std_colors[1] ) {
- tval[i] = rgb[i] / web_std_colors[1];
- } else {
- int pos = ((short)rgb[i] / web_std_colors[1]);
- if( abs(rgb[i] - web_std_colors[pos]) > abs(rgb[i] - web_std_colors[pos+1]) )
- tval[i] = pos+1;
- else
- tval[i] = pos;
- }
+ if(0 == rgb[i] % web_std_colors[1] ) {
+ tval[i] = rgb[i] / web_std_colors[1];
+ } else {
+ int pos = ((short)rgb[i] / web_std_colors[1]);
+ if( abs(rgb[i] - web_std_colors[pos]) > abs(rgb[i] - web_std_colors[pos+1]) )
+ tval[i] = pos+1;
+ else
+ tval[i] = pos;
+ }
}
return(tval[2]*36+tval[1]*6+tval[0]);
}
@@ -692,6 +735,7 @@ static void dump_vdi_info(short vdih)
printf("};\n");
}
+
/**
* Create an snapshot of the screen image in device format.
*/
@@ -702,29 +746,29 @@ static MFDB * snapshot_create_native_mfdb(int x, int y, int w, int h)
/* allocate memory for the snapshot */
{
- int scr_stride = MFDB_STRIDE( w );
- int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
- if(size_buf_scr == 0 ){
- /* init screen mfdb */
- buf_scr.fd_addr = malloc( scr_size );
- size_buf_scr = scr_size;
- } else {
- if( scr_size >size_buf_scr ) {
- buf_scr.fd_addr = realloc(
- buf_scr.fd_addr, scr_size
- );
- size_buf_scr = scr_size;
- }
- }
- if(buf_scr.fd_addr == NULL ) {
- size_buf_scr = 0;
- return( NULL );
- }
- buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp;
- buf_scr.fd_w = scr_stride;
- buf_scr.fd_h = h;
- buf_scr.fd_wdwidth = scr_stride >> 4;
- assert(buf_scr.fd_addr != NULL );
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
+ if(size_buf_scr == 0 ){
+ /* init screen mfdb */
+ buf_scr.fd_addr = malloc( scr_size );
+ size_buf_scr = scr_size;
+ } else {
+ if( scr_size >size_buf_scr ) {
+ buf_scr.fd_addr = realloc(
+ buf_scr.fd_addr, scr_size
+ );
+ size_buf_scr = scr_size;
+ }
+ }
+ if(buf_scr.fd_addr == NULL ) {
+ size_buf_scr = 0;
+ return( NULL );
+ }
+ buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp;
+ buf_scr.fd_w = scr_stride;
+ buf_scr.fd_h = h;
+ buf_scr.fd_wdwidth = scr_stride >> 4;
+ assert(buf_scr.fd_addr != NULL );
}
init_mfdb( 0, w, h, 0, &scr );
pxy[0] = x;
@@ -736,18 +780,27 @@ static MFDB * snapshot_create_native_mfdb(int x, int y, int w, int h)
pxy[6] = w-1;
pxy[7] = h-1;
vro_cpyfm(
- atari_plot_vdi_handle, S_ONLY, (short*)&pxy,
- &scr, &buf_scr
- );
+ atari_plot_vdi_handle, S_ONLY, (short*)&pxy,
+ &scr, &buf_scr
+ );
return( &buf_scr );
}
-/*
+/**
* Create an snapshot of the screen in netsurf ABGR format
+ *
+ * This creates an snapshot in RGBA format (NetSurf's native format)
+ *
+ * Capture the screen at x,y location
+ * \param self instance
+ * \param x absolute screen coords
+ * \param y absolute screen coords
+ * \param w width
+ * \param h height
*/
-static struct bitmap * snapshot_create(int x, int y, int w, int h)
+static struct bitmap *snapshot_create(int x, int y, int w, int h)
{
int err;
MFDB * native;
@@ -764,37 +817,37 @@ static struct bitmap * snapshot_create(int x, int y, int w, int h)
native = snapshot_create_native_mfdb(x, y, w, h );
if(vfmt.bits == 32 )
- goto no_copy;
+ goto no_copy;
/* allocate buffer for result bitmap: */
if(buf_scr_compat == NULL ) {
- buf_scr_compat = atari_bitmap_create(w, h, 0);
+ buf_scr_compat = atari_bitmap_create(w, h, 0);
} else {
- buf_scr_compat = atari_bitmap_realloc( w, h,
- buf_scr_compat->bpp,
- w *buf_scr_compat->bpp,
- BITMAP_GROW,
- buf_scr_compat );
+ buf_scr_compat = atari_bitmap_realloc( w, h,
+ buf_scr_compat->bpp,
+ w *buf_scr_compat->bpp,
+ BITMAP_GROW,
+ buf_scr_compat );
}
/* convert screen buffer to ns format: */
err = Hermes_ConverterRequest( hermes_cnv_h,
- &vfmt,
- &nsfmt
- );
+ &vfmt,
+ &nsfmt
+ );
assert( err != 0 );
err = Hermes_ConverterCopy( hermes_cnv_h,
- native->fd_addr,
- 0, /* x src coord of top left in pixel coords */
- 0, /* y src coord of top left in pixel coords */
- w, h,
- native->fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */
- buf_scr_compat->pixdata,
- 0, /* x dst coord of top left in pixel coords */
- 0, /* y dst coord of top left in pixel coords */
- w, h,
- atari_bitmap_get_rowstride(buf_scr_compat) /* stride as bytes */
- );
+ native->fd_addr,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ w, h,
+ native->fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */
+ buf_scr_compat->pixdata,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ w, h,
+ atari_bitmap_get_rowstride(buf_scr_compat) /* stride as bytes */
+ );
assert( err != 0 );
return( (struct bitmap * )buf_scr_compat );
@@ -808,59 +861,61 @@ no_copy:
uint32_t row, col;
for (row = 0; row<(uint32_t)h; row++) {
- // fd_w matches stride!
- uint32_t *rowptr = ((uint32_t*)native->fd_addr + ((row*native->fd_w)));
- for (col=0; col<(uint32_t)w; col++) {
- *(rowptr+col) = (*(rowptr+col)<<8);
- }
+ // fd_w matches stride!
+ uint32_t *rowptr = ((uint32_t*)native->fd_addr + ((row*native->fd_w)));
+ for (col=0; col<(uint32_t)w; col++) {
+ *(rowptr+col) = (*(rowptr+col)<<8);
+ }
}
return( &snapshot );
}
+
/**
* Notify the snapshot interface that the last snapshot is no longer in use.
*/
static void snapshot_suspend(void)
{
if(size_buf_scr > CONV_KEEP_LIMIT ) {
- buf_scr.fd_addr = realloc(
- buf_scr.fd_addr, CONV_KEEP_LIMIT
- );
- if(buf_scr.fd_addr != NULL ) {
- size_buf_scr = CONV_KEEP_LIMIT;
- } else {
- size_buf_scr = 0;
- }
+ buf_scr.fd_addr = realloc(
+ buf_scr.fd_addr, CONV_KEEP_LIMIT
+ );
+ if(buf_scr.fd_addr != NULL ) {
+ size_buf_scr = CONV_KEEP_LIMIT;
+ } else {
+ size_buf_scr = 0;
+ }
}
#ifdef WITH_8BPP_SUPPORT
if(size_buf_std > CONV_KEEP_LIMIT ) {
- buf_std.fd_addr = realloc(
- buf_std.fd_addr, CONV_KEEP_LIMIT
- );
- if(buf_std.fd_addr != NULL ) {
- size_buf_std = CONV_KEEP_LIMIT;
- } else {
- size_buf_std = 0;
- }
+ buf_std.fd_addr = realloc(
+ buf_std.fd_addr, CONV_KEEP_LIMIT
+ );
+ if(buf_std.fd_addr != NULL ) {
+ size_buf_std = CONV_KEEP_LIMIT;
+ } else {
+ size_buf_std = 0;
+ }
}
#endif
if(buf_scr_compat != NULL ) {
- size_t bs = atari_bitmap_buffer_size(buf_scr_compat );
- if( bs > CONV_KEEP_LIMIT ) {
- int w = 0;
- int h = 1;
- w = (CONV_KEEP_LIMIT /buf_scr_compat->bpp);
- assert( CONV_KEEP_LIMIT == w*buf_scr_compat->bpp );
- buf_scr_compat = atari_bitmap_realloc( w, h,
- buf_scr_compat->bpp,
- CONV_KEEP_LIMIT, BITMAP_SHRINK,buf_scr_compat
- );
- }
+ size_t bs = atari_bitmap_buffer_size(buf_scr_compat );
+ if( bs > CONV_KEEP_LIMIT ) {
+ int w = 0;
+ int h = 1;
+ w = (CONV_KEEP_LIMIT /buf_scr_compat->bpp);
+ assert( CONV_KEEP_LIMIT == w*buf_scr_compat->bpp );
+ buf_scr_compat = atari_bitmap_realloc( w, h,
+ buf_scr_compat->bpp,
+ CONV_KEEP_LIMIT, BITMAP_SHRINK,buf_scr_compat
+ );
+ }
}
}
+
/**
* Shut down the snapshot interface.
*/
@@ -869,7 +924,7 @@ static void snapshot_destroy(void)
free(buf_scr.fd_addr);
if( buf_scr_compat != NULL) {
- atari_bitmap_destroy(buf_scr_compat);
+ atari_bitmap_destroy(buf_scr_compat);
}
buf_scr.fd_addr = NULL;
@@ -890,17 +945,19 @@ inline static uint32_t ablend(uint32_t pixel, uint32_t scrpixel)
pixel >>= 8;
scrpixel >>= 8;
rb = ((pixel & 0xFF00FF) * opacity +
- (scrpixel & 0xFF00FF) * transp) >> 8;
+ (scrpixel & 0xFF00FF) * transp) >> 8;
g = ((pixel & 0x00FF00) * opacity +
- (scrpixel & 0x00FF00) * transp) >> 8;
+ (scrpixel & 0x00FF00) * transp) >> 8;
return ((rb & 0xFF00FF) | (g & 0xFF00)) << 8;
}
-/*
- Alpha blends an image, using one pixel as the background.
- The bitmap receives the result.
-*/
+
+/**
+ * Alpha blends an image, using one pixel as the background.
+ *
+ * The bitmap receives the result.
+ */
inline static bool ablend_pixel(struct bitmap * img, uint32_t bg, GRECT * clip)
{
uint32_t * imgrow;
@@ -909,22 +966,25 @@ inline static bool ablend_pixel(struct bitmap * img, uint32_t bg, GRECT * clip)
img_stride= atari_bitmap_get_rowstride(img);
for( img_y = 0; img_y < clip->g_h; img_y++) {
- imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
- for( img_x = 0; img_x < clip->g_w; img_x++ ) {
- imgrow[img_x] = ablend( imgrow[img_x], bg );
- }
+ imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
+ for( img_x = 0; img_x < clip->g_w; img_x++ ) {
+ imgrow[img_x] = ablend( imgrow[img_x], bg );
+ }
}
return(true);
}
-/*
- Aplha blends the foreground image (img) onto the
- background images (bg). The background receives the blended
- image pixels.
-*/
-inline static bool ablend_bitmap( struct bitmap * img, struct bitmap * bg,
- GRECT * img_clip, GRECT * bg_clip )
+/**
+ * Aplha blends the foreground image onto thebackground images.
+ *
+ * The background receives the blended image pixels.
+ */
+inline static bool
+ablend_bitmap(struct bitmap *img,
+ struct bitmap *bg,
+ GRECT *img_clip,
+ GRECT * bg_clip )
{
uint32_t * imgrow;
uint32_t * screenrow;
@@ -935,29 +995,29 @@ inline static bool ablend_bitmap( struct bitmap * img, struct bitmap * bg,
bg_stride = atari_bitmap_get_rowstride(bg);
for( img_y = img_clip->g_y, bg_y = 0; bg_y < img_clip->g_h; bg_y++, img_y++) {
- imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
- screenrow = (uint32_t *)(bg->pixdata + (bg_stride * bg_y));
- for( img_x = img_clip->g_x, bg_x = 0; bg_x < img_clip->g_w; bg_x++, img_x++ ) {
-
- // when the pixel isn't fully transparent,...:
- if( (imgrow[img_x] & 0x0FF) != 0 ){
- screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
- }
-
- // FIXME, maybe this loop would be faster??:
- // ---
- //if( (imgrow[img_x] & 0x0FF) != 0xFF ){
- // imgrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
- //}
-
- // or maybe even this???
- // ---
- //if( (imgrow[img_x] & 0x0FF) == 0xFF ){
- // screenrow[bg_x] = imgrow[img_x];
- //} else if( (imgrow[img_x] & 0x0FF) != 0x00 ) {
- // screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
- //}
- }
+ imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y));
+ screenrow = (uint32_t *)(bg->pixdata + (bg_stride * bg_y));
+ for( img_x = img_clip->g_x, bg_x = 0; bg_x < img_clip->g_w; bg_x++, img_x++ ) {
+
+ // when the pixel isn't fully transparent,...:
+ if( (imgrow[img_x] & 0x0FF) != 0 ){
+ screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ }
+
+ // FIXME, maybe this loop would be faster??:
+ // ---
+ //if( (imgrow[img_x] & 0x0FF) != 0xFF ){
+ // imgrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ //}
+
+ // or maybe even this???
+ // ---
+ //if( (imgrow[img_x] & 0x0FF) == 0xFF ){
+ // screenrow[bg_x] = imgrow[img_x];
+ //} else if( (imgrow[img_x] & 0x0FF) != 0x00 ) {
+ // screenrow[bg_x] = ablend( imgrow[img_x], screenrow[bg_x]);
+ //}
+ }
}
return(false);
}
@@ -972,30 +1032,30 @@ static MFDB * snapshot_create_std_mfdb(int x, int y, int w, int h)
{
/* allocate memory for the snapshot */
{
- int scr_stride = MFDB_STRIDE( w );
- int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
- if(size_buf_std == 0 ){
- /* init screen mfdb */
- buf_std.fd_addr = malloc( scr_size );
- size_buf_std = scr_size;
- } else {
- if( scr_size >size_buf_std ) {
- buf_std.fd_addr = realloc(
- buf_std.fd_addr, scr_size
- );
- size_buf_std = scr_size;
- }
- }
- if(buf_std.fd_addr == NULL ) {
- size_buf_std = 0;
- return( NULL );
- }
- buf_std.fd_nplanes = 8;
- buf_std.fd_w = scr_stride;
- buf_std.fd_h = h;
- buf_std.fd_stand = 1;
- buf_std.fd_wdwidth = scr_stride >> 4;
- assert(buf_std.fd_addr != NULL );
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = ( ((scr_stride >> 3) * h) * vdi_sysinfo.scr_bpp );
+ if(size_buf_std == 0 ){
+ /* init screen mfdb */
+ buf_std.fd_addr = malloc( scr_size );
+ size_buf_std = scr_size;
+ } else {
+ if( scr_size >size_buf_std ) {
+ buf_std.fd_addr = realloc(
+ buf_std.fd_addr, scr_size
+ );
+ size_buf_std = scr_size;
+ }
+ }
+ if(buf_std.fd_addr == NULL ) {
+ size_buf_std = 0;
+ return( NULL );
+ }
+ buf_std.fd_nplanes = 8;
+ buf_std.fd_w = scr_stride;
+ buf_std.fd_h = h;
+ buf_std.fd_stand = 1;
+ buf_std.fd_wdwidth = scr_stride >> 4;
+ assert(buf_std.fd_addr != NULL );
}
MFDB * native = snapshot_create_native_mfdb(x,y,w,h );
assert( native );
@@ -1004,6 +1064,7 @@ static MFDB * snapshot_create_std_mfdb(int x, int y, int w, int h)
return( &buf_std );
}
+
/**
* Convert an bitmap to an 8 bit device dependant MFDB
* \param img the bitmap (only tested with 32bit bitmaps)
@@ -1015,9 +1076,14 @@ static MFDB * snapshot_create_std_mfdb(int x, int y, int w, int h)
* \param out receives the converted bitmap (still owned by the plot API)
*
*/
-static bool bitmap_convert_8(struct bitmap * img, int x,
- int y, GRECT * clip, uint32_t bg, uint32_t flags,
- MFDB *out )
+static bool
+bitmap_convert_8(struct bitmap *img,
+ int x,
+ int y,
+ GRECT *clip,
+ uint32_t bg,
+ uint32_t flags,
+ MFDB *out)
{
MFDB native;
MFDB stdform;
@@ -1029,11 +1095,11 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
bool opaque = atari_bitmap_get_opaque( img );
if( opaque == false ){
- if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
- &&
- ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
- opaque = true;
- }
+ if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
+ &&
+ ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
+ opaque = true;
+ }
}
assert( clip->g_h > 0 );
@@ -1046,53 +1112,53 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
// the bitmap is fully opaque
if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){
- if( img->converted == true ){
- *out = img->native;
- return( 0 );
- }
- if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
- cache = true;
- }
+ if( img->converted == true ){
+ *out = img->native;
+ return( 0 );
+ }
+ if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
+ cache = true;
+ }
}
if( ( flags & BITMAPF_MONOGLYPH ) != 0 ){
- assert(cache == false);
+ assert(cache == false);
}
/* (re)allocate buffer for out image: */
/* altough the buffer is named "buf_packed" on 8bit systems */
/* it's not... */
if( cache == false ){
- // the size of the output will match the size of the clipping:
- dststride = MFDB_STRIDE( clip->g_w );
- dstsize = ( ((dststride >> 3) * clip->g_h) * atari_plot_bpp_virt);
- if (dstsize > size_buf_packed) {
- int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
- void *buf;
- if (buf_packed == NULL) {
- buf = malloc( blocks * CONV_BLOCK_SIZE);
- } else {
- buf = realloc(buf_packed, blocks * CONV_BLOCK_SIZE);
- }
- if (buf == NULL) {
- return( 0-ERR_NO_MEM );
- }
- buf_packed = buf;
- size_buf_packed = blocks * CONV_BLOCK_SIZE;
- }
- native.fd_addr = buf_packed;
+ // the size of the output will match the size of the clipping:
+ dststride = MFDB_STRIDE( clip->g_w );
+ dstsize = ( ((dststride >> 3) * clip->g_h) * atari_plot_bpp_virt);
+ if (dstsize > size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ void *buf;
+ if (buf_packed == NULL) {
+ buf = malloc( blocks * CONV_BLOCK_SIZE);
+ } else {
+ buf = realloc(buf_packed, blocks * CONV_BLOCK_SIZE);
+ }
+ if (buf == NULL) {
+ return( 0-ERR_NO_MEM );
+ }
+ buf_packed = buf;
+ size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ native.fd_addr = buf_packed;
}
else {
- // the output image will be completly saved, so size of the output
- // image will match the input image size.
- dststride = MFDB_STRIDE( bw );
- dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt);
- assert( out->fd_addr == NULL );
- native.fd_addr = malloc( dstsize );
- if (native.fd_addr == NULL){
- if (scrbuf != NULL)
- atari_bitmap_destroy(scrbuf);
- return( 0-ERR_NO_MEM );
- }
+ // the output image will be completly saved, so size of the output
+ // image will match the input image size.
+ dststride = MFDB_STRIDE( bw );
+ dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt);
+ assert( out->fd_addr == NULL );
+ native.fd_addr = malloc( dstsize );
+ if (native.fd_addr == NULL){
+ if (scrbuf != NULL)
+ atari_bitmap_destroy(scrbuf);
+ return( 0-ERR_NO_MEM );
+ }
}
@@ -1103,29 +1169,29 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
*/
// realloc mem for stdform
if( opaque == false ){
- // point image to snapshot buffer, otherwise allocate mem
- MFDB * bg = snapshot_create_std_mfdb(x, y, clip->g_w, clip->g_h);
- stdform.fd_addr = bg->fd_addr;
- bh = clip->g_h;
+ // point image to snapshot buffer, otherwise allocate mem
+ MFDB * bg = snapshot_create_std_mfdb(x, y, clip->g_w, clip->g_h);
+ stdform.fd_addr = bg->fd_addr;
+ bh = clip->g_h;
} else {
- if (dstsize > size_buf_planar) {
- int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
- void *buf;
- if (buf_planar == NULL) {
- buf = malloc(blocks * CONV_BLOCK_SIZE);
- } else {
- buf = realloc(buf_planar, blocks * CONV_BLOCK_SIZE);
- }
- if (buf == NULL ) {
- if (cache) {
- free(native.fd_addr);
- }
- return( 0-ERR_NO_MEM );
- }
- buf_planar = buf;
- size_buf_planar = blocks * CONV_BLOCK_SIZE;
- }
- stdform.fd_addr = buf_planar;
+ if (dstsize > size_buf_planar) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ void *buf;
+ if (buf_planar == NULL) {
+ buf = malloc(blocks * CONV_BLOCK_SIZE);
+ } else {
+ buf = realloc(buf_planar, blocks * CONV_BLOCK_SIZE);
+ }
+ if (buf == NULL ) {
+ if (cache) {
+ free(native.fd_addr);
+ }
+ return( 0-ERR_NO_MEM );
+ }
+ buf_planar = buf;
+ size_buf_planar = blocks * CONV_BLOCK_SIZE;
+ }
+ stdform.fd_addr = buf_planar;
}
stdform.fd_w = dststride;
stdform.fd_h = bh;
@@ -1143,67 +1209,67 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
int wdplanesize = stdform.fd_wdwidth*stdform.fd_h;
if( opaque == false ){
- // apply transparency and convert to vdi std format
- unsigned long bgcol = 0;
- unsigned char prev_col = 0;
- for( y=0; y<clip->g_h; y++ ){
- row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y)));
- for( x=0; x<clip->g_w; x++ ){
- pixel = row[x+clip->g_x];
- if( (pixel&0xFF) == 0 ){
- continue;
- }
- if( (pixel&0xFF) < 0xF0 ){
- col = get_stdpx( &stdform, wdplanesize,x,y );
- if( (col != prev_col) || (y == 0) )
- bgcol = (((rgb_lookup[col][2] << 16) | (rgb_lookup[col][1] << 8) | (rgb_lookup[col][0]))<<8);
- if( prev_col != col || prev_pixel != pixel ){
- prev_col = col;
- pixel = ablend( pixel, bgcol );
- prev_pixel = pixel;
- pixel = pixel >> 8;
- /* convert pixel value to vdi color index: */
- col = ( ((pixel&0xFF)<<16)
- | (pixel&0xFF00)
- | ((pixel&0xFF0000)>>16) );
- val = RGB_TO_VDI( col );
- }
- set_stdpx( &stdform, wdplanesize, x, y, val );
- } else {
- if( pixel != prev_pixel ){
- /* convert pixel value to vdi color index: */
- pixel = pixel >> 8;
- col = ( ((pixel&0xFF)<<16)
- | (pixel&0xFF00)
- | ((pixel&0xFF0000)>>16) );
- val = RGB_TO_VDI( col );
- prev_pixel = pixel;
- }
- set_stdpx( &stdform, wdplanesize, x, y, val );
- }
- }
- }
- // adjust output position:
- clip->g_x = 0;
- clip->g_y = 0;
+ // apply transparency and convert to vdi std format
+ unsigned long bgcol = 0;
+ unsigned char prev_col = 0;
+ for( y=0; y<clip->g_h; y++ ){
+ row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y)));
+ for( x=0; x<clip->g_w; x++ ){
+ pixel = row[x+clip->g_x];
+ if( (pixel&0xFF) == 0 ){
+ continue;
+ }
+ if( (pixel&0xFF) < 0xF0 ){
+ col = get_stdpx( &stdform, wdplanesize,x,y );
+ if( (col != prev_col) || (y == 0) )
+ bgcol = (((rgb_lookup[col][2] << 16) | (rgb_lookup[col][1] << 8) | (rgb_lookup[col][0]))<<8);
+ if( prev_col != col || prev_pixel != pixel ){
+ prev_col = col;
+ pixel = ablend( pixel, bgcol );
+ prev_pixel = pixel;
+ pixel = pixel >> 8;
+ /* convert pixel value to vdi color index: */
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ } else {
+ if( pixel != prev_pixel ){
+ /* convert pixel value to vdi color index: */
+ pixel = pixel >> 8;
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ prev_pixel = pixel;
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ }
+ }
+ }
+ // adjust output position:
+ clip->g_x = 0;
+ clip->g_y = 0;
} else {
- // convert the whole image data to vdi std format.
- for( y=0; y < bh; y++ ){
- row = (uint32_t *)(img->pixdata + (img_stride * y));
- for( x=0; x < bw; x++ ){
- pixel = row[x];
- if( pixel != prev_pixel ){
- /* convert pixel value to vdi color index: */
- pixel = pixel >> 8;
- col = ( ((pixel&0xFF)<<16)
- | (pixel&0xFF00)
- | ((pixel&0xFF0000)>>16) );
- val = RGB_TO_VDI( col );
- prev_pixel = pixel;
- }
- set_stdpx( &stdform, wdplanesize, x, y, val );
- }
- }
+ // convert the whole image data to vdi std format.
+ for( y=0; y < bh; y++ ){
+ row = (uint32_t *)(img->pixdata + (img_stride * y));
+ for( x=0; x < bw; x++ ){
+ pixel = row[x];
+ if( pixel != prev_pixel ){
+ /* convert pixel value to vdi color index: */
+ pixel = pixel >> 8;
+ col = ( ((pixel&0xFF)<<16)
+ | (pixel&0xFF00)
+ | ((pixel&0xFF0000)>>16) );
+ val = RGB_TO_VDI( col );
+ prev_pixel = pixel;
+ }
+ set_stdpx( &stdform, wdplanesize, x, y, val );
+ }
+ }
}
// convert into native format:
@@ -1216,8 +1282,8 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
vr_trnfm(atari_plot_vdi_handle, &stdform, &native );
*out = native;
if( cache == true ){
- img->native = native;
- img->converted = true;
+ img->native = native;
+ img->converted = true;
}
return(0);
@@ -1225,24 +1291,30 @@ static bool bitmap_convert_8(struct bitmap * img, int x,
#endif
-/*
- *
+/**
* Convert bitmap to the native screen format
- * img: the bitmap
- * x: coordinate where the bitmap REGION (described in clip)
+ *
+ * \param img the bitmap
+ * \param x coordinate where the bitmap REGION (described in clip)
* shall be drawn (screen coords)
- * y: coordinate where the bitmap REGION (described in clip)
+ * \param y coordinate where the bitmap REGION (described in clip)
* shall be drawn (screen coords)
- * clip: which area of the bitmap shall be drawn
- * bg: background color
- * flags: blit flags
- * out: the result MFDB
+ * \param clip which area of the bitmap shall be drawn
+ * \param bg background color
+ * \param flags blit flags
+ * \param out the result MFDB
*/
-static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
- GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out )
+static bool
+bitmap_convert_tc(struct bitmap *img,
+ int x,
+ int y,
+ GRECT *clip,
+ uint32_t bg,
+ uint32_t flags,
+ MFDB *out)
{
- int dststride; /* stride of dest. image */
- int dstsize; /* size of dest. in byte */
+ int dststride; /* stride of dest. image */
+ int dstsize; /* size of dest. in byte */
int err;
int bw, bh;
struct bitmap * scrbuf = NULL;
@@ -1250,15 +1322,14 @@ static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
bool cache = ( flags & BITMAPF_BUFFER_NATIVE );
bool opaque = atari_bitmap_get_opaque( img );
- if( opaque == false ){
- if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
- &&
- ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
- opaque = true;
- }
+ if (opaque == false ) {
+ if( ( (atari_plot_flags & PLOT_FLAG_TRANS) == 0)
+ &&
+ ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){
+ opaque = true;
+ }
}
-
assert( clip->g_h > 0 );
assert( clip->g_w > 0 );
@@ -1277,80 +1348,80 @@ static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
// toolbar buttons right now.
if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){
- if( img->converted == true ){
- *out = img->native;
- return( 0 );
- }
- if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
- cache = true;
- }
+ if( img->converted == true ){
+ *out = img->native;
+ return( 0 );
+ }
+ if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){
+ cache = true;
+ }
}
/* rem. if eddi xy is installed, we could directly access the screen! */
/* apply transparency to the image: */
if (( opaque == false )) {
- /* copy the screen to an temp buffer: */
- if ((flags & BITMAPF_BUFFER_NATIVE) == 0) {
- scrbuf = snapshot_create(x, y, clip->g_w, clip->g_h);
- if( scrbuf != NULL ) {
-
- assert( clip->g_w <= bw );
- assert( clip->g_h <= bh );
-
- // copy blended pixels to the screen buffer:
- ablend_bitmap( img, scrbuf, clip, NULL );
- /* adjust size which gets converted: */
- bw = clip->g_w;
- bh = clip->g_h;
- /* adjust output position: */
- clip->g_x = 0;
- clip->g_y = 0;
- /* set the source of conversion: */
- source = scrbuf;
- }
- } else {
- /*
- The whole bitmap can be transformed to an mfdb
- (and get's cached)
- */
- GRECT region = { 0, 0, bw, bh };
- ablend_pixel( img, bg, ®ion );
- source = img;
- }
+ /* copy the screen to an temp buffer: */
+ if ((flags & BITMAPF_BUFFER_NATIVE) == 0) {
+ scrbuf = snapshot_create(x, y, clip->g_w, clip->g_h);
+ if( scrbuf != NULL ) {
+
+ assert( clip->g_w <= bw );
+ assert( clip->g_h <= bh );
+
+ // copy blended pixels to the screen buffer:
+ ablend_bitmap( img, scrbuf, clip, NULL );
+ /* adjust size which gets converted: */
+ bw = clip->g_w;
+ bh = clip->g_h;
+ /* adjust output position: */
+ clip->g_x = 0;
+ clip->g_y = 0;
+ /* set the source of conversion: */
+ source = scrbuf;
+ }
+ } else {
+ /*
+ The whole bitmap can be transformed to an mfdb
+ (and get's cached)
+ */
+ GRECT region = { 0, 0, bw, bh };
+ ablend_pixel( img, bg, ®ion );
+ source = img;
+ }
} else {
- source = img;
+ source = img;
}
/* (re)allocate buffer for converted image: */
dststride = MFDB_STRIDE(bw);
dstsize = ( ((dststride >> 3) * bh) * atari_plot_bpp_virt );
if (cache == false) {
- /* ensure cache buffer is large enough */
- if (dstsize > size_buf_packed) {
- int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
- void *buf;
- if (buf_packed == NULL) {
- buf = malloc(blocks * CONV_BLOCK_SIZE);
- } else {
- buf = realloc(buf_packed, blocks * CONV_BLOCK_SIZE);
- }
- if (buf == NULL ) {
- if (scrbuf != NULL) {
- atari_bitmap_destroy(scrbuf);
- }
- return( 0-ERR_NO_MEM );
- }
- buf_packed = buf;
- size_buf_packed = blocks * CONV_BLOCK_SIZE;
- }
- out->fd_addr = buf_packed;
+ /* ensure cache buffer is large enough */
+ if (dstsize > size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ void *buf;
+ if (buf_packed == NULL) {
+ buf = malloc(blocks * CONV_BLOCK_SIZE);
+ } else {
+ buf = realloc(buf_packed, blocks * CONV_BLOCK_SIZE);
+ }
+ if (buf == NULL ) {
+ if (scrbuf != NULL) {
+ atari_bitmap_destroy(scrbuf);
+ }
+ return( 0-ERR_NO_MEM );
+ }
+ buf_packed = buf;
+ size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ out->fd_addr = buf_packed;
} else {
- assert( out->fd_addr == NULL );
- out->fd_addr = (void*)malloc( dstsize );
- if( out->fd_addr == NULL ){
- if( scrbuf != NULL )
- atari_bitmap_destroy( scrbuf );
- return( 0-ERR_NO_MEM );
- }
+ assert( out->fd_addr == NULL );
+ out->fd_addr = (void*)malloc( dstsize );
+ if( out->fd_addr == NULL ){
+ if( scrbuf != NULL )
+ atari_bitmap_destroy( scrbuf );
+ return( 0-ERR_NO_MEM );
+ }
}
out->fd_w = dststride;
@@ -1361,10 +1432,10 @@ static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
err = Hermes_ConverterRequest(
- hermes_cnv_h,
- &nsfmt,
- &vfmt
- );
+ hermes_cnv_h,
+ &nsfmt,
+ &vfmt
+ );
assert( err != 0 );
// FIXME: here we can use the same optimization which is used for
@@ -1372,43 +1443,44 @@ static bool bitmap_convert_tc(struct bitmap * img, int x, int y,
/* convert image to virtual format: */
err = Hermes_ConverterCopy( hermes_cnv_h,
- source->pixdata,
- 0, /* x src coord of top left in pixel coords */
- 0, /* y src coord of top left in pixel coords */
- bw, bh,
- source->rowstride, /* stride as bytes */
- out->fd_addr,
- 0, /* x dst coord of top left in pixel coords */
- 0, /* y dst coord of top left in pixel coords */
- bw, bh,
- (dststride >> 3) * atari_plot_bpp_virt /* stride as bytes */
- );
+ source->pixdata,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ bw, bh,
+ source->rowstride, /* stride as bytes */
+ out->fd_addr,
+ 0, /* x dst coord of top left in pixel coords */
+ 0,/* y dst coord of top left in pixel coords */
+ bw, bh,
+ (dststride >> 3) * atari_plot_bpp_virt /* stride as bytes */
+ );
assert( err != 0 );
if( cache == true ){
- img->native = *out;
- img->converted = true;
+ img->native = *out;
+ img->converted = true;
}
return( 0 );
}
+
inline static void convert_bitmap_done(void)
{
if (size_buf_packed > CONV_KEEP_LIMIT) {
- void *buf;
- /* free the mem if it was an large allocation ... */
- buf = realloc(buf_packed, CONV_KEEP_LIMIT);
- if (buf != NULL) {
- buf_packed = buf;
- size_buf_packed = CONV_KEEP_LIMIT;
- }
+ void *buf;
+ /* free the mem if it was an large allocation ... */
+ buf = realloc(buf_packed, CONV_KEEP_LIMIT);
+ if (buf != NULL) {
+ buf_packed = buf;
+ size_buf_packed = CONV_KEEP_LIMIT;
+ }
}
}
bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
- unsigned long bg, unsigned long flags )
+ unsigned long bg, unsigned long flags )
{
MFDB src_mf;
MFDB scrmf;
@@ -1431,7 +1503,7 @@ bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
clip.g_h = view.clipping.y1 - view.clipping.y0;
if( !rc_intersect( &clip, &off) ) {
- return(true);
+ return(true);
}
// clip the visible rectangle of the plot area
@@ -1439,7 +1511,7 @@ bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
// screen region:
plot_get_visible_grect(&vis);
if( !rc_intersect( &vis, &off) ) {
- return(true);
+ return(true);
}
screen_x = view.x + off.g_x;
@@ -1453,8 +1525,8 @@ bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
/* Convert the Bitmap to native screen format - ready for output. */
/* This includes blending transparent pixels: */
if (bitmap_convert(bmp, screen_x, screen_y, &off, bg, flags, &src_mf)
- != 0 ) {
- return(true);
+ != 0 ) {
+ return(true);
}
// setup the src region:
@@ -1475,8 +1547,9 @@ bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
return(true);
}
+
bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor,
- uint32_t flags)
+ uint32_t flags)
{
MFDB screen;
// MFDB tran;
@@ -1487,7 +1560,7 @@ bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor,
plot_get_clip_grect(&off);
if( rc_intersect(loc, &off) == 0 ){
- return( 1 );
+ return( 1 );
}
init_mfdb( 0, loc->g_w, loc->g_h, 0, &screen );
@@ -1527,53 +1600,48 @@ bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor,
if( flags & PLOT_FLAG_TRANS && src->fd_nplanes == 1){
- vrt_cpyfm(atari_plot_vdi_handle, MD_REPLACE/*MD_TRANS*/, (short*)pxy, src, &screen, (short*)&c);
+ vrt_cpyfm(atari_plot_vdi_handle, MD_REPLACE/*MD_TRANS*/, (short*)pxy, src, &screen, (short*)&c);
} else {
- /* this method only plots transparent bitmaps, right now... */
+ /* this method only plots transparent bitmaps, right now... */
}
return( 1 );
}
-/*
- Init screen and font driver objects.
- Returns non-zero value > -1 when the objects could be succesfully created.
- Returns value < 0 to indicate an error
-*/
-int plot_init(char * fdrvrname)
+/* exported interface documented in atari/plot.h */
+int plot_init(const struct redraw_context *ctx, char *fdrvrname)
{
-
- GRECT loc_pos= {0,0,360,400};
+ GRECT loc_pos = { 0, 0, 360, 400 };
int err=0;
if( nsoption_int(atari_dither) == 1)
- atari_plot_flags |= PLOT_FLAG_DITHER;
+ atari_plot_flags |= PLOT_FLAG_DITHER;
if( nsoption_int(atari_transparency) == 1 )
- atari_plot_flags |= PLOT_FLAG_TRANS;
+ atari_plot_flags |= PLOT_FLAG_TRANS;
if( nsoption_int(atari_font_monochrom) == 1 )
- atari_font_flags |= FONTPLOT_FLAG_MONOGLYPH;
+ atari_font_flags |= FONTPLOT_FLAG_MONOGLYPH;
- if(atari_plot_vdi_handle == -1) {
+ if (atari_plot_vdi_handle == -1) {
- short dummy;
- short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1};
- short work_out[57];
- atari_plot_vdi_handle=graf_handle(&dummy, &dummy, &dummy, &dummy);
- v_opnvwk(work_in, &atari_plot_vdi_handle, work_out);
- LOG("Plot VDI handle: %d", atari_plot_vdi_handle);
+ short dummy;
+ short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1};
+ short work_out[57];
+ atari_plot_vdi_handle=graf_handle(&dummy, &dummy, &dummy, &dummy);
+ v_opnvwk(work_in, &atari_plot_vdi_handle, work_out);
+ LOG("Plot VDI handle: %d", atari_plot_vdi_handle);
}
read_vdi_sysinfo(atari_plot_vdi_handle, &vdi_sysinfo);
if(verbose_log) {
- dump_vdi_info(atari_plot_vdi_handle) ;
- dump_font_drivers();
+ dump_vdi_info(atari_plot_vdi_handle) ;
+ dump_font_drivers();
}
fplotter = new_font_plotter(atari_plot_vdi_handle, fdrvrname,
- atari_font_flags, &err);
- if(err) {
- const char * desc = plot_err_str(err);
- LOG("Unable to load font plotter %s -> %s", fdrvrname, desc );
- die("font plotter");
+ atari_font_flags, &err);
+ if (err) {
+ const char * desc = plot_err_str(err);
+ LOG("Unable to load font plotter %s -> %s", fdrvrname, desc );
+ die("font plotter");
}
memset(&view, 0, sizeof(struct s_view));
@@ -1587,9 +1655,9 @@ int plot_init(char * fdrvrname)
buf_packed = NULL;
buf_planar = NULL;
if( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) {
- atari_plot_bpp_virt = vdi_sysinfo.scr_bpp;
+ atari_plot_bpp_virt = vdi_sysinfo.scr_bpp;
} else {
- atari_plot_bpp_virt = 8;
+ atari_plot_bpp_virt = 8;
}
plot_set_scale(1.0);
@@ -1600,7 +1668,7 @@ int plot_init(char * fdrvrname)
clip.y0 = 0;
clip.x1 = view.w;
clip.y1 = view.h;
- plot_clip(&clip);
+ ctx->plot->clip(ctx, &clip);
assert(Hermes_Init());
@@ -1610,38 +1678,38 @@ int plot_init(char * fdrvrname)
/* Setup color lookup tables and palette */
unsigned char rgbcol[4];
if( vdi_sysinfo.scr_bpp <= 8 ){
- unsigned char graytone=0;
- int i;
- for( i=0; i<=255; i++ ) {
-
- // get the current color and save it for restore:
- vq_color(atari_plot_vdi_handle, i, 1, (unsigned short*)&sys_pal[i][0] );
- if( i<OFFSET_WEB_PAL ) {
- pal[i][0] = sys_pal[i][0];
- pal[i][1] = sys_pal[i][1];
- pal[i][2] = sys_pal[i][2];
- } else if( vdi_sysinfo.scr_bpp >= 8 ) {
- if ( i < OFFSET_CUST_PAL ){
- pal[i][0] = vdi_web_pal[i-OFFSET_WEB_PAL][0];
- pal[i][1] = vdi_web_pal[i-OFFSET_WEB_PAL][1];
- pal[i][2] = vdi_web_pal[i-OFFSET_WEB_PAL][2];
- //set the new palette color to websafe value:
- vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
- }
- if( i >= OFFSET_CUST_PAL && i<OFFSET_CUST_PAL+16 ) {
- /* here we define 20 additional gray colors... */
- rgbcol[1] = rgbcol[2] = rgbcol[3] = ((graytone&0x0F) << 4);
- rgb_to_vdi1000( &rgbcol[0], &pal[i][0] );
- vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
- graytone++;
- }
-
- }
- vdi1000_to_rgb( &pal[i][0], &rgb_lookup[i][0] );
- }
+ unsigned char graytone=0;
+ int i;
+ for( i=0; i<=255; i++ ) {
+
+ // get the current color and save it for restore:
+ vq_color(atari_plot_vdi_handle, i, 1, (unsigned short*)&sys_pal[i][0] );
+ if( i<OFFSET_WEB_PAL ) {
+ pal[i][0] = sys_pal[i][0];
+ pal[i][1] = sys_pal[i][1];
+ pal[i][2] = sys_pal[i][2];
+ } else if( vdi_sysinfo.scr_bpp >= 8 ) {
+ if ( i < OFFSET_CUST_PAL ){
+ pal[i][0] = vdi_web_pal[i-OFFSET_WEB_PAL][0];
+ pal[i][1] = vdi_web_pal[i-OFFSET_WEB_PAL][1];
+ pal[i][2] = vdi_web_pal[i-OFFSET_WEB_PAL][2];
+ //set the new palette color to websafe value:
+ vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
+ }
+ if( i >= OFFSET_CUST_PAL && i<OFFSET_CUST_PAL+16 ) {
+ /* here we define 20 additional gray colors... */
+ rgbcol[1] = rgbcol[2] = rgbcol[3] = ((graytone&0x0F) << 4);
+ rgb_to_vdi1000( &rgbcol[0], &pal[i][0] );
+ vs_color(atari_plot_vdi_handle, i, &pal[i][0]);
+ graytone++;
+ }
+
+ }
+ vdi1000_to_rgb( &pal[i][0], &rgb_lookup[i][0] );
+ }
} else {
- /* no need to change the palette - its application specific */
+ /* no need to change the palette - its application specific */
}
#else
bitmap_convert = bitmap_convert_tc;
@@ -1675,6 +1743,7 @@ int plot_init(char * fdrvrname)
return( err );
}
+
int plot_finalise( void )
{
@@ -1682,10 +1751,10 @@ int plot_finalise( void )
#ifdef WITH_8BPP_SUPPORT
if (vfmt.indexed) {
- int i;
- for (i=OFFSET_WEB_PAL; i<OFFSET_CUST_PAL+16; i++) {
- vs_color(atari_plot_vdi_handle, i, &sys_pal[i][0]);
- }
+ int i;
+ for (i=OFFSET_WEB_PAL; i<OFFSET_CUST_PAL+16; i++) {
+ vs_color(atari_plot_vdi_handle, i, &sys_pal[i][0]);
+ }
}
#endif
@@ -1701,25 +1770,27 @@ int plot_finalise( void )
return 0;
}
+
bool plot_lock(void)
{
if ((atari_plot_flags & PLOT_FLAG_LOCKED) != 0)
- return(true);
+ return(true);
if( !wind_update(BEG_UPDATE|0x100) )
- return(false);
+ return(false);
if( !wind_update(BEG_MCTRL|0x100) ){
- wind_update(END_UPDATE);
- return(false);
+ wind_update(END_UPDATE);
+ return(false);
}
atari_plot_flags |= PLOT_FLAG_LOCKED;
graf_mouse(M_OFF, NULL);
return(true);
}
+
bool plot_unlock(void)
{
if( (atari_plot_flags & PLOT_FLAG_LOCKED) == 0 )
- return(true);
+ return(true);
wind_update(END_MCTRL);
wind_update(END_UPDATE);
graf_mouse(M_ON, NULL);
@@ -1728,214 +1799,40 @@ bool plot_unlock(void)
return(false);
}
-bool plot_rectangle(int x0, int y0, int x1, int y1,
- const plot_style_t *pstyle )
-{
- short pxy[4];
- GRECT r, rclip, sclip;
- int sw = pstyle->stroke_width;
- uint32_t lt;
-
- /* current canvas clip: */
- rclip.g_x = view.clipping.x0;
- rclip.g_y = view.clipping.y0;
- rclip.g_w = view.clipping.x1 - view.clipping.x0;
- rclip.g_h = view.clipping.y1 - view.clipping.y0;
-
- /* physical clipping: */
- sclip.g_x = rclip.g_x;
- sclip.g_y = rclip.g_y;
- sclip.g_w = view.vis_w;
- sclip.g_h = view.vis_h;
-
- rc_intersect(&sclip, &rclip);
- r.g_x = x0;
- r.g_y = y0;
- r.g_w = x1 - x0;
- r.g_h = y1 - y0;
-
- if (!rc_intersect( &rclip, &r )) {
- return(true);
- }
- if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) {
- /*
- manually draw the line, because we do not need vdi clipping
- for vertical / horizontal line draws.
- */
- if( sw == 0)
- sw = 1;
-
- NSLT2VDI(lt, pstyle);
- vsl_type(atari_plot_vdi_handle, (lt&0x0F));
- /*
- if the line style is not available within VDI system,
- define own style:
- */
- if( (lt&0x0F) == 7 ){
- vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
- }
- vsl_width(atari_plot_vdi_handle, (short)sw );
- vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
- /* top border: */
- if( r.g_y == y0){
- pxy[0] = view.x + r.g_x;
- pxy[1] = view.y + r.g_y ;
- pxy[2] = view.x + r.g_x + r.g_w;
- pxy[3] = view.y + r.g_y;
- v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
- }
-
- /* right border: */
- if( r.g_x + r.g_w == x1 ){
- pxy[0] = view.x + r.g_x + r.g_w;
- pxy[1] = view.y + r.g_y;
- pxy[2] = view.x + r.g_x + r.g_w;
- pxy[3] = view.y + r.g_y + r.g_h;
- v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
- }
-
- /* bottom border: */
- if( r.g_y+r.g_h == y1 ){
- pxy[0] = view.x + r.g_x;
- pxy[1] = view.y + r.g_y+r.g_h;
- pxy[2] = view.x + r.g_x+r.g_w;
- pxy[3] = view.y + r.g_y+r.g_h;
- v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
- }
-
- /* left border: */
- if( r.g_x == x0 ){
- pxy[0] = view.x + r.g_x;
- pxy[1] = view.y + r.g_y;
- pxy[2] = view.x + r.g_x;
- pxy[3] = view.y + r.g_y + r.g_h;
- v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
- }
- }
-
- if( pstyle->fill_type != PLOT_OP_TYPE_NONE ){
- short stroke_width = (short)(pstyle->stroke_type != PLOT_OP_TYPE_NONE) ?
- pstyle->stroke_width : 0;
-
- vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
- vsf_perimeter(atari_plot_vdi_handle, 0);
- vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
-
-
- pxy[0] = view.x + r.g_x + stroke_width;
- pxy[1] = view.y + r.g_y + stroke_width;
- pxy[2] = view.x + r.g_x + r.g_w -1 - stroke_width;
- pxy[3] = view.y + r.g_y + r.g_h -1 - stroke_width;
-
- vsf_style(atari_plot_vdi_handle, 1);
- v_bar(atari_plot_vdi_handle, (short*)&pxy);
- }
- return (true);
-}
-
-bool plot_line(int x0, int y0, int x1, int y1,
- const plot_style_t *pstyle )
-{
- short pxy[4];
- uint32_t lt;
- int sw = pstyle->stroke_width;
-
- if((x0 < 0 && x1 < 0) || (y0 < 0 && y1 < 0)){
- return(true);
- }
-
- pxy[0] = view.x + MAX(0,x0);
- pxy[1] = view.y + MAX(0,y0);
- pxy[2] = view.x + MAX(0,x1);
- pxy[3] = view.y + MAX(0,y1);
-
- if((y0 > view.h-1) && (y1 > view.h-1))
- return(true);
-
- //printf("view: %d,%d,%d,%d\n", view.x, view.y, view.w, view.h);
- //printf("line: %d,%d,%d,%d\n", x0, y0, x1, y1);
-
-
- //plot_vdi_clip(true);
- if( sw == 0)
- sw = 1;
- NSLT2VDI(lt, pstyle)
- vsl_type(atari_plot_vdi_handle, (lt&0x0F));
- /* if the line style is not available within VDI system,define own style: */
- if( (lt&0x0F) == 7 ){
- vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
- }
- vsl_width(atari_plot_vdi_handle, (short)sw);
- vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
- v_pline(atari_plot_vdi_handle, 2, (short *)&pxy );
- //plot_vdi_clip(false);
- return (true);
-}
-static bool plot_polygon(const int *p, unsigned int n,
- const plot_style_t *pstyle)
-{
- short pxy[n*2];
- unsigned int i=0;
- if (vdi_sysinfo.maxpolycoords > 0)
- assert( (signed int)n < vdi_sysinfo.maxpolycoords);
-
- vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
- vsf_style(atari_plot_vdi_handle, 1);
- for (i = 0; i<n*2; i=i+2) {
- pxy[i] = (short)view.x+p[i];
- pxy[i+1] = (short)view.y+p[i+1];
- }
- if (pstyle->fill_type == PLOT_OP_TYPE_SOLID) {
- vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
- v_fillarea(atari_plot_vdi_handle, n, (short*)&pxy);
- } else {
- pxy[n*2]=pxy[0];
- pxy[n*2+1]=pxy[1];
- vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
- v_pline(atari_plot_vdi_handle, n+1, (short *)&pxy);
- }
-
- return ( true );
-}
-
-/***
- * Set plot origin and canvas size
- * \param x the x origin
- * \param y the y origin
- * \param w the width of the plot area
- * \param h the height of the plot area
- */
-bool plot_set_dimensions(int x, int y, int w, int h)
+/* exported interface documented in atari/plot.h */
+bool
+plot_set_dimensions(const struct redraw_context *ctx, int x, int y, int w, int h)
{
bool doupdate = false;
struct rect newclip = {0, 0, w, h};
GRECT absclip = {x, y, w, h};
if (!(w == view.w && h == view.h)) {
- view.w = (short)w;
- view.h = (short)h;
- doupdate = true;
+ view.w = (short)w;
+ view.h = (short)h;
+ doupdate = true;
}
if (!(x == view.x && y == view.y)) {
- view.x = (short)x;
- view.y = (short)y;
- doupdate = true;
+ view.x = (short)x;
+ view.y = (short)y;
+ doupdate = true;
}
if (doupdate==true)
- update_visible_rect();
+ update_visible_rect();
//dbg_rect("plot_set_dimensions", &newclip);
plot_set_abs_clipping(&absclip);
- plot_clip(&newclip);
+ ctx->plot->clip(ctx, &newclip);
return(true);
}
-/***
+
+/**
* Get current canvas size
- * \param dst the GRECT * which receives the canvas size
*
+ * \param dst the GRECT * which receives the canvas size
*/
bool plot_get_dimensions(GRECT *dst)
{
@@ -1946,6 +1843,7 @@ bool plot_get_dimensions(GRECT *dst)
return(true);
}
+
/**
* set scale of plotter.
* \param scale the new scale value
@@ -1961,6 +1859,7 @@ float plot_set_scale(float scale)
return(ret);
}
+
float plot_get_scale(void)
{
return(view.scale);
@@ -1968,10 +1867,9 @@ float plot_get_scale(void)
/**
- *
* Subsequent calls to plot_clip will be clipped by the absolute clip.
- * \param area the maximum clipping rectangle (absolute screen coords)
*
+ * \param area the maximum clipping rectangle (absolute screen coords)
*/
void plot_set_abs_clipping(const GRECT *area)
{
@@ -1980,21 +1878,20 @@ void plot_set_abs_clipping(const GRECT *area)
plot_get_dimensions(&canvas);
if(!rc_intersect(area, &canvas)){
- view.abs_clipping.x0 = 0;
- view.abs_clipping.x1 = 0;
- view.abs_clipping.y0 = 0;
- view.abs_clipping.y1 = 0;
- }
- else {
- view.abs_clipping.x0 = area->g_x;
- view.abs_clipping.x1 = area->g_x + area->g_w;
- view.abs_clipping.y0 = area->g_y;
- view.abs_clipping.y1 = area->g_y + area->g_h;
+ view.abs_clipping.x0 = 0;
+ view.abs_clipping.x1 = 0;
+ view.abs_clipping.y0 = 0;
+ view.abs_clipping.y1 = 0;
+ } else {
+ view.abs_clipping.x0 = area->g_x;
+ view.abs_clipping.x1 = area->g_x + area->g_w;
+ view.abs_clipping.y0 = area->g_y;
+ view.abs_clipping.y1 = area->g_y + area->g_h;
}
}
-/***
+/**
* Get the maximum clip extent, in absolute screen coords
* \param dst the structure that receives the absolute clipping
*/
@@ -2004,7 +1901,7 @@ void plot_get_abs_clipping(struct rect *dst)
}
-/***
+/**
* Get the maximum clip extent, in absolute screen coords
* \param dst the structure that receives the absolute clipping
*/
@@ -2016,7 +1913,64 @@ void plot_get_abs_clipping_grect(GRECT *dst)
dst->g_h = view.abs_clipping.y1 - view.abs_clipping.y0;
}
-bool plot_clip(const struct rect *clip)
+
+VdiHdl plot_get_vdi_handle(void)
+{
+ return(atari_plot_vdi_handle);
+}
+
+
+long plot_get_flags(void)
+{
+ return(atari_plot_flags);
+}
+
+
+bool plot_get_clip(struct rect * out)
+{
+ out->x0 = view.clipping.x0;
+ out->y0 = view.clipping.y0;
+ out->x1 = view.clipping.x1;
+ out->y1 = view.clipping.y1;
+ return( true );
+}
+
+
+void plot_get_clip_grect(GRECT * out)
+{
+ struct rect clip={0,0,0,0};
+
+ plot_get_clip(&clip);
+
+ out->g_x = clip.x0;
+ out->g_y = clip.y0;
+ out->g_w = clip.x1 - clip.x0;
+ out->g_h = clip.y1 - clip.y0;
+}
+
+
+FONT_PLOTTER plot_get_text_plotter()
+{
+ return(fplotter);
+}
+
+
+void plot_set_text_plotter(FONT_PLOTTER font_plotter)
+{
+ fplotter = font_plotter;
+}
+
+
+/**
+ * \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
+plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
GRECT canvas, screen, gclip, maxclip;
short pxy[4];
@@ -2041,14 +1995,14 @@ bool plot_clip(const struct rect *clip)
rc_intersect(&canvas, &gclip);
if(gclip.g_h < 0){
- gclip.g_h = 0;
+ gclip.g_h = 0;
}
if (!rc_intersect(&screen, &gclip)) {
- //dbg_rect("cliprect: ", &view.clipping);
- //dbg_grect("screen: ", &canvas);
- //dbg_grect("canvas clipped: ", &gclip);
- //assert(1 == 0);
+ //dbg_rect("cliprect: ", &view.clipping);
+ //dbg_grect("screen: ", &canvas);
+ //dbg_grect("canvas clipped: ", &gclip);
+ //assert(1 == 0);
}
// When setting VDI clipping, obey to maximum cliping rectangle:
@@ -2064,106 +2018,379 @@ bool plot_clip(const struct rect *clip)
vs_clip(atari_plot_vdi_handle, 1, (short*)&pxy);
- return ( true );
+ return NSERROR_OK;
}
-VdiHdl plot_get_vdi_handle(void)
-{
- return(atari_plot_vdi_handle);
-}
-long plot_get_flags(void)
+/**
+ * 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.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x, int y, int radius, int angle1, int angle2)
{
- return(atari_plot_flags);
+ vswr_mode(atari_plot_vdi_handle, MD_REPLACE);
+ if (pstyle->fill_type == PLOT_OP_TYPE_NONE) {
+ return NSERROR_OK;
+ }
+
+ if (pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ vsf_interior(atari_plot_vdi_handle, 1 );
+ v_arc(atari_plot_vdi_handle,
+ view.x + x,
+ view.y + y,
+ radius,
+ angle1 * 10,
+ angle2 * 10);
+ } else {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsl_width(atari_plot_vdi_handle, 1);
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ v_arc(atari_plot_vdi_handle,
+ view.x + x,
+ view.y + y, radius,
+ angle1 * 10,
+ angle2 * 10);
+ }
+
+ return NSERROR_OK;
}
-bool plot_get_clip(struct rect * out)
+/**
+ * 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x, int y, int radius)
{
- out->x0 = view.clipping.x0;
- out->y0 = view.clipping.y0;
- out->x1 = view.clipping.x1;
- out->y1 = view.clipping.y1;
- return( true );
+ if (pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 1);
+ vsf_interior(atari_plot_vdi_handle, 0);
+ v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
+ } else {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 0);
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+ v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
+ }
+ return NSERROR_OK;
}
-void plot_get_clip_grect(GRECT * out)
+
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_line(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *line)
{
- struct rect clip={0,0,0,0};
+ short pxy[4];
+ uint32_t lt;
+ int sw = pstyle->stroke_width;
- plot_get_clip(&clip);
+ if (((line->x0 < 0) && (line->x1 < 0)) ||
+ ((line->y0 < 0) && (line->y1 < 0))) {
+ return NSERROR_OK;
+ }
- out->g_x = clip.x0;
- out->g_y = clip.y0;
- out->g_w = clip.x1 - clip.x0;
- out->g_h = clip.y1 - clip.y0;
-}
+ pxy[0] = view.x + MAX(0, line->x0);
+ pxy[1] = view.y + MAX(0, line->y0);
+ pxy[2] = view.x + MAX(0, line->x1);
+ pxy[3] = view.y + MAX(0, line->y1);
-FONT_PLOTTER plot_get_text_plotter()
-{
- return(fplotter);
-}
+ if ((line->y0 > view.h-1) && (line->y1 > view.h-1)) {
+ return NSERROR_OK;
+ }
-void plot_set_text_plotter(FONT_PLOTTER font_plotter)
-{
- fplotter = font_plotter;
-}
+ //printf("view: %d,%d,%d,%d\n", view.x, view.y, view.w, view.h);
+ //printf("line: %d,%d,%d,%d\n", x0, y0, x1, y1);
-static bool plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle )
-{
- if (view.scale != 1.0) {
- plot_font_style_t newstyle = *fstyle;
- newstyle.size = (int)((float)fstyle->size*view.scale);
- fplotter->text(fplotter, x, y, text, length, &newstyle);
- } else {
- fplotter->text(fplotter, x, y, text, length, fstyle);
+ //plot_vdi_clip(true);
+
+ if (sw == 0) {
+ sw = 1;
}
+ NSLT2VDI(lt, pstyle)
+ vsl_type(atari_plot_vdi_handle, (lt&0x0F));
+ /* if the line style is not available within VDI system,define own style: */
+ if ((lt&0x0F) == 7 ) {
+ vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
+ }
+ vsl_width(atari_plot_vdi_handle, (short)sw);
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy );
+ //plot_vdi_clip(false);
- return ( true );
+ return NSERROR_OK;
}
-static bool plot_disc(int x, int y, int radius, const plot_style_t *pstyle)
+
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *rect)
{
- if (pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
- vsf_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
- vsf_perimeter(atari_plot_vdi_handle, 1);
- vsf_interior(atari_plot_vdi_handle, 0);
- v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
- } else {
- vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
- vsf_perimeter(atari_plot_vdi_handle, 0);
- vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
- v_circle(atari_plot_vdi_handle, view.x + x, view.y + y, radius);
+ short pxy[4];
+ GRECT r, rclip, sclip;
+ int sw = pstyle->stroke_width;
+ uint32_t lt;
+
+ /* current canvas clip: */
+ rclip.g_x = view.clipping.x0;
+ rclip.g_y = view.clipping.y0;
+ rclip.g_w = view.clipping.x1 - view.clipping.x0;
+ rclip.g_h = view.clipping.y1 - view.clipping.y0;
+
+ /* physical clipping: */
+ sclip.g_x = rclip.g_x;
+ sclip.g_y = rclip.g_y;
+ sclip.g_w = view.vis_w;
+ sclip.g_h = view.vis_h;
+
+ rc_intersect(&sclip, &rclip);
+ r.g_x = rect->x0;
+ r.g_y = rect->y0;
+ r.g_w = rect->x1 - rect->x0;
+ r.g_h = rect->y1 - rect->y0;
+
+ if (!rc_intersect(&rclip, &r)) {
+ return NSERROR_OK;
}
- return(true);
+ if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) {
+ /*
+ manually draw the line, because we do not need vdi clipping
+ for vertical / horizontal line draws.
+ */
+ if (sw == 0)
+ sw = 1;
+
+ NSLT2VDI(lt, pstyle);
+ vsl_type(atari_plot_vdi_handle, (lt&0x0F));
+ /*
+ if the line style is not available within VDI system,
+ define own style:
+ */
+ if ((lt&0x0F) == 7 ) {
+ vsl_udsty(atari_plot_vdi_handle, ((lt&0xFFFF00) >> 8));
+ }
+ vsl_width(atari_plot_vdi_handle, (short)sw );
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ /* top border: */
+ if (r.g_y == rect->y0) {
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y ;
+ pxy[2] = view.x + r.g_x + r.g_w;
+ pxy[3] = view.y + r.g_y;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* right border: */
+ if (r.g_x + r.g_w == rect->x1 ) {
+ pxy[0] = view.x + r.g_x + r.g_w;
+ pxy[1] = view.y + r.g_y;
+ pxy[2] = view.x + r.g_x + r.g_w;
+ pxy[3] = view.y + r.g_y + r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* bottom border: */
+ if ( r.g_y+r.g_h == rect->y1 ) {
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y+r.g_h;
+ pxy[2] = view.x + r.g_x+r.g_w;
+ pxy[3] = view.y + r.g_y+r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+
+ /* left border: */
+ if ( r.g_x == rect->x0 ) {
+ pxy[0] = view.x + r.g_x;
+ pxy[1] = view.y + r.g_y;
+ pxy[2] = view.x + r.g_x;
+ pxy[3] = view.y + r.g_y + r.g_h;
+ v_pline(atari_plot_vdi_handle, 2, (short *)&pxy);
+ }
+ }
+
+ if (pstyle->fill_type != PLOT_OP_TYPE_NONE ) {
+ short stroke_width = (short)(pstyle->stroke_type != PLOT_OP_TYPE_NONE) ?
+ pstyle->stroke_width : 0;
+
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ vsf_perimeter(atari_plot_vdi_handle, 0);
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+
+
+ pxy[0] = view.x + r.g_x + stroke_width;
+ pxy[1] = view.y + r.g_y + stroke_width;
+ pxy[2] = view.x + r.g_x + r.g_w -1 - stroke_width;
+ pxy[3] = view.y + r.g_y + r.g_h -1 - stroke_width;
+
+ vsf_style(atari_plot_vdi_handle, 1);
+ v_bar(atari_plot_vdi_handle, (short*)&pxy);
+ }
+
+ return NSERROR_OK;
}
-static bool plot_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *pstyle)
+
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const int *p,
+ unsigned int n)
{
+ short pxy[n*2];
+ unsigned int i = 0;
- vswr_mode(atari_plot_vdi_handle, MD_REPLACE );
- if (pstyle->fill_type == PLOT_OP_TYPE_NONE)
- return(true);
- if ( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
- vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
- vsf_perimeter(atari_plot_vdi_handle, 1);
- vsf_interior(atari_plot_vdi_handle, 1 );
- v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10);
+ if (vdi_sysinfo.maxpolycoords > 0)
+ assert( (signed int)n < vdi_sysinfo.maxpolycoords);
+
+ vsf_interior(atari_plot_vdi_handle, FIS_SOLID);
+ vsf_style(atari_plot_vdi_handle, 1);
+ for (i = 0; i<n*2; i=i+2) {
+ pxy[i] = (short)view.x+p[i];
+ pxy[i+1] = (short)view.y+p[i+1];
+ }
+
+ if (pstyle->fill_type == PLOT_OP_TYPE_SOLID) {
+ vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
+ v_fillarea(atari_plot_vdi_handle, n, (short*)&pxy);
} else {
- vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
- vsl_width(atari_plot_vdi_handle, 1 );
- vsf_perimeter(atari_plot_vdi_handle, 1);
- v_arc(atari_plot_vdi_handle, view.x + x, view.y + y, radius, angle1*10, angle2*10);
+ pxy[n*2]=pxy[0];
+ pxy[n*2+1]=pxy[1];
+ vsl_rgbcolor(atari_plot_vdi_handle, pstyle->stroke_colour);
+ v_pline(atari_plot_vdi_handle, n+1, (short *)&pxy);
}
- return (true);
+ return NSERROR_OK;
}
-static bool plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+
+/**
+ * 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
+plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
+{
+ /** \todo Implement atari path plot */
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
struct bitmap * bm = NULL;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
@@ -2175,78 +2402,109 @@ static bool plot_bitmap(int x, int y, int width, int height,
bmph = atari_bitmap_get_height(bitmap);
if(view.scale != 1.0){
- width = (int)(((float)width)*view.scale);
- height = (int)(((float)height)*view.scale);
+ width = (int)(((float)width)*view.scale);
+ height = (int)(((float)height)*view.scale);
}
if ( repeat_x || repeat_y ) {
- plot_get_clip(&clip);
- if( repeat_x && width == 1 && repeat_y && height == 1 ) {
- width = MAX( width, clip.x1 - x );
- height = MAX( height, clip.y1 - y );
- } else if( repeat_x && width == 1 ) {
- width = MAX( width, clip.x1 - x);
- } else if( repeat_y && height == 1) {
- height = MAX( height, clip.y1 - y );
- }
- }
-
- if( width != bmpw || height != bmph ) {
- atari_bitmap_resize(bitmap, hermes_res_h, &nsfmt, width, height );
- if( bitmap->resized )
- bm = bitmap->resized;
- else
- bm = bitmap;
+ plot_get_clip(&clip);
+ if (repeat_x && width == 1 && repeat_y && height == 1 ) {
+ width = MAX( width, clip.x1 - x );
+ height = MAX( height, clip.y1 - y );
+ } else if (repeat_x && width == 1 ) {
+ width = MAX( width, clip.x1 - x);
+ } else if (repeat_y && height == 1) {
+ height = MAX( height, clip.y1 - y );
+ }
+ }
+
+ if (width != bmpw || height != bmph) {
+ atari_bitmap_resize(bitmap, hermes_res_h, &nsfmt, width, height );
+ if (bitmap->resized) {
+ bm = bitmap->resized;
+ } else {
+ bm = bitmap;
+ }
} else {
- bm = bitmap;
+ bm = bitmap;
}
/* out of memory? */
- if( bm == NULL ) {
- printf("plot: out of memory! bmp: %p, bmpres: %p\n", bitmap, bitmap->resized );
- return( true );
+ if (bm == NULL) {
+ printf("plot: out of memory! bmp: %p, bmpres: %p\n",
+ bitmap, bitmap->resized );
+ return NSERROR_NOMEM;
}
if (!(repeat_x || repeat_y) ) {
- plot_blit_bitmap(bm, x, y, bg, flags );
+ plot_blit_bitmap(bm, x, y, bg, flags);
} else {
- int xf,yf;
- int xoff = x;
- int yoff = y;
-
- if (yoff > clip.y0 )
- yoff = (clip.y0 - height) + ((yoff - clip.y0) % height);
- if (xoff > clip.x0 )
- xoff = (clip.x0 - width) + ((xoff - clip.x0) % width);
- /* for now, repeating just works in the rigth / down direction */
- /*
- if( repeat_x == true )
- xoff = clip.x0;
- if(repeat_y == true )
- yoff = clip.y0;
- */
-
- for( xf = xoff; xf < clip.x1; xf += width ) {
- for( yf = yoff; yf < clip.y1; yf += height ) {
- plot_blit_bitmap(bm, xf, yf, bg, flags );
- if (!repeat_y)
- break;
- }
- if (!repeat_x)
- break;
- }
- }
- return ( true );
+ int xf,yf;
+ int xoff = x;
+ int yoff = y;
+
+ if (yoff > clip.y0) {
+ yoff = (clip.y0 - height) + ((yoff - clip.y0) % height);
+ }
+ if (xoff > clip.x0) {
+ xoff = (clip.x0 - width) + ((xoff - clip.x0) % width);
+ }
+ /* for now, repeating just works in the rigth / down direction */
+ /*
+ if( repeat_x == true )
+ xoff = clip.x0;
+ if(repeat_y == true )
+ yoff = clip.y0;
+ */
+
+ for (xf = xoff; xf < clip.x1; xf += width ) {
+ for (yf = yoff; yf < clip.y1; yf += height ) {
+ plot_blit_bitmap(bm, xf, yf, bg, flags );
+ if (!repeat_y) {
+ break;
+ }
+ }
+ if (!repeat_x) {
+ break;
+ }
+ }
+ }
+
+ return NSERROR_OK;
}
-static bool plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
-{
- return ( true );
-}
+/**
+ * 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
+plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ if (view.scale != 1.0) {
+ plot_font_style_t newstyle = *fstyle;
+ newstyle.size = (int)((float)fstyle->size*view.scale);
+ fplotter->text(fplotter, x, y, text, length, &newstyle);
+ } else {
+ fplotter->text(fplotter, x, y, text, length, fstyle);
+ }
+ return NSERROR_OK;
+}
+/** atari plottr operation table */
const struct plotter_table atari_plotters = {
.rectangle = plot_rectangle,
.line = plot_line,
diff --git a/frontends/atari/plot/plot.h b/frontends/atari/plot/plot.h
index fd73a8c..c8bf915 100644
--- a/frontends/atari/plot/plot.h
+++ b/frontends/atari/plot/plot.h
@@ -55,6 +55,7 @@
#define ERR_PLOTTER_NOT_AVAILABLE 3 /* invalid plotter driver name passed */
struct plot_style_s;
+struct redraw_context;
struct s_vdi_sysinfo {
short vdi_handle; /**< vdi handle */
@@ -83,7 +84,15 @@ struct rect;
extern const struct plotter_table atari_plotters;
-int plot_init(char *);
+/**
+ * Init screen and font driver objects.
+ *
+ * \param fdrvrname font driver name.
+ * \return value > 1 when the objects could be succesfully created or
+ * <= 0 to indicate an error.
+ */
+int plot_init(const struct redraw_context *ctx, char *fdrvrname);
+
int plot_finalise(void);
/**
@@ -93,7 +102,15 @@ const char* plot_err_str(int i) ;
bool plot_lock(void);
bool plot_unlock(void);
-bool plot_set_dimensions( int x, int y, int w, int h );
+
+/**
+ * Set plot origin and canvas size
+ * \param x the x origin
+ * \param y the y origin
+ * \param w the width of the plot area
+ * \param h the height of the plot area
+ */
+bool plot_set_dimensions(const struct redraw_context *ctx, int x, int y, int w, int h );
bool plot_get_dimensions(GRECT *dst);
float plot_get_scale(void);
float plot_set_scale(float);
@@ -101,13 +118,10 @@ void plot_set_abs_clipping(const GRECT *area);
void plot_get_abs_clipping(struct rect *dst);
void plot_get_abs_clipping_grect(GRECT *dst);
bool plot_get_clip(struct rect * out);
-/* Get clipping for current framebuffer as GRECT */
+/** Get clipping for current framebuffer as GRECT */
void plot_get_clip_grect(GRECT * out);
-bool plot_clip(const struct rect *clip);
VdiHdl plot_get_vdi_handle(void);
long plot_get_flags(void);
-bool plot_rectangle( int x0, int y0, int x1, int y1,const struct plot_style_s *style );
-bool plot_line( int x0, int y0, int x1, int y1, const struct plot_style_s *style );
bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
unsigned long bg, unsigned long flags);
bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor, uint32_t flags);
diff --git a/frontends/atari/rootwin.c b/frontends/atari/rootwin.c
index aa8e080..0b77cbb 100644
--- a/frontends/atari/rootwin.c
+++ b/frontends/atari/rootwin.c
@@ -758,8 +758,11 @@ void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
xoff = ((work.g_w-work.g_h)/2);
work.g_w = work.g_h;
}
- plot_set_dimensions( work.g_x+xoff, work.g_y, work.g_w,
- work.g_h);
+ plot_set_dimensions(&rootwin_rdrw_ctx,
+ work.g_x+xoff,
+ work.g_y,
+ work.g_w,
+ work.g_h);
wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
while (visible.g_h > 0 && visible.g_w > 0) {
@@ -776,8 +779,14 @@ void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
vs_clip(plot_vdi_handle, 1, (short*)&pxy);
//dbg_pxy("vdi clip", (short*)&pxy);
- atari_plotters.bitmap(0, 0, work.g_w, work.g_h,
- rootwin->icon, 0xffffff, 0);
+ rootwin_rdrw_ctx.plot->bitmap(&rootwin_rdrw_ctx,
+ rootwin->icon,
+ 0,
+ 0,
+ work.g_w,
+ work.g_h,
+ 0xffffff,
+ 0);
} else {
//dbg_grect("redraw vis area outside", &visible);
}
@@ -822,7 +831,8 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
//dbg_grect("browser redraw, content area", content_area);
//dbg_grect("browser redraw, content clip", clip);
- plot_set_dimensions(content_area->g_x, content_area->g_y,
+ plot_set_dimensions(&rootwin_rdrw_ctx,
+ content_area->g_x, content_area->g_y,
content_area->g_w, content_area->g_h);
oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw));
@@ -849,7 +859,7 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w;
redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h;
- plot_clip(&redraw_area);
+ rootwin_rdrw_ctx.plot->clip(&rootwin_rdrw_ctx, &redraw_area);
//dbg_rect("rdrw area", &redraw_area);
diff --git a/frontends/atari/toolbar.c b/frontends/atari/toolbar.c
index 9ed8784..1b93717 100644
--- a/frontends/atari/toolbar.c
+++ b/frontends/atari/toolbar.c
@@ -435,7 +435,7 @@ void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
if (rc_intersect(clip, &area)) {
float old_scale;
- plot_set_dimensions(area_ro.g_x, area_ro.g_y, area_ro.g_w, area_ro.g_h);
+ plot_set_dimensions(&toolbar_rdrw_ctx, area_ro.g_x, area_ro.g_y, area_ro.g_w, area_ro.g_h);
struct rect r = {
.x0 = MAX(0,area.g_x - area_ro.g_x),
.y0 = MAX(0,area.g_y - area_ro.g_y),
diff --git a/frontends/atari/treeview.c b/frontends/atari/treeview.c
index 93aef6e..8e9834e 100644
--- a/frontends/atari/treeview.c
+++ b/frontends/atari/treeview.c
@@ -223,7 +223,11 @@ void atari_treeview_redraw(struct core_window *cw)
.background_images = true,
.plot = &atari_plotters
};
- plot_set_dimensions(work.g_x, work.g_y, work.g_w, work.g_h);
+ plot_set_dimensions(&ctx,
+ work.g_x,
+ work.g_y,
+ work.g_w,
+ work.g_h);
if (plot_lock() == false)
return;
diff --git a/frontends/beos/plotters.cpp b/frontends/beos/plotters.cpp
index 5ba3fbb..6544d63 100644
--- a/frontends/beos/plotters.cpp
+++ b/frontends/beos/plotters.cpp
@@ -18,7 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Target independent plotting (BeOS/Haiku implementation).
*/
@@ -50,581 +51,753 @@ extern "C" {
* the right-bottom pixel is actually part of the BRect!
*/
-static bool nsbeos_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool nsbeos_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool nsbeos_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
-static bool nsbeos_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6]);
-static bool nsbeos_plot_clip(const struct rect *ns_clip);
-static bool nsbeos_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool nsbeos_plot_disc(int x, int y, int radius, const plot_style_t *style);
-static bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *style);
-static bool nsbeos_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
-
-
#warning make patterns nicer
-static const pattern kDottedPattern = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
-static const pattern kDashedPattern = { 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33 };
-
-static const rgb_color kBlackColor = { 0, 0, 0, 255 };
-
-struct plotter_table plot;
+static const pattern kDottedPattern = {
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa
+};
+static const pattern kDashedPattern = {
+ 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33
+};
-const struct plotter_table nsbeos_plotters = {
- nsbeos_plot_clip,
- nsbeos_plot_arc,
- nsbeos_plot_disc,
- nsbeos_plot_line,
- nsbeos_plot_rectangle,
- nsbeos_plot_polygon,
- nsbeos_plot_path,
- nsbeos_plot_bitmap,
- nsbeos_plot_text,
- NULL, // Group Start
- NULL, // Group End
- NULL, // Flush
- true // option_knockout
+static const rgb_color kBlackColor = {
+ 0, 0, 0, 255
};
+//struct plotter_table plot;
// #pragma mark - implementation
-
BView *nsbeos_current_gc(void)
{
- return current_view;
+ return current_view;
}
+
BView *nsbeos_current_gc_lock(void)
{
- BView *view = current_view;
- if (view && view->LockLooper())
- return view;
- return NULL;
+ BView *view = current_view;
+ if (view && view->LockLooper())
+ return view;
+ return NULL;
}
+
void nsbeos_current_gc_unlock(void)
{
- if (current_view)
- current_view->UnlockLooper();
+ if (current_view) {
+ current_view->UnlockLooper();
+ }
}
+
void nsbeos_current_gc_set(BView *view)
{
- // XXX: (un)lock previous ?
- current_view = view;
+ // XXX: (un)lock previous ?
+ current_view = view;
}
-bool nsbeos_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+
+static nserror
+nsbeos_plot_bbitmap(int x, int y, int width, int height, BBitmap *b, colour bg)
{
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- BView *view;
+ /* XXX: This currently ignores the background colour supplied.
+ * Does this matter?
+ */
+
+ if (width == 0 || height == 0) {
+ return NSERROR_OK;
+ }
+
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
+
+ drawing_mode oldmode = view->DrawingMode();
+ source_alpha alpha;
+ alpha_function func;
+ view->GetBlendingMode(&alpha, &func);
+ //view->SetDrawingMode(B_OP_OVER);
+ view->SetDrawingMode(B_OP_ALPHA);
+ view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
+
+ // XXX DrawBitmap() resamples if rect doesn't match,
+ // but doesn't do any filtering
+ // XXX: use Zeta API if available ?
+
+ BRect rect(x, y, x + width - 1, y + height - 1);
+ /*
+ rgb_color old = view->LowColor();
+ if (bg != NS_TRANSPARENT) {
+ view->SetLowColor(nsbeos_rgb_colour(bg));
+ view->FillRect(rect, B_SOLID_LOW);
+ }
+ */
+ view->DrawBitmap(b, rect);
+ // maybe not needed?
+ //view->SetLowColor(old);
+ view->SetBlendingMode(alpha, func);
+ view->SetDrawingMode(oldmode);
+
+ //nsbeos_current_gc_unlock();
+
+ return NSERROR_OK;
+}
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
- nsbeos_set_colour(style->fill_colour);
+static BPoint transform_pt(float x, float y, const float transform[6])
+{
+#warning XXX: verify
+ //return BPoint(x, y);
+ BPoint pt;
+ pt.x = x * transform[0] + y * transform[1] + transform[4];
+ pt.y = x * transform[2] + y * transform[3] + transform[5];
+ /*
+ printf("TR: {%f, %f} { %f, %f, %f, %f, %f, %f} = { %f, %f }\n",
+ x, y,
+ transform[0], transform[1], transform[2],
+ transform[3], transform[4], transform[5],
+ pt.x, pt.y);
+ */
+ return pt;
+}
- BRect rect(x0, y0, x1 - 1, y1 - 1);
- view->FillRect(rect);
- //nsbeos_current_gc_unlock();
+rgb_color nsbeos_rgb_colour(colour c)
+{
+ rgb_color color;
+ if (c == NS_TRANSPARENT)
+ return B_TRANSPARENT_32_BIT;
+ color.red = c & 0x0000ff;
+ color.green = (c & 0x00ff00) >> 8;
+ color.blue = (c & 0xff0000) >> 16;
+ return color;
+}
- }
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- pattern pat;
- BView *view;
+void nsbeos_set_colour(colour c)
+{
+ rgb_color color = nsbeos_rgb_colour(c);
+ BView *view = nsbeos_current_gc();
+ view->SetHighColor(color);
+}
- switch (style->stroke_type) {
- case PLOT_OP_TYPE_SOLID: /**< Solid colour */
- default:
- pat = B_SOLID_HIGH;
- break;
- case PLOT_OP_TYPE_DOT: /**< Doted plot */
- pat = kDottedPattern;
- break;
+/**
+ * Plot a caret.
+ *
+ * It is assumed that the plotters have been set up.
+ */
+void nsbeos_plot_caret(int x, int y, int h)
+{
+ BView *view;
- case PLOT_OP_TYPE_DASH: /**< dashed plot */
- pat = kDashedPattern;
- break;
- }
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL)
+ /* TODO: report an error here */
+ return;
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
+ BPoint start(x, y);
+ BPoint end(x, y + h - 1);
+#if defined(__HAIKU__) || defined(B_BEOS_VERSION_DANO)
+ view->SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
+#else
+ view->SetHighColor(kBlackColor);
+#endif
+ view->StrokeLine(start, end);
- nsbeos_set_colour(style->stroke_colour);
+ //nsbeos_current_gc_unlock();
+}
- float pensize = view->PenSize();
- view->SetPenSize(style->stroke_width);
- BRect rect(x0, y0, x1, y1);
- view->StrokeRect(rect, pat);
+/**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param ns_clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_clip(const struct redraw_context *ctx, const struct rect *ns_clip)
+{
+ BView *view;
+ //fprintf(stderr, "%s(%d, %d, %d, %d)\n", __FUNCTION__, clip_x0, clip_y0, clip_x1, clip_y1);
- view->SetPenSize(pensize);
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
- //nsbeos_current_gc_unlock();
+ BRect rect(ns_clip->x0, ns_clip->y0, ns_clip->x1 - 1, ns_clip->y1 - 1);
+ BRegion clip(rect);
+ view->ConstrainClippingRegion(NULL);
+ if (view->Bounds() != rect) {
+ view->ConstrainClippingRegion(&clip);
+ }
- }
+ //nsbeos_current_gc_unlock();
- return true;
+ return NSERROR_OK;
}
-
-bool nsbeos_plot_line(int x0, int y0, int x1, int y1, 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.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
- pattern pat;
- BView *view;
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
- switch (style->stroke_type) {
- case PLOT_OP_TYPE_SOLID: /**< Solid colour */
- default:
- pat = B_SOLID_HIGH;
- break;
+ nsbeos_set_colour(style->fill_colour);
- case PLOT_OP_TYPE_DOT: /**< Doted plot */
- pat = kDottedPattern;
- break;
+ BPoint center(x, y);
+ float angle = angle1; // in degree
+ float span = angle2 - angle1; // in degree
+ view->StrokeArc(center, radius, radius, angle, span);
- case PLOT_OP_TYPE_DASH: /**< dashed plot */
- pat = kDashedPattern;
- break;
- }
+ //nsbeos_current_gc_unlock();
+
+ return NSERROR_OK;
+}
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
- nsbeos_set_colour(style->stroke_colour);
+/**
+ * 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ BView *view;
- float pensize = view->PenSize();
- view->SetPenSize(style->stroke_width);
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
- BPoint start(x0, y0);
- BPoint end(x1, y1);
- view->StrokeLine(start, end, pat);
+ nsbeos_set_colour(style->fill_colour);
- view->SetPenSize(pensize);
+ BPoint center(x, y);
+ if (style->fill_type != PLOT_OP_TYPE_NONE)
+ view->FillEllipse(center, radius, radius);
+ else
+ view->StrokeEllipse(center, radius, radius);
- //nsbeos_current_gc_unlock();
+ //nsbeos_current_gc_unlock();
- return true;
+ return NSERROR_OK;
}
-bool nsbeos_plot_polygon(const int *p, unsigned int n, 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
- unsigned int i;
- BView *view;
+ pattern pat;
+ BView *view;
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
+ switch (style->stroke_type) {
+ case PLOT_OP_TYPE_SOLID: /**< Solid colour */
+ default:
+ pat = B_SOLID_HIGH;
+ break;
- nsbeos_set_colour(style->fill_colour);
+ case PLOT_OP_TYPE_DOT: /**< Doted plot */
+ pat = kDottedPattern;
+ break;
- BPoint points[n];
-
- for (i = 0; i < n; i++) {
- points[i] = BPoint(p[2 * i] - 0.5, p[2 * i + 1] - 0.5);
- }
+ case PLOT_OP_TYPE_DASH: /**< dashed plot */
+ pat = kDashedPattern;
+ break;
+ }
- if (style->fill_colour == NS_TRANSPARENT)
- view->StrokePolygon(points, (int32)n);
- else
- view->FillPolygon(points, (int32)n);
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_OK;
+ }
- return true;
-}
+ nsbeos_set_colour(style->stroke_colour);
+ float pensize = view->PenSize();
+ view->SetPenSize(style->stroke_width);
+ BPoint start(line->x0, line->y0);
+ BPoint end(line->x1, line->y1);
+ view->StrokeLine(start, end, pat);
+ view->SetPenSize(pensize);
-bool nsbeos_plot_clip(const struct rect *ns_clip)
-{
- BView *view;
- //fprintf(stderr, "%s(%d, %d, %d, %d)\n", __FUNCTION__, clip_x0, clip_y0, clip_x1, clip_y1);
-
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
-
- BRect rect(ns_clip->x0, ns_clip->y0, ns_clip->x1 - 1,
- ns_clip->y1 - 1);
- BRegion clip(rect);
- view->ConstrainClippingRegion(NULL);
- if (view->Bounds() != rect)
- view->ConstrainClippingRegion(&clip);
-
-
- //nsbeos_current_gc_unlock();
-
- return true;
+ //nsbeos_current_gc_unlock();
+
+ return NSERROR_OK;
}
-bool nsbeos_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
- return nsfont_paint(fstyle, text, length, x, y);
-}
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ BView *view;
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
-bool nsbeos_plot_disc(int x, int y, int radius, const plot_style_t *style)
-{
- BView *view;
+ nsbeos_set_colour(style->fill_colour);
+
+ BRect rect(rect->x0, rect->y0, rect->x1 - 1, rect->y1 - 1);
+ view->FillRect(rect);
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
+ //nsbeos_current_gc_unlock();
+ }
- nsbeos_set_colour(style->fill_colour);
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ pattern pat;
+ BView *view;
+
+ switch (style->stroke_type) {
+ case PLOT_OP_TYPE_SOLID: /**< Solid colour */
+ default:
+ pat = B_SOLID_HIGH;
+ break;
- BPoint center(x, y);
- if (style->fill_type != PLOT_OP_TYPE_NONE)
- view->FillEllipse(center, radius, radius);
- else
- view->StrokeEllipse(center, radius, radius);
+ case PLOT_OP_TYPE_DOT: /**< Doted plot */
+ pat = kDottedPattern;
+ break;
+
+ case PLOT_OP_TYPE_DASH: /**< dashed plot */
+ pat = kDashedPattern;
+ break;
+ }
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
- //nsbeos_current_gc_unlock();
+ nsbeos_set_colour(style->stroke_colour);
- return true;
+ float pensize = view->PenSize();
+ view->SetPenSize(style->stroke_width);
+
+ BRect rect(rect->x0, rect->y0, rect->x1, rect->y1);
+ view->StrokeRect(rect, pat);
+
+ view->SetPenSize(pensize);
+
+ //nsbeos_current_gc_unlock();
+ }
+
+ return NSERROR_OK;
}
-bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
+
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
- BView *view;
+ unsigned int i;
+ BView *view;
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
- nsbeos_set_colour(style->fill_colour);
+ nsbeos_set_colour(style->fill_colour);
- BPoint center(x, y);
- float angle = angle1; // in degree
- float span = angle2 - angle1; // in degree
- view->StrokeArc(center, radius, radius, angle, span);
+ BPoint points[n];
- //nsbeos_current_gc_unlock();
+ for (i = 0; i < n; i++) {
+ points[i] = BPoint(p[2 * i] - 0.5, p[2 * i + 1] - 0.5);
+ }
- return true;
+ if (style->fill_colour == NS_TRANSPARENT) {
+ view->StrokePolygon(points, (int32)n);
+ } else {
+ view->FillPolygon(points, (int32)n);
+ }
+
+ return NSERROR_OK;
}
-static bool nsbeos_plot_bbitmap(int x, int y, int width, int height,
- BBitmap *b, colour bg)
+
+/**
+ * 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
+nsbeos_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
- /* XXX: This currently ignores the background colour supplied.
- * Does this matter?
- */
-
- if (width == 0 || height == 0)
- return true;
-
- BView *view;
-
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
-
- drawing_mode oldmode = view->DrawingMode();
- source_alpha alpha;
- alpha_function func;
- view->GetBlendingMode(&alpha, &func);
- //view->SetDrawingMode(B_OP_OVER);
- view->SetDrawingMode(B_OP_ALPHA);
- view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
-
- // XXX DrawBitmap() resamples if rect doesn't match,
- // but doesn't do any filtering
- // XXX: use Zeta API if available ?
-
- BRect rect(x, y, x + width - 1, y + height - 1);
- /*
- rgb_color old = view->LowColor();
- if (bg != NS_TRANSPARENT) {
- view->SetLowColor(nsbeos_rgb_colour(bg));
- view->FillRect(rect, B_SOLID_LOW);
- }
- */
- view->DrawBitmap(b, rect);
- // maybe not needed?
- //view->SetLowColor(old);
- view->SetBlendingMode(alpha, func);
- view->SetDrawingMode(oldmode);
-
- //nsbeos_current_gc_unlock();
-
- return true;
+ unsigned int i;
+ BShape shape;
+
+ if (n == 0) {
+ return NSERROR_OK;
+ }
+
+ if (p[0] != PLOTTER_PATH_MOVE) {
+ LOG("path doesn't start with a move");
+ return NSERROR_INVALID;
+ }
+
+ for (i = 0; i < n; ) {
+ if (p[i] == PLOTTER_PATH_MOVE) {
+ BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
+ shape.MoveTo(pt);
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_CLOSE) {
+ shape.Close();
+ i++;
+ } else if (p[i] == PLOTTER_PATH_LINE) {
+ BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
+ shape.LineTo(pt);
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_BEZIER) {
+ BPoint pt[3] = {
+ transform_pt(p[i + 1], p[i + 2], transform),
+ transform_pt(p[i + 3], p[i + 4], transform),
+ transform_pt(p[i + 5], p[i + 6], transform)
+ };
+ shape.BezierTo(pt);
+ i += 7;
+ } else {
+ LOG("bad path command %f", p[i]);
+ return NSERROR_INVALID;
+ }
+ }
+ shape.Close();
+
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ rgb_color old_high = view->HighColor();
+ float old_pen = view->PenSize();
+ view->SetPenSize(width);
+ view->MovePenTo(0, 0);
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ view->SetHighColor(nsbeos_rgb_colour(pstyle->fill_colour));
+ view->FillShape(&shape);
+ }
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ view->SetHighColor(nsbeos_rgb_colour(pstyle->stroke_colour));
+ view->StrokeShape(&shape);
+ }
+ // restore
+ view->SetPenSize(old_pen);
+ view->SetHighColor(old_high);
+
+ //nsbeos_current_gc_unlock();
+
+ return NSERROR_OK;
}
-bool nsbeos_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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsbeos_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;
- BBitmap *primary;
- BBitmap *pretiled;
+ int doneheight = 0, donewidth = 0;
+ BBitmap *primary;
+ BBitmap *pretiled;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
bool repeat_y = (flags & BITMAPF_REPEAT_Y);
- if (!(repeat_x || repeat_y)) {
- /* Not repeating at all, so just plot it */
+ if (!(repeat_x || repeat_y)) {
+ /* Not repeating at all, so just plot it */
primary = nsbeos_bitmap_get_primary(bitmap);
return nsbeos_plot_bbitmap(x, y, width, height, primary, bg);
- }
-
- if (repeat_x && !repeat_y)
- pretiled = nsbeos_bitmap_get_pretile_x(bitmap);
- if (repeat_x && repeat_y)
- pretiled = nsbeos_bitmap_get_pretile_xy(bitmap);
- if (!repeat_x && repeat_y)
- pretiled = nsbeos_bitmap_get_pretile_y(bitmap);
- primary = nsbeos_bitmap_get_primary(bitmap);
-
- /* use the primary and pretiled widths to scale the w/h provided */
- width *= pretiled->Bounds().Width() + 1;
- width /= primary->Bounds().Width() + 1;
- height *= pretiled->Bounds().Height() + 1;
- height /= primary->Bounds().Height() + 1;
-
- BView *view;
-
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL) {
- beos_warn_user("No GC", 0);
- return false;
- }
-
- // XXX: do we really need to use clipping reg ?
- // I guess it's faster to not draw clipped out stuff...
-
- BRect cliprect;
- BRegion clipreg;
- view->GetClippingRegion(&clipreg);
- cliprect = clipreg.Frame();
-
- //XXX: FIXME
-
- if (y > cliprect.top)
- doneheight = ((int)cliprect.top - height) + ((y - (int)cliprect.top) % height);
- else
- doneheight = y;
-
- while (doneheight < ((int)cliprect.bottom)) {
- if (x > cliprect.left)
- donewidth = ((int)cliprect.left - width) + ((x - (int)cliprect.left) % width);
- else
- donewidth = x;
- while (donewidth < (cliprect.right)) {
- nsbeos_plot_bbitmap(donewidth, doneheight,
- width, height, pretiled, bg);
- donewidth += width;
- if (!repeat_x) break;
- }
- doneheight += height;
- if (!repeat_y) break;
- }
+ }
+
+ if (repeat_x && !repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_x(bitmap);
+ if (repeat_x && repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_xy(bitmap);
+ if (!repeat_x && repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_y(bitmap);
+ primary = nsbeos_bitmap_get_primary(bitmap);
+
+ /* use the primary and pretiled widths to scale the w/h provided */
+ width *= pretiled->Bounds().Width() + 1;
+ width /= primary->Bounds().Width() + 1;
+ height *= pretiled->Bounds().Height() + 1;
+ height /= primary->Bounds().Height() + 1;
+
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ beos_warn_user("No GC", 0);
+ return NSERROR_INVALID;
+ }
+
+ // XXX: do we really need to use clipping reg ?
+ // I guess it's faster to not draw clipped out stuff...
+
+ BRect cliprect;
+ BRegion clipreg;
+ view->GetClippingRegion(&clipreg);
+ cliprect = clipreg.Frame();
+
+ //XXX: FIXME
+
+ if (y > cliprect.top) {
+ doneheight = ((int)cliprect.top - height) + ((y - (int)cliprect.top) % height);
+ } else {
+ doneheight = y;
+ }
+
+ while (doneheight < ((int)cliprect.bottom)) {
+ if (x > cliprect.left) {
+ donewidth = ((int)cliprect.left - width) + ((x - (int)cliprect.left) % width);
+ } else {
+ donewidth = x;
+ }
+
+ while (donewidth < (cliprect.right)) {
+ nsbeos_plot_bbitmap(donewidth, doneheight,
+ width, height, pretiled, bg);
+ donewidth += width;
+ if (!repeat_x) {
+ break;
+ }
+ }
+ doneheight += height;
+ if (!repeat_y) {
+ break;
+ }
+ }
#warning WRITEME
- return true;
-}
-static BPoint transform_pt(float x, float y, const float transform[6])
-{
-#warning XXX: verify
- //return BPoint(x, y);
- BPoint pt;
- pt.x = x * transform[0] + y * transform[1] + transform[4];
- pt.y = x * transform[2] + y * transform[3] + transform[5];
- /*
- printf("TR: {%f, %f} { %f, %f, %f, %f, %f, %f} = { %f, %f }\n",
- x, y,
- transform[0], transform[1], transform[2],
- transform[3], transform[4], transform[5],
- pt.x, pt.y);
- */
- return pt;
+ return NSERROR_OK;
}
-bool nsbeos_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
-{
- unsigned int i;
-
- if (n == 0)
- return true;
-
- if (p[0] != PLOTTER_PATH_MOVE) {
- LOG("path doesn't start with a move");
- return false;
- }
-
- BShape shape;
-
- for (i = 0; i < n; ) {
- if (p[i] == PLOTTER_PATH_MOVE) {
- BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
- shape.MoveTo(pt);
- i += 3;
- } else if (p[i] == PLOTTER_PATH_CLOSE) {
- shape.Close();
- i++;
- } else if (p[i] == PLOTTER_PATH_LINE) {
- BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
- shape.LineTo(pt);
- i += 3;
- } else if (p[i] == PLOTTER_PATH_BEZIER) {
- BPoint pt[3] = {
- transform_pt(p[i + 1], p[i + 2], transform),
- transform_pt(p[i + 3], p[i + 4], transform),
- transform_pt(p[i + 5], p[i + 6], transform)
- };
- shape.BezierTo(pt);
- i += 7;
- } else {
- LOG("bad path command %f", p[i]);
- return false;
- }
- }
- shape.Close();
-
- BView *view;
-
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL)
- return false;
-
- rgb_color old_high = view->HighColor();
- float old_pen = view->PenSize();
- view->SetPenSize(width);
- view->MovePenTo(0, 0);
- if (fill != NS_TRANSPARENT) {
- view->SetHighColor(nsbeos_rgb_colour(fill));
- view->FillShape(&shape);
- }
- if (c != NS_TRANSPARENT) {
- view->SetHighColor(nsbeos_rgb_colour(c));
- view->StrokeShape(&shape);
- }
- // restore
- view->SetPenSize(old_pen);
- view->SetHighColor(old_high);
-
- //nsbeos_current_gc_unlock();
-
- return true;
-}
-rgb_color nsbeos_rgb_colour(colour c)
+/**
+ * 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
+nsbeos_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
- rgb_color color;
- if (c == NS_TRANSPARENT)
- return B_TRANSPARENT_32_BIT;
- color.red = c & 0x0000ff;
- color.green = (c & 0x00ff00) >> 8;
- color.blue = (c & 0xff0000) >> 16;
- return color;
-}
+ if (!nsfont_paint(fstyle, text, length, x, y)) {
+ return NSERROR_INVALID;
+ }
-void nsbeos_set_colour(colour c)
-{
- rgb_color color = nsbeos_rgb_colour(c);
- BView *view = nsbeos_current_gc();
- view->SetHighColor(color);
+ return NSERROR_OK;
}
-/** Plot a caret. It is assumed that the plotters have been set up. */
-void nsbeos_plot_caret(int x, int y, int h)
-{
- BView *view;
-
- view = nsbeos_current_gc/*_lock*/();
- if (view == NULL)
- /* TODO: report an error here */
- return;
-
- BPoint start(x, y);
- BPoint end(x, y + h - 1);
-#if defined(__HAIKU__) || defined(B_BEOS_VERSION_DANO)
- view->SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
-#else
- view->SetHighColor(kBlackColor);
-#endif
- view->StrokeLine(start, end);
- //nsbeos_current_gc_unlock();
+/**
+ * beos plotter operation table
+ */
+const struct plotter_table nsbeos_plotters = {
+ nsbeos_plot_clip,
+ nsbeos_plot_arc,
+ nsbeos_plot_disc,
+ nsbeos_plot_line,
+ nsbeos_plot_rectangle,
+ nsbeos_plot_polygon,
+ nsbeos_plot_path,
+ nsbeos_plot_bitmap,
+ nsbeos_plot_text,
+ NULL, // Group Start
+ NULL, // Group End
+ NULL, // Flush
+ true // option_knockout
+};
-}
#ifdef TEST_PLOTTERS
//
static void test_plotters(void)
{
- int x0, y0;
- int x1, y1;
- struct rect r;
-
- x0 = 5;
- y0 = 5;
- x1 = 35;
- y1 = 6;
-
- plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, false);
- y0+=2; y1+=2;
- plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, false);
- y0+=2; y1+=2;
- plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, true);
- y0+=2; y1+=2;
- plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, true);
- y0+=10; y1+=20;
-
- plot.fill(x0, y0, x1, y1, 0x00ff0000);
- plot.rectangle(x0+10, y0+10, x1-x0+1, y1-y0+1, 2, 0x00ffff00, true, false);
- y0+=30; y1+=30;
-
- r.x0 = x0 + 2;
- r.y0 = y0 + 2;
- r.x1 = x1 - 2;
- r.y1 = y1 - 2;
- plot.clip(&r);
-
- plot.fill(x0, y0, x1, y1, 0x00000000);
- plot.disc(x1, y1, 8, 0x000000ff, false);
-
- r.x0 = 0;
- r.y0 = 0;
- r.x1 = 300;
- r.y1 = 300;
- plot.clip(&r);
-
- y0+=30; y1+=30;
-
+ int x0, y0;
+ int x1, y1;
+ struct rect r;
+
+ x0 = 5;
+ y0 = 5;
+ x1 = 35;
+ y1 = 6;
+
+ plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, false);
+ y0+=2; y1+=2;
+ plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, false);
+ y0+=2; y1+=2;
+ plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, true);
+ y0+=2; y1+=2;
+ plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, true);
+ y0+=10; y1+=20;
+
+ plot.fill(x0, y0, x1, y1, 0x00ff0000);
+ plot.rectangle(x0+10, y0+10, x1-x0+1, y1-y0+1, 2, 0x00ffff00, true, false);
+ y0+=30; y1+=30;
+
+ r.x0 = x0 + 2;
+ r.y0 = y0 + 2;
+ r.x1 = x1 - 2;
+ r.y1 = y1 - 2;
+ plot.clip(&r);
+
+ plot.fill(x0, y0, x1, y1, 0x00000000);
+ plot.disc(x1, y1, 8, 0x000000ff, false);
+
+ r.x0 = 0;
+ r.y0 = 0;
+ r.x1 = 300;
+ r.y1 = 300;
+ plot.clip(&r);
+
+ y0+=30; y1+=30;
+
}
#include <Application.h>
@@ -632,28 +805,27 @@ static void test_plotters(void)
#include <Window.h>
class PTView : public BView {
public:
- PTView(BRect frame) : BView(frame, "view", B_FOLLOW_NONE, B_WILL_DRAW) {};
- virtual ~PTView() {};
- virtual void Draw(BRect update)
- {
- test_plotters();
- };
+ PTView(BRect frame) : BView(frame, "view", B_FOLLOW_NONE, B_WILL_DRAW) {};
+ virtual ~PTView() {};
+ virtual void Draw(BRect update)
+ {
+ test_plotters();
+ };
};
extern "C" void test_plotters_main(void);
void test_plotters_main(void)
{
- BApplication app("application/x-vnd.NetSurf");
- memcpy(&plot, &nsbeos_plotters, sizeof(plot));
- BRect frame(0,0,300,300);
- PTView *view = new PTView(frame);
- frame.OffsetBySelf(100,100);
- BWindow *win = new BWindow(frame, "NetSurfPlotterTest", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
- win->AddChild(view);
- nsbeos_current_gc_set(view);
- win->Show();
- app.Run();
+ BApplication app("application/x-vnd.NetSurf");
+ memcpy(&plot, &nsbeos_plotters, sizeof(plot));
+ BRect frame(0,0,300,300);
+ PTView *view = new PTView(frame);
+ frame.OffsetBySelf(100,100);
+ BWindow *win = new BWindow(frame, "NetSurfPlotterTest", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
+ win->AddChild(view);
+ nsbeos_current_gc_set(view);
+ win->Show();
+ app.Run();
}
#endif /* TEST_PLOTTERS */
-
diff --git a/frontends/framebuffer/fbtk/text.c b/frontends/framebuffer/fbtk/text.c
index 00dcba4..31417c2 100644
--- a/frontends/framebuffer/fbtk/text.c
+++ b/frontends/framebuffer/fbtk/text.c
@@ -98,6 +98,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int padding;
int scroll = 0;
bool caret = false;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
fb_text_font_style(widget, &fh, &padding, &font_style);
@@ -142,8 +147,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
}
/* Call the fb text plotting, baseline is 3/4 down the font */
- fb_plotters.text(x, y, widget->u.text.text,
- widget->u.text.len, &font_style);
+ ctx.plot->text(&ctx,
+ &font_style,
+ x, y,
+ widget->u.text.text,
+ widget->u.text.len);
}
if (caret) {
@@ -209,6 +217,11 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int fh;
int border;
fbtk_widget_t *root = fbtk_get_root_widget(widget);
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
fb_text_font_style(widget, &fh, &border, &font_style);
@@ -256,11 +269,12 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
if (widget->u.text.text != NULL) {
/* Call the fb text plotting, baseline is 3/4 down the font */
- fb_plotters.text(bbox.x0 + border,
- bbox.y0 + ((fh * 3) / 4) + border,
- widget->u.text.text,
- widget->u.text.len,
- &font_style);
+ ctx.plot->text(&ctx,
+ &font_style,
+ bbox.x0 + border,
+ bbox.y0 + ((fh * 3) / 4) + border,
+ widget->u.text.text,
+ widget->u.text.len);
}
nsfb_update(root->u.root.fb, &bbox);
diff --git a/frontends/framebuffer/framebuffer.c b/frontends/framebuffer/framebuffer.c
index 74c72fe..7b8ee91 100644
--- a/frontends/framebuffer/framebuffer.c
+++ b/frontends/framebuffer/framebuffer.c
@@ -45,139 +45,274 @@
static nsfb_t *nsfb;
-static bool
-framebuffer_plot_disc(int x, int y, int radius, const plot_style_t *style)
+/**
+ * \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
+framebuffer_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
- nsfb_bbox_t ellipse;
- ellipse.x0 = x - radius;
- ellipse.y0 = y - radius;
- ellipse.x1 = x + radius;
- ellipse.y1 = y + radius;
-
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
- }
- return true;
+ nsfb_bbox_t nsfb_clip;
+ nsfb_clip.x0 = clip->x0;
+ nsfb_clip.y0 = clip->y0;
+ nsfb_clip.x1 = clip->x1;
+ nsfb_clip.y1 = clip->y1;
+
+ if (!nsfb_plot_set_clip(nsfb, &nsfb_clip)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
-static bool
-framebuffer_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.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
- return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour);
+ if (!nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
-static bool
-framebuffer_plot_polygon(const int *p, unsigned int n, 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
{
- return nsfb_plot_polygon(nsfb, p, n, style->fill_colour);
+ nsfb_bbox_t ellipse;
+ ellipse.x0 = x - radius;
+ ellipse.y0 = y - radius;
+ ellipse.x1 = x + radius;
+ ellipse.y1 = y + radius;
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
+ }
+ return NSERROR_OK;
}
-#ifdef FB_USE_FREETYPE
-static bool
-framebuffer_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
- uint32_t ucs4;
- size_t nxtchr = 0;
- FT_Glyph glyph;
- FT_BitmapGlyph bglyph;
- nsfb_bbox_t loc;
-
- while (nxtchr < length) {
- ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
- nxtchr = utf8_next(text, length, nxtchr);
-
- glyph = fb_getglyph(fstyle, ucs4);
- if (glyph == NULL)
- continue;
-
- if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
- bglyph = (FT_BitmapGlyph)glyph;
-
- loc.x0 = x + bglyph->left;
- loc.y0 = y - bglyph->top;
- loc.x1 = loc.x0 + bglyph->bitmap.width;
- loc.y1 = loc.y0 + bglyph->bitmap.rows;
-
- /* now, draw to our target surface */
- if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- nsfb_plot_glyph1(nsfb,
- &loc,
- bglyph->bitmap.buffer,
- bglyph->bitmap.pitch,
- fstyle->foreground);
- } else {
- nsfb_plot_glyph8(nsfb,
- &loc,
- bglyph->bitmap.buffer,
- bglyph->bitmap.pitch,
- fstyle->foreground);
- }
- }
- x += glyph->advance.x >> 16;
-
- }
- return true;
+ nsfb_bbox_t rect;
+ nsfb_plot_pen_t pen;
+ rect.x0 = line->x0;
+ rect.y0 = line->y0;
+ rect.x1 = line->x1;
+ rect.y1 = line->y1;
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xAAAAAAAA;
+ } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xF0F0F0F0;
+ } else {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ }
+
+ pen.stroke_colour = style->stroke_colour;
+ pen.stroke_width = style->stroke_width;
+ nsfb_plot_line(nsfb, &rect, &pen);
+ }
+
+ return NSERROR_OK;
}
-#else
-static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+
+
+/**
+ * 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.
+ * \param nsrect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *nsrect)
{
- enum fb_font_style style = fb_get_font_style(fstyle);
- int size = fb_get_font_size(fstyle);
- const uint8_t *chrp;
- size_t nxtchr = 0;
- nsfb_bbox_t loc;
- uint32_t ucs4;
- int p = FB_FONT_PITCH * size;
- int w = FB_FONT_WIDTH * size;
- int h = FB_FONT_HEIGHT * size;
+ nsfb_bbox_t rect;
+ bool dotted = false;
+ bool dashed = false;
- y -= ((h * 3) / 4);
- /* the coord is the bottom-left of the pixels offset by 1 to make
- * it work since fb coords are the top-left of pixels */
- y += 1;
+ rect.x0 = nsrect->x0;
+ rect.y0 = nsrect->y0;
+ rect.x1 = nsrect->x1;
+ rect.y1 = nsrect->y1;
- while (nxtchr < length) {
- ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
- nxtchr = utf8_next(text, length, nxtchr);
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
+ }
- if (!codepoint_displayable(ucs4))
- continue;
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ dotted = true;
+ }
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + w;
- loc.y1 = loc.y0 + h;
+ if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ dashed = true;
+ }
- chrp = fb_get_glyph(ucs4, style, size);
- nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
+ nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
+ }
+ return NSERROR_OK;
+}
- x += w;
- }
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ if (!nsfb_plot_polygon(nsfb, p, n, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+}
- return true;
+
+/**
+ * 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
+framebuffer_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
+{
+ LOG("path unimplemented");
+ return NSERROR_OK;
}
-#endif
-static bool
-framebuffer_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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
- nsfb_bbox_t loc;
- nsfb_bbox_t clipbox;
- bool repeat_x = (flags & BITMAPF_REPEAT_X);
- bool repeat_y = (flags & BITMAPF_REPEAT_Y);
+ nsfb_bbox_t loc;
+ nsfb_bbox_t clipbox;
+ bool repeat_x = (flags & BITMAPF_REPEAT_X);
+ bool repeat_y = (flags & BITMAPF_REPEAT_Y);
int bmwidth;
int bmheight;
int bmstride;
@@ -193,15 +328,15 @@ framebuffer_plot_bitmap(int x, int y,
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just plot it */
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + width;
- loc.y1 = loc.y0 + height;
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
- return nsfb_plot_copy(bm, NULL, nsfb, &loc);
+ return nsfb_plot_copy(bm, NULL, nsfb, &loc);
}
- nsfb_plot_get_clip(nsfb, &clipbox);
+ nsfb_plot_get_clip(nsfb, &clipbox);
nsfb_get_geometry(bm, &bmwidth, &bmheight, &bmformat);
nsfb_get_buffer(bm, &bmptr, &bmstride);
@@ -209,8 +344,11 @@ framebuffer_plot_bitmap(int x, int y,
* of the area. Can only be done when image is fully opaque. */
if ((bmwidth == 1) && (bmheight == 1)) {
if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
- return nsfb_plot_rectangle_fill(nsfb, &clipbox,
- *(nsfb_colour_t *)bmptr);
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
}
@@ -221,24 +359,29 @@ framebuffer_plot_bitmap(int x, int y,
if (framebuffer_bitmap_get_opaque(bm)) {
/** TODO: Currently using top left pixel. Maybe centre
* pixel or average value would be better. */
- return nsfb_plot_rectangle_fill(nsfb, &clipbox,
- *(nsfb_colour_t *)bmptr);
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
}
/* get left most tile position */
- if (repeat_x)
+ if (repeat_x) {
for (; x > clipbox.x0; x -= width);
+ }
/* get top most tile position */
- if (repeat_y)
+ if (repeat_y) {
for (; y > clipbox.y0; y -= height);
+ }
/* set up top left tile location */
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + width;
- loc.y1 = loc.y0 + height;
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
/* plot tiling across and down to extents */
nsfb_plot_bitmap_tiles(nsfb, &loc,
@@ -247,94 +390,135 @@ framebuffer_plot_bitmap(int x, int y,
(nsfb_colour_t *)bmptr, bmwidth, bmheight,
bmstride * 8 / 32, bmformat == NSFB_FMT_ABGR8888);
- return true;
+ return NSERROR_OK;
}
-static bool
-framebuffer_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- nsfb_bbox_t rect;
- bool dotted = false;
- bool dashed = false;
-
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- if (style->stroke_type == PLOT_OP_TYPE_DOT)
- dotted = true;
-
- if (style->stroke_type == PLOT_OP_TYPE_DASH)
- dashed = true;
+#ifdef FB_USE_FREETYPE
+/**
+ * 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
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
+ nsfb_bbox_t loc;
+
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+
+ loc.x0 = x + bglyph->left;
+ loc.y0 = y - bglyph->top;
+ loc.x1 = loc.x0 + bglyph->bitmap.width;
+ loc.y1 = loc.y0 + bglyph->bitmap.rows;
+
+ /* now, draw to our target surface */
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ nsfb_plot_glyph1(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ } else {
+ nsfb_plot_glyph8(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ }
+ }
+ x += glyph->advance.x >> 16;
- nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
}
+ return NSERROR_OK;
- return true;
}
-static bool
-framebuffer_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+#else
+
+/**
+ * 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
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
- nsfb_bbox_t rect;
- nsfb_plot_pen_t pen;
+ enum fb_font_style style = fb_get_font_style(fstyle);
+ int size = fb_get_font_size(fstyle);
+ const uint8_t *chrp;
+ size_t nxtchr = 0;
+ nsfb_bbox_t loc;
+ uint32_t ucs4;
+ int p = FB_FONT_PITCH * size;
+ int w = FB_FONT_WIDTH * size;
+ int h = FB_FONT_HEIGHT * size;
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ y -= ((h * 3) / 4);
+ /* the coord is the bottom-left of the pixels offset by 1 to make
+ * it work since fb coords are the top-left of pixels */
+ y += 1;
- if (style->stroke_type == PLOT_OP_TYPE_DOT) {
- pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
- pen.stroke_pattern = 0xAAAAAAAA;
- } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
- pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
- pen.stroke_pattern = 0xF0F0F0F0;
- } else {
- pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
- }
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
- pen.stroke_colour = style->stroke_colour;
- pen.stroke_width = style->stroke_width;
- nsfb_plot_line(nsfb, &rect, &pen);
- }
+ if (!codepoint_displayable(ucs4))
+ continue;
- return true;
-}
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + w;
+ loc.y1 = loc.y0 + h;
+ chrp = fb_get_glyph(ucs4, style, size);
+ nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
-static bool
-framebuffer_plot_path(const float *p,
- unsigned int n,
- colour fill,
- float width,
- colour c,
- const float transform[6])
-{
- LOG("path unimplemented");
- return true;
-}
+ x += w;
-static bool
-framebuffer_plot_clip(const struct rect *clip)
-{
- nsfb_bbox_t nsfb_clip;
- nsfb_clip.x0 = clip->x0;
- nsfb_clip.y0 = clip->y0;
- nsfb_clip.x1 = clip->x1;
- nsfb_clip.y1 = clip->y1;
+ }
- return nsfb_plot_set_clip(nsfb, &nsfb_clip);
+ return NSERROR_OK;
}
+#endif
+
+/** framebuffer plot operation table */
const struct plotter_table fb_plotters = {
.clip = framebuffer_plot_clip,
.arc = framebuffer_plot_arc,
@@ -345,7 +529,7 @@ const struct plotter_table fb_plotters = {
.path = framebuffer_plot_path,
.bitmap = framebuffer_plot_bitmap,
.text = framebuffer_plot_text,
- .option_knockout = true,
+ .option_knockout = true,
};
@@ -394,33 +578,33 @@ framebuffer_initialise(const char *fename, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
- return NULL;
+ return NULL;
}
fbtype = nsfb_type_from_name(fename);
if (fbtype == NSFB_SURFACE_NONE) {
- LOG("The %s surface is not available from libnsfb\n", fename);
- return NULL;
+ LOG("The %s surface is not available from libnsfb\n", fename);
+ return NULL;
}
nsfb = nsfb_new(fbtype);
if (nsfb == NULL) {
- LOG("Unable to create %s fb surface\n", fename);
- return NULL;
+ LOG("Unable to create %s fb surface\n", fename);
+ return NULL;
}
-
+
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
- LOG("Unable to set surface geometry\n");
- nsfb_free(nsfb);
- return NULL;
+ LOG("Unable to set surface geometry\n");
+ nsfb_free(nsfb);
+ return NULL;
}
nsfb_cursor_init(nsfb);
-
+
if (nsfb_init(nsfb) == -1) {
- LOG("Unable to initialise nsfb surface\n");
- nsfb_free(nsfb);
- return NULL;
+ LOG("Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return NULL;
}
return nsfb;
@@ -434,12 +618,12 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
- return false;
+ return false;
}
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
- LOG("Unable to change surface geometry\n");
- return false;
+ LOG("Unable to change surface geometry\n");
+ return false;
}
return true;
@@ -449,14 +633,14 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
void
framebuffer_finalise(void)
{
- nsfb_free(nsfb);
+ nsfb_free(nsfb);
}
bool
framebuffer_set_cursor(struct fbtk_bitmap *bm)
{
return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
-}
+}
nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
{
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..54b3a89 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,30 @@ 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.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \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 +133,26 @@ 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \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 +191,25 @@ 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.
+ * \param line A rectangle defining the line to be drawn
+ * \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,17 +238,22 @@ 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.
+
+/**
+ * Plot a caret.
*
* @note It is assumed that the plotters have been set up.
*/
@@ -207,14 +270,35 @@ 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \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 +326,36 @@ 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)
+
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+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 +370,116 @@ 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;
}
+/**
+ * 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 NSERROR_OK;
-static bool nsgtk_plot_text(int x, int y, const char *text, size_t length,
- const struct plot_font_style *fstyle)
-{
- return nsfont_paint(x, y, text, length, fstyle);
-}
+ if (p[0] != PLOTTER_PATH_MOVE) {
+ LOG("Path does not start with move");
+ return NSERROR_INVALID;
+ }
+ /* Save CTM */
+ cairo_get_matrix(current_cr, &old_ctm);
+ /* Set up line style and width */
+ cairo_set_line_width(current_cr, 1);
+ nsgtk_set_solid();
+
+ /* Load new CTM */
+ n_ctm.xx = transform[0];
+ n_ctm.yx = transform[1];
+ n_ctm.xy = transform[2];
+ n_ctm.yy = transform[3];
+ n_ctm.x0 = transform[4];
+ n_ctm.y0 = transform[5];
+
+ cairo_set_matrix(current_cr, &n_ctm);
+
+ /* Construct path */
+ for (i = 0; i < n; ) {
+ if (p[i] == PLOTTER_PATH_MOVE) {
+ cairo_move_to(current_cr, p[i+1], p[i+2]);
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_CLOSE) {
+ cairo_close_path(current_cr);
+ i++;
+ } else if (p[i] == PLOTTER_PATH_LINE) {
+ cairo_line_to(current_cr, p[i+1], p[i+2]);
+ i += 3;
+ } else if (p[i] == PLOTTER_PATH_BEZIER) {
+ cairo_curve_to(current_cr, p[i+1], p[i+2],
+ p[i+3], p[i+4],
+ p[i+5], p[i+6]);
+ i += 7;
+ } else {
+ LOG("bad path command %f", p[i]);
+ /* Reset matrix for safety */
+ cairo_set_matrix(current_cr, &old_ctm);
+ return NSERROR_INVALID;
+ }
+ }
+
+ /* Restore original CTM */
+ cairo_set_matrix(current_cr, &old_ctm);
+
+ /* Now draw path */
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ nsgtk_set_colour(pstyle->fill_colour);
-static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg)
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ /* Fill & Stroke */
+ cairo_fill_preserve(current_cr);
+ nsgtk_set_colour(pstyle->stroke_colour);
+ cairo_stroke(current_cr);
+ } else {
+ /* Fill only */
+ cairo_fill(current_cr);
+ }
+ } else if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ /* Stroke only */
+ nsgtk_set_colour(pstyle->stroke_colour);
+ cairo_stroke(current_cr);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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 +490,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 +533,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 +589,42 @@ 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \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 +633,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,90 +666,33 @@ 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])
-{
- unsigned int i;
- cairo_matrix_t old_ctm, n_ctm;
-
- if (n == 0)
- return true;
-
- if (p[0] != PLOTTER_PATH_MOVE) {
- LOG("Path does not start with move");
- return false;
- }
-
-
- /* Save CTM */
- cairo_get_matrix(current_cr, &old_ctm);
-
- /* Set up line style and width */
- cairo_set_line_width(current_cr, 1);
- nsgtk_set_solid();
-
- /* Load new CTM */
- n_ctm.xx = transform[0];
- n_ctm.yx = transform[1];
- n_ctm.xy = transform[2];
- n_ctm.yy = transform[3];
- n_ctm.x0 = transform[4];
- n_ctm.y0 = transform[5];
-
- cairo_set_matrix(current_cr, &n_ctm);
-
- /* Construct path */
- for (i = 0; i < n; ) {
- if (p[i] == PLOTTER_PATH_MOVE) {
- cairo_move_to(current_cr, p[i+1], p[i+2]);
- i += 3;
- } else if (p[i] == PLOTTER_PATH_CLOSE) {
- cairo_close_path(current_cr);
- i++;
- } else if (p[i] == PLOTTER_PATH_LINE) {
- cairo_line_to(current_cr, p[i+1], p[i+2]);
- i += 3;
- } else if (p[i] == PLOTTER_PATH_BEZIER) {
- cairo_curve_to(current_cr, p[i+1], p[i+2],
- p[i+3], p[i+4],
- p[i+5], p[i+6]);
- i += 7;
- } else {
- LOG("bad path command %f", p[i]);
- /* Reset matrix for safety */
- cairo_set_matrix(current_cr, &old_ctm);
- return false;
- }
- }
-
- /* Restore original CTM */
- cairo_set_matrix(current_cr, &old_ctm);
-
- /* Now draw path */
- if (fill != NS_TRANSPARENT) {
- nsgtk_set_colour(fill);
- if (c != NS_TRANSPARENT) {
- /* Fill & Stroke */
- cairo_fill_preserve(current_cr);
- nsgtk_set_colour(c);
- cairo_stroke(current_cr);
- } else {
- /* Fill only */
- cairo_fill(current_cr);
- }
- } else if (c != NS_TRANSPARENT) {
- /* Stroke only */
- nsgtk_set_colour(c);
- cairo_stroke(current_cr);
- }
-
- return true;
+/**
+ * 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
+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);
}
+
/** GTK plotter table */
const struct plotter_table nsgtk_plotters = {
.clip = nsgtk_plot_clip,
@@ -532,6 +706,3 @@ const struct plotter_table nsgtk_plotters = {
.text = nsgtk_plot_text,
.option_knockout = true
};
-
-
-
diff --git a/frontends/gtk/print.c b/frontends/gtk/print.c
index 55dcf63..4f34081 100644
--- a/frontends/gtk/print.c
+++ b/frontends/gtk/print.c
@@ -17,8 +17,10 @@
* 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
- * GTK printing (implementation).
+
+/**
+ * \file
+ * GTK printing implementation.
* All the functions and structures necessary for printing( signal handlers,
* plotters, printer) are here.
* Most of the plotters have been copied from the gtk_plotters.c file.
@@ -71,7 +73,7 @@ static inline void nsgtk_print_set_colour(colour c)
-static bool gtk_print_font_paint(int x, int y,
+static nserror gtk_print_font_paint(int x, int y,
const char *string, size_t length,
const plot_font_style_t *fstyle)
{
@@ -81,7 +83,7 @@ static bool gtk_print_font_paint(int x, int y,
PangoLayoutLine *line;
if (length == 0)
- return true;
+ return NSERROR_OK;
desc = nsfont_style_to_description(fstyle);
size = (gint) ((double) pango_font_description_get_size(desc) *
@@ -106,7 +108,7 @@ static bool gtk_print_font_paint(int x, int y,
g_object_unref(layout);
pango_font_description_free(desc);
- return true;
+ return NSERROR_OK;
}
@@ -131,10 +133,20 @@ static inline void nsgtk_print_set_dashed(void)
cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0);
}
-/** Set clipping area for subsequent plot operations. */
-static bool nsgtk_print_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_print_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
- LOG("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", clip->x0, clip->y0, clip->x1, clip->y1);
+ LOG("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i",
+ clip->x0, clip->y0, clip->x1, clip->y1);
/* Normalize cllipping area - to prevent overflows.
* See comment in pdf_plot_fill. */
@@ -153,10 +165,24 @@ static bool nsgtk_print_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_print_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_print_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
nsgtk_print_set_colour(style->fill_colour);
nsgtk_print_set_solid();
@@ -167,10 +193,23 @@ static bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, int angle
(angle2 + 90) * (M_PI / 180));
cairo_stroke(gtk_print_current_cr);
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_print_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_print_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_print_set_colour(style->fill_colour);
@@ -208,10 +247,25 @@ static bool nsgtk_print_plot_disc(int x, int y, int radius, const plot_style_t *
cairo_stroke(gtk_print_current_cr);
}
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_print_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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_print_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
nsgtk_print_set_colour(style->stroke_colour);
@@ -235,16 +289,35 @@ static bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_sty
else
cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
- cairo_move_to(gtk_print_current_cr, x0 + 0.5, y0 + 0.5);
- cairo_line_to(gtk_print_current_cr, x1 + 0.5, y1 + 0.5);
+ cairo_move_to(gtk_print_current_cr, line->x0 + 0.5, line->y0 + 0.5);
+ cairo_line_to(gtk_print_current_cr, line->x1 + 0.5, line->y1 + 0.5);
cairo_stroke(gtk_print_current_cr);
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_print_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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
- LOG("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", x0, y0, x1, y1);
+ int x0,y0,x1,y1;
+ LOG("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i",
+ rect->x0, rect->y0, rect->x1, rect->y1);
if (style->fill_type != PLOT_OP_TYPE_NONE) {
@@ -253,13 +326,15 @@ static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plo
/* Normalize boundaries of the area - to prevent overflows.
* See comment in pdf_plot_fill. */
- x0 = min(max(x0, 0), settings->page_width);
- y0 = min(max(y0, 0), settings->page_height);
- x1 = min(max(x1, 0), settings->page_width);
- y1 = min(max(y1, 0), settings->page_height);
+ x0 = min(max(rect->x0, 0), settings->page_width);
+ y0 = min(max(rect->y0, 0), settings->page_height);
+ x1 = min(max(rect->x1, 0), settings->page_width);
+ y1 = min(max(rect->y1, 0), settings->page_height);
cairo_set_line_width(gtk_print_current_cr, 0);
- cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0);
+ cairo_rectangle(gtk_print_current_cr,
+ x0, y0,
+ x1 - x0, y1 - y0);
cairo_fill(gtk_print_current_cr);
cairo_stroke(gtk_print_current_cr);
}
@@ -291,10 +366,15 @@ static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plo
cairo_stroke(gtk_print_current_cr);
}
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+
+static nserror
+nsgtk_print_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
unsigned int i;
@@ -316,18 +396,37 @@ static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, const plot_st
cairo_fill(gtk_print_current_cr);
cairo_stroke(gtk_print_current_cr);
- return true;
+ return NSERROR_OK;
}
-static bool nsgtk_print_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_print_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
/* Only the internal SVG renderer uses this plot call currently,
* and the GTK version uses librsvg. Thus, we ignore this complexity,
* and just return true obliviously. */
- return true;
+ return NSERROR_OK;
}
@@ -445,9 +544,30 @@ static bool nsgtk_print_plot_pixbuf(int x, int y, int width, int height,
}
-static bool nsgtk_print_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_print_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);
@@ -495,12 +615,19 @@ static bool nsgtk_print_plot_bitmap(int x, int y, int width, int height,
return true;
}
-static bool nsgtk_print_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+
+static nserror
+nsgtk_print_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
return gtk_print_font_paint(x, y, text, length, fstyle);
}
+
/** GTK print plotter table */
static const struct plotter_table nsgtk_print_plotters = {
.clip = nsgtk_print_plot_clip,
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);
diff --git a/frontends/monkey/plot.c b/frontends/monkey/plot.c
index bd94e75..9eb40ac 100644
--- a/frontends/monkey/plot.c
+++ b/frontends/monkey/plot.c
@@ -19,82 +19,250 @@
#include <stdio.h>
#include "utils/utils.h"
+#include "utils/errors.h"
#include "netsurf/plotters.h"
-static bool
-monkey_plot_disc(int x, int y, int radius, const plot_style_t *style)
+/**
+ * \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
+monkey_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
- return true;
+ fprintf(stdout,
+ "PLOT CLIP X0 %d Y0 %d X1 %d Y1 %d\n",
+ clip->x0, clip->y0, clip->x1, clip->y1);
+ return NSERROR_OK;
}
-static bool
-monkey_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.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
- return true;
+ fprintf(stdout,
+ "PLOT ARC X %d Y %d RADIUS %d ANGLE1 %d ANGLE2 %d\n",
+ x, y, radius, angle1, angle2);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_polygon(const int *p, unsigned int n, 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
{
- return true;
+ fprintf(stdout,
+ "PLOT DISC X %d Y %d RADIUS %d\n",
+ x, y, radius);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
- fprintf(stdout, "PLOT TEXT X %d Y %d STR %*s\n", x, y, (int)length, text);
- return true;
+ fprintf(stdout,
+ "PLOT LINE X0 %d Y0 %d X1 %d Y1 %d\n",
+ line->x0, line->y0, line->x1, line->y1);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_bitmap(int x, int y,
- int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
- fprintf(stdout, "PLOT BITMAP X %d Y %d WIDTH %d HEIGHT %d\n",
- x, y, width, height);
- return true;
+ fprintf(stdout,
+ "PLOT RECT X0 %d Y0 %d X1 %d Y1 %d\n",
+ rect->x0, rect->y0, rect->x1, rect->y1);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
- fprintf(stdout, "PLOT RECT X0 %d Y0 %d X1 %d Y1 %d\n",
- x0, y0, x1, y1);
- return true;
+ fprintf(stdout,
+ "PLOT POLYGON VERTICIES %d\n",
+ n);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+
+/**
+ * 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
+monkey_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
- fprintf(stdout, "PLOT LINE X0 %d Y0 %d X1 %d Y1 %d\n",
- x0, y0, x1, y1);
- return true;
+ fprintf(stdout,
+ "PLOT PATH VERTICIES %d WIDTH %f\n",
+ n, width);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_path(const float *p,
- unsigned int n,
- colour fill,
- float width,
- colour c,
- const float transform[6])
+/**
+ * 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+monkey_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
- return true;
+ fprintf(stdout,
+ "PLOT BITMAP X %d Y %d WIDTH %d HEIGHT %d\n",
+ x, y, width, height);
+ return NSERROR_OK;
}
-static bool
-monkey_plot_clip(const struct rect *clip)
+
+/**
+ * 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
+monkey_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
- fprintf(stdout, "PLOT CLIP X0 %d Y0 %d X1 %d Y1 %d\n",
- clip->x0, clip->y0, clip->x1, clip->y1);
- return true;
+ fprintf(stdout,
+ "PLOT TEXT X %d Y %d STR %*s\n",
+ x, y, (int)length, text);
+ return NSERROR_OK;
}
+
+/** monkey plotter operations table */
static const struct plotter_table plotters = {
.clip = monkey_plot_clip,
.arc = monkey_plot_arc,
diff --git a/frontends/riscos/content-handlers/artworks.c b/frontends/riscos/content-handlers/artworks.c
index f70b10a..7a7d79c 100644
--- a/frontends/riscos/content-handlers/artworks.c
+++ b/frontends/riscos/content-handlers/artworks.c
@@ -317,7 +317,7 @@ bool artworks_redraw(struct content *c, struct content_redraw_data *data,
int clip_x1 = clip->x1;
int clip_y1 = clip->y1;
- if (ctx->plot->flush && !ctx->plot->flush())
+ if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
/* pick up render addresses again in case they've changed
diff --git a/frontends/riscos/content-handlers/draw.c b/frontends/riscos/content-handlers/draw.c
index 9dff757..0c84de8 100644
--- a/frontends/riscos/content-handlers/draw.c
+++ b/frontends/riscos/content-handlers/draw.c
@@ -184,7 +184,7 @@ bool draw_redraw(struct content *c, struct content_redraw_data *data,
const void *src_data;
os_error *error;
- if (ctx->plot->flush && !ctx->plot->flush())
+ if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
if (!c->width || !c->height)
diff --git a/frontends/riscos/content-handlers/sprite.c b/frontends/riscos/content-handlers/sprite.c
index ed06110..02976e4 100644
--- a/frontends/riscos/content-handlers/sprite.c
+++ b/frontends/riscos/content-handlers/sprite.c
@@ -180,7 +180,7 @@ bool sprite_redraw(struct content *c, struct content_redraw_data *data,
{
sprite_content *sprite = (sprite_content *) c;
- if (ctx->plot->flush && !ctx->plot->flush())
+ if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
return image_redraw(sprite->data,
diff --git a/frontends/riscos/gui/progress_bar.c b/frontends/riscos/gui/progress_bar.c
index c26b46c..c47c2af 100644
--- a/frontends/riscos/gui/progress_bar.c
+++ b/frontends/riscos/gui/progress_bar.c
@@ -30,9 +30,9 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
-#include "netsurf/plotters.h"
#include "utils/log.h"
#include "utils/utils.h"
+#include "netsurf/plotters.h"
#include "riscos/gui.h"
#include "riscos/tinct.h"
@@ -482,6 +482,11 @@ void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
osbool more = true;
struct rect clip;
int progress_ymid;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
/* initialise the plotters */
ro_plot_origin_x = 0;
@@ -513,16 +518,16 @@ void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
redraw->box.y0 + pb->visible.y0) >> 1;
if ((clip.x0 < clip.x1) && (clip.y0 < clip.y1)) {
if (progress_icon) {
- ro_plotters.clip(&clip);
+ ctx.plot->clip(&ctx, &clip);
_swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
progress_icon,
redraw->box.x0 - pb->offset,
progress_ymid - progress_height,
tinct_FILL_HORIZONTALLY);
} else {
- ro_plotters.rectangle(clip.x0, clip.y0,
- clip.x1, clip.y1,
- plot_style_fill_red);
+ ctx.plot->rectangle(&ctx,
+ plot_style_fill_red,
+ &clip);
}
}
}
diff --git a/frontends/riscos/gui/status_bar.c b/frontends/riscos/gui/status_bar.c
index 9d1bada..bcaf3ba 100644
--- a/frontends/riscos/gui/status_bar.c
+++ b/frontends/riscos/gui/status_bar.c
@@ -28,9 +28,10 @@
#include "oslib/os.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
-#include "netsurf/plotters.h"
+
#include "utils/log.h"
#include "utils/utils.h"
+#include "netsurf/plotters.h"
#include "riscos/gui.h"
#include "riscos/wimp.h"
@@ -436,6 +437,12 @@ void ro_gui_status_bar_redraw(wimp_draw *redraw)
os_error *error;
osbool more;
rufl_code code;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+ struct rect rect;
sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(redraw->w);
assert(sb);
@@ -467,18 +474,22 @@ void ro_gui_status_bar_redraw(wimp_draw *redraw)
rufl_BLEND_FONT);
if (code != rufl_OK) {
if (code == rufl_FONT_MANAGER_ERROR)
- LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
+ LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s",
+ rufl_fm_error->errnum, rufl_fm_error->errmess);
else
LOG("rufl_paint: 0x%x", code);
}
}
+ rect.x0 = (redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1;
+ rect.y0 = -redraw->box.y0 >> 1;
+ rect.x1 = (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1;
+ rect.y1 = -redraw->box.y1 >> 1;
+
/* separate the widget from the text with a line */
- ro_plotters.rectangle((redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1,
- -redraw->box.y0 >> 1,
- (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1,
- -redraw->box.y1 >> 1,
- plot_style_fill_black);
+ ctx.plot->rectangle(&ctx,
+ plot_style_fill_black,
+ &rect);
error = xwimp_get_rectangle(redraw, &more);
if (error) {
diff --git a/frontends/riscos/plotters.c b/frontends/riscos/plotters.c
index 06e732d..b12d6c4 100644
--- a/frontends/riscos/plotters.c
+++ b/frontends/riscos/plotters.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Target independent plotting (RISC OS screen implementation).
+/**
+ * \file
+ * RISC OS screen plotter implementation.
*/
#include <stdbool.h>
@@ -35,38 +36,6 @@
#include "riscos/font.h"
#include "riscos/oslib_pre7.h"
-static bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool ro_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool ro_plot_draw_path(const draw_path * const path, int width,
- colour c, bool dotted, bool dashed);
-static bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
-static bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6]);
-static bool ro_plot_clip(const struct rect *clip);
-static bool ro_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style);
-static bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *style);
-static bool ro_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
-
-
-struct plotter_table plot;
-
-const struct plotter_table ro_plotters = {
- .rectangle = ro_plot_rectangle,
- .line = ro_plot_line,
- .polygon = ro_plot_polygon,
- .clip = ro_plot_clip,
- .text = ro_plot_text,
- .disc = ro_plot_disc,
- .arc = ro_plot_arc,
- .bitmap = ro_plot_bitmap,
- .path = ro_plot_path,
- .option_knockout = true,
-};
int ro_plot_origin_x = 0;
int ro_plot_origin_y = 0;
@@ -74,143 +43,387 @@ int ro_plot_origin_y = 0;
/** One version of the A9home OS is incapable of drawing patterned lines */
bool ro_plot_patterned_lines = true;
+/**
+ * plot a path on RISC OS
+ */
+static nserror
+ro_plot_draw_path(const draw_path * const path,
+ int width,
+ colour c,
+ bool dotted,
+ bool dashed)
+{
+ static const draw_line_style line_style = {
+ draw_JOIN_MITRED,
+ draw_CAP_BUTT,
+ draw_CAP_BUTT,
+ 0, 0x7fffffff,
+ 0, 0, 0, 0
+ };
+ draw_dash_pattern dash = { 0, 1, { 512 } };
+ const draw_dash_pattern *dash_pattern = 0;
+ os_error *error;
+
+ if (width < 1)
+ width = 1;
+
+ if (ro_plot_patterned_lines) {
+ if (dotted) {
+ dash.elements[0] = 512 * width;
+ dash_pattern = ‐
+ } else if (dashed) {
+ dash.elements[0] = 1536 * width;
+ dash_pattern = ‐
+ }
+ }
+
+ error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ error = xdraw_stroke(path, 0, 0, 0, width * 2 * 256,
+ &line_style, dash_pattern);
+ if (error) {
+ LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * \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
+ro_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ os_error *error;
+ char buf[12];
+
+ int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
+ int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
+ int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
+ int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
+
+ if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
+ LOG("bad clip rectangle %i %i %i %i",
+ clip_x0, clip_y0, clip_x1, clip_y1);
+ return NSERROR_BAD_SIZE;
+ }
+
+ buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
+ buf[1] = clip_x0;
+ buf[2] = clip_x0 >> 8;
+ buf[3] = clip_y1;
+ buf[4] = clip_y1 >> 8;
+ buf[5] = clip_x1;
+ buf[6] = clip_x1 >> 8;
+ buf[7] = clip_y0;
+ buf[8] = clip_y0 >> 8;
+
+ error = xos_writen(buf, 9);
+ if (error) {
+ LOG("xos_writen: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ os_error *error;
+ int sx, sy, ex, ey;
+ double t;
+
+ x = ro_plot_origin_x + x * 2;
+ y = ro_plot_origin_y - y * 2;
+ radius <<= 1;
+
+ error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ t = ((double)angle1 * M_PI) / 180.0;
+ sx = (x + (int)(radius * cos(t)));
+ sy = (y + (int)(radius * sin(t)));
+ t = ((double)angle2 * M_PI) / 180.0;
+ ex = (x + (int)(radius * cos(t)));
+ ey = (y + (int)(radius * sin(t)));
-bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
+ error = xos_plot(os_MOVE_TO, x, y); /* move to centre */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ error = xos_plot(os_MOVE_TO, sx, sy); /* move to start */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ error = xos_plot(os_PLOT_ARC | os_PLOT_TO, ex, ey); /* arc to end */
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * 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.
+ * \param x The x coordinate of the circle.
+ * \param y The y coordinate of the circle.
+ * \param radius The radius of the circle.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
{
+ os_error *error;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
- os_error *error;
- error = xcolourtrans_set_gcol(style->fill_colour << 8,
- colourtrans_USE_ECFS_GCOL,
- os_ACTION_OVERWRITE, 0, 0);
+ error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
}
-
error = xos_plot(os_MOVE_TO,
- ro_plot_origin_x + x0 * 2,
- ro_plot_origin_y - y0 * 2 - 1);
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ return NSERROR_INVALID;
}
-
- error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
- ro_plot_origin_x + x1 * 2 - 1,
- ro_plot_origin_y - y1 * 2);
+ error = xos_plot(os_PLOT_CIRCLE | os_PLOT_BY, radius * 2, 0);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ return NSERROR_INVALID;
}
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- bool dotted = false;
- bool dashed = false;
-
- const int path[] = { draw_MOVE_TO,
- (ro_plot_origin_x + x0 * 2) * 256,
- (ro_plot_origin_y - y0 * 2 - 1) * 256,
- draw_LINE_TO,
- (ro_plot_origin_x + (x1) * 2) * 256,
- (ro_plot_origin_y - y0 * 2 - 1) * 256,
- draw_LINE_TO,
- (ro_plot_origin_x + (x1) * 2) * 256,
- (ro_plot_origin_y - (y1) * 2 - 1) * 256,
- draw_LINE_TO,
- (ro_plot_origin_x + x0 * 2) * 256,
- (ro_plot_origin_y - (y1) * 2 - 1) * 256,
- draw_CLOSE_LINE,
- (ro_plot_origin_x + x0 * 2) * 256,
- (ro_plot_origin_y - y0 * 2 - 1) * 256,
- draw_END_PATH };
-
- if (style->stroke_type == PLOT_OP_TYPE_DOT)
- dotted = true;
- if (style->stroke_type == PLOT_OP_TYPE_DASH)
- dashed = true;
+ error = xcolourtrans_set_gcol(style->stroke_colour << 8, 0,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+ error = xos_plot(os_MOVE_TO,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+ error = xos_plot(os_PLOT_CIRCLE_OUTLINE | os_PLOT_BY,
+ radius * 2, 0);
- ro_plot_draw_path((const draw_path *)path,
- style->stroke_width,
- style->stroke_colour,
- dotted, dashed);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
}
-
- return true;
+ return NSERROR_OK;
}
-bool ro_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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- const int path[] = { draw_MOVE_TO,
- (ro_plot_origin_x + x0 * 2) * 256,
- (ro_plot_origin_y - y0 * 2 - 1) * 256,
- draw_LINE_TO,
- (ro_plot_origin_x + x1 * 2) * 256,
- (ro_plot_origin_y - y1 * 2 - 1) * 256,
- draw_END_PATH };
- bool dotted = false;
+ const int path[] = {
+ draw_MOVE_TO,
+ (ro_plot_origin_x + line->x0 * 2) * 256,
+ (ro_plot_origin_y - line->y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + line->x1 * 2) * 256,
+ (ro_plot_origin_y - line->y1 * 2 - 1) * 256,
+ draw_END_PATH };
+ bool dotted = false;
bool dashed = false;
- if (style->stroke_type == PLOT_OP_TYPE_DOT)
+ if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
- if (style->stroke_type == PLOT_OP_TYPE_DASH)
+ if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
- return ro_plot_draw_path((const draw_path *)path,
- style->stroke_width,
- style->stroke_colour,
+ return ro_plot_draw_path((const draw_path *)path,
+ style->stroke_width,
+ style->stroke_colour,
dotted, dashed);
}
- return true;
+ return NSERROR_OK;
}
-bool ro_plot_draw_path(const draw_path * const path, int width,
- colour c, bool dotted, bool dashed)
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
- static const draw_line_style line_style = { draw_JOIN_MITRED,
- draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
- 0, 0, 0, 0 };
- draw_dash_pattern dash = { 0, 1, { 512 } };
- const draw_dash_pattern *dash_pattern = 0;
- os_error *error;
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ os_error *error;
+ error = xcolourtrans_set_gcol(style->fill_colour << 8,
+ colourtrans_USE_ECFS_GCOL,
+ os_ACTION_OVERWRITE, 0, 0);
+ if (error) {
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
- if (width < 1)
- width = 1;
+ error = xos_plot(os_MOVE_TO,
+ ro_plot_origin_x + rect->x0 * 2,
+ ro_plot_origin_y - rect->y0 * 2 - 1);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
- if (ro_plot_patterned_lines) {
- if (dotted) {
- dash.elements[0] = 512 * width;
- dash_pattern = ‐
- } else if (dashed) {
- dash.elements[0] = 1536 * width;
- dash_pattern = ‐
+ error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ ro_plot_origin_x + rect->x1 * 2 - 1,
+ ro_plot_origin_y - rect->y1 * 2);
+ if (error) {
+ LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
+ return NSERROR_INVALID;
}
}
- error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0);
- if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ bool dotted = false;
+ bool dashed = false;
- error = xdraw_stroke(path, 0, 0, 0, width * 2 * 256,
- &line_style, dash_pattern);
- if (error) {
- LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ const int path[] = {
+ draw_MOVE_TO,
+ (ro_plot_origin_x + rect->x0 * 2) * 256,
+ (ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + (rect->x1) * 2) * 256,
+ (ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + (rect->x1) * 2) * 256,
+ (ro_plot_origin_y - (rect->y1) * 2 - 1) * 256,
+ draw_LINE_TO,
+ (ro_plot_origin_x + rect->x0 * 2) * 256,
+ (ro_plot_origin_y - (rect->y1) * 2 - 1) * 256,
+ draw_CLOSE_LINE,
+ (ro_plot_origin_x + rect->x0 * 2) * 256,
+ (ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
+ draw_END_PATH
+ };
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT)
+ dotted = true;
+
+ if (style->stroke_type == PLOT_OP_TYPE_DASH)
+ dashed = true;
+
+ ro_plot_draw_path((const draw_path *)path,
+ style->stroke_width,
+ style->stroke_colour,
+ dotted,
+ dashed);
}
- return true;
+ return NSERROR_OK;
}
-bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
int path[n * 3 + 2];
unsigned int i;
@@ -225,34 +438,60 @@ bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
path[n * 3] = draw_END_PATH;
path[n * 3 + 1] = 0;
- error = xcolourtrans_set_gcol(style->fill_colour << 8, 0, os_ACTION_OVERWRITE, 0, 0);
+ error = xcolourtrans_set_gcol(style->fill_colour << 8,
+ 0, os_ACTION_OVERWRITE, 0, 0);
if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
}
error = xdraw_fill((draw_path *) path, 0, 0, 0);
if (error) {
LOG("xdraw_fill: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ return NSERROR_INVALID;
}
- return true;
+ return NSERROR_OK;
}
-bool ro_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
+ro_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
- static const draw_line_style line_style = { draw_JOIN_MITRED,
- draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
- 0, 0, 0, 0 };
+ static const draw_line_style line_style = {
+ draw_JOIN_MITRED,
+ draw_CAP_BUTT,
+ draw_CAP_BUTT,
+ 0, 0x7fffffff,
+ 0, 0, 0, 0
+ };
int *path = 0;
unsigned int i;
os_trfm trfm;
os_error *error;
- if (n == 0)
- return true;
+ if (n == 0) {
+ return NSERROR_OK;
+ }
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("path doesn't start with a move");
@@ -303,222 +542,159 @@ bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
trfm.entries[2][0] = (ro_plot_origin_x + transform[4] * 2) * 256;
trfm.entries[2][1] = (ro_plot_origin_y - transform[5] * 2) * 256;
- if (fill != NS_TRANSPARENT) {
- error = xcolourtrans_set_gcol(fill << 8, 0,
+ if (pstyle->fill_colour != NS_TRANSPARENT) {
+ error = xcolourtrans_set_gcol(pstyle->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
goto error;
}
error = xdraw_fill((draw_path *) path, 0, &trfm, 0);
if (error) {
- LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ LOG("xdraw_stroke: 0x%x: %s",
+ error->errnum, error->errmess);
goto error;
}
}
- if (c != NS_TRANSPARENT) {
- error = xcolourtrans_set_gcol(c << 8, 0,
+ if (pstyle->stroke_colour != NS_TRANSPARENT) {
+ error = xcolourtrans_set_gcol(pstyle->stroke_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
+ LOG("xcolourtrans_set_gcol: 0x%x: %s",
+ error->errnum, error->errmess);
goto error;
}
error = xdraw_stroke((draw_path *) path, 0, &trfm, 0,
width * 2 * 256, &line_style, 0);
if (error) {
- LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
+ LOG("xdraw_stroke: 0x%x: %s",
+ error->errnum, error->errmess);
goto error;
}
}
free(path);
- return true;
+ return NSERROR_OK;
error:
free(path);
- return false;
+ return NSERROR_INVALID;
}
-
-
-bool ro_plot_clip(const struct rect *clip)
+/**
+ * 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
- os_error *error;
- char buf[12];
-
- int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
- int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
- int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
- int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
+ const uint8_t *buffer;
- if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
- LOG("bad clip rectangle %i %i %i %i", clip_x0, clip_y0, clip_x1, clip_y1);
- return false;
+ buffer = riscos_bitmap_get_buffer(bitmap);
+ if (!buffer) {
+ LOG("bitmap_get_buffer failed");
+ return NSERROR_INVALID;
}
- buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
- buf[1] = clip_x0;
- buf[2] = clip_x0 >> 8;
- buf[3] = clip_y1;
- buf[4] = clip_y1 >> 8;
- buf[5] = clip_x1;
- buf[6] = clip_x1 >> 8;
- buf[7] = clip_y0;
- buf[8] = clip_y0 >> 8;
-
- error = xos_writen(buf, 9);
- if (error) {
- LOG("xos_writen: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ if (!image_redraw(bitmap->sprite_area,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2,
+ width, height,
+ bitmap->width,
+ bitmap->height,
+ bg,
+ flags & BITMAPF_REPEAT_X, flags & BITMAPF_REPEAT_Y,
+ flags & BITMAPF_REPEAT_X || flags & BITMAPF_REPEAT_Y,
+ riscos_bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
+ IMAGE_PLOT_TINCT_ALPHA)) {
+ return NSERROR_INVALID;
}
-
- return true;
+ return NSERROR_OK;
}
-bool ro_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
+ro_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
os_error *error;
error = xcolourtrans_set_font_colours(font_CURRENT,
- fstyle->background << 8, fstyle->foreground << 8,
+ fstyle->background << 8, fstyle->foreground << 8,
14, 0, 0, 0);
if (error) {
- LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ LOG("xcolourtrans_set_font_colours: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
}
- return nsfont_paint(fstyle, text, length,
+ if (!nsfont_paint(fstyle, text, length,
ro_plot_origin_x + x * 2,
- ro_plot_origin_y - y * 2);
-}
-
-
-bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style)
-{
- os_error *error;
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
- os_ACTION_OVERWRITE, 0, 0);
- if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- error = xos_plot(os_MOVE_TO,
- ro_plot_origin_x + x * 2,
- ro_plot_origin_y - y * 2);
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- error = xos_plot(os_PLOT_CIRCLE | os_PLOT_BY, radius * 2, 0);
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
-
- error = xcolourtrans_set_gcol(style->stroke_colour << 8, 0,
- os_ACTION_OVERWRITE, 0, 0);
- if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- error = xos_plot(os_MOVE_TO,
- ro_plot_origin_x + x * 2,
- ro_plot_origin_y - y * 2);
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- error = xos_plot(os_PLOT_CIRCLE_OUTLINE | os_PLOT_BY,
- radius * 2, 0);
-
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
- }
- return true;
-}
-
-bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
-{
- os_error *error;
- int sx, sy, ex, ey;
- double t;
-
- x = ro_plot_origin_x + x * 2;
- y = ro_plot_origin_y - y * 2;
- radius <<= 1;
-
- error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
- os_ACTION_OVERWRITE, 0, 0);
-
- if (error) {
- LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
-
- t = ((double)angle1 * M_PI) / 180.0;
- sx = (x + (int)(radius * cos(t)));
- sy = (y + (int)(radius * sin(t)));
-
- t = ((double)angle2 * M_PI) / 180.0;
- ex = (x + (int)(radius * cos(t)));
- ey = (y + (int)(radius * sin(t)));
-
- error = xos_plot(os_MOVE_TO, x, y); /* move to centre */
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
-
- error = xos_plot(os_MOVE_TO, sx, sy); /* move to start */
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
- }
-
- error = xos_plot(os_PLOT_ARC | os_PLOT_TO, ex, ey); /* arc to end */
- if (error) {
- LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
- return false;
+ ro_plot_origin_y - y * 2)) {
+ return NSERROR_INVALID;
}
-
- return true;
+ return NSERROR_OK;
}
-
-bool ro_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
-{
- const uint8_t *buffer;
-
- buffer = riscos_bitmap_get_buffer(bitmap);
- if (!buffer) {
- LOG("bitmap_get_buffer failed");
- return false;
- }
-
- return image_redraw(bitmap->sprite_area,
- ro_plot_origin_x + x * 2,
- ro_plot_origin_y - y * 2,
- width, height,
- bitmap->width,
- bitmap->height,
- bg,
- flags & BITMAPF_REPEAT_X, flags & BITMAPF_REPEAT_Y,
- flags & BITMAPF_REPEAT_X || flags & BITMAPF_REPEAT_Y,
- riscos_bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
- IMAGE_PLOT_TINCT_ALPHA);
-}
+/**
+ * RISC OS plotter operation table
+ */
+const struct plotter_table ro_plotters = {
+ .rectangle = ro_plot_rectangle,
+ .line = ro_plot_line,
+ .polygon = ro_plot_polygon,
+ .clip = ro_plot_clip,
+ .text = ro_plot_text,
+ .disc = ro_plot_disc,
+ .arc = ro_plot_arc,
+ .bitmap = ro_plot_bitmap,
+ .path = ro_plot_path,
+ .option_knockout = true,
+};
diff --git a/frontends/riscos/print.c b/frontends/riscos/print.c
index 465627e..1ccfc7f 100644
--- a/frontends/riscos/print.c
+++ b/frontends/riscos/print.c
@@ -104,39 +104,12 @@ static void print_send_printsave(struct hlcache_handle *h);
static bool print_send_printtypeknown(wimp_message *m);
static bool print_document(struct gui_window *g, const char *filename);
static const char *print_declare_fonts(struct hlcache_handle *h);
-static bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
-static bool print_fonts_plot_clip(const struct rect *clip);
-static bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style);
-static bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style);
-static bool print_fonts_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags);
-static bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6]);
static void print_fonts_callback(void *context,
const char *font_name, unsigned int font_size,
const char *s8, unsigned short *s16, unsigned int n,
int x, int y);
-/** Plotter for print_declare_fonts(). All the functions do nothing except for
- * print_fonts_plot_text, which records the fonts used. */
-static const struct plotter_table print_fonts_plotters = {
- .rectangle = print_fonts_plot_rectangle,
- .line = print_fonts_plot_line,
- .polygon = print_fonts_plot_polygon,
- .clip = print_fonts_plot_clip,
- .text = print_fonts_plot_text,
- .disc = print_fonts_plot_disc,
- .arc = print_fonts_plot_arc,
- .bitmap = print_fonts_plot_bitmap,
- .path = print_fonts_plot_path,
- .option_knockout = false,
-};
/**
@@ -780,6 +753,143 @@ error:
}
+
+
+static nserror
+print_fonts_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
+{
+ return NSERROR_OK;
+}
+
+static nserror
+print_fonts_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
+{
+ return NSERROR_OK;
+}
+
+/**
+ * text plotting during RO print font listing.
+ *
+ * \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
+print_fonts_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ const char *font_family;
+ unsigned int font_size;
+ rufl_style font_style;
+ rufl_code code;
+
+ nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
+
+ code = rufl_paint_callback(font_family, font_style, font_size,
+ text, length, 0, 0, print_fonts_callback, 0);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR) {
+ LOG("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: ""0x%x: %s",
+ rufl_fm_error->errnum, rufl_fm_error->errmess);
+ print_fonts_error = rufl_fm_error->errmess;
+ } else {
+ LOG("rufl_paint_callback: 0x%x", code);
+ }
+ return NSERROR_INVALID;
+ }
+ if (print_fonts_error)
+ return NSERROR_INVALID;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plotter table for print_declare_fonts().
+ *
+ * All the functions do nothing except for print_fonts_plot_text,
+ * which records the fonts used.
+*/
+static const struct plotter_table print_fonts_plotters = {
+ .rectangle = print_fonts_plot_rectangle,
+ .line = print_fonts_plot_line,
+ .polygon = print_fonts_plot_polygon,
+ .clip = print_fonts_plot_clip,
+ .text = print_fonts_plot_text,
+ .disc = print_fonts_plot_disc,
+ .arc = print_fonts_plot_arc,
+ .bitmap = print_fonts_plot_bitmap,
+ .path = print_fonts_plot_path,
+ .option_knockout = false,
+};
+
+
/**
* Declare fonts to the printer driver.
*
@@ -850,84 +960,6 @@ end:
}
-bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- return true;
-}
-
-
-bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- return true;
-}
-
-bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
-{
- return true;
-}
-
-
-bool print_fonts_plot_clip(const struct rect *clip)
-{
- return true;
-}
-
-bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style)
-{
- return true;
-}
-
-bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *style)
-{
- return true;
-}
-
-bool print_fonts_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
-{
- return true;
-}
-
-bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
-{
- return true;
-}
-
-
-/**
- * Plotter for text plotting during font listing.
- */
-
-bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
-{
- const char *font_family;
- unsigned int font_size;
- rufl_style font_style;
- rufl_code code;
-
- nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
-
- code = rufl_paint_callback(font_family, font_style, font_size,
- text, length, 0, 0, print_fonts_callback, 0);
- if (code != rufl_OK) {
- if (code == rufl_FONT_MANAGER_ERROR) {
- LOG("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
- print_fonts_error = rufl_fm_error->errmess;
- } else {
- LOG("rufl_paint_callback: 0x%x", code);
- }
- return false;
- }
- if (print_fonts_error)
- return false;
-
- return true;
-}
-
-
/**
* Callback for print_fonts_plot_text().
*
diff --git a/frontends/riscos/save_draw.c b/frontends/riscos/save_draw.c
index 7e6c946..1e0bc1e 100644
--- a/frontends/riscos/save_draw.c
+++ b/frontends/riscos/save_draw.c
@@ -18,7 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Export a content as a DrawFile (implementation).
*/
@@ -39,38 +40,6 @@
#include "riscos/save_draw.h"
#include "riscos/font.h"
-static bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
-static bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style);
-static bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
- float width, colour c, const float transform[6]);
-static bool ro_save_draw_clip(const struct rect *clip);
-static bool ro_save_draw_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle);
-static bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style);
-static bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *style);
-static bool ro_save_draw_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg, bitmap_flags_t flags);
-static bool ro_save_draw_group_start(const char *name);
-static bool ro_save_draw_group_end(void);
-static bool ro_save_draw_error(pencil_code code);
-
-
-static const struct plotter_table ro_save_draw_plotters = {
- .rectangle = ro_save_draw_rectangle,
- .line = ro_save_draw_line,
- .polygon = ro_save_draw_polygon,
- .clip = ro_save_draw_clip,
- .text = ro_save_draw_text,
- .disc = ro_save_draw_disc,
- .arc = ro_save_draw_arc,
- .bitmap = ro_save_draw_bitmap,
- .group_start = ro_save_draw_group_start,
- .group_end = ro_save_draw_group_end,
- .path = ro_save_draw_path,
- .option_knockout = false,
-};
static struct pencil_diagram *ro_save_draw_diagram;
static int ro_save_draw_width;
@@ -78,157 +47,229 @@ static int ro_save_draw_height;
/**
- * Export a content as a DrawFile.
+ * Report an error from pencil.
*
- * \param h content to export
- * \param path path to save DrawFile as
- * \return true on success, false on error and error reported
+ * \param code error code
+ * \return false
*/
-
-bool save_as_draw(struct hlcache_handle *h, const char *path)
+static nserror ro_save_draw_error(pencil_code code)
{
- pencil_code code;
- char *drawfile_buffer;
- struct rect clip;
- struct content_redraw_data data;
- size_t drawfile_size;
- os_error *error;
- struct redraw_context ctx = {
- .interactive = false,
- .background_images = true,
- .plot = &ro_save_draw_plotters
- };
+ LOG("code %i", code);
- ro_save_draw_diagram = pencil_create();
- if (!ro_save_draw_diagram) {
+ switch (code) {
+ case pencil_OK:
+ assert(0);
+ break;
+
+ case pencil_OUT_OF_MEMORY:
ro_warn_user("NoMemory", 0);
- return false;
+ break;
+
+ case pencil_FONT_MANAGER_ERROR:
+ ro_warn_user("SaveError", rufl_fm_error->errmess);
+ break;
+
+ case pencil_FONT_NOT_FOUND:
+ case pencil_IO_ERROR:
+ case pencil_IO_EOF:
+ ro_warn_user("SaveError", "generating the DrawFile failed");
+ break;
}
- ro_save_draw_width = content_get_width(h);
- ro_save_draw_height = content_get_height(h);
+ return NSERROR_INVALID;
+}
- clip.x0 = clip.y0 = INT_MIN;
- clip.x1 = clip.y1 = INT_MAX;
+/**
+ * \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
+ro_save_draw_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ return NSERROR_OK;
+}
- data.x = 0;
- data.y = -ro_save_draw_height;
- data.width = ro_save_draw_width;
- data.height = ro_save_draw_height;
- data.background_colour = 0xFFFFFF;
- data.scale = 1;
- data.repeat_x = false;
- data.repeat_y = false;
- if (!content_redraw(h, &data, &clip, &ctx)) {
- pencil_free(ro_save_draw_diagram);
- return false;
- }
+/**
+ * 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.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ return NSERROR_OK;
+}
- /*pencil_dump(ro_save_draw_diagram);*/
- code = pencil_save_drawfile(ro_save_draw_diagram, "NetSurf",
- &drawfile_buffer, &drawfile_size);
- if (code != pencil_OK) {
- ro_warn_user("SaveError", 0);
- pencil_free(ro_save_draw_diagram);
- return false;
- }
- assert(drawfile_buffer);
+/**
+ * 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.
+ * \param x The x coordinate of the circle.
+ * \param y The y coordinate of the circle.
+ * \param radius The radius of the circle.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ return NSERROR_OK;
+}
- error = xosfile_save_stamped(path, osfile_TYPE_DRAW,
- (byte *) drawfile_buffer,
- (byte *) drawfile_buffer + drawfile_size);
- if (error) {
- LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess);
- ro_warn_user("SaveError", error->errmess);
- pencil_free(ro_save_draw_diagram);
- return false;
- }
- pencil_free(ro_save_draw_diagram);
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ pencil_code code;
+ const int path[] = {
+ draw_MOVE_TO, line->x0 * 2, -line->y0 * 2 - 1,
+ draw_LINE_TO, line->x1 * 2, -line->y1 * 2 - 1,
+ draw_END_PATH
+ };
- return true;
+ code = pencil_path(ro_save_draw_diagram,
+ path,
+ sizeof path / sizeof path[0],
+ pencil_TRANSPARENT,
+ style->stroke_colour << 8,
+ style->stroke_width,
+ pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0, 0, false,
+ pencil_SOLID);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return NSERROR_OK;
}
-bool ro_save_draw_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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
{
pencil_code code;
- const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
- draw_LINE_TO, x1 * 2, -y0 * 2 - 1,
- draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
- draw_LINE_TO, x0 * 2, -y1 * 2 - 1,
- draw_CLOSE_LINE,
- draw_END_PATH };
+ const int path[] = {
+ draw_MOVE_TO, rect->x0 * 2, -rect->y0 * 2 - 1,
+ draw_LINE_TO, rect->x1 * 2, -rect->y0 * 2 - 1,
+ draw_LINE_TO, rect->x1 * 2, -rect->y1 * 2 - 1,
+ draw_LINE_TO, rect->x0 * 2, -rect->y1 * 2 - 1,
+ draw_CLOSE_LINE,
+ draw_END_PATH
+ };
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
- code = pencil_path(ro_save_draw_diagram,
+ code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
- style->fill_colour << 8,
- pencil_TRANSPARENT,
- 0,
+ style->fill_colour << 8,
+ pencil_TRANSPARENT,
+ 0,
pencil_JOIN_MITRED,
- pencil_CAP_BUTT,
- pencil_CAP_BUTT,
- 0,
- 0,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- code = pencil_path(ro_save_draw_diagram,
+ code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
- pencil_TRANSPARENT,
- style->stroke_colour << 8,
- style->stroke_width,
+ pencil_TRANSPARENT,
+ style->stroke_colour << 8,
+ style->stroke_width,
pencil_JOIN_MITRED,
- pencil_CAP_BUTT,
- pencil_CAP_BUTT,
- 0,
- 0,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
- return true;
-}
-
-
-bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- pencil_code code;
- const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
- draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
- draw_END_PATH };
-
- code = pencil_path(ro_save_draw_diagram,
- path,
- sizeof path / sizeof path[0],
- pencil_TRANSPARENT,
- style->stroke_colour << 8,
- style->stroke_width,
- pencil_JOIN_MITRED,
- pencil_CAP_BUTT,
- pencil_CAP_BUTT,
- 0, 0, false,
- pencil_SOLID);
- if (code != pencil_OK)
- return ro_save_draw_error(code);
-
- return true;
+ return NSERROR_OK;
}
-bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style)
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
pencil_code code;
int path[n * 3 + 1];
@@ -242,44 +283,66 @@ bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *styl
path[0] = draw_MOVE_TO;
path[n * 3] = draw_END_PATH;
- code = pencil_path(ro_save_draw_diagram,
+ code = pencil_path(ro_save_draw_diagram,
path, n * 3 + 1,
- style->fill_colour << 8,
- pencil_TRANSPARENT,
- 0,
+ style->fill_colour << 8,
+ pencil_TRANSPARENT,
+ 0,
pencil_JOIN_MITRED,
- pencil_CAP_BUTT,
- pencil_CAP_BUTT,
- 0,
- 0,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
- return true;
+ return NSERROR_OK;
}
-bool ro_save_draw_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
+ro_save_draw_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
{
+ pencil_code code;
+ int *path;
+ unsigned int i;
+ bool empty_path = true;
+
if (n == 0)
- return true;
+ return NSERROR_OK;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("path doesn't start with a move");
- return false;
+ return NSERROR_INVALID;
}
- int *path = malloc(sizeof *path * (n + 10));
+ path = malloc(sizeof *path * (n + 10));
if (!path) {
LOG("out of memory");
- return false;
+ return NSERROR_INVALID;
}
- unsigned int i;
- bool empty_path = true;
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
path[i] = draw_MOVE_TO;
@@ -328,40 +391,111 @@ bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
} else {
LOG("bad path command %f", p[i]);
free(path);
- return false;
+ return NSERROR_INVALID;
}
}
path[i] = draw_END_PATH;
if (empty_path) {
free(path);
- return true;
+ return NSERROR_OK;
}
- pencil_code code = pencil_path(ro_save_draw_diagram, path, i + 1,
- fill == NS_TRANSPARENT ? pencil_TRANSPARENT : fill << 8,
- c == NS_TRANSPARENT ? pencil_TRANSPARENT : c << 8,
- width, pencil_JOIN_MITRED,
- pencil_CAP_BUTT, pencil_CAP_BUTT, 0, 0, false,
- pencil_SOLID);
+ code = pencil_path(ro_save_draw_diagram,
+ path, i + 1,
+ pstyle->fill_colour == NS_TRANSPARENT ?
+ pencil_TRANSPARENT :
+ pstyle->fill_colour << 8,
+ pstyle->stroke_colour == NS_TRANSPARENT ?
+ pencil_TRANSPARENT :
+ pstyle->stroke_colour << 8,
+ width, pencil_JOIN_MITRED,
+ pencil_CAP_BUTT,
+ pencil_CAP_BUTT,
+ 0,
+ 0,
+ false,
+ pencil_SOLID);
free(path);
if (code != pencil_OK)
return ro_save_draw_error(code);
- return true;
+ return NSERROR_OK;
}
+/**
+ * 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
+{
+ pencil_code code;
+ const uint8_t *buffer;
+ buffer = riscos_bitmap_get_buffer(bitmap);
+ if (!buffer) {
+ ro_warn_user("NoMemory", 0);
+ return NSERROR_INVALID;
+ }
-bool ro_save_draw_clip(const struct rect *clip)
-{
- return true;
+ code = pencil_sprite(ro_save_draw_diagram,
+ x * 2, (-y - height) * 2,
+ width * 2, height * 2,
+ ((char *) bitmap->sprite_area) +
+ bitmap->sprite_area->first);
+ if (code != pencil_OK)
+ return ro_save_draw_error(code);
+
+ return NSERROR_OK;
}
-bool ro_save_draw_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
+ro_save_draw_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
pencil_code code;
const char *font_family;
@@ -371,102 +505,135 @@ bool ro_save_draw_text(int x, int y, const char *text, size_t length,
nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
code = pencil_text(ro_save_draw_diagram, x * 2, -y * 2, font_family,
- font_style, font_size, text, length,
+ font_style, font_size, text, length,
fstyle->foreground << 8);
if (code != pencil_OK)
return ro_save_draw_error(code);
- return true;
+ return NSERROR_OK;
}
-bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style)
-{
- return true;
-}
-
-bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
- const plot_style_t *style)
-{
- return true;
-}
-
-bool ro_save_draw_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
+/**
+ * Start of a group of objects.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_group_start(const struct redraw_context *ctx, const char *name)
{
pencil_code code;
- const uint8_t *buffer;
-
- buffer = riscos_bitmap_get_buffer(bitmap);
- if (!buffer) {
- ro_warn_user("NoMemory", 0);
- return false;
- }
- code = pencil_sprite(ro_save_draw_diagram, x * 2, (-y - height) * 2,
- width * 2, height * 2,
- ((char *) bitmap->sprite_area) +
- bitmap->sprite_area->first);
+ code = pencil_group_start(ro_save_draw_diagram, name);
if (code != pencil_OK)
return ro_save_draw_error(code);
- return true;
+ return NSERROR_OK;
}
-bool ro_save_draw_group_start(const char *name)
+/**
+ * End of the most recently started group.
+ *
+ * \param ctx The current redraw context.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+ro_save_draw_group_end(const struct redraw_context *ctx)
{
pencil_code code;
- code = pencil_group_start(ro_save_draw_diagram, name);
+ code = pencil_group_end(ro_save_draw_diagram);
if (code != pencil_OK)
return ro_save_draw_error(code);
- return true;
+ return NSERROR_OK;
}
-bool ro_save_draw_group_end(void)
+static const struct plotter_table ro_save_draw_plotters = {
+ .rectangle = ro_save_draw_rectangle,
+ .line = ro_save_draw_line,
+ .polygon = ro_save_draw_polygon,
+ .clip = ro_save_draw_clip,
+ .text = ro_save_draw_text,
+ .disc = ro_save_draw_disc,
+ .arc = ro_save_draw_arc,
+ .bitmap = ro_save_draw_bitmap,
+ .group_start = ro_save_draw_group_start,
+ .group_end = ro_save_draw_group_end,
+ .path = ro_save_draw_path,
+ .option_knockout = false,
+};
+
+
+/* exported interface documented in save_draw.h */
+bool save_as_draw(struct hlcache_handle *h, const char *path)
{
pencil_code code;
+ char *drawfile_buffer;
+ struct rect clip;
+ struct content_redraw_data data;
+ size_t drawfile_size;
+ os_error *error;
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &ro_save_draw_plotters
+ };
- code = pencil_group_end(ro_save_draw_diagram);
- if (code != pencil_OK)
- return ro_save_draw_error(code);
+ ro_save_draw_diagram = pencil_create();
+ if (!ro_save_draw_diagram) {
+ ro_warn_user("NoMemory", 0);
+ return false;
+ }
- return true;
-}
+ ro_save_draw_width = content_get_width(h);
+ ro_save_draw_height = content_get_height(h);
+ clip.x0 = clip.y0 = INT_MIN;
+ clip.x1 = clip.y1 = INT_MAX;
-/**
- * Report an error from pencil.
- *
- * \param code error code
- * \return false
- */
+ data.x = 0;
+ data.y = -ro_save_draw_height;
+ data.width = ro_save_draw_width;
+ data.height = ro_save_draw_height;
+ data.background_colour = 0xFFFFFF;
+ data.scale = 1;
+ data.repeat_x = false;
+ data.repeat_y = false;
-bool ro_save_draw_error(pencil_code code)
-{
- LOG("code %i", code);
+ if (!content_redraw(h, &data, &clip, &ctx)) {
+ pencil_free(ro_save_draw_diagram);
+ return false;
+ }
- switch (code) {
- case pencil_OK:
- assert(0);
- break;
- case pencil_OUT_OF_MEMORY:
- ro_warn_user("NoMemory", 0);
- break;
- case pencil_FONT_MANAGER_ERROR:
- ro_warn_user("SaveError", rufl_fm_error->errmess);
- break;
- case pencil_FONT_NOT_FOUND:
- case pencil_IO_ERROR:
- case pencil_IO_EOF:
- ro_warn_user("SaveError", "generating the DrawFile failed");
- break;
+ /*pencil_dump(ro_save_draw_diagram);*/
+
+ code = pencil_save_drawfile(ro_save_draw_diagram, "NetSurf",
+ &drawfile_buffer, &drawfile_size);
+ if (code != pencil_OK) {
+ ro_warn_user("SaveError", 0);
+ pencil_free(ro_save_draw_diagram);
+ return false;
}
+ assert(drawfile_buffer);
- return false;
+ error = xosfile_save_stamped(path, osfile_TYPE_DRAW,
+ (byte *) drawfile_buffer,
+ (byte *) drawfile_buffer + drawfile_size);
+ if (error) {
+ LOG("xosfile_save_stamped failed: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("SaveError", error->errmess);
+ pencil_free(ro_save_draw_diagram);
+ return false;
+ }
+
+ pencil_free(ro_save_draw_diagram);
+
+ return true;
}
#endif
diff --git a/frontends/riscos/save_draw.h b/frontends/riscos/save_draw.h
index 7ae4477..99662e3 100644
--- a/frontends/riscos/save_draw.h
+++ b/frontends/riscos/save_draw.h
@@ -24,6 +24,13 @@
#include <stdbool.h>
struct hlcache_handle;
+/**
+ * Export a content as a DrawFile.
+ *
+ * \param h content to export
+ * \param path path to save DrawFile as
+ * \return true on success, false on error and error reported
+ */
bool save_as_draw(struct hlcache_handle *h, const char *path);
#endif
diff --git a/frontends/windows/plot.c b/frontends/windows/plot.c
index fd29619..5b7648e 100644
--- a/frontends/windows/plot.c
+++ b/frontends/windows/plot.c
@@ -50,341 +50,331 @@ HDC plot_hdc;
static RECT plot_clip; /* currently set clipping rectangle */
-static bool clip(const struct rect *clip)
-{
- PLOT_LOG("clip %d,%d to %d,%d", clip->x0, clip->y0, clip->x1, clip->y1);
-
- plot_clip.left = clip->x0;
- plot_clip.top = clip->y0;
- plot_clip.right = clip->x1 + 1; /* co-ordinates are exclusive */
- plot_clip.bottom = clip->y1 + 1; /* co-ordinates are exclusive */
-
- return true;
-}
-static bool line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+/**
+ * bitmap helper to plot a solid block of colour
+ *
+ * \param col colour to plot with
+ * \param x the x coordinate to plot at
+ * \param y the y coordinate to plot at
+ * \param width the width of block to plot
+ * \param height the height to plot
+ * \return NSERROR_OK on sucess else error code.
+ */
+static nserror
+plot_block(COLORREF col, int x, int y, int width, int height)
{
- PLOT_LOG("from %d,%d to %d,%d", x0, y0, x1, y1);
+ HRGN clipregion;
+ HGDIOBJ original = NULL;
+
+ /* Bail early if we can */
+ if ((x >= plot_clip.right) ||
+ ((x + width) < plot_clip.left) ||
+ (y >= plot_clip.bottom) ||
+ ((y + height) < plot_clip.top)) {
+ /* Image completely outside clip region */
+ return NSERROR_OK;
+ }
/* ensure the plot HDC is set */
if (plot_hdc == NULL) {
LOG("HDC not set on call to plotters");
- return false;
+ return NSERROR_INVALID;
}
- HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
+ clipregion = CreateRectRgnIndirect(&plot_clip);
if (clipregion == NULL) {
- return false;
+ return NSERROR_INVALID;
}
- COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF);
- /* windows 0x00bbggrr */
- DWORD penstyle = PS_GEOMETRIC | ((style->stroke_type ==
- PLOT_OP_TYPE_DOT) ? PS_DOT :
- (style->stroke_type == PLOT_OP_TYPE_DASH) ? PS_DASH:
- 0);
- LOGBRUSH lb = {BS_SOLID, col, 0};
- HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
- if (pen == NULL) {
- DeleteObject(clipregion);
- return false;
- }
- HGDIOBJ bak = SelectObject(plot_hdc, (HGDIOBJ) pen);
- if (bak == NULL) {
- DeleteObject(pen);
- DeleteObject(clipregion);
- return false;
- }
-/*
- RECT r;
- r.left = x0;
- r.top = y0;
- r.right = x1;
- r.bottom = y1;
-*/
SelectClipRgn(plot_hdc, clipregion);
- MoveToEx(plot_hdc, x0, y0, (LPPOINT) NULL);
+ /* Saving the original pen object */
+ original = SelectObject(plot_hdc,GetStockObject(DC_PEN));
- LineTo(plot_hdc, x1, y1);
+ SelectObject(plot_hdc, GetStockObject(DC_PEN));
+ SelectObject(plot_hdc, GetStockObject(DC_BRUSH));
+ SetDCPenColor(plot_hdc, col);
+ SetDCBrushColor(plot_hdc, col);
+ Rectangle(plot_hdc, x, y, width, height);
- SelectClipRgn(plot_hdc, NULL);
- pen = SelectObject(plot_hdc, bak);
+ SelectObject(plot_hdc,original); /* Restoring the original pen object */
- DeleteObject(pen);
DeleteObject(clipregion);
- return true;
+ return NSERROR_OK;
+
}
-static bool rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- PLOT_LOG("rectangle from %d,%d to %d,%d", x0, y0, x1, y1);
- /* ensure the plot HDC is set */
- if (plot_hdc == NULL) {
- LOG("HDC not set on call to plotters");
- return false;
- }
-
- HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
- if (clipregion == NULL) {
- return false;
+/**
+ * plot an alpha blended bitmap
+ *
+ * blunt force truma way of achiving alpha blended plotting
+ */
+static nserror
+plot_alpha_bitmap(HDC hdc,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width, int height)
+{
+#ifdef WINDOWS_GDI_ALPHA_WORKED
+ BLENDFUNCTION blnd = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA };
+ HDC bmihdc;
+ bool bltres;
+ bmihdc = CreateCompatibleDC(hdc);
+ SelectObject(bmihdc, bitmap->windib);
+ bltres = AlphaBlend(hdc,
+ x, y,
+ width, height,
+ bmihdc,
+ 0, 0,
+ bitmap->width, bitmap->height,
+ blnd);
+ DeleteDC(bmihdc);
+ if (!bltres) {
+ return NSERROR_INVALID;
}
+#else
+ HDC Memhdc;
+ BITMAPINFOHEADER bmih;
+ int v, vv, vi, h, hh, width4, transparency;
+ unsigned char alpha;
+ bool isscaled = false; /* set if the scaled bitmap requires freeing */
+ BITMAP MemBM;
+ BITMAPINFO *bmi;
+ HBITMAP MemBMh;
- x1++;
- y1++;
-
- COLORREF pencol = (DWORD)(style->stroke_colour & 0x00FFFFFF);
- DWORD penstyle = PS_GEOMETRIC |
- (style->stroke_type == PLOT_OP_TYPE_DOT ? PS_DOT :
- (style->stroke_type == PLOT_OP_TYPE_DASH ? PS_DASH :
- (style->stroke_type == PLOT_OP_TYPE_NONE ? PS_NULL :
- 0)));
- LOGBRUSH lb = {BS_SOLID, pencol, 0};
- LOGBRUSH lb1 = {BS_SOLID, style->fill_colour, 0};
- if (style->fill_type == PLOT_OP_TYPE_NONE)
- lb1.lbStyle = BS_HOLLOW;
+ PLOT_LOG("%p bitmap %d,%d width %d height %d", bitmap, x, y, width, height);
+ PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom);
- HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
- if (pen == NULL) {
- return false;
- }
- HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen);
- if (penbak == NULL) {
- DeleteObject(pen);
- return false;
- }
- HBRUSH brush = CreateBrushIndirect(&lb1);
- if (brush == NULL) {
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- return false;
- }
- HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush);
- if (brushbak == NULL) {
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- DeleteObject(brush);
- return false;
+ Memhdc = CreateCompatibleDC(hdc);
+ if (Memhdc == NULL) {
+ return NSERROR_INVALID;
}
- SelectClipRgn(plot_hdc, clipregion);
-
- Rectangle(plot_hdc, x0, y0, x1, y1);
+ if ((bitmap->width != width) ||
+ (bitmap->height != height)) {
+ PLOT_LOG("scaling from %d,%d to %d,%d",
+ bitmap->width, bitmap->height, width, height);
+ bitmap = bitmap_scale(bitmap, width, height);
+ if (bitmap == NULL) {
+ return NSERROR_INVALID;
+ }
+ isscaled = true;
+ }
- pen = SelectObject(plot_hdc, penbak);
- brush = SelectObject(plot_hdc, brushbak);
- SelectClipRgn(plot_hdc, NULL);
- DeleteObject(pen);
- DeleteObject(brush);
- DeleteObject(clipregion);
+ bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) +
+ (bitmap->width * bitmap->height * 4));
+ if (bmi == NULL) {
+ DeleteDC(Memhdc);
+ return NSERROR_INVALID;
+ }
- return true;
-}
+ MemBMh = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height);
+ if (MemBMh == NULL){
+ free(bmi);
+ DeleteDC(Memhdc);
+ return NSERROR_INVALID;
+ }
+ /* save 'background' data for alpha channel work */
+ SelectObject(Memhdc, MemBMh);
+ BitBlt(Memhdc, 0, 0, bitmap->width, bitmap->height, hdc, x, y, SRCCOPY);
+ GetObject(MemBMh, sizeof(BITMAP), &MemBM);
-static bool polygon(const int *p, unsigned int n, const plot_style_t *style)
-{
- PLOT_LOG("polygon %d points", n);
+ bmih.biSize = sizeof(bmih);
+ bmih.biWidth = bitmap->width;
+ bmih.biHeight = bitmap->height;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = BI_RGB;
+ bmih.biSizeImage = 4 * bitmap->height * bitmap->width;
+ bmih.biXPelsPerMeter = 3600; /* 100 dpi */
+ bmih.biYPelsPerMeter = 3600;
+ bmih.biClrUsed = 0;
+ bmih.biClrImportant = 0;
+ bmi->bmiHeader = bmih;
- /* ensure the plot HDC is set */
- if (plot_hdc == NULL) {
- LOG("HDC not set on call to plotters");
- return false;
- }
+ GetDIBits(hdc, MemBMh, 0, bitmap->height, bmi->bmiColors, bmi,
+ DIB_RGB_COLORS);
- POINT points[n];
- unsigned int i;
- HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
- if (clipregion == NULL) {
- return false;
- }
+ /* then load 'foreground' bits from bitmap->pixdata */
- COLORREF pencol = (DWORD)(style->fill_colour & 0x00FFFFFF);
- COLORREF brushcol = (DWORD)(style->fill_colour & 0x00FFFFFF);
- HPEN pen = CreatePen(PS_GEOMETRIC | PS_NULL, 1, pencol);
- if (pen == NULL) {
- DeleteObject(clipregion);
- return false;
- }
- HPEN penbak = SelectObject(plot_hdc, pen);
- if (penbak == NULL) {
- DeleteObject(clipregion);
- DeleteObject(pen);
- return false;
- }
- HBRUSH brush = CreateSolidBrush(brushcol);
- if (brush == NULL) {
- DeleteObject(clipregion);
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- return false;
- }
- HBRUSH brushbak = SelectObject(plot_hdc, brush);
- if (brushbak == NULL) {
- DeleteObject(clipregion);
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- DeleteObject(brush);
- return false;
+ width4 = bitmap->width * 4;
+ for (v = 0, vv = 0, vi = (bitmap->height - 1) * width4;
+ v < bitmap->height;
+ v++, vv += bitmap->width, vi -= width4) {
+ for (h = 0, hh = 0; h < bitmap->width; h++, hh += 4) {
+ alpha = bitmap->pixdata[vi + hh + 3];
+/* multiplication of alpha value; subject to profiling could be optional */
+ if (alpha == 0xFF) {
+ bmi->bmiColors[vv + h].rgbBlue =
+ bitmap->pixdata[vi + hh + 2];
+ bmi->bmiColors[vv + h].rgbGreen =
+ bitmap->pixdata[vi + hh + 1];
+ bmi->bmiColors[vv + h].rgbRed =
+ bitmap->pixdata[vi + hh];
+ } else if (alpha > 0) {
+ transparency = 0x100 - alpha;
+ bmi->bmiColors[vv + h].rgbBlue =
+ (bmi->bmiColors[vv + h].rgbBlue
+ * transparency +
+ (bitmap->pixdata[vi + hh + 2]) *
+ alpha) >> 8;
+ bmi->bmiColors[vv + h].rgbGreen =
+ (bmi->bmiColors[vv + h].
+ rgbGreen
+ * transparency +
+ (bitmap->pixdata[vi + hh + 1]) *
+ alpha) >> 8;
+ bmi->bmiColors[vv + h].rgbRed =
+ (bmi->bmiColors[vv + h].rgbRed
+ * transparency +
+ bitmap->pixdata[vi + hh]
+ * alpha) >> 8;
+ }
+ }
}
- SetPolyFillMode(plot_hdc, WINDING);
- for (i = 0; i < n; i++) {
- points[i].x = (long) p[2 * i];
- points[i].y = (long) p[2 * i + 1];
+ SetDIBitsToDevice(hdc, x, y, bitmap->width, bitmap->height,
+ 0, 0, 0, bitmap->height,
+ (const void *) bmi->bmiColors,
+ bmi, DIB_RGB_COLORS);
- PLOT_LOG("%ld,%ld ", points[i].x, points[i].y);
+ if (isscaled && bitmap && bitmap->pixdata) {
+ free(bitmap->pixdata);
+ free(bitmap);
}
- SelectClipRgn(plot_hdc, clipregion);
-
- if (n >= 2)
- Polygon(plot_hdc, points, n);
-
- SelectClipRgn(plot_hdc, NULL);
-
- pen = SelectObject(plot_hdc, penbak);
- brush = SelectObject(plot_hdc, brushbak);
- DeleteObject(clipregion);
- DeleteObject(pen);
- DeleteObject(brush);
+ free(bmi);
+ DeleteObject(MemBMh);
+ DeleteDC(Memhdc);
+#endif
- return true;
+ return NSERROR_OK;
}
-static bool text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *style)
+/**
+ */
+static nserror
+plot_bitmap(struct bitmap *bitmap, int x, int y, int width, int height)
{
- PLOT_LOG("words %s at %d,%d", text, x, y);
+ HRGN clipregion;
+ nserror res = NSERROR_OK;
+
+ /* Bail early if we can */
+ if ((x >= plot_clip.right) ||
+ ((x + width) < plot_clip.left) ||
+ (y >= plot_clip.bottom) ||
+ ((y + height) < plot_clip.top)) {
+ /* Image completely outside clip region */
+ return NSERROR_OK;
+ }
/* ensure the plot HDC is set */
if (plot_hdc == NULL) {
LOG("HDC not set on call to plotters");
- return false;
+ return NSERROR_INVALID;
}
- HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
+ clipregion = CreateRectRgnIndirect(&plot_clip);
if (clipregion == NULL) {
- return false;
- }
-
- HFONT fontbak, font = get_font(style);
- if (font == NULL) {
- DeleteObject(clipregion);
- return false;
+ return NSERROR_INVALID;
}
- int wlen;
- SIZE s;
- LPWSTR wstring;
- fontbak = (HFONT) SelectObject(plot_hdc, font);
- GetTextExtentPoint(plot_hdc, text, length, &s);
-/*
- RECT r;
- r.left = x;
- r.top = y - (3 * s.cy) / 4;
- r.right = x + s.cx;
- r.bottom = y + s.cy / 4;
-*/
SelectClipRgn(plot_hdc, clipregion);
- SetTextAlign(plot_hdc, TA_BASELINE | TA_LEFT);
- if ((style->background & 0xFF000000) != 0x01000000)
- /* 100% alpha */
- SetBkColor(plot_hdc, (DWORD) (style->background & 0x00FFFFFF));
- SetBkMode(plot_hdc, TRANSPARENT);
- SetTextColor(plot_hdc, (DWORD) (style->foreground & 0x00FFFFFF));
+ if (bitmap->opaque) {
+ int bltres;
+ /* opaque bitmap */
+ if ((bitmap->width == width) &&
+ (bitmap->height == height)) {
+ /* unscaled */
+ bltres = SetDIBitsToDevice(plot_hdc,
+ x, y,
+ width, height,
+ 0, 0,
+ 0,
+ height,
+ bitmap->pixdata,
+ (BITMAPINFO *)bitmap->pbmi,
+ DIB_RGB_COLORS);
+ } else {
+ /* scaled */
+ SetStretchBltMode(plot_hdc, COLORONCOLOR);
+ bltres = StretchDIBits(plot_hdc,
+ x, y,
+ width, height,
+ 0, 0,
+ bitmap->width, bitmap->height,
+ bitmap->pixdata,
+ (BITMAPINFO *)bitmap->pbmi,
+ DIB_RGB_COLORS,
+ SRCCOPY);
- wlen = MultiByteToWideChar(CP_UTF8, 0, text, length, NULL, 0);
- wstring = malloc(2 * (wlen + 1));
- if (wstring == NULL) {
- return false;
+
+ }
+ /* check to see if GDI operation failed */
+ if (bltres == 0) {
+ res = NSERROR_INVALID;
+ }
+ PLOT_LOG("bltres = %d", bltres);
+ } else {
+ /* Bitmap with alpha.*/
+ res = plot_alpha_bitmap(plot_hdc, bitmap, x, y, width, height);
}
- MultiByteToWideChar(CP_UTF8, 0, text, length, wstring, wlen);
- TextOutW(plot_hdc, x, y, wstring, wlen);
- SelectClipRgn(plot_hdc, NULL);
- free(wstring);
- font = SelectObject(plot_hdc, fontbak);
DeleteObject(clipregion);
- DeleteObject(font);
- return true;
+ return res;
}
-static bool disc(int x, int y, int radius, const plot_style_t *style)
-{
- PLOT_LOG("disc at %d,%d radius %d", x, y, radius);
- /* ensure the plot HDC is set */
- if (plot_hdc == NULL) {
- LOG("HDC not set on call to plotters");
- return false;
- }
- HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
- if (clipregion == NULL) {
- return false;
- }
- COLORREF col = (DWORD)((style->fill_colour | style->stroke_colour)
- & 0x00FFFFFF);
- HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col);
- if (pen == NULL) {
- DeleteObject(clipregion);
- return false;
- }
- HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen);
- if (penbak == NULL) {
- DeleteObject(clipregion);
- DeleteObject(pen);
- return false;
- }
- HBRUSH brush = CreateSolidBrush(col);
- if (brush == NULL) {
- DeleteObject(clipregion);
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- return false;
- }
- HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush);
- if (brushbak == NULL) {
- DeleteObject(clipregion);
- SelectObject(plot_hdc, penbak);
- DeleteObject(pen);
- DeleteObject(brush);
- return false;
- }
-/*
- RECT r;
- r.left = x - radius;
- r.top = y - radius;
- r.right = x + radius;
- r.bottom = y + radius;
-*/
- SelectClipRgn(plot_hdc, clipregion);
-
- if (style->fill_type == PLOT_OP_TYPE_NONE)
- Arc(plot_hdc, x - radius, y - radius, x + radius, y + radius,
- x - radius, y - radius,
- x - radius, y - radius);
- else
- Ellipse(plot_hdc, x - radius, y - radius, x + radius, y + radius);
+/**
+ * \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 clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ PLOT_LOG("clip %d,%d to %d,%d", clip->x0, clip->y0, clip->x1, clip->y1);
- SelectClipRgn(plot_hdc, NULL);
- pen = SelectObject(plot_hdc, penbak);
- brush = SelectObject(plot_hdc, brushbak);
- DeleteObject(clipregion);
- DeleteObject(pen);
- DeleteObject(brush);
+ plot_clip.left = clip->x0;
+ plot_clip.top = clip->y0;
+ plot_clip.right = clip->x1 + 1; /* co-ordinates are exclusive */
+ plot_clip.bottom = clip->y1 + 1; /* co-ordinates are exclusive */
- return true;
+ return NSERROR_OK;
}
-static bool 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.
+ * \param pstyle Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y,
+ int radius, int angle1, int angle2)
{
PLOT_LOG("arc centre %d,%d radius %d from %d to %d", x, y, radius,
angle1, angle2);
@@ -392,25 +382,25 @@ static bool arc(int x, int y, int radius, int angle1, int angle2,
/* ensure the plot HDC is set */
if (plot_hdc == NULL) {
LOG("HDC not set on call to plotters");
- return false;
+ return NSERROR_INVALID;
}
HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
if (clipregion == NULL) {
- return false;
+ return NSERROR_INVALID;
}
COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF);
HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col);
if (pen == NULL) {
DeleteObject(clipregion);
- return false;
+ return NSERROR_INVALID;
}
HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen);
if (penbak == NULL) {
DeleteObject(clipregion);
DeleteObject(pen);
- return false;
+ return NSERROR_INVALID;
}
int q1, q2;
@@ -466,13 +456,6 @@ static bool arc(int x, int y, int radius, int angle1, int angle2,
break;
}
-/*
- RECT r;
- r.left = x - radius;
- r.top = y - radius;
- r.right = x + radius;
- r.bottom = y + radius;
-*/
SelectClipRgn(plot_hdc, clipregion);
Arc(plot_hdc, x - radius, y - radius, x + radius, y + radius,
@@ -484,269 +467,384 @@ static bool arc(int x, int y, int radius, int angle1, int angle2,
DeleteObject(clipregion);
DeleteObject(pen);
- return true;
+ return NSERROR_OK;
}
-static bool
-plot_block(COLORREF col, int x, int y, int width, int height)
-{
- HRGN clipregion;
- HGDIOBJ original = NULL;
- /* Bail early if we can */
- if ((x >= plot_clip.right) ||
- ((x + width) < plot_clip.left) ||
- (y >= plot_clip.bottom) ||
- ((y + height) < plot_clip.top)) {
- /* Image completely outside clip region */
- return true;
- }
+/**
+ * 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.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ PLOT_LOG("disc at %d,%d radius %d", x, y, radius);
/* ensure the plot HDC is set */
if (plot_hdc == NULL) {
LOG("HDC not set on call to plotters");
- return false;
+ return NSERROR_INVALID;
}
- clipregion = CreateRectRgnIndirect(&plot_clip);
+ HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
if (clipregion == NULL) {
- return false;
+ return NSERROR_INVALID;
}
- SelectClipRgn(plot_hdc, clipregion);
-
- /* Saving the original pen object */
- original = SelectObject(plot_hdc,GetStockObject(DC_PEN));
+ COLORREF col = (DWORD)((style->fill_colour | style->stroke_colour)
+ & 0x00FFFFFF);
+ HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ return NSERROR_INVALID;
+ }
+ HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HBRUSH brush = CreateSolidBrush(col);
+ if (brush == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush);
+ if (brushbak == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ return NSERROR_INVALID;
+ }
- SelectObject(plot_hdc, GetStockObject(DC_PEN));
- SelectObject(plot_hdc, GetStockObject(DC_BRUSH));
- SetDCPenColor(plot_hdc, col);
- SetDCBrushColor(plot_hdc, col);
- Rectangle(plot_hdc, x, y, width, height);
+ SelectClipRgn(plot_hdc, clipregion);
- SelectObject(plot_hdc,original); /* Restoring the original pen object */
+ if (style->fill_type == PLOT_OP_TYPE_NONE) {
+ Arc(plot_hdc, x - radius, y - radius, x + radius, y + radius,
+ x - radius, y - radius,
+ x - radius, y - radius);
+ } else {
+ Ellipse(plot_hdc, x - radius, y - radius, x + radius, y + radius);
+ }
+ SelectClipRgn(plot_hdc, NULL);
+ pen = SelectObject(plot_hdc, penbak);
+ brush = SelectObject(plot_hdc, brushbak);
DeleteObject(clipregion);
+ DeleteObject(pen);
+ DeleteObject(brush);
- return true;
-
+ return NSERROR_OK;
}
-/* blunt force truma way of achiving alpha blended plotting */
-static bool
-plot_alpha_bitmap(HDC hdc,
- struct bitmap *bitmap,
- int x, int y,
- int width, int height)
-{
-#ifdef WINDOWS_GDI_ALPHA_WORKED
- BLENDFUNCTION blnd = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA };
- HDC bmihdc;
- bool bltres;
- bmihdc = CreateCompatibleDC(hdc);
- SelectObject(bmihdc, bitmap->windib);
- bltres = AlphaBlend(hdc,
- x, y,
- width, height,
- bmihdc,
- 0, 0,
- bitmap->width, bitmap->height,
- blnd);
- DeleteDC(bmihdc);
- return bltres;
-#else
- HDC Memhdc;
- BITMAPINFOHEADER bmih;
- int v, vv, vi, h, hh, width4, transparency;
- unsigned char alpha;
- bool isscaled = false; /* set if the scaled bitmap requires freeing */
- BITMAP MemBM;
- BITMAPINFO *bmi;
- HBITMAP MemBMh;
- PLOT_LOG("%p bitmap %d,%d width %d height %d", bitmap, x, y, width, height);
- PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom);
+/**
+ * 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.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ PLOT_LOG("from %d,%d to %d,%d", x0, y0, x1, y1);
- Memhdc = CreateCompatibleDC(hdc);
- if (Memhdc == NULL) {
- return false;
+ /* ensure the plot HDC is set */
+ if (plot_hdc == NULL) {
+ LOG("HDC not set on call to plotters");
+ return NSERROR_INVALID;
}
- if ((bitmap->width != width) ||
- (bitmap->height != height)) {
- PLOT_LOG("scaling from %d,%d to %d,%d",
- bitmap->width, bitmap->height, width, height);
- bitmap = bitmap_scale(bitmap, width, height);
- if (bitmap == NULL)
- return false;
- isscaled = true;
+ HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
+ if (clipregion == NULL) {
+ return NSERROR_INVALID;
}
- bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) +
- (bitmap->width * bitmap->height * 4));
- if (bmi == NULL) {
- DeleteDC(Memhdc);
- return false;
+ COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF);
+ /* windows 0x00bbggrr */
+ DWORD penstyle = PS_GEOMETRIC | ((style->stroke_type ==
+ PLOT_OP_TYPE_DOT) ? PS_DOT :
+ (style->stroke_type == PLOT_OP_TYPE_DASH) ? PS_DASH:
+ 0);
+ LOGBRUSH lb = {BS_SOLID, col, 0};
+ HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ return NSERROR_INVALID;
+ }
+ HGDIOBJ bak = SelectObject(plot_hdc, (HGDIOBJ) pen);
+ if (bak == NULL) {
+ DeleteObject(pen);
+ DeleteObject(clipregion);
+ return NSERROR_INVALID;
}
- MemBMh = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height);
- if (MemBMh == NULL){
- free(bmi);
- DeleteDC(Memhdc);
- return false;
- }
+ SelectClipRgn(plot_hdc, clipregion);
+
+ MoveToEx(plot_hdc, line->x0, line->y0, (LPPOINT) NULL);
+
+ LineTo(plot_hdc, line->x1, line->y1);
+
+ SelectClipRgn(plot_hdc, NULL);
+ pen = SelectObject(plot_hdc, bak);
+
+ DeleteObject(pen);
+ DeleteObject(clipregion);
- /* save 'background' data for alpha channel work */
- SelectObject(Memhdc, MemBMh);
- BitBlt(Memhdc, 0, 0, bitmap->width, bitmap->height, hdc, x, y, SRCCOPY);
- GetObject(MemBMh, sizeof(BITMAP), &MemBM);
+ return NSERROR_OK;
+}
- bmih.biSize = sizeof(bmih);
- bmih.biWidth = bitmap->width;
- bmih.biHeight = bitmap->height;
- bmih.biPlanes = 1;
- bmih.biBitCount = 32;
- bmih.biCompression = BI_RGB;
- bmih.biSizeImage = 4 * bitmap->height * bitmap->width;
- bmih.biXPelsPerMeter = 3600; /* 100 dpi */
- bmih.biYPelsPerMeter = 3600;
- bmih.biClrUsed = 0;
- bmih.biClrImportant = 0;
- bmi->bmiHeader = bmih;
- GetDIBits(hdc, MemBMh, 0, bitmap->height, bmi->bmiColors, bmi,
- DIB_RGB_COLORS);
+/**
+ * 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.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
+{
+ PLOT_LOG("rectangle from %d,%d to %d,%d",
+ rect->x0, rect->y0, rect->x1, rect->y1);
- /* then load 'foreground' bits from bitmap->pixdata */
+ /* ensure the plot HDC is set */
+ if (plot_hdc == NULL) {
+ LOG("HDC not set on call to plotters");
+ return NSERROR_INVALID;
+ }
- width4 = bitmap->width * 4;
- for (v = 0, vv = 0, vi = (bitmap->height - 1) * width4;
- v < bitmap->height;
- v++, vv += bitmap->width, vi -= width4) {
- for (h = 0, hh = 0; h < bitmap->width; h++, hh += 4) {
- alpha = bitmap->pixdata[vi + hh + 3];
-/* multiplication of alpha value; subject to profiling could be optional */
- if (alpha == 0xFF) {
- bmi->bmiColors[vv + h].rgbBlue =
- bitmap->pixdata[vi + hh + 2];
- bmi->bmiColors[vv + h].rgbGreen =
- bitmap->pixdata[vi + hh + 1];
- bmi->bmiColors[vv + h].rgbRed =
- bitmap->pixdata[vi + hh];
- } else if (alpha > 0) {
- transparency = 0x100 - alpha;
- bmi->bmiColors[vv + h].rgbBlue =
- (bmi->bmiColors[vv + h].rgbBlue
- * transparency +
- (bitmap->pixdata[vi + hh + 2]) *
- alpha) >> 8;
- bmi->bmiColors[vv + h].rgbGreen =
- (bmi->bmiColors[vv + h].
- rgbGreen
- * transparency +
- (bitmap->pixdata[vi + hh + 1]) *
- alpha) >> 8;
- bmi->bmiColors[vv + h].rgbRed =
- (bmi->bmiColors[vv + h].rgbRed
- * transparency +
- bitmap->pixdata[vi + hh]
- * alpha) >> 8;
- }
- }
+ HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
+ if (clipregion == NULL) {
+ return NSERROR_INVALID;
}
- SetDIBitsToDevice(hdc, x, y, bitmap->width, bitmap->height,
- 0, 0, 0, bitmap->height,
- (const void *) bmi->bmiColors,
- bmi, DIB_RGB_COLORS);
- if (isscaled && bitmap && bitmap->pixdata) {
- free(bitmap->pixdata);
- free(bitmap);
+ COLORREF pencol = (DWORD)(style->stroke_colour & 0x00FFFFFF);
+ DWORD penstyle = PS_GEOMETRIC |
+ (style->stroke_type == PLOT_OP_TYPE_DOT ? PS_DOT :
+ (style->stroke_type == PLOT_OP_TYPE_DASH ? PS_DASH :
+ (style->stroke_type == PLOT_OP_TYPE_NONE ? PS_NULL :
+ 0)));
+ LOGBRUSH lb = {BS_SOLID, pencol, 0};
+ LOGBRUSH lb1 = {BS_SOLID, style->fill_colour, 0};
+ if (style->fill_type == PLOT_OP_TYPE_NONE)
+ lb1.lbStyle = BS_HOLLOW;
+
+ HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ if (pen == NULL) {
+ return NSERROR_INVALID;
+ }
+ HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen);
+ if (penbak == NULL) {
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HBRUSH brush = CreateBrushIndirect(&lb1);
+ if (brush == NULL) {
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush);
+ if (brushbak == NULL) {
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ return NSERROR_INVALID;
}
- free(bmi);
- DeleteObject(MemBMh);
- DeleteDC(Memhdc);
- return true;
-#endif
+ SelectClipRgn(plot_hdc, clipregion);
+
+ /* windows GDI call coordinates are inclusive */
+ Rectangle(plot_hdc, rect->x0, rect->y0, rect->x1 + 1, rect->y1 + 1);
+
+ pen = SelectObject(plot_hdc, penbak);
+ brush = SelectObject(plot_hdc, brushbak);
+ SelectClipRgn(plot_hdc, NULL);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ DeleteObject(clipregion);
+
+ return NSERROR_OK;
}
-static bool
-plot_bitmap(struct bitmap *bitmap, int x, int y, int width, int height)
+/**
+ * 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
{
- int bltres;
- HRGN clipregion;
-
- /* Bail early if we can */
- if ((x >= plot_clip.right) ||
- ((x + width) < plot_clip.left) ||
- (y >= plot_clip.bottom) ||
- ((y + height) < plot_clip.top)) {
- /* Image completely outside clip region */
- return true;
- }
+ PLOT_LOG("polygon %d points", n);
/* ensure the plot HDC is set */
if (plot_hdc == NULL) {
LOG("HDC not set on call to plotters");
- return false;
+ return NSERROR_INVALID;
}
- clipregion = CreateRectRgnIndirect(&plot_clip);
+ POINT points[n];
+ unsigned int i;
+ HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
if (clipregion == NULL) {
- return false;
+ return NSERROR_INVALID;
}
- SelectClipRgn(plot_hdc, clipregion);
+ COLORREF pencol = (DWORD)(style->fill_colour & 0x00FFFFFF);
+ COLORREF brushcol = (DWORD)(style->fill_colour & 0x00FFFFFF);
+ HPEN pen = CreatePen(PS_GEOMETRIC | PS_NULL, 1, pencol);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ return NSERROR_INVALID;
+ }
+ HPEN penbak = SelectObject(plot_hdc, pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HBRUSH brush = CreateSolidBrush(brushcol);
+ if (brush == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ return NSERROR_INVALID;
+ }
+ HBRUSH brushbak = SelectObject(plot_hdc, brush);
+ if (brushbak == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(plot_hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ return NSERROR_INVALID;
+ }
+ SetPolyFillMode(plot_hdc, WINDING);
+ for (i = 0; i < n; i++) {
+ points[i].x = (long) p[2 * i];
+ points[i].y = (long) p[2 * i + 1];
- if (bitmap->opaque) {
- /* opaque bitmap */
- if ((bitmap->width == width) &&
- (bitmap->height == height)) {
- /* unscaled */
- bltres = SetDIBitsToDevice(plot_hdc,
- x, y,
- width, height,
- 0, 0,
- 0,
- height,
- bitmap->pixdata,
- (BITMAPINFO *)bitmap->pbmi,
- DIB_RGB_COLORS);
- } else {
- /* scaled */
- SetStretchBltMode(plot_hdc, COLORONCOLOR);
- bltres = StretchDIBits(plot_hdc,
- x, y,
- width, height,
- 0, 0,
- bitmap->width, bitmap->height,
- bitmap->pixdata,
- (BITMAPINFO *)bitmap->pbmi,
- DIB_RGB_COLORS,
- SRCCOPY);
+ PLOT_LOG("%ld,%ld ", points[i].x, points[i].y);
+ }
+ SelectClipRgn(plot_hdc, clipregion);
- }
- } else {
- /* Bitmap with alpha.*/
- bltres = plot_alpha_bitmap(plot_hdc, bitmap, x, y, width, height);
+ if (n >= 2) {
+ Polygon(plot_hdc, points, n);
}
- PLOT_LOG("bltres = %d", bltres);
+ SelectClipRgn(plot_hdc, NULL);
+ pen = SelectObject(plot_hdc, penbak);
+ brush = SelectObject(plot_hdc, brushbak);
DeleteObject(clipregion);
+ DeleteObject(pen);
+ DeleteObject(brush);
+
+ return NSERROR_OK;
+}
- return true;
+/**
+ * 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
+path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
+{
+ PLOT_LOG("path unimplemented");
+ return NSERROR_OK;
}
-static bool
-windows_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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
int xf,yf;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
@@ -758,12 +856,12 @@ windows_plot_bitmap(int x, int y,
if (bitmap == NULL) {
LOG("Passed null bitmap!");
- return true;
+ return NSERROR_OK;
}
/* check if nothing to plot */
if (width == 0 || height == 0)
- return true;
+ return NSERROR_OK;
/* x and y define coordinate of top left of of the initial explicitly
* placed tile. The width and height are the image scaling and the
@@ -775,7 +873,7 @@ windows_plot_bitmap(int x, int y,
/* Not repeating at all, so just plot it */
if ((bitmap->width == 1) && (bitmap->height == 1)) {
if ((*(bitmap->pixdata + 3) & 0xff) == 0) {
- return true;
+ return NSERROR_OK;
}
return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff, x, y, x + width, y + height);
@@ -788,10 +886,10 @@ windows_plot_bitmap(int x, int y,
* of the area. Can only be done when image is fully opaque. */
if ((bitmap->width == 1) && (bitmap->height == 1)) {
if ((*(COLORREF *)bitmap->pixdata & 0xff000000) != 0) {
- return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff,
- plot_clip.left,
- plot_clip.top,
- plot_clip.right,
+ return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff,
+ plot_clip.left,
+ plot_clip.top,
+ plot_clip.right,
plot_clip.bottom);
}
}
@@ -803,10 +901,10 @@ windows_plot_bitmap(int x, int y,
if (bitmap->opaque) {
/** TODO: Currently using top left pixel. Maybe centre
* pixel or average value would be better. */
- return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff,
- plot_clip.left,
- plot_clip.top,
- plot_clip.right,
+ return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff,
+ plot_clip.left,
+ plot_clip.top,
+ plot_clip.right,
plot_clip.bottom);
}
}
@@ -815,12 +913,14 @@ windows_plot_bitmap(int x, int y,
PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom);
/* get left most tile position */
- if (repeat_x)
+ if (repeat_x) {
for (; x > plot_clip.left; x -= width);
+ }
/* get top most tile position */
- if (repeat_y)
+ if (repeat_y) {
for (; y > plot_clip.top; y -= height);
+ }
PLOT_LOG("repeat from %d,%d to %ld,%ld", x, y, plot_clip.right, plot_clip.bottom);
@@ -833,25 +933,86 @@ windows_plot_bitmap(int x, int y,
break;
}
if (!repeat_x)
- break;
+ break;
}
- return true;
+ return NSERROR_OK;
}
-static bool flush(void)
+/**
+ * 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
+text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
- PLOT_LOG("flush unimplemented");
- return true;
-}
+ PLOT_LOG("words %s at %d,%d", text, x, y);
-static bool path(const float *p, unsigned int n, colour fill, float width,
- colour c, const float transform[6])
-{
- PLOT_LOG("path unimplemented");
- return true;
+ /* ensure the plot HDC is set */
+ if (plot_hdc == NULL) {
+ LOG("HDC not set on call to plotters");
+ return NSERROR_INVALID;
+ }
+
+ HRGN clipregion = CreateRectRgnIndirect(&plot_clip);
+ if (clipregion == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ HFONT fontbak, font = get_font(fstyle);
+ if (font == NULL) {
+ DeleteObject(clipregion);
+ return NSERROR_INVALID;
+ }
+ int wlen;
+ SIZE s;
+ LPWSTR wstring;
+ fontbak = (HFONT) SelectObject(plot_hdc, font);
+ GetTextExtentPoint(plot_hdc, text, length, &s);
+
+ SelectClipRgn(plot_hdc, clipregion);
+
+ SetTextAlign(plot_hdc, TA_BASELINE | TA_LEFT);
+ if ((fstyle->background & 0xFF000000) != 0x01000000) {
+ /* 100% alpha */
+ SetBkColor(plot_hdc, (DWORD) (fstyle->background & 0x00FFFFFF));
+ }
+ SetBkMode(plot_hdc, TRANSPARENT);
+ SetTextColor(plot_hdc, (DWORD) (fstyle->foreground & 0x00FFFFFF));
+
+ wlen = MultiByteToWideChar(CP_UTF8, 0, text, length, NULL, 0);
+ wstring = malloc(2 * (wlen + 1));
+ if (wstring == NULL) {
+ return NSERROR_INVALID;
+ }
+ MultiByteToWideChar(CP_UTF8, 0, text, length, wstring, wlen);
+ TextOutW(plot_hdc, x, y, wstring, wlen);
+
+ SelectClipRgn(plot_hdc, NULL);
+ free(wstring);
+ font = SelectObject(plot_hdc, fontbak);
+ DeleteObject(clipregion);
+ DeleteObject(font);
+
+ return NSERROR_OK;
}
+
+/**
+ * win32 API plot operation table
+ */
const struct plotter_table win_plotters = {
.rectangle = rectangle,
.line = line,
@@ -860,8 +1021,7 @@ const struct plotter_table win_plotters = {
.text = text,
.disc = disc,
.arc = arc,
- .bitmap = windows_plot_bitmap,
- .flush = flush,
+ .bitmap = bitmap,
.path = path,
.option_knockout = true,
};
diff --git a/include/netsurf/plotters.h b/include/netsurf/plotters.h
index 88cbbe5..87fbd9a 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,189 @@ 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.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \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.
+ * \param x The x coordinate of the circle.
+ * \param y The y coordinate of the circle.
+ * \param radius The radius of the circle.
+ * \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.
+ * \param pstyle Style controlling the line plot.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line);
- /* 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.
+ * \param pstyle Style controlling the rectangle plot.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+ nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle);
- /* 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.
+ * \param pstyle Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \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
+ * controlled by 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.
+ * \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.
*/
- 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.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \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
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/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_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 ae86756..598e613 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,858 +304,43 @@ 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))
- return false;
- }
- }
-
- if (!highlighted) {
- if (!plot->text(x, y + (int) (height * 0.75 * scale),
- utf8_text, utf8_len,
- &plot_fstyle))
- return false;
- }
- 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,
-};
-
-/**
- * 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)
-{
- 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;
-
- 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:
- 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))
- 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;
- } 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_fillbdr))
- return false;
- }
- } else {
- if (!plot->polygon(p, 4, &plot_style_fillbdr))
- 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];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
- 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];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
- 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 */
- int x0, y0, x1, y1;
-
- /* 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];
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; 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;
- }
-
- /* 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;
- } else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; 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;
- }
- } 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;
- }
- } 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;
- }
- }
- } 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];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
- 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))
+ (ctx->plot->clip(ctx, clip) != 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 */
- int x0, y0, x1, y1;
-
- /* 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];
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; 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;
- }
-
- /* 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;
- } else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; 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;
- }
- } 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;
- }
- } 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;
- }
- }
- } 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];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
- 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))
- 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))
+ if (!highlighted) {
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int) (height * 0.75 * scale),
+ utf8_text,
+ utf8_len);
+ 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;
}
-
- 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;
}
@@ -1152,42 +360,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 +459,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 +538,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 +556,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 +586,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 +603,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 +733,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 +762,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 +811,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 +823,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 +890,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 +918,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 +954,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 +1002,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 +1214,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 +1360,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 +1408,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 +1424,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 +1489,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 +1568,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 +1600,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 +1625,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 +1664,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 +1677,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 +1690,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 +1743,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 +1762,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 +1812,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 +1824,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 +1858,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 +1909,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/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;
+}
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;
+ }
}
}
--
NetSurf Browser