Diff of /trunk/src/osm-gps-map.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 55 by harbaum, Thu Aug 13 12:01:52 2009 UTC revision 280 by harbaum, Fri May 21 19:28:16 2010 UTC
# Line 4  Line 4 
4   * osm-gps-map.c   * osm-gps-map.c
5   * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>   * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>
6   * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>   * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>
7     * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
8   *   *
9   * Contributions by   * Contributions by
10   * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>   * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>
11   *   *
12   * osm-gps-map.c is free software: you can redistribute it and/or modify it   * osm-gps-map.c is free software: you can redistribute it and/or modify it
13   * under the terms of the GNU General Public License as published by the   * under the terms of the GNU General Public License
14   * Free Software Foundation, either version 3 of the License, or   * as published by the Free Software Foundation; version 2.
  * (at your option) any later version.  
15   *   *
16   * osm-gps-map.c is distributed in the hope that it will be useful, but   * This program is distributed in the hope that it will be useful,
17   * WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * See the GNU General Public License for more details.   * GNU General Public License for more details.
20   *   *
21   * You should have received a copy of the GNU General Public License along   * You should have received a copy of the GNU General Public License
22   * with this program.  If not, see <http://www.gnu.org/licenses/>.   * along with this program; if not, see <http://www.gnu.org/licenses/>.
23   */   */
24    
25  #include "config.h"  #include "config.h"
# Line 36  Line 36 
36  #include <glib/gstdio.h>  #include <glib/gstdio.h>
37  #include <glib/gprintf.h>  #include <glib/gprintf.h>
38  #include <libsoup/soup.h>  #include <libsoup/soup.h>
39    #include <cairo.h>
40    
41  #include "converter.h"  #include "converter.h"
42  #include "osm-gps-map-types.h"  #include "osm-gps-map-types.h"
43  #include "osm-gps-map.h"  #include "osm-gps-map.h"
44    
 #ifdef USE_CAIRO  
 #include <cairo.h>  
 #endif  
   
45  #define ENABLE_DEBUG 0  #define ENABLE_DEBUG 0
46    
47  #define EXTRA_BORDER (TILESIZE / 2)  #define EXTRA_BORDER (TILESIZE / 2)
48    
49    #define OSM_GPS_MAP_SCROLL_STEP 10
50    
51    #define USER_AGENT "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"
52    
53  struct _OsmGpsMapPrivate  struct _OsmGpsMapPrivate
54  {  {
55      GHashTable *tile_queue;      GHashTable *tile_queue;
# Line 78  struct _OsmGpsMapPrivate Line 79  struct _OsmGpsMapPrivate
79      char *proxy_uri;      char *proxy_uri;
80    
81      //where downloaded tiles are cached      //where downloaded tiles are cached
82        char *tile_dir;
83        char *tile_base_dir;
84      char *cache_dir;      char *cache_dir;
     gboolean cache_dir_is_full_path;  
85    
86      //contains flags indicating the various special characters      //contains flags indicating the various special characters
87      //the uri string contains, that will be replaced when calculating      //the uri string contains, that will be replaced when calculating
# Line 96  struct _OsmGpsMapPrivate Line 98  struct _OsmGpsMapPrivate
98      gboolean show_trip_history;      gboolean show_trip_history;
99      GSList *trip_history;      GSList *trip_history;
100      coord_t *gps;      coord_t *gps;
101        float gps_heading;
102      gboolean gps_valid;      gboolean gps_valid;
103    
104    #ifdef ENABLE_OSD
105        //the osd controls (if present)
106        osm_gps_map_osd_t *osd;
107    #ifdef OSD_DOUBLE_BUFFER
108        GdkPixmap *dbuf_pixmap;
109    #endif
110    #endif
111      //additional images or tracks added to the map      //additional images or tracks added to the map
112      GSList *tracks;      GSList *tracks;
113      GSList *images;      GSList *images;
# Line 117  struct _OsmGpsMapPrivate Line 127  struct _OsmGpsMapPrivate
127      int drag_start_mouse_y;      int drag_start_mouse_y;
128      int drag_start_map_x;      int drag_start_map_x;
129      int drag_start_map_y;      int drag_start_map_y;
130        int drag_limit;
131        guint drag_expose;
132    
133      //for customizing the redering of the gps track      //for customizing the redering of the gps track
134      int ui_gps_track_width;      int ui_gps_track_width;
135      int ui_gps_point_inner_radius;      int ui_gps_point_inner_radius;
136      int ui_gps_point_outer_radius;      int ui_gps_point_outer_radius;
137    
138        //For storing keybindings
139        guint keybindings[OSM_GPS_MAP_KEY_MAX];
140    
141        guint fullscreen : 1;
142        guint keybindings_enabled : 1;
143      guint is_disposed : 1;      guint is_disposed : 1;
144      guint dragging : 1;      guint dragging : 1;
145      guint center_coord_set : 1;      guint button_down : 1;
146        guint double_pixel : 1;
147  };  };
148    
149  #define OSM_GPS_MAP_PRIVATE(o)  (OSM_GPS_MAP (o)->priv)  #define OSM_GPS_MAP_PRIVATE(o)  (OSM_GPS_MAP (o)->priv)
# Line 142  enum Line 160  enum
160  {  {
161      PROP_0,      PROP_0,
162    
163        PROP_DOUBLE_PIXEL,
164      PROP_AUTO_CENTER,      PROP_AUTO_CENTER,
165      PROP_RECORD_TRIP_HISTORY,      PROP_RECORD_TRIP_HISTORY,
166      PROP_SHOW_TRIP_HISTORY,      PROP_SHOW_TRIP_HISTORY,
# Line 149  enum Line 168  enum
168      PROP_REPO_URI,      PROP_REPO_URI,
169      PROP_PROXY_URI,      PROP_PROXY_URI,
170      PROP_TILE_CACHE_DIR,      PROP_TILE_CACHE_DIR,
171        PROP_TILE_CACHE_BASE_DIR,
172      PROP_TILE_CACHE_DIR_IS_FULL_PATH,      PROP_TILE_CACHE_DIR_IS_FULL_PATH,
173      PROP_ZOOM,      PROP_ZOOM,
174      PROP_MAX_ZOOM,      PROP_MAX_ZOOM,
# Line 162  enum Line 182  enum
182      PROP_GPS_POINT_R1,      PROP_GPS_POINT_R1,
183      PROP_GPS_POINT_R2,      PROP_GPS_POINT_R2,
184      PROP_MAP_SOURCE,      PROP_MAP_SOURCE,
185      PROP_IMAGE_FORMAT      PROP_IMAGE_FORMAT,
186        PROP_DRAG_LIMIT,
187  };  };
188    
189  G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);  G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);
# Line 176  static gchar    *replace_map_uri(OsmGpsM Line 197  static gchar    *replace_map_uri(OsmGpsM
197  static void     osm_gps_map_print_images (OsmGpsMap *map);  static void     osm_gps_map_print_images (OsmGpsMap *map);
198  static void     osm_gps_map_draw_gps_point (OsmGpsMap *map);  static void     osm_gps_map_draw_gps_point (OsmGpsMap *map);
199  static void     osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);  static void     osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);
200  #ifdef LIBSOUP22  #if USE_LIBSOUP22
201  static void     osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data);  static void     osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data);
202  #else  #else
203  static void     osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);  static void     osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
# Line 310  static void Line 331  static void
331  inspect_map_uri(OsmGpsMap *map)  inspect_map_uri(OsmGpsMap *map)
332  {  {
333      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
334        priv->uri_format = 0;
335        priv->the_google = FALSE;
336    
337      if (g_strrstr(priv->repo_uri, URI_MARKER_X))      if (g_strrstr(priv->repo_uri, URI_MARKER_X))
338          priv->uri_format |= URI_HAS_X;          priv->uri_format |= URI_HAS_X;
# Line 518  osm_gps_map_print_images (OsmGpsMap *map Line 541  osm_gps_map_print_images (OsmGpsMap *map
541                           priv->gc_map,                           priv->gc_map,
542                           im->image,                           im->image,
543                           0,0,                           0,0,
544                           x-(im->w/2),y-(im->h/2),                           x-im->xoffset,y-im->yoffset,
545                           im->w,im->h,                           im->w,im->h,
546                           GDK_RGB_DITHER_NONE, 0, 0);                           GDK_RGB_DITHER_NONE, 0, 0);
547    
# Line 546  osm_gps_map_draw_gps_point (OsmGpsMap *m Line 569  osm_gps_map_draw_gps_point (OsmGpsMap *m
569          int x, y;          int x, y;
570          int r = priv->ui_gps_point_inner_radius;          int r = priv->ui_gps_point_inner_radius;
571          int r2 = priv->ui_gps_point_outer_radius;          int r2 = priv->ui_gps_point_outer_radius;
572          // int lw = priv->ui_gps_track_width;          int mr = MAX(3*r,r2);
         int mr = MAX(r,r2);  
573    
574          map_x0 = priv->map_x - EXTRA_BORDER;          map_x0 = priv->map_x - EXTRA_BORDER;
575          map_y0 = priv->map_y - EXTRA_BORDER;          map_y0 = priv->map_y - EXTRA_BORDER;
576          x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;          x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;
577          y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;          y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;
 #ifdef USE_CAIRO  
578          cairo_t *cr;          cairo_t *cr;
579          cairo_pattern_t *pat;          cairo_pattern_t *pat;
 #else  
         GdkColor color;  
         GdkGC *marker;  
 #endif  
580    
 #ifdef USE_CAIRO  
581          cr = gdk_cairo_create(priv->pixmap);          cr = gdk_cairo_create(priv->pixmap);
582    
583          // draw transparent area          // draw transparent area
# Line 578  osm_gps_map_draw_gps_point (OsmGpsMap *m Line 594  osm_gps_map_draw_gps_point (OsmGpsMap *m
594    
595          // draw ball gradient          // draw ball gradient
596          if (r > 0) {          if (r > 0) {
597                // draw direction arrow
598                if(!isnan(priv->gps_heading))
599                {
600                    cairo_move_to (cr, x-r*cos(priv->gps_heading), y-r*sin(priv->gps_heading));
601                    cairo_line_to (cr, x+3*r*sin(priv->gps_heading), y-3*r*cos(priv->gps_heading));
602                    cairo_line_to (cr, x+r*cos(priv->gps_heading), y+r*sin(priv->gps_heading));
603                    cairo_close_path (cr);
604    
605                    cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.5);
606                    cairo_fill_preserve (cr);
607    
608                    cairo_set_line_width (cr, 1.0);
609                    cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
610                    cairo_stroke(cr);
611                }
612    
613              pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x,  y, r);              pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x,  y, r);
614              cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);              cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);
615              cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);              cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);
# Line 598  osm_gps_map_draw_gps_point (OsmGpsMap *m Line 630  osm_gps_map_draw_gps_point (OsmGpsMap *m
630                                      y-mr,                                      y-mr,
631                                      mr*2,                                      mr*2,
632                                      mr*2);                                      mr*2);
 #else  
         marker = gdk_gc_new(priv->pixmap);  
         color.red = 5000;  
         color.green = 5000;  
         color.blue = 55000;  
         gdk_gc_set_rgb_fg_color(marker, &color);  
         gdk_gc_set_line_attributes(marker, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);  
   
         if (r2 > 0) {  
             gdk_draw_arc (priv->pixmap,  
                           marker,  
                           FALSE,            //filled  
                           x-r2, y-r2,       // x,y  
                           r2*2,r2*2,        // width, height  
                           0, 360*64);       // start-end angle 64th, from 3h, anti clockwise  
         }  
         if (r > 0) {  
             gdk_draw_arc (priv->pixmap,  
                           marker,  
                           TRUE,         //filled  
                           x-r, y-r,     // x,y  
                           r*2,r*2,      // width, height  
                           0, 360*64);   // start-end angle 64th, from 3h, anti clockwise  
         }  
   
         g_object_unref(marker);  
         gtk_widget_queue_draw_area (GTK_WIDGET(map),  
                                     x-(mr+lw),  
                                     y-(mr+lw),  
                                     (mr*2)+lw+lw,  
                                     (mr*2)+lw+lw);  
 #endif  
