Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#11791) SGL software 2D drawing
Home

[Freeciv-Dev] (PR#11791) SGL software 2D drawing

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#11791) SGL software 2D drawing
From: "Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx>
Date: Tue, 4 Jan 2005 11:24:23 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This patch changes the gtk-2.0 client to use our own software rendering
code, more or less based on SDL code. For now only 'trident' will
work more or less properly, a lot of things are broken. But the main
map should display most things.

Why not just use SDL? Because SDL plays along poorly with GTK+ for one,
and is made with a single output window model in mind for another.

Things TODO:
Fix isometric drawing, fix overview map, implement line drawing for
borders, make text look less bad, etc, etc.

Index: client/gui-gtk-2.0/colors.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/colors.c,v
retrieving revision 1.4
diff -u -r1.4 colors.c
--- client/gui-gtk-2.0/colors.c 14 Nov 2002 09:14:55 -0000      1.4
+++ client/gui-gtk-2.0/colors.c 4 Jan 2005 19:15:03 -0000
@@ -26,9 +26,7 @@
 
 #include "colors.h"
 
-static struct rgbtriple {
-  int r, g, b;
-} colors_standard_rgb[COLOR_STD_LAST] = {
+struct rgbtriple colors_standard_rgb[COLOR_STD_LAST] = {
   {  0,   0,   0},  /* Black */
   {255, 255, 255},  /* White */
   {255,   0,   0},  /* Red */
Index: client/gui-gtk-2.0/colors.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/colors.h,v
retrieving revision 1.1
diff -u -r1.1 colors.h
--- client/gui-gtk-2.0/colors.h 11 Mar 2002 23:09:43 -0000      1.1
+++ client/gui-gtk-2.0/colors.h 4 Jan 2005 19:15:03 -0000
@@ -17,6 +17,11 @@
 
 #include "colors_g.h"
 
+struct rgbtriple {
+  int r, g, b;
+};
+
+extern struct rgbtriple colors_standard_rgb[COLOR_STD_LAST];
 extern GdkColor *colors_standard[COLOR_STD_LAST];
 
 #endif  /* FC__COLORS_H */
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       4 Jan 2005 19:15:03 -0000
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include <gtk/gtk.h>
+#include <pango/pangoft2.h>
 
 #include "gtkpixcomm.h"
 
@@ -103,6 +104,9 @@
                           int mask_offset_x, int mask_offset_y)
 {
   GdkPixmap *mypixmap, *mymask = NULL;
+  SGL_Image *image;
+
+  image = sgl_image_new(width, height);
 
   mypixmap = gdk_pixmap_new(root_window, width, height, -1);
 
@@ -133,7 +137,11 @@
     }
   }
 
-  return ctor_sprite_mask(mypixmap, mymask, width, height);
+  image = sgl_image_new(width, height);
+
+  sgl_blend_image(image, source->image, x, y, 0, 0, width, height);
+
+  return ctor_sprite_mask(mypixmap, mymask, image, width, height);
 }
 
 /****************************************************************************
@@ -213,7 +221,7 @@
  Create a new sprite with the given pixmap, dimensions, and
  (optional) mask.
 ***************************************************************************/
-SPRITE *ctor_sprite_mask( GdkPixmap *mypixmap, GdkPixmap *mask, 
+SPRITE *ctor_sprite_mask( GdkPixmap *mypixmap, GdkPixmap *mask, SGL_Image 
*image,
                          int width, int height )
 {
     SPRITE *mysprite = fc_malloc(sizeof(SPRITE));
@@ -227,6 +235,8 @@
 
     mysprite->pixbuf   = NULL;
 
+    mysprite->image    = image;
+
     return mysprite;
 }
 
@@ -263,16 +273,17 @@
 ***************************************************************************/
 struct Sprite *load_gfxfile(const char *filename)
 {
-  GdkPixbuf *im;
+  GdkPixbuf *im, *im2;
   SPRITE    *mysprite;
   int       w, h;
+  guchar    *pixels;
 
   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));
+  mysprite = fc_malloc(sizeof(*mysprite));
 
   w = gdk_pixbuf_get_width(im); h = gdk_pixbuf_get_height(im);
   gdk_pixbuf_render_pixmap_and_mask(im, &mysprite->pixmap, &mysprite->mask, 1);
@@ -280,10 +291,11 @@
   mysprite->width     = w;
   mysprite->height    = h;
 
