Patch:graphics/sdl:Make debugging less noisy
[profile/ivi/navit.git] / navit / navit / graphics / sdl / graphics_sdl.c
index 5937d67..f896ea7 100644 (file)
@@ -18,6 +18,9 @@
 */
 
 #include <glib.h>
+#include <pthread.h>
+#include <poll.h>
+#include <signal.h>
 #include "config.h"
 #include "debug.h"
 #include "point.h"
 #include "item.h"
 #include "attr.h"
 #include "callback.h"
+#include "font/freetype/font_freetype.h"
 
 #include <SDL/SDL.h>
 #include <math.h>
 
+#ifdef USE_WEBOS
+# include "vehicle.h"
+# include <PDL.h>
+# define USE_WEBOS_ACCELEROMETER
+#endif
+
 #define RASTER
 #undef SDL_SGE
 #undef SDL_GFX
 #define SDL_IMAGE
 #undef LINUX_TOUCHSCREEN
 
+#ifdef USE_WEBOS
+#define DISPLAY_W 0
+#define DISPLAY_H 0
+#else
 #define DISPLAY_W 800
 #define DISPLAY_H 600
+#endif
 
 
 #undef DEBUG
 #undef PROFILE
 
-#define OVERLAY_MAX 16
+#define OVERLAY_MAX 32
 
 #ifdef RASTER
 #include "raster.h"
@@ -67,7 +82,6 @@
 #ifdef SDL_TTF
 #include <SDL/SDL_ttf.h>
 #else
-#include <fontconfig/fontconfig.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include <freetype/ftglyph.h>
@@ -116,11 +130,17 @@ struct graphics_priv {
     int overlay_enable;
     enum draw_mode_num draw_mode;
 
-       int resize_callback_initial;
+    int resize_callback_initial;
 
     struct navit *nav;
     struct callback_list *cbl;
 
+#ifdef USE_WEBOS_ACCELEROMETER
+    SDL_Joystick *accelerometer;
+    char orientation;
+    int real_w, real_h;
+#endif
+
 #ifdef LINUX_TOUCHSCREEN
     int ts_fd;
     int32_t ts_hit;
@@ -136,11 +156,78 @@ struct graphics_priv {
     struct timeval draw_begin_tv;
     unsigned long draw_time_peak;
 #endif
+    struct font_freetype_methods freetype_methods;
     /* </main> */
 };
 
 static int dummy;
 
+#ifdef USE_WEBOS
+# define WEBOS_KEY_SHIFT 0x130
+# define WEBOS_KEY_SYM 0x131
+# define WEBOS_KEY_ORANGE 0x133
+
+# define WEBOS_KEY_MOD_SHIFT 0x1
+# define WEBOS_KEY_MOD_ORANGE 0x2
+# define WEBOS_KEY_MOD_SYM 0x4
+
+# define WEBOS_KEY_MOD_SHIFT_STICKY 0x11
+# define WEBOS_KEY_MOD_ORANGE_STICKY 0x22
+# define WEBOS_KEY_MOD_SYM_STICKY 0x44
+
+# ifdef USE_WEBOS_ACCELEROMETER
+#  define WEBOS_ORIENTATION_PORTRAIT 0x1
+#  define WEBOS_ORIENTATION_LANDSCAPE 0x2
+# endif
+
+# define SDL_USEREVENT_CODE_TIMER 0x1
+# define SDL_USEREVENT_CODE_CALL_CALLBACK 0x2
+# define SDL_USEREVENT_CODE_IDLE_EVENT 0x4
+# define SDL_USEREVENT_CODE_WATCH 0x8
+# ifdef USE_WEBOS_ACCELEROMETER
+#  define SDL_USEREVENT_CODE_ROTATE 0xA
+# endif
+
+struct event_timeout {
+    SDL_TimerID id;
+    int multi;
+    struct callback *cb;
+};
+
+struct idle_task {
+    int priority;
+    struct callback *cb;
+};
+
+struct event_watch {
+    struct pollfd *pfd;
+    struct callback *cb;
+};
+
+static struct graphics_priv* the_graphics = NULL;
+static int quit_event_loop             = 0; // quit the main event loop
+static int the_graphics_count          = 0; // count how many graphics objects are created
+static GPtrArray *idle_tasks           = NULL;
+static pthread_t sdl_watch_thread      = 0;
+static GPtrArray *sdl_watch_list       = NULL;
+
+static void event_sdl_watch_thread (GPtrArray *);
+static void event_sdl_watch_startthread(GPtrArray *watch_list);
+static void event_sdl_watch_stopthread(void);
+static struct event_watch *event_sdl_add_watch(void *, enum event_watch_cond, struct callback *);
+static void event_sdl_remove_watch(struct event_watch *);
+static struct event_timeout *event_sdl_add_timeout(int, int, struct callback *);
+static void event_sdl_remove_timeout(struct event_timeout *);
+static struct event_idle *event_sdl_add_idle(int, struct callback *);
+static void event_sdl_remove_idle(struct event_idle *);
+static void event_sdl_call_callback(struct callback_list *);
+# ifdef USE_WEBOS_ACCELEROMETER
+static unsigned int sdl_orientation_count = 2^16;
+static char sdl_next_orientation = 0;
+# endif
+#endif
+unsigned char * ft_buffer = NULL;
+unsigned int    ft_buffer_size = 0;
 
 struct graphics_font_priv {
 #ifdef SDL_TTF
@@ -175,7 +262,7 @@ static int input_ts_exit(struct graphics_priv *gr);
 static void
 graphics_destroy(struct graphics_priv *gr)
 {
-    dbg(0, "graphics_destroy %p %u\n", gr, gr->overlay_mode);
+    dbg(1, "graphics_destroy %p %u\n", gr, gr->overlay_mode);
 
     if(gr->overlay_mode)
     {
@@ -184,139 +271,27 @@ graphics_destroy(struct graphics_priv *gr)
     }
     else
     {
+       g_free (ft_buffer);
 #ifdef SDL_TTF
         TTF_Quit();
 #else
         FT_Done_FreeType(gr->library);
-        FcFini();
 #endif
 #ifdef LINUX_TOUCHSCREEN
         input_ts_exit(gr);
 #endif
+#ifdef USE_WEBOS_ACCELEROMETER
+       SDL_JoystickClose(gr->accelerometer);
+#endif
+#ifdef USE_WEBOS
+        PDL_Quit();
+#endif
         SDL_Quit();
     }
 
     g_free(gr);
 }
 
-/* graphics_font */
-static char *fontfamilies[]={
-       "Liberation Mono",
-       "Arial",
-       "DejaVu Sans",
-       "NcrBI4nh",
-       "luximbi",
-       "FreeSans",
-       NULL,
-};
-
-static void font_destroy(struct graphics_font_priv *gf)
-{
-#ifdef SDL_TTF
-#else
-    FT_Done_Face(gf->face);
-#endif
-    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, char *fontfamily, 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->overlay_mode)
-    {
-        gr = gr->overlay_parent;
-    }
-
-       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
@@ -365,20 +340,20 @@ gc_set_background(struct graphics_gc_priv *gc, struct color *c)
 }
 
 static struct graphics_gc_methods gc_methods = {
-       gc_destroy,
-       gc_set_linewidth,
-       gc_set_dashes,  
-       gc_set_foreground,      
-       gc_set_background       
+    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_new0(struct graphics_gc_priv, 1);
-       *meth=gc_methods;
+    *meth=gc_methods;
     gc->gr=gr;
     gc->linewidth=1; /* upper layer should override anyway? */
-       return gc;
+    return gc;
 }
 
 
@@ -399,7 +374,7 @@ static struct graphics_image_methods gi_methods =
 
 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, int rotation)
+        struct point *hot, int rotation)
 {
 #ifdef SDL_IMAGE
     struct graphics_image_priv *gi;
@@ -422,7 +397,7 @@ image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *n
     else
     {
         /* TODO: debug "colour parse errors" on xpm */
-        printf("graphics_sdl: image_new on '%s' failed: %s\n", name, IMG_GetError());
+        dbg(0,"image_new on '%s' failed: %s\n", name, IMG_GetError());
         g_free(gi);
         gi = NULL;
     }
@@ -445,67 +420,72 @@ image_free(struct graphics_priv *gr, struct graphics_image_priv * gi)
 static void
 get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
 {
-       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 );
-               FT_Done_Glyph(glyph);
-               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;
+    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 );
+       FT_Done_Glyph(glyph);
+       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)
 {
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
+    {
+       return;
+    }
+
     Sint16 *vx, *vy;
     Sint16 x, y;
     int i;
@@ -541,49 +521,49 @@ draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point
     if(gr->aa)
     {
         raster_aapolygon(gr->screen, count, vx, vy,
-                       SDL_MapRGBA(gr->screen->format,
-                                  gc->fore_r,
-                                  gc->fore_g,
-                                  gc->fore_b,
-                                  gc->fore_a));
+                SDL_MapRGBA(gr->screen->format,
+                    gc->fore_r,
+                    gc->fore_g,
+                    gc->fore_b,
+                    gc->fore_a));
     }
     else
     {
         raster_polygon(gr->screen, count, vx, vy,
-                       SDL_MapRGBA(gr->screen->format,
-                                  gc->fore_r,
-                                  gc->fore_g,
-                                  gc->fore_b,
-                                  gc->fore_a));
+                SDL_MapRGBA(gr->screen->format,
+                    gc->fore_r,
+                    gc->fore_g,
+                    gc->fore_b,
+                    gc->fore_a));
     }
 #else
-#ifdef SDL_SGE
-#ifdef ALPHA
+# ifdef SDL_SGE
+#  ifdef ALPHA
     sge_FilledPolygonAlpha(gr->screen, count, vx, vy,
-                           SDL_MapRGB(gr->screen->format,
-                                      gc->fore_r,
-                                      gc->fore_g,
-                                      gc->fore_b),
-                           gc->fore_a);
-#else
-#ifdef ANTI_ALIAS
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b),
+            gc->fore_a);
+#  else
+#   ifdef ANTI_ALIAS
     sge_AAFilledPolygon(gr->screen, count, vx, vy,
-                           SDL_MapRGB(gr->screen->format,
-                                      gc->fore_r,
-                                      gc->fore_g,
-                                      gc->fore_b));
-#else
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b));
+#   else
     sge_FilledPolygon(gr->screen, count, vx, vy,
-                           SDL_MapRGB(gr->screen->format,
-                                      gc->fore_r,
-                                      gc->fore_g,
-                                      gc->fore_b));
-#endif
-#endif
-#else
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b));
+#   endif
+#  endif
+# else
     filledPolygonRGBA(gr->screen, vx, vy, count,
-                      gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
-#endif
+            gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+# endif
 #endif
 }
 
