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

This finally got irritating enough that I took a small
digression from working on the editor to fix it. I am
not sure that all platforms using the gtk-2.0 client had
this bug, but for me at least flag images have always
been visually corrupted in a manner that would suggest
reading from uninitialized (or already freed) memory.

The attached patches for 2.1, 2.2 and trunk ensure that
flag pixbufs are not prematurely freed due to reference
counting mistakes.


---------------------------------------------------------------------
詰まらない存在は最低だぞ
diff --git a/client/gui-gtk-2.0/dialogs.c b/client/gui-gtk-2.0/dialogs.c
index cf8b3c8..854ce00 100644
--- a/client/gui-gtk-2.0/dialogs.c
+++ b/client/gui-gtk-2.0/dialogs.c
@@ -51,6 +51,7 @@
 #include "mapview.h"
 #include "options.h"
 #include "packhand.h"
+#include "plrdlg.h"
 #include "text.h"
 #include "tilespec.h"
 
@@ -660,7 +661,6 @@ static GtkWidget* create_list_of_nations_in_group(struct nation_group* group,
 
   /* Populate nation list store. */
   nations_iterate(pnation) {
-    struct sprite *s;
     bool used;
     GdkPixbuf *img;
     GtkTreeIter it;
@@ -676,11 +676,13 @@ static GtkWidget* create_list_of_nations_in_group(struct nation_group* group,
 
     gtk_list_store_append(store, &it);
 
-    s = crop_blankspace(get_nation_flag_sprite(tileset, pnation));
-    img = sprite_get_pixbuf(s);
     used = (pnation->player != NULL && pnation->player != races_player);
-    gtk_list_store_set(store, &it, 0, pnation->index, 1, used, 2, img, -1);
-    free_sprite(s);
+    gtk_list_store_set(store, &it, 0, nation_number(pnation), 1, used, -1);
+    img = get_flag(pnation);
+    if (img != NULL) {
+      gtk_list_store_set(store, &it, 2, img, -1);
+      g_object_unref(img);
+    }
 
     if (pnation->player == races_player) {
       /* FIXME: should select this one by default. */
diff --git a/client/gui-gtk-2.0/plrdlg.c b/client/gui-gtk-2.0/plrdlg.c
index cea6a88..cd88021 100644
--- a/client/gui-gtk-2.0/plrdlg.c
+++ b/client/gui-gtk-2.0/plrdlg.c
@@ -532,12 +532,14 @@ void create_players_dialog(void)
 #define MIN_DIMENSION 5
 
 /**************************************************************************
- Builds the flag pixmap.
+ Builds the flag pixmap. May return NULL if there is not enough memory.
+ You must call g_object_unref on the returned pixbuf when it is no
+ longer needed.
 **************************************************************************/
 GdkPixbuf *get_flag(const struct nation_type *nation)
 {
   int x0, y0, x1, y1, w, h;
-  GdkPixbuf *im, *im2;
+  GdkPixbuf *im;
   struct sprite *flag;
 
   flag = get_nation_flag_sprite(tileset, nation);
@@ -557,12 +559,14 @@ GdkPixbuf *get_flag(const struct nation_type *nation)
   assert(w >= MIN_DIMENSION && h >= MIN_DIMENSION);
 
   /* croping */
-  im = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(flag), x0, y0, w, h);
-  im2 = gdk_pixbuf_copy(im);
-  g_object_unref(im);
+  im = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
+  if (im != NULL) {
+    gdk_pixbuf_copy_area(sprite_get_pixbuf(flag), x0, y0, w, h,
+                         im, 0, 0);
+  }
 
   /* and finaly store the scaled flag pixbuf in the static flags array */
-  return im2;
+  return im;
 }
 
 
diff --git a/client/gui-gtk-2.0/dialogs.c b/client/gui-gtk-2.0/dialogs.c
index 8aaaa2c..4561974 100644
--- a/client/gui-gtk-2.0/dialogs.c
+++ b/client/gui-gtk-2.0/dialogs.c
@@ -50,6 +50,7 @@
 #include "mapview.h"
 #include "options.h"
 #include "packhand.h"
+#include "plrdlg.h"
 #include "text.h"
 #include "tilespec.h"
 
@@ -691,7 +692,6 @@ static GtkWidget* create_list_of_nations_in_group(struct nation_group* group,
 
   /* Populate nation list store. */
   nations_iterate(pnation) {
-    struct sprite *s;
     bool used;
     GdkPixbuf *img;
     GtkTreeIter it;
@@ -707,12 +707,13 @@ static GtkWidget* create_list_of_nations_in_group(struct nation_group* group,
 
     gtk_list_store_append(store, &it);
 
-    s = crop_blankspace(get_nation_flag_sprite(tileset, pnation));
-    img = sprite_get_pixbuf(s);
     used = (pnation->player != NULL && pnation->player != races_player);
-    gtk_list_store_set(store, &it, 0, nation_number(pnation), 1, used, 2, img, -1);
-    free_sprite(s);
-
+    gtk_list_store_set(store, &it, 0, nation_number(pnation), 1, used, -1);
+    img = get_flag(pnation);
+    if (img != NULL) {
+      gtk_list_store_set(store, &it, 2, img, -1);
+      g_object_unref(img);
+    }
     if (pnation->player == races_player) {
       /* FIXME: should select this one by default. */
     }
diff --git a/client/gui-gtk-2.0/plrdlg.c b/client/gui-gtk-2.0/plrdlg.c
index c819824..f91f81b 100644
--- a/client/gui-gtk-2.0/plrdlg.c
+++ b/client/gui-gtk-2.0/plrdlg.c
@@ -555,12 +555,14 @@ void create_players_dialog(void)
 #define MIN_DIMENSION 5
 
 /**************************************************************************
- Builds the flag pixmap.
+ Builds the flag pixmap. May return NULL if there is not enough memory.
+ You must call g_object_unref on the returned pixbuf when it is no
+ longer needed.
 **************************************************************************/
 GdkPixbuf *get_flag(const struct nation_type *nation)
 {
   int x0, y0, x1, y1, w, h;
-  GdkPixbuf *im, *im2;
+  GdkPixbuf *im;
   struct sprite *flag;
 
   flag = get_nation_flag_sprite(tileset, nation);
@@ -580,12 +582,14 @@ GdkPixbuf *get_flag(const struct nation_type *nation)
   assert(w >= MIN_DIMENSION && h >= MIN_DIMENSION);
 
   /* croping */
-  im = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(flag), x0, y0, w, h);
-  im2 = gdk_pixbuf_copy(im);
-  g_object_unref(im);
+  im = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
+  if (im != NULL) {
+    gdk_pixbuf_copy_area(sprite_get_pixbuf(flag), x0, y0, w, h,
+                         im, 0, 0);
+  }
 
   /* and finaly store the scaled flag pixbuf in the static flags array */
-  return im2;
+  return im;
 }
 
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to