--- trunk/src/osm-gps-map-osd-classic.c 2009/08/30 19:05:44 86 +++ trunk/src/osm-gps-map-osd-classic.c 2009/09/10 13:06:16 106 @@ -19,11 +19,7 @@ #include "config.h" #include // abs -#include // M_PI - -#define OSD_SOURCE_SEL - -#define OSD_Y (-10) +#include // M_PI/cos() /* parameters that can be overwritten from the config file: */ /* OSD_DIAMETER */ @@ -38,15 +34,35 @@ #include "osm-gps-map.h" #include "osm-gps-map-osd-classic.h" +#define OSD_COORDINATES + //the osd controls typedef struct { /* the offscreen representation of the OSD */ cairo_surface_t *overlay; +#ifdef OSD_SCALE + cairo_surface_t *scale; + int scale_zoom; +#endif + +#ifdef OSD_CROSSHAIR + cairo_surface_t *crosshair; +#endif + +#ifdef OSD_COORDINATES + cairo_surface_t *coordinates; +#endif + +#ifdef OSD_SOURCE_SEL + /* values to handle the "source" menu */ cairo_surface_t *map_source; gboolean expanded; gint shift, dir, count; gint handler_id; + gint width, height; +#endif + } osd_priv_t; /* position and extent of bounding box */ @@ -128,7 +144,6 @@ if(enabled) gdk_cairo_set_source_color(cr, fg); else gdk_cairo_set_source_color(cr, disabled); cairo_set_line_width (cr, width); - cairo_stroke (cr); } #else static void @@ -136,7 +151,6 @@ if(enabled) cairo_set_source_rgb (cr, OSD_COLOR); else cairo_set_source_rgb (cr, OSD_COLOR_DISABLED); cairo_set_line_width (cr, width); - cairo_stroke (cr); } #endif @@ -145,7 +159,6 @@ osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) { cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15); cairo_set_line_width (cr, width); - cairo_stroke (cr); } #endif @@ -262,6 +275,8 @@ return OSD_NONE; } +#ifdef OSD_SOURCE_SEL + /* place source selection at right border */ #define OSD_S_RAD (Z_RAD) #define OSD_S_X (-OSD_X) @@ -271,15 +286,22 @@ #define OSD_S_PH (2 * Z_RAD) #define OSD_S_H (OSD_S_PH + OSD_SHADOW) -/* size of usable area when exapnded */ -#define OSD_S_AREA_W (200) -#define OSD_S_AREA_H (200) +/* size of usable area when expanded */ +#define OSD_S_AREA_W (priv->width) +#define OSD_S_AREA_H (priv->height) #define OSD_S_EXP_W (OSD_S_PW + OSD_S_AREA_W + OSD_SHADOW) #define OSD_S_EXP_H (OSD_S_AREA_H + OSD_SHADOW) /* internal value to draw the arrow on the "puller" */ #define OSD_S_D0 (OSD_S_RAD/2) +#ifndef OSD_FONT_SIZE +#define OSD_FONT_SIZE 16.0 +#endif +#define OSD_TEXT_BORDER (OSD_FONT_SIZE/2) +#define OSD_TEXT_SKIP (OSD_FONT_SIZE/8) +/* draw the shape of the source selection OSD, either only the puller (not expanded) */ +/* or the entire menu incl. the puller (expanded) */ static void osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) { if(!priv->expanded) { @@ -305,22 +327,77 @@ } static void -osd_source_content(osd_priv_t *priv, cairo_t *cr, gint x, gint y) { - y += OSD_S_RAD - OSD_S_D0; +osd_source_content(osm_gps_map_osd_t *osd, cairo_t *cr, gint offset) { + osd_priv_t *priv = (osd_priv_t*)osd->priv; + + int py = offset + OSD_S_RAD - OSD_S_D0; if(!priv->expanded) { /* draw the "puller" open (<) arrow */ - cairo_move_to (cr, x + OSD_S_RAD + OSD_S_D0/2, y); + cairo_move_to (cr, offset + OSD_S_RAD + OSD_S_D0/2, py); cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0); cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0); } else { if(OSD_S_Y < 0) - y += OSD_S_AREA_H - OSD_S_PH; + py += OSD_S_AREA_H - OSD_S_PH; /* draw the "puller" close (>) arrow */ - cairo_move_to (cr, x + OSD_S_RAD - OSD_S_D0/2, y); + cairo_move_to (cr, offset + OSD_S_RAD - OSD_S_D0/2, py); cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0); cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0); + cairo_stroke(cr); + + /* don't draw a shadow for the text content */ + if(offset == 1) { + gint source; + g_object_get(osd->widget, "map-source", &source, NULL); + + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, OSD_FONT_SIZE); + + int i, step = (priv->height - 2*OSD_TEXT_BORDER) / + OSM_GPS_MAP_SOURCE_LAST; + for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) { + cairo_text_extents_t extents; + const char *src = osm_gps_map_source_get_friendly_name(i); + cairo_text_extents (cr, src, &extents); + + int x = offset + OSD_S_PW + OSD_TEXT_BORDER; + int y = offset + step * (i-1) + OSD_TEXT_BORDER; + + /* draw filled rectangle if selected */ + if(source == i) { + cairo_rectangle(cr, x - OSD_TEXT_BORDER/2, + y - OSD_TEXT_SKIP, + priv->width - OSD_TEXT_BORDER, + step + OSD_TEXT_SKIP); + cairo_fill(cr); + + /* temprarily draw with background color */ +#ifndef OSD_COLOR + GdkColor bg = osd->widget->style->bg[GTK_STATE_NORMAL]; + gdk_cairo_set_source_color(cr, &bg); +#else + cairo_set_source_rgb (cr, OSD_COLOR_BG); +#endif + } + + cairo_move_to (cr, x, y + OSD_TEXT_SKIP - extents.y_bearing); + cairo_show_text (cr, src); + + /* restore color */ + if(source == i) { +#ifndef OSD_COLOR + GdkColor fg = osd->widget->style->fg[GTK_STATE_NORMAL]; + gdk_cairo_set_source_color(cr, &fg); +#else + cairo_set_source_rgb (cr, OSD_COLOR); +#endif + } + } + } } } @@ -354,42 +431,69 @@ #endif #ifdef OSD_SHADOW_ENABLE - osd_source_content(priv, cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); osd_labels_shadow(cr, Z_RAD/3, TRUE); + osd_source_content(osd, cr, 1+OSD_LBL_SHADOW); + cairo_stroke (cr); #endif - osd_source_content(priv, cr, 1, 1); #ifndef OSD_COLOR osd_labels(cr, Z_RAD/3, TRUE, &fg, &da); #else osd_labels(cr, Z_RAD/3, TRUE); #endif + osd_source_content(osd, cr, 1); + cairo_stroke (cr); cairo_destroy(cr); } +/* re-allocate the buffer used to draw the menu. This is used */ +/* to collapse/expand the buffer */ static void osd_source_reallocate(osm_gps_map_osd_t *osd) { osd_priv_t *priv = (osd_priv_t*)osd->priv; /* re-allocate offscreen bitmap */ g_assert (priv->map_source); - cairo_surface_destroy(priv->map_source); int w = OSD_S_W, h = OSD_S_H; if(priv->expanded) { + cairo_text_extents_t extents; + + /* determine content size */ + cairo_t *cr = cairo_create(priv->map_source); + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, OSD_FONT_SIZE); + + /* calculate menu size */ + int i, max_h = 0, max_w = 0; + for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) { + const char *src = osm_gps_map_source_get_friendly_name(i); + cairo_text_extents (cr, src, &extents); + + if(extents.width > max_w) max_w = extents.width; + if(extents.height > max_h) max_h = extents.height; + } + cairo_destroy(cr); + + priv->width = max_w + 2*OSD_TEXT_BORDER; + priv->height = OSM_GPS_MAP_SOURCE_LAST * + (max_h + 2*OSD_TEXT_SKIP) + 2*OSD_TEXT_BORDER; + w = OSD_S_EXP_W; h = OSD_S_EXP_H; } + cairo_surface_destroy(priv->map_source); priv->map_source = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2); osd_render_source_sel(osd); - } #define OSD_HZ 15 -#define OSD_TIME 1000 +#define OSD_TIME 500 static gboolean osd_source_animate(gpointer data) { osm_gps_map_osd_t *osd = (osm_gps_map_osd_t*)data; @@ -417,10 +521,6 @@ /* count runs linearly from 0 to 1000, map this nicely onto a position */ - /* simple linear mapping */ - // priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) + - // (diff * priv->count)/1000; - /* nicer sinoid mapping */ float m = 0.5-cos(priv->count * M_PI / 1000.0)/2; priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) + @@ -461,6 +561,7 @@ priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd); } +/* check if the user clicked inside the source selection area */ static osd_button_t osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) { osd_priv_t *priv = (osd_priv_t*)osd->priv; @@ -487,8 +588,46 @@ return OSD_BG; } } + + /* check for clicks into data area */ + if(priv->expanded && !priv->handler_id) { + /* re-adjust from puller top to content top */ + if(OSD_S_Y < 0) + y += OSD_S_EXP_H - OSD_S_PH; + + if(x > OSD_S_PW && + x < OSD_S_PW + OSD_S_EXP_W && + y > 0 && + y < OSD_S_EXP_H) { + + int step = (priv->height - 2*OSD_TEXT_BORDER) + / OSM_GPS_MAP_SOURCE_LAST; + + y -= OSD_TEXT_BORDER - OSD_TEXT_SKIP; + y /= step; + y += 1; + + gint old = 0; + g_object_get(osd->widget, "map-source", &old, NULL); + + if(y > OSM_GPS_MAP_SOURCE_NULL && + y <= OSM_GPS_MAP_SOURCE_LAST && + old != y) { + g_object_set(osd->widget, "map-source", y, NULL); + + osd_render_source_sel(osd); + osm_gps_map_repaint(OSM_GPS_MAP(osd->widget)); + } + + /* return "clicked in OSD background" to prevent further */ + /* processing by application */ + return OSD_BG; + } + } + return OSD_NONE; } +#endif // OSD_SOURCE_SEL static osd_button_t osd_check(osm_gps_map_osd_t *osd, gint x, gint y) { @@ -594,8 +733,234 @@ cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID); } +#ifdef OSD_COORDINATES +#define OSD_COORDINATES_W 100 +#define OSD_COORDINATES_H 50 + +static void +osd_render_coordinates(osm_gps_map_osd_t *osd) +{ + osd_priv_t *priv = (osd_priv_t*)osd->priv; + + /* first fill with transparency */ + cairo_t *cr = cairo_create(priv->coordinates); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + // cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); + cairo_paint(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + + cairo_destroy(cr); +} +#endif // OSD_COORDINATES + +#ifdef OSD_CROSSHAIR + +#ifndef OSD_CROSSHAIR_RADIUS +#define OSD_CROSSHAIR_RADIUS 10 +#endif + +#define OSD_CROSSHAIR_TICK (OSD_CROSSHAIR_RADIUS/2) +#define OSD_CROSSHAIR_BORDER (OSD_CROSSHAIR_TICK + OSD_CROSSHAIR_RADIUS/4) +#define OSD_CROSSHAIR_W ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) +#define OSD_CROSSHAIR_H ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) + +static void +osd_render_crosshair_shape(cairo_t *cr) { + cairo_arc (cr, OSD_CROSSHAIR_W/2, OSD_CROSSHAIR_H/2, + OSD_CROSSHAIR_RADIUS, 0, 2*M_PI); + + cairo_move_to (cr, OSD_CROSSHAIR_W/2 - OSD_CROSSHAIR_RADIUS, + OSD_CROSSHAIR_H/2); + cairo_rel_line_to (cr, -OSD_CROSSHAIR_TICK, 0); + cairo_move_to (cr, OSD_CROSSHAIR_W/2 + OSD_CROSSHAIR_RADIUS, + OSD_CROSSHAIR_H/2); + cairo_rel_line_to (cr, OSD_CROSSHAIR_TICK, 0); + + cairo_move_to (cr, OSD_CROSSHAIR_W/2, + OSD_CROSSHAIR_H/2 - OSD_CROSSHAIR_RADIUS); + cairo_rel_line_to (cr, 0, -OSD_CROSSHAIR_TICK); + cairo_move_to (cr, OSD_CROSSHAIR_W/2, + OSD_CROSSHAIR_H/2 + OSD_CROSSHAIR_RADIUS); + cairo_rel_line_to (cr, 0, OSD_CROSSHAIR_TICK); + + cairo_stroke (cr); +} + static void -osd_render(osm_gps_map_osd_t *osd) { +osd_render_crosshair(osm_gps_map_osd_t *osd) +{ + osd_priv_t *priv = (osd_priv_t*)osd->priv; + + /* first fill with transparency */ + cairo_t *cr = cairo_create(priv->crosshair); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + // cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); + cairo_paint(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5); + cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/2); + osd_render_crosshair_shape(cr); + + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); + cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/4); + osd_render_crosshair_shape(cr); + + cairo_destroy(cr); +} +#endif + +#ifdef OSD_SCALE + +#ifndef OSD_SCALE_FONT_SIZE +#define OSD_SCALE_FONT_SIZE 12 +#endif +#define OSD_SCALE_W (10*OSD_SCALE_FONT_SIZE) +#define OSD_SCALE_H (5*OSD_SCALE_FONT_SIZE/2) + +/* various parameters used to create the scale */ +#define OSD_SCALE_H2 (OSD_SCALE_H/2) +#define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3) +#define OSD_SCALE_M (OSD_SCALE_H2 - OSD_SCALE_TICK) +#define OSD_SCALE_I (OSD_SCALE_H2 + OSD_SCALE_TICK) +#define OSD_SCALE_FD (OSD_SCALE_FONT_SIZE/4) + +static void +osd_render_scale(osm_gps_map_osd_t *osd) +{ + osd_priv_t *priv = (osd_priv_t*)osd->priv; + + /* this only needs to be rendered if the zoom has changed */ + gint zoom; + g_object_get(OSM_GPS_MAP(osd->widget), "zoom", &zoom, NULL); + if(zoom == priv->scale_zoom) + return; + + priv->scale_zoom = zoom; + + float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget)); + + /* first fill with transparency */ + cairo_t *cr = cairo_create(priv->scale); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0); + // pink for testing: cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); + cairo_paint(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + + /* determine the size of the scale width in meters */ + float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix; + + /* scale this to useful values */ + int exp = logf(width)*M_LOG10E; + int mant = width/pow(10,exp); + int width_metric = mant * pow(10,exp); + char *dist_str = NULL; + if(width_metric<1000) + dist_str = g_strdup_printf("%u m", width_metric); + else + dist_str = g_strdup_printf("%u km", width_metric/1000); + width_metric /= m_per_pix; + + /* and now the hard part: scale for useful imperial values :-( */ + /* try to convert to feet, 1ft == 0.3048 m */ + width /= 0.3048; + float imp_scale = 0.3048; + char *dist_imp_unit = "ft"; + + if(width >= 100) { + /* 1yd == 3 feet */ + width /= 3.0; + imp_scale *= 3.0; + dist_imp_unit = "yd"; + + if(width >= 1760.0) { + /* 1mi == 1760 yd */ + width /= 1760.0; + imp_scale *= 1760.0; + dist_imp_unit = "mi"; + } + } + + /* also convert this to full tens/hundreds */ + exp = logf(width)*M_LOG10E; + mant = width/pow(10,exp); + int width_imp = mant * pow(10,exp); + char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit); + + /* convert back to pixels */ + width_imp *= imp_scale; + width_imp /= m_per_pix; + + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + + cairo_text_extents_t extents; + cairo_text_extents (cr, dist_str, &extents); + + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); + cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); + cairo_text_path (cr, dist_str); + cairo_stroke (cr); + cairo_move_to (cr, 2*OSD_SCALE_FD, + OSD_SCALE_H2+OSD_SCALE_FD + extents.height); + cairo_text_path (cr, dist_str_imp); + cairo_stroke (cr); + + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); + cairo_show_text (cr, dist_str); + cairo_move_to (cr, 2*OSD_SCALE_FD, + OSD_SCALE_H2+OSD_SCALE_FD + extents.height); + cairo_show_text (cr, dist_str_imp); + + g_free(dist_str); + g_free(dist_str_imp); + + /* draw white line */ + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); + cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3); + cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); + cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); + cairo_rel_line_to (cr, width_metric, 0); + cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); + cairo_stroke(cr); + cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); + cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); + cairo_rel_line_to (cr, width_imp, 0); + cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); + cairo_stroke(cr); + + /* draw black line */ + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); + cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); + cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); + cairo_rel_line_to (cr, width_metric, 0); + cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); + cairo_stroke(cr); + cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); + cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); + cairo_rel_line_to (cr, width_imp, 0); + cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); + cairo_stroke(cr); + + cairo_destroy(cr); +} +#endif + +static void +osd_render(osm_gps_map_osd_t *osd) +{ osd_priv_t *priv = (osd_priv_t*)osd->priv; #ifndef OSD_COLOR @@ -641,38 +1006,57 @@ /* --------- draw zoom and dpad labels --------- */ #ifdef OSD_SHADOW_ENABLE + osd_labels_shadow(cr, Z_RAD/3, TRUE); osd_zoom_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); #ifndef OSD_NO_DPAD osd_dpad_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); #endif - osd_labels_shadow(cr, Z_RAD/3, TRUE); + cairo_stroke(cr); #ifdef OSD_GPS_BUTTON - osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL); + osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); + cairo_stroke(cr); #endif #endif - osd_zoom_labels(cr, 1, 1); -#ifndef OSD_NO_DPAD - osd_dpad_labels(cr, 1, 1); -#endif #ifndef OSD_COLOR osd_labels(cr, Z_RAD/3, TRUE, &fg, &da); #else osd_labels(cr, Z_RAD/3, TRUE); #endif -#ifdef OSD_GPS_BUTTON - osd_dpad_gps(cr, 1, 1); + osd_zoom_labels(cr, 1, 1); +#ifndef OSD_NO_DPAD + osd_dpad_labels(cr, 1, 1); +#endif + cairo_stroke(cr); + #ifndef OSD_COLOR osd_labels(cr, Z_RAD/6, osd->cb != NULL, &fg, &da); #else osd_labels(cr, Z_RAD/6, osd->cb != NULL); #endif +#ifdef OSD_GPS_BUTTON + osd_dpad_gps(cr, 1, 1); #endif + cairo_stroke(cr); cairo_destroy(cr); +#ifdef OSD_SOURCE_SEL osd_render_source_sel(osd); +#endif + +#ifdef OSD_SCALE + osd_render_scale(osd); +#endif + +#ifdef OSD_CROSSHAIR + osd_render_crosshair(osd); +#endif + +#ifdef OSD_COORDINATES + osd_render_coordinates(osd); +#endif } static void @@ -687,10 +1071,31 @@ priv->overlay = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2); +#ifdef OSD_SOURCE_SEL /* the initial OSD state is alway not-expanded */ priv->map_source = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_S_W+2, OSD_S_H+2); +#endif + +#ifdef OSD_SCALE + priv->scale = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + OSD_SCALE_W, OSD_SCALE_H); + priv->scale_zoom = -1; +#endif + +#ifdef OSD_CROSSHAIR + priv->crosshair = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + OSD_CROSSHAIR_W, OSD_CROSSHAIR_H); +#endif + +#ifdef OSD_COORDINATES + priv->coordinates = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + OSD_COORDINATES_W, OSD_COORDINATES_H); +#endif /* ... and render it */ osd_render(osd); @@ -699,12 +1104,43 @@ // now draw this onto the original context cairo_t *cr = gdk_cairo_create(drawable); - int x = OSD_X, y = OSD_Y; - if(OSD_X < 0) - x = osd->widget->allocation.width - OSD_W + OSD_X; + int x, y; - if(OSD_Y < 0) - y = osd->widget->allocation.height - OSD_H + OSD_Y; +#ifdef OSD_SCALE + x = OSD_X; + y = -OSD_Y; + if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W; + if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H; + + cairo_set_source_surface(cr, priv->scale, x, y); + cairo_paint(cr); +#endif + +#ifdef OSD_CROSSHAIR + x = (osd->widget->allocation.width - OSD_CROSSHAIR_W)/2; + y = (osd->widget->allocation.height - OSD_CROSSHAIR_H)/2; + + cairo_set_source_surface(cr, priv->crosshair, x, y); + cairo_paint(cr); +#endif + +#ifdef OSD_COORDINATES + x = -OSD_X; + y = -OSD_Y; + if(x < 0) x += osd->widget->allocation.width - OSD_COORDINATES_W; + if(y < 0) y += osd->widget->allocation.height - OSD_COORDINATES_H; + + cairo_set_source_surface(cr, priv->coordinates, x, y); + cairo_paint(cr); +#endif + + x = OSD_X; + if(x < 0) + x += osd->widget->allocation.width - OSD_W; + + y = OSD_Y; + if(y < 0) + y += osd->widget->allocation.height - OSD_H; cairo_set_source_surface(cr, priv->overlay, x, y); cairo_paint(cr); @@ -739,23 +1175,54 @@ { osd_priv_t *priv = (osd_priv_t *)(osd->priv); - if(priv->handler_id) - gtk_timeout_remove(priv->handler_id); - if (priv->overlay) cairo_surface_destroy(priv->overlay); +#ifdef OSD_SOURCE_SEL + if(priv->handler_id) + gtk_timeout_remove(priv->handler_id); + if (priv->map_source) cairo_surface_destroy(priv->map_source); +#endif + +#ifdef OSD_SCALE + if (priv->scale) + cairo_surface_destroy(priv->scale); +#endif + +#ifdef OSD_CROSSHAIR + if (priv->crosshair) + cairo_surface_destroy(priv->crosshair); +#endif + +#ifdef OSD_COORDINATES + if (priv->coordinates) + cairo_surface_destroy(priv->coordinates); +#endif g_free(priv); } +static gboolean +osd_busy(osm_gps_map_osd_t *osd) +{ +#ifdef OSD_SOURCE_SEL + osd_priv_t *priv = (osd_priv_t *)(osd->priv); + return (priv->handler_id != 0); +#else + return FALSE; +#endif +} + static osm_gps_map_osd_t osd_classic = { + .widget = NULL, + .draw = osd_draw, .check = osd_check, .render = osd_render, .free = osd_free, + .busy = osd_busy, .cb = NULL, .data = NULL,