Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#11507) use pixbufs for gtk2 sprites
Home

[Freeciv-Dev] (PR#11507) use pixbufs for gtk2 sprites

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#11507) use pixbufs for gtk2 sprites
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 31 Jan 2005 17:02:29 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Seems crop_sprite completely didn't work with a mask, meaning isotrident
basically didn't work at all.  Dunno how I missed that, I guess I only
tested it in trident.

Anyway, here is a new patch with a new-and-cool implementation of
crop_sprite.  The new implementation allows alpha levels in the cropping
mask as well.  This means alpha levels can be used for the blending mask.

At some point we should introduce a cleanup_sprite() function.  This
function should remove and unreference the pixbuf if there is a pixmap
present (i.e., if there's no alpha).  sprite_get_pixbuf is used for
small sprites which is fine, but it's also used inside crop_sprite which
means we end up with duplicate copies for each base tileset sprite.

-jason

Index: client/gui-gtk-2.0/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/dialogs.c,v
retrieving revision 1.88
diff -u -r1.88 dialogs.c
--- client/gui-gtk-2.0/dialogs.c        22 Jan 2005 19:45:40 -0000      1.88
+++ client/gui-gtk-2.0/dialogs.c        1 Feb 2005 00:59:15 -0000
@@ -1652,10 +1652,9 @@
     gtk_list_store_append(store, &it);
 
     s = crop_blankspace(nation->flag_sprite);
-    img = gdk_pixbuf_new_from_sprite(s);
-    free_sprite(s);
+    img = sprite_get_pixbuf(s);
     gtk_list_store_set(store, &it, 0, i, 1, FALSE, 2, img, -1);
-    g_object_unref(img);
+    free_sprite(s);
 
     g_value_init(&value, G_TYPE_STRING);
     g_value_set_static_string(&value, nation->name);
Index: client/gui-gtk-2.0/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/diplodlg.c,v
retrieving revision 1.26
diff -u -r1.26 diplodlg.c
--- client/gui-gtk-2.0/diplodlg.c       22 Jan 2005 20:31:11 -0000      1.26
+++ client/gui-gtk-2.0/diplodlg.c       1 Feb 2005 00:59:15 -0000
@@ -640,12 +640,10 @@
     gtk_list_store_set(store, &it, 0, buf, -1);
   } clause_list_iterate_end;
 
-  gtk_image_set_from_pixmap(GTK_IMAGE(pdialog->image0),
-                           get_thumb_pixmap(pdialog->treaty.accept0),
-                           NULL);
-  gtk_image_set_from_pixmap(GTK_IMAGE(pdialog->image1),
-                           get_thumb_pixmap(pdialog->treaty.accept1),
-                           NULL);
+  gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image0),
+                           get_thumb_pixbuf(pdialog->treaty.accept0));
+  gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image1),
+                           get_thumb_pixbuf(pdialog->treaty.accept1));
 }
 
 /****************************************************************
Index: client/gui-gtk-2.0/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/graphics.c,v
retrieving revision 1.31
diff -u -r1.31 graphics.c
--- client/gui-gtk-2.0/graphics.c       25 Dec 2004 19:50:29 -0000      1.31
+++ client/gui-gtk-2.0/graphics.c       1 Feb 2005 00:59:15 -0000
@@ -49,8 +49,8 @@
 #include "patrol_cursor.xbm"
 #include "patrol_cursor_mask.xbm"
 
-SPRITE *               intro_gfx_sprite;
-SPRITE *               radar_gfx_sprite;
+SPRITE *               intro_gfx_sprite;
+SPRITE *               radar_gfx_sprite;
 
 GdkCursor *            goto_cursor;
 GdkCursor *            drop_cursor;
@@ -102,38 +102,65 @@
                           struct Sprite *mask,
                           int mask_offset_x, int mask_offset_y)
 {
-  GdkPixmap *mypixmap, *mymask = NULL;
-
-  mypixmap = gdk_pixmap_new(root_window, width, height, -1);
-
-  gdk_draw_drawable(mypixmap, civ_gc, source->pixmap, x, y, 0, 0,
-                   width, height);
-
-  if (source->mask) {
-    mymask = gdk_pixmap_new(NULL, width, height, 1);
-    gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1);
-
-    gdk_draw_drawable(mymask, mask_fg_gc, source->mask,
-                     x, y, 0, 0, width, height);
-  }
+  GdkPixbuf *mypixbuf, *sub, *mask_pixbuf;
 
+  /* First just crop the image. */
+  if (x < 0) {
+    width += x;
+    x = 0;
+  }
+  if (y < 0) {
+    height += y;
+    y = 0;
+  }
+  width = CLIP(0, width, source->width - x);
+  height = CLIP(0, height, source->height - y);
+  sub = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(source), x, y,
+                                width, height);
+  mypixbuf = gdk_pixbuf_copy(sub);
+  g_object_unref(sub);
+
+  /* Now mask.  This reduces the alpha of the final image proportional to the
+   * alpha of the mask.  Thus if the mask has 50% alpha the final image will
+   * be reduced by 50% alpha.  Note that the mask offset is in coordinates
+   * relative to the clipped image not the final image. */
   if (mask) {
-    if (mymask) {
-      gdk_gc_set_function(mask_fg_gc, GDK_AND);
-      gdk_draw_drawable(mymask, mask_fg_gc, mask->mask,
-                       x - mask_offset_x, y - mask_offset_y,
-                       0, 0, width, height);
-      gdk_gc_set_function(mask_fg_gc, GDK_OR);
-    } else {
-      mymask = gdk_pixmap_new(NULL, width, height, 1);
-      gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1);
+    int x1, y1;
 
-      gdk_draw_drawable(mymask, mask_fg_gc, source->mask,
-                       x, y, 0, 0, width, height);
+    /* The mask offset is the offset into the mask relative to the origin
+     * of the original source image.  For instance when cropping with
+     * blending sprites the offset is always 0.  Here we convert the
+     * coordinates so that they are relative to the origin of the new
+     * (cropped) image. */
+    mask_offset_x += x;
+    mask_offset_y += y;
+
+    width = CLIP(0, width, mask->width - mask_offset_x);
+    height = CLIP(0, height, mask->height - mask_offset_y);
+
+    mask_pixbuf = sprite_get_pixbuf(mask);
+
+    gdk_pixbuf_add_alpha(mypixbuf, FALSE, 0, 0, 0);
+    gdk_pixbuf_add_alpha(mask_pixbuf, FALSE, 0, 0, 0);
+
+    for (x1 = 0; x1 < width; x1++) {
+      for (y1 = 0; y1 < height; y1++) {
+       int mask_x = x1 + mask_offset_x, mask_y = y1 + mask_offset_y;
+       guchar *alpha = gdk_pixbuf_get_pixels(mypixbuf)
+         + y1 * gdk_pixbuf_get_rowstride(mypixbuf)
+         + x1 * gdk_pixbuf_get_n_channels(mypixbuf)
+         + 3;
+       guchar *mask_alpha = gdk_pixbuf_get_pixels(mask_pixbuf)
+         + mask_y * gdk_pixbuf_get_rowstride(mask_pixbuf)
+         + mask_x * gdk_pixbuf_get_n_channels(mask_pixbuf)
+         + 3;
+
+       *alpha = (*alpha) * (*mask_alpha) / 255;
+      }
     }
   }
 
