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

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

revision 77 by harbaum, Tue Aug 25 12:49:03 2009 UTC revision 107 by harbaum, Fri Sep 11 12:16:50 2009 UTC
# Line 19  Line 19 
19    
20  #include "config.h"  #include "config.h"
21  #include <stdlib.h>  // abs  #include <stdlib.h>  // abs
22  #include <math.h>    // M_PI  #include <math.h>    // M_PI/cos()
23    
24  /* parameters that can be overwritten from the config file: */  /* parameters that can be overwritten from the config file: */
25  /* OSD_DIAMETER */  /* OSD_DIAMETER */
# Line 38  Line 38 
38  typedef struct {  typedef struct {
39      /* the offscreen representation of the OSD */      /* the offscreen representation of the OSD */
40      cairo_surface_t *overlay;      cairo_surface_t *overlay;
41    
42    #ifdef OSD_SCALE
43        cairo_surface_t *scale;
44        int scale_zoom;
45    #endif
46    
47    #ifdef OSD_CROSSHAIR
48        cairo_surface_t *crosshair;
49    #endif
50    
51    #ifdef OSD_COORDINATES
52        cairo_surface_t *coordinates;
53    #endif
54    
55    #ifdef OSD_SOURCE_SEL
56        /* values to handle the "source" menu */
57        cairo_surface_t *map_source;
58        gboolean expanded;
59        gint shift, dir, count;
60        gint handler_id;
61        gint width, height;
62    #endif
63    
64  } osd_priv_t;  } osd_priv_t;
65    
66  /* position and extent of bounding box */  /* position and extent of bounding box */
# Line 100  typedef struct { Line 123  typedef struct {
123    
124  /* create the cairo shape used for the zoom buttons */  /* create the cairo shape used for the zoom buttons */
125  static void  static void
126  osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y)  osd_zoom_shape(cairo_t *cr, gint x, gint y)
127  {  {
128      cairo_move_to (cr, x+Z_LEFT,    y+Z_TOP);      cairo_move_to (cr, x+Z_LEFT,    y+Z_TOP);
129      cairo_line_to (cr, x+Z_RIGHT,   y+Z_TOP);      cairo_line_to (cr, x+Z_RIGHT,   y+Z_TOP);
# Line 109  osm_gps_map_osd_zoom_shape(cairo_t *cr, Line 132  osm_gps_map_osd_zoom_shape(cairo_t *cr,
132      cairo_arc     (cr, x+Z_LEFT,    y+Z_MID, Z_RAD,  M_PI/2, -M_PI/2);      cairo_arc     (cr, x+Z_LEFT,    y+Z_MID, Z_RAD,  M_PI/2, -M_PI/2);
133  }  }
134    
135    /* ------------------- color/shadow functions ----------------- */
136    
137    #ifndef OSD_COLOR
138    /* if no color has been specified we just use the gdks default colors */
139    static void
140    osd_labels(cairo_t *cr, gint width, gboolean enabled,
141                           GdkColor *fg, GdkColor *disabled) {
142        if(enabled)  gdk_cairo_set_source_color(cr, fg);
143        else         gdk_cairo_set_source_color(cr, disabled);
144        cairo_set_line_width (cr, width);
145    }
146    #else
147    static void
148    osd_labels(cairo_t *cr, gint width, gboolean enabled) {
149        if(enabled)  cairo_set_source_rgb (cr, OSD_COLOR);
150        else         cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);
151        cairo_set_line_width (cr, width);
152    }
153    #endif
154    
155    #ifdef OSD_SHADOW_ENABLE
156    static void
157    osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {
158        cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);
159        cairo_set_line_width (cr, width);
160    }
161    #endif
162    
163  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
164  /* create the cairo shape used for the dpad */  /* create the cairo shape used for the dpad */
165  static void  static void
166  osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y)  osd_dpad_shape(cairo_t *cr, gint x, gint y)
167  {  {
168      cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);      cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);
169  }  }
170  #endif  #endif
171    
172    #ifdef OSD_SHADOW_ENABLE
173    static void
174    osd_shape_shadow(cairo_t *cr) {
175        cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
176        cairo_fill (cr);
177        cairo_stroke (cr);
178    }
179    #endif
180    
181    #ifndef OSD_COLOR
182    /* if no color has been specified we just use the gdks default colors */
183    static void
184    osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {
185        gdk_cairo_set_source_color(cr, bg);
186        cairo_fill_preserve (cr);
187        gdk_cairo_set_source_color(cr, fg);
188        cairo_set_line_width (cr, 1);
189        cairo_stroke (cr);
190    }
191    #else
192    static void
193    osd_shape(cairo_t *cr) {
194        cairo_set_source_rgb (cr, OSD_COLOR_BG);
195        cairo_fill_preserve (cr);
196        cairo_set_source_rgb (cr, OSD_COLOR);
197        cairo_set_line_width (cr, 1);
198        cairo_stroke (cr);
199    }
200    #endif
201    
202    
203  static gboolean  static gboolean
204  osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)  osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)
205  {  {
# Line 127  osm_gps_map_in_circle(gint x, gint y, gi Line 209  osm_gps_map_in_circle(gint x, gint y, gi
209  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
210  /* check whether x/y is within the dpad */  /* check whether x/y is within the dpad */
211  static osd_button_t  static osd_button_t
212  osm_gps_map_osd_check_dpad(gint x, gint y)  osd_check_dpad(gint x, gint y)
213  {  {
214      /* within entire dpad circle */      /* within entire dpad circle */
215      if( osm_gps_map_in_circle(x, y, D_RAD, D_RAD, D_RAD))      if( osm_gps_map_in_circle(x, y, D_RAD, D_RAD, D_RAD))
# Line 162  osm_gps_map_osd_check_dpad(gint x, gint Line 244  osm_gps_map_osd_check_dpad(gint x, gint
244    
245  /* check whether x/y is within the zoom pads */  /* check whether x/y is within the zoom pads */
246  static osd_button_t  static osd_button_t
247  osm_gps_map_osd_check_zoom(gint x, gint y) {  osd_check_zoom(gint x, gint y) {
248      if( x > 0 && x < OSD_W && y > Z_TOP && y < Z_BOT) {      if( x > 0 && x < OSD_W && y > Z_TOP && y < Z_BOT) {
249    
250          /* within circle around (-) label */          /* within circle around (-) label */
# Line 191  osm_gps_map_osd_check_zoom(gint x, gint Line 273  osm_gps_map_osd_check_zoom(gint x, gint
273      return OSD_NONE;      return OSD_NONE;
274  }  }
275    
276    #ifdef OSD_SOURCE_SEL
277    
278    /* place source selection at right border */
279    #define OSD_S_RAD (Z_RAD)
280    #define OSD_S_X   (-OSD_X)
281    #define OSD_S_Y   (OSD_Y)
282    #define OSD_S_PW  (2 * Z_RAD)
283    #define OSD_S_W   (OSD_S_PW)
284    #define OSD_S_PH  (2 * Z_RAD)
285    #define OSD_S_H   (OSD_S_PH + OSD_SHADOW)
286    
287    /* size of usable area when expanded */
288    #define OSD_S_AREA_W (priv->width)
289    #define OSD_S_AREA_H (priv->height)
290    #define OSD_S_EXP_W  (OSD_S_PW + OSD_S_AREA_W + OSD_SHADOW)
291    #define OSD_S_EXP_H  (OSD_S_AREA_H + OSD_SHADOW)
292    
293    /* internal value to draw the arrow on the "puller" */
294    #define OSD_S_D0  (OSD_S_RAD/2)
295    #ifndef OSD_FONT_SIZE
296    #define OSD_FONT_SIZE 16.0
297    #endif
298    #define OSD_TEXT_BORDER   (OSD_FONT_SIZE/2)
299    #define OSD_TEXT_SKIP     (OSD_FONT_SIZE/8)
300    
301    /* draw the shape of the source selection OSD, either only the puller (not expanded) */
302    /* or the entire menu incl. the puller (expanded) */
303    static void
304    osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) {
305        if(!priv->expanded) {
306            /* just draw the puller */
307            cairo_move_to (cr, x + OSD_S_PW, y + OSD_S_PH);
308            cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
309            cairo_line_to (cr, x + OSD_S_PW, y);
310        } else {
311            /* draw the puller and the area itself */
312            cairo_move_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y + OSD_S_AREA_H);
313            cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H);
314            if(OSD_S_Y > 0) {
315                cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_PH);
316                cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
317            } else {
318                cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_AREA_H-OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
319                cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H - OSD_S_PH);
320                cairo_line_to (cr, x + OSD_S_PW, y);
321            }
322            cairo_line_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y);
323            cairo_close_path (cr);
324        }
325    }
326    
327    static void
328    osd_source_content(osm_gps_map_osd_t *osd, cairo_t *cr, gint offset) {
329        osd_priv_t *priv = (osd_priv_t*)osd->priv;
330    
331        int py = offset + OSD_S_RAD - OSD_S_D0;
332    
333        if(!priv->expanded) {
334            /* draw the "puller" open (<) arrow */
335            cairo_move_to (cr, offset + OSD_S_RAD + OSD_S_D0/2, py);
336            cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
337            cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
338        } else {
339            if(OSD_S_Y < 0)
340                py += OSD_S_AREA_H - OSD_S_PH;
341    
342            /* draw the "puller" close (>) arrow */
343            cairo_move_to (cr, offset + OSD_S_RAD - OSD_S_D0/2, py);
344            cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
345            cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
346            cairo_stroke(cr);
347    
348            /* don't draw a shadow for the text content */
349            if(offset == 1) {
350                gint source;
351                g_object_get(osd->widget, "map-source", &source, NULL);
352    
353                cairo_select_font_face (cr, "Sans",
354                                        CAIRO_FONT_SLANT_NORMAL,
355                                        CAIRO_FONT_WEIGHT_BOLD);
356                cairo_set_font_size (cr, OSD_FONT_SIZE);
357    
358                int i, step = (priv->height - 2*OSD_TEXT_BORDER) /
359                    OSM_GPS_MAP_SOURCE_LAST;
360                for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
361                    cairo_text_extents_t extents;
362                    const char *src = osm_gps_map_source_get_friendly_name(i);
363                    cairo_text_extents (cr, src, &extents);
364    
365                    int x = offset + OSD_S_PW + OSD_TEXT_BORDER;
366                    int y = offset + step * (i-1) + OSD_TEXT_BORDER;
367    
368                    /* draw filled rectangle if selected */
369                    if(source == i) {
370                        cairo_rectangle(cr, x - OSD_TEXT_BORDER/2,
371                                        y - OSD_TEXT_SKIP,
372                                        priv->width - OSD_TEXT_BORDER,
373                                        step + OSD_TEXT_SKIP);
374                        cairo_fill(cr);
375    
376                        /* temprarily draw with background color */
377    #ifndef OSD_COLOR
378                        GdkColor bg = osd->widget->style->bg[GTK_STATE_NORMAL];
379                        gdk_cairo_set_source_color(cr, &bg);
380    #else
381                        cairo_set_source_rgb (cr, OSD_COLOR_BG);
382    #endif
383                    }
384    
385                    cairo_move_to (cr, x, y + OSD_TEXT_SKIP - extents.y_bearing);
386                    cairo_show_text (cr, src);
387    
388                    /* restore color */
389                    if(source == i) {
390    #ifndef OSD_COLOR
391                        GdkColor fg = osd->widget->style->fg[GTK_STATE_NORMAL];
392                        gdk_cairo_set_source_color(cr, &fg);
393    #else
394                        cairo_set_source_rgb (cr, OSD_COLOR);
395    #endif
396                    }
397                }
398            }
399        }
400    }
401    
402    static void
403    osd_render_source_sel(osm_gps_map_osd_t *osd) {
404        osd_priv_t *priv = (osd_priv_t*)osd->priv;
405    
406    #ifndef OSD_COLOR
407        GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
408        GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
409        GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
410    #endif
411    
412        /* draw source selector */
413        cairo_t *cr = cairo_create(priv->map_source);
414        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
415        cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
416        cairo_paint(cr);
417        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
418    
419    #ifdef OSD_SHADOW_ENABLE
420        osd_source_shape(priv, cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
421        osd_shape_shadow(cr);
422    #endif
423    
424        osd_source_shape(priv, cr, 1, 1);
425    #ifndef OSD_COLOR
426        osd_shape(cr, &bg, &fg);
427    #else
428        osd_shape(cr);
429    #endif
430    
431    #ifdef OSD_SHADOW_ENABLE
432        osd_labels_shadow(cr, Z_RAD/3, TRUE);
433        osd_source_content(osd, cr, 1+OSD_LBL_SHADOW);
434        cairo_stroke (cr);
435    #endif
436    #ifndef OSD_COLOR
437        osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
438    #else
439        osd_labels(cr, Z_RAD/3, TRUE);
440    #endif
441        osd_source_content(osd, cr, 1);
442        cairo_stroke (cr);
443    
444        cairo_destroy(cr);
445    }
446    
447    /* re-allocate the buffer used to draw the menu. This is used */
448    /* to collapse/expand the buffer */
449    static void
450    osd_source_reallocate(osm_gps_map_osd_t *osd) {
451        osd_priv_t *priv = (osd_priv_t*)osd->priv;
452    
453        /* re-allocate offscreen bitmap */
454        g_assert (priv->map_source);
455    
456        int w = OSD_S_W, h = OSD_S_H;
457        if(priv->expanded) {
458            cairo_text_extents_t extents;
459    
460            /* determine content size */
461            cairo_t *cr = cairo_create(priv->map_source);
462            cairo_select_font_face (cr, "Sans",
463                                    CAIRO_FONT_SLANT_NORMAL,
464                                    CAIRO_FONT_WEIGHT_BOLD);
465            cairo_set_font_size (cr, OSD_FONT_SIZE);
466    
467            /* calculate menu size */
468            int i, max_h = 0, max_w = 0;
469            for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
470                const char *src = osm_gps_map_source_get_friendly_name(i);
471                cairo_text_extents (cr, src, &extents);
472    
473                if(extents.width > max_w) max_w = extents.width;
474                if(extents.height > max_h) max_h = extents.height;
475            }
476            cairo_destroy(cr);
477    
478            priv->width  = max_w + 2*OSD_TEXT_BORDER;
479            priv->height = OSM_GPS_MAP_SOURCE_LAST *
480                (max_h + 2*OSD_TEXT_SKIP) + 2*OSD_TEXT_BORDER;
481    
482            w = OSD_S_EXP_W;
483            h = OSD_S_EXP_H;
484        }
485    
486        cairo_surface_destroy(priv->map_source);
487        priv->map_source =
488            cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2);
489    
490        osd_render_source_sel(osd);
491    }
492    
493    #define OSD_HZ      15
494    #define OSD_TIME    500
495    
496    static gboolean osd_source_animate(gpointer data) {
497        osm_gps_map_osd_t *osd = (osm_gps_map_osd_t*)data;
498        osd_priv_t *priv = (osd_priv_t*)osd->priv;
499        int diff = OSD_S_EXP_W - OSD_S_W - OSD_S_X;
500        gboolean done = FALSE;
501        priv->count += priv->dir;
502    
503        /* shifting in */
504        if(priv->dir < 0) {
505            if(priv->count <= 0) {
506                priv->count = 0;
507                done = TRUE;
508            }
509        } else {
510            if(priv->count >= 1000) {
511                priv->expanded = FALSE;
512                osd_source_reallocate(osd);
513    
514                priv->count = 1000;
515                done = TRUE;
516            }
517        }
518    
519    
520        /* count runs linearly from 0 to 1000, map this nicely onto a position */
521    
522        /* nicer sinoid mapping */
523        float m = 0.5-cos(priv->count * M_PI / 1000.0)/2;
524        priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +
525            m * diff;
526    
527        osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
528    
529        if(done)
530            priv->handler_id = 0;
531    
532        return !done;
533    }
534    
535    /* switch between expand and collapse mode of source selection */
536    static void
537    osd_source_toggle(osm_gps_map_osd_t *osd)
538    {
539        osd_priv_t *priv = (osd_priv_t*)osd->priv;
540    
541        /* ignore clicks while animation is running */
542        if(priv->handler_id)
543            return;
544    
545        /* expand immediately, collapse is handle at the end of the collapse animation */
546        if(!priv->expanded) {
547            priv->expanded = TRUE;
548            osd_source_reallocate(osd);
549    
550            priv->count = 1000;
551            priv->shift = osd->widget->allocation.width - OSD_S_W;
552            priv->dir = -1000/OSD_HZ;
553        } else {
554            priv->count =  0;
555            priv->shift = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
556            priv->dir = +1000/OSD_HZ;
557        }
558    
559        priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd);
560    }
561    
562    /* check if the user clicked inside the source selection area */
563    static osd_button_t
564    osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) {
565        osd_priv_t *priv = (osd_priv_t*)osd->priv;
566    
567        if(!priv->expanded)
568            x -= osd->widget->allocation.width - OSD_S_W;
569        else
570            x -= osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
571    
572        if(OSD_S_Y > 0)
573            y -= OSD_S_Y;
574        else
575            y -= osd->widget->allocation.height - OSD_S_PH + OSD_S_Y;
576    
577        /* within square around puller? */
578        if(y > 0 && y < OSD_S_PH && x > 0 && x < OSD_S_PW) {
579            /* really within puller shape? */
580            if(x > Z_RAD || osm_gps_map_in_circle(x, y, Z_RAD, Z_RAD, Z_RAD)) {
581                /* expand source selector */
582                osd_source_toggle(osd);
583    
584                /* tell upper layers that user clicked some background element */
585                /* of the OSD */
586                return OSD_BG;
587            }
588        }
589    
590        /* check for clicks into data area */
591        if(priv->expanded && !priv->handler_id) {
592            /* re-adjust from puller top to content top */
593            if(OSD_S_Y < 0)
594                y += OSD_S_EXP_H - OSD_S_PH;
595    
596            if(x > OSD_S_PW &&
597               x < OSD_S_PW + OSD_S_EXP_W &&
598               y > 0 &&
599               y < OSD_S_EXP_H) {
600    
601                int step = (priv->height - 2*OSD_TEXT_BORDER)
602                    / OSM_GPS_MAP_SOURCE_LAST;
603    
604                y -= OSD_TEXT_BORDER - OSD_TEXT_SKIP;
605                y /= step;
606                y += 1;
607    
608                gint old = 0;
609                g_object_get(osd->widget, "map-source", &old, NULL);
610    
611                if(y > OSM_GPS_MAP_SOURCE_NULL &&
612                   y <= OSM_GPS_MAP_SOURCE_LAST &&
613                   old != y) {
614                    g_object_set(osd->widget, "map-source", y, NULL);
615    
616                    osd_render_source_sel(osd);
617                    osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
618                }
619    
620                /* return "clicked in OSD background" to prevent further */
621                /* processing by application */
622                return OSD_BG;
623            }
624        }
625    
626        return OSD_NONE;
627    }
628    #endif // OSD_SOURCE_SEL
629    
630  static osd_button_t  static osd_button_t
631  osm_gps_map_osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {  osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {
632      osd_button_t but = OSD_NONE;      osd_button_t but = OSD_NONE;
633    
634    #ifdef OSD_SOURCE_SEL
635        /* the source selection area is handles internally */
636        but = osd_source_check(osd, x, y);
637        if(but != OSD_NONE)
638            return but;
639    #endif
640    
641      x -= OSD_X;      x -= OSD_X;
642      y -= OSD_Y;      y -= OSD_Y;
643    
# Line 208  osm_gps_map_osd_check(osm_gps_map_osd_t Line 651  osm_gps_map_osd_check(osm_gps_map_osd_t
651      /* this is just to avoid an unnecessary detailed test */      /* this is just to avoid an unnecessary detailed test */
652      if(x > 0 && x < OSD_W && y > 0 && y < OSD_H) {      if(x > 0 && x < OSD_W && y > 0 && y < OSD_H) {
653  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
654          but = osm_gps_map_osd_check_dpad(x, y);          but = osd_check_dpad(x, y);
655  #endif  #endif
656    
657          if(but == OSD_NONE)          if(but == OSD_NONE)
658              but = osm_gps_map_osd_check_zoom(x, y);              but = osd_check_zoom(x, y);
659      }      }
660    
661      return but;      return but;
662  }  }
663    
 #ifdef OSD_SHADOW_ENABLE  
 static void  
 osm_gps_map_osd_shape_shadow(cairo_t *cr) {  
     cairo_set_source_rgba (cr, 0, 0, 0, 0.2);  
     cairo_fill (cr);  
     cairo_stroke (cr);  
 }  
 #endif  
   
 #ifndef OSD_COLOR  
 /* if no color has been specified we just use the gdks default colors */  
 static void  
 osm_gps_map_osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {  
     gdk_cairo_set_source_color(cr, bg);  
     cairo_fill_preserve (cr);  
     gdk_cairo_set_source_color(cr, fg);  
     cairo_set_line_width (cr, 1);  
     cairo_stroke (cr);  
 }  
 #else  
 static void  
 osm_gps_map_osd_shape(cairo_t *cr) {  
     cairo_set_source_rgb (cr, OSD_COLOR_BG);  
     cairo_fill_preserve (cr);  
     cairo_set_source_rgb (cr, OSD_COLOR);  
     cairo_set_line_width (cr, 1);  
     cairo_stroke (cr);  
 }  
 #endif  
   
