📄 zoom-region.c
字号:
test_image = gdk_image_new (GDK_IMAGE_FASTEST, gdk_visual_get_system (), width, height); for (i = 0; i < width; ++i) for (j = 0; j < height; ++j) gdk_image_put_pixel (test_image, i, j, i*j); zoom_region->priv->source_drawable = gdk_pixmap_new (zoom_region->priv->w->window, width, height, -1); if (zoom_region->priv->default_gc == NULL) zoom_region->priv->default_gc = gdk_gc_new(zoom_region->priv->w->window); gdk_draw_image (zoom_region->priv->source_drawable, zoom_region->priv->default_gc, test_image, 0, 0, 0, 0, width, height); } else { if (magnifier->priv->source_drawable) { zoom_region->priv->source_drawable = magnifier->priv->source_drawable; } else zoom_region->priv->source_drawable = gdk_screen_get_root_window (gdk_display_get_screen (magnifier->source_display, magnifier->source_screen_num)); } if (zoom_region->cache_source) { zoom_region->priv->source_pixbuf_cache = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, /* FIXME: not always 8? */ width, height); } } DEBUG_RECT ("getting subimage from ", bounds); subimage = gdk_pixbuf_get_from_drawable (NULL, zoom_region->priv->source_drawable, gdk_colormap_get_system (), bounds.x, bounds.y, 0, 0, bounds.width, bounds.height); /* TODO: blank the region overlapped by the target display if source == target */ if (!subimage) _debug_announce_rect ("update of invalid subregion!\n", bounds); /* if this zoom-region keeps a cache, do a diff to see if update is necessary */ if (zoom_region->cache_source && subimage) { GdkPixbuf *cache_subpixbuf = gdk_pixbuf_new_subpixbuf (zoom_region->priv->source_pixbuf_cache, bounds.x, bounds.y, bounds.width, bounds.height); if (_diff_pixbufs (subimage, cache_subpixbuf)) { gdk_pixbuf_copy_area (subimage, 0, 0, bounds.width, bounds.height, zoom_region->priv->source_pixbuf_cache, bounds.x, bounds.y); } else { if (subimage) g_object_unref (subimage); subimage = NULL; } g_object_unref (cache_subpixbuf); } return subimage;}static GdkRectanglezoom_region_update_pixmap (ZoomRegion *zoom_region, const GdkRectangle update_rect, GdkRectangle *p_rect){ GdkPixbuf *subimage; GdkRectangle source_rect;#ifdef ZOOM_REGION_DEBUG g_assert (zoom_region->alive);#endif DEBUG_RECT ("unclipped update rect", update_rect); source_rect = zoom_region_clip_to_source (zoom_region, update_rect); DEBUG_RECT ("clipped to source", source_rect); source_rect = zoom_region_clip_to_exposed_target (zoom_region, source_rect); DEBUG_RECT ("update rect clipped to exposed target", source_rect); subimage = zoom_region_get_source_subwindow (zoom_region, source_rect); if (subimage) { GdkRectangle paint_rect; g_timer_start (mag_timing.scale); DEBUG_RECT ("source rect", source_rect); paint_rect = zoom_region_view_rect_from_source_rect (zoom_region, source_rect); if (p_rect) { *p_rect = paint_rect; } /* paint_rect = zoom_region_clip_to_scaled_pixmap (zoom_region, paint_rect); */ DEBUG_RECT ("paint rect", paint_rect); zoom_region_process_pixbuf (zoom_region, subimage); /** * XXX: We seem to be breaking with the original intention * here, which was to keep a fullscreen scaled pixbuf in-sync. **/ gdk_pixbuf_scale (subimage, zoom_region->priv->scaled_pixbuf, 0, 0, paint_rect.width, paint_rect.height, 0, 0, zoom_region->xscale, zoom_region->yscale, zoom_region->priv->gdk_interp_type); zoom_region_post_process_pixbuf (zoom_region, subimage, zoom_region->priv->scaled_pixbuf); if (zoom_region->priv->default_gc == NULL) zoom_region->priv->default_gc = gdk_gc_new(zoom_region->priv->w->window);#ifndef USE_GDK_PIXBUF_RENDER_TO_DRAWABLE if (GDK_IS_DRAWABLE (zoom_region->priv->pixmap)) gdk_draw_pixbuf (zoom_region->priv->pixmap, zoom_region->priv->default_gc, zoom_region->priv->scaled_pixbuf, 0, 0, paint_rect.x + zoom_region->priv->exposed_bounds.x1 - zoom_region->priv->source_area.x1 * zoom_region->xscale, paint_rect.y + zoom_region->priv->exposed_bounds.y1 - zoom_region->priv->source_area.y1 * zoom_region->yscale, paint_rect.width, paint_rect.height, GDK_RGB_DITHER_NONE, 0, 0); else g_warning ("updating non-drawable pixmap: region %p", zoom_region);#else gdk_pixbuf_render_to_drawable (zoom_region->priv->scaled_pixbuf, zoom_region->priv->pixmap, zoom_region->priv->default_gc, 0, 0, paint_rect.x + zoom_region->priv->exposed_bounds.x1, paint_rect.y + zoom_region->priv->exposed_bounds.y1, paint_rect.width, paint_rect.height, GDK_RGB_DITHER_NONE, 0, 0);#endif if (magnifier_error_check ()) g_warning ("Could not render scaled image to drawable; out of memory!\n"); g_object_unref (subimage); g_timer_stop (mag_timing.scale); } return source_rect;}/** * zoom_region_update: * * @rect: a RectBounds structure indicating the source area to update, * in the source coordinate system. **/static voidzoom_region_update (ZoomRegion *zoom_region, const GdkRectangle update_rect){ GdkRectangle paint_rect = {0, 0, 0, 0}; if (zoom_region->priv->w && zoom_region->priv->w->window) { GdkRectangle source_rect = zoom_region_update_pixmap (zoom_region, update_rect, &paint_rect); if (paint_rect.x != 0 || paint_rect.y != 0 || paint_rect.width != 0 || paint_rect.height != 0) { gdk_window_begin_paint_rect ( zoom_region->priv->w->window, &paint_rect); zoom_region_paint (zoom_region, &paint_rect); gdk_window_end_paint (zoom_region->priv->w->window); } if (timing_test) { mag_timing.num_scale_samples++; gulong microseconds; mag_timing.scale_val = g_timer_elapsed (mag_timing.scale, µseconds); mag_timing.scale_total += mag_timing.scale_val; if (mag_timing.scale_val != 0 && (timing_scale_max == 0 || (1.0/(float)mag_timing.scale_val) > (1.0/(float)timing_scale_max))) timing_scale_max = mag_timing.scale_val; if ((source_rect.height * source_rect.width / mag_timing.scale_val) > update_nrr_max) update_nrr_max = source_rect.height * source_rect.width / mag_timing.scale_val; mag_timing.update_pixels_total += source_rect.height * source_rect.width; if (zoom_region->timing_output) { fprintf(stderr, " Update Duration = %f (avg. %f) (max. %f) (tot. %f) seconds\n", mag_timing.scale_val, (mag_timing.scale_total / mag_timing.num_scale_samples), timing_scale_max, mag_timing.scale_total); fprintf(stderr, " Update Pixels = %ld (avg. %ld) pixels/frame\n", (long) source_rect.height * source_rect.width, mag_timing.update_pixels_total / mag_timing.num_scale_samples); fprintf(stderr, " Update Rate = (avg. %f) (max. %f) updates/second\n", 1.0/(mag_timing.scale_total / mag_timing.num_scale_samples), 1.0/(float)timing_scale_max); fprintf(stderr, " Net Update Rate = (avg. %f) (max. %f) Mpex/second\n", ((float)mag_timing.update_pixels_total / (float)mag_timing.scale_total) / 1000000.0, update_nrr_max / 1000000.0); } } } else { fprintf (stderr, "update on uninitialized zoom region!\n"); }}static voidzoom_region_init_window (ZoomRegion *zoom_region){ GtkFixed *parent; GtkWidget *zoomer, *border; DBG(fprintf (stderr, "window not yet created...\n")); parent = GTK_FIXED ( ((Magnifier *)zoom_region->priv->parent)->priv->canvas); zoomer = gtk_drawing_area_new (); border = gtk_drawing_area_new (); zoom_region->priv->border = border; zoom_region->priv->w = zoomer;#ifdef ZOOM_REGION_DEBUG g_assert (zoom_region->alive);#endif gtk_widget_set_size_request (GTK_WIDGET (border), zoom_region->viewport.x2 - zoom_region->viewport.x1, zoom_region->viewport.y2 - zoom_region->viewport.y1); gtk_widget_set_size_request (GTK_WIDGET (zoomer), zoom_region->viewport.x2 - zoom_region->viewport.x1 - zoom_region->border_size * 2, zoom_region->viewport.y2 - zoom_region->viewport.y1 - zoom_region->border_size * 2); gtk_fixed_put (parent, border, zoom_region->viewport.x1, zoom_region->viewport.y1); gtk_fixed_put (parent, zoomer, zoom_region->viewport.x1 + zoom_region->border_size, zoom_region->viewport.y1 + zoom_region->border_size); gtk_widget_show (GTK_WIDGET (border)); gtk_widget_show (GTK_WIDGET (zoomer)); gtk_widget_show (GTK_WIDGET (parent)); zoom_region->priv->expose_handler_id = g_signal_connect (G_OBJECT (zoom_region->priv->w), "expose_event", G_CALLBACK (zoom_region_expose_handler), zoom_region); DBG(fprintf (stderr, "New window created\n"));}static intzoom_region_process_updates (gpointer data){ ZoomRegion *zoom_region = (ZoomRegion *) data; /* TODO: lock the queue when copying it? */ zoom_region_coalesce_updates (zoom_region); if (zoom_region->priv->q != NULL) { GList *last = g_list_last (zoom_region->priv->q);#ifdef ZOOM_REGION_DEBUG fprintf (stderr, "qlen=%d\n", g_list_length (zoom_region->priv->q));#endif if (last) { zoom_region->priv->q = g_list_remove_link (zoom_region->priv->q, last); zoom_region_update (zoom_region, * (GdkRectangle *) last->data); g_list_free (last);#ifdef DEBUG fputs (".\n", stderr); /* debug output, means we actually did something. */#endif } return TRUE; } else { if (zoom_region->priv) zoom_region->priv->update_handler_id = 0; return FALSE; }}voidtiming_report(ZoomRegion *zoom_region){ float frame_avg; float x_scroll_incr, y_scroll_incr; int width, height, x, y; if (timing_test) { width = (zoom_region->viewport.x2 - zoom_region->viewport.x1) / zoom_region->xscale; height = (zoom_region->viewport.y2 - zoom_region->viewport.y1) / zoom_region->yscale; frame_avg = mag_timing.frame_total / mag_timing.num_frame_samples; x_scroll_incr = (float)mag_timing.dx_total / (float)mag_timing.num_line_samples; y_scroll_incr = (float)mag_timing.dy_total / (float)mag_timing.num_line_samples; gdk_drawable_get_size (GDK_DRAWABLE (zoom_region->priv->w->window), &x, &y); fprintf(stderr, " Frames Processed = %ld\n", mag_timing.num_frame_samples + 1); fprintf(stderr, " Width/Height/Depth = %d/%d/%d\n", x, y, gdk_drawable_get_depth (zoom_region->priv->w->window)); fprintf(stderr, " Zoom Factor (x/y) = %f/%f\n", zoom_region->xscale, zoom_region->yscale); if (mag_timing.num_scale_samples != 0) { fprintf(stderr, " Update Duration = (avg. %f) (max. %f) (tot. %f) seconds\n", (mag_timing.scale_total / mag_timing.num_scale_samples), timing_scale_max, mag_timing.scale_total); fprintf(stderr, " Update Pixels = (avg. %ld) pixels/frame\n", mag_timing.update_pixels_total / mag_timing.num_scale_samples); fprintf(stderr, " Update Rate = (avg. %f) (max. %f) updates/second\n", 1.0/((float)mag_timing.scale_total / (float)mag_timing.num_scale_samples), 1.0/(float)timing_scale_max); fprintf(stderr, " Net Update Rate = (avg. %f) (max. %f) Mpex/second\n", ((float)mag_timing.update_pixels_total / (float)mag_timing.scale_total) / 1000000.0, update_nrr_max / 1000000.0); } fprintf(stderr, " Pan Latency = (avg. %f) (max. %f) seconds\n", (mag_timing.idle_total / mag_timing.num_idle_samples), timing_idle_max); fprintf(stderr, " Total Frame Duration = (avg. %f) (max. %f) (tot. %f) seconds\n", frame_avg, timing_frame_max, mag_timing.frame_total); fprintf(stderr, " Frame Rate = (avg. %f) (max. %f) frames/second\n", 1.0 / (mag_timing.frame_total / mag_timing.num_frame_samples), cps_max); fprintf(stderr, " Scroll Delta (x) = (avg. %f) (tot. %d) lines\n", x_scroll_incr, mag_timing.dx_total); fprintf(stderr, " Scroll Delta (y) = (avg. %f) (tot. %d) lines\n", y_scroll_incr, mag_timing.dy_total); fprintf(stderr, " Scroll Rate (x) = (avg. %f) lines/second\n", x_scroll_incr / frame_avg); fprintf(stderr, " Scroll Rate (y) = (avg. %f) lines/second\n", y_scroll_incr / frame_avg); fprintf(stderr, " Net Render Rate = (avg. %f) (max. %f) Mpex/second\n\n", (height * width * ((float)mag_timing.num_frame_samples / (float)mag_timing.frame_total)) / 1000000.0, nrr_max / 1000000.0); }}static voidzoom_region_time_frame(ZoomRegion *zoom_region, Magnifier *magnifier){ float frame_avg; float x_scroll_incr, y_scroll_incr; int width = magnifier->target_bounds.x2 - magnifier->target_bounds.x1; int height = magnifier->target_bounds.y2 - magnifier->target_bounds.y1; mag_timing.num_frame_samples++; g_timer_stop (mag_timing.frame); gulong microseconds; mag_timing.frame_val = g_timer_elapsed (mag_timing.frame, µseconds); mag_timing.frame_total += mag_timing.frame_val; if (mag_timing.frame_val > timing_frame_max) timing_frame_max = mag_timing.frame_val; if (mag_timing.frame_val != 0 && 1.0/mag_timing.frame_val > cps_max) cps_max = 1.0/mag_timing.frame_val; frame_avg = mag_timing.frame_total / mag_timing.num_frame_samples; x_scroll_incr = (float)mag_timing.dx_total / (float)mag_timing.num_line_samples; y_scroll_incr = (float)mag_timing.dy_total / (float)mag_timing.num_line_samples; if ((height * width / mag_timing.frame_val) > nrr_max) nrr_max = height * width / mag_timing.frame_val; if (zoom_region->timing_output) { fprintf(stderr, " Total Frame Duration = %f (avg. %f) (max. %f) (tot. %f) seconds\n", mag_timing.frame_val, frame_avg, timing_frame_max, mag_timing.frame_total); fprintf(stderr, " Frame Rate = (avg. %f) (max. %f) frames/second\n", 1.0 /frame_avg, cps_max); fprintf(stderr, " Scroll Delta (x) = (avg. %f) (tot. %d) lines\n", x_scroll_incr, mag_timing.dx_total); fprintf(stderr, " Scroll Delta (y) = (avg. %f) (tot. %d) lines\n", y_scroll_incr, mag_timing.dy_total); fprintf(stderr, " Scroll Rate (x) = (avg. %f) lines/second\n", x_scroll_incr / frame_avg); fprintf(stderr, " Scroll Rate (y) = (avg. %f) lines/second\n", y_scroll_incr / frame_avg); fprintf(stderr, " Net Render Rate = (avg. %f) (max. %f) Mpex/second\n", (height * width * ((float)mag_timing.num_frame_samples / (float)mag_timing.frame_total)) / 1000000.0, nrr_max / 1000000.0); } mag_timing.last_frame_val = mag_timing.frame_val; mag_timing.last_dy = mag_timing.dy; if (reset_timing) { fprintf(stderr, "\n### Updates summary:\n\n"); timing_report (zoom_region); fprintf(stderr, "\n### Updates finished, starting panning test\n"); reset_timing_stats(); reset_timing = FALSE; }}static voidzoom_region_sync (ZoomRegion *zoom_regi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -