25 |
/* OSD_DIAMETER */ |
/* OSD_DIAMETER */ |
26 |
/* OSD_X, OSD_Y */ |
/* OSD_X, OSD_Y */ |
27 |
|
|
|
#define OSD_SCALE |
|
|
|
|
|
#define OSD_SCALE_W 120 |
|
|
#define OSD_SCALE_H 20 |
|
|
|
|
28 |
#ifndef USE_CAIRO |
#ifndef USE_CAIRO |
29 |
#error "OSD control display lacks a non-cairo implementation!" |
#error "OSD control display lacks a non-cairo implementation!" |
30 |
#endif |
#endif |
34 |
#include "osm-gps-map.h" |
#include "osm-gps-map.h" |
35 |
#include "osm-gps-map-osd-classic.h" |
#include "osm-gps-map-osd-classic.h" |
36 |
|
|
37 |
|
#define OSD_COORDINATES |
38 |
|
|
39 |
//the osd controls |
//the osd controls |
40 |
typedef struct { |
typedef struct { |
41 |
/* the offscreen representation of the OSD */ |
/* the offscreen representation of the OSD */ |
43 |
|
|
44 |
#ifdef OSD_SCALE |
#ifdef OSD_SCALE |
45 |
cairo_surface_t *scale; |
cairo_surface_t *scale; |
46 |
|
int scale_zoom; |
47 |
|
#endif |
48 |
|
|
49 |
|
#ifdef OSD_CROSSHAIR |
50 |
|
cairo_surface_t *crosshair; |
51 |
|
#endif |
52 |
|
|
53 |
|
#ifdef OSD_COORDINATES |
54 |
|
cairo_surface_t *coordinates; |
55 |
#endif |
#endif |
56 |
|
|
57 |
#ifdef OSD_SOURCE_SEL |
#ifdef OSD_SOURCE_SEL |
733 |
cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID); |
cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID); |
734 |
} |
} |
735 |
|
|
736 |
static char * |
#ifdef OSD_COORDINATES |
737 |
dist_str_metric(int dist) |
#define OSD_COORDINATES_W 100 |
738 |
|
#define OSD_COORDINATES_H 50 |
739 |
|
|
740 |
|
static void |
741 |
|
osd_render_coordinates(osm_gps_map_osd_t *osd) |
742 |
{ |
{ |
743 |
if(dist<1000) |
osd_priv_t *priv = (osd_priv_t*)osd->priv; |
744 |
return g_strdup_printf("%u m", dist); |
|
745 |
|
/* first fill with transparency */ |
746 |
|
cairo_t *cr = cairo_create(priv->coordinates); |
747 |
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
748 |
|
// cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); |
749 |
|
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); |
750 |
|
cairo_paint(cr); |
751 |
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
752 |
|
|
753 |
return g_strdup_printf("%u km", dist/1000); |
cairo_destroy(cr); |
754 |
} |
} |
755 |
|
#endif // OSD_COORDINATES |
756 |
|
|
757 |
|
#ifdef OSD_CROSSHAIR |
758 |
|
|
759 |
|
#ifndef OSD_CROSSHAIR_RADIUS |
760 |
|
#define OSD_CROSSHAIR_RADIUS 10 |
761 |
|
#endif |
762 |
|
|
763 |
|
#define OSD_CROSSHAIR_TICK (OSD_CROSSHAIR_RADIUS/2) |
764 |
|
#define OSD_CROSSHAIR_BORDER (OSD_CROSSHAIR_TICK + OSD_CROSSHAIR_RADIUS/4) |
765 |
|
#define OSD_CROSSHAIR_W ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) |
766 |
|
#define OSD_CROSSHAIR_H ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) |
767 |
|
|
768 |
|
static void |
769 |
|
osd_render_crosshair_shape(cairo_t *cr) { |
770 |
|
cairo_arc (cr, OSD_CROSSHAIR_W/2, OSD_CROSSHAIR_H/2, |
771 |
|
OSD_CROSSHAIR_RADIUS, 0, 2*M_PI); |
772 |
|
|
773 |
|
cairo_move_to (cr, OSD_CROSSHAIR_W/2 - OSD_CROSSHAIR_RADIUS, |
774 |
|
OSD_CROSSHAIR_H/2); |
775 |
|
cairo_rel_line_to (cr, -OSD_CROSSHAIR_TICK, 0); |
776 |
|
cairo_move_to (cr, OSD_CROSSHAIR_W/2 + OSD_CROSSHAIR_RADIUS, |
777 |
|
OSD_CROSSHAIR_H/2); |
778 |
|
cairo_rel_line_to (cr, OSD_CROSSHAIR_TICK, 0); |
779 |
|
|
780 |
|
cairo_move_to (cr, OSD_CROSSHAIR_W/2, |
781 |
|
OSD_CROSSHAIR_H/2 - OSD_CROSSHAIR_RADIUS); |
782 |
|
cairo_rel_line_to (cr, 0, -OSD_CROSSHAIR_TICK); |
783 |
|
cairo_move_to (cr, OSD_CROSSHAIR_W/2, |
784 |
|
OSD_CROSSHAIR_H/2 + OSD_CROSSHAIR_RADIUS); |
785 |
|
cairo_rel_line_to (cr, 0, OSD_CROSSHAIR_TICK); |
786 |
|
|
787 |
|
cairo_stroke (cr); |
788 |
|
} |
789 |
|
|
790 |
|
static void |
791 |
|
osd_render_crosshair(osm_gps_map_osd_t *osd) |
792 |
|
{ |
793 |
|
osd_priv_t *priv = (osd_priv_t*)osd->priv; |
794 |
|
|
795 |
|
/* first fill with transparency */ |
796 |
|
cairo_t *cr = cairo_create(priv->crosshair); |
797 |
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
798 |
|
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); |
799 |
|
// cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); |
800 |
|
cairo_paint(cr); |
801 |
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
802 |
|
|
803 |
|
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); |
804 |
|
|
805 |
|
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5); |
806 |
|
cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/2); |
807 |
|
osd_render_crosshair_shape(cr); |
808 |
|
|
809 |
|
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); |
810 |
|
cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/4); |
811 |
|
osd_render_crosshair_shape(cr); |
812 |
|
|
813 |
|
cairo_destroy(cr); |
814 |
|
} |
815 |
|
#endif |
816 |
|
|
817 |
|
#ifdef OSD_SCALE |
818 |
|
|
819 |
|
#ifndef OSD_SCALE_FONT_SIZE |
820 |
#define OSD_SCALE_FONT_SIZE 12 |
#define OSD_SCALE_FONT_SIZE 12 |
821 |
|
#endif |
822 |
|
#define OSD_SCALE_W (10*OSD_SCALE_FONT_SIZE) |
823 |
|
#define OSD_SCALE_H (5*OSD_SCALE_FONT_SIZE/2) |
824 |
|
|
825 |
|
/* various parameters used to create the scale */ |
826 |
|
#define OSD_SCALE_H2 (OSD_SCALE_H/2) |
827 |
|
#define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3) |
828 |
|
#define OSD_SCALE_M (OSD_SCALE_H2 - OSD_SCALE_TICK) |
829 |
|
#define OSD_SCALE_I (OSD_SCALE_H2 + OSD_SCALE_TICK) |
830 |
|
#define OSD_SCALE_FD (OSD_SCALE_FONT_SIZE/4) |
831 |
|
|
832 |
static void |
static void |
833 |
osd_render_scale(osm_gps_map_osd_t *osd) |
osd_render_scale(osm_gps_map_osd_t *osd) |
834 |
{ |
{ |
835 |
osd_priv_t *priv = (osd_priv_t*)osd->priv; |
osd_priv_t *priv = (osd_priv_t*)osd->priv; |
836 |
|
|
837 |
|
/* this only needs to be rendered if the zoom has changed */ |
838 |
|
gint zoom; |
839 |
|
g_object_get(OSM_GPS_MAP(osd->widget), "zoom", &zoom, NULL); |
840 |
|
if(zoom == priv->scale_zoom) |
841 |
|
return; |
842 |
|
|
843 |
|
priv->scale_zoom = zoom; |
844 |
|
|
845 |
float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget)); |
float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget)); |
846 |
|
|
847 |
/* first fill with transparency */ |
/* first fill with transparency */ |
848 |
cairo_t *cr = cairo_create(priv->scale); |
cairo_t *cr = cairo_create(priv->scale); |
849 |
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
850 |
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); |
851 |
// cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); |
// pink for testing: cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); |
852 |
cairo_paint(cr); |
cairo_paint(cr); |
853 |
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
854 |
|
|
855 |
/* determine the size of the scale width in meters */ |
/* determine the size of the scale width in meters */ |
856 |
float width = (OSD_SCALE_W-2) * m_per_pix; |
float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix; |
|
printf("%d pixels is %f m\n", OSD_SCALE_W-2, width); |
|
857 |
|
|
858 |
/* scale this to useful values */ |
/* scale this to useful values */ |
859 |
int exp = logf(width)*M_LOG10E; |
int exp = logf(width)*M_LOG10E; |
860 |
int mant = width/pow(10,exp); |
int mant = width/pow(10,exp); |
861 |
int width_metric = mant * pow(10,exp); |
int width_metric = mant * pow(10,exp); |
862 |
char *dist_str = dist_str_metric(width_metric); |
char *dist_str = NULL; |
863 |
|
if(width_metric<1000) |
864 |
|
dist_str = g_strdup_printf("%u m", width_metric); |
865 |
|
else |
866 |
|
dist_str = g_strdup_printf("%u km", width_metric/1000); |
867 |
width_metric /= m_per_pix; |
width_metric /= m_per_pix; |
868 |
|
|
869 |
/* and now the hard part: scale for useful imperial values :-( */ |
/* and now the hard part: scale for useful imperial values :-( */ |
886 |
} |
} |
887 |
} |
} |
888 |
|
|
889 |
printf("this is %f %s\n", width, dist_imp_unit); |
/* also convert this to full tens/hundreds */ |
890 |
printf("this is %f pixels\n", width * imp_scale / m_per_pix); |
exp = logf(width)*M_LOG10E; |
891 |
|
mant = width/pow(10,exp); |
892 |
|
int width_imp = mant * pow(10,exp); |
893 |
|
char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit); |
894 |
|
|
895 |
|
/* convert back to pixels */ |
896 |
|
width_imp *= imp_scale; |
897 |
|
width_imp /= m_per_pix; |
898 |
|
|
899 |
cairo_select_font_face (cr, "Sans", |
cairo_select_font_face (cr, "Sans", |
900 |
CAIRO_FONT_SLANT_NORMAL, |
CAIRO_FONT_SLANT_NORMAL, |
906 |
cairo_text_extents (cr, dist_str, &extents); |
cairo_text_extents (cr, dist_str, &extents); |
907 |
|
|
908 |
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); |
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); |
909 |
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/3, OSD_SCALE_FONT_SIZE); |
cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); |
910 |
|
cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); |
911 |
cairo_text_path (cr, dist_str); |
cairo_text_path (cr, dist_str); |
912 |
cairo_set_line_width (cr, 2); |
cairo_stroke (cr); |
913 |
|
cairo_move_to (cr, 2*OSD_SCALE_FD, |
914 |
|
OSD_SCALE_H2+OSD_SCALE_FD + extents.height); |
915 |
|
cairo_text_path (cr, dist_str_imp); |
916 |
cairo_stroke (cr); |
cairo_stroke (cr); |
917 |
|
|
918 |
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); |
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); |
919 |
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/3, OSD_SCALE_FONT_SIZE); |
cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); |
920 |
cairo_show_text (cr, dist_str); |
cairo_show_text (cr, dist_str); |
921 |
|
cairo_move_to (cr, 2*OSD_SCALE_FD, |
922 |
|
OSD_SCALE_H2+OSD_SCALE_FD + extents.height); |
923 |
|
cairo_show_text (cr, dist_str_imp); |
924 |
|
|
925 |
|
g_free(dist_str); |
926 |
|
g_free(dist_str_imp); |
927 |
|
|
928 |
/* draw white line */ |
/* draw white line */ |
929 |
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); |
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); |
930 |
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); |
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); |
931 |
cairo_set_line_width (cr, 4); |
cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3); |
932 |
cairo_move_to (cr, 2, 2*OSD_SCALE_FONT_SIZE/3); |
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); |
933 |
cairo_rel_line_to (cr, 0, 2*OSD_SCALE_FONT_SIZE/3); |
cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); |
934 |
cairo_rel_line_to (cr, width_metric, 0); |
cairo_rel_line_to (cr, width_metric, 0); |
935 |
cairo_rel_line_to (cr, 0, -2*OSD_SCALE_FONT_SIZE/3); |
cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); |
936 |
|
cairo_stroke(cr); |
937 |
|
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); |
938 |
|
cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); |
939 |
|
cairo_rel_line_to (cr, width_imp, 0); |
940 |
|
cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); |
941 |
cairo_stroke(cr); |
cairo_stroke(cr); |
942 |
|
|
943 |
/* draw black line */ |
/* draw black line */ |
944 |
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); |
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); |
945 |
cairo_set_line_width (cr, 2); |
cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); |
946 |
cairo_move_to (cr, 2, 2*OSD_SCALE_FONT_SIZE/3); |
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); |
947 |
cairo_rel_line_to (cr, 0, 2*OSD_SCALE_FONT_SIZE/3); |
cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); |
948 |
cairo_rel_line_to (cr, width_metric, 0); |
cairo_rel_line_to (cr, width_metric, 0); |
949 |
cairo_rel_line_to (cr, 0, -2*OSD_SCALE_FONT_SIZE/3); |
cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); |
950 |
|
cairo_stroke(cr); |
951 |
|
cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); |
952 |
|
cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); |
953 |
|
cairo_rel_line_to (cr, width_imp, 0); |
954 |
|
cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); |
955 |
cairo_stroke(cr); |
cairo_stroke(cr); |
|
|
|
|
/* xyz */ |
|
956 |
|
|
957 |
cairo_destroy(cr); |
cairo_destroy(cr); |
958 |
} |
} |
959 |
|
#endif |
960 |
|
|
961 |
static void |
static void |
962 |
osd_render(osm_gps_map_osd_t *osd) |
osd_render(osm_gps_map_osd_t *osd) |
1049 |
#ifdef OSD_SCALE |
#ifdef OSD_SCALE |
1050 |
osd_render_scale(osd); |
osd_render_scale(osd); |
1051 |
#endif |
#endif |
1052 |
|
|
1053 |
|
#ifdef OSD_CROSSHAIR |
1054 |
|
osd_render_crosshair(osd); |
1055 |
|
#endif |
1056 |
|
|
1057 |
|
#ifdef OSD_COORDINATES |
1058 |
|
osd_render_coordinates(osd); |
1059 |
|
#endif |
1060 |
} |
} |
1061 |
|
|
1062 |
static void |
static void |
1081 |
#ifdef OSD_SCALE |
#ifdef OSD_SCALE |
1082 |
priv->scale = |
priv->scale = |
1083 |
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
1084 |
OSD_SCALE_W+2, OSD_SCALE_H+2); |
OSD_SCALE_W, OSD_SCALE_H); |
1085 |
|
priv->scale_zoom = -1; |
1086 |
|
#endif |
1087 |
|
|
1088 |
|
#ifdef OSD_CROSSHAIR |
1089 |
|
priv->crosshair = |
1090 |
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
1091 |
|
OSD_CROSSHAIR_W, OSD_CROSSHAIR_H); |
1092 |
|
#endif |
1093 |
|
|
1094 |
|
#ifdef OSD_COORDINATES |
1095 |
|
priv->coordinates = |
1096 |
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
1097 |
|
OSD_COORDINATES_W, OSD_COORDINATES_H); |
1098 |
#endif |
#endif |
1099 |
|
|
1100 |
/* ... and render it */ |
/* ... and render it */ |
1104 |
// now draw this onto the original context |
// now draw this onto the original context |
1105 |
cairo_t *cr = gdk_cairo_create(drawable); |
cairo_t *cr = gdk_cairo_create(drawable); |
1106 |
|
|
1107 |
int x = OSD_X, y = OSD_Y; |
int x, y; |
|
if(OSD_X < 0) |
|
|
x = osd->widget->allocation.width - OSD_W + OSD_X; |
|
1108 |
|
|
1109 |
if(OSD_Y < 0) |
#ifdef OSD_SCALE |
1110 |
y = osd->widget->allocation.height - OSD_H + OSD_Y; |
x = OSD_X; |
1111 |
|
y = -OSD_Y; |
1112 |
|
if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W; |
1113 |
|
if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H; |
1114 |
|
|
1115 |
|
cairo_set_source_surface(cr, priv->scale, x, y); |
1116 |
|
cairo_paint(cr); |
1117 |
|
#endif |
1118 |
|
|
1119 |
|
#ifdef OSD_CROSSHAIR |
1120 |
|
x = (osd->widget->allocation.width - OSD_CROSSHAIR_W)/2; |
1121 |
|
y = (osd->widget->allocation.height - OSD_CROSSHAIR_H)/2; |
1122 |
|
|
1123 |
|
cairo_set_source_surface(cr, priv->crosshair, x, y); |
1124 |
|
cairo_paint(cr); |
1125 |
|
#endif |
1126 |
|
|
1127 |
|
#ifdef OSD_COORDINATES |
1128 |
|
x = -OSD_X; |
1129 |
|
y = -OSD_Y; |
1130 |
|
if(x < 0) x += osd->widget->allocation.width - OSD_COORDINATES_W; |
1131 |
|
if(y < 0) y += osd->widget->allocation.height - OSD_COORDINATES_H; |
1132 |
|
|
1133 |
|
cairo_set_source_surface(cr, priv->coordinates, x, y); |
1134 |
|
cairo_paint(cr); |
1135 |
|
#endif |
1136 |
|
|
1137 |
|
x = OSD_X; |
1138 |
|
if(x < 0) |
1139 |
|
x += osd->widget->allocation.width - OSD_W; |
1140 |
|
|
1141 |
|
y = OSD_Y; |
1142 |
|
if(y < 0) |
1143 |
|
y += osd->widget->allocation.height - OSD_H; |
1144 |
|
|
1145 |
cairo_set_source_surface(cr, priv->overlay, x, y); |
cairo_set_source_surface(cr, priv->overlay, x, y); |
1146 |
cairo_paint(cr); |
cairo_paint(cr); |
1167 |
cairo_paint(cr); |
cairo_paint(cr); |
1168 |
#endif |
#endif |
1169 |
|
|
|
#ifdef OSD_SCALE |
|
|
x = OSD_X; |
|
|
y = -OSD_Y; |
|
|
if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W; |
|
|
if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H; |
|
|
|
|
|
cairo_set_source_surface(cr, priv->scale, x, y); |
|
|
cairo_paint(cr); |
|
|
#endif |
|
|
|
|
1170 |
cairo_destroy(cr); |
cairo_destroy(cr); |
1171 |
} |
} |
1172 |
|
|
1191 |
cairo_surface_destroy(priv->scale); |
cairo_surface_destroy(priv->scale); |
1192 |
#endif |
#endif |
1193 |
|
|
1194 |
|
#ifdef OSD_CROSSHAIR |
1195 |
|
if (priv->crosshair) |
1196 |
|
cairo_surface_destroy(priv->crosshair); |
1197 |
|
#endif |
1198 |
|
|
1199 |
|
#ifdef OSD_COORDINATES |
1200 |
|
if (priv->coordinates) |
1201 |
|
cairo_surface_destroy(priv->coordinates); |
1202 |
|
#endif |
1203 |
|
|
1204 |
g_free(priv); |
g_free(priv); |
1205 |
} |
} |
1206 |
|
|