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

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

revision 71 by harbaum, Fri Aug 21 13:20:40 2009 UTC revision 74 by harbaum, Mon Aug 24 09:23:36 2009 UTC
# Line 17  Line 17 
17   * with this program.  If not, see <http://www.gnu.org/licenses/>.   * with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */   */
19    
20  #include "config.h"  #include "config.h"
21    #include <stdlib.h>  // abs
22    #include <math.h>    // M_PI
23    
24  /* parameters that can be overwritten from the config file: */  /* parameters that can be overwritten from the config file: */
25  /* OSM_GPS_MAP_OSD_DIAMETER */  /* OSM_GPS_MAP_OSD_DIAMETER */
# Line 29  Line 31 
31  #include <cairo.h>  #include <cairo.h>
32    
33  #include "osm-gps-map.h"  #include "osm-gps-map.h"
34    #include "osm-gps-map-osd-classic.h"
35    
36  //the osd controls  //the osd controls
37  typedef struct {  typedef struct {
38        /* the offscreen representation of the OSD */
39        cairo_surface_t *overlay;
40    
41        /* stuff required to restore the original map content */
42      GdkPixmap *backup;      GdkPixmap *backup;
43      gint backup_x, backup_y;      gint backup_x, backup_y;
44    
45      cairo_surface_t *overlay;      GdkColor bg, fg, da;
46    
     OsmGpsMapOsdGpsCallback cb;  
     gpointer data;  
47  } osd_priv_t;  } osd_priv_t;
48    
 /* the osd structure mainly contains various callbacks */  
 /* required to draw and update the OSD */  
 typedef struct {  
   
     void(enable_gps)(OsmGpsMap *, OsmGpsMapOsdGpsCallback, gpointer);  
     void(restore)(OsmGpsMap*);  
     void(draw)(OsmGpsMap *, gint, gint);  
     void(render)(OsmGpsMapPrivate *);  
     osd_button_t(*check)(gint, gint);       /* check if x/y lies within OSD */  
     void(free)(gpointer);  
   
     gpointer priv;  
 } osm_gps_map_osd_t;  
   
 static osm_gps_map_osd_t osd_classic = {  
     .restore    = osm_gps_map_osd_restore,  
     .draw       = osm_gps_map_osd_draw_controls,  
     .check      = osm_gps_map_osd_check,  
     .render     = osm_gps_map_osd_render,  
     .enable_gps = osm_gps_map_osd_enable_gps,  
     .free       = osm_gps_map_osd_free,  
     .priv       = NULL;  
 }  
   
 /* this is the only function that's externally visible */  
 osm_gps_map_osd_t *  
 osm_gps_map_osd_classic_init(void)  
 {  
     return osd_classic;  
 }  
   
 static void  
 osm_gps_map_osd_free(gpointer priv_ptr)  
 {  
     osd_priv_t *priv = (osd_priv_t *)priv_ptr;  
   
   
     g_free(priv);  
 }  
   
49  /* position and extent of bounding box */  /* position and extent of bounding box */
50  #define OSD_X      (10)  #define OSD_X      (10)
51  #define OSD_Y      (10)  #define OSD_Y      (10)
52    
 #define OSD_COLOR            0.5, 0.5, 1  
 #define OSD_COLOR_DISABLED   0.8, 0.8, 0.8  
   
