chiark / gitweb /
Patch from Mark Wooding to introduce a draw_thick_line() function in
authorSimon Tatham <anakin@pobox.com>
Sat, 29 May 2010 15:43:46 +0000 (15:43 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 29 May 2010 15:43:46 +0000 (15:43 +0000)
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.

[originally from svn r8962]

drawing.c
gtk.c
loopy.c
net.c
netslide.c
nullfe.c
puzzles.h

index 4cbb46dbdf4aa971f0592a19e004adaa0dbd7e7a..7f4a6cf6746eabdea9fba7a63f6d9b9900ef35d0 100644 (file)
--- 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 0b3355e9b8617952e69add95926168582439f731..9d134426aabb328b09f9c2b20bba984f76f32e6f 100644 (file)
--- 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 488b5077672e7c1f52254c036428e64f14d42ce4..d915ff7093d4c2bbd384831b33a1877165053592 100644 (file)
--- 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 ecbbbfbbbb27876cb00c8869381d71f17a61fc74..c6226f2aca134c94ca46f8ac0c488f93847062fa 100644 (file)
--- 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) {
index 99eb6e13620f87cb5aeb347daabe8693bc3d0224..552b728c4f9d2dcc7fddae2568fadc4edc0cc44f 100644 (file)
@@ -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) {
index f80a50c4ba209440c1023d186f4be1115fee4d64..4c9975b90e7c23793e107ccabbdffeae7d44c7f0 100644 (file)
--- 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,
index a97746cb61be303001e0ac70f78dc066df4ebcf7..971cb291dc0a16af8b761a2e5dc8143e4d935b02 100644 (file)
--- 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);
 };
 
 /*