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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 102 - (hide annotations)
Tue Sep 8 19:08:37 2009 UTC (14 years, 8 months ago) by harbaum
File MIME type: text/plain
File size: 31210 byte(s)
Imperial scale
1 harbaum 71 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
2     /* vim:set et sw=4 ts=4 cino=t0,(0: */
3 harbaum 70 /*
4     * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
5     *
6     * osm-gps-map is free software: you can redistribute it and/or modify it
7     * under the terms of the GNU General Public License as published by the
8     * Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * osm-gps-map is distributed in the hope that it will be useful, but
12     * WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14     * See the GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License along
17     * with this program. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20 harbaum 73 #include "config.h"
21     #include <stdlib.h> // abs
22 harbaum 87 #include <math.h> // M_PI/cos()
23 harbaum 70
24 harbaum 71 /* parameters that can be overwritten from the config file: */
25 harbaum 77 /* OSD_DIAMETER */
26     /* OSD_X, OSD_Y */
27 harbaum 71
28 harbaum 98 #define OSD_SCALE
29    
30 harbaum 100 #define OSD_SCALE_W 120
31 harbaum 98 #define OSD_SCALE_H 20
32    
33 harbaum 71 #ifndef USE_CAIRO
34     #error "OSD control display lacks a non-cairo implementation!"
35 harbaum 70 #endif
36    
37 harbaum 71 #include <cairo.h>
38    
39     #include "osm-gps-map.h"
40 harbaum 73 #include "osm-gps-map-osd-classic.h"
41 harbaum 71
42 harbaum 70 //the osd controls
43     typedef struct {
44 harbaum 74 /* the offscreen representation of the OSD */
45     cairo_surface_t *overlay;
46 harbaum 86
47 harbaum 98 #ifdef OSD_SCALE
48     cairo_surface_t *scale;
49     #endif
50    
51 harbaum 88 #ifdef OSD_SOURCE_SEL
52 harbaum 87 /* values to handle the "source" menu */
53 harbaum 86 cairo_surface_t *map_source;
54     gboolean expanded;
55     gint shift, dir, count;
56     gint handler_id;
57 harbaum 87 gint width, height;
58 harbaum 88 #endif
59 harbaum 87
60 harbaum 70 } osd_priv_t;
61    
62     /* position and extent of bounding box */
63 harbaum 77 #ifndef OSD_X
64 harbaum 70 #define OSD_X (10)
65 harbaum 77 #endif
66    
67     #ifndef OSD_Y
68 harbaum 70 #define OSD_Y (10)
69 harbaum 77 #endif
70 harbaum 70
71     /* parameters of the direction shape */
72 harbaum 77 #ifndef OSD_DIAMETER
73 harbaum 70 #define D_RAD (30) // diameter of dpad
74     #else
75 harbaum 77 #define D_RAD (OSD_DIAMETER)
76 harbaum 70 #endif
77     #define D_TIP (4*D_RAD/5) // distance of arrow tip from dpad center
78     #define D_LEN (D_RAD/4) // length of arrow
79     #define D_WID (D_LEN) // width of arrow
80    
81     /* parameters of the "zoom" pad */
82     #define Z_STEP (D_RAD/4) // distance between dpad and zoom
83     #define Z_RAD (D_RAD/2) // radius of "caps" of zoom bar
84    
85 harbaum 74 #ifdef OSD_SHADOW_ENABLE
86 harbaum 70 /* shadow also depends on control size */
87     #define OSD_SHADOW (D_RAD/6)
88 harbaum 74 #else
89     #define OSD_SHADOW (0)
90     #endif
91 harbaum 70
92 harbaum 77 /* normally the GPS button is in the center of the dpad. if there's */
93     /* no dpad it will go into the zoom area */
94     #if defined(OSD_GPS_BUTTON) && defined(OSD_NO_DPAD)
95     #define Z_GPS 1
96     #else
97     #define Z_GPS 0
98     #endif
99    
100 harbaum 70 /* total width and height of controls incl. shadow */
101 harbaum 77 #define OSD_W (2*D_RAD + OSD_SHADOW + Z_GPS * 2 * Z_RAD)
102     #if !Z_GPS
103 harbaum 70 #define OSD_H (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)
104 harbaum 77 #else
105     #define OSD_H (2*Z_RAD + OSD_SHADOW)
106     #endif
107 harbaum 70
108 harbaum 74 #ifdef OSD_SHADOW_ENABLE
109 harbaum 70 #define OSD_LBL_SHADOW (OSD_SHADOW/2)
110 harbaum 74 #endif
111 harbaum 70
112 harbaum 77 #define Z_TOP ((1-Z_GPS) * (2 * D_RAD + Z_STEP))
113    
114 harbaum 70 #define Z_MID (Z_TOP + Z_RAD)
115     #define Z_BOT (Z_MID + Z_RAD)
116     #define Z_LEFT (Z_RAD)
117 harbaum 77 #define Z_RIGHT (2 * D_RAD - Z_RAD + Z_GPS * 2 * Z_RAD)
118     #define Z_CENTER ((Z_RIGHT + Z_LEFT)/2)
119 harbaum 70
120     /* create the cairo shape used for the zoom buttons */
121     static void
122 harbaum 86 osd_zoom_shape(cairo_t *cr, gint x, gint y)
123 harbaum 71 {
124 harbaum 70 cairo_move_to (cr, x+Z_LEFT, y+Z_TOP);
125     cairo_line_to (cr, x+Z_RIGHT, y+Z_TOP);
126     cairo_arc (cr, x+Z_RIGHT, y+Z_MID, Z_RAD, -M_PI/2, M_PI/2);
127     cairo_line_to (cr, x+Z_LEFT, y+Z_BOT);
128     cairo_arc (cr, x+Z_LEFT, y+Z_MID, Z_RAD, M_PI/2, -M_PI/2);
129     }
130    
131 harbaum 86 /* ------------------- color/shadow functions ----------------- */
132    
133     #ifndef OSD_COLOR
134     /* if no color has been specified we just use the gdks default colors */
135     static void
136     osd_labels(cairo_t *cr, gint width, gboolean enabled,
137     GdkColor *fg, GdkColor *disabled) {
138     if(enabled) gdk_cairo_set_source_color(cr, fg);
139     else gdk_cairo_set_source_color(cr, disabled);
140     cairo_set_line_width (cr, width);
141     }
142     #else
143     static void
144     osd_labels(cairo_t *cr, gint width, gboolean enabled) {
145     if(enabled) cairo_set_source_rgb (cr, OSD_COLOR);
146     else cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);
147     cairo_set_line_width (cr, width);
148     }
149     #endif
150    
151     #ifdef OSD_SHADOW_ENABLE
152     static void
153     osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {
154     cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);
155     cairo_set_line_width (cr, width);
156     }
157     #endif
158    
159 harbaum 76 #ifndef OSD_NO_DPAD
160 harbaum 70 /* create the cairo shape used for the dpad */
161     static void
162 harbaum 86 osd_dpad_shape(cairo_t *cr, gint x, gint y)
163 harbaum 71 {
164 harbaum 70 cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);
165     }
166 harbaum 76 #endif
167 harbaum 70
168 harbaum 86 #ifdef OSD_SHADOW_ENABLE
169     static void
170     osd_shape_shadow(cairo_t *cr) {
171     cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
172     cairo_fill (cr);
173     cairo_stroke (cr);
174     }
175     #endif
176    
177     #ifndef OSD_COLOR
178     /* if no color has been specified we just use the gdks default colors */
179     static void
180     osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {
181     gdk_cairo_set_source_color(cr, bg);
182     cairo_fill_preserve (cr);
183     gdk_cairo_set_source_color(cr, fg);
184     cairo_set_line_width (cr, 1);
185     cairo_stroke (cr);
186     }
187     #else
188     static void
189     osd_shape(cairo_t *cr) {
190     cairo_set_source_rgb (cr, OSD_COLOR_BG);
191     cairo_fill_preserve (cr);
192     cairo_set_source_rgb (cr, OSD_COLOR);
193     cairo_set_line_width (cr, 1);
194     cairo_stroke (cr);
195     }
196     #endif
197    
198    
199 harbaum 70 static gboolean
200     osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)
201     {
202     return( pow(cx - x, 2) + pow(cy - y, 2) < rad * rad);
203     }
204    
205 harbaum 76 #ifndef OSD_NO_DPAD
206 harbaum 70 /* check whether x/y is within the dpad */
207     static osd_button_t
208 harbaum 86 osd_check_dpad(gint x, gint y)
209 harbaum 70 {
210     /* within entire dpad circle */
211 harbaum 77 if( osm_gps_map_in_circle(x, y, D_RAD, D_RAD, D_RAD))
212 harbaum 70 {
213     /* convert into position relative to dpads centre */
214 harbaum 77 x -= D_RAD;
215     y -= D_RAD;
216 harbaum 70
217 harbaum 76 #ifdef OSD_GPS_BUTTON
218 harbaum 70 /* check for dpad center goes here! */
219     if( osm_gps_map_in_circle(x, y, 0, 0, D_RAD/3))
220     return OSD_GPS;
221 harbaum 76 #endif
222 harbaum 70
223     if( y < 0 && abs(x) < abs(y))
224     return OSD_UP;
225    
226     if( y > 0 && abs(x) < abs(y))
227     return OSD_DOWN;
228    
229     if( x < 0 && abs(y) < abs(x))
230     return OSD_LEFT;
231    
232     if( x > 0 && abs(y) < abs(x))
233     return OSD_RIGHT;
234    
235     return OSD_BG;
236     }
237     return OSD_NONE;
238     }
239 harbaum 76 #endif
240 harbaum 70
241     /* check whether x/y is within the zoom pads */
242     static osd_button_t
243 harbaum 86 osd_check_zoom(gint x, gint y) {
244 harbaum 77 if( x > 0 && x < OSD_W && y > Z_TOP && y < Z_BOT) {
245 harbaum 70
246     /* within circle around (-) label */
247 harbaum 77 if( osm_gps_map_in_circle(x, y, Z_LEFT, Z_MID, Z_RAD))
248 harbaum 70 return OSD_OUT;
249    
250 harbaum 77 /* within circle around (+) label */
251     if( osm_gps_map_in_circle(x, y, Z_RIGHT, Z_MID, Z_RAD))
252     return OSD_IN;
253    
254     #if Z_GPS == 1
255     /* within square around center */
256     if( x > Z_CENTER - Z_RAD && x < Z_CENTER + Z_RAD)
257     return OSD_GPS;
258     #endif
259    
260 harbaum 70 /* between center of (-) button and center of entire zoom control area */
261 harbaum 77 if(x > OSD_LEFT && x < D_RAD)
262 harbaum 70 return OSD_OUT;
263    
264     /* between center of (+) button and center of entire zoom control area */
265 harbaum 77 if(x < OSD_RIGHT && x > D_RAD)
266 harbaum 70 return OSD_IN;
267     }
268    
269     return OSD_NONE;
270     }
271    
272 harbaum 88 #ifdef OSD_SOURCE_SEL
273    
274 harbaum 86 /* place source selection at right border */
275     #define OSD_S_RAD (Z_RAD)
276     #define OSD_S_X (-OSD_X)
277     #define OSD_S_Y (OSD_Y)
278     #define OSD_S_PW (2 * Z_RAD)
279     #define OSD_S_W (OSD_S_PW)
280     #define OSD_S_PH (2 * Z_RAD)
281     #define OSD_S_H (OSD_S_PH + OSD_SHADOW)
282    
283 harbaum 87 /* size of usable area when expanded */
284     #define OSD_S_AREA_W (priv->width)
285     #define OSD_S_AREA_H (priv->height)
286 harbaum 86 #define OSD_S_EXP_W (OSD_S_PW + OSD_S_AREA_W + OSD_SHADOW)
287     #define OSD_S_EXP_H (OSD_S_AREA_H + OSD_SHADOW)
288    
289     /* internal value to draw the arrow on the "puller" */
290     #define OSD_S_D0 (OSD_S_RAD/2)
291 harbaum 87 #ifndef OSD_FONT_SIZE
292     #define OSD_FONT_SIZE 16.0
293     #endif
294     #define OSD_TEXT_BORDER (OSD_FONT_SIZE/2)
295     #define OSD_TEXT_SKIP (OSD_FONT_SIZE/8)
296 harbaum 86
297 harbaum 88 /* draw the shape of the source selection OSD, either only the puller (not expanded) */
298     /* or the entire menu incl. the puller (expanded) */
299 harbaum 86 static void
300     osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) {
301     if(!priv->expanded) {
302     /* just draw the puller */
303     cairo_move_to (cr, x + OSD_S_PW, y + OSD_S_PH);
304     cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
305     cairo_line_to (cr, x + OSD_S_PW, y);
306     } else {
307     /* draw the puller and the area itself */
308     cairo_move_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y + OSD_S_AREA_H);
309     cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H);
310     if(OSD_S_Y > 0) {
311     cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_PH);
312     cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
313     } else {
314     cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_AREA_H-OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
315     cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H - OSD_S_PH);
316     cairo_line_to (cr, x + OSD_S_PW, y);
317     }
318     cairo_line_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y);
319     cairo_close_path (cr);
320     }
321     }
322    
323     static void
324 harbaum 87 osd_source_content(osm_gps_map_osd_t *osd, cairo_t *cr, gint offset) {
325     osd_priv_t *priv = (osd_priv_t*)osd->priv;
326 harbaum 86
327 harbaum 87 int py = offset + OSD_S_RAD - OSD_S_D0;
328    
329 harbaum 86 if(!priv->expanded) {
330     /* draw the "puller" open (<) arrow */
331 harbaum 87 cairo_move_to (cr, offset + OSD_S_RAD + OSD_S_D0/2, py);
332 harbaum 86 cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
333     cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
334     } else {
335     if(OSD_S_Y < 0)
336 harbaum 87 py += OSD_S_AREA_H - OSD_S_PH;
337 harbaum 86
338     /* draw the "puller" close (>) arrow */
339 harbaum 87 cairo_move_to (cr, offset + OSD_S_RAD - OSD_S_D0/2, py);
340 harbaum 86 cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
341     cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
342 harbaum 87 cairo_stroke(cr);
343    
344     /* don't draw a shadow for the text content */
345     if(offset == 1) {
346     gint source;
347     g_object_get(osd->widget, "map-source", &source, NULL);
348    
349     cairo_select_font_face (cr, "Sans",
350     CAIRO_FONT_SLANT_NORMAL,
351     CAIRO_FONT_WEIGHT_BOLD);
352     cairo_set_font_size (cr, OSD_FONT_SIZE);
353    
354 harbaum 89 int i, step = (priv->height - 2*OSD_TEXT_BORDER) /
355     OSM_GPS_MAP_SOURCE_LAST;
356 harbaum 87 for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
357     cairo_text_extents_t extents;
358     const char *src = osm_gps_map_source_get_friendly_name(i);
359     cairo_text_extents (cr, src, &extents);
360    
361     int x = offset + OSD_S_PW + OSD_TEXT_BORDER;
362     int y = offset + step * (i-1) + OSD_TEXT_BORDER;
363    
364     /* draw filled rectangle if selected */
365     if(source == i) {
366     cairo_rectangle(cr, x - OSD_TEXT_BORDER/2,
367     y - OSD_TEXT_SKIP,
368     priv->width - OSD_TEXT_BORDER,
369     step + OSD_TEXT_SKIP);
370     cairo_fill(cr);
371    
372     /* temprarily draw with background color */
373     #ifndef OSD_COLOR
374     GdkColor bg = osd->widget->style->bg[GTK_STATE_NORMAL];
375     gdk_cairo_set_source_color(cr, &bg);
376     #else
377     cairo_set_source_rgb (cr, OSD_COLOR_BG);
378     #endif
379     }
380    
381     cairo_move_to (cr, x, y + OSD_TEXT_SKIP - extents.y_bearing);
382     cairo_show_text (cr, src);
383    
384     /* restore color */
385     if(source == i) {
386     #ifndef OSD_COLOR
387     GdkColor fg = osd->widget->style->fg[GTK_STATE_NORMAL];
388     gdk_cairo_set_source_color(cr, &fg);
389     #else
390     cairo_set_source_rgb (cr, OSD_COLOR);
391     #endif
392     }
393     }
394     }
395 harbaum 86 }
396     }
397    
398     static void
399     osd_render_source_sel(osm_gps_map_osd_t *osd) {
400     osd_priv_t *priv = (osd_priv_t*)osd->priv;
401    
402     #ifndef OSD_COLOR
403     GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
404     GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
405     GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
406     #endif
407    
408     /* draw source selector */
409     cairo_t *cr = cairo_create(priv->map_source);
410     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
411     cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
412     cairo_paint(cr);
413     cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
414    
415     #ifdef OSD_SHADOW_ENABLE
416     osd_source_shape(priv, cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
417     osd_shape_shadow(cr);
418     #endif
419    
420     osd_source_shape(priv, cr, 1, 1);
421     #ifndef OSD_COLOR
422     osd_shape(cr, &bg, &fg);
423     #else
424     osd_shape(cr);
425     #endif
426    
427     #ifdef OSD_SHADOW_ENABLE
428     osd_labels_shadow(cr, Z_RAD/3, TRUE);
429 harbaum 87 osd_source_content(osd, cr, 1+OSD_LBL_SHADOW);
430     cairo_stroke (cr);
431 harbaum 86 #endif
432     #ifndef OSD_COLOR
433     osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
434     #else
435     osd_labels(cr, Z_RAD/3, TRUE);
436     #endif
437 harbaum 87 osd_source_content(osd, cr, 1);
438     cairo_stroke (cr);
439 harbaum 86
440     cairo_destroy(cr);
441     }
442    
443 harbaum 89 /* re-allocate the buffer used to draw the menu. This is used */
444     /* to collapse/expand the buffer */
445 harbaum 86 static void
446     osd_source_reallocate(osm_gps_map_osd_t *osd) {
447     osd_priv_t *priv = (osd_priv_t*)osd->priv;
448    
449     /* re-allocate offscreen bitmap */
450     g_assert (priv->map_source);
451    
452     int w = OSD_S_W, h = OSD_S_H;
453     if(priv->expanded) {
454 harbaum 87 cairo_text_extents_t extents;
455    
456     /* determine content size */
457     cairo_t *cr = cairo_create(priv->map_source);
458     cairo_select_font_face (cr, "Sans",
459     CAIRO_FONT_SLANT_NORMAL,
460     CAIRO_FONT_WEIGHT_BOLD);
461     cairo_set_font_size (cr, OSD_FONT_SIZE);
462    
463     /* calculate menu size */
464     int i, max_h = 0, max_w = 0;
465     for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
466     const char *src = osm_gps_map_source_get_friendly_name(i);
467     cairo_text_extents (cr, src, &extents);
468    
469     if(extents.width > max_w) max_w = extents.width;
470     if(extents.height > max_h) max_h = extents.height;
471     }
472     cairo_destroy(cr);
473    
474     priv->width = max_w + 2*OSD_TEXT_BORDER;
475     priv->height = OSM_GPS_MAP_SOURCE_LAST *
476     (max_h + 2*OSD_TEXT_SKIP) + 2*OSD_TEXT_BORDER;
477    
478 harbaum 86 w = OSD_S_EXP_W;
479     h = OSD_S_EXP_H;
480     }
481    
482 harbaum 87 cairo_surface_destroy(priv->map_source);
483 harbaum 86 priv->map_source =
484     cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2);
485    
486     osd_render_source_sel(osd);
487     }
488    
489     #define OSD_HZ 15
490 harbaum 87 #define OSD_TIME 500
491 harbaum 86
492     static gboolean osd_source_animate(gpointer data) {
493     osm_gps_map_osd_t *osd = (osm_gps_map_osd_t*)data;
494     osd_priv_t *priv = (osd_priv_t*)osd->priv;
495     int diff = OSD_S_EXP_W - OSD_S_W - OSD_S_X;
496     gboolean done = FALSE;
497     priv->count += priv->dir;
498    
499     /* shifting in */
500     if(priv->dir < 0) {
501     if(priv->count <= 0) {
502     priv->count = 0;
503     done = TRUE;
504     }
505     } else {
506     if(priv->count >= 1000) {
507     priv->expanded = FALSE;
508     osd_source_reallocate(osd);
509    
510     priv->count = 1000;
511     done = TRUE;
512     }
513     }
514    
515    
516     /* count runs linearly from 0 to 1000, map this nicely onto a position */
517    
518     /* nicer sinoid mapping */
519     float m = 0.5-cos(priv->count * M_PI / 1000.0)/2;
520     priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +
521     m * diff;
522    
523     osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
524    
525     if(done)
526     priv->handler_id = 0;
527    
528     return !done;
529     }
530    
531     /* switch between expand and collapse mode of source selection */
532     static void
533     osd_source_toggle(osm_gps_map_osd_t *osd)
534     {
535     osd_priv_t *priv = (osd_priv_t*)osd->priv;
536    
537     /* ignore clicks while animation is running */
538     if(priv->handler_id)
539     return;
540    
541     /* expand immediately, collapse is handle at the end of the collapse animation */
542     if(!priv->expanded) {
543     priv->expanded = TRUE;
544     osd_source_reallocate(osd);
545    
546     priv->count = 1000;
547     priv->shift = osd->widget->allocation.width - OSD_S_W;
548     priv->dir = -1000/OSD_HZ;
549     } else {
550     priv->count = 0;
551     priv->shift = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
552     priv->dir = +1000/OSD_HZ;
553     }
554    
555     priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd);
556     }
557    
558 harbaum 89 /* check if the user clicked inside the source selection area */
559 harbaum 70 static osd_button_t
560 harbaum 86 osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) {
561     osd_priv_t *priv = (osd_priv_t*)osd->priv;
562    
563     if(!priv->expanded)
564     x -= osd->widget->allocation.width - OSD_S_W;
565     else
566     x -= osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
567    
568     if(OSD_S_Y > 0)
569     y -= OSD_S_Y;
570     else
571     y -= osd->widget->allocation.height - OSD_S_PH + OSD_S_Y;
572    
573     /* within square around puller? */
574     if(y > 0 && y < OSD_S_PH && x > 0 && x < OSD_S_PW) {
575     /* really within puller shape? */
576     if(x > Z_RAD || osm_gps_map_in_circle(x, y, Z_RAD, Z_RAD, Z_RAD)) {
577     /* expand source selector */
578     osd_source_toggle(osd);
579    
580     /* tell upper layers that user clicked some background element */
581     /* of the OSD */
582     return OSD_BG;
583     }
584     }
585 harbaum 88
586     /* check for clicks into data area */
587 harbaum 89 if(priv->expanded && !priv->handler_id) {
588 harbaum 94 /* re-adjust from puller top to content top */
589     if(OSD_S_Y < 0)
590     y += OSD_S_EXP_H - OSD_S_PH;
591    
592 harbaum 88 if(x > OSD_S_PW &&
593     x < OSD_S_PW + OSD_S_EXP_W &&
594     y > 0 &&
595     y < OSD_S_EXP_H) {
596 harbaum 94
597 harbaum 89 int step = (priv->height - 2*OSD_TEXT_BORDER)
598     / OSM_GPS_MAP_SOURCE_LAST;
599 harbaum 88
600 harbaum 89 y -= OSD_TEXT_BORDER - OSD_TEXT_SKIP;
601     y /= step;
602     y += 1;
603    
604     gint old = 0;
605     g_object_get(osd->widget, "map-source", &old, NULL);
606    
607     if(y > OSM_GPS_MAP_SOURCE_NULL &&
608     y <= OSM_GPS_MAP_SOURCE_LAST &&
609     old != y) {
610     g_object_set(osd->widget, "map-source", y, NULL);
611    
612     osd_render_source_sel(osd);
613     osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
614     }
615    
616     /* return "clicked in OSD background" to prevent further */
617     /* processing by application */
618 harbaum 88 return OSD_BG;
619     }
620     }
621    
622 harbaum 86 return OSD_NONE;
623     }
624 harbaum 88 #endif // OSD_SOURCE_SEL
625 harbaum 86
626     static osd_button_t
627     osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {
628 harbaum 70 osd_button_t but = OSD_NONE;
629    
630 harbaum 86 #ifdef OSD_SOURCE_SEL
631     /* the source selection area is handles internally */
632     but = osd_source_check(osd, x, y);
633     if(but != OSD_NONE)
634     return but;
635     #endif
636    
637 harbaum 77 x -= OSD_X;
638     y -= OSD_Y;
639    
640     if(OSD_X < 0)
641     x -= (osd->widget->allocation.width - OSD_W);
642    
643     if(OSD_Y < 0)
644     y -= (osd->widget->allocation.height - OSD_H);
645    
646 harbaum 70 /* first do a rough test for the OSD area. */
647     /* this is just to avoid an unnecessary detailed test */
648 harbaum 77 if(x > 0 && x < OSD_W && y > 0 && y < OSD_H) {
649 harbaum 76 #ifndef OSD_NO_DPAD
650 harbaum 86 but = osd_check_dpad(x, y);
651 harbaum 76 #endif
652 harbaum 70
653     if(but == OSD_NONE)
654 harbaum 86 but = osd_check_zoom(x, y);
655 harbaum 70 }
656    
657     return but;
658     }
659    
660 harbaum 76 #ifndef OSD_NO_DPAD
661 harbaum 70 static void
662 harbaum 86 osd_dpad_labels(cairo_t *cr, gint x, gint y) {
663 harbaum 70 /* move reference to dpad center */
664     x += D_RAD;
665     y += D_RAD;
666    
667     const static gint offset[][3][2] = {
668     /* left arrow/triangle */
669     { { -D_TIP+D_LEN, -D_WID }, { -D_LEN, D_WID }, { +D_LEN, D_WID } },
670     /* right arrow/triangle */
671     { { +D_TIP-D_LEN, -D_WID }, { +D_LEN, D_WID }, { -D_LEN, D_WID } },
672     /* top arrow/triangle */
673     { { -D_WID, -D_TIP+D_LEN }, { D_WID, -D_LEN }, { D_WID, +D_LEN } },
674     /* bottom arrow/triangle */
675     { { -D_WID, +D_TIP-D_LEN }, { D_WID, +D_LEN }, { D_WID, -D_LEN } }
676     };
677    
678     int i;
679     for(i=0;i<4;i++) {
680     cairo_move_to (cr, x + offset[i][0][0], y + offset[i][0][1]);
681     cairo_rel_line_to (cr, offset[i][1][0], offset[i][1][1]);
682     cairo_rel_line_to (cr, offset[i][2][0], offset[i][2][1]);
683     }
684     }
685 harbaum 76 #endif
686 harbaum 70
687 harbaum 76 #ifdef OSD_GPS_BUTTON
688     /* draw the satellite dish icon in the center of the dpad */
689 harbaum 77 #define GPS_V0 (D_RAD/7)
690 harbaum 70 #define GPS_V1 (D_RAD/10)
691     #define GPS_V2 (D_RAD/5)
692    
693     /* draw a satellite receiver dish */
694 harbaum 77 /* this is either drawn in the center of the dpad (if present) */
695     /* or in the middle of the zoom area */
696 harbaum 70 static void
697 harbaum 86 osd_dpad_gps(cairo_t *cr, gint x, gint y) {
698 harbaum 70 /* move reference to dpad center */
699 harbaum 77 x += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD * 3;
700     y += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD + GPS_V0;
701 harbaum 70
702     cairo_move_to (cr, x-GPS_V0, y+GPS_V0);
703     cairo_rel_line_to (cr, +GPS_V0, -GPS_V0);
704     cairo_rel_line_to (cr, +GPS_V0, +GPS_V0);
705     cairo_close_path (cr);
706    
707     cairo_move_to (cr, x+GPS_V1-GPS_V2, y-2*GPS_V2);
708     cairo_curve_to (cr, x-GPS_V2, y, x+GPS_V1, y+GPS_V1, x+GPS_V1+GPS_V2, y);
709     cairo_close_path (cr);
710    
711     x += GPS_V1;
712     cairo_move_to (cr, x, y-GPS_V2);
713     cairo_rel_line_to (cr, +GPS_V1, -GPS_V1);
714     }
715 harbaum 76 #endif
716 harbaum 70
717     #define Z_LEN (2*Z_RAD/3)
718    
719     static void
720 harbaum 86 osd_zoom_labels(cairo_t *cr, gint x, gint y) {
721 harbaum 70 cairo_move_to (cr, x + Z_LEFT - Z_LEN, y + Z_MID);
722     cairo_line_to (cr, x + Z_LEFT + Z_LEN, y + Z_MID);
723    
724     cairo_move_to (cr, x + Z_RIGHT, y + Z_MID - Z_LEN);
725     cairo_line_to (cr, x + Z_RIGHT, y + Z_MID + Z_LEN);
726     cairo_move_to (cr, x + Z_RIGHT - Z_LEN, y + Z_MID);
727     cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
728     }
729    
730 harbaum 99 static char *
731     dist_str_metric(int dist)
732     {
733     if(dist<1000)
734     return g_strdup_printf("%u m", dist);
735    
736     return g_strdup_printf("%u km", dist/1000);
737 harbaum 98 }
738    
739 harbaum 102 #define OSD_SCALE_FONT_SIZE 12
740    
741 harbaum 70 static void
742 harbaum 98 osd_render_scale(osm_gps_map_osd_t *osd)
743     {
744 harbaum 86 osd_priv_t *priv = (osd_priv_t*)osd->priv;
745 harbaum 99 float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget));
746 harbaum 70
747 harbaum 98 /* first fill with transparency */
748     cairo_t *cr = cairo_create(priv->scale);
749     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
750 harbaum 100 cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
751     // cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
752 harbaum 98 cairo_paint(cr);
753     cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
754    
755     /* determine the size of the scale width in meters */
756 harbaum 99 float width = (OSD_SCALE_W-2) * m_per_pix;
757 harbaum 102 printf("%d pixels is %f m\n", OSD_SCALE_W-2, width);
758    
759 harbaum 98 /* scale this to useful values */
760     int exp = logf(width)*M_LOG10E;
761     int mant = width/pow(10,exp);
762 harbaum 99 int width_metric = mant * pow(10,exp);
763     char *dist_str = dist_str_metric(width_metric);
764     width_metric /= m_per_pix;
765    
766 harbaum 102 /* and now the hard part: scale for useful imperial values :-( */
767     /* try to convert to feet, 1ft == 0.3048 m */
768     width /= 0.3048;
769     float imp_scale = 0.3048;
770     char *dist_imp_unit = "ft";
771 harbaum 99
772 harbaum 102 if(width >= 100) {
773     /* 1yd == 3 feet */
774     width /= 3.0;
775     imp_scale *= 3.0;
776     dist_imp_unit = "yd";
777    
778     if(width >= 1760.0) {
779     /* 1mi == 1760 yd */
780     width /= 1760.0;
781     imp_scale *= 1760.0;
782     dist_imp_unit = "mi";
783     }
784     }
785    
786     printf("this is %f %s\n", width, dist_imp_unit);
787     printf("this is %f pixels\n", width * imp_scale / m_per_pix);
788    
789 harbaum 99 cairo_select_font_face (cr, "Sans",
790     CAIRO_FONT_SLANT_NORMAL,
791     CAIRO_FONT_WEIGHT_BOLD);
792 harbaum 102 cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE);
793 harbaum 99 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
794    
795     cairo_text_extents_t extents;
796     cairo_text_extents (cr, dist_str, &extents);
797    
798 harbaum 100 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
799 harbaum 102 cairo_move_to (cr, OSD_SCALE_FONT_SIZE/3, OSD_SCALE_FONT_SIZE);
800 harbaum 100 cairo_text_path (cr, dist_str);
801     cairo_set_line_width (cr, 2);
802     cairo_stroke (cr);
803    
804     cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
805 harbaum 102 cairo_move_to (cr, OSD_SCALE_FONT_SIZE/3, OSD_SCALE_FONT_SIZE);
806 harbaum 99 cairo_show_text (cr, dist_str);
807    
808     /* draw white line */
809     cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
810     cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
811 harbaum 100 cairo_set_line_width (cr, 4);
812 harbaum 102 cairo_move_to (cr, 2, 2*OSD_SCALE_FONT_SIZE/3);
813     cairo_rel_line_to (cr, 0, 2*OSD_SCALE_FONT_SIZE/3);
814 harbaum 99 cairo_rel_line_to (cr, width_metric, 0);
815 harbaum 102 cairo_rel_line_to (cr, 0, -2*OSD_SCALE_FONT_SIZE/3);
816 harbaum 99 cairo_stroke(cr);
817    
818     /* draw black line */
819     cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
820     cairo_set_line_width (cr, 2);
821 harbaum 102 cairo_move_to (cr, 2, 2*OSD_SCALE_FONT_SIZE/3);
822     cairo_rel_line_to (cr, 0, 2*OSD_SCALE_FONT_SIZE/3);
823 harbaum 99 cairo_rel_line_to (cr, width_metric, 0);
824 harbaum 102 cairo_rel_line_to (cr, 0, -2*OSD_SCALE_FONT_SIZE/3);
825 harbaum 99 cairo_stroke(cr);
826    
827     /* xyz */
828    
829 harbaum 98 cairo_destroy(cr);
830     }
831    
832     static void
833     osd_render(osm_gps_map_osd_t *osd)
834     {
835     osd_priv_t *priv = (osd_priv_t*)osd->priv;
836    
837 harbaum 86 #ifndef OSD_COLOR
838     GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
839     GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
840     GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
841 harbaum 74 #endif
842 harbaum 70
843     /* first fill with transparency */
844 harbaum 73 cairo_t *cr = cairo_create(priv->overlay);
845 harbaum 70 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
846     cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
847     cairo_paint(cr);
848     cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
849    
850     /* --------- draw zoom and dpad shape shadow ----------- */
851 harbaum 74 #ifdef OSD_SHADOW_ENABLE
852 harbaum 86 osd_zoom_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
853     osd_shape_shadow(cr);
854 harbaum 76 #ifndef OSD_NO_DPAD
855 harbaum 86 osd_dpad_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
856     osd_shape_shadow(cr);
857 harbaum 74 #endif
858 harbaum 76 #endif
859 harbaum 70
860     /* --------- draw zoom and dpad shape ----------- */
861    
862 harbaum 86 osd_zoom_shape(cr, 1, 1);
863 harbaum 74 #ifndef OSD_COLOR
864 harbaum 86 osd_shape(cr, &bg, &fg);
865 harbaum 74 #else
866 harbaum 86 osd_shape(cr);
867 harbaum 74 #endif
868 harbaum 76 #ifndef OSD_NO_DPAD
869 harbaum 86 osd_dpad_shape(cr, 1, 1);
870 harbaum 74 #ifndef OSD_COLOR
871 harbaum 86 osd_shape(cr, &bg, &fg);
872 harbaum 74 #else
873 harbaum 86 osd_shape(cr);
874 harbaum 74 #endif
875 harbaum 76 #endif
876 harbaum 70
877     /* --------- draw zoom and dpad labels --------- */
878    
879 harbaum 74 #ifdef OSD_SHADOW_ENABLE
880 harbaum 87 osd_labels_shadow(cr, Z_RAD/3, TRUE);
881 harbaum 86 osd_zoom_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
882 harbaum 76 #ifndef OSD_NO_DPAD
883 harbaum 86 osd_dpad_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
884 harbaum 76 #endif
885 harbaum 87 cairo_stroke(cr);
886 harbaum 76 #ifdef OSD_GPS_BUTTON
887 harbaum 87 osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL);
888 harbaum 86 osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
889 harbaum 87 cairo_stroke(cr);
890 harbaum 74 #endif
891 harbaum 76 #endif
892 harbaum 70
893 harbaum 74 #ifndef OSD_COLOR
894 harbaum 86 osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
895 harbaum 74 #else
896 harbaum 86 osd_labels(cr, Z_RAD/3, TRUE);
897 harbaum 74 #endif
898 harbaum 87 osd_zoom_labels(cr, 1, 1);
899     #ifndef OSD_NO_DPAD
900     osd_dpad_labels(cr, 1, 1);
901     #endif
902     cairo_stroke(cr);
903    
904 harbaum 74 #ifndef OSD_COLOR
905 harbaum 86 osd_labels(cr, Z_RAD/6, osd->cb != NULL, &fg, &da);
906 harbaum 74 #else
907 harbaum 86 osd_labels(cr, Z_RAD/6, osd->cb != NULL);
908 harbaum 74 #endif
909 harbaum 87 #ifdef OSD_GPS_BUTTON
910     osd_dpad_gps(cr, 1, 1);
911 harbaum 76 #endif
912 harbaum 87 cairo_stroke(cr);
913 harbaum 70
914     cairo_destroy(cr);
915 harbaum 86
916 harbaum 88 #ifdef OSD_SOURCE_SEL
917 harbaum 86 osd_render_source_sel(osd);
918 harbaum 88 #endif
919 harbaum 98
920     #ifdef OSD_SCALE
921     osd_render_scale(osd);
922     #endif
923 harbaum 70 }
924    
925     static void
926 harbaum 86 osd_draw(osm_gps_map_osd_t *osd, GdkDrawable *drawable)
927 harbaum 70 {
928 harbaum 73 osd_priv_t *priv = (osd_priv_t*)osd->priv;
929 harbaum 70
930     /* OSD itself uses some off-screen rendering, so check if the */
931     /* offscreen buffer is present and create it if not */
932 harbaum 73 if(!priv->overlay) {
933 harbaum 70 /* create overlay ... */
934 harbaum 73 priv->overlay =
935 harbaum 86 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2);
936    
937 harbaum 88 #ifdef OSD_SOURCE_SEL
938 harbaum 86 /* the initial OSD state is alway not-expanded */
939     priv->map_source =
940     cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
941     OSD_S_W+2, OSD_S_H+2);
942 harbaum 88 #endif
943 harbaum 86
944 harbaum 98 #ifdef OSD_SCALE
945     priv->scale =
946     cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
947 harbaum 99 OSD_SCALE_W+2, OSD_SCALE_H+2);
948 harbaum 98 #endif
949    
950 harbaum 70 /* ... and render it */
951 harbaum 86 osd_render(osd);
952 harbaum 70 }
953    
954     // now draw this onto the original context
955 harbaum 75 cairo_t *cr = gdk_cairo_create(drawable);
956 harbaum 77
957     int x = OSD_X, y = OSD_Y;
958     if(OSD_X < 0)
959     x = osd->widget->allocation.width - OSD_W + OSD_X;
960    
961     if(OSD_Y < 0)
962     y = osd->widget->allocation.height - OSD_H + OSD_Y;
963    
964     cairo_set_source_surface(cr, priv->overlay, x, y);
965 harbaum 70 cairo_paint(cr);
966 harbaum 86
967     #ifdef OSD_SOURCE_SEL
968     if(!priv->handler_id) {
969     /* the OSD source selection is not being animated */
970     if(!priv->expanded)
971     x = osd->widget->allocation.width - OSD_S_W;
972     else
973     x = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
974     } else
975     x = priv->shift;
976    
977     y = OSD_S_Y;
978     if(OSD_S_Y < 0) {
979     if(!priv->expanded)
980     y = osd->widget->allocation.height - OSD_S_H + OSD_S_Y;
981     else
982     y = osd->widget->allocation.height - OSD_S_EXP_H + OSD_S_Y;
983     }
984    
985     cairo_set_source_surface(cr, priv->map_source, x, y);
986     cairo_paint(cr);
987     #endif
988    
989 harbaum 98 #ifdef OSD_SCALE
990     x = OSD_X;
991     y = -OSD_Y;
992     if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W;
993     if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H;
994    
995     cairo_set_source_surface(cr, priv->scale, x, y);
996     cairo_paint(cr);
997     #endif
998    
999 harbaum 70 cairo_destroy(cr);
1000     }
1001    
1002     static void
1003 harbaum 86 osd_free(osm_gps_map_osd_t *osd)
1004 harbaum 70 {
1005 harbaum 73 osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1006 harbaum 70
1007 harbaum 88 if (priv->overlay)
1008     cairo_surface_destroy(priv->overlay);
1009    
1010     #ifdef OSD_SOURCE_SEL
1011 harbaum 86 if(priv->handler_id)
1012     gtk_timeout_remove(priv->handler_id);
1013    
1014     if (priv->map_source)
1015     cairo_surface_destroy(priv->map_source);
1016 harbaum 88 #endif
1017 harbaum 86
1018 harbaum 98 #ifdef OSD_SCALE
1019     if (priv->scale)
1020     cairo_surface_destroy(priv->scale);
1021     #endif
1022    
1023 harbaum 73 g_free(priv);
1024     }
1025    
1026 harbaum 87 static gboolean
1027     osd_busy(osm_gps_map_osd_t *osd)
1028     {
1029 harbaum 88 #ifdef OSD_SOURCE_SEL
1030 harbaum 87 osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1031     return (priv->handler_id != 0);
1032 harbaum 88 #else
1033     return FALSE;
1034     #endif
1035 harbaum 87 }
1036    
1037 harbaum 73 static osm_gps_map_osd_t osd_classic = {
1038 harbaum 88 .widget = NULL,
1039    
1040 harbaum 86 .draw = osd_draw,
1041     .check = osd_check,
1042     .render = osd_render,
1043     .free = osd_free,
1044 harbaum 87 .busy = osd_busy,
1045 harbaum 73
1046     .cb = NULL,
1047     .data = NULL,
1048    
1049     .priv = NULL
1050     };
1051    
1052     /* this is the only function that's externally visible */
1053     void
1054     osm_gps_map_osd_classic_init(OsmGpsMap *map)
1055     {
1056     osd_priv_t *priv = osd_classic.priv = g_new0(osd_priv_t, 1);
1057    
1058     osd_classic.priv = priv;
1059    
1060     osm_gps_map_register_osd(map, &osd_classic);
1061     }
1062    
1063 harbaum 76 #ifdef OSD_GPS_BUTTON
1064 harbaum 74 /* below are osd specific functions which aren't used by osm-gps-map */
1065     /* but instead are to be used by the main application */
1066 harbaum 76 void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb,
1067     gpointer data) {
1068 harbaum 73 osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
1069     g_return_if_fail (osd);
1070    
1071     osd->cb = cb;
1072     osd->data = data;
1073    
1074 harbaum 70 /* this may have changed the state of the gps button */
1075     /* we thus re-render the overlay */
1076 harbaum 73 osd->render(osd);
1077 harbaum 70
1078 harbaum 73 osm_gps_map_redraw(map);
1079 harbaum 70 }
1080 harbaum 76 #endif
1081 harbaum 86
1082     osd_button_t
1083     osm_gps_map_osd_check(OsmGpsMap *map, gint x, gint y) {
1084     osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
1085     g_return_val_if_fail (osd, OSD_NONE);
1086    
1087     return osd_check(osd, x, y);
1088     }