You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spOSMroute/gtk/gtk_gfx.c

185 lines
5.6 KiB

/***************************************************************************
* 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);
};