633      }      }
634  }  }
635    
# Line 638  osm_gps_map_blit_tile(OsmGpsMap *map, Gd Line 638  osm_gps_map_blit_tile(OsmGpsMap *map, Gd
638  {  {
639      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
640    
641      g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);      if (priv->double_pixel) {
642            g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE*2,TILESIZE*2);
643    
644            GdkPixbuf *double_pixbuf = gdk_pixbuf_scale_simple (pixbuf, TILESIZE*2, TILESIZE*2,
645                                          GDK_INTERP_NEAREST);
646    
647            /* draw pixbuf onto pixmap */
648            gdk_draw_pixbuf (priv->pixmap,
649                             priv->gc_map,
650                             double_pixbuf,
651                             0,0,
652                             offset_x,offset_y,
653                             TILESIZE*2,TILESIZE*2,
654                             GDK_RGB_DITHER_NONE, 0, 0);
655            g_object_unref (double_pixbuf);
656        }
657        else
658        {
659            g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);
660    
661      /* draw pixbuf onto pixmap */          /* draw pixbuf onto pixmap */
662      gdk_draw_pixbuf (priv->pixmap,          gdk_draw_pixbuf (priv->pixmap,
663                       priv->gc_map,                           priv->gc_map,
664                       pixbuf,                           pixbuf,
665                       0,0,                           0,0,
666                       offset_x,offset_y,                           offset_x,offset_y,
667                       TILESIZE,TILESIZE,                           TILESIZE,TILESIZE,
668                       GDK_RGB_DITHER_NONE, 0, 0);                           GDK_RGB_DITHER_NONE, 0, 0);
669        }
670  }  }
671    
672  /* libsoup-2.2 and libsoup-2.4 use different ways to store the body data */  /* libsoup-2.2 and libsoup-2.4 use different ways to store the body data */
673  #ifdef LIBSOUP22  #if USE_LIBSOUP22
674  #define  soup_message_headers_append(a,b,c) soup_message_add_header(a,b,c)  #define  soup_message_headers_append(a,b,c) soup_message_add_header(a,b,c)
675  #define MSG_RESPONSE_BODY(a)    ((a)->response.body)  #define MSG_RESPONSE_BODY(a)    ((a)->response.body)
676  #define MSG_RESPONSE_LEN(a)     ((a)->response.length)  #define MSG_RESPONSE_LEN(a)     ((a)->response.length)
# Line 662  osm_gps_map_blit_tile(OsmGpsMap *map, Gd Line 681  osm_gps_map_blit_tile(OsmGpsMap *map, Gd
681  #define MSG_RESPONSE_LEN_FORMAT "%lld"  #define MSG_RESPONSE_LEN_FORMAT "%lld"
682  #endif  #endif
683    
684  #ifdef LIBSOUP22  #if USE_LIBSOUP22
685  static void  static void
686  osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data)  osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data)
687  #else  #else
# Line 695  osm_gps_map_tile_download_complete (Soup Line 714  osm_gps_map_tile_download_complete (Soup
714              }              }
715              else              else
716              {              {
717                  g_warning("Error creating tile download directory: %s", dl->folder);                  g_warning("Error creating tile download directory: %s",
718                              dl->folder);
719                    perror("perror:");
720              }              }
721          }          }
722    
# Line 776  osm_gps_map_tile_download_complete (Soup Line 797  osm_gps_map_tile_download_complete (Soup
797          }          }
798          else          else
799          {          {
800  #ifdef LIBSOUP22  #if USE_LIBSOUP22
801              soup_session_requeue_message(dl->session, msg);              soup_session_requeue_message(dl->session, msg);
802  #else  #else
803              soup_session_requeue_message(session, msg);              soup_session_requeue_message(session, msg);
# Line 798  osm_gps_map_download_tile (OsmGpsMap *ma Line 819  osm_gps_map_download_tile (OsmGpsMap *ma
819      //calculate the uri to download      //calculate the uri to download
820      dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);      dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
821    
822  #ifdef LIBSOUP22  #if USE_LIBSOUP22
823      dl->session = priv->soup_session;      dl->session = priv->soup_session;
824  #endif  #endif
825    
# Line 842  osm_gps_map_download_tile (OsmGpsMap *ma Line 863  osm_gps_map_download_tile (OsmGpsMap *ma
863                  }                  }
864              }              }
865    
866    #if USE_LIBSOUP22
867                soup_message_headers_append(msg->request_headers,
868                                            "User-Agent", USER_AGENT);
869    #endif
870    
871              g_hash_table_insert (priv->tile_queue, dl->uri, msg);              g_hash_table_insert (priv->tile_queue, dl->uri, msg);
872              soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);              soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);
873          } else {          } else {
# Line 883  osm_gps_map_load_cached_tile (OsmGpsMap Line 909  osm_gps_map_load_cached_tile (OsmGpsMap
909              tile->pixbuf = pixbuf;              tile->pixbuf = pixbuf;
910              g_hash_table_insert (priv->tile_cache, filename, tile);              g_hash_table_insert (priv->tile_cache, filename, tile);
911          }          }
912            else
913            {
914                g_free (filename);
915            }
916      }      }
917    
918      /* set/update the redraw_cycle timestamp on the tile */      /* set/update the redraw_cycle timestamp on the tile */
# Line 950  osm_gps_map_render_missing_tile (OsmGpsM Line 980  osm_gps_map_render_missing_tile (OsmGpsM
980      return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);      return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);
981  }  }
982    
983    /* default tile lifetime is one week */
984    #ifndef OSD_GPS_MAP_TILE_TTL
985    #define  OSD_GPS_MAP_TILE_TTL  (60*60*24*7)
986    #endif
987    
988    static gboolean
989    osm_gps_map_tile_age_exceeded(char *filename)
990    {
991        struct stat buf;
992    
993        if(!g_stat(filename, &buf))
994            return(time(NULL) - buf.st_mtime > OSD_GPS_MAP_TILE_TTL);
995    
996        return FALSE;
997    }
998    
999  static void  static void
1000  osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)  osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)
1001  {  {
1002      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
1003      gchar *filename;      gchar *filename;
1004      GdkPixbuf *pixbuf;      GdkPixbuf *pixbuf = NULL;
1005    
1006      g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);      g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);
1007    
# Line 971  osm_gps_map_load_tile (OsmGpsMap *map, i Line 1017  osm_gps_map_load_tile (OsmGpsMap *map, i
1017                  y,                  y,
1018                  priv->image_format);                  priv->image_format);
1019    
1020      /* try to get file from internal cache first */      gboolean needs_refresh = FALSE;
1021      if(!(pixbuf = osm_gps_map_load_cached_tile(map, zoom, x, y)))      if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
1022          pixbuf = gdk_pixbuf_new_from_file (filename, NULL);          /* try to get file from internal cache first */
1023            if(!(pixbuf = osm_gps_map_load_cached_tile(map, zoom, x, y)))
1024                pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1025    
1026             needs_refresh = osm_gps_map_tile_age_exceeded(filename);
1027        }
1028    
1029      if(pixbuf)      if(pixbuf)
1030      {      {
# Line 981  osm_gps_map_load_tile (OsmGpsMap *map, i Line 1032  osm_gps_map_load_tile (OsmGpsMap *map, i
1032          osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);          osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);
1033          g_object_unref (pixbuf);          g_object_unref (pixbuf);
1034      }      }
1035      else  
1036    
1037        if(!pixbuf || needs_refresh)
1038      {      {
1039          if (priv->map_auto_download)          if (priv->map_auto_download)
1040              osm_gps_map_download_tile(map, zoom, x, y, TRUE);              osm_gps_map_download_tile(map, zoom, x, y, TRUE);
1041    
1042          /* try to render the tile by scaling cached tiles from other zoom          if(!needs_refresh) {
1043           * levels */              /* try to render the tile by scaling cached tiles from other zoom
1044          pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);               * levels */
1045          if (pixbuf)              pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);
1046          {              if (pixbuf)
1047              gdk_draw_pixbuf (priv->pixmap,              {
1048                               priv->gc_map,                  osm_gps_map_blit_tile (map, pixbuf, offset_x,offset_y);
1049                               pixbuf,                  g_object_unref (pixbuf);
1050                               0,0,              }
1051                               offset_x,offset_y,              else
1052                               TILESIZE,TILESIZE,              {
1053                               GDK_RGB_DITHER_NONE, 0, 0);                  //prevent some artifacts when drawing not yet loaded areas.
1054              g_object_unref (pixbuf);                  gdk_draw_rectangle (priv->pixmap,
1055          }                                      GTK_WIDGET(map)->style->white_gc,
1056          else                                      TRUE, offset_x, offset_y, TILESIZE, TILESIZE);
1057          {              }
             //prevent some artifacts when drawing not yet loaded areas.  
             gdk_draw_rectangle (priv->pixmap,  
                                 GTK_WIDGET(map)->style->white_gc,  
                                 TRUE, offset_x, offset_y, TILESIZE, TILESIZE);  
1058          }          }
1059      }      }
1060      g_free(filename);      g_free(filename);
# Line 1023  osm_gps_map_fill_tiles_pixel (OsmGpsMap Line 1072  osm_gps_map_fill_tiles_pixel (OsmGpsMap
1072    
1073      g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);      g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);
1074    
1075      offset_x = - priv->map_x % TILESIZE;      if (priv->double_pixel)
1076      offset_y = - priv->map_y % TILESIZE;      {
1077      if (offset_x > 0) offset_x -= TILESIZE;          width  = GTK_WIDGET(map)->allocation.width;
1078      if (offset_y > 0) offset_y -= TILESIZE;          height = GTK_WIDGET(map)->allocation.height;
1079    
1080      offset_xn = offset_x + EXTRA_BORDER;          offset_x = - priv->map_x % (TILESIZE*2);
1081      offset_yn = offset_y + EXTRA_BORDER;          offset_y = - priv->map_y % (TILESIZE*2);
1082            if (offset_x > 0) offset_x -= (TILESIZE*2);
1083            if (offset_y > 0) offset_y -= (TILESIZE*2);
1084    
1085      width  = GTK_WIDGET(map)->allocation.width;          offset_xn = offset_x + EXTRA_BORDER;
1086      height = GTK_WIDGET(map)->allocation.height;          offset_yn = offset_y + EXTRA_BORDER;
1087    
1088      tiles_nx = (width  - offset_x) / TILESIZE + 1;          tiles_nx = (width  - offset_x) / (TILESIZE*2) + 1;
1089      tiles_ny = (height - offset_y) / TILESIZE + 1;          tiles_ny = (height - offset_y) / (TILESIZE*2) + 1;
1090    
1091      tile_x0 =  floor((float)priv->map_x / (float)TILESIZE);          tile_x0 =  floor((float)priv->map_x / (float)(TILESIZE*2));
1092      tile_y0 =  floor((float)priv->map_y / (float)TILESIZE);          tile_y0 =  floor((float)priv->map_y / (float)(TILESIZE*2));
1093    
1094      //TODO: implement wrap around          for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
     for (i=tile_x0; i<(tile_x0+tiles_nx);i++)  
     {  
         for (j=tile_y0;  j<(tile_y0+tiles_ny); j++)  
1095          {          {
1096              if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))              for (j=tile_y0;  j<(tile_y0+tiles_ny); j++)
1097              {              {
1098                  gdk_draw_rectangle (priv->pixmap,                  if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
1099                                      GTK_WIDGET(map)->style->white_gc,                  {
1100                                      TRUE,                      gdk_draw_rectangle (priv->pixmap,
1101                                      offset_xn, offset_yn,                                          GTK_WIDGET(map)->style->white_gc,
1102                                      TILESIZE,TILESIZE);                                          TRUE,
1103                                            offset_xn, offset_yn,
1104                                            TILESIZE*2, TILESIZE*2);
1105                    }
1106                    else
1107                    {
1108                        osm_gps_map_load_tile(map,
1109                                              priv->map_zoom - 1,
1110                                              i,j,
1111                                              offset_xn,offset_yn);
1112                    }
1113                    offset_yn += TILESIZE*2;
1114              }              }
1115              else              offset_xn += TILESIZE*2;
1116                offset_yn = offset_y + EXTRA_BORDER;
1117            }
1118        }
1119        else
1120        {
1121            offset_x = - priv->map_x % TILESIZE;
1122            offset_y = - priv->map_y % TILESIZE;
1123            if (offset_x > 0) offset_x -= TILESIZE;
1124            if (offset_y > 0) offset_y -= TILESIZE;
1125    
1126            offset_xn = offset_x + EXTRA_BORDER;
1127            offset_yn = offset_y + EXTRA_BORDER;
1128    
1129            width  = GTK_WIDGET(map)->allocation.width;
1130            height = GTK_WIDGET(map)->allocation.height;
1131    
1132            tiles_nx = (width  - offset_x) / TILESIZE + 1;
1133            tiles_ny = (height - offset_y) / TILESIZE + 1;
1134    
1135            tile_x0 =  floor((float)priv->map_x / (float)TILESIZE);
1136            tile_y0 =  floor((float)priv->map_y / (float)TILESIZE);
1137    
1138            //TODO: implement wrap around
1139            for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
1140            {
1141                for (j=tile_y0;  j<(tile_y0+tiles_ny); j++)
1142              {              {
1143                  osm_gps_map_load_tile(map,                  if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
1144                                        priv->map_zoom,                  {
1145                                        i,j,                      gdk_draw_rectangle (priv->pixmap,
1146                                        offset_xn,offset_yn);                                          GTK_WIDGET(map)->style->white_gc,
1147                                            TRUE,
1148                                            offset_xn, offset_yn,
1149                                            TILESIZE,TILESIZE);
1150                    }
1151                    else
1152                    {
1153                        osm_gps_map_load_tile(map,
1154                                              priv->map_zoom,
1155                                              i,j,
1156                                              offset_xn,offset_yn);
1157                    }
1158                    offset_yn += TILESIZE;
1159              }              }
1160              offset_yn += TILESIZE;              offset_xn += TILESIZE;
1161                offset_yn = offset_y + EXTRA_BORDER;
1162          }          }
         offset_xn += TILESIZE;  
         offset_yn = offset_y + EXTRA_BORDER;  