-  return ctor_sprite_mask(mypixmap, mymask, width, height);
+  return ctor_sprite(mypixbuf);
 }
 
 /****************************************************************************
@@ -213,21 +240,51 @@
  Create a new sprite with the given pixmap, dimensions, and
  (optional) mask.
 ***************************************************************************/
-SPRITE *ctor_sprite_mask( GdkPixmap *mypixmap, GdkPixmap *mask, 
-                         int width, int height )
+SPRITE *ctor_sprite(GdkPixbuf *pixbuf)
 {
-    SPRITE *mysprite = fc_malloc(sizeof(SPRITE));
+  struct Sprite *sprite = fc_malloc(sizeof(*sprite));
+  bool has_alpha = FALSE, has_mask = FALSE;
 
-    mysprite->pixmap   = mypixmap;
-    mysprite->fogged = NULL;
-    mysprite->mask = mask;
+  sprite->width = gdk_pixbuf_get_width(pixbuf);
+  sprite->height = gdk_pixbuf_get_height(pixbuf);
 
-    mysprite->width    = width;
-    mysprite->height   = height;
+  /* Check to see if this pixbuf has an alpha layer. */
+  if (gdk_pixbuf_get_has_alpha(pixbuf)) {
+    guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+    int x, y, rowstride = gdk_pixbuf_get_rowstride(pixbuf);
+
+    for (y = 0; y < sprite->height; y++) {
+      for (x = 0; x < sprite->width; x++) {
+       int i = y * rowstride + 4 * x + 3;
+       guchar pixel = pixels[i];
 
-    mysprite->pixbuf   = NULL;
+       if (pixel > 0 && pixel < 255) {
+         has_alpha = TRUE;
+       }
+       if (pixel == 0) {
+         has_mask = TRUE;
+       }
+      }
+    }
+  }
 
-    return mysprite;
+  sprite->pixbuf_fogged = NULL;
+  sprite->pixmap_fogged = NULL;
+  if (has_alpha) {
+    sprite->pixbuf = pixbuf;
+    sprite->pixmap = NULL;
+    sprite->mask = NULL;
+  } else {
+    gdk_pixbuf_render_pixmap_and_mask(pixbuf, &sprite->pixmap,
+                                     &sprite->mask, 1);
+    if (!has_mask && sprite->mask) {
+      g_object_unref(sprite->mask);
+      sprite->mask = NULL;
+    }
+    g_object_unref(pixbuf);
+    sprite->pixbuf = NULL;
+  }
+  return sprite;
 }
 
 