@@ -592,9 +572,14 @@ draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point
 static void
 draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
 {
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
+    {
+       return;
+    }
+
 #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);
+    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 > gr->screen->w)
     {
@@ -607,32 +592,32 @@ draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct poi
 
 #ifdef RASTER
     raster_rect(gr->screen, p->x, p->y, w, h,
-                SDL_MapRGBA(gr->screen->format,
-                           gc->fore_r,
-                           gc->fore_g,
-                           gc->fore_b,
-                           gc->fore_a));
+            SDL_MapRGBA(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b,
+                gc->fore_a));
 #else
-#ifdef SDL_SGE
-#ifdef ALPHA
+# ifdef SDL_SGE
+#  ifdef ALPHA
     sge_FilledRectAlpha(gr->screen, p->x, p->y, p->x + w, p->y + h,
-                        SDL_MapRGB(gr->screen->format,
-                                   gc->fore_r,
-                                   gc->fore_g,
-                                   gc->fore_b),
-                        gc->fore_a);
-#else
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b),
+            gc->fore_a);
+#  else
     /* no AA -- should use poly instead for that */
     sge_FilledRect(gr->screen, p->x, p->y, p->x + w, p->y + h,
-                        SDL_MapRGB(gr->screen->format,
-                                   gc->fore_r,
-                                   gc->fore_g,
-                                   gc->fore_b));
-#endif
-#else
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r,
+                gc->fore_g,
+                gc->fore_b));
+#  endif
+# else
     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);
-#endif
+# endif
 #endif
 
 }
@@ -640,12 +625,17 @@ draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct poi
 static void
 draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
 {
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
+    {
+       return;
+    }
+
 #if 0
-        if(gc->fore_a != 0xff)
-        {
+    if(gc->fore_a != 0xff)
+    {
         dbg(0, "%d %d %d %u %u:%u:%u:%u\n", p->x, p->y, r, gc->linewidth,
-            gc->fore_a, gc->fore_r, gc->fore_g, gc->fore_b);
-        }
+               gc->fore_a, gc->fore_r, gc->fore_g, gc->fore_b);
+    }
 #endif
 
     /* FIXME: does not quite match gtk */
@@ -657,51 +647,51 @@ draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point
     }
 
 #ifdef RASTER
-        if(gr->aa)
-        {
-            raster_aacircle(gr->screen, p->x, p->y, r,
-                            SDL_MapRGBA(gr->screen->format,
-                                       gc->fore_r,
-                                       gc->fore_g,
-                                       gc->fore_b,
-                                       gc->fore_a));
-        }
-        else
-        {
-            raster_circle(gr->screen, p->x, p->y, r,
-                          SDL_MapRGBA(gr->screen->format,
-                                     gc->fore_r,
-                                     gc->fore_g,
-                                     gc->fore_b,
-                                     gc->fore_a));
-        }
-#else
-#ifdef SDL_SGE
-#ifdef ALPHA
-        sge_FilledCircleAlpha(gr->screen, p->x, p->y, r,
-                         SDL_MapRGB(gr->screen->format,
-                                    gc->fore_r, gc->fore_g, gc->fore_b),
-                         gc->fore_a);
-#else
-#ifdef ANTI_ALIAS
-        sge_AAFilledCircle(gr->screen, p->x, p->y, r,
-                         SDL_MapRGB(gr->screen->format,
-                                    gc->fore_r, gc->fore_g, gc->fore_b));
-#else
-        sge_FilledCircle(gr->screen, p->x, p->y, r,
-                         SDL_MapRGB(gr->screen->format,
-                                    gc->fore_r, gc->fore_g, gc->fore_b));
-#endif
-#endif
-#else
-#ifdef ANTI_ALIAS
-        aacircleRGBA(gr->screen, p->x, p->y, r,
-                   gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+    if(gr->aa)
+    {
+        raster_aacircle(gr->screen, p->x, p->y, r,
+                SDL_MapRGBA(gr->screen->format,
+                    gc->fore_r,
+                    gc->fore_g,
+                    gc->fore_b,
+                    gc->fore_a));
+    }
+    else
+    {
+        raster_circle(gr->screen, p->x, p->y, r,
+                SDL_MapRGBA(gr->screen->format,
+                    gc->fore_r,
+                    gc->fore_g,
+                    gc->fore_b,
+                    gc->fore_a));
+    }
 #else
-        filledCircleRGBA(gr->screen, p->x, p->y, r,
-                         gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
-#endif
-#endif
+# ifdef SDL_SGE
+#  ifdef ALPHA
+    sge_FilledCircleAlpha(gr->screen, p->x, p->y, r,
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r, gc->fore_g, gc->fore_b),
+            gc->fore_a);
+#  else
+#   ifdef ANTI_ALIAS
+    sge_AAFilledCircle(gr->screen, p->x, p->y, r,
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r, gc->fore_g, gc->fore_b));
+#   else
+    sge_FilledCircle(gr->screen, p->x, p->y, r,
+            SDL_MapRGB(gr->screen->format,
+                gc->fore_r, gc->fore_g, gc->fore_b));
+#   endif
+#  endif
+# else
+#  ifdef ANTI_ALIAS
+    aacircleRGBA(gr->screen, p->x, p->y, r,
+            gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#  else
+    filledCircleRGBA(gr->screen, p->x, p->y, r,
+            gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#  endif
+# endif
 #endif
 }
 
@@ -709,11 +699,16 @@ draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point
 static void
 draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
 {
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
+    {
+       return;
+    }
+
     /* 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;
 
@@ -752,19 +747,19 @@ draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *
 
 #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);
+                    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);
+                    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
-    */
+       this could be 100% integer code pretty easily,
+       except that i am lazy
+       */
     struct point vert[4];
     int lw = gc->linewidth;
     //int lw = 1;
@@ -772,12 +767,12 @@ draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *
 
     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;
+       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;
+       float cx=(p[i+1].x+p[i].x)/2;
+       float cy=(p[i+1].y+p[i].y)/2;
 #endif
 
         float angle;
@@ -790,48 +785,48 @@ draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *
             if(gr->aa)
             {
                 raster_aaline(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
-                         SDL_MapRGBA(gr->screen->format,
-                                    gc->fore_r,
-                                    gc->fore_g,
-                                    gc->fore_b,
-                                    gc->fore_a));
+                        SDL_MapRGBA(gr->screen->format,
+                            gc->fore_r,
+                            gc->fore_g,
+                            gc->fore_b,
+                            gc->fore_a));
             }
             else
             {
                 raster_line(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
-                         SDL_MapRGBA(gr->screen->format,
-                                    gc->fore_r,
-                                    gc->fore_g,
-                                    gc->fore_b,
-                                    gc->fore_a));
+                        SDL_MapRGBA(gr->screen->format,
+                            gc->fore_r,
+                            gc->fore_g,
+                            gc->fore_b,
+                            gc->fore_a));
             }
 #else
-#ifdef SDL_SGE
-#ifdef ALPHA
+# ifdef SDL_SGE
+#  ifdef ALPHA
             sge_LineAlpha(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
-                     SDL_MapRGB(gr->screen->format,
-                                gc->fore_r, gc->fore_g, gc->fore_b),
-                     gc->fore_a);
-#else
-#ifdef ANTI_ALIAS
+                    SDL_MapRGB(gr->screen->format,
+                        gc->fore_r, gc->fore_g, gc->fore_b),
+                    gc->fore_a);
+#  else
+#   ifdef ANTI_ALIAS
             sge_AALine(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
-                     SDL_MapRGB(gr->screen->format,
-                                gc->fore_r, gc->fore_g, gc->fore_b));
-#else
+                    SDL_MapRGB(gr->screen->format,
+                        gc->fore_r, gc->fore_g, gc->fore_b));
+#   else
             sge_Line(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
-                     SDL_MapRGB(gr->screen->format,
-                                gc->fore_r, gc->fore_g, gc->fore_b));
-#endif
-#endif
-#else
-#ifdef ANTI_ALIAS
+                    SDL_MapRGB(gr->screen->format,
+                        gc->fore_r, gc->fore_g, gc->fore_b));
+#   endif
+#  endif
+# else
+#  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
+                    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
-#endif
+                    gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
+#  endif
+# endif
 #endif
         }
         else
@@ -901,11 +896,11 @@ draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *
             /* 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 */ 
+            /* now some circular endcaps, if the width is over 2 */
             if(lw > 2)
             {
                 if(i == 0)
@@ -921,553 +916,283 @@ draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *
 }
 
 
-#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)
+set_pixel(SDL_Surface *surface, int x, int y, Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2)
 {
-    SDL_Surface *ss;
-    SDL_Color f, b;
-    SDL_Rect r;
+    if(x<0 || y<0 || x>=surface->w || y>=surface->h) {
+       return;
+    }
 
-#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
+    void *target_pixel = ((Uint8*)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel);
 
-    /* TODO: dx + dy? */
+    Uint8 r1,g1,b1,a1;
 
-    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);
+    switch(surface->format->BytesPerPixel) {
+       case 2:
+           {
+               SDL_GetRGBA(*(Uint16 *)target_pixel, surface->format, &r1, &g1, &b1, &a1);
+               *(Uint16 *)target_pixel = SDL_MapRGBA(surface->format,
+                       (r1*(0xff-a2)/0xff) + (r2*a2/0xff),
+                       (g1*(0xff-a2)/0xff) + (g2*a2/0xff),
+                       (b1*(0xff-a2)/0xff) + (b2*a2/0xff),
+                       a2 + a1*(0xff-a2)/0xff );
+               break;
+           }
+       case 4:
+           {
+               SDL_GetRGBA(*(Uint32 *)target_pixel, surface->format, &r1, &g1, &b1, &a1);
+               *(Uint32 *)target_pixel = SDL_MapRGBA(surface->format,
+                       (r1*(0xff-a2)/0xff) + (r2*a2/0xff),
+                       (g1*(0xff-a2)/0xff) + (g2*a2/0xff),
+                       (b1*(0xff-a2)/0xff) + (b2*a2/0xff),
+                       a2 + a1*(0xff-a2)/0xff );
+               break;
+           }
     }
 }
