Add:graphics_sdl:Added graphics_sdl code from rphlx
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 15 Jun 2008 20:11:01 +0000 (20:11 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 15 Jun 2008 20:11:01 +0000 (20:11 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@1121 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/configure.in
navit/navit/graphics/Makefile.am
navit/navit/graphics/sdl/Makefile.am [new file with mode: 0644]
navit/navit/graphics/sdl/graphics_sdl.c [new file with mode: 0644]
navit/navit/gui/internal/gui_internal.c
navit/navit/route.c

index 167a248..50e5ba6 100644 (file)
@@ -13,6 +13,8 @@ AC_PROG_CC
 if eval "test x$GCC = xyes"; then
         CFLAGS="$CFLAGS -Wall -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith -Wreturn-type -D_GNU_SOURCE"
 fi
+AM_PROG_CC_C_O
+
 AC_PROG_CXX
 if eval "test x$GXX = xyes"; then
         CXXFLAGS="$CXXFLAGS -Wall -Wcast-align -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith -Wreturn-type -D_GNU_SOURCE"
@@ -120,6 +122,39 @@ if test "x${enable_graphics_qt_qpainter}" = "xyes" ; then
 fi
 AM_CONDITIONAL(USE_GRAPHICS_QT_QPAINTER, test "x${enable_graphics_qt_qpainter}" = "xyes")
 
+AC_ARG_ENABLE(graphics-sdl, [  --disable-graphics-sdl             don't create graphics sdl], enable_graphics_sdl=$enableval, enable_graphics_sdl=yes)
+if test "x${enable_graphics_sdl}" = "xyes" ; then
+       if test -z "$SDL_CONFIG"; then
+            AC_PATH_PROG([SDL_CONFIG], [sdl-config], [])
+        fi
+fi
+if test "x${enable_graphics_sdl}" = "xyes" ; then
+        AC_MSG_CHECKING([for SDL libraries with $SDL_CONFIG])
+       if test ! -x "$SDL_CONFIG"; then
+           enable_graphics_sdl = "no"
+            AC_MSG_RESULT([no])
+       else
+           SDL_CFLAGS="`$SDL_CONFIG --cflags`"
+           SDL_LIBS="`$SDL_CONFIG --libs`"
+           AC_SUBST(SDL_CFLAGS)
+           AC_SUBST(SDL_LIBS)
+            AC_MSG_RESULT([yes])
+               fi 
+fi
+if test "x${enable_graphics_sdl}" = "xyes" ; then
+       save_CPPFLAGS=$CPPFLAGS
+       CPPFLAGS="$($SDL_CONFIG --cflags) $CPPFLAGS"
+       AC_CHECK_HEADER(SDL_image.h,SDL_IMAGE_LIBS=-lSDL_image,enable_graphics_sdl=no)
+       AC_CHECK_HEADER(SDL_gfxPrimitives.h,SDL_GFX_LIBS=-lSDL_gfx,enable_graphics_sdl=no)
+       AC_SUBST(SDL_IMAGE_LIBS)
+       AC_SUBST(SDL_GFX_LIBS)
+       CPPFLAGS=$save_CPPFLAGS
+fi
+if test "x${enable_graphics_sdl}" = "xyes" ; then
+       AC_DEFINE(USE_GRAPICS_SDL, 1, [Build with graphics sdl])
+fi
+AM_CONDITIONAL(USE_GRAPHICS_SDL, test "x${enable_graphics_sdl}" = "xyes")
+
 AC_ARG_ENABLE(postgresql, [  --disable-postgresql             don't add postgresql support to osm2navit], enable_postgresql=$enableval, enable_postgresql=yes)
 if test "x${enable_postgresql}" = "xyes" ; then
        if test -z "$PG_CONFIG"; then
@@ -185,8 +220,6 @@ if test "x$MODULE_GUI_SDL" = "xyes"; then
                AC_MSG_WARN([*** no SDL/SDL.h -- SDL support disabled])
        )
 fi
-AC_SUBST(SDL_CFLAGS)
-AC_SUBST(SDL_LIBS)
 
 PKG_CHECK_MODULES(
         [CEGUI],
@@ -501,6 +534,7 @@ navit/graphics/Makefile
 navit/graphics/gtk_drawing_area/Makefile
 navit/graphics/opengl/Makefile
 navit/graphics/null/Makefile
+navit/graphics/sdl/Makefile
 navit/graphics/qt_qpainter/Makefile
 navit/gui/Makefile
 navit/gui/gtk/Makefile
index 22bbc6e..1a6e89f 100644 (file)
@@ -8,3 +8,6 @@ endif
 if USE_GRAPHICS_QT_QPAINTER
   SUBDIRS+=qt_qpainter
 endif
+if USE_GRAPHICS_SDL
+  SUBDIRS+=sdl
+endif
diff --git a/navit/navit/graphics/sdl/Makefile.am b/navit/navit/graphics/sdl/Makefile.am
new file mode 100644 (file)
index 0000000..7865ca5
--- /dev/null
@@ -0,0 +1,5 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = @NAVIT_CFLAGS@ @SDL_CFLAGS@ @FREETYPE2_CFLAGS@ @FONTCONFIG_CFLAGS@ -I$(top_srcdir)/navit -DMODULE=graphics_sdl
+modulegraphics_LTLIBRARIES = libgraphics_sdl.la
+libgraphics_sdl_la_SOURCES = graphics_sdl.c
+libgraphics_sdl_la_LDFLAGS = @SDL_LIBS@ @SDL_IMAGE_LIBS@ @SDL_GFX_LIBS@ @FREETYPE2_LIBS@ @FONTCONFIG_LIBS@ @IMLIB2_LIBS@
diff --git a/navit/navit/graphics/sdl/graphics_sdl.c b/navit/navit/graphics/sdl/graphics_sdl.c
new file mode 100644 (file)
index 0000000..f5396c1
--- /dev/null
@@ -0,0 +1,1313 @@
+/* graphics_sdl.c -- barebones sdl graphics layer
+
+   copyright (c) 2008 bryan rittmeyer <bryanr@bryanr.org>
+   license: GPLv2
+
+   TODO:
+   - kb events
+   - raw linux touchscreen
+   - resize events (cannot be generated right now)
+   - SDL window title for X
+   - text visibility cleanup/tweaks
+   - dashed lines
+   - ifdef DEBUG -> dbg()
+   - valgrind
+
+   revision history:
+   2008-06-01 initial
+*/
+
+#include <glib.h>
+#include "config.h"
+#include "debug.h"
+#include "point.h"
+#include "graphics.h"
+#include "color.h"
+#include "plugin.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_gfxPrimitives.h>
+
+#undef SDL_TTF
+
+#ifdef SDL_TTF
+#include <SDL/SDL_ttf.h>
+#else
+#include <fontconfig/fontconfig.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <freetype/ftglyph.h>
+#endif
+
+#define SDL_IMAGE
+#ifdef SDL_IMAGE
+#include <SDL/SDL_image.h>
+#endif
+
+#include <alloca.h>
+
+#define DISPLAY_W 800
+#define DISPLAY_H 600
+
+#undef ANTI_ALIAS
+
+#undef DEBUG
+
+
+struct graphics_priv {
+    SDL_Surface *screen;
+
+       void (*resize_callback)(void *data, int w, int h);
+       void *resize_callback_data;
+       void (*motion_callback)(void *data, struct point *p);
+       void *motion_callback_data;
+       void (*button_callback)(void *data, int press, int button, struct point *p);
+       void *button_callback_data;
+
+#ifndef SDL_TTF
+    FT_Library library;
+    int library_init;
+#endif
+};
+
+static int dummy;
+
+
+struct graphics_font_priv {
+#ifdef SDL_TTF
+    TTF_Font *font;
+#else
+    FT_Face face;
+#endif
+};
+
+struct graphics_gc_priv {
+    struct graphics_priv *gr;
+    Uint8 fore_r;
+    Uint8 fore_g;
+    Uint8 fore_b;
+    Uint8 fore_a;
+    Uint8 back_r;
+    Uint8 back_g;
+    Uint8 back_b;
+    Uint8 back_a;
+    int linewidth;
+};
+
+struct graphics_image_priv {
+    SDL_Surface *img;
+};
+
+
+static void
+graphics_destroy(struct graphics_priv *gr)
+{
+#ifdef SDL_TTF
+    TTF_Quit();
+#endif
+    SDL_Quit();
+}
+
+/* graphics_font */
+static char *fontfamilies[]={
+       "Liberation Mono",
+       "Arial",
+       "DejaVu Sans",
+       "NcrBI4nh",
+       "luximbi",
+       "FreeSans",
+       NULL,
+};
+
+static void font_destroy(struct graphics_font_priv *gf)
+{
+    /* TODO: free FT stuff? */
+    g_free(gf);
+}
+
+static struct graphics_font_methods font_methods = {
+       font_destroy
+};
+
+static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size, int flags)
+{
+    struct graphics_font_priv *gf=g_new(struct graphics_font_priv, 1);
+
+#ifdef SDL_TTF
+    /* 'size' is in pixels, TTF_OpenFont wants pts. */
+    size = size / 15;
+
+//    gf->font = TTF_OpenFont("/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf", size);
+    if(flags)
+    {
+        gf->font = TTF_OpenFont("/usr/share/fonts/truetype/LiberationMono-Bold.ttf", size);
+    }
+    else
+    {
+        gf->font = TTF_OpenFont("/usr/share/fonts/truetype/LiberationMono-Regular.ttf", size);
+    }
+
+    if(gf->font == NULL)
+    {
+        g_free(gf);
+        return NULL;
+    }
+
+    if(flags)
+    {
+        /* apparently just means bold right now */
+        TTF_SetFontStyle(gf->font, TTF_STYLE_BOLD);
+    }
+    else
+    {
+        TTF_SetFontStyle(gf->font, TTF_STYLE_NORMAL);
+    }
+#else
+    /* copy-pasted from graphics_gtk_drawing_area.c
+
+       FIXME: figure out some way to share this b/t gtk and sdl graphics plugin.
+       new 'font' plugin type that uses an abstracted bitmap fmt to pass to gfx plugin?
+    */
+
+       int exact, found;
+       char **family;
+
+       if (!gr->library_init) {
+               FT_Init_FreeType( &gr->library );
+               gr->library_init=1;
+       }
+       found=0;
+       for (exact=1;!found && exact>=0;exact--) {
+               family=fontfamilies;
+               while (*family && !found) {
+                       dbg(1, "Looking for font family %s. exact=%d\n", *family, exact);
+                       FcPattern *required = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, *family, NULL);
+                       if (flags)
+                               FcPatternAddInteger(required,FC_WEIGHT,FC_WEIGHT_BOLD);
+                       FcConfigSubstitute(FcConfigGetCurrent(), required, FcMatchFont);
+                       FcDefaultSubstitute(required);
+                       FcResult result;
+                       FcPattern *matched = FcFontMatch(FcConfigGetCurrent(), required, &result);
+                       if (matched) {
+                               FcValue v1, v2;
+                               FcChar8 *fontfile;
+                               int fontindex;
+                               FcPatternGet(required, FC_FAMILY, 0, &v1);
+                               FcPatternGet(matched, FC_FAMILY, 0, &v2);
+                               FcResult r1 = FcPatternGetString(matched, FC_FILE, 0, &fontfile);
+                               FcResult r2 = FcPatternGetInteger(matched, FC_INDEX, 0, &fontindex);
+                               if ((r1 == FcResultMatch) && (r2 == FcResultMatch) && (FcValueEqual(v1,v2) || !exact)) {
+                                       dbg(2, "About to load font from file %s index %d\n", fontfile, fontindex);
+                                       FT_New_Face( gr->library, (char *)fontfile, fontindex, &gf->face );
+                                       found=1;
+                               }
+                               FcPatternDestroy(matched);
+                       }
+                       FcPatternDestroy(required);
+                       family++;
+               }
+       }
+       if (!found) {
+               g_warning("Failed to load font, no labelling");
+               g_free(gf);
+               return NULL;
+       }
+        FT_Set_Char_Size(gf->face, 0, size, 300, 300);
+       FT_Select_Charmap(gf->face, FT_ENCODING_UNICODE);
+#endif
+
+       *meth=font_methods;
+
+    return gf;
+}
+
+
+/* graphics_gc */
+
+static void
+gc_destroy(struct graphics_gc_priv *gc)
+{
+    g_free(gc);
+}
+
+static void
+gc_set_linewidth(struct graphics_gc_priv *gc, int w)
+{
+#ifdef DEBUG
+    printf("gc_set_linewidth %p %d\n", gc, w);
+#endif
+    gc->linewidth = w;
+}
+
+static void
+gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
+{
+    /* TODO */
+}
+
+static void
+gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
+{
+#ifdef DEBUG
+    printf("gc_set_foreground: %p %d %d %d %d\n", gc, c->a, c->r, c->g, c->b);
+#endif
+    gc->fore_r = c->r/256;
+    gc->fore_g = c->g/256;
+    gc->fore_b = c->b/256;
+    gc->fore_a = c->a/256;
+}
+
+static void
+gc_set_background(struct graphics_gc_priv *gc, struct color *c)
+{
+#ifdef DEBUG
+    printf("gc_set_background: %p %d %d %d %d\n", gc, c->a, c->r, c->g, c->b);
+#endif
+    gc->back_r = c->r/256;
+    gc->back_g = c->g/256;
+    gc->back_b = c->b/256;
+    gc->back_a = c->a/256;
+}
+
+static struct graphics_gc_methods gc_methods = {
+       gc_destroy,
+       gc_set_linewidth,
+       gc_set_dashes,  
+       gc_set_foreground,      
+       gc_set_background       
+};
+
+static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
+{
+    struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
+       *meth=gc_methods;
+    gc->gr=gr;
+    gc->linewidth=1; /* upper layer should override anyway? */
+       return gc;
+}
+
+
+static void image_destroy(struct graphics_image_priv *gi)
+{
+#ifdef SDL_IMAGE
+    SDL_FreeSurface(gi->img);
+    g_free(gi);
+#endif
+}
+
+static struct graphics_image_methods gi_methods =
+{
+    image_destroy
+};
+
+static struct graphics_image_priv *
+image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h,
+          struct point *hot)
+{
+#ifdef SDL_IMAGE
+    struct graphics_image_priv *gi;
+
+    /* FIXME: meth is not used yet.. so gi leaks. at least xpm is small */
+
+    gi = g_new0(struct graphics_image_priv, 1);
+    gi->img = IMG_Load(name);
+    if(gi->img)
+    {
+        /* TBD: improves blit performance? */
+        SDL_SetColorKey(gi->img, SDL_RLEACCEL, gi->img->format->colorkey);
+        *w=gi->img->w;
+        *h=gi->img->h;
+        hot->x=*w/2;
+        hot->y=*h/2;
+        *meth = gi_methods;
+    }
+    else
+    {
+        /* TODO: debug "colour parse errors" on xpm */
+        printf("graphics_sdl: image_new on '%s' failed: %s\n", name, IMG_GetError());
+        g_free(gi);
+        gi = NULL;
+    }
+
+    return gi;
+#else
+    return NULL;
+#endif
+}
+
+static void
+image_free(struct graphics_priv *gr, struct graphics_image_priv * img)
+{
+       dbg(0,"TODO");
+}
+
+static void
+get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret)
+{
+       char *p=text;
+       FT_BBox bbox;
+       FT_UInt  glyph_index;
+               FT_GlyphSlot  slot = font->face->glyph;  // a small shortcut
+       FT_Glyph glyph;
+       FT_Matrix matrix;
+       FT_Vector pen;
+       pen.x = 0 * 64;
+       pen.y = 0 * 64;
+       matrix.xx = dx;
+       matrix.xy = dy;
+       matrix.yx = -dy;
+       matrix.yy = dx;
+       int n,len,x=0,y=0;
+
+       bbox.xMin = bbox.yMin = 32000;
+       bbox.xMax = bbox.yMax = -32000; 
+       FT_Set_Transform( font->face, &matrix, &pen );
+       len=g_utf8_strlen(text, -1);
+       for ( n = 0; n < len; n++ ) {
+               FT_BBox glyph_bbox;
+               glyph_index = FT_Get_Char_Index(font->face, g_utf8_get_char(p));
+               p=g_utf8_next_char(p);
+               FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT );
+               FT_Get_Glyph(font->face->glyph, &glyph);
+               FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox );
+               glyph_bbox.xMin += x >> 6;
+               glyph_bbox.xMax += x >> 6;
+               glyph_bbox.yMin += y >> 6;
+               glyph_bbox.yMax += y >> 6;
+               x += slot->advance.x;
+               y -= slot->advance.y;
+               if ( glyph_bbox.xMin < bbox.xMin )
+                       bbox.xMin = glyph_bbox.xMin;
+               if ( glyph_bbox.yMin < bbox.yMin )
+                       bbox.yMin = glyph_bbox.yMin;
+               if ( glyph_bbox.xMax > bbox.xMax )
+                       bbox.xMax = glyph_bbox.xMax;
+               if ( glyph_bbox.yMax > bbox.yMax )
+                       bbox.yMax = glyph_bbox.yMax;
+       } 
+       if ( bbox.xMin > bbox.xMax ) {
+               bbox.xMin = 0;
+               bbox.yMin = 0;
+               bbox.xMax = 0;
+               bbox.yMax = 0;
+       }
+       ret[0].x=bbox.xMin;
+       ret[0].y=-bbox.yMin;
+       ret[1].x=bbox.xMin;
+       ret[1].y=-bbox.yMax;
+       ret[2].x=bbox.xMax;
+       ret[2].y=-bbox.yMax;
+       ret[3].x=bbox.xMax;
+       ret[3].y=-bbox.yMin;
+}
+
+static void
+draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
+{
+    Sint16 *vx, *vy;
+    int i;
+
+    vx = alloca(count * sizeof(Sint16));
+    vy = alloca(count * sizeof(Sint16));
+
+    for(i = 0; i < count; i++)
+    {
+        vx[i] = (Sint16)p[i].x;
+        vy[i] = (Sint16)p[i].y;
+#ifdef DEBUG
+        printf("draw_polygon: %p %i %d,%d\n", gc, i, p[i].x, p[i].y);
+#endif
+    }
+
+    filledPolygonRGBA(gr->screen, vx, vy, count,
+                      gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+}
+
+
+
+static void
+draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
+{
+#ifdef DEBUG
+        printf("draw_rectangle: %d %d %d %d r=%d g=%d b=%d a=%d\n", p->x, p->y, w, h,
+               gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#endif
+    if(w > DISPLAY_W)
+    {
+        w = DISPLAY_W-1;
+    }
+    if(h > DISPLAY_H)
+    {
+        h = DISPLAY_H-1;
+    }
+    boxRGBA(gr->screen, p->x, p->y, p->x + w, p->y + h,
+            gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+
+}
+
+static void
+draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
+{
+    int l, a;
+#ifdef DEBUG
+        printf("draw_circle: %d %d %d\n", p->x, p->y, r);
+#endif
+
+    /* FIXME: does not quite match gtk */
+
+    /* looks like GTK counts the outline in r,
+       sdl-gfx does not?
+    */
+    r = r - 1;
+
+    for(l = 0; l < gc->linewidth; l++)
+    {
+        a = l - (gc->linewidth/2);
+#ifdef ANTI_ALIAS
+        aacircleRGBA(gr->screen, p->x, p->y, r - l,
+                   gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#else
+        circleRGBA(gr->screen, p->x, p->y, r - l,
+                   gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#endif
+    }
+}
+
+
+static void
+draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
+{
+    /* you might expect lines to be simpler than the other shapes.
+       but, that would be wrong. 1 line can generate 1 polygon + 2 circles
+       and even worse, we have to calculate their parameters!
+       go dust off your trigonometry hat.
+    */
+
+#if 0
+    int i, l, x_inc, y_inc, lw;
+
+    lw = gc->linewidth;
+
+    for(i = 0; i < count-1; i++)
+    {
+#ifdef DEBUG
+        printf("draw_lines: %p %d %d,%d->%d,%d %d\n", gc, i, p[i].x, p[i].y, p[i+1].x, p[i+1].y, gc->linewidth);
+#endif
+        for(l = 0; l < lw; l++)
+        {
+            /* FIXME: center? */
+#if 1
+            if(p[i].x != p[i+1].x)
+            {
+                x_inc = l - (lw/2);
+            }
+            else
+            {
+                x_inc = 0;
+            }
+
+            if(p[i].y != p[i+1].y)
+            {
+                y_inc = l - (lw/2);
+            }
+            else
+            {
+                y_inc = 0;
+            }
+#else
+            x_inc = 0;
+            y_inc = 0;
+#endif
+
+#ifdef ANTI_ALIAS
+            aalineRGBA(gr->screen, p[i].x + x_inc, p[i].y + y_inc, p[i+1].x + x_inc, p[i+1].y + y_inc,
+                     gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#else
+            lineRGBA(gr->screen, p[i].x + x_inc, p[i].y + y_inc, p[i+1].x + x_inc, p[i+1].y + y_inc,
+                     gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#endif
+        }
+    }
+#else
+    /* sort of based on graphics_opengl.c::draw_lines */
+    /* FIXME: should honor ./configure flag for no fp.
+              this could be 100% integer code pretty easily,
+              except that i am lazy
+    */
+    struct point vert[4];
+    int lw = gc->linewidth;
+    //int lw = 1;
+    int i;
+
+    for(i = 0; i < count-1; i++)
+    {
+               float dx=p[i+1].x-p[i].x;
+               float dy=p[i+1].y-p[i].y;
+
+#if 0
+               float cx=(p[i+1].x+p[i].x)/2;
+               float cy=(p[i+1].y+p[i].y)/2;
+#endif
+
+               int l=round(sqrt(dx*dx+dy*dy));
+        float angle;
+
+        int x_lw_adj, y_lw_adj;
+
+        if(lw == 1)
+        {
+#ifdef ANTI_ALIAS
+            aalineRGBA(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
+                     gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#else
+            lineRGBA(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
+                     gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#endif
+        }
+        else
+        {
+            /* there is probably a much simpler way but this works ok */
+
+            /* FIXME: float + double mixture */
+            /* FIXME: lrint(round())? */
+            if(dy == 0.0)
+            {
+                angle = 0.0;
+                x_lw_adj = 0;
+                y_lw_adj = round((float)lw/2.0);
+            }
+            else if(dx == 0.0)
+            {
+                angle = 0.0;
+                x_lw_adj = round((float)lw/2.0);
+                y_lw_adj = 0;
+            }
+            else
+            {
+                angle = (M_PI/2.0) - atan(abs(dx)/abs(dy));
+                x_lw_adj = round(sin(angle)*(float)lw/2.0);
+                y_lw_adj = round(cos(angle)*(float)lw/2.0);
+                if((x_lw_adj < 0) || (y_lw_adj < 0))
+                {
+                    printf("i=%d\n", i);
+                    printf("   %d,%d->%d,%d\n", p[i].x, p[i].y, p[i+1].x, p[i+1].y);
+                    printf("   lw=%d angle=%f\n", lw, 180.0 * angle / M_PI);
+                    printf("   x_lw_adj=%d y_lw_adj=%d\n", x_lw_adj, y_lw_adj);
+                }
+            }
+
+            if(p[i+1].x > p[i].x)
+            {
+                x_lw_adj = -x_lw_adj;
+            }
+            if(p[i+1].y > p[i].y)
+            {
+                y_lw_adj = -y_lw_adj;
+            }
+
+#ifdef DEBUG
+            printf("i=%d\n", i);
+            printf("   %d,%d->%d,%d\n", p[i].x, p[i].y, p[i+1].x, p[i+1].y);
+            printf("   lw=%d angle=%f\n", lw, 180.0 * angle / M_PI);
+            printf("   x_lw_adj=%d y_lw_adj=%d\n", x_lw_adj, y_lw_adj);
+#endif
+
+            /* FIXME: draw a circle/square if p[i]==p[i+1]? */
+            /* FIXME: clipping, check for neg values. hoping sdl-gfx does this */
+            vert[0].x = p[i].x + x_lw_adj;
+            vert[0].y = p[i].y - y_lw_adj;
+            vert[1].x = p[i].x - x_lw_adj;
+            vert[1].y = p[i].y + y_lw_adj;
+            vert[2].x = p[i+1].x - x_lw_adj;
+            vert[2].y = p[i+1].y + y_lw_adj;
+            vert[3].x = p[i+1].x + x_lw_adj;
+            vert[3].y = p[i+1].y - y_lw_adj;
+            /* FIXME?: need extra copy of vert[0] here to "close" the poly? apparently not! */
+
+            draw_polygon(gr, gc, vert, 4);
+
+            /* draw small circles at the ends. this looks better than nothing, and slightly
+             * better than the triangle used by graphics_opengl, but is more expensive.
+             * should have an ifdef/xml attr?
+            */
+
+            /* FIXME: should just draw a half circle */
+
+            /* now some circular endcaps, if the width is over 2 */ 
+            if(lw > 2)
+            {
+                if(i == 0)
+                {
+                    draw_circle(gr, gc, &p[i], lw/2);
+                }
+                /* we truncate on the divide on purpose, so we don't go outside the line */
+                draw_circle(gr, gc, &p[i+1], lw/2);
+            }
+        }
+    }
+#endif
+}
+
+
+#ifdef SDL_TTF
+static void
+draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *gf, char *text, struct point *p, int dx, int dy)
+{
+    SDL_Surface *ss;
+    SDL_Color f, b;
+    SDL_Rect r;
+
+#if 0
+    /* correct? */
+    f.r = bg->back_r;
+    f.g = bg->back_g;
+    f.b = bg->back_b;
+    b.r = bg->back_r;
+    b.g = bg->back_g;
+    b.b = bg->back_b;
+#else
+    f.r = 0xff;
+    f.g = 0xff;
+    f.b = 0xff;
+    b.r = 0x00;
+    b.g = 0x00;
+    b.b = 0x00;
+#endif
+
+    /* TODO: dx + dy? */
+
+    ss = TTF_RenderUTF8_Solid(gf->font, text, b);
+    if(ss)
+    {
+        r.x = p->x;
+        r.y = p->y;
+        r.w = ss->w;
+        r.h = ss->h;
+        //SDL_SetAlpha(ss, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
+        SDL_BlitSurface(ss, NULL, gr->screen, &r);
+    }
+}
+#else
+
+struct text_glyph {
+       int x,y,w,h;
+    unsigned char *shadow;
+       unsigned char pixmap[0];
+};
+
+struct text_render {
+       int x1,y1;
+       int x2,y2;
+       int x3,y3;
+       int x4,y4;
+       int glyph_count;
+       struct text_glyph *glyph[0];
+};
+
+#ifndef _WIN32
+static unsigned char *
+display_text_render_shadow(struct text_glyph *g)
+{
+       int mask0, mask1, mask2, x, y, w=g->w, h=g->h;
+       int str=(g->w+9)/8;
+       unsigned char *shadow;
+       unsigned char *p, *pm=g->pixmap;
+
+       shadow=malloc(str*(g->h+2)); /* do not use g_malloc() here */
+       memset(shadow, 0, str*(g->h+2));
+       for (y = 0 ; y < h ; y++) {
+               p=shadow+str*y;
+               mask0=0x4000;
+               mask1=0xe000;
+               mask2=0x4000;
+               for (x = 0 ; x < w ; x++) {
+                       if (pm[x+y*w]) {
+                               p[0]|=(mask0 >> 8);
+                               if (mask0 & 0xff)
+                                       p[1]|=mask0;
+
+                               p[str]|=(mask1 >> 8);
+                               if (mask1 & 0xff)
+                                       p[str+1]|=mask1;
+                               p[str*2]|=(mask2 >> 8);
+                               if (mask2 & 0xff)
+                                       p[str*2+1]|=mask2;
+                       }
+                       mask0 >>= 1;
+                       mask1 >>= 1;
+                       mask2 >>= 1;
+                       if (!((mask0 >> 8) | (mask1 >> 8) | (mask2 >> 8))) {
+                               mask0<<=8;
+                               mask1<<=8;
+                               mask2<<=8;
+                               p++;
+                       }
+               }
+       }
+       return shadow;
+}
+#else
+/* TODO FIXME */
+static GdkImage *
+display_text_render_shadow(struct text_glyph *g)
+{
+       int mask0, mask1, mask2, x, y, w=g->w, h=g->h;
+       int str=(g->w+9)/8;
+       unsigned char *p, *pm=g->pixmap;
+       GdkImage *ret;
+
+       ret=gdk_image_new( GDK_IMAGE_NORMAL , gdk_visual_get_system(), w+2, h+2);
+
+       for (y = 0 ; y < h ; y++) {
+               p=ret->mem+str*y;
+
+               mask0=0x4000;
+               mask1=0xe000;
+               mask2=0x4000;
+               for (x = 0 ; x < w ; x++) {
+                       if (pm[x+y*w]) {
+                               p[0]|=(mask0 >> 8);
+                               if (mask0 & 0xff)
+                                       p[1]|=mask0;
+
+                               p[str]|=(mask1 >> 8);
+                               if (mask1 & 0xff)
+                                       p[str+1]|=mask1;
+                               p[str*2]|=(mask2 >> 8);
+                               if (mask2 & 0xff)
+                                       p[str*2+1]|=mask2;
+                       }
+                       mask0 >>= 1;
+                       mask1 >>= 1;
+                       mask2 >>= 1;
+                       if (!((mask0 >> 8) | (mask1 >> 8) | (mask2 >> 8))) {
+                               mask0<<=8;
+                               mask1<<=8;
+                               mask2<<=8;
+                       }
+               }
+       }
+       return ret;
+}
+#endif
+
+static struct text_render *
+display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y)
+{
+               FT_GlyphSlot  slot = font->face->glyph;  // a small shortcut
+       FT_Matrix matrix;
+       FT_Vector pen;
+       FT_UInt  glyph_index;
+       int n,len;
+       struct text_render *ret;
+       struct text_glyph *curr;
+       char *p=text;
+
+       len=g_utf8_strlen(text, -1);
+       ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *));
+       ret->glyph_count=len;
+
+       matrix.xx = dx;
+       matrix.xy = dy;
+       matrix.yx = -dy;
+       matrix.yy = dx;
+
+       pen.x = 0 * 64;
+       pen.y = 0 * 64;
+       x <<= 6;
+       y <<= 6;
+       FT_Set_Transform( font->face, &matrix, &pen );
+
+       for ( n = 0; n < len; n++ )
+       {
+
+               glyph_index = FT_Get_Char_Index(font->face, g_utf8_get_char(p));
+               FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT );
+               FT_Render_Glyph(font->face->glyph, ft_render_mode_normal );
+
+               curr=g_malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch);
+               ret->glyph[n]=curr;
+
+               curr->x=(x>>6)+slot->bitmap_left;
+               curr->y=(y>>6)-slot->bitmap_top;
+               curr->w=slot->bitmap.width;
+               curr->h=slot->bitmap.rows;
+               if (slot->bitmap.width && slot->bitmap.rows) {
+                       memcpy(curr->pixmap, slot->bitmap.buffer, slot->bitmap.rows*slot->bitmap.pitch);
+                       curr->shadow=display_text_render_shadow(curr);
+               }
+               else
+                       curr->shadow=NULL;
+#if 0
+               printf("height=%d\n", slot->metrics.height);
+               printf("height2=%d\n", face->height);
+               printf("bbox %d %d %d %d\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax);
+#endif
+#if 0
+        printf("slot->advance x %d y %d\n",
+               slot->advance.x,
+               slot->advance.y);
+#endif
+
+               x += slot->advance.x;
+               y -= slot->advance.y;
+               p=g_utf8_next_char(p);
+       }
+       return ret;
+}
+
+static void hexdump(unsigned char *buf, unsigned int n)
+{
+    int i;
+    for(i = 0; i < n; i++)
+    {
+        if((i&0xf)==0)
+        {
+            printf("\n%02x: ", i);
+        }
+        printf("%02x ", buf[i]);
+    }
+    printf("\n");
+}
+
+#if 0
+static void sdl_inv_grayscale_pal_set(SDL_Surface *ss)
+{
+    SDL_Color c;
+    int i;
+
+    for(i = 0; i < 256; i++)
+    {
+        c.r = 255-i;
+        c.g = 255-i;
+        c.b = 255-i;
+        SDL_SetPalette(ss, SDL_LOGPAL, &c, i, 1); 
+    }
+}
+#endif
+
+static void sdl_scale_pal_set(SDL_Surface *ss, Uint8 r, Uint8 g, Uint8 b)
+{
+    SDL_Color c;
+    int i;
+
+
+    for(i = 0; i < 256; i++)
+    {
+        c.r = 255 - (i * r) / 256;
+        c.g = 255 - (i * g) / 256;
+        c.b = 255 - (i * b) / 256;
+        SDL_SetPalette(ss, SDL_LOGPAL, &c, i, 1); 
+    }
+}
+
+#if 0
+static void sdl_fixed_pal_set(SDL_Surface *ss, Uint8 r, Uint8 g, Uint8 b)
+{
+    SDL_Color c;
+    int i;
+
+    c.r = r;
+    c.g = g;
+    c.b = b;
+    for(i = 0; i < 256; i++)
+    {
+        SDL_SetPalette(ss, SDL_LOGPAL, &c, i, 1); 
+    }
+}
+#endif
+
+static void
+display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg)
+{
+       int i;
+       struct text_glyph *g, **gp;
+    SDL_Surface *ss;
+    SDL_Rect r;
+    SDL_Color b, f;
+
+       gp=text->glyph;
+       i=text->glyph_count;
+       while (i-- > 0)
+       {
+               g=*gp++;
+        if(g->shadow && bg)
+        {
+            ss = SDL_CreateRGBSurfaceFrom(g->pixmap, g->w+2, g->h+2, 8, g->w+2, 0, 0, 0, 0);
+            if(ss)
+            {
+                //sdl_inv_grayscale_pal_set(ss);
+                sdl_scale_pal_set(ss, bg->back_r, bg->back_g, bg->back_b);
+                r.x = g->x-1;
+                r.y = g->y-1;
+                r.w = g->w+2;
+                r.h = g->h+2;
+                //printf("%d %d %d %d\n", g->x, g->y, g->w, g->h);
+                SDL_SetAlpha(ss, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
+                //SDL_SetColorKey(ss, SDL_SRCCOLORKEY, 0x00);
+                SDL_BlitSurface(ss, NULL, gr->screen, &r);
+                SDL_FreeSurface(ss);
+            }
+        }
+               //if (g->shadow && bg)
+                       //gdk_draw_image(gr->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2);
+       }
+       gp=text->glyph;
+       i=text->glyph_count;
+       while (i-- > 0)
+       {
+               g=*gp++;
+               if (g->w && g->h)
+        {
+            //hexdump(g->pixmap, g->w * g->h);
+
+            ss = SDL_CreateRGBSurfaceFrom(g->pixmap, g->w, g->h, 8, g->w, 0, 0, 0, 0);
+            if(ss)
+            {
+                //sdl_inv_grayscale_pal_set(ss);
+                sdl_scale_pal_set(ss, fg->fore_r, fg->fore_g, fg->fore_b);
+                //sdl_inv_bw_pal_set(ss);
+                r.x = g->x;
+                r.y = g->y;
+                r.w = g->w;
+                r.h = g->h;
+                //printf("%d %d %d %d\n", g->x, g->y, g->w, g->h);
+                //SDL_SetAlpha(ss, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
+                SDL_SetColorKey(ss, SDL_SRCCOLORKEY, 0x00);
+                SDL_BlitSurface(ss, NULL, gr->screen, &r);
+                SDL_FreeSurface(ss);
+            }
+        }
+                       //gdk_draw_gray_image(gr->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w);
+       }
+}
+
+static void
+display_text_free(struct text_render *text)
+{
+       int i;
+       struct text_glyph **gp;
+
+       gp=text->glyph;
+       i=text->glyph_count;
+       while (i-- > 0) {
+               if ((*gp)->shadow) {
+           free((*gp)->shadow);
+           }   
+               g_free(*gp++);
+       }
+       g_free(text);
+}
+
+static void
+draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
+{
+       struct text_render *t;
+
+       if (! font)
+               return;
+#if 0
+       if (bg) {
+               gdk_gc_set_function(fg->gc, GDK_AND_INVERT);
+               gdk_gc_set_function(bg->gc, GDK_OR);
+       }
+#endif
+
+       t=display_text_render(text, font, dx, dy, p->x, p->y);
+       display_text_draw(t, gr, fg, bg);
+       display_text_free(t);
+#if 0
+       if (bg) {
+               gdk_gc_set_function(fg->gc, GDK_COPY);
+               gdk_gc_set_function(bg->gc, GDK_COPY);
+       }
+#endif
+}
+#endif
+
+
+
+static void
+draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
+{
+#ifdef SDL_IMAGE
+    SDL_Rect r;
+
+    r.x = p->x;
+    r.y = p->y;
+    r.w = img->img->w;
+    r.h = img->img->h;
+
+    SDL_BlitSurface(img->img, NULL, gr->screen, &r);
+#endif
+}
+
+static void
+draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
+{
+    /* TODO */
+}
+
+static void
+draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
+{
+#ifdef DEBUG
+    printf("draw_restore\n");
+#endif
+}
+
+static void
+background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
+{
+#ifdef DEBUG
+    printf("background_gc\n");
+#endif
+}
+
+static void
+draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
+{
+    SDL_Rect rect;
+
+#ifdef DEBUG
+    printf("draw_mode: %d\n", mode);
+#endif
+
+    if(mode == draw_mode_end)
+    {
+        /* TBD: just update the modified rects? that may be slower, actually */
+        rect.x = 0;
+        rect.y = 0;
+        rect.w = DISPLAY_W;
+        rect.h = DISPLAY_H;
+        SDL_UpdateRects(gr->screen, 1, &rect);
+    }
+}
+
+static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h);
+
+static void *
+get_data(struct graphics_priv *this, char *type)
+{
+    printf("get_data: %s\n", type);
+       return &dummy;
+}
+
+
+
+static void
+register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data)
+{
+       this->resize_callback=callback;
+       this->resize_callback_data=data;
+
+    if(this->resize_callback)
+    {
+        this->resize_callback(this->resize_callback_data, DISPLAY_W, DISPLAY_H);
+    }
+}
+
+static void
+register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data)
+{
+       this->motion_callback=callback;
+       this->motion_callback_data=data;
+}
+
+static void
+register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data)
+{
+       this->button_callback=callback;
+       this->button_callback_data=data;
+}
+
+static struct graphics_methods graphics_methods = {
+       graphics_destroy,
+       draw_mode,
+       draw_lines,
+       draw_polygon,
+       draw_rectangle,
+       draw_circle,
+       draw_text,
+       draw_image,
+       draw_image_warp,
+       draw_restore,
+       font_new,
+       gc_new,
+       background_gc,
+       overlay_new,
+       image_new,
+       get_data,
+       register_resize_callback,
+       register_button_callback,
+       register_motion_callback,
+       image_free,
+        get_text_bbox,
+};
+
+static struct graphics_priv *
+overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h)
+{
+    return NULL;
+}
+
+static gboolean graphics_sdl_idle(void *data)
+{
+    struct graphics_priv *gr = (struct graphics_priv *)data;
+    struct point p;
+    SDL_Event ev;
+    int ret;
+
+    while(1)
+    {
+        ret = SDL_PollEvent(&ev);
+        if(ret == 0)
+        {
+            break;
+        }
+
+        switch(ev.type)
+        {
+            case SDL_MOUSEMOTION:
+            {
+                p.x = ev.motion.x;
+                p.y = ev.motion.y;
+                if(gr->motion_callback)
+                {
+                    gr->motion_callback(gr->motion_callback_data, &p);
+                }
+                break;
+            }
+
+            case SDL_KEYDOWN:
+            {
+                break;
+            }
+
+            case SDL_KEYUP:
+            {
+                break;
+            }
+
+            case SDL_MOUSEBUTTONDOWN:
+            {
+#ifdef DEBUG
+                printf("SDL_MOUSEBUTTONDOWN %d %d %d %d %d\n",
+                       ev.button.which,
+                       ev.button.button,
+                       ev.button.state,
+                       ev.button.x,
+                       ev.button.y);
+#endif
+
+                p.x = ev.button.x;
+                p.y = ev.button.y;
+                if(gr->button_callback)
+                {
+                    gr->button_callback(gr->button_callback_data, 1, ev.button.button, &p);
+                }
+                break;
+            }
+
+            case SDL_MOUSEBUTTONUP:
+            {
+#ifdef DEBUG
+                printf("SDL_MOUSEBUTTONUP %d %d %d %d %d\n",
+                       ev.button.which,
+                       ev.button.button,
+                       ev.button.state,
+                       ev.button.x,
+                       ev.button.y);
+#endif
+
+                p.x = ev.button.x;
+                p.y = ev.button.y;
+                if(gr->button_callback)
+                {
+                    gr->button_callback(gr->button_callback_data, 0, ev.button.button, &p);
+                }
+                break;
+            }
+
+            case SDL_QUIT:
+            {
+                //g_main_loop_quit(GMainLoop);
+                break;
+            }
+
+#if 0
+            case SDL_VIDEOEXPOSE:
+            {
+                /* hack to repair damage */
+                if(gr->resize_callback)
+                {
+                    gr->resize_callback(gr->resize_callback_data, DISPLAY_W, DISPLAY_H);
+                }
+                break;
+            }
+#endif
+
+            default:
+            {
+#ifdef DEBUG
+                printf("SDL_Event %d\n", ev.type);
+#endif
+                break;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+
+static struct graphics_priv *
+graphics_sdl_new(struct graphics_methods *meth, struct attr **attrs)
+{
+    struct graphics_priv *this=g_new0(struct graphics_priv, 1);
+    int ret;
+
+#ifndef SDL_TTF
+    this->library_init = 0;
+#endif
+
+    ret = SDL_Init(SDL_INIT_VIDEO);
+    if(ret < 0)
+    {
+        g_free(this);
+        return NULL;
+    }
+
+#ifdef SDL_TTF
+    ret = TTF_Init();
+    if(ret < 0)
+    {
+        g_free(this);
+        SDL_Quit();
+        return NULL;
+    }
+#endif
+
+    this->screen = SDL_SetVideoMode(DISPLAY_W, DISPLAY_H, 32, SDL_HWSURFACE);
+    if(this->screen == NULL)
+    {
+        g_free(this);
+        SDL_Quit();
+        return NULL;
+    }
+
+    SDL_WM_SetCaption("navit", NULL);
+
+       *meth=graphics_methods;
+
+    g_timeout_add(10, graphics_sdl_idle, this);
+
+       return this;
+}
+
+void
+plugin_init(void)
+{
+        plugin_register_graphics_type("sdl", graphics_sdl_new);
+}
+
index 2a74f67..25e4d0c 100644 (file)
@@ -34,6 +34,7 @@
 #include <glib.h>
 #include "config.h"
 #include "item.h"
+#include "file.h"
 #include "navit.h"
 #include "debug.h"
 #include "gui.h"
@@ -136,13 +137,29 @@ static struct widget * gui_internal_box_new(struct gui_priv *this, enum flags fl
 static void gui_internal_widget_append(struct widget *parent, struct widget *child);
 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w);
 
+static char *
+image_path(char *name, int w, int h)
+{
+       char *full_name;
+       full_name=g_strdup_printf("%s/xpm/%s.svg", getenv("NAVIT_SHAREDIR"), name);
+       if (file_exists(full_name))
+               return full_name;
+       full_name=g_strdup_printf("%s/xpm/%s.png", getenv("NAVIT_SHAREDIR"), name);
+       if (file_exists(full_name))
+               return full_name;
+       return NULL;
+}
+
 static struct graphics_image *
 image_new(struct gui_priv *this, char *name)
 {
-       char *full_name=g_strdup_printf("xpm/%s.svg", name);
-       struct graphics_image *ret;
+       char *full_name=image_path(name, -1, -1);
+       struct graphics_image *ret=NULL;
 
-       ret=graphics_image_new(this->gra, full_name);
+       if (full_name);
+               ret=graphics_image_new(this->gra, full_name);
+       if (! ret)
+               dbg(0,"Failed to load %s\n", full_name);
        g_free(full_name);
        return ret;
 }
@@ -151,10 +168,13 @@ image_new(struct gui_priv *this, char *name)
 static struct graphics_image *
 image_new_scaled(struct gui_priv *this, char *name, int w, int h)
 {
-       char *full_name=g_strdup_printf("xpm/%s.svg", name);
-       struct graphics_image *ret;
+       char *full_name=image_path(name, w, h);
+       struct graphics_image *ret=NULL;
 
-       ret=graphics_image_new_scaled(this->gra, full_name, w, h);
+       if (full_name);
+               ret=graphics_image_new_scaled(this->gra, full_name, w, h);
+       if (! ret)
+               dbg(0,"Failed to load %s\n", full_name);
        g_free(full_name);
        return ret;
 }
@@ -227,8 +247,10 @@ gui_internal_image_new(struct gui_priv *this, struct graphics_image *image)
        struct widget *widget=g_new0(struct widget, 1);
        widget->type=widget_image;
        widget->img=image;
-       widget->w=widget->img->width;
-       widget->h=widget->img->height;
+       if (image) {
+               widget->w=image->width;
+               widget->h=image->height;
+       }
        return widget;
 }
 
@@ -268,6 +290,8 @@ gui_internal_button_new_with_callback(struct gui_priv *this, char *text, struct
                        ret=gui_internal_label_new(this, text);
                if (image)
                        ret=gui_internal_image_new(this, image);
+               if (! ret)
+                       ret=gui_internal_box_new(this, flags);
        }
        if (ret) {
                ret->func=func;
index ad8cb9d..7b58b0a 100644 (file)
@@ -1021,7 +1021,7 @@ route_graph_update(struct route *this)
 struct street_data *
 street_get_data (struct item *item)
 {
-       int maxcount=2000;
+       int maxcount=4000;
        struct coord c[maxcount];
        int count=0;
        struct street_data *ret;