1163      }      }
1164  }  }
1165    
# Line 1077  osm_gps_map_print_track (OsmGpsMap *map, Line 1173  osm_gps_map_print_track (OsmGpsMap *map,
1173      int min_x = 0,min_y = 0,max_x = 0,max_y = 0;      int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
1174      int lw = priv->ui_gps_track_width;      int lw = priv->ui_gps_track_width;
1175      int map_x0, map_y0;      int map_x0, map_y0;
 #ifdef USE_CAIRO  
1176      cairo_t *cr;      cairo_t *cr;
 #else  
     int last_x = 0, last_y = 0;  
     GdkColor color;  
     GdkGC *gc;  
 #endif  
1177    
 #ifdef USE_CAIRO  
1178      cr = gdk_cairo_create(priv->pixmap);      cr = gdk_cairo_create(priv->pixmap);
1179      cairo_set_line_width (cr, lw);      cairo_set_line_width (cr, lw);
1180      cairo_set_source_rgba (cr, 60000.0/65535.0, 0.0, 0.0, 0.6);      cairo_set_source_rgba (cr, 60000.0/65535.0, 0.0, 0.0, 0.6);
1181      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
1182      cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);      cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
 #else  
     gc = gdk_gc_new(priv->pixmap);  
     color.green = 0;  
     color.blue = 0;  
     color.red = 60000;  
     gdk_gc_set_rgb_fg_color(gc, &color);  
     gdk_gc_set_line_attributes(gc, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);  
 #endif  
1183    
1184      map_x0 = priv->map_x - EXTRA_BORDER;      map_x0 = priv->map_x - EXTRA_BORDER;
1185      map_y0 = priv->map_y - EXTRA_BORDER;      map_y0 = priv->map_y - EXTRA_BORDER;
# Line 1111  osm_gps_map_print_track (OsmGpsMap *map, Line 1192  osm_gps_map_print_track (OsmGpsMap *map,
1192    
1193          // first time through loop          // first time through loop
1194          if (list == trackpoint_list) {          if (list == trackpoint_list) {
 #ifdef USE_CAIRO  
1195              cairo_move_to(cr, x, y);              cairo_move_to(cr, x, y);
 #else  
             last_x = x;  
             last_y = y;  
 #endif  
1196          }          }
1197    
 #ifdef USE_CAIRO  
1198          cairo_line_to(cr, x, y);          cairo_line_to(cr, x, y);
 #else  
         gdk_draw_line (priv->pixmap, gc, x, y, last_x, last_y);  
         last_x = x;  
         last_y = y;  
 #endif  
1199    
1200          max_x = MAX(x,max_x);          max_x = MAX(x,max_x);
1201          min_x = MIN(x,min_x);          min_x = MIN(x,min_x);
# Line 1140  osm_gps_map_print_track (OsmGpsMap *map, Line 1210  osm_gps_map_print_track (OsmGpsMap *map,
1210                                  max_x + (lw * 2),                                  max_x + (lw * 2),
1211                                  max_y + (lw * 2));                                  max_y + (lw * 2));
1212    
 #ifdef USE_CAIRO  
1213      cairo_stroke(cr);      cairo_stroke(cr);
1214      cairo_destroy(cr);      cairo_destroy(cr);
 #else  
     g_object_unref(gc);  
 #endif  