664  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
665  static void  static void
666  osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {  osd_dpad_labels(cairo_t *cr, gint x, gint y) {
667      /* move reference to dpad center */      /* move reference to dpad center */
668      x += D_RAD;      x += D_RAD;
669      y += D_RAD;      y += D_RAD;
# Line 285  osm_gps_map_osd_dpad_labels(cairo_t *cr, Line 698  osm_gps_map_osd_dpad_labels(cairo_t *cr,
698  /* this is either drawn in the center of the dpad (if present) */  /* this is either drawn in the center of the dpad (if present) */
699  /* or in the middle of the zoom area */  /* or in the middle of the zoom area */
700  static void  static void
701  osm_gps_map_osd_dpad_gps(cairo_t *cr, gint x, gint y) {  osd_dpad_gps(cairo_t *cr, gint x, gint y) {
702      /* move reference to dpad center */      /* move reference to dpad center */
703      x += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD * 3;      x += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD * 3;
704      y += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD + GPS_V0;      y += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD + GPS_V0;
# Line 308  osm_gps_map_osd_dpad_gps(cairo_t *cr, gi Line 721  osm_gps_map_osd_dpad_gps(cairo_t *cr, gi
721  #define Z_LEN  (2*Z_RAD/3)  #define Z_LEN  (2*Z_RAD/3)
722    
723  static void  static void
724  osm_gps_map_osd_zoom_labels(cairo_t *cr, gint x, gint y) {  osd_zoom_labels(cairo_t *cr, gint x, gint y) {
725      cairo_move_to (cr, x + Z_LEFT  - Z_LEN, y + Z_MID);      cairo_move_to (cr, x + Z_LEFT  - Z_LEN, y + Z_MID);
726      cairo_line_to (cr, x + Z_LEFT  + Z_LEN, y + Z_MID);      cairo_line_to (cr, x + Z_LEFT  + Z_LEN, y + Z_MID);
727    
# Line 318  osm_gps_map_osd_zoom_labels(cairo_t *cr, Line 731  osm_gps_map_osd_zoom_labels(cairo_t *cr,
731      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
732  }  }
733    
734  #ifndef OSD_COLOR  #ifdef OSD_COORDINATES
735  /* if no color has been specified we just use the gdks default colors */  
736  static void  #ifndef OSD_COORDINATES_FONT_SIZE
737  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled,  #define OSD_COORDINATES_FONT_SIZE 12
738                         GdkColor *fg, GdkColor *disabled) {  #endif
739      if(enabled)  gdk_cairo_set_source_color(cr, fg);  
740      else         gdk_cairo_set_source_color(cr, disabled);  #define OSD_COORDINATES_W  (9*OSD_COORDINATES_FONT_SIZE)
741      cairo_set_line_width (cr, width);  #define OSD_COORDINATES_H  (2*OSD_COORDINATES_FONT_SIZE)
742      cairo_stroke (cr);  
743    /* these can be overwritten with versions that support */
744    /* localization */
745    #ifndef OSD_COORDINATES_CHR_N
746    #define OSD_COORDINATES_CHR_N  "N"
747    #endif
748    #ifndef OSD_COORDINATES_CHR_S
749    #define OSD_COORDINATES_CHR_S  "S"
750    #endif
751    #ifndef OSD_COORDINATES_CHR_E
752    #define OSD_COORDINATES_CHR_E  "E"
753    #endif
754    #ifndef OSD_COORDINATES_CHR_W
755    #define OSD_COORDINATES_CHR_W  "W"
756    #endif
757    
758    
759    
760    /* this is the classic geocaching notation */
761    static char
762    *osd_latitude_str(float latitude) {
763        char *c = OSD_COORDINATES_CHR_N;
764        float integral, fractional;
765    
766        if(isnan(latitude))
767            return NULL;
768    
769        if(latitude < 0) {
770            latitude = fabs(latitude);
771            c = OSD_COORDINATES_CHR_S;
772        }
773    
774        fractional = modff(latitude, &integral);
775    
776        return g_strdup_printf("%s %02d° %06.3f'",
777                               c, (int)integral, fractional*60.0);
778  }  }
779  #else  
780    static char
781    *osd_longitude_str(float longitude) {
782        char *c = OSD_COORDINATES_CHR_E;
783        float integral, fractional;
784    
785        if(isnan(longitude))
786            return NULL;
787    
788        if(longitude < 0) {
789            longitude = fabs(longitude);
790            c = OSD_COORDINATES_CHR_W;
791        }
792    
793        fractional = modff(longitude, &integral);
794    
795        return g_strdup_printf("%s %03d° %06.3f'",
796                               c, (int)integral, fractional*60.0);
797    }
798    
799    #define OSD_COORDINATES_OFFSET (OSD_COORDINATES_FONT_SIZE/6)
800    
801  static void  static void
802  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {  osd_render_coordinates(osm_gps_map_osd_t *osd)
803      if(enabled)  cairo_set_source_rgb (cr, OSD_COLOR);  {
804      else         cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);      osd_priv_t *priv = (osd_priv_t*)osd->priv;
805      cairo_set_line_width (cr, width);  
806        /* get current map position */
807        gfloat lat, lon;
808        g_object_get(osd->widget, "latitude", &lat, "longitude", &lon, NULL);
809    
810        /* first fill with transparency */
811        cairo_t *cr = cairo_create(priv->coordinates);
812        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
813        //    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
814        cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
815        cairo_paint(cr);
816        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
817    
818        cairo_select_font_face (cr, "Sans",
819                                CAIRO_FONT_SLANT_NORMAL,
820                                CAIRO_FONT_WEIGHT_BOLD);
821        cairo_set_font_size (cr, OSD_COORDINATES_FONT_SIZE);
822    
823        char *latitude = osd_latitude_str(lat);
824        char *longitude = osd_longitude_str(lon);
825    
826        cairo_text_extents_t lat_extents, lon_extents;
827        cairo_text_extents (cr, latitude, &lat_extents);
828        cairo_text_extents (cr, longitude, &lon_extents);
829    
830        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
831        cairo_set_line_width (cr, OSD_COORDINATES_FONT_SIZE/6);
832        cairo_move_to (cr,
833                       OSD_COORDINATES_OFFSET - lat_extents.x_bearing,
834                       OSD_COORDINATES_OFFSET - lat_extents.y_bearing);
835        cairo_text_path (cr, latitude);
836        cairo_move_to (cr,
837                       OSD_COORDINATES_OFFSET - lon_extents.x_bearing,
838                       OSD_COORDINATES_OFFSET - lon_extents.y_bearing +
839                       OSD_COORDINATES_FONT_SIZE);
840        cairo_text_path (cr, longitude);
841      cairo_stroke (cr);      cairo_stroke (cr);
842    
843        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
844        cairo_move_to (cr,
845                       OSD_COORDINATES_OFFSET - lat_extents.x_bearing,
846                       OSD_COORDINATES_OFFSET - lat_extents.y_bearing);
847        cairo_show_text (cr, latitude);
848        cairo_move_to (cr,
849                       OSD_COORDINATES_OFFSET - lon_extents.x_bearing,
850                       OSD_COORDINATES_OFFSET - lon_extents.y_bearing +
851                       OSD_COORDINATES_FONT_SIZE);
852        cairo_show_text (cr, longitude);
853    
854        g_free(latitude);
855        g_free(longitude);
856    
857        cairo_destroy(cr);
858  }  }
859    #endif  // OSD_COORDINATES
860    
861    #ifdef OSD_CROSSHAIR
862    
863    #ifndef OSD_CROSSHAIR_RADIUS
864    #define OSD_CROSSHAIR_RADIUS 10
865  #endif  #endif
866    
867  #ifdef OSD_SHADOW_ENABLE  #define OSD_CROSSHAIR_TICK  (OSD_CROSSHAIR_RADIUS/2)
868  static void  #define OSD_CROSSHAIR_BORDER (OSD_CROSSHAIR_TICK + OSD_CROSSHAIR_RADIUS/4)
869  osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {  #define OSD_CROSSHAIR_W  ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2)
870      cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);  #define OSD_CROSSHAIR_H  ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2)
871      cairo_set_line_width (cr, width);  
872    static void
873    osd_render_crosshair_shape(cairo_t *cr) {
874        cairo_arc (cr, OSD_CROSSHAIR_W/2, OSD_CROSSHAIR_H/2,
875                   OSD_CROSSHAIR_RADIUS, 0,  2*M_PI);
876    
877        cairo_move_to (cr, OSD_CROSSHAIR_W/2 - OSD_CROSSHAIR_RADIUS,
878                       OSD_CROSSHAIR_H/2);
879        cairo_rel_line_to (cr, -OSD_CROSSHAIR_TICK, 0);
880        cairo_move_to (cr, OSD_CROSSHAIR_W/2 + OSD_CROSSHAIR_RADIUS,
881                       OSD_CROSSHAIR_H/2);
882        cairo_rel_line_to (cr,  OSD_CROSSHAIR_TICK, 0);
883    
884        cairo_move_to (cr, OSD_CROSSHAIR_W/2,
885                       OSD_CROSSHAIR_H/2 - OSD_CROSSHAIR_RADIUS);
886        cairo_rel_line_to (cr, 0, -OSD_CROSSHAIR_TICK);
887        cairo_move_to (cr, OSD_CROSSHAIR_W/2,
888                       OSD_CROSSHAIR_H/2 + OSD_CROSSHAIR_RADIUS);
889        cairo_rel_line_to (cr, 0, OSD_CROSSHAIR_TICK);
890    
891      cairo_stroke (cr);      cairo_stroke (cr);
892  }  }
893    
894    static void
895    osd_render_crosshair(osm_gps_map_osd_t *osd)
896    {
897        osd_priv_t *priv = (osd_priv_t*)osd->priv;
898    
899        /* first fill with transparency */
900        cairo_t *cr = cairo_create(priv->crosshair);
901        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
902        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
903        //    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
904        cairo_paint(cr);
905        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
906    
907        cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
908    
909        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);
910        cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/2);
911        osd_render_crosshair_shape(cr);
912    
913        cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
914        cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/4);
915        osd_render_crosshair_shape(cr);
916    
917        cairo_destroy(cr);
918    }
919    #endif
920    
921    #ifdef OSD_SCALE
922    
923    #ifndef OSD_SCALE_FONT_SIZE
924    #define OSD_SCALE_FONT_SIZE 12
925  #endif  #endif
926    #define OSD_SCALE_W   (10*OSD_SCALE_FONT_SIZE)
927    #define OSD_SCALE_H   (5*OSD_SCALE_FONT_SIZE/2)
928    
929    /* various parameters used to create the scale */
930    #define OSD_SCALE_H2   (OSD_SCALE_H/2)
931    #define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3)
932    #define OSD_SCALE_M    (OSD_SCALE_H2 - OSD_SCALE_TICK)
933    #define OSD_SCALE_I    (OSD_SCALE_H2 + OSD_SCALE_TICK)
934    #define OSD_SCALE_FD   (OSD_SCALE_FONT_SIZE/4)
935    
936  static void  static void
937  osm_gps_map_osd_render(osm_gps_map_osd_t *osd) {  osd_render_scale(osm_gps_map_osd_t *osd)
938    {
939      osd_priv_t *priv = (osd_priv_t*)osd->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
940    
941        /* this only needs to be rendered if the zoom has changed */
942        gint zoom;
943        g_object_get(OSM_GPS_MAP(osd->widget), "zoom", &zoom, NULL);
944        if(zoom == priv->scale_zoom)
945            return;
946    
947        priv->scale_zoom = zoom;
948    
949        float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget));
950    
951      /* first fill with transparency */      /* first fill with transparency */
952      cairo_t *cr = cairo_create(priv->overlay);      cairo_t *cr = cairo_create(priv->scale);
953      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
954      cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);      cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
955        // pink for testing:    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
956      cairo_paint(cr);      cairo_paint(cr);
957        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
958    
959        /* determine the size of the scale width in meters */
960        float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix;
961    
962        /* scale this to useful values */
963        int exp = logf(width)*M_LOG10E;
964        int mant = width/pow(10,exp);
965        int width_metric = mant * pow(10,exp);
966        char *dist_str = NULL;
967        if(width_metric<1000)
968            dist_str = g_strdup_printf("%u m", width_metric);
969        else
970            dist_str = g_strdup_printf("%u km", width_metric/1000);
971        width_metric /= m_per_pix;
972    
973        /* and now the hard part: scale for useful imperial values :-( */
974        /* try to convert to feet, 1ft == 0.3048 m */
975        width /= 0.3048;
976        float imp_scale = 0.3048;
977        char *dist_imp_unit = "ft";
978    
979        if(width >= 100) {
980            /* 1yd == 3 feet */
981            width /= 3.0;
982            imp_scale *= 3.0;
983            dist_imp_unit = "yd";
984    
985            if(width >= 1760.0) {
986                /* 1mi == 1760 yd */
987                width /= 1760.0;
988                imp_scale *= 1760.0;
989                dist_imp_unit = "mi";
990            }
991        }
992    
993        /* also convert this to full tens/hundreds */
994        exp = logf(width)*M_LOG10E;
995        mant = width/pow(10,exp);
996        int width_imp = mant * pow(10,exp);
997        char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit);
998    
999        /* convert back to pixels */
1000        width_imp *= imp_scale;
1001        width_imp /= m_per_pix;
1002    
1003        cairo_select_font_face (cr, "Sans",
1004                                CAIRO_FONT_SLANT_NORMAL,
1005                                CAIRO_FONT_WEIGHT_BOLD);
1006        cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE);
1007        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
1008    
1009        cairo_text_extents_t extents;
1010        cairo_text_extents (cr, dist_str, &extents);
1011    
1012        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1013        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
1014        cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
1015        cairo_text_path (cr, dist_str);
1016        cairo_stroke (cr);
1017        cairo_move_to (cr, 2*OSD_SCALE_FD,
1018                       OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
1019        cairo_text_path (cr, dist_str_imp);
1020        cairo_stroke (cr);
1021    
1022        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
1023        cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
1024        cairo_show_text (cr, dist_str);
1025        cairo_move_to (cr, 2*OSD_SCALE_FD,
1026                       OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
1027        cairo_show_text (cr, dist_str_imp);
1028    
1029        g_free(dist_str);
1030        g_free(dist_str_imp);
1031    
1032        /* draw white line */
1033        cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
1034        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
1035        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3);
1036        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
1037        cairo_rel_line_to (cr, 0,  OSD_SCALE_TICK);
1038        cairo_rel_line_to (cr, width_metric, 0);
1039        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1040        cairo_stroke(cr);
1041        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
1042        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1043        cairo_rel_line_to (cr, width_imp, 0);
1044        cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
1045        cairo_stroke(cr);
1046    
1047        /* draw black line */
1048        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
1049        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
1050        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
1051        cairo_rel_line_to (cr, 0,  OSD_SCALE_TICK);
1052        cairo_rel_line_to (cr, width_metric, 0);
1053        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1054        cairo_stroke(cr);
1055        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
1056        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1057        cairo_rel_line_to (cr, width_imp, 0);
1058        cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
1059        cairo_stroke(cr);
1060    
1061        cairo_destroy(cr);
1062    }
1063    #endif
1064    
1065    static void
1066    osd_render(osm_gps_map_osd_t *osd)
1067    {
1068        osd_priv_t *priv = (osd_priv_t*)osd->priv;
1069    
1070  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1071      GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];      GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
# Line 363  osm_gps_map_osd_render(osm_gps_map_osd_t Line 1073  osm_gps_map_osd_render(osm_gps_map_osd_t
1073      GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];      GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
1074  #endif  #endif
1075    
1076        /* first fill with transparency */
1077        cairo_t *cr = cairo_create(priv->overlay);
1078        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1079        cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
1080        cairo_paint(cr);
1081      cairo_set_operator(cr, CAIRO_OPERATOR_OVER);      cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1082    
1083      /* --------- draw zoom and dpad shape shadow ----------- */      /* --------- draw zoom and dpad shape shadow ----------- */
     gint x = 0, y = 0;  
   