-  mysprite->pixbuf    = NULL;
-  mysprite->fogged = NULL;
-
-  g_object_unref(im);
+  mysprite->pixbuf    = im;
+  im2                = gdk_pixbuf_add_alpha(im, FALSE, 0, 0, 0);
+  pixels              = gdk_pixbuf_get_pixels(im2);
+  mysprite->image     = sgl_image_new_from_data(w, h, (uint32_t *) pixels);
+  mysprite->fogged    = NULL;
 
   return mysprite;
 }
@@ -304,6 +316,9 @@
   if (s->pixbuf) {
     g_object_unref(s->pixbuf);
   }
+  if (s->image) {
+    sgl_image_free(s->image);
+  }
   if (s->fogged) {
     g_object_unref(s->fogged);
   }
@@ -537,3 +552,460 @@
   return sprite->pixbuf;
 }
 
+
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+SGL_Image *sgl_image_new(int w, int h)
+{
+  SGL_Image *image;
+
+  image = fc_malloc(sizeof(*image));
+  image->w = w;
+  image->h = h;
+
+  image->data = fc_calloc(1, 4 * w * h);
+  return image;
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+SGL_Image *sgl_image_new_from_data(int w, int h, uint32_t *data)
+{
+  SGL_Image *image;
+  size_t size;
+
+  image = fc_malloc(sizeof(*image));
+  image->w = w;
+  image->h = h;
+
+  size = 4 * w * h;
+
+  image->data = fc_malloc(size);
+  memcpy(image->data, data, size);
+  return image;
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+void sgl_image_free(SGL_Image *img)
+{
+  if (img->data) {
+    free(img->data);
+  }
+
+  free(img);
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+#define RGBA_FROM_PIXEL(pixel, r, g, b, a)                               \
+{                                                                        \
+  b = ((pixel >> 16) & 0xff);                                            \
+  g = ((pixel >> 8) & 0xff);                                             \
+  r = (pixel & 0xff);                                                    \
+  a = (pixel >> 24);                                                     \
+}
+
+#define DISEMBLE_RGBA(buf, r, g, b, a)                                   \
+  do {                                                                   \
+    uint32_t pixel;                                                      \
+    pixel = *((uint32_t *)(buf));                                        \
+    RGBA_FROM_PIXEL(pixel, r, g, b, a);                                  \
+  } while(0)
+
+#define PIXEL_FROM_RGBA(pixel, r, g, b, a)                               \
+{                                                                        \
+  pixel = (a << 24) | (b << 16) | (g << 8) | r;                          \
+}
+
+#define ASSEMBLE_RGBA(buf, r, g, b, a)                                  \
+{                                                                       \
+  uint32_t pixel;                                                       \
+                                                                        \
+  PIXEL_FROM_RGBA(pixel, r, g, b, a);                                   \
+  *((uint32_t *)(buf)) = pixel;                                         \
+}
+
+/* Blend the RGB values of two pixels based on a source alpha value */
+#define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB)                           \
+  do {                                                                   \
+    dR = (((sR-dR)*(A))>>8)+dR;                                          \
+    dG = (((sG-dG)*(A))>>8)+dG;                                          \
+    dB = (((sB-dB)*(A))>>8)+dB;                                          \
+  } while(0)
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+uint32_t sgl_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+  uint32_t color;
+
+  PIXEL_FROM_RGBA(color, r, g, b, a);
+  return color;
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+void sgl_blend_rectangle(SGL_Image *dst, int xdst, int ydst,
+                        int width, int height, uint32_t color)
+{
+  int w, h;
+  int maxw, maxh;
+
+  w = width;
+  h = height;
+
+  /* clip the destination rectangle against the destination surface */
+  if (xdst < 0) {
+    w += xdst;
+    xdst = 0;
+  }
+  maxw = dst->w - xdst;
+  if (maxw < w)
+    w = maxw;
+
+  if (ydst < 0) {
+    h += ydst;
+    ydst = 0;
+  }
+  maxh = dst->h - ydst;
+  if (maxh < h)
+    h = maxh;
+
+  if (w > 0 && h > 0) {
+    uint32_t *dstp;
+    int dstskip;
+
+    uint32_t sR, sG, sB, sA;
+
+    DISEMBLE_RGBA(&color, sR, sG, sB, sA);
+
+    dstp = dst->data + ydst * dst->w + xdst;
+    dstskip = dst->w - w;
+
+    if (sA) {
+      if (sA == 255) {
+       do {
+         int n = w;
+
+         do {
+           *dstp++ = color;
+         } while (--n);
+         dstp += dstskip;
+       } while (--h);
+      } else {
+       do {
+         int n = w;
+
+         do {
+           uint32_t dR, dG, dB, dA;
+
+           DISEMBLE_RGBA(dstp, dR, dG, dB, dA);
+           ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
+           ASSEMBLE_RGBA(dstp, dR, dG, dB, dA);
+           ++dstp;
+         } while (--n);
+         dstp += dstskip;
+       } while (--h);
+      }
+    }
+  }
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+void sgl_clear(SGL_Image *dst, uint32_t color)
+{
+  int w, h;
+
+  w = dst->w;
+  h = dst->h;
+
+  if (w > 0 && h > 0) {
+    uint32_t *dstp;
+
+    dstp = dst->data;
+
+    do {
+      int n = w;
+
+      do {
+       *dstp++ = color;
+      } while (--n);
+    } while (--h);
+  }
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+void sgl_blend_image(SGL_Image *dst, SGL_Image *src,
+                    int xsrc, int ysrc, int xdst, int ydst,
+                    int width, int height)
+{
+  int w, h;
+  int maxw, maxh;
+
+  w = (width == -1) ? src->w : width;
+  h = (height == -1) ? src->h : height;
+
+  /* clip the source rectangle to the source surface */
+  if (xsrc < 0) {
+    w += xsrc;
+    xdst -= xsrc;
+    xsrc = 0;
+  }
+  maxw = src->w - xsrc;
+  if (maxw < w)
+    w = maxw;
+
+  if (ysrc < 0) {
+    h += ysrc;
+    ydst -= ysrc;
+    ysrc = 0;
+  }
+  maxh = src->h - ysrc;
+  if (maxh < h)
+    h = maxh;
+
+  /* clip the destination rectangle against the destination surface */
+  if (xdst < 0) {
+    w += xdst;
+    xsrc -= xdst;
+    xdst = 0;
+  }
+  maxw = dst->w - xdst;
+  if (maxw < w)
+    w = maxw;
+
+  if (ydst < 0) {
+    h += ydst;
+    ysrc -= ydst;
+    ydst = 0;
+  }
+  maxh = dst->h - ydst;
+  if (maxh < h)
+    h = maxh;
+
+  /* if there is something to draw, do it */
+  if (w > 0 && h > 0) {
+    uint32_t *srcp, *dstp;
+    int srcskip, dstskip;
+
+    srcp = src->data + ysrc * src->w + xsrc;
+    dstp = dst->data + ydst * dst->w + xdst;
+
+    srcskip = src->w - w;
+    dstskip = dst->w - w;
+
+    do {
+      int n = w;
+
+      do {
+       uint32_t sR, sG, sB, sA;
+
+       DISEMBLE_RGBA(srcp, sR, sG, sB, sA);
+
+       if (sA) {
+         if (sA == 255) {
+           *dstp = *srcp;
+         } else {
+           uint32_t dR, dG, dB, dA;
+
+           DISEMBLE_RGBA(dstp, dR, dG, dB, dA);
+           ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
+           ASSEMBLE_RGBA(dstp, dR, dG, dB, dA);
+         }
+       }
+       ++srcp;
+       ++dstp;
+      } while (--n);
+      srcp += srcskip;
+      dstp += dstskip;
+    } while (--h);
+  }
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+void sgl_blend_darken(SGL_Image *dst, SGL_Image *src,
+                     int xsrc, int ysrc, int xdst, int ydst,
+                     int width, int height)
+{
+  int w, h;
+  int maxw, maxh;
+
+  w = (width == -1) ? src->w : width;
+  h = (height == -1) ? src->h : height;
+
+  /* clip the source rectangle to the source surface */
+  if (xsrc < 0) {
+    w += xsrc;
+    xdst -= xsrc;
+    xsrc = 0;
+  }
+  maxw = src->w - xsrc;
+  if (maxw < w)
+    w = maxw;
+
+  if (ysrc < 0) {
+    h += ysrc;
+    ydst -= ysrc;
+    ysrc = 0;
+  }
+  maxh = src->h - ysrc;
+  if (maxh < h)
+    h = maxh;
+
+  /* clip the destination rectangle against the destination surface */
+  if (xdst < 0) {
+    w += xdst;
+    xsrc -= xdst;
+    xdst = 0;
+  }
+  maxw = dst->w - xdst;
+  if (maxw < w)
+    w = maxw;
+
+  if (ydst < 0) {
+    h += ydst;
+    ysrc -= ydst;
+    ydst = 0;
+  }
+  maxh = dst->h - ydst;
+  if (maxh < h)
+    h = maxh;
+
+  /* if there is something to draw, do it */
+  if (w > 0 && h > 0) {
+    uint32_t *srcp, *dstp;
+    int srcskip, dstskip;
+
+    srcp = src->data + ysrc * src->w + xsrc;
+    dstp = dst->data + ydst * dst->w + xdst;
+
+    srcskip = src->w - w;
+    dstskip = dst->w - w;
+
+    do {
+      int n = w;
+
+      do {
+       uint32_t sR, sG, sB, sA;
+
+       DISEMBLE_RGBA(srcp, sR, sG, sB, sA);
+       sR /= 2; sG /= 2; sB /= 2;
+
+       if (sA) {
+         if (sA == 255) {
+           ASSEMBLE_RGBA(dstp, sR, sG, sB, sA);
+         } else {
+           uint32_t dR, dG, dB, dA;
+
+           DISEMBLE_RGBA(dstp, dR, dG, dB, dA);
+           ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
+           ASSEMBLE_RGBA(dstp, dR, dG, dB, dA);
+         }
+       }
+       ++srcp;
+       ++dstp;
+      } while (--n);
+      srcp += srcskip;
+      dstp += dstskip;
+    } while (--h);
+  }
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+GdkPixbuf *pixbuf_new_from_image(SGL_Image *img)
+{
+  return
+    gdk_pixbuf_new_from_data((uint8_t *)img->data,
+       GDK_COLORSPACE_RGB, TRUE, 8,
+       img->w, img->h, 4 * img->w, NULL, NULL);
+}
+
+/*****************************************************************************
+ ...
+******************************************************************************/
+SGL_Image *sgl_render_layout(PangoLayout *layout)
+{
+  PangoRectangle rect;
+  FT_Bitmap bitmap;
+  SGL_Image *img;
+  uint8_t *srcp;
+  uint32_t *dstp;
+  int w, h, y, x;
+
+  pango_layout_get_pixel_extents(layout, NULL, &rect);
+  w = rect.width;
+  h = rect.height;
+
+  bitmap.width = w;
+  bitmap.rows = h;
+
+  img = sgl_image_new(w+1, h+1);
+
+  if (rect.width == 0 || rect.height == 0) {
+    return img;
+  }
+
+  bitmap.pitch = w;
+  bitmap.buffer = fc_calloc(1, w * h);
+  bitmap.num_grays = 256;
+  bitmap.pixel_mode = ft_pixel_mode_grays;
+
+  pango_ft2_render_layout(&bitmap, layout, 0, 0);
+
+  dstp = img->data + w + 1;
+  srcp = bitmap.buffer;
+
+  x = w;
+  y = h;
+
+  do {
+    int n = x;
+
+  dstp++;
+    do {
+      *dstp++ = sgl_color_rgba(0, 0, 0, *srcp++);
+    } while (--n);
+  } while (--y);
+
+  dstp = img->data;
+  srcp = bitmap.buffer;
+
+  x = w;
+  y = h;
+
+  do {
+    int n = x;
+
+    do {
+      uint32_t dR, dG, dB, dA, sA;
+
+      sA = *srcp++;
+
+      DISEMBLE_RGBA(dstp, dR, dG, dB, dA);
+      ALPHA_BLEND(255, 255, 255, sA, dR, dG, dB);
+      ASSEMBLE_RGBA(dstp, dR, dG, dB, MAX(sA, dA));
+      dstp++;
+    } while (--n);
+    dstp++;
+  } while (--y);
+
+  free(bitmap.buffer);
+  return img;
+}
+
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       4 Jan 2005 19:15:03 -0000
@@ -14,10 +14,17 @@
 #define FC__GRAPHICS_H
 
 #include <gtk/gtk.h>
+#include <stdint.h>
 
 #include "graphics_g.h"
 #include "mapview_common.h"
 
+typedef struct {
+  int w;
+  int h;
+  uint32_t *data;
+} SGL_Image;
+
 struct Sprite
 {
   GdkPixmap *pixmap;
@@ -27,6 +34,7 @@
   int       height;
 
   GdkPixbuf *pixbuf;
+  SGL_Image *image;
 };
 
 typedef struct Sprite SPRITE;
@@ -45,7 +53,7 @@
                              GdkGC *white_gc,
                              gint x, gint y, PangoLayout *layout);
 
-SPRITE *ctor_sprite_mask(GdkPixmap *mypixmap, GdkPixmap *mask,
+SPRITE *ctor_sprite_mask(GdkPixmap *mypixmap, GdkPixmap *mask, SGL_Image 
*image,
                         int width, int height);
 SPRITE* sprite_scale(SPRITE *src, int new_w, int new_h);
 void sprite_get_bounding_box(SPRITE * sprite, int *start_x,
@@ -60,5 +68,21 @@
  ********************************************************************/
 GdkPixbuf *sprite_get_pixbuf(SPRITE *sprite);
 
+SGL_Image *sgl_image_new(int w, int h);
+SGL_Image *sgl_image_new_from_data(int w, int h, uint32_t *data);
+void sgl_image_free(SGL_Image *img);
+uint32_t sgl_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+void sgl_blend_rectangle(SGL_Image *dst, int xdst, int ydst,
+                        int width, int height, uint32_t color);
+void sgl_clear(SGL_Image *dst, uint32_t color);
+void sgl_blend_image(SGL_Image *dst, SGL_Image *src,
+                    int xsrc, int ysrc, int xdst, int ydst,
+                    int width, int height);
+void sgl_blend_darken(SGL_Image *dst, SGL_Image *src,
+                     int xsrc, int ysrc, int xdst, int ydst,
+                     int width, int height);
+GdkPixbuf *pixbuf_new_from_image(SGL_Image *img);
+SGL_Image *sgl_render_layout(PangoLayout *layout);
+
 #endif  /* FC__GRAPHICS_H */
 
Index: client/gui-gtk-2.0/gui_main.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.h,v
retrieving revision 1.19
diff -u -r1.19 gui_main.h
--- client/gui-gtk-2.0/gui_main.h       25 Dec 2004 19:50:29 -0000      1.19
+++ client/gui-gtk-2.0/gui_main.h       4 Jan 2005 19:15:03 -0000
@@ -21,7 +21,8 @@
 enum canvas_type {
   CANVAS_PIXMAP,
   CANVAS_PIXCOMM,
-  CANVAS_PIXBUF
+  CANVAS_PIXBUF,
+  CANVAS_IMAGE
 };
 
 struct canvas
@@ -32,6 +33,7 @@
     GdkPixmap *pixmap;
     GtkPixcomm *pixcomm;
     GdkPixbuf *pixbuf;
+    SGL_Image *image;
   } v;
 };
 
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.152
diff -u -r1.152 mapview.c
--- client/gui-gtk-2.0/mapview.c        28 Dec 2004 23:01:51 -0000      1.152
+++ client/gui-gtk-2.0/mapview.c        4 Jan 2005 19:15:03 -0000
@@ -23,6 +23,7 @@
 #endif
 
 #include <gtk/gtk.h>
+#include <pango/pangoft2.h>
 
 #include "fcintl.h"
 #include "log.h"
@@ -55,15 +56,6 @@
 
 #define map_canvas_store (mapview_canvas.store->v.pixmap)
 
-static void pixmap_put_overlay_tile(GdkDrawable *pixmap,
-                                   int canvas_x, int canvas_y,
-                                   struct Sprite *ssprite);
-
-static void pixmap_put_overlay_tile_draw(GdkDrawable *pixmap,
-                                        int canvas_x, int canvas_y,
-                                        struct Sprite *ssprite,
-                                        bool fog);
-
 static GtkObject *map_hadj, *map_vadj;
 
 
@@ -269,8 +261,8 @@
 {
   struct canvas *result = fc_malloc(sizeof(*result));
 
-  result->type = CANVAS_PIXMAP;
-  result->v.pixmap = gdk_pixmap_new(root_window, width, height, -1);
+  result->type = CANVAS_IMAGE;
+  result->v.image = sgl_image_new(width, height);
   return result;
 }
 
@@ -279,8 +271,8 @@
 **************************************************************************/
 void canvas_free(struct canvas *store)
 {
-  if (store->type == CANVAS_PIXMAP) {
-    g_object_unref(store->v.pixmap);
+  if (store->type == CANVAS_IMAGE) {
+    sgl_image_free(store->v.image);
   }
   free(store);
 }
@@ -303,12 +295,6 @@
 gboolean overview_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer 
data)
 {
   if (!can_client_change_view()) {
-    if (radar_gfx_sprite) {
-      gdk_draw_drawable(overview_canvas->window, civ_gc,
-                       radar_gfx_sprite->pixmap, ev->area.x, ev->area.y,
-                       ev->area.x, ev->area.y,
-                       ev->area.width, ev->area.height);
-    }
     return TRUE;
   }
   
@@ -322,10 +308,18 @@
 static bool map_center = TRUE;
 static bool map_configure = FALSE;
 
+static GdkPixbuf *map_pixbuf;
+
 gboolean map_canvas_configure(GtkWidget * w, GdkEventConfigure * ev,
                              gpointer data)
 {
   if (map_canvas_resized(ev->width, ev->height)) {
+
+    if (map_pixbuf) {
+      g_object_unref(map_pixbuf);
+    }
+    map_pixbuf = pixbuf_new_from_image(mapview_canvas.store->v.image);
+
     map_configure = TRUE;
   }
 
@@ -349,9 +343,7 @@
   else
   {
     if (map_exists()) { /* do we have a map at all */
-      gdk_draw_drawable(map_canvas->window, civ_gc, map_canvas_store,
-                       ev->area.x, ev->area.y, ev->area.x, ev->area.y,
-                       ev->area.width, ev->area.height);
+      flush_mapcanvas(ev->area.x, ev->area.y, ev->area.width, ev->area.height);
       cleared = FALSE;
     } else {
       if (!cleared) {
@@ -378,9 +370,11 @@
 void flush_mapcanvas(int canvas_x, int canvas_y,
                     int pixel_width, int pixel_height)
 {
-  gdk_draw_drawable(map_canvas->window, civ_gc, map_canvas_store,
-                   canvas_x, canvas_y, canvas_x, canvas_y,
-                   pixel_width, pixel_height);
+  if (map_pixbuf) {
+    gdk_pixbuf_render_to_drawable(map_pixbuf, map_canvas->window, civ_gc,
+       canvas_x, canvas_y, canvas_x, canvas_y,
+       pixel_width, pixel_height, GDK_RGB_DITHER_NORMAL, 0, 0);
+  }
 }
 
 #define MAX_DIRTY_RECTS 20
@@ -500,15 +494,18 @@
 void show_city_desc(struct canvas *pcanvas, int canvas_x, int canvas_y,
                    struct city *pcity, int *width, int *height)
 {
-  if (pcanvas->type == CANVAS_PIXMAP) {
   static char buffer[512], buffer2[32];
   PangoRectangle rect, rect2;
   enum color_std color;
   int extra_width = 0;
   static PangoLayout *layout;
+  SGL_Image *img;
 
   if (!layout) {
-    layout = pango_layout_new(gdk_pango_context_get());
+    PangoContext *context;
+
+    context = pango_ft2_get_context(72.0, 72.0);
+    layout = pango_layout_new(context);
   }
 
   *width = *height = 0;
@@ -545,24 +542,32 @@
       rect2.width = 0;
     }
 
-    gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                            toplevel->style->black_gc,
-                            toplevel->style->white_gc,
-                            canvas_x - (rect.width + rect2.width) / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
+    if (pcanvas->type == CANVAS_IMAGE) {
+      img = sgl_render_layout(layout);
+      sgl_blend_image(pcanvas->v.image, img,
+         0, 0,
+         canvas_x - (rect.width + rect2.width) / 2,
+         canvas_y + PANGO_ASCENT(rect),
+         -1, -1);
+      sgl_image_free(img);
+    }
 
     if (draw_city_growth && pcity->owner == game.player_idx) {
       pango_layout_set_font_description(layout, city_productions_font);
       pango_layout_set_text(layout, buffer2, -1);
       gdk_gc_set_foreground(civ_gc, colors_standard[color]);
-      gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                              toplevel->style->black_gc,
-                              civ_gc,
-                              canvas_x - (rect.width + rect2.width) / 2
-                              + rect.width,
-                              canvas_y + PANGO_ASCENT(rect)
-                              + rect.height / 2 - rect2.height / 2,
-                              layout);
+
+      if (pcanvas->type == CANVAS_IMAGE) {
+       img = sgl_render_layout(layout);
+       sgl_blend_image(pcanvas->v.image, img,
+           0, 0,
+           canvas_x - (rect.width + rect2.width) / 2
+           + rect.width,
+           canvas_y + PANGO_ASCENT(rect)
+           + rect.height / 2 - rect2.height / 2,
+           -1, -1);
+       sgl_image_free(img);
+      }
     }
 
     canvas_y += rect.height + 3;
@@ -578,16 +583,20 @@
     pango_layout_set_text(layout, buffer, -1);
 
     pango_layout_get_pixel_extents(layout, &rect, NULL);
-    gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                            toplevel->style->black_gc,
-                            toplevel->style->white_gc,
-                            canvas_x - rect.width / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
+
+    if (pcanvas->type == CANVAS_IMAGE) {
+      img = sgl_render_layout(layout);
+      sgl_blend_image(pcanvas->v.image, img,
+         0, 0,
+         canvas_x - rect.width / 2,
+         canvas_y + PANGO_ASCENT(rect),
+         -1, -1);
+      sgl_image_free(img);
+    }
 
     *width = MAX(*width, rect.width);
     *height += rect.height;
   }
-  }
 }
 
 /**************************************************************************
@@ -630,50 +639,6 @@
 }
 
 /**************************************************************************
-...
-**************************************************************************/
-static void pixmap_put_overlay_tile(GdkDrawable *pixmap,
-                                   int canvas_x, int canvas_y,
-                                   struct Sprite *ssprite)
-{
-  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,
-                   0, 0,
-                   canvas_x, canvas_y,
-                   ssprite->width, ssprite->height);
-  gdk_gc_set_clip_mask(civ_gc, NULL);
-}
-
-/**************************************************************************
-  Place part of a (possibly masked) sprite on a pixmap.
-**************************************************************************/
-static void pixmap_put_sprite(GdkDrawable *pixmap,
-                             int pixmap_x, int pixmap_y,
-                             struct Sprite *ssprite,
-                             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);
-  }
-
-  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);
-}
-
-/**************************************************************************
   Draw some or all of a sprite onto the mapview or citydialog canvas.
 **************************************************************************/
 void canvas_put_sprite(struct canvas *pcanvas,
@@ -682,38 +647,9 @@
                       int offset_x, int offset_y, int width, int height)
 {
   switch (pcanvas->type) {
-    case CANVAS_PIXMAP:
-      pixmap_put_sprite(pcanvas->v.pixmap, canvas_x, canvas_y,
-         sprite, offset_x, offset_y, width, height);
-      break;
-    case CANVAS_PIXCOMM:
-      gtk_pixcomm_copyto(pcanvas->v.pixcomm, sprite, canvas_x, canvas_y);
-      break;
-    case CANVAS_PIXBUF:
-      {
-       GdkPixbuf *src, *dst;
-
-       /* FIXME: is this right??? */
-       if (canvas_x < 0) {
-         offset_x -= canvas_x;
-         canvas_x = 0;
-       }
-       if (canvas_y < 0) {
-         offset_y -= canvas_y;
-         canvas_y = 0;
-       }
-
-
-       src = sprite_get_pixbuf(sprite);
-       dst = pcanvas->v.pixbuf;
-       gdk_pixbuf_composite(src, dst, canvas_x, canvas_y,
-           MIN(width,
-             MIN(gdk_pixbuf_get_width(dst), gdk_pixbuf_get_width(src))),
-           MIN(height,
-             MIN(gdk_pixbuf_get_height(dst), gdk_pixbuf_get_height(src))),
-           canvas_x - offset_x, canvas_y - offset_y,
-           1.0, 1.0, GDK_INTERP_NEAREST, 255);
-      }
+    case CANVAS_IMAGE:
+      sgl_blend_image(pcanvas->v.image, sprite->image,
+         offset_x, offset_y, canvas_x, canvas_y, width, height);
       break;
     default:
       break;
@@ -740,9 +676,14 @@
                              struct Sprite *psprite,
                              bool fog, int fog_x, int fog_y)
 {
-  if (pcanvas->type == CANVAS_PIXMAP) {
-    pixmap_put_overlay_tile_draw(pcanvas->v.pixmap, canvas_x, canvas_y,
-                                psprite, fog);
+  if (pcanvas->type == CANVAS_IMAGE) {
+    if (fog) {
+      sgl_blend_darken(pcanvas->v.image, psprite->image,
+         0, 0, canvas_x, canvas_y, psprite->width, psprite->height);
+    } else {
+      sgl_blend_image(pcanvas->v.image, psprite->image,
+         0, 0, canvas_x, canvas_y, psprite->width, psprite->height);
+    }
   }
 }
 
@@ -754,6 +695,7 @@
                          int canvas_x, int canvas_y, int width, int height)
 {
   GdkColor *col = colors_standard[color];
+  struct rgbtriple *pcol = &colors_standard_rgb[color];
 
   switch (pcanvas->type) {
     case CANVAS_PIXMAP:
@@ -769,6 +711,11 @@
          ((guint32)(col->red & 0xff00) << 16)
          | ((col->green & 0xff00) << 8) | (col->blue & 0xff00) | 0xff);
       break;
+    case CANVAS_IMAGE:
+      sgl_blend_rectangle(pcanvas->v.image,
+         canvas_x, canvas_y, width, height,
+         sgl_color_rgba(pcol->r, pcol->g, pcol->b, 255));
+      break;
     default:
       break;
   }
@@ -856,110 +803,11 @@
       gdk_draw_drawable(dest->v.pixmap, fill_bg_gc, src->v.pixmap,
                        src_x, src_y, dest_x, dest_y, width, height);
     }
-  }
-}
-
-/**************************************************************************
-  Created a fogged version of the sprite.  This can fail on older systems
-  in which case the callers needs a fallback.
-**************************************************************************/
-static void fog_sprite(struct Sprite *sprite)
-{
-  int x, y;
-  GdkImage* ftile;
-
-  if (gdk_drawable_get_visual(sprite->pixmap)->type
-      != GDK_VISUAL_TRUE_COLOR) {
-    /* In this case the below code won't work. */
-    return;
-  }
-
-  ftile = gdk_drawable_get_image(sprite->pixmap,
-                                0, 0, sprite->width, sprite->height);
-
-  /* Iterate over all pixels, reducing brightness by 50%. */
-  for (x = 0; x < sprite->width; x++) {
-    for (y = 0; y < sprite->height; y++) {
-      guint32 pixel =  gdk_image_get_pixel(ftile, x, y);
-
-      guint8 red = ((pixel & ftile->visual->red_mask)
-                   >> ftile->visual->red_shift) / 2;
-      guint8 green = ((pixel & ftile->visual->green_mask)
-                     >> ftile->visual->green_shift) / 2;
-      guint8 blue = ((pixel & ftile->visual->blue_mask)
-                    >> ftile->visual->blue_shift) / 2;
-      guint32 result = red << ftile->visual->red_shift
-       | green << ftile->visual->green_shift          
-       | blue << ftile->visual->blue_shift;
-
-      gdk_image_put_pixel(ftile, x , y, result);
-    }
-  }
-
-  /* Convert the image back to a pixmap, since pixmaps are much faster
-   * to draw. */
-  sprite->fogged = gdk_pixmap_new(root_window,
-                                 sprite->width, sprite->height, -1);
-  gdk_gc_set_clip_origin(fill_tile_gc, 0, 0);
-  gdk_gc_set_clip_mask(fill_tile_gc, sprite->mask);
-  gdk_draw_image(sprite->fogged, fill_tile_gc, ftile,
-                0, 0, 0, 0, sprite->width, sprite->height);
-  gdk_gc_set_clip_mask(fill_tile_gc, NULL);
-  g_object_unref(ftile);
-}
-
-/**************************************************************************
-Only used for isometric view.
-**************************************************************************/
-static void pixmap_put_overlay_tile_draw(GdkDrawable *pixmap,
-                                        int canvas_x, int canvas_y,
-                                        struct Sprite *ssprite,
-                                        bool fog)
-{
-  if (!ssprite) {
-    return;
-  }
-
-  if (fog && better_fog && !ssprite->fogged) {
-    fog_sprite(ssprite);
-    if (!ssprite->fogged) {
-      freelog(LOG_NORMAL,
-             _("Better fog will only work in truecolor.  Disabling it"));
-      better_fog = FALSE;
+    if (src->type == CANVAS_IMAGE) {
+      sgl_blend_image(dest->v.image, src->v.image,
+         src_x, src_y, dest_x, dest_y, width, height);
     }
   }
-
-  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);
-
-    return;
-  }
-
-  pixmap_put_sprite(pixmap, canvas_x, canvas_y, ssprite,
-                   0, 0, ssprite->width, ssprite->height);
-
-  /* I imagine this could be done more efficiently. Some pixels We first
-     draw from the sprite, and then draw black afterwards. It would be much
-     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_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);
-
-    gdk_draw_rectangle(pixmap, fill_tile_gc, TRUE,
-                      canvas_x, canvas_y, ssprite->width, ssprite->height);
-    gdk_gc_set_clip_mask(fill_tile_gc, NULL);
-  }
 }
 
 /**************************************************************************
@@ -970,9 +818,11 @@
   int canvas_x, canvas_y;
 
   if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
+/*
     pixmap_put_overlay_tile(map_canvas->window,
                            canvas_x, canvas_y,
                            sprites.user.attention);
+*/
   }
 }
 
@@ -1110,3 +960,4 @@
   reset_unit_table();
   blank_max_unit_size();
 }
+
Index: data/freeciv.rc-2.0
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/freeciv.rc-2.0,v
retrieving revision 1.22
diff -u -r1.22 freeciv.rc-2.0
--- data/freeciv.rc-2.0 29 Dec 2004 17:34:19 -0000      1.22
+++ data/freeciv.rc-2.0 4 Jan 2005 19:15:03 -0000
@@ -65,12 +65,12 @@
 
 style "city_names_font"
 {
-  font_name = "Sans Bold 10"
+  font_name = "Sans Bold 11"
 }
 
 style "city_productions_font"
 {
-  font_name = "Serif 10"
+  font_name = "Serif 11"
 }
 
 style "tooltips"

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