-#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];
-};
 
-static unsigned char *
-display_text_render_shadow(struct text_glyph *g)
+static void
+resize_ft_buffer (unsigned int new_size)
 {
-       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));
-       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;
+    if (new_size > ft_buffer_size) {
+       g_free (ft_buffer);
+       ft_buffer = g_malloc (new_size);
+       dbg(1, "old_size(%i) new_size(%i) ft_buffer(%i)\n", ft_buffer_size, new_size, ft_buffer);
+       ft_buffer_size = new_size;
+    }
 }
 
-
-static struct text_render *
-display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y)
+static void
+display_text_draw(struct font_freetype_text *text,
+                 struct graphics_priv *gr, struct graphics_gc_priv *fg,
+                 struct graphics_gc_priv *bg, int color, struct point *p)
 {
-               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 );
+    int i, x, y, stride;
+    struct font_freetype_glyph *g, **gp;
+    struct color transparent = { 0x0000, 0x0000, 0x0000, 0x0000 };
+    struct color black = { fg->fore_r * 255, fg->fore_g * 255, 
+       fg->fore_b * 255, fg->fore_a * 255 };
+    struct color white = { 0xffff, 0xffff, 0xffff, 0xffff };
+
+    if (bg) {
+       if (COLOR_IS_WHITE(black) && COLOR_IS_BLACK(white)) {
+           black.r = 65535;
+           black.g = 65535;
+           black.b = 65535;
+           black.a = 65535;
+
+           white.r = 0;
+           white.g = 0;
+           white.b = 0;
+           white.a = 65535;
+       } else if (COLOR_IS_BLACK(black) && COLOR_IS_WHITE(white)) {
+           white.r = 65535;
+           white.g = 65535;
+           white.b = 65535;
+           white.a = 65535;
+
+           black.r = 0;
+           black.g = 0;
+           black.b = 0;
+           black.a = 65535;
+       } else {
+           white.r = bg->fore_r * 255;
+           white.g = bg->fore_g * 255;
+           white.b = bg->fore_b * 255;
+           white.a = bg->fore_a * 255;
+       }
+    } else {
+       white.r = 0;
+       white.g = 0;
+       white.b = 0;
+       white.a = 0;
+    }
 
-               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);
+    gp = text->glyph;
+    i = text->glyph_count;
+    x = p->x << 6;
+    y = p->y << 6;
+    while (i-- > 0) {
+       g = *gp++;
+       if (g->w && g->h && bg) {
+           stride = (g->w + 2) * 4;
+           if (color) {
+               resize_ft_buffer(stride * (g->h + 2));
+               gr->freetype_methods.get_shadow(g, ft_buffer, 32, stride, &white, &transparent);
+
+               SDL_Surface *glyph_surface =
+                   SDL_CreateRGBSurfaceFrom(ft_buffer, g->w + 2, g->h + 2,
+                           32,
+                           stride,
+                           0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+               if (glyph_surface) {
+                   SDL_Rect r;
+                   r.x = (x + g->x) >> 6;
+                   r.y = (y + g->y) >> 6;
+                   r.w = g->w + 2;
+                   r.h = g->h + 2;
+
+                   SDL_BlitSurface(glyph_surface, NULL, gr->screen, &r);
+                   SDL_FreeSurface(glyph_surface);
                }
-               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;
-}
+       x += g->dx;
+       y += g->dy;
+    }
 
-#if 0
-static void hexdump(unsigned char *buf, unsigned int w, unsigned int h)
-{
-    int x, y;
-    printf("hexdump %u %u\n", w, h);
-    for(y = 0; y < h; y++)
-    {
-        for(x = 0; x < w; x++)
-        {
-            printf("%02x ", buf[y*w+x]);
-        }
-        printf("\n");
+    gp = text->glyph;
+    i = text->glyph_count;
+    x = p->x << 6;
+    y = p->y << 6;
+    while (i-- > 0) {
+       g = *gp++;
+       if (g->w && g->h) {
+           if (color) {
+               stride = g->w;
+               if (bg) {
+                   resize_ft_buffer(stride * g->h * 4);
+                   gr->freetype_methods.get_glyph(g, ft_buffer, 32,
+                           stride * 4, &black,
+                           &white, &transparent);
+                   SDL_Surface *glyph_surface =
+                       SDL_CreateRGBSurfaceFrom(ft_buffer, g->w, g->h, 32,
+                               stride * 4,
+                               0x000000ff,0x0000ff00, 0x00ff0000,0xff000000);
+                   if (glyph_surface) {
+                       SDL_Rect r;
+                       r.x = (x + g->x) >> 6;
+                       r.y = (y + g->y) >> 6;
+                       r.w = g->w;
+                       r.h = g->h;
+
+                       SDL_BlitSurface(glyph_surface, NULL, gr->screen,&r);
+                       SDL_FreeSurface(glyph_surface);
+                   }
+               }
+               stride *= 4;
+               resize_ft_buffer(stride * g->h);
+               gr->freetype_methods.get_glyph(g, ft_buffer, 32, stride,
+                       &black, &white,
+                       &transparent);
+               int ii, jj;
+               unsigned char* pGlyph = ft_buffer;
+               for (jj = 0; jj < g->h; ++jj) {
+                   for (ii = 0; ii < g->w; ++ii) {
+                       if(*(pGlyph+3) > 0) {
+                            set_pixel(gr->screen,
+                                   ii+((x + g->x) >> 6),
+                                   jj+((y + g->y) >> 6),
+                                    *(pGlyph+2),                       // Pixels are in BGRA format
+                                    *(pGlyph+1),
+                                    *(pGlyph+0),
+                                    *(pGlyph+3)
+                                    );
+                        }
+                        pGlyph += 4;
+                   }
+               }
+           }
+       }
+       x += g->dx;
+       y += g->dy;
     }
 }
 
-static void bitdump(unsigned char *buf, unsigned int w, unsigned int h)
+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)
 {
-    int x, pos;
-    printf("bitdump %u %u\n", w, h);
-    pos = 0;
-    for(x = 0; x < h * w; x++)
-    {
-        if(buf[pos] & (1 << (x&0x7)))
-        {
-            printf("00 ");
-        }
-        else
-        {
-            printf("ff ");
-        }
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable)
+           || (gr->overlay_parent && gr->overlay_parent->overlay_enable
+               && !gr->overlay_enable)) {
+       return;
+    }
 
-        if((x & 0x7) == 0x7)
-        {
-            pos++;
-        }
+    struct font_freetype_text *t;
+    int color = 1;
 
-        if((x % w) == (w-1))
-        {
-            printf("\n");
-        }
+    if (!font) {
+       dbg(0, "no font, returning\n");
+       return;
     }
-    printf("\n");
-}
-#endif
+    t = gr->freetype_methods.text_new(text,
+           (struct font_freetype_font *) font,
+           dx, dy);
 
-#if 0
-static void sdl_inv_grayscale_pal_set(SDL_Surface *ss)
-{
-    SDL_Color c;
-    int i;
+    struct point p_eff;
+    p_eff.x = p->x;
+    p_eff.y = p->y;
 
-    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); 
-    }
+    display_text_draw(t, gr, fg, bg, color, &p_eff);
+    gr->freetype_methods.text_destroy(t);
 }
 
-static void sdl_scale_pal_set(SDL_Surface *ss, Uint8 r, Uint8 g, Uint8 b)
+static void
+draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
 {
-    SDL_Color c;
-    int i;
-
-    for(i = 0; i < 256; i++)
+    if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
     {
-        c.r = (i * r) / 256;
-        c.g = (i * g) / 256;
-        c.b = (i * b) / 256;
-        SDL_SetPalette(ss, SDL_LOGPAL, &c, i, 1); 
+       return;
     }
-}
+
+#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
+}
 