1084  #ifdef OSD_SHADOW_ENABLE  #ifdef OSD_SHADOW_ENABLE
1085      osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);      osd_zoom_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
1086      osm_gps_map_osd_shape_shadow(cr);      osd_shape_shadow(cr);
1087  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
1088      osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);      osd_dpad_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
1089      osm_gps_map_osd_shape_shadow(cr);      osd_shape_shadow(cr);
1090  #endif  #endif
1091  #endif  #endif
1092    
1093      /* --------- draw zoom and dpad shape ----------- */      /* --------- draw zoom and dpad shape ----------- */
1094    
1095      osm_gps_map_osd_zoom_shape(cr, x, y);      osd_zoom_shape(cr, 1, 1);
1096  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1097      osm_gps_map_osd_shape(cr, &bg, &fg);      osd_shape(cr, &bg, &fg);
1098  #else  #else
1099      osm_gps_map_osd_shape(cr);      osd_shape(cr);
1100  #endif  #endif
1101  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
1102      osm_gps_map_osd_dpad_shape(cr, x, y);      osd_dpad_shape(cr, 1, 1);
1103  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1104      osm_gps_map_osd_shape(cr, &bg, &fg);      osd_shape(cr, &bg, &fg);
1105  #else  #else
1106      osm_gps_map_osd_shape(cr);      osd_shape(cr);
1107  #endif  #endif
1108  #endif  #endif
1109    
1110      /* --------- draw zoom and dpad labels --------- */      /* --------- draw zoom and dpad labels --------- */
1111    
1112  #ifdef OSD_SHADOW_ENABLE  #ifdef OSD_SHADOW_ENABLE
1113      osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osd_labels_shadow(cr, Z_RAD/3, TRUE);
1114        osd_zoom_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
1115  #ifndef OSD_NO_DPAD  #ifndef OSD_NO_DPAD
1116      osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osd_dpad_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
1117  #endif  #endif
1118      osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);      cairo_stroke(cr);
1119  #ifdef OSD_GPS_BUTTON  #ifdef OSD_GPS_BUTTON
1120      osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL);
1121      osm_gps_map_osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL);      osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
1122        cairo_stroke(cr);
1123  #endif  #endif
1124  #endif  #endif
1125    
     osm_gps_map_osd_zoom_labels(cr, x, y);  
 #ifndef OSD_NO_DPAD  
     osm_gps_map_osd_dpad_labels(cr, x, y);  
 #endif  