@@ -264,28 +321,13 @@
 struct Sprite *load_gfxfile(const char *filename)
 {
   GdkPixbuf *im;
-  SPRITE    *mysprite;
-  int       w, h;
 
   if (!(im = gdk_pixbuf_new_from_file(filename, NULL))) {
     freelog(LOG_FATAL, "Failed reading graphics file: %s", filename);
     exit(EXIT_FAILURE);
   }
 
-  mysprite=fc_malloc(sizeof(struct Sprite));
-
-  w = gdk_pixbuf_get_width(im); h = gdk_pixbuf_get_height(im);
-  gdk_pixbuf_render_pixmap_and_mask(im, &mysprite->pixmap, &mysprite->mask, 1);
-
-  mysprite->width     = w;
-  mysprite->height    = h;
-
-  mysprite->pixbuf    = NULL;
-  mysprite->fogged = NULL;
-
-  g_object_unref(im);
-
-  return mysprite;
+  return ctor_sprite(im);
 }
 
 /***************************************************************************
@@ -303,9 +345,13 @@
   }
   if (s->pixbuf) {
     g_object_unref(s->pixbuf);
+    s->pixbuf = NULL;
   }
-  if (s->fogged) {
-    g_object_unref(s->fogged);
+  if (s->pixmap_fogged) {
+    g_object_unref(s->pixmap_fogged);
+  }
+  if (s->pixbuf_fogged) {
+    g_object_unref(s->pixbuf_fogged);
   }
   free(s);
 }
@@ -376,24 +422,9 @@
 ***************************************************************************/
 SPRITE* sprite_scale(SPRITE *src, int new_w, int new_h)
 {
-  GdkPixbuf *original, *im;
-  SPRITE    *mysprite;
-
-  original = sprite_get_pixbuf(src);
-  im = gdk_pixbuf_scale_simple(original, new_w, new_h, GDK_INTERP_BILINEAR);
-
-  mysprite=fc_malloc(sizeof(struct Sprite));
-
-  gdk_pixbuf_render_pixmap_and_mask(im, &mysprite->pixmap, &mysprite->mask, 1);
-
-  mysprite->width     = new_w;
-  mysprite->height    = new_h;
-
-  mysprite->pixbuf    = NULL;
-  mysprite->fogged = NULL;
-  g_object_unref(im);
-
-  return mysprite;
+  return ctor_sprite(gdk_pixbuf_scale_simple(sprite_get_pixbuf(src),
+                                            new_w, new_h,
+                                            GDK_INTERP_BILINEAR));
 }
 
 /***************************************************************************
@@ -405,9 +436,10 @@
                             int *start_y, int *end_x, int *end_y)
 {
   GdkImage *mask_image;
+  GdkBitmap *mask = sprite_get_mask(sprite);
   int i, j;
 
-  if (!sprite->mask) {
+  if (!mask) {
     *start_x = 0;
     *start_y = 0;
     *end_x = sprite->width - 1;
@@ -416,7 +448,7 @@
   }
 
   mask_image =
-    gdk_drawable_get_image(sprite->mask, 0, 0, sprite->width, sprite->height);
+    gdk_drawable_get_image(mask, 0, 0, sprite->width, sprite->height);
 
 
   /* parses mask image for the first column that contains a visible pixel */
@@ -522,9 +554,11 @@
 }
 
 /********************************************************************
+  Render a pixbuf from the sprite.
+
  NOTE: the pixmap and mask of a sprite must not change after this
        function is called!
- ********************************************************************/
+********************************************************************/
 GdkPixbuf *sprite_get_pixbuf(SPRITE *sprite)
 {
   if (!sprite) {
@@ -537,3 +571,18 @@
   return sprite->pixbuf;
 }
 
+/****************************************************************************
+  Render a mask from the sprite.
+
+  NOTE: the pixbuf of a sprite must not change after this function is called!
+****************************************************************************/
+GdkBitmap *sprite_get_mask(struct Sprite *sprite)
+{
+  if (!sprite->pixmap && !sprite->mask) {
+    /* If we're not in pixmap mode and we don't yet have a mask, render
+     * the pixbuf to a mask. */
+    gdk_pixbuf_render_pixmap_and_mask(sprite->pixbuf, NULL,
+                                     &sprite->mask, 1);
+  }
+  return sprite->mask;
+}
Index: client/gui-gtk-2.0/graphics.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/graphics.h,v
retrieving revision 1.10
diff -u -r1.10 graphics.h
--- client/gui-gtk-2.0/graphics.h       25 Dec 2004 19:50:29 -0000      1.10
+++ client/gui-gtk-2.0/graphics.h       1 Feb 2005 00:59:15 -0000
@@ -20,13 +20,17 @@
 
 struct Sprite
 {
-  GdkPixmap *pixmap;
-  GdkPixmap *fogged;
+  /* A pixmap + mask is used if there's a 1-bit alpha channel.  mask may be
+   * NULL if there's no alpha.  For multi-bit alpha levels, a pixbuf will be
+   * used instead.  For consistency a pixbuf may be generated on-demand when
+   * doing drawing (into a gtkpixcomm or gtkimage), so it's important that
+   * the sprite data not be changed after the sprite is loaded. */
+  GdkPixmap *pixmap, *pixmap_fogged;
   GdkBitmap *mask;
+  GdkPixbuf *pixbuf, *pixbuf_fogged;
+
   int       width;
   int       height;
-
-  GdkPixbuf *pixbuf;
 };
 
 typedef struct Sprite SPRITE;
@@ -45,8 +49,7 @@
                              GdkGC *white_gc,
                              gint x, gint y, PangoLayout *layout);
 