-#if 0
-static void sdl_fixed_pal_set(SDL_Surface *ss, Uint8 r, Uint8 g, Uint8 b)
+static void
+draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
 {
-    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); 
-    }
+    /* 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
-display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg)
+background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
 {
-    int i, x, y, poff, soff, col_lev;
-    struct text_glyph *gly, **gp;
-    Uint32 pix;
-    Uint8 r, g, b, a;
+#ifdef DEBUG
+    printf("background_gc\n");
+#endif
+}
 
-#if 0
-    dbg(0,"%u %u %u %u, %u %u %u %u\n",
-        fg->fore_a, fg->fore_r, fg->fore_g, fg->fore_b,
-        fg->back_a, fg->back_r, fg->back_g, fg->back_b);
 
-    dbg(0,"%u %u %u %u, %u %u %u %u\n",
-        bg->fore_a, bg->fore_r, bg->fore_g, bg->fore_b,
-        bg->back_a, bg->back_r, bg->back_g, bg->back_b);
+static void
+draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
+{
+#ifdef PROFILE
+    struct timeval now;
+    unsigned long elapsed;
 #endif
-    
-    if(bg)
+    struct graphics_priv *ov;
+    SDL_Rect rect;
+    int i;
+
+    if(gr->overlay_mode)
     {
-        col_lev = bg->fore_r + bg->fore_g + bg->fore_b;
+        /* will be drawn below */
     }
     else
     {
-        col_lev = 0;
-    }
-
-    /* TODO: lock/unlock in draw_mode() to reduce overhead */
-    SDL_LockSurface(gr->screen);
-       gp=text->glyph;
-       i=text->glyph_count;
-       while (i-- > 0)
-       {
-               gly=*gp++;
-               if (gly->w && gly->h)
-        {
-#if 0
-            if(gly->shadow && bg)
-            {
-                hexdump(gly->pixmap, gly->w, gly->h);
-                bitdump(gly->shadow, gly->w+2, gly->h+2);    
-            }
-#endif
-
-            for(y = 0; y < gly->h + 2; y++)
-            {
-                if(gly->y - 1 + y < 0)
-                {
-                    continue;
-                }
-
-                if(((gly->y-1) + y) >= gr->screen->h)
-                {
-                    break;
-                }
-
-                for(x = 0; x < gly->w + 2; x++)
-                {
-                    if(gly->x - 1 + x < 0)
-                    {
-                        continue;
-                    }
-
-                    if(((gly->x-1) + x) >= gr->screen->w)
-                    {
-                        break;
-                    }
-
-                    poff = gr->screen->w * ((gly->y-1) + y) + ((gly->x-1) + x);
-                    poff = poff * gr->screen->format->BytesPerPixel;
-
-                    switch(gr->screen->format->BytesPerPixel)
-                    {
-                        case 2:
-                        {
-                            pix = *(Uint16 *)((Uint8*)gr->screen->pixels + poff);
-                            break;
-                        }
-                        case 4:
-                        {
-                            pix = *(Uint32 *)((Uint8*)gr->screen->pixels + poff);
-                            break;
-                        }
-                        default:
-                        {
-                            pix = 0;
-                            break;
-                        }
-                    }
-
-                    SDL_GetRGBA(pix,
-                               gr->screen->format,
-                               &r,
-                               &g,
-                               &b,
-                               &a);
-
-#ifdef DEBUG
-                    printf("%u %u -> %u off\n",
-                           gly->x,
-                           gly->y,
-                           off);
-
-                    printf("%u,%u: %u %u %u in\n",
-                           x, y,
-                           r, g, b, off);
-#endif
-
-
-
-                    if(gly->shadow && bg)
-                    {
-                        soff = (8 * ((gly->w+9)/8) * y) + x;
-                        pix = gly->shadow[soff/8];
-
-                        if(pix & (1 << (7-(soff&0x7))))
-                        {
-                            if(col_lev >= 3*0x80)
-                            {
-                                r = bg->fore_r;
-                                g = bg->fore_g;
-                                b = bg->fore_b;
-                                a = bg->fore_a;
-                            }
-                            else
-                            {
-                                r &= ~bg->fore_r;
-                                g &= ~bg->fore_g;
-                                b &= ~bg->fore_b;
-                                a &= ~bg->fore_a;
-                            }
-                        }
-                    }
-
-                    /* glyph */
-                    if((x > 0) && (x <= gly->w) &&
-                       (y > 0) && (y <= gly->h))
-                    {
-                        if(bg && (col_lev >= 3*0x80))
-                        {
-                            r &= ~gly->pixmap[gly->w * (y-1) + (x-1)];
-                            g &= ~gly->pixmap[gly->w * (y-1) + (x-1)];
-                            b &= ~gly->pixmap[gly->w * (y-1) + (x-1)];
-                        }
-                        else
-                        {
-                            r |= gly->pixmap[gly->w * (y-1) + (x-1)];
-                            g |= gly->pixmap[gly->w * (y-1) + (x-1)];
-                            b |= gly->pixmap[gly->w * (y-1) + (x-1)];
-                        }
-                    }
-
-#ifdef DEBUG
-                    printf("%u,%u: %u %u %u out\n",
-                           x, y,
-                           r, g, b);
-#endif
-
-                    pix = SDL_MapRGBA(gr->screen->format,
-                                     r,
-                                     g,
-                                     b,
-                                     a);
-
-                    switch(gr->screen->format->BytesPerPixel)
-                    {
-                        case 2:
-                        {
-                            *(Uint16 *)((Uint8*)gr->screen->pixels + poff) = pix;
-                            break;
-                        }
-                        case 4:
-                        {
-                            *(Uint32 *)((Uint8*)gr->screen->pixels + poff) = pix;
-                            break;
-                        }
-                        default:
-                        {
-                            break;
-                        }
-                    }
-                }
-            }
-
-            //dbg(0, "glyph %d %d %d %d\n", g->x, g->y, g->w, g->h);
-        }
-       }
-    SDL_UnlockSurface(gr->screen);
-}
-
-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)
-{
-#ifdef PROFILE
-    struct timeval now;
-    unsigned long elapsed;
-#endif
-    struct graphics_priv *ov;
-    SDL_Rect rect;
-    int i;
-
-    if(gr->overlay_mode)
-    {
-        /* will be drawn below */
-    }
-    else
-    {
-#ifdef DEBUG
-        printf("draw_mode: %d\n", mode);
+#ifdef DEBUG
+        printf("draw_mode: %d\n", mode);
 #endif
 
 #ifdef PROFILE
@@ -1484,7 +1209,7 @@ draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
                 for(i = 0; i < OVERLAY_MAX; i++)
                 {
                     ov = gr->overlay_array[i];
-                    if(ov)
+                    if(ov && ov->overlay_enable)
                     {
                         rect.x = ov->overlay_x;
                         if(rect.x<0) rect.x += gr->screen->w;
@@ -1519,6 +1244,11 @@ draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
 static void overlay_disable(struct graphics_priv *gr, int disable)
 {
     gr->overlay_enable = !disable;
+    struct graphics_priv *curr_gr = gr;
+    if(gr->overlay_parent) {
+       curr_gr = gr->overlay_parent;
+    }
+    draw_mode(curr_gr,draw_mode_end);
 }
 
 static struct graphics_priv *
@@ -1526,151 +1256,169 @@ overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct poin
 
 static int window_fullscreen(struct window *win, int on)
 {
-       struct graphics_priv *gr=(struct graphics_priv *)win->priv;
+    struct graphics_priv *gr=(struct graphics_priv *)win->priv;
 
-       /* Update video flags */
-       if(on) {
-               gr->video_flags |= SDL_FULLSCREEN;
-       } else {
-               gr->video_flags &= ~SDL_FULLSCREEN;
-       }
+    /* Update video flags */
+    if(on) {
+       gr->video_flags |= SDL_FULLSCREEN;
+    } else {
+       gr->video_flags &= ~SDL_FULLSCREEN;
+    }
 
-       /* Update video mode */
-       gr->screen = SDL_SetVideoMode(gr->screen->w, gr->screen->h, gr->video_bpp, gr->video_flags);
-       if(gr->screen == NULL) {
-               navit_destroy(gr->nav);
-       } 
-       else {
-               callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
-       }
-       return 1;
+    /* Update video mode */
+    gr->screen = SDL_SetVideoMode(gr->screen->w, gr->screen->h, gr->video_bpp, gr->video_flags);
+    if(gr->screen == NULL) {
+       navit_destroy(gr->nav);
+    }
+    else {
+       callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
+    }
+    return 1;
 }
 
 static void *
-get_data(struct graphics_priv *this, char *type)
+get_data(struct graphics_priv *this, char const *type)
 {
-       if(strcmp(type, "window") == 0) {
-               struct window *win;
-               win=g_new(struct window, 1);
-               win->priv=this;
-               win->fullscreen=window_fullscreen;
-               win->disable_suspend=NULL;
-               return win;
-       } else {
-               return &dummy;
-       }
+    if(strcmp(type, "window") == 0) {
+       struct window *win;
+       win=g_new(struct window, 1);
+       win->priv=this;
+       win->fullscreen=window_fullscreen;
+       win->disable_suspend=NULL;
+       return win;
+    } else {
+       return &dummy;
+    }
 }
 
 static void draw_drag(struct graphics_priv *gr, struct point *p)
 {
-       if(p) {
-           gr->overlay_x = p->x;
-           gr->overlay_y = p->y;
-       }
+    if(p) {
+       gr->overlay_x = p->x;
+       gr->overlay_y = p->y;
+    }
 }
 
 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,
-       draw_drag,
-       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,
-       overlay_disable,
-//     register_keypress_callback
+    graphics_destroy,
+    draw_mode,
+    draw_lines,
+    draw_polygon,
+    draw_rectangle,
+    NULL /*draw_circle*/,
+    draw_text,
+    draw_image,
+    draw_image_warp,
+    draw_restore,
+    draw_drag,
+    NULL,
+    gc_new,
+    background_gc,
+    overlay_new,
+    image_new,
+    get_data,
+    image_free,
+    get_text_bbox,
+    overlay_disable,
 };
 
 static struct graphics_priv *
 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h,int alpha, int wraparound)
 {
-       struct graphics_priv *ov;
-       Uint32 rmask, gmask, bmask, amask;
-       int i;
+    struct graphics_priv *ov;
+    Uint32 rmask, gmask, bmask, amask;
+    int i;
 
-       for(i = 0; i < OVERLAY_MAX; i++)
-       {
-               if(gr->overlay_array[i] == NULL)
-               {
-                       break;
-               }
-       }
-       if(i == OVERLAY_MAX)
+    for(i = 0; i < OVERLAY_MAX; i++)
+    {
+       if(gr->overlay_array[i] == NULL)
        {
-               dbg(0, "too many overlays! increase OVERLAY_MAX\n");
-               return NULL;
+           break;
        }
+    }
+    if(i == OVERLAY_MAX)
+    {
+       dbg(0, "too many overlays! increase OVERLAY_MAX\n");
+       return NULL;
+    }
 
-       dbg(1, "overlay_new %d %d %d %u %u (%x, %x, %x ,%x, %d)\n", i,
-                       p->x,
-                       p->y,
-                       w,
-                       h,
-                       gr->screen->format->Rmask,
-                       gr->screen->format->Gmask,
-                       gr->screen->format->Bmask,
-                       gr->screen->format->Amask,
-                       gr->screen->format->BitsPerPixel
-          );
-
-       ov = g_new0(struct graphics_priv, 1);
-
-       switch(gr->screen->format->BitsPerPixel) {
+    dbg(1, "overlay_new %d %d %d %u %u (%x, %x, %x ,%x, %d)\n", i,
+           p->x,
+           p->y,
+           w,
+           h,
+           gr->screen->format->Rmask,
+           gr->screen->format->Gmask,
+           gr->screen->format->Bmask,
+           gr->screen->format->Amask,
+           gr->screen->format->BitsPerPixel
+       );
+
+    ov = g_new0(struct graphics_priv, 1);
+
+    switch(gr->screen->format->BitsPerPixel) {
        case 8:
-               rmask = 0xc0;
-               gmask = 0x30;
-               bmask = 0x0c;
-               amask = 0x03;
-               break;
+           rmask = 0xc0;
+           gmask = 0x30;
+           bmask = 0x0c;
+           amask = 0x03;
+           break;
        case 16:
-               rmask = 0xf000;
-               gmask = 0x0f00;
-               bmask = 0x00f0;
-               amask = 0x000f;
-               break;
+           rmask = 0xf000;
+           gmask = 0x0f00;
+           bmask = 0x00f0;
+           amask = 0x000f;
+           break;
        case 32:
-               rmask = 0xff000000;
-               gmask = 0x00ff0000;
-               bmask = 0x0000ff00;
-               amask = 0x000000ff;
-               break;
+           rmask = 0xff000000;
+           gmask = 0x00ff0000;
+           bmask = 0x0000ff00;
+           amask = 0x000000ff;
+           break;
        default:
-               rmask = gr->screen->format->Rmask;
-               gmask = gr->screen->format->Gmask;
-               bmask = gr->screen->format->Bmask;
-               amask = gr->screen->format->Amask;
-       }
+           rmask = gr->screen->format->Rmask;
+           gmask = gr->screen->format->Gmask;
+           bmask = gr->screen->format->Bmask;
+           amask = gr->screen->format->Amask;
+    }
+
+    ov->screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
+           w, h,
+           gr->screen->format->BitsPerPixel,
+           rmask, gmask, bmask, amask);
+
+    ov->overlay_mode = 1;
+    ov->overlay_enable = 1;
+    ov->overlay_x = p->x;
+    ov->overlay_y = p->y;
+    ov->overlay_parent = gr;
+    ov->overlay_idx = i;
+    gr->overlay_array[i] = ov;
+
+
+    struct font_priv *(*font_freetype_new) (void *meth);
+    font_freetype_new = plugin_get_font_type ("freetype");
+
+    if (!font_freetype_new)
+    {
+       return NULL;
+    }
+
+
+    font_freetype_new (&ov->freetype_methods);
+
+    *meth=graphics_methods;
+
+    meth->font_new =
+       (struct graphics_font_priv *
+        (*)(struct graphics_priv *, struct graphics_font_methods *, char *, int,
+            int)) ov->freetype_methods.font_new;
+    meth->get_text_bbox = (void *)ov->freetype_methods.get_text_bbox;
+
+
 
-       ov->screen = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, 
-                       w, h,
-                       gr->screen->format->BitsPerPixel,
-                       rmask, gmask, bmask, amask);
-
-       ov->overlay_mode = 1;
-       ov->overlay_enable = 1;
-       ov->overlay_x = p->x;
-       ov->overlay_y = p->y;
-       ov->overlay_parent = gr;
-       ov->overlay_idx = i;
-       gr->overlay_array[i] = ov;
-       *meth=graphics_methods;
-
-       return ov;
+
+    return ov;
 }
 
 
@@ -1714,15 +1462,15 @@ static int input_ts_init(struct graphics_priv *gr)
             {
 #if 1
                 printf("bustype %04x vendor %04x product %04x version %04x\n",
-                       ii.bustype,
-                       ii.vendor,
-                       ii.product,
-                       ii.version);
+                               ii.bustype,
+                               ii.vendor,
+                               ii.product,
+                               ii.version);
 #endif
 
                 if((ii.bustype == BUS_USB) &&
-                   (ii.vendor == 0x0eef) &&
-                   (ii.product == 0x0001))
+                       (ii.vendor == 0x0eef) &&
+                       (ii.product == 0x0001))
                 {
                     ret = fcntl(fd, F_SETFL, O_NONBLOCK);
                     if(ret == 0)
@@ -1767,8 +1515,8 @@ static void input_ts_map(int *disp_x, int *disp_y,
        bot right =   63,1872
 
        calibrate your TS using input_event_dump
-       and touching all four corners. use the most extreme values. 
-    */
+       and touching all four corners. use the most extreme values.
+       */
 
 #define INPUT_TS_LEFT 1978
 #define INPUT_TS_RIGHT  48
@@ -1803,7 +1551,7 @@ static void input_ts_map(int *disp_x, int *disp_y,
     ts_y = ts_y - INPUT_TS_TOP;
 
     *disp_y = ((DISPLAY_H-1) * ts_y) / (INPUT_TS_BOT - INPUT_TS_TOP);
-/*  *disp_y = (DISPLAY_H-1) - *disp_y; */
+/*    *disp_y = (DISPLAY_H-1) - *disp_y; */
 }
 
 #if 0
@@ -1832,6 +1580,63 @@ static int input_ts_exit(struct graphics_priv *gr)
 }
 #endif
 
+#ifdef USE_WEBOS_ACCELEROMETER
+static void
+sdl_accelerometer_handler(void* param)
+{
+    struct graphics_priv *gr = (struct graphics_priv *)param;
+    int xAxis = SDL_JoystickGetAxis(gr->accelerometer, 0);
+    int yAxis = SDL_JoystickGetAxis(gr->accelerometer, 1);
+    int zAxis = SDL_JoystickGetAxis(gr->accelerometer, 2);
+    unsigned char new_orientation;
+
+    dbg(2,"x(%d) y(%d) z(%d) c(%d)\n",xAxis, yAxis, zAxis, sdl_orientation_count);
+
+    if (zAxis > -30000) {
+       if (xAxis < -15000 && yAxis > -5000 && yAxis < 5000)
+           new_orientation = WEBOS_ORIENTATION_LANDSCAPE;
+       else if (yAxis > 15000 && xAxis > -5000 && xAxis < 5000)
+           new_orientation = WEBOS_ORIENTATION_PORTRAIT;
+       else
+           return;
+    }
+    else
+       return;
+
+    if (new_orientation == sdl_next_orientation) {
+       if (sdl_orientation_count < 3) sdl_orientation_count++;
+    }
+    else {
+       sdl_orientation_count = 0;
+       sdl_next_orientation = new_orientation;
+       return;
+    }
+
+
+    if (sdl_orientation_count == 3 || sdl_next_orientation == 0)
+    {
+       sdl_orientation_count++;
+
+       if (new_orientation != gr->orientation) {
+           dbg(1,"x(%d) y(%d) z(%d) o(%d)\n",xAxis, yAxis, zAxis, new_orientation);
+           gr->orientation = new_orientation;
+
+           SDL_Event event;
+           SDL_UserEvent userevent;
+
+           userevent.type = SDL_USEREVENT;
+           userevent.code = SDL_USEREVENT_CODE_ROTATE;
+           userevent.data1 = NULL;
+           userevent.data2 = NULL;
+
+           event.type = SDL_USEREVENT;
+           event.user = userevent;
+
+           SDL_PushEvent (&event);
+       }
+    }
+}
+#endif
 
 static gboolean graphics_sdl_idle(void *data)
 {
@@ -1842,15 +1647,28 @@ static gboolean graphics_sdl_idle(void *data)
     struct input_event ie;
     ssize_t ss;
 #endif
-    int ret, key;
-    char keybuf[2];
+    int ret;
+    char key_mod = 0;
+    char keybuf[8];
+
+#ifdef USE_WEBOS
+    if(data==NULL) {
+       if(the_graphics!=NULL) {
+           gr = the_graphics;
+       }
+       else {
+           dbg(0,"graphics_idle: graphics not set!\n");
+           return FALSE;
+       }
+    }
+#endif
 
     /* generate the initial resize callback, so the gui knows W/H
 
        its unsafe to do this directly inside register_resize_callback;
        graphics_gtk does it during Configure, but SDL does not have
        an equivalent event, so we use our own flag
-    */
+       */
     if(gr->resize_callback_initial != 0)
     {
         callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
@@ -1864,234 +1682,440 @@ static gboolean graphics_sdl_idle(void *data)
         if(ss == sizeof(ie))
         {
             /* we (usually) get three events on a touchscreen hit:
-              1: type =EV_KEY
-                 code =330 [BTN_TOUCH]
-                 value=1
+              1: type =EV_KEY
+              code =330 [BTN_TOUCH]
+              value=1
 
-              2: type =EV_ABS
-                 code =0 [X]
-                 value=X pos
+              2: type =EV_ABS
+              code =0 [X]
+              value=X pos
 
-              3: type =EV_ABS
-                 code =1 [Y]
-                 value=Y pos
+              3: type =EV_ABS
+              code =1 [Y]
+              value=Y pos
 
-              4: type =EV_SYN
+              4: type =EV_SYN
 
-              once hit, if the contact point changes, we'll get more 
-              EV_ABS (for 1 or both axes), followed by an EV_SYN.
+              once hit, if the contact point changes, we'll get more
+              EV_ABS (for 1 or both axes), followed by an EV_SYN.
 
-              and, on a lift:
+              and, on a lift:
 
-              5: type =EV_KEY
-                 code =330 [BTN_TOUCH]
-                 value=0
+              5: type =EV_KEY
+              code =330 [BTN_TOUCH]
+              value=0
 
-              6: type =EV_SYN
-            */
+              6: type =EV_SYN
+           */
             switch(ie.type)
             {
                 case EV_KEY:
-                {
-                    if(ie.code == BTN_TOUCH)
                     {
-                        gr->ts_hit = ie.value;
-                    }
+                       if(ie.code == BTN_TOUCH)
+                       {
+                            gr->ts_hit = ie.value;
+                       }
 
-                    break;
-                }
+                       break;
+                    }
 
                 case EV_ABS:
-                {
-                    if(ie.code == 0)
                     {
-                        gr->ts_x = ie.value;
+                       if(ie.code == 0)
+                       {
+                            gr->ts_x = ie.value;
+                       }
+                       else if(ie.code == 1)
+                       {
+                            gr->ts_y = ie.value;
+                       }
+
+                       break;
                     }
-                    else if(ie.code == 1)
-                    {
-                        gr->ts_y = ie.value;
-                    }
-
-                    break;
-                }
 
                 case EV_SYN:
-                {
-                    input_ts_map(&p.x, &p.y, gr->ts_x, gr->ts_y);
-
-                    /* always send MOUSE_MOTION (first) */
-                   callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p); 
-                    if(gr->ts_hit > 0)
-                    {
-                       callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)SDL_BUTTON_LEFT, (void *)&p); 
-                    }
-                    else if(gr->ts_hit == 0)
                     {
-                       callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)SDL_BUTTON_LEFT, (void *)&p); 
+                       input_ts_map(&p.x, &p.y, gr->ts_x, gr->ts_y);
+
+                       /* always send MOUSE_MOTION (first) */
+                       callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p);
+                       if(gr->ts_hit > 0)
+                       {
+                           callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)SDL_BUTTON_LEFT, (void *)&p);
+                       }
+                       else if(gr->ts_hit == 0)
+                       {
+                           callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)SDL_BUTTON_LEFT, (void *)&p);
+                       }
+
+                       /* reset ts_hit */
+                       gr->ts_hit = -1;
+
+                       break;
                     }
 