1126  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1127      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);      osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
1128  #else  #else
1129      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);      osd_labels(cr, Z_RAD/3, TRUE);
1130  #endif  #endif
1131  #ifdef OSD_GPS_BUTTON      osd_zoom_labels(cr, 1, 1);
1132      osm_gps_map_osd_dpad_gps(cr, x, y);  #ifndef OSD_NO_DPAD
1133        osd_dpad_labels(cr, 1, 1);
1134    #endif
1135        cairo_stroke(cr);
1136    
1137  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1138      osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL, &fg, &da);      osd_labels(cr, Z_RAD/6, osd->cb != NULL, &fg, &da);
1139  #else  #else
1140      osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL);      osd_labels(cr, Z_RAD/6, osd->cb != NULL);
1141  #endif  #endif
1142    #ifdef OSD_GPS_BUTTON
1143        osd_dpad_gps(cr, 1, 1);
1144  #endif  #endif
1145        cairo_stroke(cr);
1146    
1147      cairo_destroy(cr);      cairo_destroy(cr);
1148    
1149    #ifdef OSD_SOURCE_SEL
1150        osd_render_source_sel(osd);
1151    #endif
1152    
1153    #ifdef OSD_SCALE
1154        osd_render_scale(osd);
1155    #endif
1156    
1157    #ifdef OSD_CROSSHAIR
1158        osd_render_crosshair(osd);
1159    #endif
1160    
1161    #ifdef OSD_COORDINATES
1162        osd_render_coordinates(osd);
1163    #endif
1164  }  }
1165    
1166  static void  static void
1167  osm_gps_map_osd_draw(osm_gps_map_osd_t *osd, GdkDrawable *drawable)  osd_draw(osm_gps_map_osd_t *osd, GdkDrawable *drawable)
1168  {  {
1169      osd_priv_t *priv = (osd_priv_t*)osd->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
1170    
# Line 439  osm_gps_map_osd_draw(osm_gps_map_osd_t * Line 1173  osm_gps_map_osd_draw(osm_gps_map_osd_t *
1173      if(!priv->overlay) {      if(!priv->overlay) {
1174          /* create overlay ... */          /* create overlay ... */
1175          priv->overlay =          priv->overlay =
1176              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2);
1177    
1178    #ifdef OSD_SOURCE_SEL
1179            /* the initial OSD state is alway not-expanded */
1180            priv->map_source =
1181                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1182                                               OSD_S_W+2, OSD_S_H+2);
1183    #endif
1184    
1185    #ifdef OSD_SCALE
1186            priv->scale =
1187                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1188                                           OSD_SCALE_W, OSD_SCALE_H);
1189            priv->scale_zoom = -1;
1190    #endif
1191    
1192    #ifdef OSD_CROSSHAIR
1193            priv->crosshair =
1194                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1195                                           OSD_CROSSHAIR_W, OSD_CROSSHAIR_H);
1196    #endif
1197    
1198    #ifdef OSD_COORDINATES
1199            priv->coordinates =
1200                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1201                                           OSD_COORDINATES_W, OSD_COORDINATES_H);
1202    #endif
1203    
1204          /* ... and render it */          /* ... and render it */
1205          osm_gps_map_osd_render(osd);          osd_render(osd);
1206      }      }
1207    
1208      // now draw this onto the original context      // now draw this onto the original context
1209      cairo_t *cr = gdk_cairo_create(drawable);      cairo_t *cr = gdk_cairo_create(drawable);
1210    
1211      int x = OSD_X, y = OSD_Y;      int x, y;
     if(OSD_X < 0)  
         x = osd->widget->allocation.width - OSD_W + OSD_X;  