-SPRITE *ctor_sprite_mask(GdkPixmap *mypixmap, GdkPixmap *mask,
-                        int width, int height);
+SPRITE *ctor_sprite(GdkPixbuf *pixbuf);
 SPRITE* sprite_scale(SPRITE *src, int new_w, int new_h);
 void sprite_get_bounding_box(SPRITE * sprite, int *start_x,
                             int *start_y, int *end_x, int *end_y);
@@ -55,10 +58,10 @@
 GdkPixbuf *gdk_pixbuf_new_from_sprite(SPRITE *src);
   
 /********************************************************************
- NOTE: the pixmap and mask of a sprite must not change after this
-       function is called!
+  Note: a sprite cannot be changed after these functions are called!
  ********************************************************************/
 GdkPixbuf *sprite_get_pixbuf(SPRITE *sprite);
+GdkBitmap *sprite_get_mask(struct Sprite *sprite);
 
 #endif  /* FC__GRAPHICS_H */
 
Index: client/gui-gtk-2.0/gtkpixcomm.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gtkpixcomm.c,v
retrieving revision 1.13
diff -u -r1.13 gtkpixcomm.c
--- client/gui-gtk-2.0/gtkpixcomm.c     15 Dec 2004 23:18:18 -0000      1.13
+++ client/gui-gtk-2.0/gtkpixcomm.c     1 Feb 2005 00:59:15 -0000
@@ -246,24 +246,33 @@
         break;
 
       case OP_COPY:
-        if (rop->src->mask) {
-          gdk_gc_set_clip_mask(civ_gc, rop->src->mask);
-          gdk_gc_set_clip_origin(civ_gc, x + rop->x, y + rop->y);
-
-          gdk_draw_drawable(widget->window, civ_gc,
-             rop->src->pixmap,
-             0, 0,
-             x + rop->x, y + rop->y,
-             rop->src->width, rop->src->height);
-
-          gdk_gc_set_clip_origin(civ_gc, 0, 0);
-          gdk_gc_set_clip_mask(civ_gc, NULL);
-        } else {
-          gdk_draw_drawable(widget->window, civ_gc,
-             rop->src->pixmap,
-             0, 0,
-             x + rop->x, y + rop->y,
-             rop->src->width, rop->src->height);
+       if (rop->src->pixmap) {
+         if (rop->src->mask) {
+           gdk_gc_set_clip_mask(civ_gc, rop->src->mask);
+           gdk_gc_set_clip_origin(civ_gc, x + rop->x, y + rop->y);
+
+           gdk_draw_drawable(widget->window, civ_gc,
+                             rop->src->pixmap,
+                             0, 0,
+                             x + rop->x, y + rop->y,
+                             rop->src->width, rop->src->height);
+
+           gdk_gc_set_clip_origin(civ_gc, 0, 0);
+           gdk_gc_set_clip_mask(civ_gc, NULL);
+         } else {
+           gdk_draw_drawable(widget->window, civ_gc,
+                             rop->src->pixmap,
+                             0, 0,
+                             x + rop->x, y + rop->y,
+                             rop->src->width, rop->src->height);
+         }
+       } else {
+         gdk_draw_pixbuf(widget->window, civ_gc,
+                         rop->src->pixbuf,
+                         0, 0,
+                         x + rop->x, y + rop->y,
+                         rop->src->width, rop->src->height,
+                         GDK_RGB_DITHER_NONE, 0, 0);
        }
         break;
 
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.c,v
retrieving revision 1.103
diff -u -r1.103 gui_main.c
--- client/gui-gtk-2.0/gui_main.c       28 Jan 2005 19:57:09 -0000      1.103
+++ client/gui-gtk-2.0/gui_main.c       1 Feb 2005 00:59:16 -0000
@@ -621,8 +621,8 @@
     gtk_pixcomm_clear(GTK_PIXCOMM(unit_below_pixmap[i]));
   }
 
-  more_arrow_pixmap = gtk_image_new_from_pixmap(sprites.right_arrow->pixmap,
-                                               NULL);
+  more_arrow_pixmap
+    = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprites.right_arrow));
   gtk_widget_ref(more_arrow_pixmap);
   gtk_table_attach_defaults(GTK_TABLE(table), more_arrow_pixmap, 4, 5, 1, 2);
 
@@ -826,14 +826,16 @@
                      G_CALLBACK(taxrates_callback), GINT_TO_POINTER(i));
 
     sprite = i < 5 ? sprites.tax_science : sprites.tax_gold;
-    econ_label[i] = gtk_image_new_from_pixmap(sprite->pixmap, sprite->mask);
+    econ_label[i] = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprite));
     gtk_container_add(GTK_CONTAINER(ebox), econ_label[i]);
   }
 
   /* science, environmental, govt, timeout */
