[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"
- [Freeciv-Dev] (PR#11791) SGL software 2D drawing,
Vasco Alexandre da Silva Costa <=
|
|