From: Kaj-Michael Lang Date: Tue, 29 Apr 2008 10:36:50 +0000 (+0300) Subject: Copy & Paste some more code from map.c to gtkmap.c X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e5fa9028b9379c0cf5869886502b463e9717b08;p=mapper Copy & Paste some more code from map.c to gtkmap.c --- diff --git a/src/gtkmap.c b/src/gtkmap.c index b12f55f..d3cd94f 100644 --- a/src/gtkmap.c +++ b/src/gtkmap.c @@ -132,7 +132,7 @@ gtk_map_new(void) GtkMap *map; GtkWidget *widget; -map=gtk_type_new(gtk_map_get_type ()); +map=g_object_new(GTK_MAP_TYPE, NULL); widget=GTK_WIDGET(map); map->heading=0; @@ -184,7 +184,7 @@ map->height=256; } static void -gtk_map_realize (GtkWidget *widget) +gtk_map_realize(GtkWidget *widget) { GtkMap *map; @@ -202,9 +202,183 @@ g_return_val_if_fail(event != NULL, FALSE); map=GTK_MAP(widget); +gdk_draw_drawable(GDK_DRAWABLE(map->widget->window), + map->gc[COLORABLE_MARK], + map->pixmap, + event->area.x + map->offsetx, event->area.y + map->offsety, + event->area.x, event->area.y, + event->area.width, event->area.height); + return TRUE; } +static void +map_scale_draw(GtkWidget *widget, GdkEventExpose *event) +{ +GtkMap *map; +gchar buffer[16]; +gdouble distance; +gdouble lat1, lon1, lat2, lon2; +gint width; + +g_return_if_fail(GTK_IS_MAP(widget)); +map=GTK_MAP(widget); + +pango_layout_set_text(scale_layout, "0", -1); +pango_layout_get_pixel_size(scale_layout, NULL, &scale_rect.height); +scale_rect.y = _screen_height_pixels - scale_rect.height - 1; + +gdk_rectangle_intersect(&event->area, &scale_rect, &event->area); + +if (event->area.width && event->area.height) { + gdk_draw_rectangle(_map_widget->window, + _map_widget->style->bg_gc[GTK_WIDGET_STATE(_map_widget)], + TRUE, scale_rect.x, scale_rect.y, + scale_rect.width, + scale_rect.height); + gdk_draw_rectangle(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + FALSE, scale_rect.x, scale_rect.y, + scale_rect.width, + scale_rect.height); + + /* Now calculate and draw the distance. */ + unit2latlon(_center.unitx - pixel2unit(SCALE_WIDTH / 2 - 4), _center.unity, lat1, lon1); + unit2latlon(_center.unitx + pixel2unit(SCALE_WIDTH / 2 - 4), _center.unity, lat2, lon2); + distance=calculate_distance(lat1, lon1, lat2, lon2) * UNITS_CONVERT[_units]; + + if (distance < 1.f) + g_snprintf(buffer, sizeof(buffer), "%0.2f %s", distance, UNITS_TEXT[_units]); + else if (distance < 10.f) + g_snprintf(buffer, sizeof(buffer), "%0.1f %s", distance, UNITS_TEXT[_units]); + else + g_snprintf(buffer, sizeof(buffer), "%0.f %s", distance, UNITS_TEXT[_units]); + + pango_layout_set_text(scale_layout, buffer, -1); + pango_layout_get_pixel_size(scale_layout, &width, NULL); + + /* Draw the layout itself. */ + gdk_draw_layout(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + scale_rect.x + (scale_rect.width - width) / 2, + scale_rect.y, scale_layout); + + /* Draw little hashes on the ends. */ + gdk_draw_line(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + scale_rect.x + 4, + scale_rect.y + scale_rect.height / 2 - 4, + scale_rect.x + 4, + scale_rect.y + scale_rect.height / 2 + 4); + gdk_draw_line(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + scale_rect.x + 4, + scale_rect.y + scale_rect.height / 2, + scale_rect.x + (scale_rect.width - width) / 2 - 4, + scale_rect.y + scale_rect.height / 2); + gdk_draw_line(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + scale_rect.x + scale_rect.width - 4, + scale_rect.y + scale_rect.height / 2 - 4, + scale_rect.x + scale_rect.width - 4, + scale_rect.y + scale_rect.height / 2 + 4); + gdk_draw_line(_map_widget->window, + _map_widget->style->fg_gc[GTK_WIDGET_STATE(_map_widget)], + scale_rect.x + scale_rect.width - 4, + scale_rect.y + scale_rect.height / 2, + scale_rect.x + (scale_rect.width + width) / 2 + 4, + scale_rect.y + scale_rect.height / 2); + } +} + +static void +map_information_text(GtkWidget *widget, guint x, guint y, GdkGC *gc, gchar *msg) +{ +guint width, height; + +g_return_if_fail(GTK_IS_MAP(widget)); +map=GTK_MAP(widget); + +pango_layout_set_text(speed_layout, msg, -1); +pango_layout_get_pixel_size(speed_layout, &width, &height); +gtk_widget_queue_draw_area(_map_widget, x - 5, y - 5, width * 3 + 15, height + 5); +gdk_window_process_all_updates(); +gdk_draw_layout(_map_widget->window, gc, x, y, speed_layout); +gdk_window_process_all_updates(); +} + +static void +map_speed_draw(GtkWidget *widget, gfloat speed, gboolean overspeed) +{ +GdkGC *gc; +gfloat cur_speed; +gchar *buffer; + +g_return_if_fail(GTK_IS_MAP(widget)); +map=GTK_MAP(widget); + +gc=(overspeed) ? speed_gc1 : speed_gc2; +buffer = g_strdup_printf("%0.0f", speed); +map_information_text(10, 10, gc, buffer); +g_free(buffer); +} + +/** + * Do an in-place scaling of a pixbuf's pixels at the given ratio from the + * given source location. It would have been nice if gdk_pixbuf provided + * this method, but I guess it's not general-purpose enough. + */ +static void +map_pixbuf_scale_inplace(GdkPixbuf *pixbuf, guint ratio_p2, guint src_x, guint src_y) +{ +guint dest_x = 0, dest_y = 0, dest_dim = TILE_SIZE_PIXELS; +guint rowstride = gdk_pixbuf_get_rowstride(pixbuf); +guint n_channels = gdk_pixbuf_get_n_channels(pixbuf); +guchar *pixels = gdk_pixbuf_get_pixels(pixbuf); + +/* Sweep through the entire dest area, copying as necessary, but + * DO NOT OVERWRITE THE SOURCE AREA. We'll copy it afterward. */ +do { + guint src_dim = dest_dim >> ratio_p2; + guint src_endx = src_x - dest_x + src_dim; + gint x, y; + + for (y = dest_dim - 1; y >= 0; y--) { + guint src_offset_y, dest_offset_y; + + src_offset_y = (src_y + (y >> ratio_p2)) * rowstride; + dest_offset_y = (dest_y + y) * rowstride; + x = dest_dim - 1; + + if ((unsigned)(dest_y + y - src_y) < src_dim && (unsigned)(dest_x + x - src_x) < src_dim) + x -= src_dim; + + for (; x >= 0; x--) { + guint src_offset, dest_offset, i; + + src_offset = src_offset_y + (src_x + (x >> ratio_p2)) * n_channels; + dest_offset = dest_offset_y + (dest_x + x) * n_channels; + + pixels[dest_offset] = pixels[src_offset]; + for (i = n_channels - 1; i; i--) + pixels[dest_offset + i] = pixels[src_offset + i]; + + if ((unsigned)(dest_y + y - src_y) < src_dim && x == src_endx) + x -= src_dim; + } + } + + /* Reuse src_dim and src_endx to store new src_x and src_y. */ + src_dim = src_x + ((src_x - dest_x) >> ratio_p2); + src_endx = src_y + ((src_y - dest_y) >> ratio_p2); + dest_x = src_x; + dest_y = src_y; + src_x = src_dim; + src_y = src_endx; +} +while ((dest_dim >>= ratio_p2) > 1); +} + void gtk_map_refresh(GtkWidget *widget) { @@ -215,3 +389,36 @@ g_return_if_fail(GTK_IS_MAP(widget)); map=GTK_MAP(widget); gtk_widget_queue_draw_area(widget, 0, 0, map->width, map->height); } + +gint +map_zoom(GtkWidget *widget, gint zdir) +{ +gint nzoom; +GtkMap *map; + +g_return_val_if_fail(GTK_IS_MAP(widget), -1); + +map=GTK_MAP(widget); + +nzoom=map->zoom+zdir; +if ((nzoom >= 0) && (nzoom < map->max_zoom - 1)) { + map_set_zoom(widget, nzoom); +} +return nzoom; +} + +gboolean +map_zoom_in(GtkWidget *widget) +{ +g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); +map_zoom(widget, -1); +return FALSE; +} + +gboolean +map_zoom_out(GtkWidget *widget) +{ +g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); +map_zoom(widget, 1); +return FALSE; +}