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 75 by harbaum, Mon Aug 24 12:57:15 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      GdkPixmap *backup;      /* the offscreen representation of the OSD */
     gint backup_x, backup_y;  
   
39      cairo_surface_t *overlay;      cairo_surface_t *overlay;
40    
41      OsmGpsMapOsdGpsCallback cb;      GdkColor bg, fg, da;
     gpointer data;  
 } osd_priv_t;  
   
 /* 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;  
   
42    
43      g_free(priv);  } osd_priv_t;
 }  
44    
45  /* position and extent of bounding box */  /* position and extent of bounding box */
46  #define OSD_X      (10)  #define OSD_X      (10)
47  #define OSD_Y      (10)  #define OSD_Y      (10)
48    
 #define OSD_COLOR            0.5, 0.5, 1  
 #define OSD_COLOR_DISABLED   0.8, 0.8, 0.8  
   
49  /* parameters of the direction shape */  /* parameters of the direction shape */
50  #ifndef OSM_GPS_MAP_OSD_DIAMETER  #ifndef OSM_GPS_MAP_OSD_DIAMETER
51  #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 60  osm_gps_map_osd_free(gpointer priv_ptr)
60  #define Z_STEP   (D_RAD/4)  // distance between dpad and zoom  #define Z_STEP   (D_RAD/4)  // distance between dpad and zoom
61  #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar  #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar
62    
63    #ifdef OSD_SHADOW_ENABLE
64  /* shadow also depends on control size */  /* shadow also depends on control size */
65  #define OSD_SHADOW (D_RAD/6)  #define OSD_SHADOW (D_RAD/6)
66    #else
67    #define OSD_SHADOW (0)
68    #endif
69    
70  /* total width and height of controls incl. shadow */  /* total width and height of controls incl. shadow */
71  #define OSD_W    (2*D_RAD + OSD_SHADOW)  #define OSD_W    (2*D_RAD + OSD_SHADOW)
72  #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)
73    
74    #ifdef OSD_SHADOW_ENABLE
75  #define OSD_LBL_SHADOW (OSD_SHADOW/2)  #define OSD_LBL_SHADOW (OSD_SHADOW/2)
76    #endif
77    
78  #define Z_TOP    (2 * D_RAD + Z_STEP)  #define Z_TOP    (2 * D_RAD + Z_STEP)
79  #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 180  osm_gps_map_osd_check(gint x, gint y) {
180      return but;      return but;
181  }  }
182    
183    #ifdef OSD_SHADOW_ENABLE
184  static void  static void
185  osm_gps_map_osd_shape_shadow(cairo_t *cr) {  osm_gps_map_osd_shape_shadow(cairo_t *cr) {
186      cairo_set_source_rgba (cr, 0, 0, 0, 0.2);      cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
187      cairo_fill (cr);      cairo_fill (cr);
188      cairo_stroke (cr);      cairo_stroke (cr);
189  }  }
190    #endif
191    
192    #ifndef OSD_COLOR
193    /* if no color has been specified we just use the gdks default colors */
194    static void
195    osm_gps_map_osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {
196        gdk_cairo_set_source_color(cr, bg);
197        cairo_fill_preserve (cr);
198        gdk_cairo_set_source_color(cr, fg);
199        cairo_set_line_width (cr, 1);
200        cairo_stroke (cr);
201    }
202    #else
203  static void  static void
204  osm_gps_map_osd_shape(cairo_t *cr) {  osm_gps_map_osd_shape(cairo_t *cr) {
205      cairo_set_source_rgb (cr, 1, 1, 1);      cairo_set_source_rgb (cr, OSD_COLOR_BG);
206      cairo_fill_preserve (cr);      cairo_fill_preserve (cr);
207      cairo_set_source_rgb (cr, OSD_COLOR);      cairo_set_source_rgb (cr, OSD_COLOR);
208      cairo_set_line_width (cr, 1);      cairo_set_line_width (cr, 1);
209      cairo_stroke (cr);      cairo_stroke (cr);
210  }  }
211    #endif
212    
213  static void  static void
214  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 274  osm_gps_map_osd_zoom_labels(cairo_t *cr,
274      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
275  }  }
276    
277    #ifndef OSD_COLOR
278    /* if no color has been specified we just use the gdks default colors */
279    static void
280    osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled,
281                           GdkColor *fg, GdkColor *disabled) {
282        if(enabled)  gdk_cairo_set_source_color(cr, fg);
283        else         gdk_cairo_set_source_color(cr, disabled);
284        cairo_set_line_width (cr, width);
285        cairo_stroke (cr);
286    }
287    #else
288  static void  static void
289  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {  osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {
290      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 292  osm_gps_map_osd_labels(cairo_t *cr, gint
292      cairo_set_line_width (cr, width);      cairo_set_line_width (cr, width);
293      cairo_stroke (cr);      cairo_stroke (cr);
294  }  }
295    #endif
296    
297    #ifdef OSD_SHADOW_ENABLE
298  static void  static void
299  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) {
300      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);
301      cairo_set_line_width (cr, width);      cairo_set_line_width (cr, width);
302      cairo_stroke (cr);      cairo_stroke (cr);
303  }  }
304    #endif
305    
306  static void  static void
307  osm_gps_map_osd_render(OsmGpsMapPrivate *priv) {  osm_gps_map_osd_render(osm_gps_map_osd_t *osd) {
308        osd_priv_t *priv = (osd_priv_t*)osd->priv;
309    
310      /* first fill with transparency */      /* first fill with transparency */
311      cairo_t *cr = cairo_create(priv->osd.overlay);      cairo_t *cr = cairo_create(priv->overlay);
312      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
313      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);
314      cairo_paint(cr);      cairo_paint(cr);
# Line 325  osm_gps_map_osd_render(OsmGpsMapPrivate Line 318  osm_gps_map_osd_render(OsmGpsMapPrivate
318      /* --------- draw zoom and dpad shape shadow ----------- */      /* --------- draw zoom and dpad shape shadow ----------- */
319      gint x = 0, y = 0;      gint x = 0, y = 0;
320    
321    #ifdef OSD_SHADOW_ENABLE
322      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);
323      osm_gps_map_osd_shape_shadow(cr);      osm_gps_map_osd_shape_shadow(cr);
324      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);
325      osm_gps_map_osd_shape_shadow(cr);      osm_gps_map_osd_shape_shadow(cr);
326    #endif
327    
328      /* --------- draw zoom and dpad shape ----------- */      /* --------- draw zoom and dpad shape ----------- */
329    
330      osm_gps_map_osd_zoom_shape(cr, x, y);      osm_gps_map_osd_zoom_shape(cr, x, y);
331    #ifndef OSD_COLOR
332        osm_gps_map_osd_shape(cr, &priv->bg, &priv->fg);
333    #else
334      osm_gps_map_osd_shape(cr);      osm_gps_map_osd_shape(cr);
335    #endif
336      osm_gps_map_osd_dpad_shape(cr, x, y);      osm_gps_map_osd_dpad_shape(cr, x, y);
337    #ifndef OSD_COLOR
338        osm_gps_map_osd_shape(cr, &priv->bg, &priv->fg);
339    #else
340      osm_gps_map_osd_shape(cr);      osm_gps_map_osd_shape(cr);
341    #endif
342    
343      /* --------- draw zoom and dpad labels --------- */      /* --------- draw zoom and dpad labels --------- */
344    
345    #ifdef OSD_SHADOW_ENABLE
346      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);
347      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);
348      osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);      osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);
349      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);
350      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);
351    #endif
352    
353      osm_gps_map_osd_zoom_labels(cr, x, y);      osm_gps_map_osd_zoom_labels(cr, x, y);
354      osm_gps_map_osd_dpad_labels(cr, x, y);      osm_gps_map_osd_dpad_labels(cr, x, y);
355    #ifndef OSD_COLOR
356        osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE, &priv->fg, &priv->da);
357    #else
358      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);      osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);
359    #endif
360      osm_gps_map_osd_dpad_gps(cr, x, y);      osm_gps_map_osd_dpad_gps(cr, x, y);
361      osm_gps_map_osd_labels(cr, Z_RAD/6, priv->osd.cb != NULL);  #ifndef OSD_COLOR
362        osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL, &priv->fg, &priv->da);
363    #else
364        osm_gps_map_osd_labels(cr, Z_RAD/6, osd->cb != NULL);
365    #endif
366    
367      cairo_destroy(cr);      cairo_destroy(cr);
368  }  }
369    
370  static void  static void
371  osm_gps_map_osd_draw_controls (OsmGpsMap *map, gint xoffset, gint yoffset)  osm_gps_map_osd_draw(osm_gps_map_osd_t *osd, GdkDrawable *drawable)
372  {  {
373      OsmGpsMapPrivate *priv = map->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
   
     /* backup previous contents */  
     if(!priv->osd.backup)  
         priv->osd.backup = gdk_pixmap_new(priv->pixmap, OSD_W+2, OSD_H+2, -1);  
   
     gint x = OSD_X + EXTRA_BORDER + xoffset;  
     gint y = OSD_Y + EXTRA_BORDER + yoffset;  
   
     /* create backup of background */  
     gdk_draw_drawable(priv->osd.backup,  
         GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],  
                       priv->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);  
   
     priv->osd.backup_x = x-1;  
     priv->osd.backup_y = y-1;  
374    
375      /* OSD itself uses some off-screen rendering, so check if the */      /* OSD itself uses some off-screen rendering, so check if the */
376      /* offscreen buffer is present and create it if not */      /* offscreen buffer is present and create it if not */
377      if(!priv->osd.overlay) {      if(!priv->overlay) {
378          /* create overlay ... */          /* create overlay ... */
379          priv->osd.overlay =          priv->overlay =
380              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);
381          /* ... and render it */          /* ... and render it */
382          osm_gps_map_osd_render(priv);          osm_gps_map_osd_render(osd);
383      }      }
384    
385      // now draw this onto the original context      // now draw this onto the original context
386      cairo_t *cr = gdk_cairo_create(priv->pixmap);      cairo_t *cr = gdk_cairo_create(drawable);
387      cairo_set_source_surface(cr, priv->osd.overlay, x, y);      cairo_set_source_surface(cr, priv->overlay, OSD_X, OSD_Y);
388      cairo_paint(cr);      cairo_paint(cr);
389      cairo_destroy(cr);      cairo_destroy(cr);
390  }  }
391    
392  static void  static void
393  osm_gps_map_osd_restore (OsmGpsMap *map)  osm_gps_map_osd_free(osm_gps_map_osd_t *osd)
394  {  {
395      OsmGpsMapPrivate *priv = map->priv;      osd_priv_t *priv = (osd_priv_t *)(osd->priv);
396    
397      /* restore backup of previous contents */      if (priv->overlay)
398      if(priv->osd.backup) {           cairo_surface_destroy(priv->overlay);
399          /* create backup of background */  
400          gdk_draw_drawable(priv->pixmap,      g_free(priv);
             GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],  
                       priv->osd.backup, 0, 0,  
                       priv->osd.backup_x, priv->osd.backup_y, OSD_W+2, OSD_H+2);  
     }  
401  }  }
402    
403  static void  static osm_gps_map_osd_t osd_classic = {
404  osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data)      .draw       = osm_gps_map_osd_draw,
405        .check      = osm_gps_map_osd_check,
406        .render     = osm_gps_map_osd_render,
407        .free       = osm_gps_map_osd_free,
408    
409        .cb         = NULL,
410        .data       = NULL,
411    
412        .priv       = NULL
413    };
414    
415    /* this is the only function that's externally visible */
416    void
417    osm_gps_map_osd_classic_init(OsmGpsMap *map)
418  {  {
419      OsmGpsMapPrivate *priv;      osd_priv_t *priv = osd_classic.priv = g_new0(osd_priv_t, 1);
420    
421        osd_classic.priv = priv;
422    
423        /* extract style info from the widget */
424        priv->bg = GTK_WIDGET(map)->style->bg[GTK_STATE_NORMAL];
425        priv->fg = GTK_WIDGET(map)->style->fg[GTK_STATE_NORMAL];
426        priv->da = GTK_WIDGET(map)->style->fg[GTK_STATE_INSENSITIVE];
427    
428        osm_gps_map_register_osd(map, &osd_classic);
429    }
430    
431    
432    /* below are osd specific functions which aren't used by osm-gps-map */
433    /* but instead are to be used by the main application */
434    void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb, gpointer data) {
435        osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
436    
437      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (osd);
     priv = map->priv;  
438    
439      priv->osd.cb = cb;      osd->cb = cb;
440      priv->osd.data = data;      osd->data = data;
441    
442      /* this may have changed the state of the gps button */      /* this may have changed the state of the gps button */
443      /* we thus re-render the overlay */      /* we thus re-render the overlay */
444      osm_gps_map_osd_render(priv);      osd->render(osd);
445    
446      osm_gps_map_map_redraw_idle(map);      osm_gps_map_redraw(map);
447  }  }

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