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

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

revision 87 by harbaum, Mon Aug 31 12:01:28 2009 UTC revision 108 by harbaum, Fri Sep 11 19:20:55 2009 UTC
# Line 37  Line 37 
37  //the osd controls  //the osd controls
38  typedef struct {  typedef struct {
39      /* the offscreen representation of the OSD */      /* the offscreen representation of the OSD */
40      cairo_surface_t *overlay;      struct {
41            cairo_surface_t *surface;
42            gboolean rendered;
43    #ifdef OSD_GPS_BUTTON
44            gboolean gps_enabled;
45    #endif
46        } controls;
47    
48    #ifdef OSD_SCALE
49        cairo_surface_t *scale;
50        int scale_zoom;
51    #endif
52    
53    #ifdef OSD_CROSSHAIR
54        cairo_surface_t *crosshair;
55    #endif
56    
57    #ifdef OSD_COORDINATES
58        cairo_surface_t *coordinates;
59        float coo_lat, coo_lon;
60    #endif
61    
62    #ifdef OSD_SOURCE_SEL
63      /* values to handle the "source" menu */      /* values to handle the "source" menu */
64      cairo_surface_t *map_source;      cairo_surface_t *map_source;
65      gboolean expanded;      gboolean expanded;
66      gint shift, dir, count;      gint shift, dir, count;
67      gint handler_id;      gint handler_id;
68      gint width, height;      gint width, height;
69    #endif
70    
71  } osd_priv_t;  } osd_priv_t;
72    
# Line 258  osd_check_zoom(gint x, gint y) { Line 280  osd_check_zoom(gint x, gint y) {
280      return OSD_NONE;      return OSD_NONE;
281  }  }
282    
283    #ifdef OSD_SOURCE_SEL
284    
285  /* place source selection at right border */  /* place source selection at right border */
286  #define OSD_S_RAD (Z_RAD)  #define OSD_S_RAD (Z_RAD)
287  #define OSD_S_X   (-OSD_X)  #define OSD_S_X   (-OSD_X)
# Line 281  osd_check_zoom(gint x, gint y) { Line 305  osd_check_zoom(gint x, gint y) {
305  #define OSD_TEXT_BORDER   (OSD_FONT_SIZE/2)  #define OSD_TEXT_BORDER   (OSD_FONT_SIZE/2)
306  #define OSD_TEXT_SKIP     (OSD_FONT_SIZE/8)  #define OSD_TEXT_SKIP     (OSD_FONT_SIZE/8)
307    
308    /* draw the shape of the source selection OSD, either only the puller (not expanded) */
309    /* or the entire menu incl. the puller (expanded) */
310  static void  static void
311  osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) {  osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) {
312      if(!priv->expanded) {      if(!priv->expanded) {
# Line 336  osd_source_content(osm_gps_map_osd_t *os Line 362  osd_source_content(osm_gps_map_osd_t *os
362                                      CAIRO_FONT_WEIGHT_BOLD);                                      CAIRO_FONT_WEIGHT_BOLD);
363              cairo_set_font_size (cr, OSD_FONT_SIZE);              cairo_set_font_size (cr, OSD_FONT_SIZE);
364    
365              int i, step = (priv->height - 2*OSD_TEXT_BORDER)              int i, step = (priv->height - 2*OSD_TEXT_BORDER) /
366                  / OSM_GPS_MAP_SOURCE_LAST;                  OSM_GPS_MAP_SOURCE_LAST;
367              for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {              for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
368                  cairo_text_extents_t extents;                  cairo_text_extents_t extents;
369                  const char *src = osm_gps_map_source_get_friendly_name(i);                  const char *src = osm_gps_map_source_get_friendly_name(i);
# Line 425  osd_render_source_sel(osm_gps_map_osd_t Line 451  osd_render_source_sel(osm_gps_map_osd_t
451      cairo_destroy(cr);      cairo_destroy(cr);
452  }  }
453    
454    /* re-allocate the buffer used to draw the menu. This is used */
455    /* to collapse/expand the buffer */
456  static void  static void
457  osd_source_reallocate(osm_gps_map_osd_t *osd) {  osd_source_reallocate(osm_gps_map_osd_t *osd) {
458      osd_priv_t *priv = (osd_priv_t*)osd->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
# Line 434  osd_source_reallocate(osm_gps_map_osd_t Line 462  osd_source_reallocate(osm_gps_map_osd_t
462    
463      int w = OSD_S_W, h = OSD_S_H;      int w = OSD_S_W, h = OSD_S_H;
464      if(priv->expanded) {      if(priv->expanded) {
         /* ... and right of it the waypoint id */  
465          cairo_text_extents_t extents;          cairo_text_extents_t extents;
466    
467          /* determine content size */          /* determine content size */
# Line 450  osd_source_reallocate(osm_gps_map_osd_t Line 477  osd_source_reallocate(osm_gps_map_osd_t
477              const char *src = osm_gps_map_source_get_friendly_name(i);              const char *src = osm_gps_map_source_get_friendly_name(i);
478              cairo_text_extents (cr, src, &extents);              cairo_text_extents (cr, src, &extents);
479    
             //            printf("Source %d: %s = %f %f\n", i, src,  
             //                   extents.width, extents.height);  
   
480              if(extents.width > max_w) max_w = extents.width;              if(extents.width > max_w) max_w = extents.width;
481              if(extents.height > max_h) max_h = extents.height;              if(extents.height > max_h) max_h = extents.height;
482          }          }
# Line 471  osd_source_reallocate(osm_gps_map_osd_t Line 495  osd_source_reallocate(osm_gps_map_osd_t
495          cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2);          cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2);
496    
497      osd_render_source_sel(osd);      osd_render_source_sel(osd);
   
