<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40646 >

> [book - Thu Jan 08 22:42:38 2009]:
> 
> Attached patch changes the selection rectangle drawing
> code to use xor instead overwriting pixel values. This
> means that it can be erased by just drawing over itself
> again, rather than redrawing all of the sprites at all
> of the tiles that it touches.

Here is an improved version for S2_1 and trunk. The changes
to guis other than gtk2 were removed since they had no effect.


-----------------------------------------------------------------------
妻は三角形です。
 client/editor.c               |   43 ++++++++++++++++++++---------------------
 client/editor.h               |    1 -
 client/gui-gtk-2.0/gui_main.c |    4 +++
 client/gui-gtk-2.0/gui_main.h |    1 +
 client/gui-gtk-2.0/mapview.c  |   26 +++++++++++++++++++-----
 client/mapctrl_common.c       |    3 +-
 client/mapview_common.c       |    7 ------
 7 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/client/editor.c b/client/editor.c
index 08f67fb..9100213 100644
--- a/client/editor.c
+++ b/client/editor.c
@@ -676,6 +676,24 @@ static void editor_end_selection_rectangle(int canvas_x, int canvas_y)
 }
 
 /****************************************************************************
+  Draws the editor selection rectangle using draw_selection_rectangle().
+****************************************************************************/
+static void editor_draw_selrect(void)
+{
+  if (!editor) {
+    return;
+  }
+
+  if (editor->selrect_active && editor->selrect_width > 0
+      && editor->selrect_height > 0) {
+    draw_selection_rectangle(editor->selrect_x,
+                             editor->selrect_y,
+                             editor->selrect_width,
+                             editor->selrect_height);
+  }
+}
+
+/****************************************************************************
   Handle the release of a mouse button click.
 ****************************************************************************/
 void editor_mouse_button_release(int canvas_x, int canvas_y,
@@ -726,8 +744,8 @@ static void editor_resize_selection_rectangle(int canvas_x, int canvas_y)
     y2 = editor->selrect_start_y;
   }
 
