/*************************************************************************** * gtk_gfx.c * * Copyright 2010 Steffen Pohle * steffen@gulpe.de ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "map.h" #include "gtk_port.h" #include "memoryleak.h" #include "system.h" iPoint gfx_screensize; struct image *gfx_doublebuffer = NULL; /************************************************************************ * functions for starting and finishing the drawing process */ void gfx_flip () { gc = gdk_gc_new (map_da->window); gdk_gc_get_values (gc, &gcvalues); gdk_draw_drawable (map_da->window, gc, gfx_doublebuffer->pixmap, 0, 0, 0, 0, gfx_screensize.x, gfx_screensize.y); gdk_gc_unref (gc); }; void gfx_resize (int width, int height) { if (width != gfx_screensize.x || height != gfx_screensize.y) { if (height == 0) height = 1; if (width == 0) width = 1; gfx_screensize.x = width; gfx_screensize.y = height; if (gfx_doublebuffer) gfx_img_free (gfx_doublebuffer); gfx_doublebuffer = gfx_img_alloc (width, height); } }; int gfx_color_alloc (struct color *c, unsigned short int r, unsigned short int g, unsigned short int b) { c->r = r; c->b = b; c->g = g; if (c->alloc && colormap != NULL) { gdk_colormap_free_colors (colormap, &c->c, 1); c->alloc = 0; } if (colormap != NULL) { c->alloc = 1; c->c.red = r; c->c.blue = b; c->c.green = g; gdk_colormap_alloc_color (colormap, &c->c, TRUE, TRUE); } else c->alloc = 0; return 1; }; /*************************************************************************** * img functions */ struct image *gfx_img_alloc (int w, int h) { struct image *img = (struct image*) ml_malloc (sizeof (struct image)); d_printf ("img_gfx_alloc: %d,%d", w, h); img->pixmap = gdk_pixmap_new (map_da->window, w, h, -1); img->gc = gdk_gc_new (img->pixmap); img->width = w; img->height = h; return img; }; void gfx_img_free (struct image *img) { gdk_gc_unref (img->gc); g_object_unref (img->pixmap); ml_free (img); }; void gfx_clear (struct image *img, struct color *c) { if (img == NULL) img = gfx_doublebuffer; gdk_gc_set_foreground (img->gc,&c->c); gdk_draw_rectangle (img->pixmap, img->gc, TRUE, 0, 0, img->width, img->height); }; void gfx_draw_img (struct image *dimg, int dx, int dy, int dw, int dh, struct image *simg, int sx, int sy) { if (dimg == NULL) dimg = gfx_doublebuffer; if (simg == NULL || simg->pixmap == NULL || dimg == NULL || dimg->pixmap == NULL) { d_printf ("WARN: gfx_img_draw_img drawing on NULL or from NULL image"); d_print_backtrace (); return; } /* check for boundrys, do clipping */ if (sx + dw > simg->width) dw = simg->width - sx; if (dx + dw > dimg->width) dw = dimg->width - dx; if (sy + dh > simg->height) dh = simg->height - sy; if (dh + dh > gfx_screensize.y) dh = dimg->height - dy; if (dw <= 0 || dh <= 0) return; /* draw the pixmap onto the screen */ gdk_draw_drawable (dimg->pixmap, dimg->gc, simg->pixmap, sx, sy, dx, dy, dw, dh); }; void gfx_draw_line (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) { if (dimg == NULL) dimg = gfx_doublebuffer; gdk_gc_set_foreground (dimg->gc,&style.c.c); gdk_gc_set_line_attributes (dimg->gc, style.width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); gdk_draw_line(dimg->pixmap, dimg->gc, x1, y1, x2, y2); }; void gfx_draw_text (struct image *dimg, int x, int y, char *text, struct color *c) { if (dimg == NULL) dimg = gfx_doublebuffer; PangoLayout *layout = gtk_widget_create_pango_layout(map_da, NULL); pango_layout_set_text(layout, text, -1); gdk_gc_set_foreground (dimg->gc, &color[COLOR_white][2].c); gdk_draw_layout(dimg->pixmap, dimg->gc, x-1, y-1, layout); gdk_draw_layout(dimg->pixmap, dimg->gc, x-1, y+1, layout); gdk_draw_layout(dimg->pixmap, dimg->gc, x+1, y-1, layout); gdk_draw_layout(dimg->pixmap, dimg->gc, x+1, y+1, layout); gdk_gc_set_foreground (dimg->gc, &c->c); gdk_draw_layout(dimg->pixmap, dimg->gc, x, y, layout); g_object_unref(layout); }; void gfx_draw_polygon (struct image *dimg, iPoint *p, int pcnt, struct line_style style, struct color c) { static GdkPoint *polygon = NULL; static int polygon_cnt = 0; int i; if (dimg == NULL) dimg = gfx_doublebuffer; if (polygon_cnt < pcnt) { polygon_cnt = pcnt; if (polygon != NULL) polygon = (GdkPoint *) ml_realloc (polygon, sizeof (GdkPoint) * polygon_cnt); else polygon = (GdkPoint *) ml_malloc (sizeof (GdkPoint) * polygon_cnt); } for (i = 0; i < pcnt; i++) { polygon[i].x = p[i].x; polygon[i].y = p[i].y; } gdk_gc_set_foreground (dimg->gc, &c.c); gdk_draw_polygon (dimg->pixmap, dimg->gc, TRUE, polygon, pcnt); }; void gfx_draw_rect (struct image *dimg, int x1, int y1, int x2, int y2, struct color *c) { if (dimg == NULL) dimg = gfx_doublebuffer; gdk_gc_set_foreground (dimg->gc, &c->c); gdk_draw_rectangle (dimg->pixmap, dimg->gc, TRUE, x1, y1, x2-x1, y2-y1); };