498  }  }
499    
500  #define OSD_HZ      15  #define OSD_HZ      15
# Line 503  static gboolean osd_source_animate(gpoin Line 526  static gboolean osd_source_animate(gpoin
526    
527      /* count runs linearly from 0 to 1000, map this nicely onto a position */      /* count runs linearly from 0 to 1000, map this nicely onto a position */
528    
     /* simple linear mapping */  
     //    priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +  
     //        (diff * priv->count)/1000;  
   
529      /* nicer sinoid mapping */      /* nicer sinoid mapping */
530      float m = 0.5-cos(priv->count * M_PI / 1000.0)/2;      float m = 0.5-cos(priv->count * M_PI / 1000.0)/2;
531      priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +      priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +
# Line 547  osd_source_toggle(osm_gps_map_osd_t *osd Line 566  osd_source_toggle(osm_gps_map_osd_t *osd
566      priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd);      priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd);
567  }  }
568    
569    /* check if the user clicked inside the source selection area */
570  static osd_button_t  static osd_button_t
571  osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) {  osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) {
572      osd_priv_t *priv = (osd_priv_t*)osd->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
# Line 573  osd_source_check(osm_gps_map_osd_t *osd, Line 593  osd_source_check(osm_gps_map_osd_t *osd,
593              return OSD_BG;              return OSD_BG;
594          }          }
595      }      }
596    
597        /* check for clicks into data area */
598        if(priv->expanded && !priv->handler_id) {
599            /* re-adjust from puller top to content top */
600            if(OSD_S_Y < 0)
601                y += OSD_S_EXP_H - OSD_S_PH;
602    
603            if(x > OSD_S_PW &&
604               x < OSD_S_PW + OSD_S_EXP_W &&
605               y > 0 &&
606               y < OSD_S_EXP_H) {
607    
608                int step = (priv->height - 2*OSD_TEXT_BORDER)
609                    / OSM_GPS_MAP_SOURCE_LAST;
610    
611                y -= OSD_TEXT_BORDER - OSD_TEXT_SKIP;
612                y /= step;
613                y += 1;
614    
615                gint old = 0;
616                g_object_get(osd->widget, "map-source", &old, NULL);
617    
618                if(y > OSM_GPS_MAP_SOURCE_NULL &&
619                   y <= OSM_GPS_MAP_SOURCE_LAST &&
620                   old != y) {
621                    g_object_set(osd->widget, "map-source", y, NULL);
622    
623                    osd_render_source_sel(osd);
624                    osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
625                }
626    
627                /* return "clicked in OSD background" to prevent further */
628                /* processing by application */
629                return OSD_BG;
630            }
631        }
632    
633      return OSD_NONE;      return OSD_NONE;
634  }  }
635    #endif // OSD_SOURCE_SEL
636    
637  static osd_button_t  static osd_button_t
638  osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {  osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {
# Line 680  osd_zoom_labels(cairo_t *cr, gint x, gin Line 738  osd_zoom_labels(cairo_t *cr, gint x, gin
738      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);      cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
739  }  }
740    
741    #ifdef OSD_COORDINATES
742    
743    #ifndef OSD_COORDINATES_FONT_SIZE
744    #define OSD_COORDINATES_FONT_SIZE 12
745    #endif
746    
747    #define OSD_COORDINATES_OFFSET (OSD_COORDINATES_FONT_SIZE/6)
748    
749    #define OSD_COORDINATES_W  (8*OSD_COORDINATES_FONT_SIZE+2*OSD_COORDINATES_OFFSET)
750    #define OSD_COORDINATES_H  (2*OSD_COORDINATES_FONT_SIZE+OSD_COORDINATES_OFFSET)
751    
752    /* these can be overwritten with versions that support */
753    /* localization */
754    #ifndef OSD_COORDINATES_CHR_N
755    #define OSD_COORDINATES_CHR_N  "N"
756    #endif
757    #ifndef OSD_COORDINATES_CHR_S
758    #define OSD_COORDINATES_CHR_S  "S"
759    #endif
760    #ifndef OSD_COORDINATES_CHR_E
761    #define OSD_COORDINATES_CHR_E  "E"
762    #endif
763    #ifndef OSD_COORDINATES_CHR_W
764    #define OSD_COORDINATES_CHR_W  "W"
765    #endif
766    
767    
768    
769    /* this is the classic geocaching notation */
770    static char
771    *osd_latitude_str(float latitude) {
772        char *c = OSD_COORDINATES_CHR_N;
773        float integral, fractional;
774    
775        if(isnan(latitude))
776            return NULL;
777    
778        if(latitude < 0) {
779            latitude = fabs(latitude);
780            c = OSD_COORDINATES_CHR_S;
781        }
782    
783        fractional = modff(latitude, &integral);
784    
785        return g_strdup_printf("%s %02d° %06.3f'",
786                               c, (int)integral, fractional*60.0);
787    }
788    
789    static char
790    *osd_longitude_str(float longitude) {
791        char *c = OSD_COORDINATES_CHR_E;
792        float integral, fractional;
793    
794        if(isnan(longitude))
795            return NULL;
796    
797        if(longitude < 0) {
798            longitude = fabs(longitude);
799            c = OSD_COORDINATES_CHR_W;
800        }
801    
802        fractional = modff(longitude, &integral);
803    
804        return g_strdup_printf("%s %03d° %06.3f'",
805                               c, (int)integral, fractional*60.0);
806    }
807    
808    static void
809    osd_render_coordinates(osm_gps_map_osd_t *osd)
810    {
811        osd_priv_t *priv = (osd_priv_t*)osd->priv;
812    
813        /* get current map position */
814        gfloat lat, lon;
815        g_object_get(osd->widget, "latitude", &lat, "longitude", &lon, NULL);
816    
817        /* check if position has changed enough to require redraw */
818        if(!isnan(priv->coo_lat) && !isnan(priv->coo_lon))
819            if((fabsf(lat - priv->coo_lat) < 1/60000) &&     /* 1/60000 == 1/1000 minute */
820               (fabsf(lon - priv->coo_lon) < 1/60000))
821                return;
822    
823        priv->coo_lat = lat;
824        priv->coo_lon = lon;
825    
826        /* first fill with light transparency */
827        cairo_t *cr = cairo_create(priv->coordinates);
828        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
829        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.5);
830        cairo_paint(cr);
831        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
832    
833        cairo_select_font_face (cr, "Sans",
834                                CAIRO_FONT_SLANT_NORMAL,
835                                CAIRO_FONT_WEIGHT_BOLD);
836        cairo_set_font_size (cr, OSD_COORDINATES_FONT_SIZE);
837    
838        char *latitude = osd_latitude_str(lat);
839        char *longitude = osd_longitude_str(lon);
840    
841        cairo_text_extents_t lat_extents, lon_extents;
842        cairo_text_extents (cr, latitude, &lat_extents);
843        cairo_text_extents (cr, longitude, &lon_extents);
844    
845        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
846        cairo_set_line_width (cr, OSD_COORDINATES_FONT_SIZE/6);
847        cairo_move_to (cr,
848                       (OSD_COORDINATES_W - lat_extents.width)/2,
849                       OSD_COORDINATES_OFFSET - lat_extents.y_bearing);
850        cairo_text_path (cr, latitude);
851        cairo_move_to (cr,
852                       (OSD_COORDINATES_W - lon_extents.width)/2,
853                       OSD_COORDINATES_OFFSET - lon_extents.y_bearing +
854                       OSD_COORDINATES_FONT_SIZE);
855        cairo_text_path (cr, longitude);
856        cairo_stroke (cr);
857    
858        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
859        cairo_move_to (cr,
860                       (OSD_COORDINATES_W - lat_extents.width)/2,
861                       OSD_COORDINATES_OFFSET - lat_extents.y_bearing);
862        cairo_show_text (cr, latitude);
863        cairo_move_to (cr,
864                       (OSD_COORDINATES_W - lon_extents.width)/2,
865                       OSD_COORDINATES_OFFSET - lon_extents.y_bearing +
866                       OSD_COORDINATES_FONT_SIZE);
867        cairo_show_text (cr, longitude);
868    
869        g_free(latitude);
870        g_free(longitude);
871    
872        cairo_destroy(cr);
873    }
874    #endif  // OSD_COORDINATES
875    
876    #ifdef OSD_CROSSHAIR
877    
878    #ifndef OSD_CROSSHAIR_RADIUS
879    #define OSD_CROSSHAIR_RADIUS 10
880    #endif
881    
882    #define OSD_CROSSHAIR_TICK  (OSD_CROSSHAIR_RADIUS/2)
883    #define OSD_CROSSHAIR_BORDER (OSD_CROSSHAIR_TICK + OSD_CROSSHAIR_RADIUS/4)
884    #define OSD_CROSSHAIR_W  ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2)
885    #define OSD_CROSSHAIR_H  ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2)
886    
887    static void
888    osd_render_crosshair_shape(cairo_t *cr) {
889        cairo_arc (cr, OSD_CROSSHAIR_W/2, OSD_CROSSHAIR_H/2,
890                   OSD_CROSSHAIR_RADIUS, 0,  2*M_PI);
891    
892        cairo_move_to (cr, OSD_CROSSHAIR_W/2 - OSD_CROSSHAIR_RADIUS,
893                       OSD_CROSSHAIR_H/2);
894        cairo_rel_line_to (cr, -OSD_CROSSHAIR_TICK, 0);
895        cairo_move_to (cr, OSD_CROSSHAIR_W/2 + OSD_CROSSHAIR_RADIUS,
896                       OSD_CROSSHAIR_H/2);
897        cairo_rel_line_to (cr,  OSD_CROSSHAIR_TICK, 0);
898    
899        cairo_move_to (cr, OSD_CROSSHAIR_W/2,
900                       OSD_CROSSHAIR_H/2 - OSD_CROSSHAIR_RADIUS);
901        cairo_rel_line_to (cr, 0, -OSD_CROSSHAIR_TICK);
902        cairo_move_to (cr, OSD_CROSSHAIR_W/2,
903                       OSD_CROSSHAIR_H/2 + OSD_CROSSHAIR_RADIUS);
904        cairo_rel_line_to (cr, 0, OSD_CROSSHAIR_TICK);
905    
906        cairo_stroke (cr);
907    }
908    
909  static void  static void
910  osd_render(osm_gps_map_osd_t *osd) {  osd_render_crosshair(osm_gps_map_osd_t *osd)
911    {
912      osd_priv_t *priv = (osd_priv_t*)osd->priv;      osd_priv_t *priv = (osd_priv_t*)osd->priv;
913    
914        /* first fill with transparency */
915        cairo_t *cr = cairo_create(priv->crosshair);
916        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
917        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
918        //    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
919        cairo_paint(cr);
920        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
921    
922        cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
923    
924        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);
925        cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/2);
926        osd_render_crosshair_shape(cr);
927    
928        cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
929        cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/4);
930        osd_render_crosshair_shape(cr);
931    
932        cairo_destroy(cr);
933    }
934    #endif
935    
936    #ifdef OSD_SCALE
937    
938    #ifndef OSD_SCALE_FONT_SIZE
939    #define OSD_SCALE_FONT_SIZE 12
940    #endif
941    #define OSD_SCALE_W   (10*OSD_SCALE_FONT_SIZE)
942    #define OSD_SCALE_H   (5*OSD_SCALE_FONT_SIZE/2)
943    
944    /* various parameters used to create the scale */
945    #define OSD_SCALE_H2   (OSD_SCALE_H/2)
946    #define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3)
947    #define OSD_SCALE_M    (OSD_SCALE_H2 - OSD_SCALE_TICK)
948    #define OSD_SCALE_I    (OSD_SCALE_H2 + OSD_SCALE_TICK)
949    #define OSD_SCALE_FD   (OSD_SCALE_FONT_SIZE/4)
950    
951    static void
952    osd_render_scale(osm_gps_map_osd_t *osd)
953    {
954        osd_priv_t *priv = (osd_priv_t*)osd->priv;
955    
956        /* this only needs to be rendered if the zoom has changed */
957        gint zoom;
958        g_object_get(OSM_GPS_MAP(osd->widget), "zoom", &zoom, NULL);
959        if(zoom == priv->scale_zoom)
960            return;
961    
962        priv->scale_zoom = zoom;
963    
964        float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget));
965    
966        /* first fill with transparency */
967        cairo_t *cr = cairo_create(priv->scale);
968        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
969        cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
970        // pink for testing:    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
971        cairo_paint(cr);
972        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
973    
974        /* determine the size of the scale width in meters */
975        float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix;
976    
977        /* scale this to useful values */
978        int exp = logf(width)*M_LOG10E;
979        int mant = width/pow(10,exp);
980        int width_metric = mant * pow(10,exp);
981        char *dist_str = NULL;
982        if(width_metric<1000)
983            dist_str = g_strdup_printf("%u m", width_metric);
984        else
985            dist_str = g_strdup_printf("%u km", width_metric/1000);
986        width_metric /= m_per_pix;
987    
988        /* and now the hard part: scale for useful imperial values :-( */
989        /* try to convert to feet, 1ft == 0.3048 m */
990        width /= 0.3048;
991        float imp_scale = 0.3048;
992        char *dist_imp_unit = "ft";
993    
994        if(width >= 100) {
995            /* 1yd == 3 feet */
996            width /= 3.0;
997            imp_scale *= 3.0;
998            dist_imp_unit = "yd";
999    
1000            if(width >= 1760.0) {
1001                /* 1mi == 1760 yd */
1002                width /= 1760.0;
1003                imp_scale *= 1760.0;
1004                dist_imp_unit = "mi";
1005            }
1006        }
1007    
1008        /* also convert this to full tens/hundreds */
1009        exp = logf(width)*M_LOG10E;
1010        mant = width/pow(10,exp);
1011        int width_imp = mant * pow(10,exp);
1012        char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit);
1013    
1014        /* convert back to pixels */
1015        width_imp *= imp_scale;
1016        width_imp /= m_per_pix;
1017    
1018        cairo_select_font_face (cr, "Sans",
1019                                CAIRO_FONT_SLANT_NORMAL,
1020                                CAIRO_FONT_WEIGHT_BOLD);
1021        cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE);
1022        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
1023    
1024        cairo_text_extents_t extents;
1025        cairo_text_extents (cr, dist_str, &extents);
1026    
1027        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1028        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
1029        cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
1030        cairo_text_path (cr, dist_str);
1031        cairo_stroke (cr);
1032        cairo_move_to (cr, 2*OSD_SCALE_FD,
1033                       OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
1034        cairo_text_path (cr, dist_str_imp);
1035        cairo_stroke (cr);
1036    
1037        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
1038        cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
1039        cairo_show_text (cr, dist_str);
1040        cairo_move_to (cr, 2*OSD_SCALE_FD,
1041                       OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
1042        cairo_show_text (cr, dist_str_imp);
1043    
1044        g_free(dist_str);
1045        g_free(dist_str_imp);
1046    
1047        /* draw white line */
1048        cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
1049        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
1050        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3);
1051        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
1052        cairo_rel_line_to (cr, 0,  OSD_SCALE_TICK);
1053        cairo_rel_line_to (cr, width_metric, 0);
1054        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1055        cairo_stroke(cr);
1056        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
1057        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1058        cairo_rel_line_to (cr, width_imp, 0);
1059        cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
1060        cairo_stroke(cr);
1061    
1062        /* draw black line */
1063        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
1064        cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
1065        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
1066        cairo_rel_line_to (cr, 0,  OSD_SCALE_TICK);
1067        cairo_rel_line_to (cr, width_metric, 0);
1068        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1069        cairo_stroke(cr);
1070        cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
1071        cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
1072        cairo_rel_line_to (cr, width_imp, 0);
1073        cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
1074        cairo_stroke(cr);
1075    
1076        cairo_destroy(cr);
1077    }
1078    #endif
1079    
1080    static void
1081    osd_render_controls(osm_gps_map_osd_t *osd)
1082    {
1083        osd_priv_t *priv = (osd_priv_t*)osd->priv;
1084    
1085        if(priv->controls.rendered
1086    #ifdef OSD_GPS_BUTTON
1087           && (priv->controls.gps_enabled == (osd->cb != NULL))
1088    #endif
1089           )
1090            return;
1091    
1092    #ifdef OSD_GPS_BUTTON
1093        priv->controls.gps_enabled = (osd->cb != NULL);
1094    #endif
1095    
1096  #ifndef OSD_COLOR  #ifndef OSD_COLOR
1097      GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];      GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
1098      GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];      GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
# Line 691  osd_render(osm_gps_map_osd_t *osd) { Line 1100  osd_render(osm_gps_map_osd_t *osd) {
1100  #endif  #endif
1101    
1102      /* first fill with transparency */      /* first fill with transparency */
1103      cairo_t *cr = cairo_create(priv->overlay);      cairo_t *cr = cairo_create(priv->controls.surface);
1104      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1105      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);
1106      cairo_paint(cr);      cairo_paint(cr);
# Line 762  osd_render(osm_gps_map_osd_t *osd) { Line 1171  osd_render(osm_gps_map_osd_t *osd) {
1171      cairo_stroke(cr);      cairo_stroke(cr);
1172    
1173      cairo_destroy(cr);      cairo_destroy(cr);
1174    }
1175    
1176    static void
1177    osd_render(osm_gps_map_osd_t *osd)
1178    {
1179        osd_render_controls(osd);
1180    
1181    #ifdef OSD_SOURCE_SEL
1182      osd_render_source_sel(osd);      osd_render_source_sel(osd);
1183    #endif
1184    
1185    #ifdef OSD_SCALE
1186        osd_render_scale(osd);
1187    #endif
1188    
1189    #ifdef OSD_CROSSHAIR
1190        osd_render_crosshair(osd);
1191    #endif
1192    
1193    #ifdef OSD_COORDINATES
1194        osd_render_coordinates(osd);
1195    #endif
1196  }  }
1197    
1198  static void  static void
# Line 773  osd_draw(osm_gps_map_osd_t *osd, GdkDraw Line 1202  osd_draw(osm_gps_map_osd_t *osd, GdkDraw
1202    
1203      /* OSD itself uses some off-screen rendering, so check if the */      /* OSD itself uses some off-screen rendering, so check if the */
1204      /* offscreen buffer is present and create it if not */      /* offscreen buffer is present and create it if not */
1205      if(!priv->overlay) {      if(!priv->controls.surface) {
1206          /* create overlay ... */          /* create overlay ... */
1207          priv->overlay =          priv->controls.surface =
1208              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2);              cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2);
1209    
1210            priv->controls.rendered = FALSE;
1211    #ifdef OSD_GPS_BUTTON
1212            priv->controls.gps_enabled = FALSE;
1213    #endif
1214    
1215    #ifdef OSD_SOURCE_SEL
1216          /* the initial OSD state is alway not-expanded */          /* the initial OSD state is alway not-expanded */
1217          priv->map_source =          priv->map_source =
1218              cairo_image_surface_create(CAIRO_FORMAT_ARGB32,              cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1219                                             OSD_S_W+2, OSD_S_H+2);                                             OSD_S_W+2, OSD_S_H+2);
1220    #endif
1221    
1222    #ifdef OSD_SCALE
1223            priv->scale =
1224                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1225                                           OSD_SCALE_W, OSD_SCALE_H);
1226            priv->scale_zoom = -1;
1227    #endif
1228    
1229    #ifdef OSD_CROSSHAIR
1230            priv->crosshair =
1231                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1232                                           OSD_CROSSHAIR_W, OSD_CROSSHAIR_H);
1233    #endif
1234    
1235    #ifdef OSD_COORDINATES
1236            priv->coordinates =
1237                cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1238                                           OSD_COORDINATES_W, OSD_COORDINATES_H);
1239    
1240            priv->coo_lat = priv->coo_lon = OSM_GPS_MAP_INVALID;
1241    #endif
1242    
1243          /* ... and render it */          /* ... and render it */
1244          osd_render(osd);          osd_render(osd);
# Line 790  osd_draw(osm_gps_map_osd_t *osd, GdkDraw Line 1247  osd_draw(osm_gps_map_osd_t *osd, GdkDraw
1247      // now draw this onto the original context      // now draw this onto the original context
1248      cairo_t *cr = gdk_cairo_create(drawable);      cairo_t *cr = gdk_cairo_create(drawable);
1249    
1250      int x = OSD_X, y = OSD_Y;      int x, y;
     if(OSD_X < 0)  
         x = osd->widget->allocation.width - OSD_W + OSD_X;  
