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

📄 pixbuf-renderer.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 5 页
字号:
	pr_border_draw(pr, 0, 0, pr->window_width, pr->window_height);}void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color){	GtkStyle *style;	GtkWidget *widget;	g_return_if_fail(IS_PIXBUF_RENDERER(pr));	widget = GTK_WIDGET(pr);	style = gtk_style_copy(gtk_widget_get_style(widget));	g_object_ref(G_OBJECT(style));	if (color)		{		GdkColor *slot;		slot = &style->bg[GTK_STATE_NORMAL];		slot->red = color->red;		slot->green = color->green;		slot->blue = color->blue;		}	gtk_widget_set_style(widget, style);	g_object_unref(G_OBJECT(style));	if (GTK_WIDGET_VISIBLE(widget)) pr_border_clear(pr);}void pixbuf_renderer_set_black(PixbufRenderer *pr, gint black){	GdkColor color = { 0, 0, 0, 0};	pixbuf_renderer_set_color(pr, &color);}/* *------------------------------------------------------------------- * source tiles *------------------------------------------------------------------- */static void pr_source_tile_free(SourceTile *st){	if (!st) return;	if (st->pixbuf) g_object_unref(st->pixbuf);	g_free(st);}static void pr_source_tile_free_all(PixbufRenderer *pr){	GList *work;	work = pr->source_tiles;	while (work)		{		SourceTile *st;		st = work->data;		work = work->next;		pr_source_tile_free(st);		}	g_list_free(pr->source_tiles);	pr->source_tiles = NULL;}static void pr_source_tile_unset(PixbufRenderer *pr){	pr_source_tile_free_all(pr);	pr->source_tiles_enabled = FALSE;}static gint pr_source_tile_visible(PixbufRenderer *pr, SourceTile *st){	gint x1, y1, x2, y2;	if (!st) return FALSE;	x1 = (pr->x_scroll / pr->tile_width) * pr->tile_width;	y1 = (pr->y_scroll / pr->tile_height) * pr->tile_height;	x2 = ((pr->x_scroll + pr->vis_width) / pr->tile_width) * pr->tile_width + pr->tile_width;	y2 = ((pr->y_scroll + pr->vis_height) / pr->tile_height) * pr->tile_height + pr->tile_height;	return !((double)st->x * pr->scale > (double)x2 ||		 (double)(st->x + pr->source_tile_width) * pr->scale < (double)x1 ||		 (double)st->y * pr->scale > (double)y2 ||		 (double)(st->y + pr->source_tile_height) * pr->scale < (double)y1);}static SourceTile *pr_source_tile_new(PixbufRenderer *pr, gint x, gint y){	SourceTile *st = NULL;	gint count;	g_return_val_if_fail(pr->source_tile_width >= 1 && pr->source_tile_height >= 1, NULL);	if (pr->source_tiles_cache_size < 4) pr->source_tiles_cache_size = 4;	count = g_list_length(pr->source_tiles);	if (count >= pr->source_tiles_cache_size)		{		GList *work;		work = g_list_last(pr->source_tiles);		while (work && count >= pr->source_tiles_cache_size)			{			SourceTile *needle;			needle = work->data;			work = work->prev;			if (!pr_source_tile_visible(pr, needle))				{				pr->source_tiles = g_list_remove(pr->source_tiles, needle);				if (pr->func_tile_dispose)					{					pr->func_tile_dispose(pr, needle->x, needle->y,							      pr->source_tile_width, pr->source_tile_height,							      needle->pixbuf, pr->func_tile_data);					}				if (!st)					{					st = needle;					}				else					{					pr_source_tile_free(needle);					}				count--;				}			}		}	if (!st)		{		st = g_new0(SourceTile, 1);		st->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,					    pr->source_tile_width, pr->source_tile_height);		}	st->x = (x / pr->source_tile_width) * pr->source_tile_width;	st->y = (y / pr->source_tile_height) * pr->source_tile_height;	st->blank = TRUE;	pr->source_tiles = g_list_prepend(pr->source_tiles, st);	return st;}static SourceTile *pr_source_tile_request(PixbufRenderer *pr, gint x, gint y){	SourceTile *st;	st = pr_source_tile_new(pr, x, y);	if (!st) return NULL;	if (pr->func_tile_request &&	    pr->func_tile_request(pr, st->x, st->y,				   pr->source_tile_width, pr->source_tile_height, st->pixbuf, pr->func_tile_data))		{		st->blank = FALSE;		}	pr_tile_invalidate_region(pr, st->x * pr->scale, st->y * pr->scale,				  pr->source_tile_width * pr->scale, pr->source_tile_height * pr->scale);	return st;}static SourceTile *pr_source_tile_find(PixbufRenderer *pr, gint x, gint y){	GList *work;	work = pr->source_tiles;	while (work)		{		SourceTile *st = work->data;		if (x >= st->x && x < st->x + pr->source_tile_width &&		    y >= st->y && y < st->y + pr->source_tile_height)			{			if (work != pr->source_tiles)				{				pr->source_tiles = g_list_remove_link(pr->source_tiles, work);				pr->source_tiles = g_list_concat(work, pr->source_tiles);				}			return st;			}		work = work->next;		}	return NULL;}static GList *pr_source_tile_compute_region(PixbufRenderer *pr, gint x, gint y, gint w, gint h, gint request){	gint x1, y1;	GList *list = NULL;	gint sx, sy;	if (x < 0) x = 0;	if (y < 0) y = 0;	if (w > pr->image_width) w = pr->image_width;	if (h > pr->image_height) h = pr->image_height;	sx = (x / pr->source_tile_width) * pr->source_tile_width;	sy = (y / pr->source_tile_height) * pr->source_tile_height;	for (x1 = sx; x1 < x + w; x1+= pr->source_tile_width)		{		for (y1 = sy; y1 < y + h; y1 += pr->source_tile_height)			{			SourceTile *st;			st = pr_source_tile_find(pr, x1, y1);			if (!st && request) st = pr_source_tile_request(pr, x1, y1);			if (st) list = g_list_prepend(list, st);			}		}	return g_list_reverse(list);}static void pr_source_tile_changed(PixbufRenderer *pr, gint x, gint y, gint width, gint height){	GList *work;	work = pr->source_tiles;	while (work)		{		SourceTile *st;		gint rx, ry, rw, rh;		st = work->data;		work = work->next;		if (pr_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height,				   x, y, width, height,				   &rx, &ry, &rw, &rh))			{			GdkPixbuf *pixbuf;			pixbuf = gdk_pixbuf_new_subpixbuf(st->pixbuf, rx - st->x, ry - st->y, rw, rh);			if (pr->func_tile_request &&			    pr->func_tile_request(pr, rx, ry, rw, rh, pixbuf, pr->func_tile_data))				{				pr_tile_invalidate_region(pr, rx * pr->scale, ry * pr->scale,							      rw * pr->scale, rh * pr->scale);				}			g_object_unref(pixbuf);			}		}}static gint pr_source_tile_render(PixbufRenderer *pr, ImageTile *it,				  gint x, gint y, gint w, gint h,				  gint new_data, gint fast){	GtkWidget *box;	GList *list;	GList *work;	gint draw = FALSE;	box = GTK_WIDGET(pr);	if (pr->zoom == 1.0 || pr->scale == 1.0)		{		list = pr_source_tile_compute_region(pr, it->x + x, it->y + y, w, h, TRUE);		work = list;		while (work)			{			SourceTile *st;			gint rx, ry, rw, rh;			st = work->data;			work = work->next;			if (pr_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height,					   it->x + x, it->y + y, w, h,					   &rx, &ry, &rw, &rh))				{				if (st->blank)					{					gdk_draw_rectangle(it->pixmap, box->style->black_gc, TRUE,							   rx - st->x, ry - st->y, rw, rh);					}				else /* (pr->zoom == 1.0 || pr->scale == 1.0) */					{					gdk_draw_pixbuf(it->pixmap,							box->style->fg_gc[GTK_WIDGET_STATE(box)],							st->pixbuf,							rx - st->x, ry - st->y,							rx - it->x, ry - it->y,							rw, rh,							pr->dither_quality, rx, ry);					}				}			}		}	else		{		double scale_x, scale_y;		gint sx, sy, sw, sh;		if (pr->image_width == 0 || pr->image_height == 0) return FALSE;		scale_x = (double)pr->width / pr->image_width;		scale_y = (double)pr->height / pr->image_height;		sx = (double)(it->x + x) / scale_x;		sy = (double)(it->y + y) / scale_y;		sw = (double)w / scale_x;		sh = (double)h / scale_y;		if (pr->width < PR_MIN_SCALE_SIZE || pr->height < PR_MIN_SCALE_SIZE) fast = TRUE;#if 0		/* draws red over draw region, to check for leaks (regions not filled) */		pixbuf_set_rect_fill(it->pixbuf, x, y, w, h, 255, 0, 0, 255);#endif		list = pr_source_tile_compute_region(pr, sx, sy, sw, sh, TRUE);		work = list;		while (work)			{			SourceTile *st;			gint rx, ry, rw, rh;			gint stx, sty, stw, sth;			st = work->data;			work = work->next;			stx = floor((double)st->x * scale_x);			sty = floor((double)st->y * scale_y);			stw = ceil ((double)(st->x + pr->source_tile_width) * scale_x) - stx;			sth = ceil ((double)(st->y + pr->source_tile_height) * scale_y) - sty;			if (pr_clip_region(stx, sty, stw, sth,					   it->x + x, it->y + y, w, h,					   &rx, &ry, &rw, &rh))				{				if (st->blank)					{					gdk_draw_rectangle(it->pixmap, box->style->black_gc, TRUE,							   rx - st->x, ry - st->y, rw, rh);					}				else					{					double offset_x;					double offset_y;					/* may need to use unfloored stx,sty values here */					offset_x = (double)(stx - it->x);					offset_y = (double)(sty - it->y);					gdk_pixbuf_scale(st->pixbuf, it->pixbuf, rx - it->x, ry - it->y, rw, rh,						 (double) 0.0 + offset_x,						 (double) 0.0 + offset_y,						 scale_x, scale_y,						 (fast) ? GDK_INTERP_NEAREST : pr->zoom_quality);					draw = TRUE;					}				}			}		}	g_list_free(list);	return draw;}void pixbuf_renderer_set_tiles(PixbufRenderer *pr, gint width, gint height,			       gint tile_width, gint tile_height, gint cache_size,			       PixbufRendererTileRequestFunc func_request,			       PixbufRendererTileDisposeFunc func_dispose,			       gpointer user_data,			       gdouble zoom){	g_return_if_fail(IS_PIXBUF_RENDERER(pr));	g_return_if_fail(tile_width >= 32 && tile_width >= 32);	g_return_if_fail(width >= 32 && height > 32);	g_return_if_fail(func_request != NULL);	if (pr->pixbuf) g_object_unref(pr->pixbuf);	pr->pixbuf = NULL;	pr_source_tile_unset(pr);	if (cache_size < 4) cache_size = 4;	pr->source_tiles_enabled = TRUE;	pr->source_tiles_cache_size = cache_size;	pr->source_tile_width = tile_width;	pr->source_tile_height = tile_height;	pr->image_width = width;	pr->image_height = height;	pr->func_tile_request = func_request;	pr->func_tile_dispose = func_dispose;	pr->func_tile_data = user_data;	pr_zoom_sync(pr, zoom, TRUE, FALSE, TRUE, FALSE, 0, 0);	pr_redraw(pr, TRUE);}gint pixbuf_renderer_get_tiles(PixbufRenderer *pr){	g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);	return pr->source_tiles_enabled;}static void pr_zoom_adjust_real(PixbufRenderer *pr, gdouble increment,				gint center_point, gint x, gint y){	gdouble zoom = pr->zoom;	if (increment == 0.0) return;	if (zoom == 0.0)		{		if (pr->scale < 1.0)			{			zoom = 0.0 - 1.0 / pr->scale;			}		else			{			zoom = pr->scale;			}		}	if (increment < 0.0)		{		if (zoom >= 1.0 && zoom + increment < 1.0)			{			zoom = zoom + increment - 2.0;			}		else			{			zoom = zoom + increment;			}		}	else		{		if (zoom <= -1.0 && zoom + increment > -1.0)			{			zoom = zoom + increment + 2.0;			}		else			{			zoom = zoom + increment;			}		}	pr_zoom_sync(pr, zoom, FALSE, FALSE, FALSE, center_point, x, y);}/* *------------------------------------------------------------------- * display tiles *------------------------------------------------------------------- */static ImageTile *pr_tile_new(gint x, gint y, gint width, gint height){	ImageTile *it;	it = g_new0(ImageTile, 1);	it->x = x;	it->y = y;	it->w = width;	it->h = height;	it->render_done = TILE_RENDER_NONE;	return it;}static void pr_tile_free(ImageTile *it){	if (!it) return;	if (it->pixbuf) gdk_pixbuf_unref(it->pixbuf);	if (it->pixmap) g_object_unref(it->pixmap);	g_free(it);}static void pr_tile_free_all(PixbufRenderer *pr){	GList *work;	work = pr->tiles;	while (work)		{		ImageTile *it;		it = work->data;		work = work->next;		pr_tile_free(it);		}	g_list_free(pr->tiles);	pr->tiles = NULL;	pr->tile_cache_size = 0;}static ImageTile *pr_tile_add(PixbufRenderer *pr, gint x, gint y){	ImageTile *it;	it = pr_tile_new(x, y, pr->tile_width, pr->tile_height);	if (it->x + it->w > pr->width) it->w = pr->width - it->x;	if (it->y + it->h > pr->height) it->h = pr->height - it->y;	pr->tiles = g_list_prepend(pr->tiles, it);	pr->tile_cache_size += it->size;	return it;}static void pr_tile_remove(PixbufRenderer *pr, ImageTile *it){	if (it->qd)		{		QueueData *qd = it->qd;		it->qd = NULL;		pr->draw_queue = g_list_remove(pr->draw_queue, qd);		g_free(qd);		}	if (it->qd2)		{		QueueData *qd = it->qd2;		it->qd2 = NULL;		pr->draw_queue_2pass = g_list_remove(pr->draw_queue_2pass, qd);		g_free(qd);		}	pr->tiles = g_list_remove(pr->tiles, it);	pr->tile_cache_size -= it->size;	pr_tile_free(it);}static void pr_tile_free_space(PixbufRenderer *pr, guint space, ImageTile *it){	GList *work;	gint tile_max;	work = g_list_last(pr->tiles);	if (pr->source_tiles_enabled && pr->scale < 1.0)		{		gint tiles;		tiles = (pr->vis_width / pr->tile_width + 1) * (pr->vis_height / pr->tile_height + 1);		tile_max = MAX(tiles * pr->tile_width * pr->tile_height * 3,			       (gint)((double)pr->tile_cache_max * 1048576.0 * pr->scale));		}	else		{		tile_max = pr->tile_cache_max * 1048576;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -