From 78d601eb76c796c038f42c2b9f10e4e591272271 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 6 Feb 2017 00:37:08 +0000 Subject: Update GTK plotters to use new API --- 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 +- 5 files changed, 457 insertions(+), 159 deletions(-) (limited to 'frontends') diff --git a/frontends/gtk/layout_pango.c b/frontends/gtk/layout_pango.c index 7c7190982..bad57d684 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 137cebe68..7ce107a5d 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 817b72808..54b3a896c 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 55dcf6390..4f3408166 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 . */ - /** \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 bbc568e15..06b51decc 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); -- cgit v1.2.3 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/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 + 9 files changed, 1055 insertions(+), 657 deletions(-) (limited to 'frontends') diff --git a/frontends/riscos/content-handlers/artworks.c b/frontends/riscos/content-handlers/artworks.c index f70b10ac7..7a7d79cb7 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 9dff75736..0c84de866 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 ed06110ec..02976e48e 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 c26b46c84..c47c2af7d 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 9d1bada91..bcaf3baf9 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 06e732d99..b12d6c403 100644 --- a/frontends/riscos/plotters.c +++ b/frontends/riscos/plotters.c @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -/** \file - * Target independent plotting (RISC OS screen implementation). +/** + * \file + * RISC OS screen plotter implementation. */ #include @@ -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 465627eea..1ccfc7f74 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 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 diff --git a/frontends/riscos/save_draw.h b/frontends/riscos/save_draw.h index 7ae447790..99662e371 100644 --- a/frontends/riscos/save_draw.h +++ b/frontends/riscos/save_draw.h @@ -24,6 +24,13 @@ #include 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 -- cgit v1.2.3 From 0f43b2327063af238ab1eb5f94c3235f4c9347f6 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 9 Feb 2017 09:56:37 +0000 Subject: update monkey plotters to new API --- frontends/monkey/plot.c | 258 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 213 insertions(+), 45 deletions(-) (limited to 'frontends') diff --git a/frontends/monkey/plot.c b/frontends/monkey/plot.c index bd94e7551..9eb40acba 100644 --- a/frontends/monkey/plot.c +++ b/frontends/monkey/plot.c @@ -19,82 +19,250 @@ #include #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, -- cgit v1.2.3 From 386951ecfc220748b81c53f3c736f2fc08686b78 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 9 Feb 2017 12:02:28 +0000 Subject: update framebuffer to new plotter API --- frontends/framebuffer/fbtk/text.c | 28 +- frontends/framebuffer/framebuffer.c | 606 +++++++++++++++++++++++------------- 2 files changed, 416 insertions(+), 218 deletions(-) (limited to 'frontends') diff --git a/frontends/framebuffer/fbtk/text.c b/frontends/framebuffer/fbtk/text.c index 00dcba491..31417c2e0 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 74c72fe71..7b8ee917f 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) { -- cgit v1.2.3 From 320c0e1a75106a74280410ce23db8a308f44193b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 10 Feb 2017 09:38:31 +0000 Subject: update windows plotters to new API --- frontends/windows/plot.c | 1176 ++++++++++++++++++++++++++-------------------- 1 file changed, 668 insertions(+), 508 deletions(-) (limited to 'frontends') diff --git a/frontends/windows/plot.c b/frontends/windows/plot.c index fd2961957..5b7648ef1 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, }; -- cgit v1.2.3 From a3a7cbf06a1d841dd6dee415fb196040c453567a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 10 Feb 2017 15:26:59 +0000 Subject: update amiga plot API --- 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 +- 5 files changed, 557 insertions(+), 357 deletions(-) (limited to 'frontends') diff --git a/frontends/amiga/dt_anim.c b/frontends/amiga/dt_anim.c index a48633403..2f998d299 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 55fc60d61..eda60edc1 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 3f597a1ba..a92b8674c 100644 --- a/frontends/amiga/icon.c +++ b/frontends/amiga/icon.c @@ -16,7 +16,8 @@ * along with this program. If not, see . */ -/** \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 6bae6346a..e87171551 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 7fe78b9b0..2327f9190 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; } /** -- cgit v1.2.3 From 4361bfeace6f3f184e871f5598138f3f36994e99 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 12 Feb 2017 18:01:46 +0000 Subject: update atari plotters to new API --- 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 +- 6 files changed, 1313 insertions(+), 1021 deletions(-) (limited to 'frontends') diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c index d4a6915cd..1287b4715 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 0a0d7a494..09174287c 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 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; yg_h; y++ ){ - row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y))); - for( x=0; xg_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; yg_h; y++ ){ + row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y))); + for( x=0; xg_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= 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= 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 && istroke_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; ifill_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; ifill_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 fd73a8c33..c8bf9157c 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 aa8e08047..0b77cbba5 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 9ed87849c..1b9371763 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 93aef6eb6..8e9834ec3 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; -- cgit v1.2.3 From 513366a7a22dfeafc6a79814701ba62210ad5040 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 12 Feb 2017 19:56:09 +0000 Subject: update beos to new plotter API --- frontends/beos/plotters.cpp | 1126 +++++++++++++++++++++++++------------------ 1 file changed, 649 insertions(+), 477 deletions(-) (limited to 'frontends') diff --git a/frontends/beos/plotters.cpp b/frontends/beos/plotters.cpp index 5ba3fbbcb..6544d63bd 100644 --- a/frontends/beos/plotters.cpp +++ b/frontends/beos/plotters.cpp @@ -18,7 +18,8 @@ * along with this program. If not, see . */ -/** \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 @@ -632,28 +805,27 @@ static void test_plotters(void) #include 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 */ - -- cgit v1.2.3