-                    /* reset ts_hit */
-                    gr->ts_hit = -1;
-
-                    break;
-                }
-
                 default:
-                {
-                    break;
-                }
+                    {
+                       break;
+                    }
             }
         }
     }
 #endif
 
+#ifdef USE_WEBOS_ACCELEROMETER
+    struct callback* accel_cb = NULL;
+    struct event_timeout* accel_to = NULL;
+    if (PDL_GetPDKVersion() > 100) {
+       accel_cb = callback_new_1(callback_cast(sdl_accelerometer_handler), gr);
+       accel_to = event_add_timeout(200, 1, accel_cb);
+    }
+#endif
+#ifdef USE_WEBOS
+    unsigned int idle_tasks_idx=0;
+    unsigned int idle_tasks_cur_priority=0;
+    struct idle_task *task;
+
+    while(!quit_event_loop)
+#else
     while(1)
+#endif
     {
-        ret = SDL_PollEvent(&ev);
-        if(ret == 0)
-        {
-            break;
-        }
+#ifdef USE_WEBOS
+       ret = 0;
+       if(idle_tasks->len > 0)
+       {
+           while (!(ret = SDL_PollEvent(&ev)) && idle_tasks->len > 0)
+           {
+               if (idle_tasks_idx >= idle_tasks->len)
+                   idle_tasks_idx = 0;
+
+               dbg(3,"idle_tasks_idx(%d)\n",idle_tasks_idx);
+               task = (struct idle_task *)g_ptr_array_index(idle_tasks,idle_tasks_idx);
+
+               if (idle_tasks_idx == 0)        // only execute tasks with lowest priority value
+                   idle_tasks_cur_priority = task->priority;
+               if (task->priority > idle_tasks_cur_priority)
+                   idle_tasks_idx = 0;
+               else
+               {
+                   callback_call_0(task->cb);
+                   idle_tasks_idx++;
+               }
+           }
+       }
+       if (!ret)       // If we get here there are no idle_tasks and we have no events pending
+           ret = SDL_WaitEvent(&ev);
+#else
+       ret = SDL_PollEvent(&ev);
+#endif
+       if(ret == 0)
+       {
+           break;
+       }
 
-        switch(ev.type)
-        {
-            case SDL_MOUSEMOTION:
-            {
-                p.x = ev.motion.x;
-                p.y = ev.motion.y;
-               callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p); 
-                break;
-            }
+#ifdef USE_WEBOS
+       dbg(5,"SDL_Event %d\n", ev.type);
+#endif
+       switch(ev.type)
+       {
+           case SDL_MOUSEMOTION:
+               {
+                   p.x = ev.motion.x;
+                   p.y = ev.motion.y;
+                   callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p);
+                   break;
+               }
 
-            case SDL_KEYDOWN:
-            {
-                switch(ev.key.keysym.sym)
-                {
-                    case SDLK_LEFT:
-                    {
-                        key = NAVIT_KEY_LEFT;
-                        break;
-                    }
-                    case SDLK_RIGHT:
-                    {
-                        key = NAVIT_KEY_RIGHT;
-                        break;
-                    }
-                    case SDLK_BACKSPACE:
-                    {
-                        key = NAVIT_KEY_BACKSPACE;
-                        break;
-                    }
-                    case SDLK_RETURN:
-                    {
-                        key = NAVIT_KEY_RETURN;
-                        break;
-                    }
-                    case SDLK_DOWN:
-                    {
-                        key = NAVIT_KEY_DOWN;
-                        break;
-                    }
-                    case SDLK_PAGEUP:
-                    {
-                        key = NAVIT_KEY_ZOOM_OUT;
-                        break;
-                    }
-                    case SDLK_UP:
-                    {
-                        key = NAVIT_KEY_UP;
-                        break;
-                    }
-                    case SDLK_PAGEDOWN:
-                    {
-                        key = NAVIT_KEY_ZOOM_IN;
-                        break;
-                    }
-                    default:
-                    {
-                        /* return unicode chars when they can be converted to ascii */
-                        key = ev.key.keysym.unicode<=127 ? ev.key.keysym.unicode : 0;
-                        break;
-                    }
-                }
+           case SDL_KEYDOWN:
+               {
+                   memset(keybuf, 0, sizeof(keybuf));
+                   switch(ev.key.keysym.sym)
+                   {
+                       case SDLK_LEFT:
+                           {
+                               keybuf[0] = NAVIT_KEY_LEFT;
+                               break;
+                           }
+                       case SDLK_RIGHT:
+                           {
+                               keybuf[0] = NAVIT_KEY_RIGHT;
+                               break;
+                           }
+                       case SDLK_BACKSPACE:
+                           {
+                               keybuf[0] = NAVIT_KEY_BACKSPACE;
+                               break;
+                           }
+                       case SDLK_RETURN:
+                           {
+                               keybuf[0] = NAVIT_KEY_RETURN;
+                               break;
+                           }
+                       case SDLK_DOWN:
+                           {
+                               keybuf[0] = NAVIT_KEY_DOWN;
+                               break;
+                           }
+                       case SDLK_PAGEUP:
+                           {
+                               keybuf[0] = NAVIT_KEY_ZOOM_OUT;
+                               break;
+                           }
+                       case SDLK_UP:
+                           {
+                               keybuf[0] = NAVIT_KEY_UP;
+                               break;
+                           }
+                       case SDLK_PAGEDOWN:
+                           {
+                               keybuf[0] = NAVIT_KEY_ZOOM_IN;
+                               break;
+                           }
+#ifdef USE_WEBOS
+                       case WEBOS_KEY_SHIFT:
+                           {
+                               if ((key_mod & WEBOS_KEY_MOD_SHIFT_STICKY) == WEBOS_KEY_MOD_SHIFT_STICKY)
+                                   key_mod &= ~(WEBOS_KEY_MOD_SHIFT_STICKY);
+                               else if ((key_mod & WEBOS_KEY_MOD_SHIFT) == WEBOS_KEY_MOD_SHIFT)
+                                   key_mod |= WEBOS_KEY_MOD_SHIFT_STICKY;
+                               else
+                                   key_mod |= WEBOS_KEY_MOD_SHIFT;
+                               break;
+                           }
+                       case WEBOS_KEY_ORANGE:
+                           {
+                               if ((key_mod & WEBOS_KEY_MOD_ORANGE_STICKY) == WEBOS_KEY_MOD_ORANGE_STICKY)
+                                   key_mod &= ~(WEBOS_KEY_MOD_ORANGE_STICKY);
+                               else if ((key_mod & WEBOS_KEY_MOD_ORANGE) == WEBOS_KEY_MOD_ORANGE)
+                                   key_mod |= WEBOS_KEY_MOD_ORANGE_STICKY;
+                               else
+                                   key_mod |= WEBOS_KEY_MOD_ORANGE;
+                               break;
+                           }
+                       case WEBOS_KEY_SYM:
+                           {
+                               /* Toggle the on-screen keyboard */
+                               //callback_list_call_attr_1(gr->cbl, attr_keyboard_toggle);     // Not implemented yet
+                               break;
+                           }
+                       case PDLK_GESTURE_BACK:
+                           {
+                               keybuf[0] = NAVIT_KEY_BACK;
+                               break;
+                           }
+                       case PDLK_GESTURE_FORWARD:
+                       case PDLK_GESTURE_AREA:
+                           {
+                               break;
+                           }
+#endif
+                       default:
+                           {
+#ifdef USE_WEBOS
+                               if (ev.key.keysym.unicode < 0x80 && ev.key.keysym.unicode > 0) {
+                                   keybuf[0] = (char)ev.key.keysym.unicode;
+                                   if ((key_mod & WEBOS_KEY_MOD_ORANGE) == WEBOS_KEY_MOD_ORANGE) {
+                                       switch(keybuf[0]) {
+                                           case 'e': keybuf[0] = '1'; break;
+                                           case 'r': keybuf[0] = '2'; break;
+                                           case 't': keybuf[0] = '3'; break;
+                                           case 'd': keybuf[0] = '4'; break;
+                                           case 'f': keybuf[0] = '5'; break;
+                                           case 'g': keybuf[0] = '6'; break;
+                                           case 'x': keybuf[0] = '7'; break;
+                                           case 'c': keybuf[0] = '8'; break;
+                                           case 'v': keybuf[0] = '9'; break;
+                                           case '@': keybuf[0] = '0'; break;
+                                           case ',': keybuf[0] = '-'; break;
+                                           case 'u': strncpy(keybuf, "ü", sizeof(keybuf)); break;
+                                           case 'a': strncpy(keybuf, "ä", sizeof(keybuf)); break;
+                                           case 'o': strncpy(keybuf, "ö", sizeof(keybuf)); break;
+                                           case 's': strncpy(keybuf, "ß", sizeof(keybuf)); break;
+                                       }
+}
+                                   if ((key_mod & WEBOS_KEY_MOD_SHIFT_STICKY) != WEBOS_KEY_MOD_SHIFT_STICKY)
+                                       key_mod &= ~(WEBOS_KEY_MOD_SHIFT_STICKY);
+                                   if ((key_mod & WEBOS_KEY_MOD_ORANGE_STICKY) != WEBOS_KEY_MOD_ORANGE_STICKY)
+                                       key_mod &= ~(WEBOS_KEY_MOD_ORANGE_STICKY);
+                               }
+                               else {
+                                   dbg(0,"Unknown key sym: %x\n", ev.key.keysym.sym);
+                               }
+#else
+                               /* return unicode chars when they can be converted to ascii */
+                               keybuf[0] = ev.key.keysym.unicode<=127 ? ev.key.keysym.unicode : 0;
+#endif
+                               break;
+                           }
+                   }
 
-                keybuf[0] = key;
-                keybuf[1] = '\0';
-               callback_list_call_attr_1(gr->cbl, attr_keypress, (void *)keybuf);
+                   dbg(2,"key mod: 0x%x\n", key_mod);
 
-                break;
-            }
+                   if (keybuf[0]) {
+                       dbg(2,"key: %s 0x%x\n", keybuf, keybuf);
+                       callback_list_call_attr_1(gr->cbl, attr_keypress, (void *)keybuf);
+                   }
+                   break;
+               }
 
-            case SDL_KEYUP:
-            {
-                break;
-            }
+           case SDL_KEYUP:
+               {
+                   break;
+               }
 
-            case SDL_MOUSEBUTTONDOWN:
-            {
+           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;
-               callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)(int)ev.button.button, (void *)&p); 
-                break;
-            }
+                   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;
+                   callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)(int)ev.button.button, (void *)&p);
+                   break;
+               }
 
