⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zoom-region.c

📁 在Linux下实现magnification功能
💻 C
📖 第 1 页 / 共 5 页
字号:
			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,						 &microseconds);			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,						&microseconds);	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 + -