summaryrefslogtreecommitdiff
path: root/navit
diff options
context:
space:
mode:
Diffstat (limited to 'navit')
-rw-r--r--navit/graphics.c38
-rw-r--r--navit/gui/internal/gui_internal.c2
-rw-r--r--navit/navit.c10
-rw-r--r--navit/transform.c20
-rw-r--r--navit/transform.h5
5 files changed, 54 insertions, 21 deletions
diff --git a/navit/graphics.c b/navit/graphics.c
index 2c7cd49ff..aabe9b7bc 100644
--- a/navit/graphics.c
+++ b/navit/graphics.c
@@ -2691,15 +2691,26 @@ static inline void displayitem_transform_holes(struct transformation *trans, enu
out->ccount=NULL;
out->coords=NULL;
if((in != NULL) && (in->count > 0)) {
- int a;
+ int a, transform_res;
/* alloc space for hole conversion. To be freed with displayitem_free_holes later*/
out->count = in->count;
out->ccount = g_malloc0(sizeof(*(out->ccount)) * in->count);
out->coords = g_malloc0(sizeof(*(out->coords)) * in->count);
for(a = 0; a < in->count; a ++) {
+ int buf_size=sizeof(*(out->coords[a])) * in->ccount[a];
in->ccount[a]=limit_count(in->coords[a], in->ccount[a]);
- out->coords[a]=g_malloc0(sizeof(*(out->coords[a])) * in->ccount[a]);
- out->ccount[a]=transform(trans, pro, in->coords[a], (struct point *)(out->coords[a]), in->ccount[a], mindist, 0, NULL);
+ out->coords[a]=g_malloc0(buf_size);
+ transform_res=transform_point_buf(trans, pro, in->coords[a], (struct point *)(out->coords[a]), buf_size, in->ccount[a],
+ mindist, 0, NULL);
+ /* if we did not have enough buf space for transfrom_point_buf, we try again with double the buffer size,
+ until we succeed. */
+ while (transform_res == TRANSFORM_ERR_BUF_SPACE) {
+ buf_size *= 2;
+ out->coords[a] = g_realloc(out->coords[a], buf_size);
+ transform_res=transform_point_buf(trans, pro, in->coords[a], (struct point *)(out->coords[a]), buf_size,
+ in->ccount[a], mindist, 0, NULL);
+ }
+ out->ccount[a] = transform_res;
}
}
}
@@ -2883,13 +2894,14 @@ static void displayitem_draw(struct displayitem *di, struct layout *l, struct di
struct graphics *gra=dc->gra;
struct element *e=dc->e;
int draw_underground=0;
+ long pa_buf_size=sizeof(struct point)*dc->maxlen;
if (dc->maxlen < ALLOCA_COORD_LIMIT) {
width=g_alloca(sizeof(int)*dc->maxlen);
- pa=g_alloca(sizeof(struct point)*dc->maxlen);
+ pa=g_alloca(pa_buf_size);
} else {
width=g_malloc(sizeof(int)*dc->maxlen);
- pa=g_malloc(sizeof(struct point)*dc->maxlen);
+ pa=g_malloc(pa_buf_size);
}
while (di) {
@@ -2937,11 +2949,13 @@ static void displayitem_draw(struct displayitem *di, struct layout *l, struct di
if (dc->type == type_poly_water_tiled)
mindist=0;
if (dc->e->type == element_polyline)
- count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
+ count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, 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);
+ count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, count, mindist, e->u.arrows.width,
+ width);
else
- count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
+ count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, count, mindist, 0, NULL);
switch (e->type) {
case element_polygon:
displayitem_draw_polygon(dc, gra, pa, count, &t_holes);
@@ -3699,13 +3713,15 @@ int graphics_displayitem_within_dist(struct displaylist *displaylist, struct dis
int result;
struct point *pa;
int count;
+ long pa_buf_size=sizeof(struct point)*displaylist->dc.maxlen;
+
if (displaylist->dc.maxlen < ALLOCA_COORD_LIMIT) {
- pa=g_alloca(sizeof(struct point)*displaylist->dc.maxlen);
+ pa=g_alloca(pa_buf_size);
} else {
- pa=g_malloc(sizeof(struct point)*displaylist->dc.maxlen);
+ pa=g_malloc(pa_buf_size);
}
- count=transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 0, 0, NULL);
+ count=transform_point_buf(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, pa_buf_size, di->count, 0, 0, NULL);
if (di->item.type < type_line) {
result = within_dist_point(p, &pa[0], dist);
diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c
index bb28c2e84..505432da9 100644
--- a/navit/gui/internal/gui_internal.c
+++ b/navit/gui/internal/gui_internal.c
@@ -1235,7 +1235,7 @@ void gui_internal_cmd_position_do(struct gui_priv *this, struct pcoord *pc_in, s
c.y=pc.y;
trans=navit_get_trans(this->nav);
- transform(trans,pc.pro,&c,&p,1,0,0,0);
+ transform_point(trans,pc.pro,&c,&p);
display=navit_get_displaylist(this->nav);
dlh=graphics_displaylist_open(display);
sel=displaylist_get_selection(display);
diff --git a/navit/navit.c b/navit/navit.c
index 14087c4ed..fc1c973a0 100644
--- a/navit/navit.c
+++ b/navit/navit.c
@@ -779,7 +779,7 @@ static void navit_autozoom(struct navit *this_, struct coord *center, int speed,
distance = speed * this_->autozoom_secs;
transform_get_size(this_->trans, &w, &h);
- transform(this_->trans, transform_get_projection(this_->trans), center, &pc, 1, 0, 0, NULL);
+ transform_point(this_->trans, transform_get_projection(this_->trans), center, &pc);
scale = transform_get_scale(this_->trans);
/* We make sure that the point we want to see is within a certain range
@@ -2277,8 +2277,8 @@ void navit_zoom_to_rect(struct navit *this_, struct coord_rect *r) {
struct point p1,p2;
transform_set_scale(this_->trans, scale);
transform_setup_source_rect(this_->trans);
- transform(this_->trans, transform_get_projection(this_->trans), &r->lu, &p1, 1, 0, 0, NULL);
- transform(this_->trans, transform_get_projection(this_->trans), &r->rl, &p2, 1, 0, 0, NULL);
+ transform_point(this_->trans, transform_get_projection(this_->trans), &r->lu, &p1);
+ transform_point(this_->trans, transform_get_projection(this_->trans), &r->rl, &p2);
dbg(lvl_debug,"%d,%d-%d,%d",p1.x,p1.y,p2.x,p2.y);
if (p1.x < 0 || p2.x < 0 || p1.x > w || p2.x > w ||
p1.y < 0 || p2.y < 0 || p1.y > h || p2.y > h)
@@ -3224,7 +3224,7 @@ static void navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, st
pro=transform_get_projection(this_->trans_cursor);
if (!pro)
return;
- transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
+ transform_point(this_->trans_cursor, pro, &nv->coord, &cursor_pnt);
}
vehicle_draw(nv->vehicle, this_->gra, &cursor_pnt, nv->dir-transform_get_yaw(this_->trans_cursor), nv->speed);
}
@@ -3309,7 +3309,7 @@ static void navit_vehicle_update_position(struct navit *this_, struct navit_vehi
if (this_->gui && nv->speed > 2)
navit_disable_suspend();
- transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
+ transform_point(this_->trans_cursor, pro, &nv->coord, &cursor_pnt);
if (this_->button_pressed != 1 && this_->follow_cursor && nv->follow_curr <= nv->follow &&
(nv->follow_curr == 1 || !transform_within_border(this_->trans_cursor, &cursor_pnt, this_->border)))
navit_set_center_cursor_draw(this_);
diff --git a/navit/transform.c b/navit/transform.c
index 771037f8c..0221c3070 100644
--- a/navit/transform.c
+++ b/navit/transform.c
@@ -545,14 +545,21 @@ static struct z_clip_result transform_z_clip_if_necessary(struct coord_3d coord,
return clip_result;
}
-int transform(struct transformation *t, enum projection required_projection, struct coord *input,
- struct point *result, int count, int mindist, int width, int *width_result) {
+int transform_point(struct transformation *t, enum projection required_projection, struct coord *input,
+ struct point *result) {
+ return transform_point_buf(t, required_projection, input, result, sizeof(struct point), 1, 0, 0, NULL);
+}
+
+int transform_point_buf(struct transformation *t, enum projection required_projection, struct coord *input,
+ struct point *result, long result_size, int count, int mindist, int width, int *width_result) {
struct coord projected_coord, shifted_coord;
struct coord_3d rotated_coord;
struct point screen_point;
int zlimit=t->znear;
struct z_clip_result clip_result, clip_result_old= {{0,0}, -1, 0, 0};
int i,result_idx = 0,result_idx_last=0;
+ long max_results = result_size / sizeof(struct point);
+
dbg(lvl_debug,"count=%d", count);
for (i=0; i < count; i++) {
dbg(lvl_debug, "input coord %d: (%d, %d)", i, input[i].x, input[i].y);
@@ -570,7 +577,14 @@ int transform(struct transformation *t, enum projection required_projection, str
clip_result=transform_z_clip_if_necessary(rotated_coord, zlimit, clip_result_old);
clip_result_old=clip_result;
if(clip_result.process_coord_again) {
- i--;
+ /* if we repeat an interation, we have to make sure that there is enough space in the result buffer to
+ not overflow. */
+ if (result_idx + 1 < max_results) {
+ i--;
+ } else {
+ dbg(lvl_debug, "Not enough space in buf for transform_point_buf");
+ return TRANSFORM_ERR_BUF_SPACE;
+ }
} else if (clip_result.skip_coord) {
continue;
}
diff --git a/navit/transform.h b/navit/transform.h
index dab69fd47..e492882a0 100644
--- a/navit/transform.h
+++ b/navit/transform.h
@@ -25,6 +25,8 @@ extern "C" {
#endif
#include "coord.h"
+#define TRANSFORM_ERR_BUF_SPACE -1
+
/* prototypes */
enum attr_type;
enum item_type;
@@ -55,7 +57,8 @@ void transform_geo_to_cart(struct coord_geo *geo, navit_float a, navit_float b,
void transform_cart_to_geo(struct coord_geo_cart *cart, navit_float a, navit_float b, struct coord_geo *geo);
void transform_utm_to_geo(const double UTMEasting, const double UTMNorthing, int ZoneNumber, int NorthernHemisphere, struct coord_geo *geo);
void transform_datum(struct coord_geo *from, enum map_datum from_datum, struct coord_geo *to, enum map_datum to_datum);
-int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int mindist, int width, int *width_return);
+int transform_point(struct transformation *t, enum projection pro, struct coord *c, struct point *p);
+int transform_point_buf(struct transformation *t, enum projection pro, struct coord *c, struct point *p, long result_size, int count, int mindist, int width, int *width_return);
int transform_reverse(struct transformation *t, struct point *p, struct coord *c);
double transform_pixels_to_map_distance(struct transformation *transformation, int pixels);
enum projection transform_get_projection(struct transformation *this_);