53  /* parameters of the direction shape */  /* parameters of the direction shape */
54  #ifndef OSM_GPS_MAP_OSD_DIAMETER  #ifndef OSM_GPS_MAP_OSD_DIAMETER
55  #define D_RAD  (30)         // diameter of dpad  #define D_RAD  (30)         // diameter of dpad
# Line 102  osm_gps_map_osd_free(gpointer priv_ptr) Line 64  osm_gps_map_osd_free(gpointer priv_ptr)
64  #define Z_STEP   (D_RAD/4)  // distance between dpad and zoom  #define Z_STEP   (D_RAD/4)  // distance between dpad and zoom
65  #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar  #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar
66    
67    #ifdef OSD_SHADOW_ENABLE
68  /* shadow also depends on control size */  /* shadow also depends on control size */
69  #define OSD_SHADOW (D_RAD/6)  #define OSD_SHADOW (D_RAD/6)
70    #else
71    #define OSD_SHADOW (0)
72    #endif
73    
74  /* total width and height of controls incl. shadow */  /* total width and height of controls incl. shadow */
75  #define OSD_W    (2*D_RAD + OSD_SHADOW)  #define OSD_W    (2*D_RAD + OSD_SHADOW)
76  #define OSD_H    (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)  #define OSD_H    (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)
77    
78    #ifdef OSD_SHADOW_ENABLE
79  #define OSD_LBL_SHADOW (OSD_SHADOW/2)  #define OSD_LBL_SHADOW (OSD_SHADOW/2)
80    #endif
81    
82  #define Z_TOP    (2 * D_RAD + Z_STEP)  #define Z_TOP    (2 * D_RAD + Z_STEP)
83  #define Z_MID    (Z_TOP + Z_RAD)  #define Z_MID    (Z_TOP + Z_RAD)
# Line 216  osm_gps_map_osd_check(gint x, gint y) { Line 184  osm_gps_map_osd_check(gint x, gint y) {
184      return but;      return but;
185  }  }
186    
187    #ifdef OSD_SHADOW_ENABLE
188  static void  static void
189  osm_gps_map_osd_shape_shadow(cairo_t *cr) {  osm_gps_map_osd_shape_shadow(cairo_t *cr) {
190      cairo_set_source_rgba (cr, 0, 0, 0, 0.2);      cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
191      cairo_fill (cr);      cairo_fill (cr);
192      cairo_stroke (cr);      cairo_stroke (cr);
193  }  }
194    #endif
195    
196    #ifndef OSD_COLOR
197    /* if no color has been specified we just use the gdks default colors */
198    static void
199    osm_gps_map_osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {
200        gdk_cairo_set_source_color(cr, bg);
201        cairo_fill_preserve (cr);
202        gdk_cairo_set_source_color(cr, fg);
203        cairo_set_line_width (cr, 1);
204        cairo_stroke (cr);
205    }
206    #else
207  static void  static void
208  osm_gps_map_osd_shape(cairo_t *cr) {  osm_gps_map_osd_shape(cairo_t *cr) {
209      cairo_set_source_rgb (cr, 1, 1, 1);      cairo_set_source_rgb (cr, OSD_COLOR_BG);
210      cairo_fill_preserve (cr);      cairo_fill_preserve (cr);
211      cairo_set_source_rgb (cr, OSD_COLOR);      cairo_set_source_rgb (cr, OSD_COLOR);
212      cairo_set_line_width (cr, 1);      cairo_set_line_width (cr, 1);
213      cairo_stroke (cr);      cairo_stroke (cr);
214  }  }
215    #endif
216    
217  static void  static void
218  osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {  osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {
# Line 296  osm_gps_map_osd_zoom_labels(cairo_t *cr, Line 278  osm_gps_map_osd_zoom_labels(cairo_t *cr,
278      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
279  }  }
280    
281    #ifndef OSD_COLOR
282    /* if no color has been specified we just use the gdks default colors */
283    static void
284    osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled,
285                           GdkColor *fg, GdkColor *disabled) {
286        if(enabled)  gdk_cairo_set_source_color(cr, fg);
287        else         gdk_cairo_set_source_color(cr, disabled);
288        cairo_set_line_width (cr, width);
289        cairo_stroke (cr);
290    }
291    #else
292  static void  static void
293  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {
294      if(enabled)  cairo_set_source_rgb (cr, OSD_COLOR);      if(enabled)  cairo_set_source_rgb (cr, OSD_COLOR);
# Line 303  osm_gps_map_osd_labels(cairo_t *cr, gint Line 296  osm_gps_map_osd_labels(cairo_t *cr, gint
296      cairo_set_line_width (cr, width);      cairo_set_line_width (cr, width);
297      cairo_stroke (cr);      cairo_stroke (cr);
298  }  }
299    #endif
300    
301    #ifdef OSD_SHADOW_ENABLE
302  static void  static void
303  osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {  osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {
304      cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);      cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);
305      cairo_set_line_width (cr, width);      cairo_set_line_width (cr, width);
306      cairo_stroke (cr);      cairo_stroke (cr);
307  }  }
308    #endif
309    
310  static void  static void
311  osm_gps_map_osd_render(OsmGpsMapPrivate *priv) {  osm_gps_map_osd_render(osm_gps_map_osd_t *osd) {
312        osd_priv_t *priv = (osd_priv_t*)osd->priv;
313    
314      /* first fill with transparency */      /* first fill with transparency */
315      cairo_t *cr = cairo_create(priv->osd.overlay);      cairo_t *cr = cairo_create(priv->overlay);
316      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
317      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);
318      cairo_paint(cr);      cairo_paint(cr);
# Line 325  osm_gps_map_osd_render(OsmGpsMapPrivate Line 322  osm_gps_map_osd_render(OsmGpsMapPrivate
322      /* --------- draw zoom and dpad shape shadow ----------- */      /* --------- draw zoom and dpad shape shadow ----------- */
323      gint x = 0, y = 0;      gint x = 0, y = 0;
324    
325    #ifdef OSD_SHADOW_ENABLE
326      osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);      osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
327      osm_gps_map_osd_shape_shadow(cr);      osm_gps_map_osd_shape_shadow(cr);
328      osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);      osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
329      osm_gps_map_osd_shape_shadow(cr);      osm_gps_map_osd_shape_shadow(cr);
330    #endif
331    
332      /* --------- draw zoom and dpad shape ----------- */      /* --------- draw zoom and dpad shape ----------- */
333    
334      osm_gps_map_osd_zoom_shape(cr, x, y);      osm_gps_map_osd_zoom_shape(cr, x, y);
335    #ifndef OSD_COLOR
336        osm_gps_map_osd_shape(cr, &priv->bg, &priv->fg);
337    #else
338      osm_gps_map_osd_shape(cr);      osm_gps_map_osd_shape(cr);
339    #endif
340      osm_gps_map_osd_dpad_shape(cr, x, y);      osm_gps_map_osd_dpad_shape(cr, x, y);
341    #ifndef OSD_COLOR
342        osm_gps_map_osd_shape(cr, &priv->bg, &priv->fg);
343    #else
344      osm_gps_map_osd_shape(cr);      osm_gps_map_osd_shape(cr);
345    #endif
346    
347      /* --------- draw zoom and dpad labels --------- */      /* --------- draw zoom and dpad labels --------- */
348    
349    #ifdef OSD_SHADOW_ENABLE
350      osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
351      osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
352      osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);      osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);
353      osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);      osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
354      osm_gps_map_osd_labels_shadow(cr, Z_RAD/6, priv->osd.cb != NULL);      osm_gps_map_osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL);
355    #endif
356    
357      osm_gps_map_osd_zoom_labels(cr, x, y);      osm_gps_map_osd_zoom_labels(cr, x, y);
358      osm_gps_map_osd_dpad_labels(cr, x, y);      osm_gps_map_osd_dpad_labels(cr, x, y);
359    #ifndef OSD_COLOR
360        osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE, &priv->fg, &priv->da);
361    #else
362      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);
363    #endif
364      osm_gps_map_osd_dpad_gps(cr, x, y);      osm_gps_map_osd_dpad_gps(cr, x, y);
365      osm_gps_map_osd_labels(cr, Z_RAD/6, priv->osd.cb != NULL);  #ifndef OSD_COLOR
366        osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL, &priv->fg, &priv->da);
367    #else
368        osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL);
369    #endif
370    
371      cairo_destroy(cr);      cairo_destroy(cr);
372  }  }
373    
374  static void  static void
375  osm_gps_map_osd_draw_controls (OsmGpsMap *map, gint xoffset, gint yoffset)  osm_gps_map_osd_draw(osm_gps_map_osd_t *osd, gint xoffset, gint yoffset)
376  {  {
377      OsmGpsMapPrivate *priv = map->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
378    
379      /* backup previous contents */      /* backup previous contents */
380      if(!priv->osd.backup)      if(!priv->backup)
381          priv->osd.backup = gdk_pixmap_new(priv->pixmap, OSD_W+2, OSD_H+2, -1);          priv->backup = gdk_pixmap_new(osd->pixmap, OSD_W+2, OSD_H+2, -1);
382    
383      gint x = OSD_X + EXTRA_BORDER + xoffset;      gint x = OSD_X + xoffset;
384      gint y = OSD_Y + EXTRA_BORDER + yoffset;      gint y = OSD_Y + yoffset;
385    
386      /* create backup of background */      /* create backup of background */
387      gdk_draw_drawable(priv->osd.backup,      gdk_draw_drawable(priv->backup,
388          GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],          osd->widget->style->fg_gc[GTK_WIDGET_STATE(osd->widget)],
389                        priv->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);                        osd->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);
390    
391      priv->osd.backup_x = x-1;      priv->backup_x = x-1;
392      priv->osd.backup_y = y-1;      priv->backup_y = y-1;
393    
394      /* OSD itself uses some off-screen rendering, so check if the */      /* OSD itself uses some off-screen rendering, so check if the */
395      /* offscreen buffer is present and create it if not */      /* offscreen buffer is present and create it if not */
396      if(!priv->osd.overlay) {      if(!priv->overlay) {
397          /* create overlay ... */          /* create overlay ... */
398          priv->osd.overlay =          priv->overlay =
399              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);
400          /* ... and render it */          /* ... and render it */
401          osm_gps_map_osd_render(priv);          osm_gps_map_osd_render(osd);
402      }      }
403    
404      // now draw this onto the original context      // now draw this onto the original context
405      cairo_t *cr = gdk_cairo_create(priv->pixmap);      cairo_t *cr = gdk_cairo_create(osd->pixmap);
406      cairo_set_source_surface(cr, priv->osd.overlay, x, y);      cairo_set_source_surface(cr, priv->overlay, x, y);
407      cairo_paint(cr);      cairo_paint(cr);
408      cairo_destroy(cr);      cairo_destroy(cr);
409  }  }
410    
411  static void  static void
412  osm_gps_map_osd_restore (OsmGpsMap *map)  osm_gps_map_osd_restore (osm_gps_map_osd_t *osd)
413  {  {
414      OsmGpsMapPrivate *priv = map->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
415    
416      /* restore backup of previous contents */      /* restore backup of previous contents */
417      if(priv->osd.backup) {      if(priv->backup) {
418          /* create backup of background */          /* create backup of background */
419          gdk_draw_drawable(priv->pixmap,          gdk_draw_drawable(osd->pixmap,
420              GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],                            osd->widget->style->fg_gc[GTK_WIDGET_STATE(osd->widget)],
421                        priv->osd.backup, 0, 0,                            priv->backup, 0, 0,
422                        priv->osd.backup_x, priv->osd.backup_y, OSD_W+2, OSD_H+2);                            priv->backup_x, priv->backup_y, OSD_W+2, OSD_H+2);
423      }      }
424  }  }
425    
426  static void  static void
427  osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data)  osm_gps_map_osd_free(osm_gps_map_osd_t *osd)
428  {  {
429      OsmGpsMapPrivate *priv;      osd_priv_t *priv = (osd_priv_t *)(osd->priv);
430    
431        if (priv->backup)
432            g_object_unref(priv->backup);
433    
434        if (priv->overlay)
435             cairo_surface_destroy(priv->overlay);
436    
437        g_free(priv);
438    }
439    
440    static osm_gps_map_osd_t osd_classic = {
441        .restore    = osm_gps_map_osd_restore,
442        .draw       = osm_gps_map_osd_draw,
443        .check      = osm_gps_map_osd_check,
444        .render     = osm_gps_map_osd_render,
445        .free       = osm_gps_map_osd_free,
446    
447        .cb         = NULL,
448        .data       = NULL,
449    
450        .priv       = NULL
451    };
452    
453    /* this is the only function that's externally visible */
454    void
455    osm_gps_map_osd_classic_init(OsmGpsMap *map)
456    {
457        osd_priv_t *priv = osd_classic.priv = g_new0(osd_priv_t, 1);
458    
459        osd_classic.priv = priv;
460    
461        /* extract style info from the widget */
462        priv->bg = GTK_WIDGET(map)->style->bg[GTK_STATE_NORMAL];
463        priv->fg = GTK_WIDGET(map)->style->fg[GTK_STATE_NORMAL];
464        priv->da = GTK_WIDGET(map)->style->fg[GTK_STATE_INSENSITIVE];
465    
466        osm_gps_map_register_osd(map, &osd_classic);
467    }
468    
469    
470    /* below are osd specific functions which aren't used by osm-gps-map */
471    /* but instead are to be used by the main application */
472    void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb, gpointer data) {
473        osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
474    
475      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (osd);
     priv = map->priv;  
476    
477      priv->osd.cb = cb;      osd->cb = cb;
478      priv->osd.data = data;      osd->data = data;
479    
480      /* this may have changed the state of the gps button */      /* this may have changed the state of the gps button */
481      /* we thus re-render the overlay */      /* we thus re-render the overlay */
482      osm_gps_map_osd_render(priv);      osd->render(osd);
483    
484      osm_gps_map_map_redraw_idle(map);      osm_gps_map_redraw(map);
485  }  }

Legend:
Removed from v.71  
changed lines
  Added in v.74