]> err.no Git - mapper/commitdiff
Some more map widget work
authorKaj-Michael Lang <milang@tal.org>
Fri, 2 May 2008 13:06:27 +0000 (16:06 +0300)
committerKaj-Michael Lang <milang@tal.org>
Fri, 2 May 2008 13:06:27 +0000 (16:06 +0300)
src/gtkmap.c

index 422858a249e9214918ac6e3f12ac267df8bf4c68..6b45832048509c722a3649e5a9ba3b79be8513ac 100644 (file)
@@ -17,6 +17,7 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <stdlib.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
 #include <math.h>
@@ -55,6 +56,10 @@ struct _GtkMapPriv
        /* Map image buffer */
        GdkPixmap *buffer;
 
+#ifdef WITH_CAIRO
+       cairo_t *ct;
+#endif
+
        PangoContext *context;
        PangoLayout *layout;
        PangoFontDescription *fontdesc;
@@ -87,14 +92,14 @@ struct _GtkMapPriv
        GdkGLConfig* gl_config;
 #endif
 
+       GdkGC *gc_mark;
+       GdkGC *gc_velvec;
+
        gint mark_x1;
        gint mark_x2;
        gint mark_y1;
        gint mark_y2;
-       gint mark_minx;
-       gint mark_miny;
-       gint mark_width;
-       gint mark_height;
+       GdkRectangle mark_rect;
 
        guint buf_width_tiles;
        guint buf_height_tiles;
@@ -180,12 +185,15 @@ struct _GtkMapPriv
 #define unit2y(unit) (unit2pixel(unit) - tile2pixel(priv->base_tiley) - priv->offsety)
 #define y2unit(y) (pixel2unit(y + priv->offsety) + tile2unit(priv->base_tiley))
 
-#define leadx2unit (location->unitx + (priv->lead_ratio) * pixel2unit(priv->vel_offsetx))
-#define leady2unit (location->unity + (0.6f*priv->lead_ratio) * pixel2unit(priv->vel_offsety))
+#define leadx2unit (priv->location.unitx + (priv->lead_ratio) * pixel2unit(priv->vel_offsetx))
+#define leady2unit (priv->location.unity + (0.6f*priv->lead_ratio) * pixel2unit(priv->vel_offsety))
 
 #define GTK_MAP_TILE_SIZE_PIXELS (256)
 #define GTK_MAP_TILE_SIZE_P2 (8)
-#define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2))
+
+/* #define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2)) */
+
+#define GTK_MAP_WORLD_SIZE_UNITS (1<<31)
 
 /* Pans are done two "grids" at a time, or 64 pixels. */
 #define GTK_MAP_PAN_UNITS (grid2unit(2))
@@ -193,8 +201,8 @@ struct _GtkMapPriv
 #define GTK_MAP_MACRO_RECALC_CENTER(center_unitx, center_unity) { \
        switch(priv->center_mode) { \
                case CENTER_LEAD: \
-                       priv->center.unitx = leadx2unit; \
-                       priv->center.unity = leady2unit; \
+                       priv->center.unitx = priv->leadx2unit; \
+                       priv->center.unity = priv->leady2unit; \
                break; \
                case CENTER_LATLON: \
                        priv->center.unitx = priv->location.unitx; \
@@ -207,14 +215,26 @@ struct _GtkMapPriv
        } \
 };
 
-#define GTK_MAP_RECALC_OFFSET(center) { \
+#define GTK_MAP_MACRO_RECALC_OFFSET(center) { \
        priv->offsetx = grid2pixel(unit2grid(center.unitx) - priv->screen_grids_halfwidth - tile2grid(priv->base_tilex)); \
        priv->offsety = grid2pixel(unit2grid(center.unity) - priv->screen_grids_halfheight - tile2grid(priv->base_tiley)); \
 }
 
