+
+static void trw_layer_draw_track_label ( gchar *name, gchar *fgcolour, gchar *bgcolour, struct DrawingParams *dp, VikCoord *coord )
+{
+ gchar *label_markup = g_strdup_printf ( "<span foreground=\"%s\" background=\"%s\" size=\"%s\">%s</span>", fgcolour, bgcolour, dp->vtl->track_fsize_str, name );
+
+ if ( pango_parse_markup ( label_markup, -1, 0, NULL, NULL, NULL, NULL ) )
+ pango_layout_set_markup ( dp->vtl->tracklabellayout, label_markup, -1 );
+ else
+ // Fallback if parse failure
+ pango_layout_set_text ( dp->vtl->tracklabellayout, name, -1 );
+
+ g_free ( label_markup );
+
+ gint label_x, label_y;
+ gint width, height;
+ pango_layout_get_pixel_size ( dp->vtl->tracklabellayout, &width, &height );
+
+ vik_viewport_coord_to_screen ( dp->vp, coord, &label_x, &label_y );
+ vik_viewport_draw_layout ( dp->vp, dp->vtl->track_bg_gc, label_x-width/2, label_y-height/2, dp->vtl->tracklabellayout );
+}
+
+/**
+ * distance_in_preferred_units:
+ * @dist: The source distance in standard SI Units (i.e. metres)
+ *
+ * TODO: This is a generic function that could be moved into globals.c or utils.c
+ *
+ * Probably best used if you have a only few conversions to perform.
+ * However if doing many points (such as on all points along a track) then this may be a bit slow,
+ * since it will be doing the preference check on each call
+ *
+ * Returns: The distance in the units as specified by the preferences
+ */
+static gdouble distance_in_preferred_units ( gdouble dist )
+{
+ gdouble mydist;
+ vik_units_distance_t dist_units = a_vik_get_units_distance ();
+ switch (dist_units) {
+ case VIK_UNITS_DISTANCE_MILES:
+ mydist = VIK_METERS_TO_MILES(dist);
+ break;
+ case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+ mydist = VIK_METERS_TO_NAUTICAL_MILES(dist);
+ break;
+ // VIK_UNITS_DISTANCE_KILOMETRES:
+ default:
+ mydist = dist/1000.0;
+ break;
+ }
+ return mydist;
+}
+
+/**
+ * trw_layer_draw_dist_labels:
+ *
+ * Draw a few labels along a track at nicely seperated distances
+ * This might slow things down if there's many tracks being displayed with this on.
+ */
+static void trw_layer_draw_dist_labels ( struct DrawingParams *dp, VikTrack *trk, gboolean drawing_highlight )
+{
+ static const gdouble chunksd[] = {0.25, 0.5, 1.0, 2.0, 5.0, 10.0, 15.0, 20.0,
+ 25.0, 40.0, 50.0, 75.0, 100.0,
+ 150.0, 200.0, 250.0, 500.0, 1000.0};
+
+ gdouble dist = vik_track_get_length_including_gaps ( trk ) / (trk->max_number_dist_labels+1);
+
+ // Convert to specified unit to find the friendly breakdown value
+ dist = distance_in_preferred_units ( dist );
+
+ gint index = 0;
+ gint i=0;
+ for ( i = 0; i < G_N_ELEMENTS(chunksd); i++ ) {
+ if ( chunksd[i] > dist ) {
+ index = i;
+ dist = chunksd[index];
+ break;
+ }
+ }
+
+ vik_units_distance_t dist_units = a_vik_get_units_distance ();
+
+ for ( i = 1; i < trk->max_number_dist_labels+1; i++ ) {
+ gdouble dist_i = dist * i;
+
+ // Convert distance back into metres for use in finding a trackpoint
+ switch (dist_units) {
+ case VIK_UNITS_DISTANCE_MILES:
+ dist_i = VIK_MILES_TO_METERS(dist_i);
+ break;
+ case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+ dist_i = VIK_NAUTICAL_MILES_TO_METERS(dist_i);
+ break;
+ // VIK_UNITS_DISTANCE_KILOMETRES:
+ default:
+ dist_i = dist_i*1000.0;
+ break;
+ }
+
+ gdouble dist_current = 0.0;
+ VikTrackpoint *tp_current = vik_track_get_tp_by_dist ( trk, dist_i, FALSE, &dist_current );
+ gdouble dist_next = 0.0;
+ VikTrackpoint *tp_next = vik_track_get_tp_by_dist ( trk, dist_i, TRUE, &dist_next );
+
+ gdouble dist_between_tps = fabs (dist_next - dist_current);
+ gdouble ratio = 0.0;
+ // Prevent division by 0 errors
+ if ( dist_between_tps > 0.0 )
+ ratio = fabs(dist_i-dist_current)/dist_between_tps;
+
+ if ( tp_current && tp_next ) {
+ // Construct the name based on the distance value
+ gchar *name;
+ gchar *units;
+ switch (dist_units) {
+ case VIK_UNITS_DISTANCE_MILES:
+ units = g_strdup ( _("miles") );
+ break;
+ // VIK_UNITS_DISTANCE_KILOMETRES:
+ default:
+ units = g_strdup ( _("km") );
+ break;
+ }
+
+ // Convert for display
+ dist_i = distance_in_preferred_units ( dist_i );
+
+ // Make the precision of the output related to the unit size.
+ if ( index == 0 )
+ name = g_strdup_printf ( "%.2f %s", dist_i, units);
+ else if ( index == 1 )
+ name = g_strdup_printf ( "%.1f %s", dist_i, units);
+ else
+ name = g_strdup_printf ( "%d %s", (gint)round(dist_i), units); // TODO single vs plurals
+ g_free ( units );
+
+ struct LatLon ll_current, ll_next;
+ vik_coord_to_latlon ( &tp_current->coord, &ll_current );
+ vik_coord_to_latlon ( &tp_next->coord, &ll_next );
+
+ // positional interpolation
+ // Using a simple ratio - may not be perfectly correct due to lat/long projections
+ // but should be good enough over the small scale that I anticipate usage on
+ struct LatLon ll_new = { ll_current.lat + (ll_next.lat-ll_current.lat)*ratio,
+ ll_current.lon + (ll_next.lon-ll_current.lon)*ratio };
+ VikCoord coord;
+ vik_coord_load_from_latlon ( &coord, dp->vtl->coord_mode, &ll_new );
+
+ gchar *fgcolour;
+ if ( dp->vtl->drawmode == DRAWMODE_BY_TRACK )
+ fgcolour = gdk_color_to_string ( &(trk->color) );
+ else
+ fgcolour = gdk_color_to_string ( &(dp->vtl->track_color) );
+
+ // if highlight mode on, then colour the background in the highlight colour
+ gchar *bgcolour;
+ if ( drawing_highlight )
+ bgcolour = g_strdup ( vik_viewport_get_highlight_color ( dp->vp ) );
+ else
+ bgcolour = gdk_color_to_string ( &(dp->vtl->track_bg_color) );
+
+ trw_layer_draw_track_label ( name, fgcolour, bgcolour, dp, &coord );
+
+ g_free ( fgcolour );
+ g_free ( bgcolour );
+ g_free ( name );
+ }
+ }
+}
+
+/**
+ * trw_layer_draw_track_name_labels:
+ *
+ * Draw a label (or labels) for the track name somewhere depending on the track's properties
+ */
+static void trw_layer_draw_track_name_labels ( struct DrawingParams *dp, VikTrack *trk, gboolean drawing_highlight )
+{
+ gchar *fgcolour;
+ if ( dp->vtl->drawmode == DRAWMODE_BY_TRACK )
+ fgcolour = gdk_color_to_string ( &(trk->color) );
+ else
+ fgcolour = gdk_color_to_string ( &(dp->vtl->track_color) );
+
+ // if highlight mode on, then colour the background in the highlight colour
+ gchar *bgcolour;
+ if ( drawing_highlight )
+ bgcolour = g_strdup ( vik_viewport_get_highlight_color ( dp->vp ) );
+ else
+ bgcolour = gdk_color_to_string ( &(dp->vtl->track_bg_color) );
+
+ gchar *ename = g_markup_escape_text ( trk->name, -1 );
+
+ if ( trk->draw_name_mode == TRACK_DRAWNAME_START_END_CENTRE ||
+ trk->draw_name_mode == TRACK_DRAWNAME_CENTRE ) {
+ struct LatLon average, maxmin[2] = { {0,0}, {0,0} };
+ trw_layer_find_maxmin_tracks ( NULL, trk, maxmin );
+ average.lat = (maxmin[0].lat+maxmin[1].lat)/2;
+ average.lon = (maxmin[0].lon+maxmin[1].lon)/2;
+ VikCoord coord;
+ vik_coord_load_from_latlon ( &coord, dp->vtl->coord_mode, &average );
+
+ trw_layer_draw_track_label ( ename, fgcolour, bgcolour, dp, &coord );
+ }
+
+ if ( trk->draw_name_mode == TRACK_DRAWNAME_CENTRE )
+ // No other labels to draw
+ return;
+
+ VikTrackpoint *tp_end = vik_track_get_tp_last ( trk );
+ if ( !tp_end )
+ return;
+ VikTrackpoint *tp_begin = vik_track_get_tp_first ( trk );
+ if ( !tp_begin )
+ return;
+ VikCoord begin_coord = tp_begin->coord;
+ VikCoord end_coord = tp_end->coord;
+
+ gboolean done_start_end = FALSE;
+
+ if ( trk->draw_name_mode == TRACK_DRAWNAME_START_END ||
+ trk->draw_name_mode == TRACK_DRAWNAME_START_END_CENTRE ) {
+
+ // This number can be configured via the settings if you really want to change it
+ gdouble distance_diff;
+ if ( ! a_settings_get_double ( "trackwaypoint_start_end_distance_diff", &distance_diff ) )
+ distance_diff = 100.0; // Metres
+
+ if ( vik_coord_diff ( &begin_coord, &end_coord ) < distance_diff ) {
+ // Start and end 'close' together so only draw one label at an average location
+ gint x1, x2, y1, y2;
+ vik_viewport_coord_to_screen ( dp->vp, &begin_coord, &x1, &y1);
+ vik_viewport_coord_to_screen ( dp->vp, &end_coord, &x2, &y2);
+ VikCoord av_coord;
+ vik_viewport_screen_to_coord ( dp->vp, (x1 + x2) / 2, (y1 + y2) / 2, &av_coord );
+
+ gchar *name = g_strdup_printf ( "%s: %s", ename, _("start/end") );
+ trw_layer_draw_track_label ( name, fgcolour, bgcolour, dp, &av_coord );
+ g_free ( name );
+
+ done_start_end = TRUE;
+ }
+ }
+
+ if ( ! done_start_end ) {
+ if ( trk->draw_name_mode == TRACK_DRAWNAME_START ||
+ trk->draw_name_mode == TRACK_DRAWNAME_START_END ||
+ trk->draw_name_mode == TRACK_DRAWNAME_START_END_CENTRE ) {
+ gchar *name_start = g_strdup_printf ( "%s: %s", ename, _("start") );
+ trw_layer_draw_track_label ( name_start, fgcolour, bgcolour, dp, &begin_coord );
+ g_free ( name_start );
+ }
+ // Don't draw end label if this is the one being created
+ if ( trk != dp->vtl->current_track ) {
+ if ( trk->draw_name_mode == TRACK_DRAWNAME_END ||
+ trk->draw_name_mode == TRACK_DRAWNAME_START_END ||
+ trk->draw_name_mode == TRACK_DRAWNAME_START_END_CENTRE ) {
+ gchar *name_end = g_strdup_printf ( "%s: %s", ename, _("end") );
+ trw_layer_draw_track_label ( name_end, fgcolour, bgcolour, dp, &end_coord );
+ g_free ( name_end );
+ }
+ }
+ }
+
+ g_free ( fgcolour );
+ g_free ( bgcolour );
+ g_free ( ename );
+}
+