1251    
1252      if(OSD_Y < 0)  #ifdef OSD_SCALE
1253          y = osd->widget->allocation.height - OSD_H + OSD_Y;      x =  OSD_X;
1254        y = -OSD_Y;
1255        if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W;
1256        if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H;
1257    
1258        cairo_set_source_surface(cr, priv->scale, x, y);
1259        cairo_paint(cr);
1260    #endif
1261    
1262    #ifdef OSD_CROSSHAIR
1263        x = (osd->widget->allocation.width - OSD_CROSSHAIR_W)/2;
1264        y = (osd->widget->allocation.height - OSD_CROSSHAIR_H)/2;
1265    
1266        cairo_set_source_surface(cr, priv->crosshair, x, y);
1267        cairo_paint(cr);
1268    #endif
1269    
1270    #ifdef OSD_COORDINATES
1271        x = -OSD_X;
1272        y = -OSD_Y;
1273        if(x < 0) x += osd->widget->allocation.width - OSD_COORDINATES_W;
1274        if(y < 0) y += osd->widget->allocation.height - OSD_COORDINATES_H;
1275    
1276      cairo_set_source_surface(cr, priv->overlay, x, y);      cairo_set_source_surface(cr, priv->coordinates, x, y);
1277        cairo_paint(cr);
1278    #endif
1279    
1280        x = OSD_X;
1281        if(x < 0)
1282            x += osd->widget->allocation.width - OSD_W;
1283    
1284        y = OSD_Y;
1285        if(y < 0)
1286            y += osd->widget->allocation.height - OSD_H;
1287    
1288        cairo_set_source_surface(cr, priv->controls.surface, x, y);
1289      cairo_paint(cr);      cairo_paint(cr);
1290    
1291  #ifdef OSD_SOURCE_SEL  #ifdef OSD_SOURCE_SEL
# Line 830  osd_free(osm_gps_map_osd_t *osd) Line 1318  osd_free(osm_gps_map_osd_t *osd)
1318  {  {
1319      osd_priv_t *priv = (osd_priv_t *)(osd->priv);      osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1320    
1321        if (priv->controls.surface)
1322             cairo_surface_destroy(priv->controls.surface);
1323    
1324    #ifdef OSD_SOURCE_SEL
1325      if(priv->handler_id)      if(priv->handler_id)
1326          gtk_timeout_remove(priv->handler_id);          gtk_timeout_remove(priv->handler_id);
1327    
     if (priv->overlay)  
          cairo_surface_destroy(priv->overlay);  
   
1328      if (priv->map_source)      if (priv->map_source)
1329           cairo_surface_destroy(priv->map_source);           cairo_surface_destroy(priv->map_source);
1330    #endif
1331    
1332    #ifdef OSD_SCALE
1333        if (priv->scale)
1334             cairo_surface_destroy(priv->scale);
1335    #endif
1336    
1337    #ifdef OSD_CROSSHAIR
1338        if (priv->crosshair)
1339             cairo_surface_destroy(priv->crosshair);
1340    #endif
1341    
1342    #ifdef OSD_COORDINATES
1343        if (priv->coordinates)
1344             cairo_surface_destroy(priv->coordinates);
1345    #endif
1346    
1347      g_free(priv);      g_free(priv);
1348  }  }
1349    
 /* this is the only function that's externally visible */  
1350  static gboolean  static gboolean
1351  osd_busy(osm_gps_map_osd_t *osd)  osd_busy(osm_gps_map_osd_t *osd)
1352  {  {
1353    #ifdef OSD_SOURCE_SEL
1354      osd_priv_t *priv = (osd_priv_t *)(osd->priv);      osd_priv_t *priv = (osd_priv_t *)(osd->priv);
1355      return (priv->handler_id != 0);      return (priv->handler_id != 0);
1356    #else
1357        return FALSE;
1358    #endif
1359  }  }
1360    
1361  static osm_gps_map_osd_t osd_classic = {  static osm_gps_map_osd_t osd_classic = {
1362        .widget     = NULL,
1363    
1364      .draw       = osd_draw,      .draw       = osd_draw,
1365      .check      = osd_check,      .check      = osd_check,
1366      .render     = osd_render,      .render     = osd_render,

Legend:
Removed from v.87  
changed lines
  Added in v.108