-#define GTK_MAP_RECALC_FOCUS_BASE(sens) { \
-       priv->focus.unitx = x2unit(priv->screen_width_pixels * sens / 20); \
-       priv->focus.unity = y2unit(priv->screen_height_pixels * sens / 20); \
+#define GTK_MAP_MACRO_RECALC_FOCUS_BASE { \
+       priv->focus.unitx = x2unit(priv->screen_width_pixels * priv->center_ratio / 20); \
+       priv->focus.unity = y2unit(priv->screen_height_pixels * priv->center_ratio / 20); \
+}
+
+#define GTK_MAP_MACRO_RECALC_FOCUS_SIZE { \
+       priv->focus_unitwidth = pixel2unit((10 - priv->center_ratio) * priv->screen_width_pixels / 10); \
+       priv->focus_unitheight = pixel2unit((10 - priv->center_ratio) * priv->screen_height_pixels / 10); \
+}
+
+#define GTK_MAP_MACRO_RECALC_CENTER_BOUNDS() { \
+       priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth)); \
+       priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight)); \
+       priv->max_center.unitx = GTK_MAP_WORLD_SIZE_UNITS-grid2unit(priv->screen_grids_halfwidth) - 1; \
+       priv->max_center.unity = GTK_MAP_WORLD_SIZE_UNITS-grid2unit(priv->screen_grids_halfheight) - 1; \
 }
 
 #define BOUND(x, a, b) { \
@@ -233,6 +253,7 @@ static gboolean gtk_map_expose(GtkWidget *widget, GdkEventExpose *event);
 static gboolean gtk_map_configure(GtkWidget *widget, GdkEventConfigure *event);
 
 static void gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event);
+static void gtk_map_draw_mark(GtkWidget *widget, GdkEventExpose *event);
 
 static gboolean gtk_map_update_buffer_size(GtkMap *map, gint new_width, gint new_height);
 
@@ -288,9 +309,13 @@ gtk_map_init(GtkMap *map)
 GtkMapPriv *priv;
 GdkColor color;
 
-g_debug("MAP: Init");
+g_debug("GTKMAP: Init");
 priv=GTK_MAP_GET_PRIVATE(map);
 
+#ifdef WITH_CAIRO
+priv->ct=gdk_cairo_create(GTK_WIDGET(map)->window);
+#endif
+
 priv->zoom=3;
 priv->center_mode=CENTER_LATLON;
 priv->base_tilex=-5;
@@ -386,8 +411,8 @@ priv->screen_grids_halfheight = pixel2grid(priv->screen_height_pixels) / 2;
 priv->scale_rect.x = (priv->screen_width_pixels - SCALE_WIDTH) / 2;
 priv->scale_rect.width = SCALE_WIDTH;
 
-GTK_MAP_MACRO_RECALC_FOCUS_BASE(priv->center_ratio);
-GTK_MAP_MACRO_RECALC_FOCUS_SIZE(priv->center_ratio);
+GTK_MAP_MACRO_RECALC_FOCUS_BASE;
+GTK_MAP_MACRO_RECALC_FOCUS_SIZE;
 
 priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth));
 priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight));
@@ -530,16 +555,83 @@ gtk_map_paths_draw(widget, event);
 
 gtk_map_markers_draw(widget, event);
 
-gtk_map_mark_draw(widget, event);
-
 gtk_map_speed_draw(widget, event);
 #endif
 
+gtk_map_mark_draw(widget, event);
 gtk_map_scale_draw(widget, event);
 
 return TRUE;
 }
 