-            case SDL_MOUSEBUTTONUP:
-            {
+           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;
-               callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)(int)ev.button.button, (void *)&p); 
-                break;
-            }
+                   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;
+                   callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)(int)ev.button.button, (void *)&p);
+                   break;
+               }
 
-            case SDL_QUIT:
-            {
-                navit_destroy(gr->nav);
-                break;
-            }
+           case SDL_QUIT:
+               {
+#ifdef USE_WEBOS
+                   quit_event_loop = 1;
+                   navit_destroy(gr->nav);
+#endif
+                   break;
+               }
 
-            case SDL_VIDEORESIZE:
-            {
+           case SDL_VIDEORESIZE:
+               {
 
-                gr->screen = SDL_SetVideoMode(ev.resize.w, ev.resize.h, gr->video_bpp, gr->video_flags);
-                if(gr->screen == NULL)
-                {
-                    navit_destroy(gr->nav);
-                }
-                else
-                {
-                   callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
-                }
+                   gr->screen = SDL_SetVideoMode(ev.resize.w, ev.resize.h, gr->video_bpp, gr->video_flags);
+                   if(gr->screen == NULL)
+                   {
+                       navit_destroy(gr->nav);
+                   }
+                   else
+                   {
+                       callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
+                   }
+
+                   break;
+               }
 
-                break;
-            }
+#ifdef USE_WEBOS
+           case SDL_USEREVENT:
+               {
+                   SDL_UserEvent userevent = ev.user;
+                   dbg(9,"received SDL_USEREVENT type(%x) code(%x)\n",userevent.type,userevent.code);
+                   if (userevent.type != SDL_USEREVENT)
+                       break;
 
-            default:
-            {
+                   if (userevent.code == PDL_GPS_UPDATE)
+                   {
+                       struct attr vehicle_attr;
+                       struct vehicle *v;
+                       navit_get_attr(gr->nav, attr_vehicle,  &vehicle_attr, NULL);
+                       v = vehicle_attr.u.vehicle;
+                       if (v) {
+                           struct attr attr;
+                           attr.type = attr_pdl_gps_update;
+                           attr.u.data = userevent.data1;
+                           vehicle_set_attr(v, &attr);
+                       }
+                   }
+                   else if(userevent.code == SDL_USEREVENT_CODE_TIMER)
+                   {
+                       struct callback *cb = (struct callback *)userevent.data1;
+                       dbg(1, "SDL_USEREVENT timer received cb(%p)\n", cb);
+                       callback_call_0(cb);
+                   }
+                   else if(userevent.code == SDL_USEREVENT_CODE_WATCH)
+                   {
+                       struct callback *cb = (struct callback *)userevent.data1;
+                       dbg(1, "SDL_USEREVENT watch received cb(%p)\n", cb);
+                       callback_call_0(cb);
+                   }
+                   else if(userevent.code == SDL_USEREVENT_CODE_CALL_CALLBACK)
+                   {
+                       struct callback_list *cbl = (struct callback_list *)userevent.data1;
+                       dbg(1, "SDL_USEREVENT call_callback received cbl(%p)\n", cbl);
+                       callback_list_call_0(cbl);
+                   }
+                   else if(userevent.code == SDL_USEREVENT_CODE_IDLE_EVENT) {
+                       dbg(1, "SDL_USEREVENT idle_event received\n");
+                   }
+#ifdef USE_WEBOS_ACCELEROMETER
+                   else if(userevent.code == SDL_USEREVENT_CODE_ROTATE)
+                   {
+                       dbg(1, "SDL_USEREVENT rotate received\n");
+                       switch(gr->orientation)
+                       {
+                           case WEBOS_ORIENTATION_PORTRAIT:
+                               gr->screen = SDL_SetVideoMode(gr->real_w, gr->real_h, gr->video_bpp, gr->video_flags);
+                               PDL_SetOrientation(PDL_ORIENTATION_0);
+                               break;
+                           case WEBOS_ORIENTATION_LANDSCAPE:
+                               gr->screen = SDL_SetVideoMode(gr->real_h, gr->real_w, gr->video_bpp, gr->video_flags);
+                               PDL_SetOrientation(PDL_ORIENTATION_270);
+                               break;
+                       }
+                       if(gr->screen == NULL)
+                       {
+                           navit_destroy(gr->nav);
+                       }
+                       else
+                       {
+                           callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
+                       }
+                   }
+#endif
+                   else
+                       dbg(1, "unknown SDL_USEREVENT\n");
+
+                   break;
+               }
+#endif
+           default:
+               {
 #ifdef DEBUG
-                printf("SDL_Event %d\n", ev.type);
+                   printf("SDL_Event %d\n", ev.type);
 #endif
-                break;
-            }
-        }
+                   break;
+               }
+       }
+    }
+
+#ifdef USE_WEBOS
+    event_sdl_watch_stopthread();
+#endif
+
+#ifdef USE_WEBOS_ACCELEROMETER
+    if (PDL_GetPDKVersion() > 100) {
+       event_remove_timeout(accel_to);
+       callback_destroy(accel_cb);
     }
+#endif
 
     return TRUE;
 }
@@ -2105,33 +2129,61 @@ graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr *
     int ret;
     int w=DISPLAY_W,h=DISPLAY_H;
 
+    struct font_priv *(*font_freetype_new) (void *meth);
+    font_freetype_new = plugin_get_font_type ("freetype");
+
+    if (!font_freetype_new)
+      {
+        return NULL;
+      }
+
+    font_freetype_new (&this->freetype_methods);
+
     this->nav = nav;
     this->cbl = cbl;
 
+    dbg(1,"Calling SDL_Init\n");
+#ifdef USE_WEBOS
+# ifdef USE_WEBOS_ACCELEROMETER
+    ret = SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_JOYSTICK);
+# else
+    ret = SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
+# endif
+#else
     ret = SDL_Init(SDL_INIT_VIDEO);
+#endif
     if(ret < 0)
     {
+       dbg(0,"SDL_Init failed %d\n", ret);
         g_free(this);
         return NULL;
     }
 
-#ifdef SDL_TTF
-    ret = TTF_Init();
+#ifdef USE_WEBOS
+    dbg(1,"Calling PDL_Init(0)\n");
+    ret = PDL_Init(0);
     if(ret < 0)
     {
+       dbg(0,"PDL_Init failed %d\n", ret);
         g_free(this);
-        SDL_Quit();
         return NULL;
     }
