Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2004:
[Freeciv-Dev] (PR#8965) much simpler draw_segment
Home

[Freeciv-Dev] (PR#8965) much simpler draw_segment

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8965) much simpler draw_segment
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 12 Jun 2004 00:37:39 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8965 >

This patch makes draw_segment much simpler.

First, there is no need for separate iso and non-iso methods.  The iso 
method is better because it involves less drawing.  This allows a lot of 
simplification...

Secondly, the logic becomes much simpler if we use map_to_gui_vector 
instead of finding the canvas positions of source and dest tile separately.

Note that if the mapview is large enough at some point it will wrap. 
The dest tile and src tiles will both be drawn, but not adjacent to each 
other.  In this case the goto line will be drawn off of the src tile but 
not onto the dest tile.  This is still an improvement from the current 
behavior which draws neither.  It would be possible to update both in 
this situation, but I think this situation is defined as buggy, and we 
don't need to worry about it for now.

jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.124
diff -u -r1.124 mapview_common.c
--- client/mapview_common.c     12 Jun 2004 06:38:29 -0000      1.124
+++ client/mapview_common.c     12 Jun 2004 07:26:06 -0000
@@ -1615,116 +1615,40 @@
 #define ABS(x) (((x) >= 0) ? (x) : -(x))
 
 /****************************************************************************
-  Put a segment on the mapview (in iso-view only).  The segment is drawn
-  from the source tile to the adjacent tile in the given direction.
-
-  This method is faster than the one used for non-iso view, but there are
-  two drawbacks:
-  1.  Since each line spans multiple tiles, updating a single tile is
-      harder (see update_map_canvas).
-  2.  We don't know where the map wraps, so we have problems when we reach
-      the wrapping point.  On very large mapviews this means segments might
-      not be drawn near the wrapping points.
-****************************************************************************/
-static void draw_segment_iso(int src_x, int src_y, enum direction8 dir)
-{
-  int dest_x, dest_y;
-  bool is_visible1, is_visible2;
-  int canvas_src_x, canvas_src_y;
-  int canvas_dest_x, canvas_dest_y;
-
-  if (!MAPSTEP(dest_x, dest_y, src_x, src_y, dir)) {
-    assert(0);
-    return;
-  }
-
-  /* Find middle of tiles. y-1 to not undraw the the middle pixel of a
-     horizontal line when we refresh the tile below-between. */
-  is_visible1
-    = map_to_canvas_pos(&canvas_src_x, &canvas_src_y, src_x, src_y);
-  is_visible2
-    = map_to_canvas_pos(&canvas_dest_x, &canvas_dest_y, dest_x, dest_y);
-
-  if (!is_visible1 && !is_visible2) {
-    return; /* No need to draw anything. */
-  }
-
-  canvas_src_x += NORMAL_TILE_WIDTH/2;
-  canvas_src_y += NORMAL_TILE_HEIGHT/2-1;
-  canvas_dest_x += NORMAL_TILE_WIDTH/2;
-  canvas_dest_y += NORMAL_TILE_HEIGHT/2-1;
-
-  /* HACK: sometimes we draw from a source tile on one side of the screen
-   * to a destination tile on the other side.  In this case we don't want
-   * to draw garbage.  Instead we just don't draw the line at all.  Note
-   * that the non-iso-view method of drawing doesn't have this problem. */
-  if (abs(canvas_dest_x - canvas_src_x) > NORMAL_TILE_WIDTH
-      || abs(canvas_dest_y - canvas_src_y) > NORMAL_TILE_HEIGHT)
-    return;
-
-  /* draw it! */
-  canvas_put_line(mapview_canvas.store, COLOR_STD_CYAN, LINE_GOTO,
-                 canvas_src_x, canvas_src_y,
-                 canvas_dest_x - canvas_src_x,
-                 canvas_dest_y - canvas_src_y);
-  dirty_rect(MIN(canvas_src_x, canvas_dest_x) - 1,
-            MIN(canvas_src_y, canvas_dest_y) - 1,
-            ABS(canvas_dest_x - canvas_src_x) + 2,
-            ABS(canvas_dest_y - canvas_src_y) + 2);
-}
-
-/****************************************************************************
-  Put a half-segment (in non-iso view only).  The segment goes from the
-  given tile *toward* the adjacent tile in the given direction.  However
-  it only goes the the edge of the source tile.  Thus only one tile is
-  spanned (making updates of single tiles easier) but two lines must be
-  drawn to get a single segment (meaning more work & slower).
-****************************************************************************/
-static void put_line(int x, int y, enum direction8 dir)
-{
-  int canvas_src_x, canvas_src_y, canvas_dest_x, canvas_dest_y;
-
-  if (!map_to_canvas_pos(&canvas_src_x, &canvas_src_y, x, y)) {
-    return;
-  }
-  canvas_src_x += NORMAL_TILE_WIDTH/2;
-  canvas_src_y += NORMAL_TILE_HEIGHT/2;
-  DIRSTEP(canvas_dest_x, canvas_dest_y, dir);
-  canvas_dest_x = canvas_src_x + (NORMAL_TILE_WIDTH * canvas_dest_x) / 2;
-  canvas_dest_y = canvas_src_y + (NORMAL_TILE_WIDTH * canvas_dest_y) / 2;
-
-  canvas_put_line(mapview_canvas.store, COLOR_STD_CYAN, LINE_GOTO,
-                 canvas_src_x, canvas_src_y,
-                 canvas_dest_x - canvas_src_x,
-                 canvas_dest_y - canvas_src_y);
-
-  dirty_rect(MIN(canvas_src_x, canvas_dest_x) - 1,
-            MIN(canvas_src_y, canvas_dest_y) - 1,
-            ABS(canvas_dest_x - canvas_src_x) + 2,
-            ABS(canvas_dest_y - canvas_src_y) + 2);
-}
-
-/****************************************************************************
   Draw a goto line at the given location and direction.  The line goes from
   the source tile to the adjacent tile in the given direction.
 ****************************************************************************/
 void draw_segment(int src_x, int src_y, enum direction8 dir)
 {
+  int canvas_x, canvas_y, canvas_dx, canvas_dy;
+
+  (void) map_to_canvas_pos(&canvas_x, &canvas_y, src_x, src_y);
+  canvas_x += NORMAL_TILE_WIDTH / 2;
+  canvas_y += NORMAL_TILE_HEIGHT / 2;
+
   if (is_isometric) {
-    draw_segment_iso(src_x, src_y, dir);
+    canvas_dx = (DIR_DX[dir] - DIR_DY[dir]) * NORMAL_TILE_WIDTH / 2;
+    canvas_dy = (DIR_DX[dir] + DIR_DY[dir]) * NORMAL_TILE_HEIGHT / 2;
   } else {
-    int dest_x, dest_y;
-    bool is_real = MAPSTEP(dest_x, dest_y, src_x, src_y, dir);
+    canvas_dx = NORMAL_TILE_WIDTH * DIR_DX[dir];
+    canvas_dy = NORMAL_TILE_HEIGHT * DIR_DY[dir];
+  }
 
-    assert(is_real);
+  canvas_put_line(mapview_canvas.store, COLOR_STD_CYAN, LINE_GOTO,
+                 canvas_x, canvas_y, canvas_dx, canvas_dy);
 
-    if (tile_visible_mapcanvas(src_x, src_y)) {
-      put_line(src_x, src_y, dir);
-    }
-    if (tile_visible_mapcanvas(dest_x, dest_y)) {
-      put_line(dest_x, dest_y, DIR_REVERSE(dir));
-    }
-  }
+  /* The actual area drawn will extend beyond the base rectangle, since
+   * the goto lines have width. */
+  dirty_rect(MIN(canvas_x, canvas_x + canvas_dx) - GOTO_WIDTH,
+            MIN(canvas_y, canvas_y + canvas_dy) - GOTO_WIDTH,
+            ABS(canvas_dx) + 2 * GOTO_WIDTH,
+            ABS(canvas_dy) + 2 * GOTO_WIDTH);
+
+  /* It is possible that the mapview wraps between the source and dest
+   * tiles.  In this case they will not be next to each other; they'll be
+   * on the opposite sides of the screen.  If this happens then the dest
+   * tile will not be updated.  This is consistent with the mapview design
+   * which fails when the size of the mapview approaches that of the map. */
 }
 
 /**************************************************************************
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.66
diff -u -r1.66 mapview_common.h
--- client/mapview_common.h     10 Jun 2004 01:04:52 -0000      1.66
+++ client/mapview_common.h     12 Jun 2004 07:26:06 -0000
@@ -128,6 +128,7 @@
 #define D_FULL D_TMB_LR
 
 #define BORDER_WIDTH 2
+#define GOTO_WIDTH 2
 
 enum update_type {
   /* Masks */

[Prev in Thread] Current Thread [Next in Thread]