/* draw.c * Copyright (C) Steffen Pohle 2010 * * main.c is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * main.c is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include "osmroute.h" #include "draw.h" #include "map.h" #include "system.h" #include "gui.h" #include "vector.h" #include "memoryleak.h" /************************************************************************** * color definitions, hopfully this can go out soon, need to find a way to * specify only the rgb values like it is in HTML and thats it. * i.e. color = 0xFF0000; for red. */ struct line_style draw_linestyle[MWAY_MAX]; struct color color_polygon[MAREA_MAX]; struct color color_bg; struct color color_fg; struct color color[COLOR_MAX][COLOR_steps]; /************************************************************************** * current screen data, center of the screen? where we look at the scale, * and the drawing flags. All these values start with view_* */ float view_scale = 0.001; float view_lon = 11.183; float view_lat = 48.736; int view_flags = DRAW_GPSFOLLOW; /************************************************************************** * internal variables set by some functions within the drawing stuff and * from withing the *_gfx sources.. Some drawing functon will have vriables * declared on top of the first function. (i.E. drawing lines, polygones. */ int draw_type[MAREA_MAX+MWAY_MAX]; /* * selection variables */ struct map_pos select_pos; int select_enabled = 0; char statusline_text[255] = ""; int statusline_progress = 0; void draw_line (struct image *img, int x1, int y1, int x2, int y2, struct line_style style); void draw_lineway (struct image *img, int x1, int y1, int x2, int y2, struct line_style style); void draw_rectangle (struct image *img, int x1, int y1, int x2, int y2, struct line_style style); /************************************************************************* * to prevent the flickering screen, we create two images inside the * memory. One which keeps a larger area of the map (so we only draw * the map once in a while) and a second map with the on screen data. * img_map: keeps the current map screen values. * img_screen: is the final data with the on screen data to copy on * the screen. */ struct image *img_map = NULL; // image data of the current map struct map_pos img_map_pos; // position of the current map float img_map_scale; // scale of the current map /************************************************************************** * * functions to convert between geo data and screen data * */ iPoint draw_geo2screen (float center_lon, float center_lat, float lon, float lat) { iPoint r; r.x = - (map_lon2km (center_lon - lon, lat) / view_scale); r.y = (map_lat2km (center_lat - lat) / view_scale); return r; }; void draw_screen2geo (int x, int y, float *lon, float *lat) { y = y - gfx_screensize.y/2; x = x - gfx_screensize.x/2; *lat = -map_km2lat(((float)y) * view_scale); *lon = map_km2lon(((float)x) * view_scale, view_lat + *lat); *lat = view_lat + *lat; *lon = view_lon + *lon; }; /****************************************************************************** * set the new scale, and check what will have to be shown */ void draw_setscale (int newscale) { float scale = view_scale; if (newscale < 0) { scale = scale / 1.5; } else { scale = scale * 1.5; } d_printf ("scale: %f -> %f (i:%d)", view_scale, scale, newscale); draw_setscalef (scale); }; void draw_setscalef (float newscale) { int i; view_scale = newscale; if (view_scale < 0.001) view_scale = 0.001; else if (view_scale > 0.5) view_scale = 0.5; /* change display settings */ if (view_scale < 0.01) { for (i = 0; i < MWAY_MAX+MAREA_MAX; i++) draw_type [i] = TRUE; } else if (view_scale < 0.1) { for (i = 0; i < MWAY_MAX+MAREA_MAX; i++) { switch (i) { case (MWAY_tertiary): case (MWAY_highway): case (MWAY_MAX + MAREA_greenfield): case (MWAY_MAX + MAREA_water): case (MWAY_MAX + MAREA_industrial): case (MWAY_MAX + MAREA_residential): draw_type [i] = TRUE; break; default: draw_type [i] = FALSE; } } } else { for (i = 0; i < MWAY_MAX+MAREA_MAX; i++) { switch (i) { case (MWAY_highway): case (MWAY_MAX + MAREA_greenfield): case (MWAY_MAX + MAREA_wood): case (MWAY_MAX + MAREA_water): case (MWAY_MAX + MAREA_residential): draw_type [i] = TRUE; break; default: draw_type [i] = FALSE; } } } main_wnd_update(); }; void draw_set_flag (int flag) { view_flags |= flag; }; void draw_del_flag (int flag) { view_flags &= (0xFFFF - flag); }; /**************************************************************************+ * drawing initial functions */ void draw_init () { int n; d_printf ("draw_init"); draw_init_color (); for (n = 0; n < MAREA_MAX; n++) draw_type[n] = 1; view_lon = cfg.last_lon; view_lat = cfg.last_lat; view_scale = cfg.last_scale; }; void draw_init_color () { int n, i, r,g,b; d_printf ("draw_init_color"); for (n = 0; n < COLOR_MAX; n++) for (i = COLOR_steps-1; i >= 0; i--) { if (i == COLOR_steps-1) { if (n == COLOR_white) gfx_color_alloc (&color[n][i], 0xFFFF, 0xFFFF, 0xFFFF); else if (n == COLOR_red) gfx_color_alloc (&color[n][i], 0xFFFF, 0x0, 0x0); else if (n == COLOR_redgray) gfx_color_alloc (&color[n][i], 0xFFFF, 0xA000, 0xA000); else if (n == COLOR_blue) gfx_color_alloc (&color[n][i], 0x0, 0x0, 0xFFFF); else if (n == COLOR_bluegray) gfx_color_alloc (&color[n][i], 0xA000, 0xA000, 0xFFFF); else if (n == COLOR_green) gfx_color_alloc (&color[n][i], 0x0, 0xFFFF, 0x0); else if (n == COLOR_greengray) gfx_color_alloc (&color[n][i], 0xA000, 0xFFFF, 0xA000); else if (n == COLOR_brown) gfx_color_alloc (&color[n][i], 0xFFFF, 0x8000, 0x0); else if (n == COLOR_pink) gfx_color_alloc (&color[n][i], 0xFFFF, 0x0, 0xFFFF); else if (n == COLOR_yellow) gfx_color_alloc (&color[n][i], 0xFFFF, 0xFFFF, 0x0000); else { d_printf ("%s:%d not all colors have been defined..", __FILE__, __LINE__); exit (1); } } else { r = color[n][COLOR_steps-1].r; g = color[n][COLOR_steps-1].g; b = color[n][COLOR_steps-1].b; if (n == COLOR_white) { if (i == 0) { r = g = b = 0; } else { r = r*(i)/COLOR_steps-1; g = g*(i)/COLOR_steps-1; b = b*(i)/COLOR_steps-1; } } else { r = r*(i+1)/COLOR_steps; g = g*(i+1)/COLOR_steps; b = b*(i+1)/COLOR_steps; } gfx_color_alloc (&color[n][i], r, g, b); } gfx_color_alloc (&color_bg, 0,0,0); // background gfx_color_alloc (&color_fg, 0x8000,0x8000,0x8000); // foreground } for (n = 0; n < MWAY_MAX; n++) { draw_linestyle[n].width = 0.0; gfx_color_alloc (&draw_linestyle[n].borderc, 0x8000, 0x8000,0x8000); switch (n) { case (MWAY_highway): draw_linestyle[n].width = 4.0; gfx_color_alloc (&draw_linestyle[n].c, 0xFFFF,0xFFFF,0x8000); break; case (MWAY_tertiary): draw_linestyle[n].width = 3.0; gfx_color_alloc (&draw_linestyle[n].c, 0xA000,0xA000,0x0000); break; case (MWAY_residential): draw_linestyle[n].width = 2.0; gfx_color_alloc (&draw_linestyle[n].c, 0xA000,0xA000,0xA000); break; case (MWAY_cycleway): gfx_color_alloc (&draw_linestyle[n].c, 0x4000,0xA000,0x4000); break; case (MWAY_footway): gfx_color_alloc (&draw_linestyle[n].c, 0x4000,0x4000,0xA000); break; case (MWAY_railway): gfx_color_alloc (&draw_linestyle[n].c, 0x8000,0x8000,0x8000); break; case (MWAY_unknown_railway): gfx_color_alloc (&draw_linestyle[n].c, 0x6000,0x6000,0x6000); break; case (MWAY_service): gfx_color_alloc (&draw_linestyle[n].c, 0x6000,0x6000,0x6000); break; case (MWAY_unknown): case (MWAY_unknown_way): default: gfx_color_alloc (&draw_linestyle[n].c, 0x7000,0x5000,0x5000); break; } } for (n = 0; n < MAREA_MAX; n++) switch (n) { case (MAREA_water): gfx_color_alloc (&color_polygon[n], 0x4000,0x4000,0xFFFF); break; case (MAREA_greenfield): gfx_color_alloc (&color_polygon[n], 0x2000,0x8000,0x2000); break; case (MAREA_wood): gfx_color_alloc (&color_polygon[n], 0x0000,0x6000,0x0000); break; case (MAREA_land): gfx_color_alloc (&color_polygon[n], 0x6000,0x6000,0x0000); break; case (MAREA_residential): gfx_color_alloc (&color_polygon[n], 0x2000,0x2000,0x2000); break; case (MAREA_farm): gfx_color_alloc (&color_polygon[n], 0x8000,0x4000,0x2000); break; case (MAREA_industrial): gfx_color_alloc (&color_polygon[n], 0x8000,0x6000,0x8000); break; case (MAREA_commercial): gfx_color_alloc (&color_polygon[n], 0x8000,0x0000,0x8000); break; case (MAREA_military): gfx_color_alloc (&color_polygon[n], 0x2000,0x2000,0x2000); break; case (MAREA_building): gfx_color_alloc (&color_polygon[n], 0x6000,0x6000,0x6000); break; default: gfx_color_alloc (&color_polygon[n],0xFFFF,0x0000,0x0000); break; } }; /**************************************************************************+ * drawing subfunctions */ /* * rectangle */ void draw_rectangle (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) { gfx_draw_line (dimg, x1, y1, x2, y1, style); gfx_draw_line (dimg, x2, y1, x2, y2, style); gfx_draw_line (dimg, x2, y2, x1, y2, style); gfx_draw_line (dimg, x1, y2, x1, y1, style); }; /* * lines */ void draw_line (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) { int width, height; if (dimg == NULL) { width = gfx_screensize.x; height = gfx_screensize.y; } else { width = dimg->width; height = dimg->height; } if ((x1 >= 0 && x1 <= width && y1 >= 0 && y1 <= height) || (x2 >= 0 && x2 <= width && y2 >= 0 && y2 <= height) || (x1 <= 0 && x2 >= width) || (x2 <= 0 && x1 >= width) || (y1 <= 0 && y2 >= height) || (y2 <= 0 && y1 >= height)) gfx_draw_line (dimg, x1, y1, x2, y2, style); }; /* * draw a polygon.. */ static iPoint _polypoints[POLYGON_MAX_POINTS]; static int _polycnt; void draw_polygonstart () { _polycnt = 0; }; void draw_polygonadd (int x, int y) { if (_polycnt >= POLYGON_MAX_POINTS) { printf ("%s:%d draw_polygonadd: too many points.\n", __FILE__, __LINE__); return; } _polypoints[_polycnt].x = x; _polypoints[_polycnt].y = y; _polycnt++; }; void draw_polygonfinish (struct image *dimg, struct line_style ls, struct color c, int border) { int i; gfx_draw_polygon (dimg, _polypoints, _polycnt, ls, c); if (border) { for (i = 1; i < _polycnt; i++) { gfx_draw_line (dimg, _polypoints[i-1].x, _polypoints[i-1].y, _polypoints[i].x, _polypoints[i].y, ls); } gfx_draw_line (dimg, _polypoints[_polycnt-1].x, _polypoints[_polycnt-1].y, _polypoints[0].x, _polypoints[0].y, ls); } _polycnt = 0; }; void draw_lineway (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) { struct line_style tmplinestyle = style; if (view_scale < 0.01) tmplinestyle.width = tmplinestyle.width * (0.005/view_scale); draw_line (dimg, x1, y1, x2, y2, tmplinestyle); }; /************************************************************************ * the drawing stuff itself. * before drawing everything on the screen, check if we need to redraw * the map or just copy a part of it into the gui image. * After copying the map into the gui screen draw the gui, afterwards * copy the gui screen onto the display. */ void draw_map () { struct map_hash *mh; struct map_way *cway; struct map_area *carea; struct map_place *cplace; struct map_poi *cpoi; int w, n, i; struct map_hashpos h, hs, he; iPoint p1, p2; fPoint nd, v1, v2, v3; struct line_style tmplinestyle; iPoint center; struct map_pos hashstart, hashend; struct color *c; char text[255]; d_printf ("view_lon: %f view_lat:%f", view_lon, view_lat); gfx_clear (img_map, &color_bg); center.x = img_map->width / 2; center.y = img_map->height / 2; tmplinestyle.width = 1.0; tmplinestyle.c = tmplinestyle.borderc = color[COLOR_red][2]; hashstart.lat = view_lat - map_km2lat(view_scale * ((float)img_map->width)); hashstart.lon = view_lon - map_km2lon(view_scale * ((float)img_map->height), hashstart.lat); hashend.lat = view_lat + map_km2lat(view_scale * ((float)img_map->height)); hashend.lon = view_lon + map_km2lon(view_scale * ((float)img_map->width), hashend.lat); hs.ilon = map_geo2igeo (hashstart.lon); hs.ilat = map_geo2igeo (hashstart.lat); he.ilon = map_geo2igeo (hashend.lon); he.ilat = map_geo2igeo (hashend.lat); /* * draw areas */ for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD); else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE); if (mh) { carea = mh->areas; while (carea) { if (draw_type[carea->type + MWAY_MAX]) { draw_polygonstart (); for (n = 0; n < carea->p_cnt; n++) if (n == 0 || n == carea->p_cnt-1 || view_scale < 0.01 || ((view_scale < 0.1 && (n % 2) == 0) || carea->p_cnt < 5) || ((view_scale < 0.1 && (n % 4) == 0) || carea->p_cnt < 10)) { p1 = draw_geo2screen (view_lon, view_lat, carea->p[n].lon, carea->p[n].lat); draw_polygonadd (p1.x + center.x, p1.y + center.y); } draw_polygonfinish (img_map, tmplinestyle, color_polygon[carea->type], 0); } carea = carea->next; } } } /* * draw ways */ /* draw outside */ for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { /* * draw the hash.. */ if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD); else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE); if (mh) { /* * ways */ cway = mh->ways; while (cway) { if (cway->id != 0 && draw_type[cway->type]) { /* go through all the nodes */ tmplinestyle.width = draw_linestyle[cway->type].width * (0.005/view_scale) + 2; tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][1]; if (view_scale < 0.01) { for (n = 0; n < cway->p_cnt; n++) { p2 = p1; nd.x = map_lon2km (view_lon - cway->p[n].lon, cway->p[n].lat); nd.y = map_lat2km (view_lat - cway->p[n].lat); p1.x = center.x - (nd.x / view_scale); p1.y = center.y + (nd.y / view_scale); if (n > 0) draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle); } } else { for (n = -1; n < cway->n_cnt;) { /* find next node */ if (n == -1) { i = 0; n++; } else { for (n = 0, w = cway->p_cnt; n < cway->n_cnt; n++) { if (cway->n[n].pnr > i && cway->n[n].pnr < w) w = cway->n[n].pnr; } if (w == cway->p_cnt) i = cway->p_cnt - 1; else { i = w; n = 1; } } p2 = p1; nd.x = map_lon2km (view_lon - cway->p[i].lon, cway->p[i].lat); nd.y = map_lat2km (view_lat - cway->p[i].lat); p1.x = center.x - (nd.x / view_scale); p1.y = center.y + (nd.y / view_scale); if (n > 0) draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle); } } /* draw the waynodes */ for (n = 0; n < cway->n_cnt; n++) if (cway->n[n].pnr < cway->p_cnt) { p1 = draw_geo2screen (view_lon, view_lat, cway->n[n].d.lon, cway->n[n].d.lat); p2 = draw_geo2screen (view_lon, view_lat, cway->p[cway->n[n].pnr].lon, cway->p[cway->n[n].pnr].lat); p1.x += center.x; p1.y += center.y; p2.x += center.x; p2.y += center.y; draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle); } } cway = cway->next; } } } /* ways inside */ for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { /* * draw the hash.. */ if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD); else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE); if (mh) { /* * ways */ cway = mh->ways; while (cway) { if (cway->id != 0 && draw_type[cway->type] && (cway->flags & MWAY_F_planed) == 0) { /* go through all the nodes */ if (view_scale < 0.01) { for (n = 0; n < cway->p_cnt; n++) { p2 = p1; nd.x = map_lon2km (view_lon - cway->p[n].lon, cway->p[n].lat); nd.y = map_lat2km (view_lat - cway->p[n].lat); p1.x = center.x - (nd.x / view_scale); p1.y = center.y + (nd.y / view_scale); if (n > 0) { if (cway->type >= MWAY_MAX) draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]); else draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]); /* one way arrow */ if (cway->flags & MWAY_F_oneway && view_scale < 0.004) { tmplinestyle.width = 1; tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][0]; nd.x = (p1.x+p2.x)/2; nd.y = (p1.y+p2.y)/2; v1.x = p1.x-p2.x; v1.y = p1.y-p2.y; v1 = vec_one (v1); v2 = vec_turn90 (v1); v3 = vec_mirror (v2); v1 = vec_mul (v1, 3.0); v2 = vec_mul (v2, 3.0); v3 = vec_mul (v3, 3.0); v1 = vec_add (v1, nd); v2 = vec_add (v2, nd); v3 = vec_add (v3, nd); draw_line (img_map, v1.x, v1.y, v2.x, v2.y, tmplinestyle); draw_line (img_map, v1.x, v1.y, v3.x, v3.y, tmplinestyle); } } } } else { for (n = -1; n < cway->n_cnt;) { // d_printf ("LINE: %lld n_cnt:%d p_cnt:%d", cway->id, cway->n_cnt, cway->p_cnt); /* find next node */ if (n == -1) { i = 0; n++; } else { for (n = 0, w = cway->p_cnt; n < cway->n_cnt; n++) { if (cway->n[n].pnr > i && cway->n[n].pnr < w) w = cway->n[n].pnr; } if (w == cway->p_cnt) i = cway->p_cnt - 1; else { i = w; n = 1; } } // d_printf (" i:%d n:%d", i, n); p2 = p1; nd.x = map_lon2km (view_lon - cway->p[i].lon, cway->p[i].lat); nd.y = map_lat2km (view_lat - cway->p[i].lat); p1.x = center.x - (nd.x / view_scale); p1.y = center.y + (nd.y / view_scale); if (n > 0) { if (cway->type >= MWAY_MAX) draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]); else draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]); } } } /* draw the waynodes */ for (n = 0; n < cway->n_cnt; n++) if (cway->n[n].pnr < cway->p_cnt) { p1 = draw_geo2screen (view_lon, view_lat, cway->n[n].d.lon, cway->n[n].d.lat); p2 = draw_geo2screen (view_lon, view_lat, cway->p[cway->n[n].pnr].lon, cway->p[cway->n[n].pnr].lat); p1.x += center.x; p1.y += center.y; p2.x += center.x; p2.y += center.y; if (cway->type >= MWAY_MAX) draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]); else draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]); } else d_printf ("%s:%d wayid:%lld cway->n[n].pnr(%d) < cway->p_cnt(%d) doesn't match", __FILE__, __LINE__, cway->id, cway->n[n].pnr, cway->p_cnt); } cway = cway->next; } } } /* * draw places, pois just on top layers */ for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD); else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE); if (mh) { /* * places */ cplace = mh->places; i = 0; while (cplace) { if (view_scale < 0.01 || cplace->type == MAP_PLACE_city || cplace->type == MAP_PLACE_town || (cplace->type == MAP_PLACE_village && view_scale < 0.05)) { i++; p1 = draw_geo2screen(view_lon, view_lat, cplace->lon, cplace->lat); p1.x += center.x; p1.y += center.y; switch (cplace->type) { case (MAP_PLACE_city): case (MAP_PLACE_town): case (MAP_PLACE_village): gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_white][3]); break; case (MAP_PLACE_hamlet): case (MAP_PLACE_suburb): gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_bluegray][2]); break; default: gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_bluegray][2]); break; } } cplace = cplace->next; } /* * poi */ cpoi = mh->pois; i = 0; if (view_scale < 0.01) while (cpoi) { p1 = draw_geo2screen(view_lon, view_lat, cpoi->lon, cpoi->lat); p1.x += center.x; p1.y += center.y; if (cpoi->type != MAP_POI_unknown && ((view_scale < 0.01 && cpoi->type == MAP_POI_gasstation) || (view_scale < 0.0015))) { switch (cpoi->type) { case (MAP_POI_campsite): sprintf (text, "C"); c = &color[COLOR_greengray][3]; break; default: sprintf (text, "?"); c = &color[COLOR_red][3]; } gfx_draw_text (img_map, p1.x-4, p1.y-4, text, c); gfx_draw_text (img_map, p1.x-strlen(cpoi->name)*2, p1.y+8, cpoi->name, c); } cpoi = cpoi->next; } } } // tmplinestyle.width = 4.0; // tmplinestyle.c = tmplinestyle.borderc = color_red1; // draw_line (img_map, center.x-100, center.y, center.x+100, center.y, tmplinestyle); // draw_line (img_map, center.x, center.y-100, center.x, center.y+100, tmplinestyle); // draw_lines (img_map); // sprintf (text, "%f,%f", view_lon, view_lat); // gfx_img_draw_text (img_map, center.x,center.y, text, &color_blue1); /* * save data of the map drawed */ img_map_pos.lon = view_lon; img_map_pos.lat = view_lat; img_map_scale = view_scale; }; int draw_mapcopy () { iPoint p1, p2; p2 = draw_geo2screen (img_map_pos.lon, img_map_pos.lat, view_lon, view_lat); p1.x = img_map->width/2 + p2.x - gfx_screensize.x/2; p1.y = img_map->height/2 + p2.y - gfx_screensize.y/2; if (p1.x < 0 || p1.y < 0 || p1.x > (img_map->width - gfx_screensize.x) || p1.y > (img_map->height - gfx_screensize.y)) return 0; gfx_draw_img (NULL, 0, 0, gfx_screensize.x, gfx_screensize.y, img_map, p1.x, p1.y); return 1; }; void draw () { static int still_drawing = 0; /* only run once at the time.. */ if (still_drawing) return; still_drawing = 1; while (view_lon > 180.0) view_lon -= 360.0; while (view_lon < -180.0) view_lon += 360.0; while (view_lat > 180.0) view_lat -= 360.0; while (view_lat < -180.0) view_lat += 360.0; /* do we need to alloc the screens */ if (img_map != NULL && (img_map->width != gfx_screensize.x * 2 || img_map->height != gfx_screensize.y * 2)) { gfx_img_free (img_map); img_map = NULL; } if (img_map == NULL) { // img_map = gfx_img_alloc (400 * 2, 400 * 2); img_map = gfx_img_alloc (gfx_screensize.x * 2, gfx_screensize.y * 2); img_map_scale = -1.0; } /* draw the map, if needed */ if (img_map_scale < 0.0 || img_map_scale != view_scale) { draw_map (); } gfx_clear (NULL, &color[COLOR_white][0]); if (draw_mapcopy () == 0) { draw_map (); draw_mapcopy (); } draw_gui (); gfx_flip (); still_drawing = 0; }; void draw_redrawmap () { img_map_scale = -1; draw (); };