1215  }  }
1216    
1217  /* Prints the gps trip history, and any other tracks */  /* Prints the gps trip history, and any other tracks */
# Line 1192  osm_gps_map_map_redraw (OsmGpsMap *map) Line 1258  osm_gps_map_map_redraw (OsmGpsMap *map)
1258  {  {
1259      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
1260    
1261        /* on diablo the map comes up at 1x1 pixel size and */
1262        /* isn't really usable. we'll just ignore this ... */
1263        if((GTK_WIDGET(map)->allocation.width < 2) ||
1264           (GTK_WIDGET(map)->allocation.height < 2)) {
1265            printf("not a useful sized map yet ...\n");
1266            return FALSE;
1267        }
1268    
1269      priv->idle_map_redraw = 0;      priv->idle_map_redraw = 0;
1270    
1271    #ifdef ENABLE_OSD
1272        /* don't redraw the entire map while the OSD is doing */
1273        /* some animation or the like. This is to keep the animation */
1274        /* fluid */
1275        if (priv->osd->busy(priv->osd))
1276            return FALSE;
1277    #endif
1278    
1279    #ifdef DRAG_DEBUG
1280        printf("trying redraw\n");
1281    #endif
1282    
1283      /* the motion_notify handler uses priv->pixmap to redraw the area; if we      /* the motion_notify handler uses priv->pixmap to redraw the area; if we
1284       * change it while we are dragging, we will end up showing it in the wrong       * change it while we are dragging, we will end up showing it in the wrong
1285       * place. This could be fixed by carefully recompute the coordinates, but       * place. This could be fixed by carefully recompute the coordinates, but
# Line 1201  osm_gps_map_map_redraw (OsmGpsMap *map) Line 1287  osm_gps_map_map_redraw (OsmGpsMap *map)
1287      if (priv->dragging)      if (priv->dragging)
1288          return FALSE;          return FALSE;
1289    
1290        /* undo all offsets that may have happened when dragging */
1291        priv->drag_mouse_dx = 0;
1292        priv->drag_mouse_dy = 0;
1293    
1294      priv->redraw_cycle++;      priv->redraw_cycle++;
1295    
1296      /* draw white background to initialise pixmap */      /* draw white background to initialise pixmap */
1297      gdk_draw_rectangle (      gdk_draw_rectangle (priv->pixmap,
                         priv->pixmap,  
1298                          GTK_WIDGET(map)->style->white_gc,                          GTK_WIDGET(map)->style->white_gc,
1299                          TRUE,                          TRUE,
1300                          0, 0,                          0, 0,
# Line 1218  osm_gps_map_map_redraw (OsmGpsMap *map) Line 1307  osm_gps_map_map_redraw (OsmGpsMap *map)
1307      osm_gps_map_draw_gps_point(map);      osm_gps_map_draw_gps_point(map);
1308      osm_gps_map_print_images(map);      osm_gps_map_print_images(map);
1309    
1310      //osm_gps_map_osd_speed(map, 1.5);  #ifdef ENABLE_OSD
1311        /* OSD may contain a coordinate/scale, so we may have to re-render it */
1312        if(priv->osd && OSM_IS_GPS_MAP (priv->osd->widget))
1313            priv->osd->render (priv->osd);
1314    #endif
1315    
1316      osm_gps_map_purge_cache(map);      osm_gps_map_purge_cache(map);
1317      gtk_widget_queue_draw (GTK_WIDGET (map));      gtk_widget_queue_draw (GTK_WIDGET (map));
1318    
# Line 1235  osm_gps_map_map_redraw_idle (OsmGpsMap * Line 1329  osm_gps_map_map_redraw_idle (OsmGpsMap *
1329  }  }
1330    
1331  static void  static void
1332    center_coord_update(OsmGpsMap *map) {
1333    
1334        GtkWidget *widget = GTK_WIDGET(map);
1335        OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(map);
1336    
1337        // pixel_x,y, offsets
1338        gint pixel_x = priv->map_x + widget->allocation.width/2;
1339        gint pixel_y = priv->map_y + widget->allocation.height/2;
1340    
1341        priv->center_rlon = pixel2lon(priv->map_zoom, pixel_x);
1342        priv->center_rlat = pixel2lat(priv->map_zoom, pixel_y);
1343    
1344        g_signal_emit_by_name(widget, "changed");
1345    }
1346    
1347    static gboolean
1348    on_window_key_press(GtkWidget *widget, GdkEventKey *event, OsmGpsMapPrivate *priv)
1349    {
1350        int i;
1351        int step;
1352        gboolean handled;
1353        OsmGpsMap *map;
1354    
1355        //if no keybindings are set, let the app handle them...
1356        if (!priv->keybindings_enabled)
1357            return FALSE;
1358    
1359        handled = FALSE;
1360        map = OSM_GPS_MAP(widget);
1361        step = GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1362    
1363        //the map handles some keys on its own
1364        for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) {
1365            //not the key we have a binding for
1366            if (map->priv->keybindings[i] != event->keyval)
1367                continue;
1368    
1369            switch(i) {
1370                case OSM_GPS_MAP_KEY_FULLSCREEN: {
1371                    GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget));
1372                    if(!priv->fullscreen)
1373                        gtk_window_fullscreen(GTK_WINDOW(toplevel));
1374                    else
1375                        gtk_window_unfullscreen(GTK_WINDOW(toplevel));
1376    
1377                    priv->fullscreen = !priv->fullscreen;
1378                    handled = TRUE;
1379                    } break;
1380                case OSM_GPS_MAP_KEY_ZOOMIN:
1381                    osm_gps_map_zoom_in(map);
1382                    handled = TRUE;
1383                    break;
1384                case OSM_GPS_MAP_KEY_ZOOMOUT:
1385                    osm_gps_map_zoom_out(map);
1386                    handled = TRUE;
1387                    break;
1388                case OSM_GPS_MAP_KEY_UP:
1389                    priv->map_y -= step;
1390                    center_coord_update(map);
1391                    osm_gps_map_map_redraw_idle(map);
1392                    handled = TRUE;
1393                    break;
1394                case OSM_GPS_MAP_KEY_DOWN:
1395                    priv->map_y += step;
1396                    center_coord_update(map);
1397                    osm_gps_map_map_redraw_idle(map);
1398                    handled = TRUE;
1399                    break;
1400                  case OSM_GPS_MAP_KEY_LEFT:
1401                    priv->map_x -= step;
1402                    center_coord_update(map);
1403                    osm_gps_map_map_redraw_idle(map);
1404                    handled = TRUE;
1405                    break;
1406                case OSM_GPS_MAP_KEY_RIGHT:
1407                    priv->map_x += step;
1408                    center_coord_update(map);
1409                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1410                    handled = TRUE;
1411                    break;
1412                default:
1413                    break;
1414            }
1415        }
1416    
1417        return handled;
1418    }
1419    
1420    static void
1421  osm_gps_map_init (OsmGpsMap *object)  osm_gps_map_init (OsmGpsMap *object)
1422  {  {
1423        int i;
1424      OsmGpsMapPrivate *priv;      OsmGpsMapPrivate *priv;
1425    
1426      priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);      priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
# Line 1247  osm_gps_map_init (OsmGpsMap *object) Line 1431  osm_gps_map_init (OsmGpsMap *object)
1431      priv->trip_history = NULL;      priv->trip_history = NULL;
1432      priv->gps = g_new0(coord_t, 1);      priv->gps = g_new0(coord_t, 1);
1433      priv->gps_valid = FALSE;      priv->gps_valid = FALSE;
1434        priv->gps_heading = OSM_GPS_MAP_INVALID;
1435    
1436    #ifdef ENABLE_OSD
1437        priv->osd = NULL;
1438    #endif
1439      priv->tracks = NULL;      priv->tracks = NULL;
1440      priv->images = NULL;      priv->images = NULL;
1441    
# Line 1262  osm_gps_map_init (OsmGpsMap *object) Line 1450  osm_gps_map_init (OsmGpsMap *object)
1450    
1451      priv->map_source = -1;      priv->map_source = -1;
1452    
1453  #ifndef LIBSOUP22      priv->keybindings_enabled = FALSE;
1454      //Change naumber of concurrent connections option?      for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++)
1455      priv->soup_session = soup_session_async_new_with_options(          priv->keybindings[i] = 0;
1456                                                               SOUP_SESSION_USER_AGENT,  
1457                                                               "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11",  
1458                                                               NULL);  #if USE_LIBSOUP22
1459  #else      /* libsoup-2.2 has no special way to set the user agent, so we */
1460      /* libsoup-2.2 seems not to be able to set the user agent */      /* set it seperately as an extra header field for each reuest */
1461      priv->soup_session = soup_session_async_new();      priv->soup_session = soup_session_async_new();
1462  #endif  #else
1463        /* set the user agent */
1464        priv->soup_session =
1465            soup_session_async_new_with_options(SOUP_SESSION_USER_AGENT,
1466                                                USER_AGENT, NULL);
1467    
1468    #endif
1469      //Hash table which maps tile d/l URIs to SoupMessage requests      //Hash table which maps tile d/l URIs to SoupMessage requests
1470      priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);      priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);
1471    
# Line 1292  osm_gps_map_init (OsmGpsMap *object) Line 1485  osm_gps_map_init (OsmGpsMap *object)
1485      GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);      GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
1486    
1487      g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);      g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
1488    
1489        //Setup signal handlers
1490        g_signal_connect(G_OBJECT(object), "key_press_event",
1491                                G_CALLBACK(on_window_key_press), priv);
1492  }  }
1493    
1494  #ifndef G_CHECKSUM_MD5  static char*
1495  /* simple hash algorithm hack if md5 is not present */  osm_gps_map_get_cache_dir(OsmGpsMapPrivate *priv)
1496  static char *simple_hash(char *str) {  {
1497      union {      if (priv->tile_base_dir)
1498          char str[4];          return g_strdup(priv->tile_base_dir);
1499          gulong val;      return osm_gps_map_get_default_cache_directory();
1500      } hash = { .val = 0x55555555 };  }
1501    
1502      while(*str) {  /* strcmp0 was introduced with glib 2.16 */
1503          hash.str[(int)str & 3] ^= *str;  #if ! GLIB_CHECK_VERSION (2, 16, 0)
1504          str++;  int g_strcmp0(const char *str1, const char *str2)
1505      }  {
1506      return g_strdup_printf("%08lX", hash.val);      if( str1 == NULL && str2 == NULL ) return 0;
1507        if( str1 == NULL ) return -1;
1508        if( str2 == NULL ) return 1;
1509        return strcmp(str1, str2);
1510  }  }
1511  #endif  #endif
1512    
1513  static GObject *  static void
1514  osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)  osm_gps_map_setup(OsmGpsMapPrivate *priv)
1515  {  {
     GObject *object;  
     OsmGpsMapPrivate *priv;  
     OsmGpsMap *map;  
1516      const char *uri;      const char *uri;
1517    
1518      //Always chain up to the parent constructor     //user can specify a map source ID, or a repo URI as the map source
     object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);  
     map = OSM_GPS_MAP(object);  
     priv = OSM_GPS_MAP_PRIVATE(object);  
   
     //user can specify a map source ID, or a repo URI as the map source  
1519      uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL);      uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL);
1520      if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) {      if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) {
1521          g_debug("Using null source");          g_debug("Using null source");
# Line 1347  osm_gps_map_constructor (GType gtype, gu Line 1539  osm_gps_map_constructor (GType gtype, gu
1539          }          }
1540      }      }
1541    
1542      if (!priv->cache_dir_is_full_path) {      if (priv->tile_dir == NULL)
1543  #ifdef G_CHECKSUM_MD5          priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
1544    
1545        if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) {
1546            priv->cache_dir = NULL;
1547        } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) {
1548            char *base = osm_gps_map_get_cache_dir(priv);
1549    #if GLIB_CHECK_VERSION (2, 16, 0)
1550          char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);          char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
1551  #else  #else
1552          char *md5 = simple_hash(priv->repo_uri);          char *md5 = g_strdup(osm_gps_map_source_get_friendly_name(priv->map_source));
1553  #endif  #endif
1554            priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5);
1555          if (priv->cache_dir) {          g_free(base);
             char *old = priv->cache_dir;  
             //the new cachedir is the given cache dir + the md5 of the repo_uri  
             priv->cache_dir = g_strdup_printf("%s%c%s", old, G_DIR_SEPARATOR, md5);  
             g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir);  
             g_free(old);  
         } else {  
             //the new cachedir is the current dir + the md5 of the repo_uri  
             priv->cache_dir = g_strdup(md5);  
         }  
   
1556          g_free(md5);          g_free(md5);
1557        } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) {
1558            char *base = osm_gps_map_get_cache_dir(priv);
1559            const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
1560            priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname);
1561            g_free(base);
1562        } else {
1563            priv->cache_dir = g_strdup(priv->tile_dir);
1564      }      }
1565        g_debug("Cache dir: %s", priv->cache_dir);
1566    }
1567    
1568    static GObject *
1569    osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
1570    {
1571        //Always chain up to the parent constructor
1572        GObject *object =
1573            G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
1574    
1575      inspect_map_uri(map);      osm_gps_map_setup(OSM_GPS_MAP_PRIVATE(object));
1576    
1577        inspect_map_uri(OSM_GPS_MAP(object));
1578    
1579      return object;      return object;
1580  }  }
# Line 1391  osm_gps_map_dispose (GObject *object) Line 1597  osm_gps_map_dispose (GObject *object)
1597      g_hash_table_destroy(priv->missing_tiles);      g_hash_table_destroy(priv->missing_tiles);
1598      g_hash_table_destroy(priv->tile_cache);      g_hash_table_destroy(priv->tile_cache);
1599    
1600        /* images and layers contain GObjects which need unreffing, so free here */
1601      osm_gps_map_free_images(map);      osm_gps_map_free_images(map);
1602    
1603      if(priv->pixmap)      if(priv->pixmap)
# Line 1405  osm_gps_map_dispose (GObject *object) Line 1612  osm_gps_map_dispose (GObject *object)
1612      if (priv->idle_map_redraw != 0)      if (priv->idle_map_redraw != 0)
1613          g_source_remove (priv->idle_map_redraw);          g_source_remove (priv->idle_map_redraw);
1614    
1615        if (priv->drag_expose != 0)
1616            g_source_remove (priv->drag_expose);
1617    
1618        g_free(priv->gps);
1619    
1620    #ifdef ENABLE_OSD
1621        if(priv->osd) {
1622            priv->osd->free(priv->osd);
1623            priv->osd = NULL;
1624        }
1625    
1626    #ifdef OSD_DOUBLE_BUFFER
1627        if(priv->dbuf_pixmap)
1628            g_object_unref (priv->dbuf_pixmap);
1629    #endif
1630    #endif
1631    
1632      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
1633  }  }
1634    
# Line 1414  osm_gps_map_finalize (GObject *object) Line 1638  osm_gps_map_finalize (GObject *object)
1638      OsmGpsMap *map = OSM_GPS_MAP(object);      OsmGpsMap *map = OSM_GPS_MAP(object);
1639      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
1640    
1641      g_free(priv->cache_dir);      if (priv->tile_dir)
1642            g_free(priv->tile_dir);
1643    
1644        if (priv->cache_dir)
1645            g_free(priv->cache_dir);
1646    
1647      g_free(priv->repo_uri);      g_free(priv->repo_uri);
1648      g_free(priv->image_format);      g_free(priv->image_format);
1649    
1650        /* trip and tracks contain simple non GObject types, so free them here */
1651      osm_gps_map_free_trip(map);      osm_gps_map_free_trip(map);
1652      osm_gps_map_free_tracks(map);      osm_gps_map_free_tracks(map);
1653    
# Line 1436  osm_gps_map_set_property (GObject *objec Line 1666  osm_gps_map_set_property (GObject *objec
1666          case PROP_AUTO_CENTER:          case PROP_AUTO_CENTER:
1667              priv->map_auto_center = g_value_get_boolean (value);              priv->map_auto_center = g_value_get_boolean (value);
1668              break;              break;
1669            case PROP_DOUBLE_PIXEL:
1670                priv->double_pixel = g_value_get_boolean (value);
1671                osm_gps_map_map_redraw_idle(map);
1672                break;
1673          case PROP_RECORD_TRIP_HISTORY:          case PROP_RECORD_TRIP_HISTORY:
1674              priv->record_trip_history = g_value_get_boolean (value);              priv->record_trip_history = g_value_get_boolean (value);
1675              break;              break;
# Line 1453  osm_gps_map_set_property (GObject *objec Line 1687  osm_gps_map_set_property (GObject *objec
1687                  priv->proxy_uri = g_value_dup_string (value);                  priv->proxy_uri = g_value_dup_string (value);
1688                  g_debug("Setting proxy server: %s", priv->proxy_uri);                  g_debug("Setting proxy server: %s", priv->proxy_uri);
1689    
1690  #ifndef LIBSOUP22  #if USE_LIBSOUP22
1691                    SoupUri* uri = soup_uri_new(priv->proxy_uri);
1692                    g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL);
1693    #else
1694                  GValue val = {0};                  GValue val = {0};
   