-  dirty_all();
-  flush_dirty();
+  /* Erase the previously drawn rectangle. */
+  editor_draw_selrect();
 
   if (x1 == x2 || y1 == y2) {
     editor->selrect_width = 0;
@@ -740,7 +758,7 @@ static void editor_resize_selection_rectangle(int canvas_x, int canvas_y)
   editor->selrect_width = x2 - x1;
   editor->selrect_height = y2 - y1;
 
-  editor_redraw();
+  editor_draw_selrect();
 }
 
 /****************************************************************************
@@ -925,25 +943,6 @@ const struct tile *editor_get_current_tile(void)
 }
 
 /****************************************************************************
-  Redraw any editor-specific decorations. This should usually be called
-  whenever the map canvas is redrawn.
-****************************************************************************/
-void editor_redraw(void)
-{
-  if (!editor) {
-    return;
-  }
-
-  if (editor->selrect_active && editor->selrect_width > 0
-      && editor->selrect_height > 0) {
-    draw_selection_rectangle(editor->selrect_x,
-                             editor->selrect_y,
-                             editor->selrect_width,
-                             editor->selrect_height);
-  }
-}
-
-/****************************************************************************
   Toggle the current tool mode between the given mode and ETM_PAINT.
 ****************************************************************************/
 void editor_tool_toggle_mode(enum editor_tool_type ett,
diff --git a/client/editor.h b/client/editor.h
index 2388720..3b8c649 100644
--- a/client/editor.h
+++ b/client/editor.h
@@ -121,7 +121,6 @@ void editor_mouse_button_press(int canvas_x, int canvas_y,
 void editor_mouse_button_release(int canvas_x, int canvas_y,
                                  int button, int modifiers);
 void editor_mouse_move(int canvas_x, int canvas_y, int modifiers);
-void editor_redraw(void);
 
 void editor_apply_tool(const struct tile *ptile,
                        bool part_of_selection);
diff --git a/client/gui-gtk-2.0/gui_main.c b/client/gui-gtk-2.0/gui_main.c
index c317155..12e66c0 100644
--- a/client/gui-gtk-2.0/gui_main.c
+++ b/client/gui-gtk-2.0/gui_main.c
@@ -118,6 +118,7 @@ GdkGC *fill_tile_gc;
 GdkGC *thin_line_gc;
 GdkGC *thick_line_gc;
 GdkGC *border_line_gc;
+GdkGC *selection_gc;
 GdkPixmap *gray50, *gray25, *black50;
 GdkPixmap *mask_bitmap;
 
@@ -1569,6 +1570,9 @@ void ui_main(int argc, char **argv)
     gdk_gc_set_foreground(mask_bg_gc, &pixel);
   }
 
+  selection_gc = gdk_gc_new(root_window);
+  gdk_gc_set_function(selection_gc, GDK_XOR);
+
   tileset_init(tileset);
   tileset_load_tiles(tileset);
 
diff --git a/client/gui-gtk-2.0/gui_main.h b/client/gui-gtk-2.0/gui_main.h
index 6cdcc46..98e5a7a 100644
--- a/client/gui-gtk-2.0/gui_main.h
+++ b/client/gui-gtk-2.0/gui_main.h
@@ -36,6 +36,7 @@ extern GdkGC *          fill_tile_gc;
 extern GdkGC *          thin_line_gc;
 extern GdkGC *          thick_line_gc;
 extern GdkGC *          border_line_gc;
+extern GdkGC *          selection_gc;
 extern GdkPixmap *      gray50;
 extern GdkPixmap *      gray25;
 extern GdkPixmap *      black50;
diff --git a/client/gui-gtk-2.0/mapview.c b/client/gui-gtk-2.0/mapview.c
index 4d4acc2..2fd2380 100644
--- a/client/gui-gtk-2.0/mapview.c
+++ b/client/gui-gtk-2.0/mapview.c
@@ -382,8 +382,6 @@ static bool is_flush_queued = FALSE;
 static gint unqueue_flush(gpointer data)
 {
   flush_dirty();
-  redraw_selection_rectangle();
-  editor_redraw();
   is_flush_queued = FALSE;
   return 0;
 }
@@ -765,14 +763,27 @@ void scrollbar_jump_callback(GtkAdjustment *adj, gpointer hscrollbar)
 }
 
 /**************************************************************************
- Area Selection
+  Draws a rectangle with top left corner at (canvas_x, canvas_y), and
+  width 'w' and height 'h'. It is drawn using the 'selection_gc' context,
+  so the pixel combining function is XOR. This means that drawing twice
+  in the same place will restore the image to its original state.
+
+  NB: A side effect of this function is to set the 'selection_gc' color
+  to COLOR_MAPVIEW_SELECTION.
 **************************************************************************/
 void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
 {
   GdkPoint points[5];
+  struct color *pcolor;
 
-  gdk_gc_set_foreground(civ_gc,
-			&get_color(tileset, COLOR_MAPVIEW_SELECTION)->color);
+  if (w == 0 || h == 0) {
+    return;
+  }
+
+  pcolor = get_color(tileset, COLOR_MAPVIEW_SELECTION);
+  if (!pcolor) {
+    return;
+  }
 
   /* gdk_draw_rectangle() must start top-left.. */
   points[0].x = canvas_x;
@@ -789,7 +800,10 @@ void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
 
   points[4].x = canvas_x;
   points[4].y = canvas_y;
-  gdk_draw_lines(map_canvas->window, civ_gc, points, ARRAY_SIZE(points));
+
+  gdk_gc_set_foreground(selection_gc, &pcolor->color);
+  gdk_draw_lines(map_canvas->window, selection_gc,
+                 points, ARRAY_SIZE(points));
 }
 
 /**************************************************************************
diff --git a/client/mapctrl_common.c b/client/mapctrl_common.c
index 67c7bf4..b74150a 100644
--- a/client/mapctrl_common.c
+++ b/client/mapctrl_common.c
@@ -210,8 +210,7 @@ void update_selection_rectangle(int canvas_x, int canvas_y)
   rec_tile = ptile;
 
   /* Clear previous rectangle. */
-  dirty_all();
-  flush_dirty();
+  draw_selection_rectangle(rec_corner_x, rec_corner_y, rec_w, rec_h);
 
   /*  Fix canvas coords to the center of the tile.
    */