+
+    if (! event_request_system("sdl","graphics_sdl_new")) {
 #else
-    FT_Init_FreeType( &this->library );
+    if (! event_request_system("glib","graphics_sdl_new")) {
 #endif
-
-    if (! event_request_system("glib","graphics_sdl_new"))
+       dbg(0,"event_request_system failed");
         return NULL;
+    }
 
+#ifdef USE_WEBOS
+    this->video_bpp = 0;
+    this->video_flags = SDL_SWSURFACE | SDL_ANYFORMAT | SDL_RESIZABLE;
+#else
     this->video_bpp = 16;
     this->video_flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE;
+#endif
 
     if ((attr=attr_search(attrs, NULL, attr_w)))
         w=attr->u.num;
@@ -2140,7 +2192,7 @@ graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr *
     if ((attr=attr_search(attrs, NULL, attr_bpp)))
         this->video_bpp=attr->u.num;
     if ((attr=attr_search(attrs, NULL, attr_flags))) {
-       if (attr->u.num & 1) 
+       if (attr->u.num & 1)
            this->video_flags = SDL_SWSURFACE;
     }
     if ((attr=attr_search(attrs, NULL, attr_frame))) {
@@ -2150,18 +2202,42 @@ graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr *
 
     this->screen = SDL_SetVideoMode(w, h, this->video_bpp, this->video_flags);
 
-    /* Use screen size instead of requested */
-    w = this->screen->w;
-    h = this->screen->h;
-
     if(this->screen == NULL)
     {
+       dbg(0,"SDL_SetVideoMode failed\n");
         g_free(this);
+#ifdef USE_WEBOS
+        PDL_Quit();
+#endif
         SDL_Quit();
         return NULL;
     }
 
+    /* Use screen size instead of requested */
+    w = this->screen->w;
+    h = this->screen->h;
+
+    dbg(0, "using screen %ix%i@%i\n",
+           this->screen->w, this->screen->h,
+           this->screen->format->BytesPerPixel * 8);
+#ifdef USE_WEBOS_ACCELEROMETER
+    if ( w > h ) {
+       this->orientation = WEBOS_ORIENTATION_LANDSCAPE;
+       this->real_w = h;
+       this->real_h = w;
+    }
+    else {
+       this->orientation = WEBOS_ORIENTATION_PORTRAIT;
+       this->real_w = w;
+       this->real_h = h;
+    }
+    this->accelerometer = SDL_JoystickOpen(0);
+#endif
+
     SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+#ifdef USE_WEBOS
+    PDL_SetOrientation(PDL_ORIENTATION_0);
+#endif
 
     SDL_EnableUNICODE(1);
     SDL_WM_SetCaption("navit", NULL);
@@ -2182,9 +2258,26 @@ graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr *
     sge_Lock_ON();
 #endif
 
-       *meth=graphics_methods;
+    *meth=graphics_methods;
+
+
+    meth->font_new =
+       (struct graphics_font_priv *
+       (*)(struct graphics_priv *, struct graphics_font_methods *, char *, int,
+        int)) this->freetype_methods.font_new;
+    meth->get_text_bbox = (void*) this->freetype_methods.get_text_bbox;
+
+
 
+#ifdef USE_WEBOS
+    if(the_graphics!=NULL) {
+       dbg(0,"graphics_sdl_new: graphics struct already set: %d!\n", the_graphics_count);
+    }
+    the_graphics = this;
+    the_graphics_count++;
+#else
     g_timeout_add(G_PRIORITY_DEFAULT+10, graphics_sdl_idle, this);
+#endif
 
     this->overlay_enable = 1;
 
@@ -2196,9 +2289,313 @@ graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr *
     return this;
 }
 
+#ifdef USE_WEBOS
+/* ---------- SDL Eventhandling ---------- */
+
+static Uint32
+sdl_timer_callback(Uint32 interval, void* param)
+{
+    struct event_timeout *timeout=(struct event_timeout*)param;
+
+    dbg(1,"timer(%p) multi(%d) interval(%d) fired\n", param, timeout->multi, interval);
+
+    SDL_Event event;
+    SDL_UserEvent userevent;
+
+    userevent.type = SDL_USEREVENT;
+    userevent.code = SDL_USEREVENT_CODE_TIMER;
+    userevent.data1 = timeout->cb;
+    userevent.data2 = NULL;
+
+    event.type = SDL_USEREVENT;
+    event.user = userevent;
+
+    SDL_PushEvent (&event);
+
+    if (timeout->multi == 0) {
+       timeout->id = 0;
+       return 0; // cancel timer
+    }
+    return interval; // reactivate timer
+}
+
+/* SDL Mainloop */
+
+static void
+event_sdl_main_loop_run(void)
+{
+    PDL_ScreenTimeoutEnable(PDL_FALSE);
+    graphics_sdl_idle(NULL);
+    PDL_ScreenTimeoutEnable(PDL_TRUE);
+}
+
+static void
+event_sdl_main_loop_quit(void)
+{
+    quit_event_loop = 1;
+}
+
+/* Watch */
+
+static void
+event_sdl_watch_thread (GPtrArray *watch_list)
+{
+    struct pollfd *pfds = g_new0 (struct pollfd, watch_list->len);
+    struct event_watch *ew;
+    int ret;
+    int idx;
+
+    for (idx = 0; idx < watch_list->len; idx++ ) {
+       ew = g_ptr_array_index (watch_list, idx);
+       g_memmove (&pfds[idx], ew->pfd, sizeof(struct pollfd));
+    }
+
+    while ((ret = ppoll(pfds, watch_list->len, NULL, NULL)) > 0) {
+       for (idx = 0; idx < watch_list->len; idx++ ) {
+           if (pfds[idx].revents == pfds[idx].events) {        /* The requested event happened, notify mainloop! */
+               ew = g_ptr_array_index (watch_list, idx);
+               dbg(1,"watch(%p) event(%d) encountered\n", ew, pfds[idx].revents);
+
+               SDL_Event event;
+               SDL_UserEvent userevent;
+
+               userevent.type = SDL_USEREVENT;
+               userevent.code = SDL_USEREVENT_CODE_WATCH;
+               userevent.data1 = ew->cb;
+               userevent.data2 = NULL;
+
+               event.type = SDL_USEREVENT;
+               event.user = userevent;
+
+               SDL_PushEvent (&event);
+           }
+       }
+    }
+
+    g_free(pfds);
+
+    pthread_exit(0);
+}
+
+static void
+event_sdl_watch_startthread(GPtrArray *watch_list)
+{
+    dbg(1,"enter\n");
+    if (sdl_watch_thread)
+       event_sdl_watch_stopthread();
+
+    int ret;
+    ret = pthread_create (&sdl_watch_thread, NULL, (void *)event_sdl_watch_thread, (void *)watch_list);
+
+    dbg_assert (ret == 0);
+}
+
+static void
+event_sdl_watch_stopthread()
+{
+    dbg(1,"enter\n");
+    if (sdl_watch_thread) {
+       /* Notify the watch thread that the list of FDs will change */
+       pthread_kill(sdl_watch_thread, SIGUSR1);
+       pthread_join(sdl_watch_thread, NULL);
+       sdl_watch_thread = 0;
+    }
+}
+
+static struct event_watch *
+event_sdl_add_watch(void *fd, enum event_watch_cond cond, struct callback *cb)
+{
+    dbg(1,"fd(%d) cond(%x) cb(%x)\n", fd, cond, cb);
+
+    event_sdl_watch_stopthread();
+
+    if (!sdl_watch_list)
+       sdl_watch_list = g_ptr_array_new();
+
+    struct event_watch *new_ew = g_new0 (struct event_watch, 1);
+    struct pollfd *pfd = g_new0 (struct pollfd, 1);
+
+    pfd->fd = (int) fd;
+
+    /* Modify watchlist here */
+    switch (cond) {
+       case event_watch_cond_read:
+           pfd->events = POLLIN;
+           break;
+       case event_watch_cond_write:
+           pfd->events = POLLOUT;
+           break;
+       case event_watch_cond_except:
+           pfd->events = POLLERR|POLLHUP;
+           break;
+    }
+
+    new_ew->pfd = (struct pollfd*) pfd;
+    new_ew->cb = cb;
+
+    g_ptr_array_add (sdl_watch_list, (gpointer)new_ew);
+
+    event_sdl_watch_startthread(sdl_watch_list);
+
+    return new_ew;
+}
+
+static void
+event_sdl_remove_watch(struct event_watch *ew)
+{
+    dbg(1,"enter %p\n",ew);
+
+    event_sdl_watch_stopthread();
+
+    g_ptr_array_remove (sdl_watch_list, ew);
+    g_free (ew->pfd);
+    g_free (ew);
+
+    if (sdl_watch_list->len > 0)
+       event_sdl_watch_startthread(sdl_watch_list);
+}
+
+/* Timeout */
+
+static struct event_timeout *
+event_sdl_add_timeout(int timeout, int multi, struct callback *cb)
+{
+    struct event_timeout * ret =  g_new0(struct event_timeout, 1);
+    if(!ret) {
+       dbg (0,"g_new0 failed\n");
+       return ret;
+    }
+    dbg(1,"timer(%p) multi(%d) interval(%d) cb(%p) added\n",ret, multi, timeout, cb);
+    ret->multi = multi;
+    ret->cb = cb;
+    ret->id = SDL_AddTimer(timeout, sdl_timer_callback, ret);
+
+    return ret;
+}
+
+static void
+event_sdl_remove_timeout(struct event_timeout *to)
+{
+    dbg(2,"enter %p\n", to);
+    if(to)
+    {
+       /* do not SDL_RemoveTimer if oneshot timer has already fired */
+       int ret = to->id == 0 ? SDL_TRUE : SDL_RemoveTimer(to->id);
+
+        if (ret == SDL_FALSE)
+           dbg(0,"SDL_RemoveTimer (%p) failed\n", to->id);
+
+       g_free(to);
+       dbg(1,"timer(%p) removed\n", to);
+    }
+}
+
+/* Idle */
+
+/* sort ptr_array by priority, increasing order */
+static gint
+sdl_sort_idle_tasks(gconstpointer parama, gconstpointer paramb)
+{
+    struct idle_task *a = (struct idle_task *)parama;
+    struct idle_task *b = (struct idle_task *)paramb;
+    if (a->priority < b->priority)
+       return -1;
+    if (a->priority > b->priority)
+       return 1;
+    return 0;
+}
+
+static struct event_idle *
+event_sdl_add_idle(int priority, struct callback *cb)
+{
+    dbg(1,"add idle priority(%d) cb(%p)\n", priority, cb);
+
+    struct idle_task *task = g_new0(struct idle_task, 1);
+    task->priority = priority;
+    task->cb = cb;
+
+    g_ptr_array_add(idle_tasks, (gpointer)task);
+
+    if (idle_tasks->len < 2)
+    {
+       SDL_Event event;
+       SDL_UserEvent userevent;
+
+       dbg(1,"poking eventloop because of new idle_events\n");
+
+       userevent.type = SDL_USEREVENT;
+       userevent.code = SDL_USEREVENT_CODE_IDLE_EVENT;
+       userevent.data1 = NULL;
+       userevent.data2 = NULL;
+
+       event.type = SDL_USEREVENT;
+       event.user = userevent;
+
+       SDL_PushEvent (&event);
+    }
+    else       // more than one entry => sort the list
+       g_ptr_array_sort(idle_tasks, sdl_sort_idle_tasks);
+
+    return (struct event_idle *)task;
+}
+
+static void
+event_sdl_remove_idle(struct event_idle *task)
+{
+    dbg(1,"remove task(%p)\n", task);
+    g_ptr_array_remove(idle_tasks, (gpointer)task);
+}
+
+/* callback */
+
+static void
+event_sdl_call_callback(struct callback_list *cbl)
+{
+    dbg(1,"call_callback cbl(%p)\n",cbl);
+    SDL_Event event;
+    SDL_UserEvent userevent;
+
+    userevent.type = SDL_USEREVENT;
+    userevent.code = SDL_USEREVENT_CODE_CALL_CALLBACK;
+    userevent.data1 = cbl;
+    userevent.data2 = NULL;
+
+    event.type = SDL_USEREVENT;
+    event.user = userevent;
+
+    SDL_PushEvent (&event);
+}
+
+static struct event_methods event_sdl_methods = {
+    event_sdl_main_loop_run,
+    event_sdl_main_loop_quit,
+    event_sdl_add_watch,
+    event_sdl_remove_watch,
+    event_sdl_add_timeout,
+    event_sdl_remove_timeout,
+    event_sdl_add_idle,
+    event_sdl_remove_idle,
+    event_sdl_call_callback,
+};
+
+static struct event_priv *
+event_sdl_new(struct event_methods* methods)
+{
+    idle_tasks = g_ptr_array_new();
+    *methods = event_sdl_methods;
+    return NULL;
+}
+
+/* ---------- SDL Eventhandling ---------- */
+#endif
+
 void
 plugin_init(void)
 {
-        plugin_register_graphics_type("sdl", graphics_sdl_new);
+#ifdef USE_WEBOS
+    plugin_register_event_type("sdl", event_sdl_new);
+#endif
+    plugin_register_graphics_type("sdl", graphics_sdl_new);
 }
 
+// vim: sw=4 ts=8