1695                  SoupURI* uri = soup_uri_new(priv->proxy_uri);                  SoupURI* uri = soup_uri_new(priv->proxy_uri);
1696                  g_value_init(&val, SOUP_TYPE_URI);                  g_value_init(&val, SOUP_TYPE_URI);
1697                  g_value_take_boxed(&val, uri);                  g_value_take_boxed(&val, uri);
   
1698                  g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);                  g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
 #else  
                 SoupUri* uri = soup_uri_new(priv->proxy_uri);  
                 g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL);  
1699  #endif  #endif
1700              } else              } else
1701                  priv->proxy_uri = NULL;                  priv->proxy_uri = NULL;
1702    
1703              break;              break;
1704          case PROP_TILE_CACHE_DIR:          case PROP_TILE_CACHE_DIR:
1705              if ( g_value_get_string(value) )              priv->tile_dir = g_value_dup_string (value);
                 priv->cache_dir = g_value_dup_string (value);  
1706              break;              break;
1707          case PROP_TILE_CACHE_DIR_IS_FULL_PATH:          case PROP_TILE_CACHE_BASE_DIR:
1708              priv->cache_dir_is_full_path = g_value_get_boolean (value);              priv->tile_base_dir = g_value_dup_string (value);
1709              break;              break;
1710            case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1711                 g_warning("GObject property tile-cache-is-full-path depreciated");
1712                 break;
1713          case PROP_ZOOM:          case PROP_ZOOM:
1714              priv->map_zoom = g_value_get_int (value);              priv->map_zoom = g_value_get_int (value);
1715              break;              break;
# Line 1487  osm_gps_map_set_property (GObject *objec Line 1721  osm_gps_map_set_property (GObject *objec
1721              break;              break;
1722          case PROP_MAP_X:          case PROP_MAP_X:
1723              priv->map_x = g_value_get_int (value);              priv->map_x = g_value_get_int (value);
1724              priv->center_coord_set = FALSE;              center_coord_update(map);
1725              break;              break;
1726          case PROP_MAP_Y:          case PROP_MAP_Y:
1727              priv->map_y = g_value_get_int (value);              priv->map_y = g_value_get_int (value);
1728              priv->center_coord_set = FALSE;              center_coord_update(map);
1729              break;              break;
1730          case PROP_GPS_TRACK_WIDTH:          case PROP_GPS_TRACK_WIDTH:
1731              priv->ui_gps_track_width = g_value_get_int (value);              priv->ui_gps_track_width = g_value_get_int (value);
# Line 1502  osm_gps_map_set_property (GObject *objec Line 1736  osm_gps_map_set_property (GObject *objec
1736          case PROP_GPS_POINT_R2:          case PROP_GPS_POINT_R2:
1737              priv->ui_gps_point_outer_radius = g_value_get_int (value);              priv->ui_gps_point_outer_radius = g_value_get_int (value);
1738              break;              break;
1739          case PROP_MAP_SOURCE:          case PROP_MAP_SOURCE: {
1740                gint old = priv->map_source;
1741              priv->map_source = g_value_get_int (value);              priv->map_source = g_value_get_int (value);
1742              break;              if(old >= OSM_GPS_MAP_SOURCE_NULL &&
1743                   priv->map_source != old &&
1744                   priv->map_source >= OSM_GPS_MAP_SOURCE_NULL &&
1745                   priv->map_source <= OSM_GPS_MAP_SOURCE_LAST) {
1746    
1747                    /* we now have to switch the entire map */
1748    
1749                    /* flush the ram cache */
1750                    g_hash_table_remove_all(priv->tile_cache);
1751    
1752                    osm_gps_map_setup(priv);
1753    
1754                    inspect_map_uri(map);
1755    
1756                    /* adjust zoom if necessary */
1757                    if(priv->map_zoom > priv->max_zoom)
1758                        osm_gps_map_set_zoom(map, priv->max_zoom);
1759    
1760                    if(priv->map_zoom < priv->min_zoom)
1761                        osm_gps_map_set_zoom(map, priv->min_zoom);
1762    
1763                } } break;
1764          case PROP_IMAGE_FORMAT:          case PROP_IMAGE_FORMAT:
1765              priv->image_format = g_value_dup_string (value);              priv->image_format = g_value_dup_string (value);
1766              break;              break;
1767            case PROP_DRAG_LIMIT:
1768                priv->drag_limit = g_value_get_int (value);
1769                break;
1770          default:          default:
1771              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1772              break;              break;
# Line 1518  static void Line 1777  static void
1777  osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)  osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1778  {  {
1779      g_return_if_fail (OSM_IS_GPS_MAP (object));      g_return_if_fail (OSM_IS_GPS_MAP (object));
     float lat,lon;  
1780      OsmGpsMap *map = OSM_GPS_MAP(object);      OsmGpsMap *map = OSM_GPS_MAP(object);
1781      OsmGpsMapPrivate *priv = map->priv;      OsmGpsMapPrivate *priv = map->priv;
1782    
1783      switch (prop_id)      switch (prop_id)
1784      {      {
1785            case PROP_DOUBLE_PIXEL:
1786                g_value_set_boolean(value, priv->double_pixel);
1787                break;
1788          case PROP_AUTO_CENTER:          case PROP_AUTO_CENTER:
1789              g_value_set_boolean(value, priv->map_auto_center);              g_value_set_boolean(value, priv->map_auto_center);
1790              break;              break;
# Line 1545  osm_gps_map_get_property (GObject *objec Line 1806  osm_gps_map_get_property (GObject *objec
1806          case PROP_TILE_CACHE_DIR:          case PROP_TILE_CACHE_DIR:
1807              g_value_set_string(value, priv->cache_dir);              g_value_set_string(value, priv->cache_dir);
1808              break;              break;
1809            case PROP_TILE_CACHE_BASE_DIR:
1810                g_value_set_string(value, priv->tile_base_dir);
1811                break;
1812          case PROP_TILE_CACHE_DIR_IS_FULL_PATH:          case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1813              g_value_set_boolean(value, priv->cache_dir_is_full_path);              g_value_set_boolean(value, FALSE);
1814              break;              break;
1815          case PROP_ZOOM:          case PROP_ZOOM:
1816              g_value_set_int(value, priv->map_zoom);              g_value_set_int(value, priv->map_zoom);
# Line 1558  osm_gps_map_get_property (GObject *objec Line 1822  osm_gps_map_get_property (GObject *objec
1822              g_value_set_int(value, priv->min_zoom);              g_value_set_int(value, priv->min_zoom);
1823              break;              break;
1824          case PROP_LATITUDE:          case PROP_LATITUDE:
1825              lat = pixel2lat(priv->map_zoom,              g_value_set_float(value, rad2deg(priv->center_rlat));
                             priv->map_y + (GTK_WIDGET(map)->allocation.height / 2));  
             g_value_set_float(value, rad2deg(lat));  
1826              break;              break;
1827          case PROP_LONGITUDE:          case PROP_LONGITUDE:
1828              lon = pixel2lon(priv->map_zoom,              g_value_set_float(value, rad2deg(priv->center_rlon));
                             priv->map_x + (GTK_WIDGET(map)->allocation.width / 2));  
             g_value_set_float(value, rad2deg(lon));  
1829              break;              break;
1830          case PROP_MAP_X:          case PROP_MAP_X:
1831              g_value_set_int(value, priv->map_x);              g_value_set_int(value, priv->map_x);
# Line 1591  osm_gps_map_get_property (GObject *objec Line 1851  osm_gps_map_get_property (GObject *objec
1851          case PROP_IMAGE_FORMAT:          case PROP_IMAGE_FORMAT:
1852              g_value_set_string(value, priv->image_format);              g_value_set_string(value, priv->image_format);
1853              break;              break;
1854            case PROP_DRAG_LIMIT:
1855                g_value_set_int(value, priv->drag_limit);
1856                break;
1857          default:          default:
1858              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1859              break;              break;
# Line 1601  static gboolean Line 1864  static gboolean
1864  osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll  *event)  osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll  *event)
1865  {  {
1866      OsmGpsMap *map = OSM_GPS_MAP(widget);      OsmGpsMap *map = OSM_GPS_MAP(widget);
     OsmGpsMapPrivate *priv = map->priv;  
1867    
1868      if (event->direction == GDK_SCROLL_UP)      if (event->direction == GDK_SCROLL_UP)
1869      {          osm_gps_map_zoom_in(map);
1870          osm_gps_map_set_zoom(map, priv->map_zoom+1);      else if (event->direction == GDK_SCROLL_DOWN)
1871      }          osm_gps_map_zoom_out(map);
     else  
     {  
         osm_gps_map_set_zoom(map, priv->map_zoom-1);  
     }  
1872    
1873      return FALSE;      return FALSE;
1874  }  }
# Line 1618  osm_gps_map_scroll_event (GtkWidget *wid Line 1876  osm_gps_map_scroll_event (GtkWidget *wid
1876  static gboolean  static gboolean
1877  osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)  osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
1878  {  {
1879      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMap *map = OSM_GPS_MAP(widget);
1880        OsmGpsMapPrivate *priv = map->priv;
1881    
1882    #ifdef ENABLE_OSD
1883        /* pressed inside OSD control? */
1884        if(priv->osd) {
1885            osd_button_t but =
1886                priv->osd->check(priv->osd, TRUE, event->x, event->y);
1887    
1888            if(but != OSD_NONE)
1889            {
1890                int step =
1891                    GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1892                priv->drag_counter = -1;
1893    
1894                switch(but) {
1895                case OSD_UP:
1896                    priv->map_y -= step;
1897                    center_coord_update(map);
1898                    g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1899                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1900                    break;
1901    
1902                case OSD_DOWN:
1903                    priv->map_y += step;
1904                    center_coord_update(map);
1905                    g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1906                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1907                    break;
1908    
1909                case OSD_LEFT:
1910                    priv->map_x -= step;
1911                    center_coord_update(map);
1912                    g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1913                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1914                    break;
1915    
1916                case OSD_RIGHT:
1917                    priv->map_x += step;
1918                    center_coord_update(map);
1919                    g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1920                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1921                    break;
1922    
1923                case OSD_IN:
1924                    osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1);
1925                    break;
1926    
1927                case OSD_OUT:
1928                    osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1);
1929                    break;
1930    
1931                default:
1932                    /* all custom buttons are forwarded to the application */
1933                    if(priv->osd->cb)
1934                        priv->osd->cb(but, priv->osd->data);
1935                    break;
1936                }
1937    
1938                return FALSE;
1939            }
1940        }
1941    #endif
1942    
1943        priv->button_down = TRUE;
1944      priv->drag_counter = 0;      priv->drag_counter = 0;
1945      priv->drag_start_mouse_x = (int) event->x;      priv->drag_start_mouse_x = (int) event->x;
1946      priv->drag_start_mouse_y = (int) event->y;      priv->drag_start_mouse_y = (int) event->y;
# Line 1632  osm_gps_map_button_press (GtkWidget *wid Line 1953  osm_gps_map_button_press (GtkWidget *wid
1953  static gboolean  static gboolean
1954  osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)  osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
1955  {  {
1956        OsmGpsMap *map = OSM_GPS_MAP(widget);
1957      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1958    
1959        if(!priv->button_down)
1960            return FALSE;
1961    
1962      if (priv->dragging)      if (priv->dragging)
1963      {      {
1964          priv->dragging = FALSE;          priv->dragging = FALSE;
# Line 1644  osm_gps_map_button_release (GtkWidget *w Line 1969  osm_gps_map_button_release (GtkWidget *w
1969          priv->map_x += (priv->drag_start_mouse_x - (int) event->x);          priv->map_x += (priv->drag_start_mouse_x - (int) event->x);
1970          priv->map_y += (priv->drag_start_mouse_y - (int) event->y);          priv->map_y += (priv->drag_start_mouse_y - (int) event->y);
1971    
1972          priv->center_coord_set = FALSE;          center_coord_update(map);
1973    
1974          osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));          osm_gps_map_map_redraw_idle(map);
1975      }      }
1976    #ifdef ENABLE_OSD
1977        /* pressed inside OSD control? */
1978        else if(priv->osd)
1979            priv->osd->check(priv->osd, FALSE, event->x, event->y);
1980    #endif
1981    
1982      priv->drag_mouse_dx = 0;  #ifdef DRAG_DEBUG
1983      priv->drag_mouse_dy = 0;      printf("dragging done\n");
1984      priv->drag_counter = 0;  #endif
1985    
1986        priv->drag_counter = -1;
1987        priv->button_down = 0;
1988    
1989      return FALSE;      return FALSE;
1990  }  }
1991    
1992  static gboolean  static gboolean
1993    osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event);
1994    
1995    static gboolean
1996    osm_gps_map_map_expose (GtkWidget *widget)
1997    {
1998        OsmGpsMapPrivate *priv = OSM_GPS_MAP(widget)->priv;
1999    
2000        priv->drag_expose = 0;
2001        osm_gps_map_expose (widget, NULL);
2002        return FALSE;
2003    }
2004    
2005    static gboolean
2006  osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)  osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
2007  {  {
2008      int x, y;      int x, y;
2009      GdkModifierType state;      GdkModifierType state;
2010      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
2011    
2012        if(!priv->button_down)
2013            return FALSE;
2014    
2015      if (event->is_hint)      if (event->is_hint)
2016          gdk_window_get_pointer (event->window, &x, &y, &state);          gdk_window_get_pointer (event->window, &x, &y, &state);
2017      else      else
# Line 1676  osm_gps_map_motion_notify (GtkWidget *wi Line 2025  osm_gps_map_motion_notify (GtkWidget *wi
2025      if (!(state & GDK_BUTTON1_MASK))      if (!(state & GDK_BUTTON1_MASK))
2026          return FALSE;          return FALSE;
2027    
2028      priv->drag_counter++;      if (priv->drag_counter < 0)
2029            return FALSE;
2030    
2031      // we havent dragged more than 6 pixels      /* not yet dragged far enough? */
2032      if (priv->drag_counter < 6)      if(!priv->drag_counter &&
2033           ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) +
2034             (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
2035             priv->drag_limit*priv->drag_limit))
2036          return FALSE;          return FALSE;
2037    
2038        priv->drag_counter++;
2039    
2040      priv->dragging = TRUE;      priv->dragging = TRUE;
2041    
2042      if (priv->map_auto_center)      if (priv->map_auto_center)
# Line 1690  osm_gps_map_motion_notify (GtkWidget *wi Line 2045  osm_gps_map_motion_notify (GtkWidget *wi
2045      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
2046      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
2047    
2048      gdk_draw_drawable (      /* instead of redrawing directly just add an idle function */
2049                         widget->window,      if (!priv->drag_expose)
2050                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],          priv->drag_expose =
2051                         priv->pixmap,              g_idle_add ((GSourceFunc)osm_gps_map_map_expose, widget);
                        0,0,  
                        priv->drag_mouse_dx - EXTRA_BORDER, priv->drag_mouse_dy - EXTRA_BORDER,  
                        -1,-1);  
   
     //Paint white outside of the map if dragging. Its less  
     //ugly than painting the corrupted map  
     if(priv->drag_mouse_dx>EXTRA_BORDER) {  
         gdk_draw_rectangle (  
                             widget->window,  
                             widget->style->white_gc,  
                             TRUE,  
                             0, 0,  
                             priv->drag_mouse_dx - EXTRA_BORDER,  
                             widget->allocation.height);  
     }  
     else if (-priv->drag_mouse_dx > EXTRA_BORDER)  
     {  
         gdk_draw_rectangle (  
                             widget->window,  
                             widget->style->white_gc,  
                             TRUE,  
                             priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,  
                             -priv->drag_mouse_dx - EXTRA_BORDER,  
                             widget->allocation.height);  
     }  
   
     if (priv->drag_mouse_dy>EXTRA_BORDER) {  
         gdk_draw_rectangle (  
                             widget->window,  
                             widget->style->white_gc,  
                             TRUE,  
                             0, 0,  
                             widget->allocation.width,  
                             priv->drag_mouse_dy - EXTRA_BORDER);  
     }  
     else if (-priv->drag_mouse_dy > EXTRA_BORDER)  
     {  
         gdk_draw_rectangle (  
                             widget->window,  
                             widget->style->white_gc,  
                             TRUE,  
                             0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,  
                             widget->allocation.width,  
                             -priv->drag_mouse_dy - EXTRA_BORDER);  
     }  