1212    
1213      if(OSD_Y < 0)  #ifdef OSD_SCALE
1214          y = osd->widget->allocation.height - OSD_H + OSD_Y;      x =  OSD_X;
1215        y = -OSD_Y;
1216        if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W;
1217        if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H;
1218    
1219        cairo_set_source_surface(cr, priv->scale, x, y);
1220        cairo_paint(cr);
1221    #endif
1222    
1223    #ifdef OSD_CROSSHAIR
1224        x = (osd->widget->allocation.width - OSD_CROSSHAIR_W)/2;
1225        y = (osd->widget->allocation.height - OSD_CROSSHAIR_H)/2;
1226    
1227        cairo_set_source_surface(cr, priv->crosshair, x, y);
1228        cairo_paint(cr);
1229    #endif
1230    
1231    #ifdef OSD_COORDINATES
1232        x = -OSD_X;
1233        y = -OSD_Y;
1234        if(x < 0) x += osd->widget->allocation.width - OSD_COORDINATES_W;
1235        if(y < 0) y += osd->widget->allocation.height - OSD_COORDINATES_H;
1236    
1237        cairo_set_source_surface(cr, priv->coordinates, x, y);
1238        cairo_paint(cr);
1239    #endif
1240    
1241        x = OSD_X;
1242        if(x < 0)
1243            x += osd->widget->allocation.width - OSD_W;
1244    
1245        y = OSD_Y;
1246        if(y < 0)
1247            y += osd->widget->allocation.height - OSD_H;
1248    
1249      cairo_set_source_surface(cr, priv->overlay, x, y);      cairo_set_source_surface(cr, priv->overlay, x, y);
1250      cairo_paint(cr);      cairo_paint(cr);
1251    
1252    #ifdef OSD_SOURCE_SEL
1253        if(!priv->handler_id) {
1254            /* the OSD source selection is not being animated */
1255            if(!priv->expanded)
1256                x = osd->widget->allocation.width - OSD_S_W;
1257            else
1258                x = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
1259        } else
1260            x = priv->shift;
1261    
1262        y = OSD_S_Y;
1263        if(OSD_S_Y < 0) {
1264            if(!priv->expanded)
1265                y = osd->widget->allocation.height - OSD_S_H + OSD_S_Y;
1266            else
1267                y = osd->widget->allocation.height - OSD_S_EXP_H + OSD_S_Y;
1268        }
1269    
1270        cairo_set_source_surface(cr, priv->map_source, x, y);
1271        cairo_paint(cr);
1272    #endif
1273    
1274      cairo_destroy(cr);      cairo_destroy(cr);
1275  }  }
1276    
1277  static void  static void
1278  osm_gps_map_osd_free(osm_gps_map_osd_t *osd)  osd_free(osm_gps_map_osd_t *osd)
1279  {  {
1280      osd_priv_t *priv = (osd_priv_t *)(osd->priv);      osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1281    
1282      if (priv->overlay)      if (priv->overlay)
1283           cairo_surface_destroy(priv->overlay);           cairo_surface_destroy(priv->overlay);
1284    
1285    #ifdef OSD_SOURCE_SEL
1286        if(priv->handler_id)
1287            gtk_timeout_remove(priv->handler_id);
1288    
1289        if (priv->map_source)
1290             cairo_surface_destroy(priv->map_source);
1291    #endif
1292    
1293    #ifdef OSD_SCALE
1294        if (priv->scale)
1295             cairo_surface_destroy(priv->scale);
1296    #endif
1297    
1298    #ifdef OSD_CROSSHAIR
1299        if (priv->crosshair)
1300             cairo_surface_destroy(priv->crosshair);
1301    #endif
1302    
1303    #ifdef OSD_COORDINATES
1304        if (priv->coordinates)
1305             cairo_surface_destroy(priv->coordinates);
1306    #endif
1307    
1308      g_free(priv);      g_free(priv);
1309  }  }
1310    
1311    static gboolean
1312    osd_busy(osm_gps_map_osd_t *osd)
1313    {
1314    #ifdef OSD_SOURCE_SEL
1315        osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1316        return (priv->handler_id != 0);
1317    #else
1318        return FALSE;
1319    #endif
1320    }
1321    
1322  static osm_gps_map_osd_t osd_classic = {  static osm_gps_map_osd_t osd_classic = {
1323      .draw       = osm_gps_map_osd_draw,      .widget     = NULL,
1324      .check      = osm_gps_map_osd_check,  
1325      .render     = osm_gps_map_osd_render,      .draw       = osd_draw,
1326      .free       = osm_gps_map_osd_free,      .check      = osd_check,
1327        .render     = osd_render,
1328        .free       = osd_free,
1329        .busy       = osd_busy,
1330    
1331      .cb         = NULL,      .cb         = NULL,
1332      .data       = NULL,      .data       = NULL,
# Line 499  osm_gps_map_osd_classic_init(OsmGpsMap * Line 1351  osm_gps_map_osd_classic_init(OsmGpsMap *
1351  void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb,  void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb,
1352                                   gpointer data) {                                   gpointer data) {
1353      osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);      osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
   
1354      g_return_if_fail (osd);      g_return_if_fail (osd);
1355    
1356      osd->cb = cb;      osd->cb = cb;
# Line 512  void osm_gps_map_osd_enable_gps (OsmGpsM Line 1363  void osm_gps_map_osd_enable_gps (OsmGpsM
1363      osm_gps_map_redraw(map);      osm_gps_map_redraw(map);
1364  }  }
1365  #endif  #endif
1366    
1367    osd_button_t
1368    osm_gps_map_osd_check(OsmGpsMap *map, gint x, gint y) {
1369        osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
1370        g_return_val_if_fail (osd, OSD_NONE);
1371    
1372        return osd_check(osd, x, y);
1373    }

Legend:
Removed from v.77  
changed lines
  Added in v.107