diff --git a/client/mapview_common.c b/client/mapview_common.c
index 11f9402..5d12cae 100644
--- a/client/mapview_common.c
+++ b/client/mapview_common.c
@@ -601,8 +601,6 @@ void set_mapview_origin(int gui_x0, int gui_y0)
       base_set_mapview_origin(start_x + diff_x * (mytime / timing_sec),
 			      start_y + diff_y * (mytime / timing_sec));
       flush_dirty();
-      redraw_selection_rectangle();
-      editor_redraw();
       gui_flush();
       frames++;
     } while (currtime < timing_sec);
@@ -1064,7 +1062,6 @@ void put_nuke_mushroom_pixmaps(struct tile *ptile)
   dirty_rect(canvas_x, canvas_y, width, height);
 
   flush_dirty();
-  redraw_selection_rectangle();
   gui_flush();
 
   myusleep(1000000);
@@ -1982,7 +1979,6 @@ void decrease_unit_hp_smooth(struct unit *punit0, int hp0,
       dirty_rect(canvas_x, canvas_y, tileset_tile_width(tileset), tileset_tile_height(tileset));
 
       flush_dirty();
-      redraw_selection_rectangle();
       gui_flush();
 
       usleep_since_timer_start(anim_timer, 20000);
@@ -2062,7 +2058,6 @@ void move_unit_map_canvas(struct unit *punit,
 
       /* Flush. */
       flush_dirty();
-      redraw_selection_rectangle();
       gui_flush();
 
       /* Restore the backup.  It won't take effect until the next flush. */
@@ -2431,8 +2426,6 @@ void unqueue_mapview_updates(bool write_to_screen)
 
   if (write_to_screen) {
     flush_dirty();
-    redraw_selection_rectangle();
-    editor_redraw();
     flush_dirty_overview();
   }
 }
 client/gui-gtk-2.0/gui_main.c |    4 ++++
 client/gui-gtk-2.0/gui_main.h |    1 +
 client/gui-gtk-2.0/mapview.c  |   25 ++++++++++++++++++++-----
 client/mapctrl_common.c       |    3 +--
 client/mapview_common.c       |    5 -----
 5 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/client/gui-gtk-2.0/gui_main.c b/client/gui-gtk-2.0/gui_main.c
index 2f79f7a..c3c0a70 100644
--- a/client/gui-gtk-2.0/gui_main.c
+++ b/client/gui-gtk-2.0/gui_main.c
@@ -115,6 +115,7 @@ GdkGC *fill_tile_gc;
 GdkGC *thin_line_gc;
 GdkGC *thick_line_gc;
 GdkGC *border_line_gc;
+GdkGC *selection_gc;
 GdkPixmap *gray50, *gray25, *black50;
 GdkPixmap *mask_bitmap;
 
@@ -1433,6 +1434,9 @@ void ui_main(int argc, char **argv)
     gdk_gc_set_foreground(mask_bg_gc, &pixel);
   }
 
+  selection_gc = gdk_gc_new(root_window);
+  gdk_gc_set_function(selection_gc, GDK_XOR);
+
   tileset_init(tileset);
   tileset_load_tiles(tileset);
 
diff --git a/client/gui-gtk-2.0/gui_main.h b/client/gui-gtk-2.0/gui_main.h
index 65c7114..9f9205e 100644
--- a/client/gui-gtk-2.0/gui_main.h
+++ b/client/gui-gtk-2.0/gui_main.h
@@ -36,6 +36,7 @@ extern GdkGC *          fill_tile_gc;
 extern GdkGC *          thin_line_gc;
 extern GdkGC *          thick_line_gc;
 extern GdkGC *          border_line_gc;
+extern GdkGC *          selection_gc;
 extern GdkPixmap *      gray50;
 extern GdkPixmap *      gray25;
 extern GdkPixmap *      black50;
diff --git a/client/gui-gtk-2.0/mapview.c b/client/gui-gtk-2.0/mapview.c
index 0c7ece5..edaab01 100644
--- a/client/gui-gtk-2.0/mapview.c
+++ b/client/gui-gtk-2.0/mapview.c
@@ -430,7 +430,6 @@ static bool is_flush_queued = FALSE;
 static gint unqueue_flush(gpointer data)
 {
   flush_dirty();
-  redraw_selection_rectangle();
   is_flush_queued = FALSE;
   return 0;
 }