2052    
2053      return FALSE;      return FALSE;
2054  }  }
# Line 1753  osm_gps_map_configure (GtkWidget *widget Line 2063  osm_gps_map_configure (GtkWidget *widget
2063          g_object_unref (priv->pixmap);          g_object_unref (priv->pixmap);
2064    
2065      priv->pixmap = gdk_pixmap_new (      priv->pixmap = gdk_pixmap_new (
2066                                     widget->window,                          widget->window,
2067                                     widget->allocation.width + EXTRA_BORDER * 2,                          widget->allocation.width + EXTRA_BORDER * 2,
2068                                     widget->allocation.height + EXTRA_BORDER * 2,                          widget->allocation.height + EXTRA_BORDER * 2,
2069                                     -1);                          -1);
2070    
2071        // pixel_x,y, offsets
2072        gint pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
2073        gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
2074    
2075        priv->map_x = pixel_x - widget->allocation.width/2;
2076        priv->map_y = pixel_y - widget->allocation.height/2;
2077    
2078    #ifdef ENABLE_OSD
2079    
2080    #ifdef OSD_DOUBLE_BUFFER
2081        if (priv->dbuf_pixmap)
2082            g_object_unref (priv->dbuf_pixmap);
2083    
2084        priv->dbuf_pixmap = gdk_pixmap_new (
2085                            widget->window,
2086                            widget->allocation.width,
2087                            widget->allocation.height,
2088                            -1);
2089    #endif
2090    
2091        /* the osd needs some references to map internal objects */
2092        if(priv->osd)
2093            priv->osd->widget = widget;
2094    #endif
2095    
2096      /* and gc, used for clipping (I think......) */      /* and gc, used for clipping (I think......) */
2097      if(priv->gc_map)      if(priv->gc_map)
# Line 1766  osm_gps_map_configure (GtkWidget *widget Line 2101  osm_gps_map_configure (GtkWidget *widget
2101    
2102      osm_gps_map_map_redraw(OSM_GPS_MAP(widget));      osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
2103    
2104        g_signal_emit_by_name(widget, "changed");
2105    
2106      return FALSE;      return FALSE;
2107  }  }
2108    
2109  static gboolean  static gboolean
2110  osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event)  osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event)
2111  {  {
2112      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMap *map = OSM_GPS_MAP(widget);
2113        OsmGpsMapPrivate *priv = map->priv;
2114    
2115    #ifdef OSD_DOUBLE_BUFFER
2116        GdkDrawable *drawable = priv->dbuf_pixmap;
2117    #else
2118        GdkDrawable *drawable = widget->window;
2119    #endif
2120    
2121    #ifdef DRAG_DEBUG
2122        printf("expose, map %d/%d\n", priv->map_x, priv->map_y);
2123    #endif
2124    
2125      gdk_draw_drawable (      if (!priv->drag_mouse_dx && !priv->drag_mouse_dy && event)
2126                         widget->window,      {
2127    #ifdef DRAG_DEBUG
2128            printf("  dragging = %d, event = %p\n", priv->dragging, event);
2129    #endif
2130    
2131            gdk_draw_drawable (drawable,
2132                               widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2133                               priv->pixmap,
2134                               event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,
2135                               event->area.x, event->area.y,
2136                               event->area.width, event->area.height);
2137        }
2138        else
2139        {
2140    #ifdef DRAG_DEBUG
2141            printf("  drag_mouse %d/%d\n",
2142                   priv->drag_mouse_dx - EXTRA_BORDER,
2143                   priv->drag_mouse_dy - EXTRA_BORDER);
2144    #endif
2145    
2146            gdk_draw_drawable (drawable,
2147                               widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2148                               priv->pixmap,
2149                               0,0,
2150                               priv->drag_mouse_dx - EXTRA_BORDER,
2151                               priv->drag_mouse_dy - EXTRA_BORDER,
2152                               -1,-1);
2153    
2154            //Paint white outside of the map if dragging. Its less
2155            //ugly than painting the corrupted map
2156            if(priv->drag_mouse_dx>EXTRA_BORDER) {
2157                gdk_draw_rectangle (drawable,
2158                                    widget->style->white_gc,
2159                                    TRUE,
2160                                    0, 0,
2161                                    priv->drag_mouse_dx - EXTRA_BORDER,
2162                                    widget->allocation.height);
2163            }
2164            else if (-priv->drag_mouse_dx > EXTRA_BORDER)
2165            {
2166                gdk_draw_rectangle (drawable,
2167                                    widget->style->white_gc,
2168                                    TRUE,
2169                                    priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,
2170                                    -priv->drag_mouse_dx - EXTRA_BORDER,
2171                                    widget->allocation.height);
2172            }
2173    
2174            if (priv->drag_mouse_dy>EXTRA_BORDER) {
2175                gdk_draw_rectangle (drawable,
2176                                    widget->style->white_gc,
2177                                    TRUE,
2178                                    0, 0,
2179                                    widget->allocation.width,
2180                                    priv->drag_mouse_dy - EXTRA_BORDER);
2181            }
2182            else if (-priv->drag_mouse_dy > EXTRA_BORDER)
2183            {
2184                gdk_draw_rectangle (drawable,
2185                                    widget->style->white_gc,
2186                                    TRUE,
2187                                    0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,
2188                                    widget->allocation.width,
2189                                    -priv->drag_mouse_dy - EXTRA_BORDER);
2190            }
2191        }
2192    
2193    #ifdef ENABLE_OSD
2194        /* draw new OSD */
2195        if(priv->osd)
2196            priv->osd->draw (priv->osd, drawable);
2197    
2198    #ifdef OSD_DOUBLE_BUFFER
2199        gdk_draw_drawable (widget->window,
2200                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2201                         priv->pixmap,                         priv->dbuf_pixmap,
2202                         event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,                         0,0,0,0,-1,-1);
2203                         event->area.x, event->area.y,  #endif
                        event->area.width, event->area.height);  
2204    
2205    #endif
2206    
2207      return FALSE;      return FALSE;
2208  }  }
2209    
# Line 1807  osm_gps_map_class_init (OsmGpsMapClass * Line 2229  osm_gps_map_class_init (OsmGpsMapClass *
2229      widget_class->scroll_event = osm_gps_map_scroll_event;      widget_class->scroll_event = osm_gps_map_scroll_event;
2230    
2231      g_object_class_install_property (object_class,      g_object_class_install_property (object_class,
2232                                         PROP_DOUBLE_PIXEL,
2233                                         g_param_spec_boolean ("double-pixel",
2234                                                               "double pixel",
2235                                                               "double map pixels for better readability",
2236                                                               FALSE,
2237                                                               G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2238    
2239    
2240        g_object_class_install_property (object_class,
2241                                       PROP_AUTO_CENTER,                                       PROP_AUTO_CENTER,
2242                                       g_param_spec_boolean ("auto-center",                                       g_param_spec_boolean ("auto-center",
2243                                                             "auto center",                                                             "auto center",
# Line 1859  osm_gps_map_class_init (OsmGpsMapClass * Line 2290  osm_gps_map_class_init (OsmGpsMapClass *
2290                                       g_param_spec_string ("tile-cache",                                       g_param_spec_string ("tile-cache",
2291                                                            "tile cache",                                                            "tile cache",
2292                                                            "osm local tile cache dir",                                                            "osm local tile cache dir",
2293                                                            NULL,                                                            OSM_GPS_MAP_CACHE_AUTO,
2294                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2295    
2296      g_object_class_install_property (object_class,      g_object_class_install_property (object_class,
2297                                       PROP_TILE_CACHE_DIR_IS_FULL_PATH,                                       PROP_TILE_CACHE_BASE_DIR,
2298                                       g_param_spec_boolean ("tile-cache-is-full-path",                                       g_param_spec_string ("tile-cache-base",
2299                                                             "tile cache is full path",                                                            "tile cache-base",
2300                                                             "if true, the path passed to tile-cache is interpreted as the full cache path",                                                            "base directory to which friendly and auto paths are appended",
2301                                                             FALSE,                                                            NULL,
2302                                                             G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2303    
2304         g_object_class_install_property (object_class,
2305                                          PROP_TILE_CACHE_DIR_IS_FULL_PATH,
2306                                          g_param_spec_boolean ("tile-cache-is-full-path",
2307                                                                "tile cache is full path",
2308                                                                "DEPRECIATED",
2309                                                                FALSE,
2310                                                                G_PARAM_READABLE | G_PARAM_WRITABLE));
2311    
2312      g_object_class_install_property (object_class,      g_object_class_install_property (object_class,
2313                                       PROP_ZOOM,                                       PROP_ZOOM,
2314                                       g_param_spec_int ("zoom",                                       g_param_spec_int ("zoom",
2315                                                         "zoom",                                                         "zoom",
2316                                                         "zoom level",                                                         "initial zoom level",
2317                                                         MIN_ZOOM, /* minimum property value */                                                         MIN_ZOOM, /* minimum property value */
2318                                                         MAX_ZOOM, /* maximum property value */                                                         MAX_ZOOM, /* maximum property value */
2319                                                         3,                                                         3,
# Line 1985  osm_gps_map_class_init (OsmGpsMapClass * Line 2424  osm_gps_map_class_init (OsmGpsMapClass *
2424                                       g_param_spec_int ("map-source",                                       g_param_spec_int ("map-source",
2425                                                         "map source",                                                         "map source",
2426                                                         "map source ID",                                                         "map source ID",
2427                                                         -1,           /* minimum property value */                                                         -1,          /* minimum property value */
2428                                                         G_MAXINT,    /* maximum property value */                                                         G_MAXINT,    /* maximum property value */
2429                                                         -1,                                                         -1,
2430                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2431    
2432      g_object_class_install_property (object_class,      g_object_class_install_property (object_class,
2433                                       PROP_IMAGE_FORMAT,                                       PROP_IMAGE_FORMAT,
# Line 1997  osm_gps_map_class_init (OsmGpsMapClass * Line 2436  osm_gps_map_class_init (OsmGpsMapClass *
2436                                                            "map source tile repository image format (jpg, png)",                                                            "map source tile repository image format (jpg, png)",
2437                                                            OSM_IMAGE_FORMAT,                                                            OSM_IMAGE_FORMAT,
2438                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2439    
2440        g_object_class_install_property (object_class,
2441                                         PROP_DRAG_LIMIT,
2442                                         g_param_spec_int ("drag-limit",
2443                                                           "drag limit",
2444                                                           "the number of pixels the user has to move the pointer in order to start dragging",
2445                                                           0,           /* minimum property value */
2446                                                           G_MAXINT,    /* maximum property value */
2447                                                           10,
2448                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2449    
2450        g_signal_new ("changed", OSM_TYPE_GPS_MAP,
2451                      G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
2452                      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2453  }  }
2454    
2455  const char*  const char*
# Line 2007  osm_gps_map_source_get_friendly_name(Osm Line 2460  osm_gps_map_source_get_friendly_name(Osm
2460          case OSM_GPS_MAP_SOURCE_NULL:          case OSM_GPS_MAP_SOURCE_NULL:
2461              return "None";              return "None";
2462          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2463              return "OpenStreetMap";              return "OpenStreetMap I";
2464          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2465              return "OpenStreetMap Renderer";              return "OpenStreetMap II";
2466          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2467              return "OpenAerialMap";              return "OpenAerialMap";
2468            case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2469                return "OpenCycleMap";
2470            case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2471                return "Public Transport";
2472            case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2473                return "OSMC Trails";
2474          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2475              return "Maps-For-Free";              return "Maps-For-Free";
2476          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
# Line 2032  osm_gps_map_source_get_friendly_name(Osm Line 2491  osm_gps_map_source_get_friendly_name(Osm
2491              return "Yahoo Satellite";              return "Yahoo Satellite";
2492          case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:          case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2493              return "Yahoo Hybrid";              return "Yahoo Hybrid";
2494            case OSM_GPS_MAP_SOURCE_LAST:
2495          default:          default:
2496              return NULL;              return NULL;
2497      }      }
# Line 2051  osm_gps_map_source_get_repo_uri(OsmGpsMa Line 2511  osm_gps_map_source_get_repo_uri(OsmGpsMa
2511              return "none://";              return "none://";
2512          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2513              return OSM_REPO_URI;              return OSM_REPO_URI;
2514            case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2515                /* OpenAerialMap is down, offline till furthur notice
2516                   http://openaerialmap.org/pipermail/talk_openaerialmap.org/2008-December/000055.html */
2517                return NULL;
2518          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2519              return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png";              return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png";
2520          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:          case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2521              return "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/#Z/#X/#Y.jpg";              return "http://c.andy.sandbox.cloudmade.com/tiles/cycle/#Z/#X/#Y.png";
2522            case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2523                return "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z/#X/#Y.png";
2524            case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2525                return "http://topo.geofabrik.de/trails/#Z/#X/#Y.png";
2526          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2527              return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg";              return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg";
2528          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
2529              return "http://mt#R.google.com/vt/v=w2.97&x=#X&y=#Y&z=#Z";              return "http://mt#R.google.com/vt/v=w2.97&x=#X&y=#Y&z=#Z";
         case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:  
             return "http://khm#R.google.com/kh?n=404&v=3&t=#Q";  
2530          case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:          case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
2531              return NULL; /* No longer working  "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */              /* No longer working
2532                   "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */
2533                return NULL;
2534            case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2535                return "http://khm#R.google.com/kh/v=51&x=#X&y=#Y&z=#Z";
2536          case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:          case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
2537              return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50";              return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50";
2538          case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:          case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
# Line 2079  osm_gps_map_source_get_repo_uri(OsmGpsMa Line 2549  osm_gps_map_source_get_repo_uri(OsmGpsMa
2549               *  z = zoom - (MAX_ZOOM - 17));               *  z = zoom - (MAX_ZOOM - 17));
2550               */               */
2551              return NULL;              return NULL;
2552            case OSM_GPS_MAP_SOURCE_LAST:
2553          default:          default:
2554              return NULL;              return NULL;
2555      }      }
# Line 2092  osm_gps_map_source_get_image_format(OsmG Line 2563  osm_gps_map_source_get_image_format(OsmG
2563          case OSM_GPS_MAP_SOURCE_NULL:          case OSM_GPS_MAP_SOURCE_NULL:
2564          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2565          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2566            case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2567            case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2568            case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2569              return "png";              return "png";
2570          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2571          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:          case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
# Line 2105  osm_gps_map_source_get_image_format(OsmG Line 2579  osm_gps_map_source_get_image_format(OsmG
2579          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2580          case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:          case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2581              return "jpg";              return "jpg";
2582            case OSM_GPS_MAP_SOURCE_LAST:
2583          default:          default:
2584              return "bin";              return "bin";
2585      }      }
# Line 2125  osm_gps_map_source_get_max_zoom(OsmGpsMa Line 2600  osm_gps_map_source_get_max_zoom(OsmGpsMa
2600          case OSM_GPS_MAP_SOURCE_NULL:          case OSM_GPS_MAP_SOURCE_NULL:
2601              return 18;              return 18;
2602          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2603            case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2604            case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2605              return OSM_MAX_ZOOM;              return OSM_MAX_ZOOM;
2606          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:          case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2607          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:          case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
# Line 2137  osm_gps_map_source_get_max_zoom(OsmGpsMa Line 2614  osm_gps_map_source_get_max_zoom(OsmGpsMa
2614          case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:          case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
2615          case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:          case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2616              return 17;              return 17;
2617            case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2618                return 15;
2619          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:          case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2620              return 11;              return 11;
2621          case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:          case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2622              return 18;              return 18;
2623            case OSM_GPS_MAP_SOURCE_LAST:
2624          default:          default:
2625              return 17;              return 17;
2626      }      }
2627      return 17;      return 17;
2628  }  }
2629    
2630    gboolean
2631    osm_gps_map_source_is_valid(OsmGpsMapSource_t source)
2632    {
2633        return osm_gps_map_source_get_repo_uri(source) != NULL;
2634    }
2635    
2636  void  void
2637  osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)  osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)
2638  {  {
# Line 2183  osm_gps_map_download_maps (OsmGpsMap *ma Line 2669  osm_gps_map_download_maps (OsmGpsMap *ma
2669                                      i, G_DIR_SEPARATOR,                                      i, G_DIR_SEPARATOR,
2670                                      j,                                      j,
2671                                      priv->image_format);                                      priv->image_format);
2672                      if (!g_file_test(filename, G_FILE_TEST_EXISTS))  
2673                        if ((!g_file_test(filename, G_FILE_TEST_EXISTS)) ||
2674                            osm_gps_map_tile_age_exceeded(filename))
2675                      {                      {
2676                          osm_gps_map_download_tile(map, zoom, i, j, FALSE);                          osm_gps_map_download_tile(map, zoom, i, j, FALSE);
2677                          num_tiles++;                          num_tiles++;
2678                      }                      }
2679    
2680                      g_free(filename);                      g_free(filename);
2681                  }                  }
2682              }              }
# Line 2227  osm_gps_map_set_center (OsmGpsMap *map, Line 2716  osm_gps_map_set_center (OsmGpsMap *map,
2716      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (OSM_IS_GPS_MAP (map));
2717      priv = map->priv;      priv = map->priv;
2718    
2719        g_object_set(G_OBJECT(map), "auto-center", FALSE, NULL);
2720    
2721      priv->center_rlat = deg2rad(latitude);      priv->center_rlat = deg2rad(latitude);
2722      priv->center_rlon = deg2rad(longitude);      priv->center_rlon = deg2rad(longitude);
     priv->center_coord_set = TRUE;  
2723    
2724      // pixel_x,y, offsets      // pixel_x,y, offsets
2725      pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);      pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
# Line 2239  osm_gps_map_set_center (OsmGpsMap *map, Line 2729  osm_gps_map_set_center (OsmGpsMap *map,
2729      priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;      priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
2730    
2731      osm_gps_map_map_redraw_idle(map);      osm_gps_map_map_redraw_idle(map);
2732    
2733        g_signal_emit_by_name(map, "changed");
2734  }  }
2735    
2736  int  int
# Line 2261  osm_gps_map_set_zoom (OsmGpsMap *map, in Line 2753  osm_gps_map_set_zoom (OsmGpsMap *map, in
2753          //constrain zoom min_zoom -> max_zoom          //constrain zoom min_zoom -> max_zoom
2754          priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);          priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);
2755    
2756          if (priv->center_coord_set)          priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
2757          {          priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
             priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;  
             priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;  
         }  
         else  
         {  
             factor = exp(priv->map_zoom * M_LN2)/exp(zoom_old * M_LN2);  
             priv->map_x = ((priv->map_x + width_center) * factor) - width_center;  
             priv->map_y = ((priv->map_y + height_center) * factor) - height_center;  
         }  
