<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