+static void 
+gtk_map_draw_mark(GtkWidget *widget, GdkEventExpose *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+#if 0
+if (!priv->draw_mark)
+       return;
+#endif
+
+if (!gdk_rectangle_intersect(&event->area, &priv->mark_rect, &event->area))
+       return;
+
+#ifdef WITH_CAIRO
+cairo_arc(priv->ct, priv->mark_x1, priv->marky1, priv->draw_width*2, 0, 2 * M_PI);
+cairo_set_source_rgb(priv->ct, 1, 1, 1);
+cairo_fill_preserve(priv->ct);
+cairo_set_source_rgb(priv->ct, 0, 0, 0);
+if (priv->show_velvec) {
+       cairo_save(priv->ct);
+       cairo_set_line_width(priv->ct, priv->draw_width);
+       cairo_move_to(priv->ct, priv->mark_x1, priv->marky1);
+       cairo_line_to(priv->ct, priv->mark_x2, priv->marky2);
+       cairo_restore(priv->ct);
+}
+cairo_stroke(priv->ct);
+#else
+gdk_draw_arc(widget->window,
+       priv->gc_mark,
+       FALSE,
+       priv->mark_x1 - priv->draw_width,
+       priv->mark_y1 - priv->draw_width,
+       2 * priv->draw_width,
+       2 * priv->draw_width,
+       0, 360 * 64);
+
+if (priv->show_velvec)
+       gdk_draw_line(widget->window, 
+               priv->gc_velvec,
+               priv->mark_x1, priv->mark_y1, 
+               priv->mark_x2, priv->mark_y2);
+#endif
+}
+
+static void 
+gtk_map_calculate_mark(GtkWidget *widget)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+priv->mark_x1 = unit2x(priv->location.unitx);
+priv->mark_y1 = unit2y(priv->location.unity);
+priv->mark_x2 = priv->mark_x1 + (priv->show_velvec ? priv->vel_offsetx : 0);
+priv->mark_y2 = priv->mark_y1 + (priv->show_velvec ? priv->vel_offsety : 0);
+
+priv->mark_rect.x= = MIN(priv->mark_x1, priv->mark_x2) - (2 * priv->draw_width);
+priv->mark_rect.y = MIN(priv->mark_y1, priv->mark_y2) - (2 * priv->draw_width);
+priv->mark_rect.width = abs(priv->mark_x1 - priv->mark_x2) + (4 * priv->draw_width);
+priv->mark_rect.height = abs(priv->mark_y1 - priv->mark_y2) + (4 * priv->draw_width);
+}
+
 static void 
 gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event)
 {
@@ -654,7 +746,7 @@ priv=GTK_MAP_GET_PRIVATE(map);
 if (priv->speed<0)
        return;
 
-buffer=g_snprintf(buffer, sizeof(buffer), "%0.0f %s", priv->speed * priv->units_conv, priv->units_str);
+g_snprintf(buffer, sizeof(buffer), "%0.0f %s", priv->speed * priv->units_conv, priv->units_str);
 map_information_text(10, 10, priv->speed_gc, buffer);
 }
 
@@ -673,9 +765,7 @@ priv->speed=speed;
 }
 
 /**
- * Do an in-place scaling of a pixbuf's pixels at the given ratio from the
- * given source location.  It would have been nice if gdk_pixbuf provided
- * this method, but I guess it's not general-purpose enough.
+ * Do an in-place scaling of a pixbuf's pixels at the given ratio from the given source location.
  */
 static void
 gtk_map_pixbuf_scale_inplace(GdkPixbuf *pixbuf, guint ratio_p2, guint src_x, guint src_y)
@@ -751,7 +841,6 @@ if (tilex > priv->world_size_tiles || tiley > priv->world_size_tiles)
 
 /* g_debug("MAP RT: %u %u (%u) %u %u (%u, %u)", tilex, tiley, priv->world_size_tiles, destx, desty, buf_width_tiles, buf_height_tiles); */
 
-/* The tile is possible. */
 for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zoff) <= priv->max_zoom && zoff <= GTK_MAP_TILE_SIZE_P2; zoff += 1) {
        pixbuf=gtk_map_tile_load(map, tilex, tiley, zoff, !fast_fail);
        if (!pixbuf) {
@@ -761,8 +850,8 @@ for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zof
                /* Check if we need to blit. */
                if (zoff) {
                        gtk_map_pixbuf_scale_inplace(pixbuf, zoff,
-                                       (tilex - ((tilex >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff),
-                                       (tiley - ((tiley >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff));
+                               (tilex - ((tilex >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff),
+                               (tiley - ((tiley >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff));
                        image_cache_invalidate_by_image(priv->icache, pixbuf);
                }
        }
@@ -813,8 +902,7 @@ priv->center.unity = new_center_unity;
 new_base_tilex = grid2tile((gint) pixel2grid((gint)unit2pixel((gint) priv->center.unitx)) - (gint)priv->screen_grids_halfwidth);
 new_base_tiley = grid2tile(pixel2grid(unit2pixel(priv->center.unity)) - priv->screen_grids_halfheight);
 
-/* Same zoom level, so it's likely that we can reuse some of the old
- * buffer's pixels. */
+/* Same zoom level, so it's likely that we can reuse some of the old buffer's pixels. */
 
 if (new_base_tilex != priv->base_tilex || new_base_tiley != priv->base_tiley) {
        /* If copying from old parts to new parts, we need to make sure we
@@ -954,7 +1042,6 @@ gtk_map_refresh(map);
 return TRUE;
 }
 
-
 gint 
 gtk_map_zoom(GtkWidget *widget, gint zdir)
 {