2758    
2759            factor = pow(2, priv->map_zoom-zoom_old);
2760          g_debug("Zoom changed from %d to %d factor:%f x:%d",          g_debug("Zoom changed from %d to %d factor:%f x:%d",
2761                  zoom_old, priv->map_zoom, factor, priv->map_x);                  zoom_old, priv->map_zoom, factor, priv->map_x);
2762    
2763            /* adjust gps precision indicator */
2764            priv->ui_gps_point_outer_radius *= factor;
2765    
2766    #ifdef ENABLE_OSD
2767            /* OSD may contain a scale, so we may have to re-render it */
2768            if(priv->osd && OSM_IS_GPS_MAP (priv->osd->widget))
2769                priv->osd->render (priv->osd);
2770    #endif
2771    
2772          osm_gps_map_map_redraw_idle(map);          osm_gps_map_map_redraw_idle(map);
2773    
2774            g_signal_emit_by_name(map, "changed");
2775      }      }
2776      return priv->map_zoom;      return priv->map_zoom;
2777  }  }
2778    
2779    int
2780    osm_gps_map_zoom_in (OsmGpsMap *map)
2781    {
2782        g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2783        return osm_gps_map_set_zoom(map, map->priv->map_zoom+1);
2784    }
2785    
2786    int
2787    osm_gps_map_zoom_out (OsmGpsMap *map)
2788    {
2789        g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2790        return osm_gps_map_set_zoom(map, map->priv->map_zoom-1);
2791    }
2792    
2793  void  void
2794  osm_gps_map_add_track (OsmGpsMap *map, GSList *track)  osm_gps_map_add_track (OsmGpsMap *map, GSList *track)
2795  {  {
# Line 2296  osm_gps_map_add_track (OsmGpsMap *map, G Line 2805  osm_gps_map_add_track (OsmGpsMap *map, G
2805  }  }
2806    
2807  void  void
2808    osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track)
2809    {
2810        OsmGpsMapPrivate *priv;
2811    
2812        if(!old_track) {
2813            osm_gps_map_add_track (map, new_track);
2814            return;
2815        }
2816    
2817        g_return_if_fail (OSM_IS_GPS_MAP (map));
2818        priv = map->priv;
2819    
2820        GSList *old = g_slist_find(priv->tracks, old_track);
2821        if(!old) {
2822            g_warning("track to be replaced not found");
2823            return;
2824        }
2825    
2826        old->data = new_track;
2827        osm_gps_map_map_redraw_idle(map);
2828    }
2829    
2830    void
2831  osm_gps_map_clear_tracks (OsmGpsMap *map)  osm_gps_map_clear_tracks (OsmGpsMap *map)
2832  {  {
2833      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (OSM_IS_GPS_MAP (map));
# Line 2305  osm_gps_map_clear_tracks (OsmGpsMap *map Line 2837  osm_gps_map_clear_tracks (OsmGpsMap *map
2837  }  }
2838    
2839  void  void
2840  osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)  osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign)
2841  {  {
2842      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (OSM_IS_GPS_MAP (map));
2843    
# Line 2320  osm_gps_map_add_image (OsmGpsMap *map, f Line 2852  osm_gps_map_add_image (OsmGpsMap *map, f
2852          im->pt.rlat = deg2rad(latitude);          im->pt.rlat = deg2rad(latitude);
2853          im->pt.rlon = deg2rad(longitude);          im->pt.rlon = deg2rad(longitude);
2854    
2855            //handle alignment
2856            im->xoffset = xalign * im->w;
2857            im->yoffset = yalign * im->h;
2858    
2859          g_object_ref(image);          g_object_ref(image);
2860          im->image = image;          im->image = image;
2861    
# Line 2329  osm_gps_map_add_image (OsmGpsMap *map, f Line 2865  osm_gps_map_add_image (OsmGpsMap *map, f
2865      }      }
2866  }  }
2867    
2868    void
2869    osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
2870    {
2871        osm_gps_map_add_image_with_alignment (map, latitude, longitude, image, 0.5, 0.5);
2872    }
2873    
2874  gboolean  gboolean
2875  osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image)  osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image)
2876  {  {
# Line 2361  osm_gps_map_clear_images (OsmGpsMap *map Line 2903  osm_gps_map_clear_images (OsmGpsMap *map
2903  }  }
2904    
2905  void  void
 osm_gps_map_osd_speed (OsmGpsMap *map, float speed)  
 {  
     OsmGpsMapPrivate *priv;  
   
     PangoContext        *context = NULL;  
     PangoLayout     *layout  = NULL;  
     PangoFontDescription    *desc    = NULL;  
   
     GdkColor color;  
     GdkGC *gc;  
   
     gchar *buffer;  
     //static int x = 10, y = 10;  
     static int width = 0, height = 0;  
   
     g_return_if_fail (OSM_IS_GPS_MAP (map));  
     priv = map->priv;  
   
     buffer = g_strdup_printf("%.0f", speed);  
   
     /* pango initialisation */  
     context = gtk_widget_get_pango_context (GTK_WIDGET(map));  
     layout  = pango_layout_new (context);  
     desc    = pango_font_description_new();  
   
     pango_font_description_set_size (desc, 40 * PANGO_SCALE);  
     pango_layout_set_font_description (layout, desc);  
     pango_layout_set_text (layout, buffer, strlen(buffer));  
   
     gc = gdk_gc_new (GTK_WIDGET(map)->window);  
   
     color.red = (0 > 50) ? 0xffff : 0;  
     color.green = 0;  
     color.blue = 0;  
   
     gdk_gc_set_rgb_fg_color (gc, &color);  
   
     /* faster / less flicker alternative:*/  
     gdk_draw_drawable (  
                        GTK_WIDGET(map)->window,  
                        GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(map)],  
                        priv->pixmap,  
                        0,0,  
                        0,0,  
                        width+10,width+10);  
   
     gdk_draw_layout(GTK_WIDGET(map)->window,  
                     gc,  
                     0, 0,  
                     layout);  
   
     /* set width and height */  
     pango_layout_get_pixel_size(layout, &width, &height);  
   
     g_free(buffer);  
     pango_font_description_free (desc);  
     g_object_unref (layout);  
     g_object_unref (gc);  
 }  
   
 void  