@@ -810,14 +809,27 @@ void scrollbar_jump_callback(GtkAdjustment *adj, gpointer hscrollbar)
 }
 
 /**************************************************************************
- Area Selection
+  Draws a rectangle with top left corner at (canvas_x, canvas_y), and
+  width 'w' and height 'h'. It is drawn using the 'selection_gc' context,
+  so the pixel combining function is XOR. This means that drawing twice
+  in the same place will restore the image to its original state.
+
+  NB: A side effect of this function is to set the 'selection_gc' color
+  to COLOR_MAPVIEW_SELECTION.
 **************************************************************************/
 void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
 {
   GdkPoint points[5];
+  struct color *pcolor;
 
-  gdk_gc_set_foreground(civ_gc,
-			&get_color(tileset, COLOR_MAPVIEW_SELECTION)->color);
+  if (w == 0 || h == 0) {
+    return;
+  }
+
+  pcolor = get_color(tileset, COLOR_MAPVIEW_SELECTION);
+  if (!pcolor) {
+    return;
+  }
 
   /* gdk_draw_rectangle() must start top-left.. */
   points[0].x = canvas_x;
@@ -834,7 +846,10 @@ void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
 
   points[4].x = canvas_x;
   points[4].y = canvas_y;
-  gdk_draw_lines(map_canvas->window, civ_gc, points, ARRAY_SIZE(points));
+
+  gdk_gc_set_foreground(selection_gc, &pcolor->color);
+  gdk_draw_lines(map_canvas->window, selection_gc,
+                 points, ARRAY_SIZE(points));
 }
 
 /**************************************************************************
diff --git a/client/mapctrl_common.c b/client/mapctrl_common.c
index eca0ec6..59758c0 100644
--- a/client/mapctrl_common.c
+++ b/client/mapctrl_common.c
@@ -204,8 +204,7 @@ void update_selection_rectangle(int canvas_x, int canvas_y)
   rec_tile = ptile;
 
   /* Clear previous rectangle. */
-  dirty_all();
-  flush_dirty();
+  draw_selection_rectangle(rec_corner_x, rec_corner_y, rec_w, rec_h);
 
   /*  Fix canvas coords to the center of the tile.
    */
diff --git a/client/mapview_common.c b/client/mapview_common.c
index 909dd21..56dd285 100644
--- a/client/mapview_common.c
+++ b/client/mapview_common.c
@@ -597,7 +597,6 @@ void set_mapview_origin(int gui_x0, int gui_y0)
       base_set_mapview_origin(start_x + diff_x * (mytime / timing_sec),
 			      start_y + diff_y * (mytime / timing_sec));
       flush_dirty();
-      redraw_selection_rectangle();
       gui_flush();
       frames++;
     } while (currtime < timing_sec);
@@ -1058,7 +1057,6 @@ void put_nuke_mushroom_pixmaps(struct tile *ptile)
   dirty_rect(canvas_x, canvas_y, width, height);
 
   flush_dirty();
-  redraw_selection_rectangle();
   gui_flush();
 
   myusleep(1000000);
@@ -1899,7 +1897,6 @@ void decrease_unit_hp_smooth(struct unit *punit0, int hp0,
       dirty_rect(canvas_x, canvas_y, tileset_tile_width(tileset), tileset_tile_height(tileset));
 
       flush_dirty();
-      redraw_selection_rectangle();
       gui_flush();
 
       usleep_since_timer_start(anim_timer, 20000);
@@ -1979,7 +1976,6 @@ void move_unit_map_canvas(struct unit *punit,
 
       /* Flush. */
       flush_dirty();
-      redraw_selection_rectangle();
       gui_flush();
 
       /* Restore the backup.  It won't take effect until the next flush. */
@@ -2316,7 +2312,6 @@ void unqueue_mapview_updates(bool write_to_screen)
 
   if (write_to_screen) {
     flush_dirty();
-    redraw_selection_rectangle();
     flush_dirty_overview();
   }
 }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to