From b0e68b797350eda0a73c250526b1fa7e9f1fc61a Mon Sep 17 00:00:00 2001 From: lains Date: Tue, 13 Mar 2018 15:51:37 +0100 Subject: change:osd: compass appearance update (#413) * Making graphics_draw_polygon_clipped() and graphics_draw_polyline_clipped() non-static * Updating compass appearance * Adding doxygen comment on graphics_draw_polyline_clipped() and graphics_draw_polygon_clipped() * Improving doxygen comment * Allowing customization of compass colors using navit.xml attributes destination_dir_color and north_color --- navit/attr_def.h | 2 + navit/graphics.c | 24 ++++++- navit/graphics.h | 2 + navit/osd/core/osd_core.c | 168 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 169 insertions(+), 27 deletions(-) diff --git a/navit/attr_def.h b/navit/attr_def.h index 9276e4d60..e2e3aeab1 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -433,6 +433,8 @@ ATTR(text_color) ATTR(idle_color) ATTR(background_color2) ATTR(text_background) +ATTR(destination_dir_color) +ATTR(north_color) ATTR2(0x0007ffff,type_color_end) ATTR2(0x00080000,type_object_begin) ATTR(navit) diff --git a/navit/graphics.c b/navit/graphics.c index f89a4f89d..378f177fb 100644 --- a/navit/graphics.c +++ b/navit/graphics.c @@ -1829,7 +1829,19 @@ clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *clip_rect) return ret; } -static void +/** + * @brief Draw polyline on the display + * + * Polylines are a serie of lines connected to each other. + * + * @param gra The graphics instance on which to draw + * @param gc The color to use for the drawing + * @param[in] pin An array of points forming the polygon + * @param count_in The number of elements inside @p pin + * @param[in] width An array of width matching the line starting from the corresponding @p pa (if all equal, all lines will have the same width) + * @param poly A boolean indicating whether the polyline should be closed to form a polygon (only the contour of this polygon will be drawn) + */ +void graphics_draw_polyline_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pa, int count, int *width, int poly) { struct point *points_to_draw=g_alloca(sizeof(struct point)*(count+1)); @@ -1937,7 +1949,15 @@ poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int } } -static void +/** + * @brief Draw a plain polygon on the display + * + * @param gra The graphics instance on which to draw + * @param gc The color to use for the drawing + * @param[in] pin An array of points forming the polygon + * @param count_in The number of elements inside @p pin + */ +void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in) { struct point_rect r=gra->r; diff --git a/navit/graphics.h b/navit/graphics.h index 2ffbd9ab0..befeb8e2b 100644 --- a/navit/graphics.h +++ b/navit/graphics.h @@ -282,6 +282,8 @@ void graphics_remove_selection(struct graphics *gra, struct item *item, enum ite void graphics_clear_selection(struct graphics *gra, struct displaylist *dl); int graphics_show_native_keyboard (struct graphics *this_, struct graphics_keyboard *kbd); int graphics_hide_native_keyboard (struct graphics *this_, struct graphics_keyboard *kbd); +void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in); +void graphics_draw_polyline_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pa, int count, int *width, int poly); /* end of prototypes */ #ifdef __cplusplus diff --git a/navit/osd/core/osd_core.c b/navit/osd/core/osd_core.c index d336d36f6..d3bf66a76 100644 --- a/navit/osd/core/osd_core.c +++ b/navit/osd/core/osd_core.c @@ -92,11 +92,21 @@ static int b_commandtable_added = 0; struct compass { - int width; - struct graphics_gc *green; - struct callback *click_cb; + int width; /*!< Width of the compass in pixels */ + struct color destination_dir_color; /*!< Color definition of the destination direction arrow */ + struct color north_color; /*!< Color definition of north handle of the compass */ + struct graphics_gc *destination_dir_gc; /*!< graphics_gc context used to draw the destination direction arrow */ + struct graphics_gc *north_gc; /*!< graphics_gc context used to draw the north handle of the compass */ + struct callback *click_cb; /*!< A callback to execute when clicking on the compass */ }; +/** + * @brief Rotate a group of points around a @p center + * @param center The coordinates of the center of the rotation to apply + * @param angle The angle of the rotation + * @param[in,out] p An array of points to rotate + * @param count The number of points stored inside @p p + */ static void transform_rotate(struct point *center, int angle, struct point *p, int count) @@ -115,27 +125,121 @@ transform_rotate(struct point *center, int angle, struct point *p, } } +/** + * @brief Move a group of points in a direction (adding @p dx and @p dy to their x and y coordinates) + * @param dx The shift to perform to the x axis + * @param dy The shift to perform to the y axis + * @param[in,out] p An array of points to move + * @param count The number of points stored inside @p p + */ static void -handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r, - int dir) +transform_move(int dx, int dy, struct point *p, + int count) +{ + int i; + for (i = 0; i < count; i++) { + p->x += dx; + p->y += dy; + p++; + } +} + +/** + * @brief Draw a compass handle of length @p r, centered at point @p p, pointing to direction @p dir + * + * @param gr The graphics instance on which to draw + * @param gc_n The color to use for the north half of the compass + * @param gc_s The color to use for the south half of the compass + * @param p The center of the compass + * @param r The radius of the compass (around the center point @p p) + * @param dir The direction the compass points to (0 being up, value is in degrees counter-clockwise) + */ +static void +draw_compass(struct graphics *gr, struct graphics_gc *gc_n, struct graphics_gc *gc_s, struct point *p, int r, + int dir) { struct point ph[3]; - int l = r * 0.4; + int wh[3] = { 1, 1, 1 }; /* Width of each line of the polygon to draw */ + int l = r * 0.25; - ph[0].x = 0; - ph[0].y = r; + ph[0].x = -l; + ph[0].y = 0; ph[1].x = 0; ph[1].y = -r; - transform_rotate(p, dir, ph, 2); - graphics_draw_lines(gr, gc, ph, 2); + ph[2].x = l; + ph[2].y = 0; + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_polygon_clipped(gr, gc_n, ph, 3); /* Draw north half */ + ph[0].x = -l; + ph[0].y = 0; + ph[1].x = 0; + ph[1].y = r; + ph[2].x = l; + ph[2].y = 0; + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_polyline_clipped(gr, gc_s, ph, 3, wh, 0); /* Draw south half */ +} + +/** + * @brief Draw an arrow of length @p r, centered at point @p p, with color @p gc, pointing to direction @p dir + * + * @param gr The graphics instance on which to draw + * @param gc The color to draw the arrow + * @param p The center of the compass + * @param r The radius of the compass (around the center point @p p) + * @param dir The direction the arrow points to (0 being up, value is in degrees counter-clockwise) + */ +static void +draw_handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r, + int dir) +{ + struct point ph[6]; + int l = r * 0.4; + int s = l * 0.4; + + ph[0].x = 0; /* Compute details for the body of the arrow */ + ph[0].y = r - l; + ph[1].x = 0; + ph[1].y = -r; + transform_rotate(p, dir, ph, 2); /* Rotate to the correct direction */ + graphics_draw_lines(gr, gc, ph, 2); /* Draw the body */ + + ph[0].x = -l; /* Compute details for the head of the arrow */ ph[0].y = -r + l; ph[1].x = 0; ph[1].y = -r; ph[2].x = l; ph[2].y = -r + l; - transform_rotate(p, dir, ph, 3); - graphics_draw_lines(gr, gc, ph, 3); + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_lines(gr, gc, ph, 3); /* Draw the head */ + + ph[0].x = -s; /* Compute details for the tail of the arrow */ + ph[0].y = r - l + s; + ph[1].x = 0; + ph[1].y = r - l; + ph[2].x = s; + ph[2].y = r - l + s; + ph[3]=ph[0]; /* Save these 3 points for future re-use */ + ph[4]=ph[1]; + ph[5]=ph[2]; + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_lines(gr, gc, ph, 3); /* Draw the tail */ + ph[0]=ph[3]; /* Restore saved points */ + ph[1]=ph[4]; + ph[2]=ph[5]; + transform_move(0, s, ph, 3); + ph[3]=ph[0]; /* Save these 3 points for future re-use */ + ph[4]=ph[1]; + ph[5]=ph[2]; + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_lines(gr, gc, ph, 3); /* Draw the tail */ + ph[0]=ph[3]; /* Restore saved points */ + ph[1]=ph[4]; + ph[2]=ph[5]; + transform_move(0, s, ph, 3); + transform_rotate(p, dir, ph, 3); /* Rotate to the correct direction */ + graphics_draw_lines(gr, gc, ph, 3); /* Draw the tail */ } /** @@ -1409,7 +1513,13 @@ osd_stopwatch_new(struct navit *nav, struct osd_methods *meth, return (struct osd_priv *) opc; } - +/** + * @brief Draw the compass on the OSD (includes north and destination direction) + * + * @param opc A contextual private data pointer (see struct osd_priv_common) + * @param nav The global navit object + * @param v The current vehicle + */ static void osd_compass_draw(struct osd_priv_common *opc, struct navit *nav, struct vehicle *v) @@ -1435,7 +1545,7 @@ osd_compass_draw(struct osd_priv_common *opc, struct navit *nav, if (v) { if (vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL)) { vdir = *attr_dir.u.numd; - handle(opc->osd_item.gr, opc->osd_item.graphic_fg, &p, opc->osd_item.w/3, -vdir); + draw_compass(opc->osd_item.gr, this->north_gc, opc->osd_item.graphic_fg, &p, opc->osd_item.w/3, -vdir); /* Draw a compass */ } if (navit_get_attr(nav, attr_destination, &destination_attr, NULL) @@ -1446,12 +1556,12 @@ osd_compass_draw(struct osd_priv_common *opc, struct navit *nav, c2.y = destination_attr.u.pcoord->y; dir = atan2(c2.x - c1.x, c2.y - c1.y) * 180.0 / M_PI; dir -= vdir; - handle(opc->osd_item.gr, this->green, &p, opc->osd_item.w/3, dir); + draw_handle(opc->osd_item.gr, this->destination_dir_gc, &p, opc->osd_item.w/3, dir); /* Draw the green arrow pointing to the destination */ buffer=format_distance(transform_distance(pro, &c1, &c2),"",imperial); graphics_get_text_bbox(opc->osd_item.gr, opc->osd_item.font, buffer, 0x10000, 0, bbox, 0); p.x=(opc->osd_item.w-bbox[2].x)/2; p.y = opc->osd_item.h-opc->osd_item.h/10; - graphics_draw_text(opc->osd_item.gr, this->green, NULL, opc->osd_item.font, buffer, &p, 0x10000, 0); + graphics_draw_text(opc->osd_item.gr, this->destination_dir_gc, NULL, opc->osd_item.font, buffer, &p, 0x10000, 0); g_free(buffer); } } @@ -1463,19 +1573,20 @@ osd_compass_draw(struct osd_priv_common *opc, struct navit *nav, static void osd_compass_init(struct osd_priv_common *opc, struct navit *nav) { - struct color c; - struct compass *this = (struct compass *)opc->data; osd_set_std_graphic(nav, &opc->osd_item, (struct osd_priv *)opc); - this->green = graphics_gc_new(opc->osd_item.gr); - c.r = 0; - c.g = 65535; - c.b = 0; - c.a = 65535; - graphics_gc_set_foreground(this->green, &c); - graphics_gc_set_linewidth(this->green, this->width); + this->destination_dir_gc = graphics_gc_new(opc->osd_item.gr); + graphics_gc_set_foreground(this->destination_dir_gc, &this->destination_dir_color); + graphics_gc_set_linewidth(this->destination_dir_gc, this->width); + + this->north_gc = graphics_gc_new(opc->osd_item.gr); + graphics_gc_set_foreground(this->north_gc, &this->north_color); + graphics_gc_set_linewidth(this->north_gc, this->width); + + opc->osd_item.graphic_fg = graphics_gc_new(opc->osd_item.gr); + graphics_gc_set_foreground(opc->osd_item.graphic_fg, &opc->osd_item.text_color); graphics_gc_set_linewidth(opc->osd_item.graphic_fg, this->width); navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_compass_draw), attr_position_coord_geo, opc)); @@ -1492,6 +1603,8 @@ osd_compass_new(struct navit *nav, struct osd_methods *meth, struct compass *this = g_new0(struct compass, 1); struct osd_priv_common *opc = g_new0(struct osd_priv_common,1); struct attr *attr; + struct color green_color={0x0400,0xffff,0x1000,0xffff}; + struct color red_color={0xffff,0x0400,0x0400,0xffff}; opc->data = (void*)this; opc->osd_item.rel_x = 20; @@ -1505,6 +1618,11 @@ osd_compass_new(struct navit *nav, struct osd_methods *meth, osd_set_std_attr(attrs, &opc->osd_item, 2); attr = attr_search(attrs, NULL, attr_width); this->width=attr ? attr->u.num : 2; + attr = attr_search(attrs, NULL, attr_destination_dir_color); + this->destination_dir_color=attr ? *attr->u.color : green_color; /* Pick destination color from configuration, default to green if unspecified */ + attr = attr_search(attrs, NULL, attr_north_color); + this->north_color=attr ? *attr->u.color : red_color; /* Pick north handle color from configuration, default to red if unspecified */ + navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_compass_init), attr_graphics_ready, opc)); return (struct osd_priv *) opc; } -- cgit v1.2.1