2906  osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)  osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
2907  {  {
2908      int pixel_x, pixel_y;      int pixel_x, pixel_y;
# Line 2433  osm_gps_map_draw_gps (OsmGpsMap *map, fl Line 2914  osm_gps_map_draw_gps (OsmGpsMap *map, fl
2914      priv->gps->rlat = deg2rad(latitude);      priv->gps->rlat = deg2rad(latitude);
2915      priv->gps->rlon = deg2rad(longitude);      priv->gps->rlon = deg2rad(longitude);
2916      priv->gps_valid = TRUE;      priv->gps_valid = TRUE;
2917        priv->gps_heading = deg2rad(heading);
2918    
2919      // pixel_x,y, offsets      // pixel_x,y, offsets
2920      pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);      pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
# Line 2463  osm_gps_map_draw_gps (OsmGpsMap *map, fl Line 2945  osm_gps_map_draw_gps (OsmGpsMap *map, fl
2945    
2946              priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;              priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
2947              priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;              priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
2948              priv->center_coord_set = FALSE;              center_coord_update(map);
2949          }          }
2950      }      }
2951    
# Line 2522  osm_gps_map_geographic_to_screen (OsmGps Line 3004  osm_gps_map_geographic_to_screen (OsmGps
3004      priv = map->priv;      priv = map->priv;
3005    
3006      if (pixel_x)      if (pixel_x)
3007          *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) - priv->map_x;          *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) -
3008                priv->map_x + priv->drag_mouse_dx;
3009      if (pixel_y)      if (pixel_y)
3010          *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) - priv->map_y;          *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) -
3011                priv->map_y + priv->drag_mouse_dy;
3012  }  }
3013    
3014  void  void
# Line 2535  osm_gps_map_scroll (OsmGpsMap *map, gint Line 3019  osm_gps_map_scroll (OsmGpsMap *map, gint
3019      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (OSM_IS_GPS_MAP (map));
3020      priv = map->priv;      priv = map->priv;
3021    
     priv->center_coord_set = FALSE;  
3022      priv->map_x += dx;      priv->map_x += dx;
3023      priv->map_y += dy;      priv->map_y += dy;
3024        center_coord_update(map);
3025    
3026    #ifdef ENABLE_OSD
3027        /* OSD may contain a coordinate, so we may have to re-render it */
3028        if(priv->osd && OSM_IS_GPS_MAP (priv->osd->widget))
3029            priv->osd->render (priv->osd);
3030    #endif
3031    
3032      osm_gps_map_map_redraw_idle (map);      osm_gps_map_map_redraw_idle (map);
3033  }  }
# Line 2547  osm_gps_map_get_scale(OsmGpsMap *map) Line 3037  osm_gps_map_get_scale(OsmGpsMap *map)
3037  {  {
3038      OsmGpsMapPrivate *priv;      OsmGpsMapPrivate *priv;
3039    
3040      g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_NAN);      g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_GPS_MAP_INVALID);
3041      priv = map->priv;      priv = map->priv;
3042    
3043      return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);      return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);
3044  }  }
3045    
3046    char * osm_gps_map_get_default_cache_directory(void)
3047    {
3048        return g_build_filename(
3049                            g_get_user_cache_dir(),
3050                            "osmgpsmap",
3051                            NULL);
3052    }
3053    
3054    void osm_gps_map_set_keyboard_shortcut(OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval)
3055    {
3056        g_return_if_fail (OSM_IS_GPS_MAP (map));
3057        g_return_if_fail(key < OSM_GPS_MAP_KEY_MAX);
3058    
3059        map->priv->keybindings[key] = keyval;
3060        map->priv->keybindings_enabled = TRUE;
3061    }
3062    
3063    #ifdef ENABLE_OSD
3064    
3065    void
3066    osm_gps_map_redraw (OsmGpsMap *map)
3067    {
3068        osm_gps_map_map_redraw_idle(map);
3069    }
3070    
3071    osm_gps_map_osd_t *
3072    osm_gps_map_osd_get(OsmGpsMap *map)
3073    {
3074        g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL);
3075        return map->priv->osd;
3076    }
3077    
3078    void
3079    osm_gps_map_register_osd(OsmGpsMap *map, osm_gps_map_osd_t *osd)
3080    {
3081        OsmGpsMapPrivate *priv;
3082    
3083        g_return_if_fail (OSM_IS_GPS_MAP (map));
3084    
3085        priv = map->priv;
3086        g_return_if_fail (!priv->osd);
3087    
3088        priv->osd = osd;
3089    }
3090    
3091    void
3092    osm_gps_map_repaint (OsmGpsMap *map)
3093    {
3094        osm_gps_map_expose (GTK_WIDGET(map), NULL);
3095    }
3096    
3097    coord_t *
3098    osm_gps_map_get_gps (OsmGpsMap *map)
3099    {
3100        g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL);
3101    
3102        if(!map->priv->gps_valid)
3103            return NULL;
3104    
3105        return map->priv->gps;
3106    }
3107    
3108    #endif

Legend:
Removed from v.55  
changed lines
  Added in v.280