From 3ea137ca3d9b0f996493bb33289d9ab3fc2881bc Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 8 Feb 2017 09:22:42 +0000 Subject: update RISC OS plotters to new API --- frontends/riscos/save_draw.c | 633 +++++++++++++++++++++++++++---------------- 1 file changed, 400 insertions(+), 233 deletions(-) (limited to 'frontends/riscos/save_draw.c') diff --git a/frontends/riscos/save_draw.c b/frontends/riscos/save_draw.c index 7e6c9462e..1e0bc1ec6 100644 --- a/frontends/riscos/save_draw.c +++ b/frontends/riscos/save_draw.c @@ -18,7 +18,8 @@ * along with this program. If not, see . */ -/** \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 -- cgit v1.2.3