static void scale_render(GpsdViewerOsd *self, OsmGpsMap *map) { GpsdViewerOsdScale *scale = self->priv->scale; if(!scale->surface) return; /* this only needs to be rendered if the zoom or latitude has changed */ gint zoom; gfloat lat; g_object_get(G_OBJECT(map), "zoom", &zoom, "latitude", &lat, NULL); if(zoom == scale->zoom && lat == scale->lat) return; scale->zoom = zoom; scale->lat = lat; float m_per_pix = osm_gps_map_get_scale(map); /* first fill with transparency */ g_assert(scale->surface); cairo_t *cr = cairo_create(scale->surface); 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 = (GPSD_VIEWER_OSD_SCALE_W-GPSD_VIEWER_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, GPSD_VIEWER_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, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6); cairo_move_to (cr, 2*GPSD_VIEWER_OSD_SCALE_FD, GPSD_VIEWER_OSD_SCALE_H2-GPSD_VIEWER_OSD_SCALE_FD); cairo_text_path (cr, dist_str); cairo_stroke (cr); cairo_move_to (cr, 2*GPSD_VIEWER_OSD_SCALE_FD, GPSD_VIEWER_OSD_SCALE_H2+GPSD_VIEWER_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*GPSD_VIEWER_OSD_SCALE_FD, GPSD_VIEWER_OSD_SCALE_H2-GPSD_VIEWER_OSD_SCALE_FD); cairo_show_text (cr, dist_str); cairo_move_to (cr, 2*GPSD_VIEWER_OSD_SCALE_FD, GPSD_VIEWER_OSD_SCALE_H2+GPSD_VIEWER_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, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/3); cairo_move_to (cr, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6, GPSD_VIEWER_OSD_SCALE_M); cairo_rel_line_to (cr, 0, GPSD_VIEWER_OSD_SCALE_TICK); cairo_rel_line_to (cr, width_metric, 0); cairo_rel_line_to (cr, 0, -GPSD_VIEWER_OSD_SCALE_TICK); cairo_stroke(cr); cairo_move_to (cr, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6, GPSD_VIEWER_OSD_SCALE_I); cairo_rel_line_to (cr, 0, -GPSD_VIEWER_OSD_SCALE_TICK); cairo_rel_line_to (cr, width_imp, 0); cairo_rel_line_to (cr, 0, +GPSD_VIEWER_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, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6); cairo_move_to (cr, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6, GPSD_VIEWER_OSD_SCALE_M); cairo_rel_line_to (cr, 0, GPSD_VIEWER_OSD_SCALE_TICK); cairo_rel_line_to (cr, width_metric, 0); cairo_rel_line_to (cr, 0, -GPSD_VIEWER_OSD_SCALE_TICK); cairo_stroke(cr); cairo_move_to (cr, GPSD_VIEWER_OSD_SCALE_FONT_SIZE/6, GPSD_VIEWER_OSD_SCALE_I); cairo_rel_line_to (cr, 0, -GPSD_VIEWER_OSD_SCALE_TICK); cairo_rel_line_to (cr, width_imp, 0); cairo_rel_line_to (cr, 0, +GPSD_VIEWER_OSD_SCALE_TICK); cairo_stroke(cr); cairo_destroy(cr); }
static int dist2pixel(OsmGpsMap *map, float km) { return 1000.0*km/osm_gps_map_get_scale(map); }