-  bulb_label = gtk_image_new_from_pixmap(sprites.bulb[0]->pixmap, NULL);
-  sun_label = gtk_image_new_from_pixmap(sprites.warming[0]->pixmap, NULL);
-  flake_label = gtk_image_new_from_pixmap(sprites.cooling[0]->pixmap, NULL);
+  bulb_label = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprites.bulb[0]));
+  sun_label
+    = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprites.warming[0]));
+  flake_label
+    = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprites.cooling[0]));
   {
     /* HACK: the UNHAPPY citizen is used for the government
      * when we don't know any better. */
@@ -841,7 +843,7 @@
 
     sprite = get_citizen_sprite(c, 0, NULL);
   }
-  government_label = gtk_image_new_from_pixmap(sprite->pixmap, sprite->mask);
+  government_label = gtk_image_new_from_pixbuf(sprite_get_pixbuf(sprite));
 
   for (i = 0; i < 4; i++) {
     GtkWidget *w;
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.155
diff -u -r1.155 mapview.c
--- client/gui-gtk-2.0/mapview.c        21 Jan 2005 03:36:26 -0000      1.155
+++ client/gui-gtk-2.0/mapview.c        1 Feb 2005 00:59:16 -0000
@@ -128,23 +128,23 @@
   for (; d < game.player_ptr->economic.luxury /10; d++) {
     struct Sprite *sprite = sprites.tax_luxury;
 
-    gtk_image_set_from_pixmap(GTK_IMAGE(econ_label[d]),
-                             sprite->pixmap, sprite->mask);
+    gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]),
+                             sprite_get_pixbuf(sprite));
   }
  
   for (; d < (game.player_ptr->economic.science
             + game.player_ptr->economic.luxury) / 10; d++) {
     struct Sprite *sprite = sprites.tax_science;
 
-    gtk_image_set_from_pixmap(GTK_IMAGE(econ_label[d]),
-                             sprite->pixmap, sprite->mask);
+    gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]),
+                             sprite_get_pixbuf(sprite));
   }
  
   for (; d < 10; d++) {
     struct Sprite *sprite = sprites.tax_gold;
 
-    gtk_image_set_from_pixmap(GTK_IMAGE(econ_label[d]),
-                             sprite->pixmap, sprite->mask);
+    gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]),
+                             sprite_get_pixbuf(sprite));
   }
  
   update_timeout_label();
@@ -216,9 +216,9 @@
 /**************************************************************************
 ...
 **************************************************************************/
-GdkPixmap *get_thumb_pixmap(int onoff)
+GdkPixbuf *get_thumb_pixbuf(int onoff)
 {
-  return sprites.treaty_thumb[BOOL_VAL(onoff)]->pixmap;
+  return sprite_get_pixbuf(sprites.treaty_thumb[BOOL_VAL(onoff)]);
 }
 
 /**************************************************************************
@@ -232,12 +232,12 @@
   sol = CLIP(0, sol, NUM_TILES_PROGRESS-1);
   flake = CLIP(0, flake, NUM_TILES_PROGRESS-1);
 
-  gtk_image_set_from_pixmap(GTK_IMAGE(bulb_label),
-                           sprites.bulb[bulb]->pixmap, NULL);
-  gtk_image_set_from_pixmap(GTK_IMAGE(sun_label),
-                           sprites.warming[sol]->pixmap, NULL);
-  gtk_image_set_from_pixmap(GTK_IMAGE(flake_label),
-                           sprites.cooling[flake]->pixmap, NULL);
+  gtk_image_set_from_pixbuf(GTK_IMAGE(bulb_label),
+                           sprite_get_pixbuf(sprites.bulb[bulb]));
+  gtk_image_set_from_pixbuf(GTK_IMAGE(sun_label),
+                           sprite_get_pixbuf(sprites.warming[sol]));
+  gtk_image_set_from_pixbuf(GTK_IMAGE(flake_label),
+                           sprite_get_pixbuf(sprites.cooling[flake]));
 
   if (game.government_count==0) {
     /* HACK: the UNHAPPY citizen is used for the government
@@ -248,8 +248,8 @@
   } else {
     gov_sprite = get_government(gov)->sprite;
   }
-  gtk_image_set_from_pixmap(GTK_IMAGE(government_label),
-                           gov_sprite->pixmap, NULL);
+  gtk_image_set_from_pixbuf(GTK_IMAGE(government_label),
+                           sprite_get_pixbuf(gov_sprite));
 }
 
 /**************************************************************************
@@ -639,15 +639,23 @@
   if (!ssprite) {
     return;
   }
-      
-  gdk_gc_set_clip_origin(civ_gc, canvas_x, canvas_y);
-  gdk_gc_set_clip_mask(civ_gc, ssprite->mask);
 
-  gdk_draw_drawable(pixmap, civ_gc, ssprite->pixmap,
+  if (ssprite->pixmap) {
+    gdk_gc_set_clip_origin(civ_gc, canvas_x, canvas_y);
+    gdk_gc_set_clip_mask(civ_gc, ssprite->mask);
+
+    gdk_draw_drawable(pixmap, civ_gc, ssprite->pixmap,
+                     0, 0,
+                     canvas_x, canvas_y,
+                     ssprite->width, ssprite->height);
+    gdk_gc_set_clip_mask(civ_gc, NULL);
+  } else {
+    gdk_draw_pixbuf(pixmap, civ_gc, ssprite->pixbuf,
                    0, 0,
-                   canvas_x, canvas_y,
-                   ssprite->width, ssprite->height);
-  gdk_gc_set_clip_mask(civ_gc, NULL);
+                 canvas_x, canvas_y,
+                 ssprite->width, ssprite->height,
+                 GDK_RGB_DITHER_NONE, 0, 0);
+  }
 }
 
 /**************************************************************************
@@ -659,18 +667,27 @@
                              int offset_x, int offset_y,
                              int width, int height)
 {
-  if (ssprite->mask) {
-    gdk_gc_set_clip_origin(civ_gc, pixmap_x, pixmap_y);
-    gdk_gc_set_clip_mask(civ_gc, ssprite->mask);
-  }
+  if (ssprite->pixmap) {
+    if (ssprite->mask) {
+      gdk_gc_set_clip_origin(civ_gc, pixmap_x, pixmap_y);
+      gdk_gc_set_clip_mask(civ_gc, ssprite->mask);
+    }
 
-  gdk_draw_drawable(pixmap, civ_gc, ssprite->pixmap,
+    gdk_draw_drawable(pixmap, civ_gc, ssprite->pixmap,
+                     offset_x, offset_y,
+                     pixmap_x + offset_x, pixmap_y + offset_y,
+                     MIN(width, MAX(0, ssprite->width - offset_x)),
+                     MIN(height, MAX(0, ssprite->height - offset_y)));
+
+    gdk_gc_set_clip_mask(civ_gc, NULL);
+  } else {
+    gdk_draw_pixbuf(pixmap, civ_gc, ssprite->pixbuf,
                    offset_x, offset_y,
                    pixmap_x + offset_x, pixmap_y + offset_y,
                    MIN(width, MAX(0, ssprite->width - offset_x)),
-                   MIN(height, MAX(0, ssprite->height - offset_y)));
-
-  gdk_gc_set_clip_mask(civ_gc, NULL);
+                   MIN(height, MAX(0, ssprite->height - offset_y)),
+                   GDK_RGB_DITHER_NONE, 0, 0);
+  }
 }
 
 /**************************************************************************
@@ -783,7 +800,7 @@
 {
   if (pcanvas->type == CANVAS_PIXMAP) {
     gdk_gc_set_clip_origin(fill_bg_gc, canvas_x, canvas_y);
-    gdk_gc_set_clip_mask(fill_bg_gc, psprite->mask);
+    gdk_gc_set_clip_mask(fill_bg_gc, sprite_get_mask(psprite));
     gdk_gc_set_foreground(fill_bg_gc, colors_standard[color]);
 
     gdk_draw_rectangle(pcanvas->v.pixmap, fill_bg_gc, TRUE,
@@ -801,7 +818,7 @@
 {
   if (pcanvas->type == CANVAS_PIXMAP) {
     gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
-    gdk_gc_set_clip_mask(fill_tile_gc, psprite->mask);
+    gdk_gc_set_clip_mask(fill_tile_gc, sprite_get_mask(psprite));
     gdk_gc_set_foreground(fill_tile_gc, colors_standard[COLOR_STD_BLACK]);
     gdk_gc_set_stipple(fill_tile_gc, black50);
     gdk_gc_set_ts_origin(fill_tile_gc, canvas_x, canvas_y);
@@ -870,10 +887,14 @@
   guchar *pixel;
   const int bright = 65; /* Brightness percentage */
 
-  fogged = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
-                         sprite->width, sprite->height);
-  gdk_pixbuf_get_from_drawable(fogged, sprite->pixmap, NULL,
-                              0, 0, 0, 0, sprite->width, sprite->height);
+  if (sprite->pixmap) {
+    fogged = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
+                           sprite->width, sprite->height);
+    gdk_pixbuf_get_from_drawable(fogged, sprite->pixmap, NULL,
+                                0, 0, 0, 0, sprite->width, sprite->height);
+  } else {
+    fogged = gdk_pixbuf_copy(sprite->pixbuf);
+  }
 
   /* Iterate over all pixels, reducing brightness by 50%. */
   for (x = 0; x < sprite->width; x++) {
@@ -888,9 +909,13 @@
     }
   }
 
-  gdk_pixbuf_render_pixmap_and_mask(fogged, &sprite->fogged,
-                                   NULL, 0);
-  g_object_unref(fogged);
+  if (sprite->pixmap) {
+    gdk_pixbuf_render_pixmap_and_mask(fogged, &sprite->pixmap_fogged,
+                                     NULL, 0);
+    g_object_unref(fogged);
+  } else {
+    sprite->pixbuf_fogged = fogged;
+  }
 }
 
 /**************************************************************************
@@ -905,9 +930,12 @@
     return;
   }
 
-  if (fog && better_fog && !ssprite->fogged) {
+  if (fog && better_fog
+      && ((ssprite->pixmap && !ssprite->pixmap_fogged)
+         || (!ssprite->pixmap && !ssprite->pixbuf_fogged))) {
     fog_sprite(ssprite);
-    if (!ssprite->fogged) {
+    if ((ssprite->pixmap && !ssprite->pixmap_fogged)
+       || (!ssprite->pixmap && !ssprite->pixbuf_fogged)) {
       freelog(LOG_NORMAL,
              _("Better fog will only work in truecolor.  Disabling it"));
       better_fog = FALSE;
@@ -915,16 +943,23 @@
   }
 
   if (fog && better_fog) {
-    gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
-    gdk_gc_set_clip_mask(fill_tile_gc, ssprite->mask);
-
-    gdk_draw_drawable(pixmap, fill_tile_gc,
-                     ssprite->fogged,
-                     0, 0,
-                     canvas_x, canvas_y,
-                     ssprite->width, ssprite->height);
-    gdk_gc_set_clip_mask(fill_tile_gc, NULL);
-
+    if (ssprite->pixmap) {
+      if (ssprite->mask) {
+       gdk_gc_set_clip_origin(civ_gc, canvas_x, canvas_y);
+       gdk_gc_set_clip_mask(civ_gc, ssprite->mask);
+      }
+      gdk_draw_drawable(pixmap, civ_gc,
+                       ssprite->pixmap_fogged,
+                       0, 0,
+                       canvas_x, canvas_y,
+                       ssprite->width, ssprite->height);
+      gdk_gc_set_clip_mask(civ_gc, NULL);
+    } else {
+      gdk_draw_pixbuf(pixmap, civ_gc, ssprite->pixbuf_fogged,
+                     0, 0, canvas_x, canvas_y, 
+                     ssprite->width, ssprite->height,
+                     GDK_RGB_DITHER_NONE, 0, 0);
+    }
     return;
   }
 
@@ -936,7 +971,7 @@
      faster to just draw every second pixel black in the first place. */
   if (fog) {
     gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
-    gdk_gc_set_clip_mask(fill_tile_gc, ssprite->mask);
+    gdk_gc_set_clip_mask(fill_tile_gc, sprite_get_mask(ssprite));
     gdk_gc_set_foreground(fill_tile_gc, colors_standard[COLOR_STD_BLACK]);
     gdk_gc_set_ts_origin(fill_tile_gc, canvas_x, canvas_y);
     gdk_gc_set_stipple(fill_tile_gc, black50);
@@ -970,6 +1005,8 @@
                     enum color_std color, enum city_tile_type worker,
                     int canvas_x, int canvas_y)
 {
+  GdkBitmap *mask;
+
   if (pcanvas->type == CANVAS_PIXMAP) {
     if (worker == C_TILE_EMPTY) {
       gdk_gc_set_stipple(fill_tile_gc, gray25);
@@ -982,9 +1019,9 @@
     gdk_gc_set_ts_origin(fill_tile_gc, canvas_x, canvas_y);
     gdk_gc_set_foreground(fill_tile_gc, colors_standard[color]);
 
-    if (sprites.black_tile && sprites.black_tile->mask) {
+    if (sprites.black_tile && (mask = sprite_get_mask(sprites.black_tile))) {
       gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
-      gdk_gc_set_clip_mask(fill_tile_gc, sprites.black_tile->mask);
+      gdk_gc_set_clip_mask(fill_tile_gc, mask);
     }
 
     gdk_draw_rectangle(pcanvas->v.pixmap, fill_tile_gc, TRUE,
Index: client/gui-gtk-2.0/mapview.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.h,v
retrieving revision 1.18
diff -u -r1.18 mapview.h
--- client/gui-gtk-2.0/mapview.h        22 Jul 2004 05:42:47 -0000      1.18
+++ client/gui-gtk-2.0/mapview.h        1 Feb 2005 00:59:16 -0000
@@ -26,7 +26,7 @@
 struct unit;
 struct city;
 
-GdkPixmap *get_thumb_pixmap(int onoff);
+GdkPixbuf *get_thumb_pixbuf(int onoff);
 
 gboolean overview_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer 
data);
 gboolean map_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer data);
Index: client/gui-gtk-2.0/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/menu.c,v
retrieving revision 1.57
diff -u -r1.57 menu.c
--- client/gui-gtk-2.0/menu.c   25 Nov 2004 06:57:17 -0000      1.57
+++ client/gui-gtk-2.0/menu.c   1 Feb 2005 00:59:17 -0000
@@ -1204,7 +1204,7 @@
           item = gtk_image_menu_item_new_with_label(buf);
 
           gsprite = get_government(g->index)->sprite;
-          image = gtk_image_new_from_pixmap(gsprite->pixmap, gsprite->mask);
+          image = gtk_image_new_from_pixbuf(sprite_get_pixbuf(gsprite));
           gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
 
           gtk_widget_show(image);
Index: client/gui-gtk-2.0/pages.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/pages.c,v
retrieving revision 1.14
diff -u -r1.14 pages.c
--- client/gui-gtk-2.0/pages.c  22 Jan 2005 19:45:40 -0000      1.14
+++ client/gui-gtk-2.0/pages.c  1 Feb 2005 00:59:17 -0000
@@ -1386,7 +1386,7 @@
 static GdkPixbuf *get_flag(char *flag_str)
 {
   int x0, y0, x1, y1, w, h;
-  GdkPixbuf *im;
+  GdkPixbuf *im, *im2;
   SPRITE *flag;
 
   flag = load_sprite(flag_str);
@@ -1410,14 +1410,13 @@
   assert(w >= MIN_DIMENSION && h >= MIN_DIMENSION);
 
   /* get the pixbuf and crop*/
-  im = gdk_pixbuf_get_from_drawable(NULL, flag->pixmap,
-                                    gdk_colormap_get_system(),
-                                    x0, y0, 0, 0, w, h);
-
+  im = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(flag), x0, y0, w, h);
+  im2 = gdk_pixbuf_copy(im);
+  g_object_unref(im);
   unload_sprite(flag_str);
 
   /* and finaly store the scaled flag pixbuf in the static flags array */
-  return im;
+  return im2;
 }
 
 /**************************************************************************
Index: client/gui-gtk-2.0/plrdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/plrdlg.c,v
retrieving revision 1.48
diff -u -r1.48 plrdlg.c
--- client/gui-gtk-2.0/plrdlg.c 17 Dec 2004 16:25:18 -0000      1.48
+++ client/gui-gtk-2.0/plrdlg.c 1 Feb 2005 00:59:17 -0000
@@ -496,12 +496,9 @@
   assert(w >= MIN_DIMENSION && h >= MIN_DIMENSION);
 
   /* croping */
-  im = gdk_pixbuf_get_from_drawable(NULL,
-                                   flag->pixmap,
-                                   gdk_colormap_get_system(),
-                                   x0, y0,
-                                   0, 0,
-                                   w, h);
+  im = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(flag), x0, y0, w, h);
+  g_object_unref(im);
+  im = gdk_pixbuf_copy(im);
 
   /* and finaly store the scaled flag pixbuf in the static flags array */
   return im;
Index: client/gui-gtk-2.0/spaceshipdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/spaceshipdlg.c,v
retrieving revision 1.14
diff -u -r1.14 spaceshipdlg.c
--- client/gui-gtk-2.0/spaceshipdlg.c   22 Jan 2005 19:45:40 -0000      1.14
+++ client/gui-gtk-2.0/spaceshipdlg.c   1 Feb 2005 00:59:17 -0000
@@ -300,13 +300,10 @@
     sprite = (k==0 ? sprites.spaceship.habitation :
              k==1 ? sprites.spaceship.life_support :
                     sprites.spaceship.solar_panels);
-    gdk_gc_set_clip_origin(civ_gc, x, y);
-    gdk_gc_set_clip_mask(civ_gc, sprite->mask);
-    gdk_draw_drawable(pdialog->image_canvas->window, civ_gc, sprite->pixmap, 
-             0, 0,
-             x, y,
-             sprite->width, sprite->height);
-    gdk_gc_set_clip_mask(civ_gc,NULL);
+    gdk_draw_pixbuf(pdialog->image_canvas->window, civ_gc,
+                   sprite_get_pixbuf(sprite), 
+                   0, 0, x, y, sprite->width, sprite->height,
+                   GDK_RGB_DITHER_NONE, 0, 0);
   }
 
   for (i=0; i < NUM_SS_COMPONENTS; i++) {
@@ -321,13 +318,10 @@
 
     sprite = (k==0) ? sprites.spaceship.fuel : sprites.spaceship.propulsion;
 
-    gdk_gc_set_clip_origin(civ_gc, x, y);
-    gdk_gc_set_clip_mask(civ_gc, sprite->mask);
-    gdk_draw_drawable(pdialog->image_canvas->window, civ_gc, sprite->pixmap,
-             0, 0,
-             x, y,
-             sprite->width, sprite->height);
-    gdk_gc_set_clip_mask(civ_gc,NULL);
+    gdk_draw_pixbuf(pdialog->image_canvas->window, civ_gc,
+                   sprite_get_pixbuf(sprite),
+                   0, 0, x, y, sprite->width, sprite->height,
+                   GDK_RGB_DITHER_NONE, 0, 0);
   }
 
   sprite = sprites.spaceship.structural;
@@ -338,13 +332,10 @@
     x = structurals_info[i].x * sprite->width  / 4 - sprite->width / 2;
     y = structurals_info[i].y * sprite->height / 4 - sprite->height / 2;
 
-    gdk_gc_set_clip_origin(civ_gc, x, y);
-    gdk_gc_set_clip_mask(civ_gc, sprite->mask);
-    gdk_draw_drawable(pdialog->image_canvas->window, civ_gc, sprite->pixmap,
-             0, 0,
-             x, y,
-             sprite->width, sprite->height);
-    gdk_gc_set_clip_mask(civ_gc,NULL);
+    gdk_draw_pixbuf(pdialog->image_canvas->window, civ_gc,
+                   sprite_get_pixbuf(sprite),
+                   0, 0, x, y, sprite->width, sprite->height,
+                   GDK_RGB_DITHER_NONE, 0, 0);
   }
 }
 

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