From d68e2171a1c9e1668f04f790d906a22550bb5991 Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Wed, 25 Sep 2019 21:52:55 +0200 Subject: fix/enhancement:graphics/layout:get default icon size from layout + draw tunnels transparent + mark oneway streets (#884) This pull request adds the possibility to globally set a default for icon size of a layout. You can now give "icon_h" and "icon_w" properties in "layout" tag. This causes navit to not use the real size of an icon but to scale it to have the requested size. Guessing prescaled icons (the name_w_h.png's of course works. Default size of 22x22px which is the default size hint on most of the svg's is used. This fixes #819. This pull request adds the property "underground_alpha" to the "graphics" tag giving the alpha value to use as transparency if ways are flagged with AF_UNDERGROUND. This effectively renders tunnels in transparent. This pull request adds a "oneway" tag to itemgras in layouts. Together with the enhancements of the "arrows" itemgra used for drawing the route graph one can print nice arrows on oneway roads. --- navit/attr_def.h | 2 + navit/color.h | 5 +- navit/graphics.c | 176 +++++++++++++++++++++++------ navit/layout.c | 41 ++++++- navit/layout.h | 7 ++ navit/navit_layout_bike_shipped.xml | 2 +- navit/navit_layout_car_android_shipped.xml | 2 +- navit/navit_layout_car_dark_shipped.xml | 2 +- navit/navit_layout_car_shipped.xml | 38 ++++++- navit/navit_layout_car_simple_shipped.xml | 2 +- navit/navit_layout_th_shipped.xml | 2 +- navit/xslt/sailfish_svg.xslt | 17 ++- 12 files changed, 250 insertions(+), 46 deletions(-) diff --git a/navit/attr_def.h b/navit/attr_def.h index 5a82d9d30..45764ebb2 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -202,6 +202,7 @@ ATTR(autozoom_max) ATTR(nav_status) ATTR(virtual_dpi) ATTR(real_dpi) +ATTR(underground_alpha) ATTR2(0x00027500,type_rel_abs_begin) /* These attributes are int that can either hold relative or absolute values. See the * documentation of ATTR_REL_RELSHIFT for details. @@ -262,6 +263,7 @@ ATTR(waypoints_flag) /* toggle for "set as destination" to switch between start ATTR(no_warning_if_map_file_missing) ATTR(duplicate) ATTR(has_menu_button) +ATTR(oneway) ATTR2(0x0002ffff,type_int_end) ATTR2(0x00030000,type_string_begin) ATTR(type) diff --git a/navit/color.h b/navit/color.h index dee10a187..067702ebe 100644 --- a/navit/color.h +++ b/navit/color.h @@ -21,7 +21,7 @@ #define NAVIT_COLOR_H struct color { - int r,g,b,a; + int r,g,b,a; }; #define COLOR_BITDEPTH 16 @@ -34,6 +34,9 @@ struct color { #define COLOR_TRANSPARENT ((struct color) {COLOR_TRANSPARENT_}) #define COLOR_FMT "0x%x,0x%x,0x%x,0x%x" #define COLOR_ARGS(c) (c).r,(c).g,(c).b,(c).a +/*default alpha value to apply for all things flagged AF_UNDERGROUND + *use solid color to not change default behaviour*/ +#define UNDERGROUND_ALPHA_ 0xFFFF #define COLOR_IS_SAME(c1,c2) ((c1).r==(c2).r && (c1).g==(c2).g && (c1).b==(c2).b && (c1).a==(c2).a) #define COLOR_IS_WHITE(c) COLOR_IS_SAME(c, COLOR_WHITE) diff --git a/navit/graphics.c b/navit/graphics.c index 784ca5540..6aaa0cb09 100644 --- a/navit/graphics.c +++ b/navit/graphics.c @@ -1366,6 +1366,7 @@ struct displayitem { char *label; struct displayitem_poly_holes * holes; int z_order; + int flags; int count; struct coord c[0]; }; @@ -1433,6 +1434,7 @@ static void display_add(struct hash_entry *entry, struct item *item, int count, int hole_count=0; int hole_total_coords=0; int holes_length; + int flags=0; /* calculate number of bytes required */ /* own length */ @@ -1446,6 +1448,11 @@ static void display_add(struct hash_entry *entry, struct item *item, int count, len++; } } + /* check for and remember flags (for underground drawing) */ + item_attr_rewind(item); + if(item_attr_get(item, attr_flags, &attr)) { + flags = attr.u.num; + } /* add length for holes */ item_attr_rewind(item); while(item_attr_get(item, attr_poly_hole, &attr)) { @@ -1464,6 +1471,7 @@ static void display_add(struct hash_entry *entry, struct item *item, int count, p+=sizeof(*di)+count*sizeof(*c); di->item=*item; di->z_order=0; + di->flags=flags; di->holes=NULL; if(hole_count > 0) { di->holes = display_add_holes(item, hole_count, &p); @@ -1539,34 +1547,101 @@ static void label_line(struct graphics *gra, struct graphics_gc *fg, struct grap } } -static void display_draw_arrow(struct point *p, int dx, int dy, int l, struct graphics_gc *gc, struct graphics *gra) { - struct point pnt[3]; +static void display_draw_arrow(struct point *p, navit_float dx, navit_float dy, navit_float width, + struct display_context *dc, + struct graphics *gra, int filled) { + struct point pnt[4]; + /* half the width in every direction */ + width /= 2; pnt[0]=pnt[1]=pnt[2]=*p; - pnt[0].x+=-dx*l/65536+dy*l/65536; - pnt[0].y+=-dy*l/65536-dx*l/65536; - pnt[2].x+=-dx*l/65536-dy*l/65536; - pnt[2].y+=-dy*l/65536+dx*l/65536; - graphics_draw_lines(gra, gc, pnt, 3); + pnt[0].x+=-dx*width+dy*width; + pnt[0].y+=-dy*width-dx*width; + pnt[2].x+=-dx*width-dy*width; + pnt[2].y+=-dy*width+dx*width; + if(filled) { + /* close the loop */ + pnt[3]=pnt[0]; + graphics_draw_polygon(gra, dc->gc, pnt, 4); + } else { + graphics_draw_lines(gra, dc->gc, pnt, 3); + } + } -static void display_draw_arrows(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count) { - int i,dx,dy,l; +/** + * @brief draw arrows along a multi polygon line + * + * This function draws arrows along a multi polygon line, and scales the + * arrows according to current view settings by interpolating sizes at + * given arrow position, + * + * @param gra current graphics instance handle + * @param dc current drawing context + * @param pnt array of points for this polyline + * @param count number of points in pnt + * @param width arrray of integers giving the expexted line width at the corresponding point + * @param filled. True to draw filled arrows, false to draw only line arrows. + */ +static void display_draw_arrows(struct graphics *gra, struct display_context *dc, struct point *pnt, int count, + int *width, int filled) { + navit_float dx,dy,dw,l; + int i; struct point p; + int w; for (i = 0 ; i < count-1 ; i++) { + /* get the X and Y size */ dx=pnt[i+1].x-pnt[i].x; dy=pnt[i+1].y-pnt[i].y; - l=sqrt(dx*dx+dy*dy); + dw=width[i+1] - width[i]; + /* calculate the length of the way segment */ + l=navit_sqrt(dx*dx+dy*dy); if (l) { - dx=dx*65536/l; - dy=dy*65536/l; - p=pnt[i]; - p.x+=dx*15/65536; - p.y+=dy*15/65536; - display_draw_arrow(&p, dx, dy, 10, gc, gra); - p=pnt[i+1]; - p.x-=dx*15/65536; - p.y-=dy*15/65536; - display_draw_arrow(&p, dx, dy, 10, gc, gra); + /* length is not zero */ + /* calculate the vector per length */ + dx=dx/l; + dy=dy/l; + dw=dw/l; + /* different behaviour for oneway arrows than for routing graph ones */ + if(filled) { + if(l > (2*width[i])) { + /* print arrow at middle point */ + p=pnt[i]; + p.x+=dx*(l/2); + p.y+=dy*(l/2); + w=width[i]; + w+=dw*(l/2); + display_draw_arrow(&p, dx, dy, w, dc, gra, filled); + } + /* if line is quite long, print arrows at 1/4 and 3/4 length */ + if(l > (20*width[i])) { + /* at 1/4 the line length */ + p=pnt[i]; + p.x+=dx*(l/4); + p.y+=dy*(l/4); + w=width[i]; + w+=dw*(l/4); + display_draw_arrow(&p, dx, dy, w, dc, gra, filled); + /* at 3/4 the arrow length */ + p=pnt[i+1]; + p.x-=dx*(l/4); + p.y-=dy*(l/4); + w=width[i+1]; + w-=dw*(l/4); + display_draw_arrow(&p, dx, dy, w, dc, gra, filled); + } + } else { + /*FIXME: what if line length was smaller than 15?*/ + /* print arrow 15 units from start */ + p=pnt[i]; + p.x+=dx*15; + p.y+=dy*15; + display_draw_arrow(&p, dx, dy, 20, dc, gra, filled); + /* print arrow 15 units before end */ + p=pnt[i+1]; + p.x-=dx*15; + p.y-=dy*15; + display_draw_arrow(&p, dx, dy, 20, dc, gra, filled); + } } } } @@ -2600,11 +2675,20 @@ static inline void displayitem_draw_text(struct displayitem *di,struct display_c } static inline void displayitem_draw_icon(struct displayitem *di,struct display_context *dc, struct element * e, - struct graphics * gra, struct point * pa, int count) { + struct graphics * gra, struct point * pa, int count, struct layout * l) { if (count) { struct graphics_image *img=dc->img; if (!img || item_is_custom_poi(di->item)) { + int icon_width = e->u.icon.width; + int icon_height = e->u.icon.height; char *path; + /* get the standard icon size out of the layout if unset */ + if(l != NULL) { + if(icon_height==-1) + icon_height=l->icon_h; + if(icon_width==-1) + icon_width=l->icon_w; + } if (item_is_custom_poi(di->item)) { char *icon; char *src; @@ -2618,7 +2702,7 @@ static inline void displayitem_draw_icon(struct displayitem *di,struct display_c g_free(icon); } else path=graphics_icon_path(e->u.icon.src); - img=graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation); + img=graphics_image_new_scaled_rotated(gra, path, icon_width, icon_height, e->u.icon.rotation); if (img) dc->img=img; else @@ -2657,15 +2741,16 @@ static inline void displayitem_draw_image (struct displayitem *di, struct displa * This function will invoke the appropriate draw primitive depending on the type of the element to draw * * @brief di The displayitem to draw - * @brief dummy Unused + * @brief l current layout for getting defaults and underground alpha * @brief dc The display_context to use to draw items */ -static void displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc) { +static void displayitem_draw(struct displayitem *di, struct layout *l, struct display_context *dc) { int *width=g_alloca(sizeof(int)*dc->maxlen); int limit=0; struct point *pa=g_alloca(sizeof(struct point)*dc->maxlen); struct graphics *gra=dc->gra; struct element *e=dc->e; + int draw_underground=0; while (di) { int count=di->count,mindist=dc->mindist; @@ -2674,10 +2759,33 @@ static void displayitem_draw(struct displayitem *di, void *dummy, struct display di->z_order=++(gra->current_z_order); + /* Skip elements that are to be drawn on oneway streets only + * if street is not oneway or roundabout */ + if((e->oneway) && ((!(di->flags & AF_ONEWAY)) || (di->flags & AF_ROUNDABOUT))) { + di=di->next; + continue; + } + if (! dc->gc) { struct graphics_gc * gc=graphics_gc_new(gra); - graphics_gc_set_foreground(gc, &e->color); dc->gc=gc; + graphics_gc_set_foreground(dc->gc, &e->color); + } + + /* If the element id flagged AF_UNDERGROUND, we apply predefined transparenc to it if + * it's not the text. */ + if((di->flags & AF_UNDERGROUND) && (dc->e->type != element_text)) { + if(!draw_underground) { + struct color fg_color = e->color; + fg_color.a= (l != NULL) ? l->underground_alpha: UNDERGROUND_ALPHA_; + graphics_gc_set_foreground(dc->gc, &fg_color); + draw_underground=1; + } + } else { + if(draw_underground) { + graphics_gc_set_foreground(dc->gc, &e->color); + draw_underground=0; + } } if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text)) @@ -2691,6 +2799,8 @@ static void displayitem_draw(struct displayitem *di, void *dummy, struct display mindist=0; if (dc->e->type == element_polyline) count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width); + else if (dc->e->type == element_arrows) + count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.arrows.width, width); else count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL); switch (e->type) { @@ -2707,13 +2817,13 @@ static void displayitem_draw(struct displayitem *di, void *dummy, struct display displayitem_draw_text(di, dc, e, gra, pa, count, &t_holes); break; case element_icon: - displayitem_draw_icon(di, dc, e, gra, pa, count); + displayitem_draw_icon(di, dc, e, gra, pa, count, l); break; case element_image: displayitem_draw_image (di, dc, gra, pa, count); break; case element_arrows: - display_draw_arrows(gra,dc->gc,pa,count); + display_draw_arrows(gra,dc,pa,count, width, e->oneway); break; default: dbg(lvl_error, "Unhandled element type %d", e->type); @@ -2731,7 +2841,8 @@ static void displayitem_draw(struct displayitem *di, void *dummy, struct display * @returns <> * @author Martin Schaller (04/2008) */ -static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm) { +static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, + struct layout * l) { struct element *e; GList *es,*types; struct display_context *dc=&display_list->dc; @@ -2746,7 +2857,7 @@ static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *dis dc->type=GPOINTER_TO_INT(types->data); entry=get_hash_entry(display_list, dc->type); if (entry && entry->di) { - displayitem_draw(entry->di, NULL, dc); + displayitem_draw(entry->di, l, dc); display_context_free(dc); } types=g_list_next(types); @@ -2806,7 +2917,8 @@ void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct tra * @returns <> * @author Martin Schaller (04/2008) */ -static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order) { +static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order, + struct layout * l) { GList *itms; struct itemgra *itm; @@ -2814,7 +2926,7 @@ static void xdisplay_draw_layer(struct displaylist *display_list, struct graphic while (itms) { itm=itms->data; if (order >= itm->order.min && order <= itm->order.max) - xdisplay_draw_elements(gra, display_list, itm); + xdisplay_draw_elements(gra, display_list, itm, l); itms=g_list_next(itms); } } @@ -2837,7 +2949,7 @@ static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra if (lay->active) { if (lay->ref) lay=lay->ref; - xdisplay_draw_layer(display_list, gra, lay, order); + xdisplay_draw_layer(display_list, gra, lay, order, l); } lays=g_list_next(lays); } diff --git a/navit/layout.c b/navit/layout.c index f2f3d1a75..65e4b7265 100644 --- a/navit/layout.c +++ b/navit/layout.c @@ -39,7 +39,9 @@ layout_new(struct attr *parent, struct attr **attrs) { struct layout *l; struct navit *navit; struct color def_color = {COLOR_BACKGROUND_}; - struct attr *name_attr,*color_attr,*order_delta_attr,*font_attr,*day_attr,*night_attr,*active_attr; + int def_underground_alpha = UNDERGROUND_ALPHA_; + struct attr *name_attr,*color_attr,*order_delta_attr,*font_attr,*day_attr,*night_attr,*active_attr, + *underground_alpha_attr,*icon_attr; if (! (name_attr=attr_search(attrs, NULL, attr_name))) return NULL; @@ -67,6 +69,21 @@ layout_new(struct attr *parent, struct attr **attrs) { l->color = *color_attr->u.color; else l->color = def_color; + if ((underground_alpha_attr=attr_search(attrs, NULL, attr_underground_alpha))) { + int a = underground_alpha_attr->u.num; + /* for convenience, the alpha value is just 8 bit as usual if using + * corresponding attr. therefore we need to shift that up */ + l->underground_alpha = (a << 8) | a; + } else + l->underground_alpha = def_underground_alpha; + if ((icon_attr=attr_search(attrs, NULL, attr_icon_w))) + l->icon_w = icon_attr->u.num; + else + l->icon_w = -1; + if ((icon_attr=attr_search(attrs, NULL, attr_icon_h))) + l->icon_h = icon_attr->u.num; + else + l->icon_h = -1; if ((order_delta_attr=attr_search(attrs, NULL, attr_order_delta))) l->order_delta=order_delta_attr->u.num; if ((active_attr=attr_search(attrs, NULL, attr_active))) @@ -389,6 +406,13 @@ int itemgra_add_attr(struct itemgra *itemgra, struct attr *attr) { } } +static void element_set_oneway(struct element *e, struct attr **attrs) { + struct attr *oneway; + oneway=attr_search(attrs, NULL, attr_oneway); + if (oneway) + e->oneway=oneway->u.num; +} + static void element_set_color(struct element *e, struct attr **attrs) { struct attr *color; color=attr_search(attrs, NULL, attr_color); @@ -412,6 +436,15 @@ static void element_set_text_size(struct element *e, struct attr **attrs) { e->text_size=text_size->u.num; } +static void element_set_arrows_width(struct element *e, struct attr **attrs) { + struct attr *width; + width=attr_search(attrs, NULL, attr_width); + if (width) + e->u.arrows.width=width->u.num; + else + e->u.arrows.width=10; +} + static void element_set_polyline_width(struct element *e, struct attr **attrs) { struct attr *width; width=attr_search(attrs, NULL, attr_width); @@ -468,6 +501,7 @@ polygon_new(struct attr *parent, struct attr **attrs) { e = g_new0(struct element, 1); e->type=element_polygon; element_set_color(e, attrs); + element_set_oneway(e, attrs); return (struct polygon *)e; } @@ -479,6 +513,7 @@ polyline_new(struct attr *parent, struct attr **attrs) { e = g_new0(struct element, 1); e->type=element_polyline; element_set_color(e, attrs); + element_set_oneway(e, attrs); element_set_polyline_width(e, attrs); element_set_polyline_directed(e, attrs); element_set_polyline_dash(e, attrs); @@ -498,6 +533,7 @@ circle_new(struct attr *parent, struct attr **attrs) { e->u.circle.background_color = color_white; element_set_color(e, attrs); element_set_background_color(&e->u.circle.background_color, attrs); + element_set_oneway(e, attrs); element_set_text_size(e, attrs); element_set_circle_width(e, attrs); element_set_circle_radius(e, attrs); @@ -518,6 +554,7 @@ text_new(struct attr *parent, struct attr **attrs) { e->u.text.background_color = color_white; element_set_color(e, attrs); element_set_background_color(&e->u.text.background_color, attrs); + element_set_oneway(e, attrs); return (struct text *)e; } @@ -572,6 +609,8 @@ arrows_new(struct attr *parent, struct attr **attrs) { e = g_malloc0(sizeof(*e)); e->type=element_arrows; element_set_color(e, attrs); + element_set_oneway(e, attrs); + element_set_arrows_width(e, attrs); return (struct arrows *)e; } diff --git a/navit/layout.h b/navit/layout.h index 700e6245a..8b8a63194 100644 --- a/navit/layout.h +++ b/navit/layout.h @@ -37,6 +37,7 @@ struct element { enum { element_point, element_polyline, element_polygon, element_circle, element_text, element_icon, element_image, element_arrows } type; struct color color; int text_size; + int oneway; union { struct element_point { char stub; @@ -67,6 +68,9 @@ struct element { struct element_text { struct color background_color; } text; + struct element_arrows { + int width; + } arrows; } u; int coord_count; struct coord *coord; @@ -105,6 +109,9 @@ struct layout { char* nightname; char *font; struct color color; + int underground_alpha; + int icon_w; + int icon_h; GList *layers; GList *cursors; int order_delta; diff --git a/navit/navit_layout_bike_shipped.xml b/navit/navit_layout_bike_shipped.xml index dd5a9943a..ae30093dd 100644 --- a/navit/navit_layout_bike_shipped.xml +++ b/navit/navit_layout_bike_shipped.xml @@ -1,5 +1,5 @@ - + diff --git a/navit/navit_layout_car_android_shipped.xml b/navit/navit_layout_car_android_shipped.xml index 046d52d37..256ab3db2 100644 --- a/navit/navit_layout_car_android_shipped.xml +++ b/navit/navit_layout_car_android_shipped.xml @@ -1,5 +1,5 @@ - + diff --git a/navit/navit_layout_car_dark_shipped.xml b/navit/navit_layout_car_dark_shipped.xml index b24978a57..61407837c 100644 --- a/navit/navit_layout_car_dark_shipped.xml +++ b/navit/navit_layout_car_dark_shipped.xml @@ -1,5 +1,5 @@ - + diff --git a/navit/navit_layout_car_shipped.xml b/navit/navit_layout_car_shipped.xml index e772ab9f4..1098e7fe7 100644 --- a/navit/navit_layout_car_shipped.xml +++ b/navit/navit_layout_car_shipped.xml @@ -1,5 +1,5 @@ - + @@ -787,22 +787,27 @@ + + + + + @@ -823,22 +828,27 @@ + + + + + @@ -855,18 +865,22 @@ + + + + @@ -887,22 +901,27 @@ + + + + + @@ -930,22 +949,27 @@ + + + + + @@ -974,22 +998,27 @@ + + + + + @@ -1021,22 +1050,27 @@ + + + + + @@ -1093,11 +1127,13 @@ + + diff --git a/navit/navit_layout_car_simple_shipped.xml b/navit/navit_layout_car_simple_shipped.xml index 4029833f5..82d730a6e 100644 --- a/navit/navit_layout_car_simple_shipped.xml +++ b/navit/navit_layout_car_simple_shipped.xml @@ -1,5 +1,5 @@ - + diff --git a/navit/navit_layout_th_shipped.xml b/navit/navit_layout_th_shipped.xml index aebc79d6e..bf4ad6731 100644 --- a/navit/navit_layout_th_shipped.xml +++ b/navit/navit_layout_th_shipped.xml @@ -1,5 +1,5 @@ - + diff --git a/navit/xslt/sailfish_svg.xslt b/navit/xslt/sailfish_svg.xslt index 7203ed34d..63d384a5a 100644 --- a/navit/xslt/sailfish_svg.xslt +++ b/navit/xslt/sailfish_svg.xslt @@ -12,6 +12,17 @@ + + + + + 16 + 16 + 0x33 + + + + @@ -21,12 +32,6 @@ - - 15 - - - 15 - -- cgit v1.2.1