From a39c3aa04022fc5209efa2ba36f3155d44fed25e Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 29 May 2010 15:43:46 +0000 Subject: [PATCH] Patch from Mark Wooding to introduce a draw_thick_line() function in the drawing API, for use by Loopy. It's optional: drawing.c will construct an acceptable alternative using a filled polygon if the front end doesn't provide it. Net and Netslide previously had static functions called draw_thick_line(), whose claim to the name is less justified and so they've been renamed. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@8962 cda61777-01e9-0310-a592-d414129be87e --- drawing.c | 28 ++++++++++++++++++++++++++++ gtk.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ loopy.c | 19 ++++--------------- net.c | 10 +++++----- netslide.c | 10 +++++----- nullfe.c | 2 ++ puzzles.h | 5 +++++ 7 files changed, 95 insertions(+), 25 deletions(-) diff --git a/drawing.c b/drawing.c index 4cbb46d..7f4a6cf 100644 --- a/drawing.c +++ b/drawing.c @@ -87,6 +87,34 @@ void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) dr->api->draw_line(dr->handle, x1, y1, x2, y2, colour); } +void draw_thick_line(drawing *dr, float thickness, + float x1, float y1, float x2, float y2, int colour) +{ + if (dr->api->draw_thick_line) { + dr->api->draw_thick_line(dr->handle, thickness, + x1, y1, x2, y2, colour); + } else { + /* We'll fake it up with a filled polygon. The tweak to the + * thickness empirically compensates for rounding errors, because + * polygon rendering uses integer coordinates. + */ + float len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); + float tvhatx = (x2 - x1)/len * (thickness/2 - 0.2); + float tvhaty = (y2 - y1)/len * (thickness/2 - 0.2); + int p[8]; + + p[0] = x1 - tvhaty; + p[1] = y1 + tvhatx; + p[2] = x2 - tvhaty; + p[3] = y2 + tvhatx; + p[4] = x2 + tvhaty; + p[5] = y2 - tvhatx; + p[6] = x1 + tvhaty; + p[7] = y1 - tvhatx; + dr->api->draw_polygon(dr->handle, p, 4, colour, colour); + } +} + void draw_polygon(drawing *dr, int *coords, int npoints, int fillcolour, int outlinecolour) { diff --git a/gtk.c b/gtk.c index 0b3355e..9d13442 100644 --- a/gtk.c +++ b/gtk.c @@ -40,6 +40,8 @@ # define USE_CAIRO #endif +/* #undef USE_CAIRO */ +/* #define NO_THICK_LINE */ #ifdef DEBUGGING static FILE *debug_fp = NULL; @@ -297,6 +299,18 @@ static void do_draw_line(frontend *fe, int x1, int y1, int x2, int y2) cairo_stroke(fe->cr); } +static void do_draw_thick_line(frontend *fe, float thickness, + float x1, float y1, float x2, float y2) +{ + cairo_save(fe->cr); + cairo_set_line_width(fe->cr, thickness); + cairo_new_path(fe->cr); + cairo_move_to(fe->cr, x1, y1); + cairo_line_to(fe->cr, x2, y2); + cairo_stroke(fe->cr); + cairo_restore(fe->cr); +} + static void do_draw_poly(frontend *fe, int *coords, int npoints, int fillcolour, int outlinecolour) { @@ -518,6 +532,25 @@ static void do_draw_line(frontend *fe, int x1, int y1, int x2, int y2) gdk_draw_line(fe->pixmap, fe->gc, x1, y1, x2, y2); } +static void do_draw_thick_line(frontend *fe, float thickness, + float x1, float y1, float x2, float y2) +{ + GdkGCValues save; + + gdk_gc_get_values(fe->gc, &save); + gdk_gc_set_line_attributes(fe->gc, + thickness, + GDK_LINE_SOLID, + GDK_CAP_BUTT, + GDK_JOIN_BEVEL); + gdk_draw_line(fe->pixmap, fe->gc, x1, y1, x2, y2); + gdk_gc_set_line_attributes(fe->gc, + save.line_width, + save.line_style, + save.cap_style, + save.join_style); +} + static void do_draw_poly(frontend *fe, int *coords, int npoints, int fillcolour, int outlinecolour) { @@ -850,6 +883,14 @@ void gtk_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour) do_draw_line(fe, x1, y1, x2, y2); } +void gtk_draw_thick_line(void *handle, float thickness, + float x1, float y1, float x2, float y2, int colour) +{ + frontend *fe = (frontend *)handle; + set_colour(fe, colour); + do_draw_thick_line(fe, thickness, x1, y1, x2, y2); +} + void gtk_draw_poly(void *handle, int *coords, int npoints, int fillcolour, int outlinecolour) { @@ -955,6 +996,11 @@ const struct drawing_api gtk_drawing = { #else NULL, #endif +#ifdef NO_THICK_LINE + NULL, +#else + gtk_draw_thick_line, +#endif }; static void destroy(GtkWidget *widget, gpointer data) diff --git a/loopy.c b/loopy.c index 488b507..d915ff7 100644 --- a/loopy.c +++ b/loopy.c @@ -3543,21 +3543,10 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, if (draw_faint_lines) draw_line(dr, x1, y1, x2, y2, line_colour); } else { - /* (dx, dy) points roughly from (x1, y1) to (x2, y2). - * The line is then "fattened" in a (roughly) perpendicular - * direction to create a thin rectangle. */ - int dx = (x1 > x2) ? -1 : ((x1 < x2) ? 1 : 0); - int dy = (y1 > y2) ? -1 : ((y1 < y2) ? 1 : 0); - int points[8]; - points[0] = x1 + dy; - points[1] = y1 - dx; - points[2] = x1 - dy; - points[3] = y1 + dx; - points[4] = x2 - dy; - points[5] = y2 + dx; - points[6] = x2 + dy; - points[7] = y2 - dx; - draw_polygon(dr, points, 4, line_colour, line_colour); + draw_thick_line(dr, 3.0, + x1 + 0.5, y1 + 0.5, + x2 + 0.5, y2 + 0.5, + line_colour); } if (ds->started) { /* Draw dots at ends of the line */ diff --git a/net.c b/net.c index ecbbbfb..c6226f2 100644 --- a/net.c +++ b/net.c @@ -2377,8 +2377,8 @@ static float *game_colours(frontend *fe, int *ncolours) return ret; } -static void draw_thick_line(drawing *dr, int x1, int y1, int x2, int y2, - int colour) +static void draw_filled_line(drawing *dr, int x1, int y1, int x2, int y2, + int colour) { draw_line(dr, x1-1, y1, x2-1, y2, COL_WIRE); draw_line(dr, x1+1, y1, x2+1, y2, COL_WIRE); @@ -2514,9 +2514,9 @@ static void draw_tile(drawing *dr, game_state *state, game_drawstate *ds, ex = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * X(dir); ey = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * Y(dir); MATMUL(tx, ty, matrix, ex, ey); - draw_thick_line(dr, bx+(int)cx, by+(int)cy, - bx+(int)(cx+tx), by+(int)(cy+ty), - COL_WIRE); + draw_filled_line(dr, bx+(int)cx, by+(int)cy, + bx+(int)(cx+tx), by+(int)(cy+ty), + COL_WIRE); } } for (dir = 1; dir < 0x10; dir <<= 1) { diff --git a/netslide.c b/netslide.c index 99eb6e1..552b728 100644 --- a/netslide.c +++ b/netslide.c @@ -1307,8 +1307,8 @@ static float *game_colours(frontend *fe, int *ncolours) return ret; } -static void draw_thick_line(drawing *dr, int x1, int y1, int x2, int y2, - int colour) +static void draw_filled_line(drawing *dr, int x1, int y1, int x2, int y2, + int colour) { draw_line(dr, x1-1, y1, x2-1, y2, COL_WIRE); draw_line(dr, x1+1, y1, x2+1, y2, COL_WIRE); @@ -1420,9 +1420,9 @@ static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state, if (tile & dir) { ex = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * X(dir); ey = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * Y(dir); - draw_thick_line(dr, bx+(int)cx, by+(int)cy, - bx+(int)(cx+ex), by+(int)(cy+ey), - COL_WIRE); + draw_filled_line(dr, bx+(int)cx, by+(int)cy, + bx+(int)(cx+ex), by+(int)(cy+ey), + COL_WIRE); } } for (dir = 1; dir < 0x10; dir <<= 1) { diff --git a/nullfe.c b/nullfe.c index f80a50c..4c9975b 100644 --- a/nullfe.c +++ b/nullfe.c @@ -13,6 +13,8 @@ void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, int align, int colour, char *text) {} void draw_rect(drawing *dr, int x, int y, int w, int h, int colour) {} void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) {} +void draw_thick_line(drawing *dr, float thickness, + float x1, float y1, float x2, float y2, int colour) {} void draw_polygon(drawing *dr, int *coords, int npoints, int fillcolour, int outlinecolour) {} void draw_circle(drawing *dr, int cx, int cy, int radius, diff --git a/puzzles.h b/puzzles.h index a97746c..971cb29 100644 --- a/puzzles.h +++ b/puzzles.h @@ -184,6 +184,8 @@ void draw_polygon(drawing *dr, int *coords, int npoints, int fillcolour, int outlinecolour); void draw_circle(drawing *dr, int cx, int cy, int radius, int fillcolour, int outlinecolour); +void draw_thick_line(drawing *dr, float thickness, + float x1, float y1, float x2, float y2, int colour); void clip(drawing *dr, int x, int y, int w, int h); void unclip(drawing *dr); void start_draw(drawing *dr); @@ -519,6 +521,9 @@ struct drawing_api { void (*line_dotted)(void *handle, int dotted); char *(*text_fallback)(void *handle, const char *const *strings, int nstrings); + void (*draw_thick_line)(void *handle, float thickness, + float x1, float y1, float x2, float y2, + int colour); }; /* -- 2.11.0