dw_image.c

来自「微型浏览器」· C语言 代码 · 共 386 行

C
386
字号
/* * File: dw_image.c * * Copyright (C) 2001 Sebastian Geerken  <S.Geerken@ping.de>, *                    Jorge Arellano Cid <jcid@inf.utfsm.cl> * * This program 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 2 of the License, or * (at your option) any later version. */#include "dw_image.h"#include <gdk/gdk.h>#include <stdio.h>#include <string.h>static void Dw_image_init(DwImage * image);static void Dw_image_class_init(DwImageClass * klass);static void Dw_image_destroy(GtkObject * object);static void Dw_image_size_request(DwWidget * widget, DwRequisition * requisition);static void Dw_image_size_allocate(DwWidget * widget, DwAllocation * allocation);static void Dw_image_draw(DwWidget * widget, DwRectangle * area, GdkEventExpose * event);static gint Dw_image_motion_notify(DwWidget * widget, gint32 x, gint32 y, GdkEventMotion * event);static gint Dw_image_enter_notify(DwWidget * widget, GdkEventMotion * event);static gint Dw_image_leave_notify(DwWidget * widget, GdkEventMotion * event);static void Dw_image_scale_row(DwImage * image, gint y_dest);static void Dw_image_scale(DwImage * image);#define Dw_image_scaled_y(image, y_src) \   ( (y_src) * ( ((DwWidget*)(image))->allocation.ascent +  \                 ((DwWidget*)(image))->allocation.descent ) \             / ((DwImage*)(image))->height );static DwWidgetClass *parent_class;/* * Standard Gtk+ function. */GtkType a_Dw_image_get_type(void){	static GtkType type = 0;	if (!type) {		GtkTypeInfo info = {			"DwImage",			sizeof(DwImage),			sizeof(DwImageClass),			(GtkClassInitFunc) Dw_image_class_init,			(GtkObjectInitFunc) Dw_image_init,			(GtkArgSetFunc) NULL,			(GtkArgGetFunc) NULL,		};		type = gtk_type_unique(DW_TYPE_WIDGET, &info);	}	return type;}/* * Standard Gtk+ function. */DwWidget *a_Dw_image_new(DwImageType type, const gchar * alt){	GtkObject *object;	object = gtk_object_new(DW_TYPE_IMAGE, NULL);	if (alt && alt[0])		DW_IMAGE(object)->alt_tooltip = a_Dw_tooltip_new(alt);	return DW_WIDGET(object);}/* * Standard Gtk+ function. */static void Dw_image_init(DwImage * image){	image->width = 0;	image->height = 0;	image->buffer = NULL;	image->scaled_buffer = NULL;	image->alt_tooltip = NULL;}/* * Standard Gtk+ function. */static void Dw_image_class_init(DwImageClass * klass){	GtkObjectClass *object_class;	DwWidgetClass *widget_class;	parent_class = gtk_type_class(DW_TYPE_WIDGET);	object_class = (GtkObjectClass *) klass;	object_class->destroy = Dw_image_destroy;	widget_class = (DwWidgetClass *) klass;	widget_class->size_request = Dw_image_size_request;	widget_class->size_allocate = Dw_image_size_allocate;	widget_class->draw = Dw_image_draw;	widget_class->motion_notify_event = Dw_image_motion_notify;	widget_class->enter_notify_event = Dw_image_enter_notify;	widget_class->leave_notify_event = Dw_image_leave_notify;}/* * Standard Gtk+ function. */static void Dw_image_destroy(GtkObject * object){	DwImage *image = DW_IMAGE(object);	if (image->alt_tooltip)		a_Dw_tooltip_destroy(image->alt_tooltip);	((GtkObjectClass *) parent_class)->destroy(object);	if (image->scaled_buffer)		g_free(image->scaled_buffer);}/* * Standard Dw function. */static void Dw_image_size_request(DwWidget * widget, DwRequisition * requisition){	DwImage *image;	image = DW_IMAGE(widget);	requisition->width = image->width;	requisition->ascent = image->height;	requisition->descent = 0;}/* * Standard Dw function. */static void Dw_image_size_allocate(DwWidget * widget, DwAllocation * allocation){	DwImage *image;	/* if image is moved only */	if (allocation->width == widget->allocation.width && allocation->ascent + allocation->descent == widget->allocation.ascent + widget->allocation.descent)		return;	/* this is also done in a_Dw_widget_size_allocate, but	   Dw_image_scale needs this. */	widget->allocation = *allocation;	image = DW_IMAGE(widget);	if (image->buffer != NULL && image->width > 0 && image->height > 0)		Dw_image_scale(image);}/* * Standard Dw function. */static void Dw_image_draw(DwWidget * widget, DwRectangle * area, GdkEventExpose * event){	gint vx, vy;	gint Width, Height;	GdkGC *gc;	DwImage *image = DW_IMAGE(widget);	guchar *buffer;	//g_print(">Area x=%d y=%d w=%d h=%d\n", area->x, area->y,	//        area->width, area->height);	vx = Dw_widget_x_world_to_viewport(widget, widget->allocation.x);	vy = Dw_widget_y_world_to_viewport(widget, widget->allocation.y);	/* todo: in future, every widget will probably have a style,	 * then this line should be used:	 * gc = widget->style->color->gc; */	gc = widget->viewport->style->fg_gc[widget->viewport->state];	Width = widget->allocation.width;	Height = widget->allocation.ascent + widget->allocation.descent;	if (image->buffer) {		if (image->scaled_buffer)			buffer = image->scaled_buffer;		else			buffer = image->buffer;		gdk_draw_rgb_image(widget->window, gc, vx + area->x, vy + area->y, area->width, area->height, GDK_RGB_DITHER_MAX, buffer + (area->y * widget->allocation.width + area->x) * 3, widget->allocation.width * 3);	}}/* * Standard Dw function. */static gint Dw_image_enter_notify(DwWidget * widget, GdkEventMotion * event){	DwImage *image = DW_IMAGE(widget);	if (image->alt_tooltip)		a_Dw_tooltip_on_enter(image->alt_tooltip);	return FALSE;}/* * Standard Dw function. */static gint Dw_image_leave_notify(DwWidget * widget, GdkEventMotion * event){	DwImage *image = DW_IMAGE(widget);	if (image->alt_tooltip)		a_Dw_tooltip_on_leave(image->alt_tooltip);	return FALSE;}/* * Standard Dw function. */static gint Dw_image_motion_notify(DwWidget * widget, gint32 x, gint32 y, GdkEventMotion * event){	DwImage *image = DW_IMAGE(widget);	if (image->alt_tooltip)		a_Dw_tooltip_on_motion(image->alt_tooltip);	return FALSE;}/* * Set or resize a image. */void a_Dw_image_size(DwImage * image, gint width, gint height){	gint Resize = (image->width != width || image->height != height);	image->width = width;	image->height = height;	if (Resize)		Dw_widget_queue_resize(DW_WIDGET(image));	if (image->buffer)		/* if a_Dw_image_set_buffer has been called before */		Dw_image_scale(image);}/* * Called after the RGB line buffer has been copied into the full * image buffer. Uses for drawing and scaling. */void a_Dw_image_draw_row(DwImage * image, gint Width, gint Height, gint x, gint y){	DwWidget *widget = DW_WIDGET(image);	gint dy1, dy2;	// g_print("a_Dw_image_draw_row: x=%d y=%d\n", x, y);	g_return_if_fail(image->buffer != NULL);	if (image->scaled_buffer) {		Dw_image_scale_row(image, y);		dy1 = Dw_image_scaled_y(image, y);		dy2 = Dw_image_scaled_y(image, y + 1);		Dw_widget_queue_draw_area(widget, x, dy1, widget->allocation.width, dy2 - dy1);	} else		Dw_widget_queue_draw_area(widget, x, y, widget->allocation.width, 1);}/* * Set the widget buffer to reference the dicache entry buffer */void a_Dw_image_set_buffer(DwImage * image, guchar * ImageBuffer){	image->buffer = ImageBuffer;	if (image->width > 0 && image->height > 0)		/* if a_Dw_image_set_size has been called before */		Dw_image_scale(image);}/* * Scale the whole image: Compare buffer size with allocation, and, if * necessary, allocate a second buffer and scale all rows. */static void Dw_image_scale(DwImage * image){	int w, h, y;	DwWidget *widget;	if (image->scaled_buffer) {		g_free(image->scaled_buffer);		image->scaled_buffer = NULL;	}	widget = DW_WIDGET(image);	w = widget->allocation.width;	h = widget->allocation.ascent + widget->allocation.descent;	/* Zero size? Ignore. */	if (w * h == 0)		return;	if (image->width != w || image->height != h) {		/* scaled image */		image->scaled_buffer = g_malloc(3 * w * h);		for (y = 0; y < image->height; y++)			Dw_image_scale_row(image, y);	}}/* * Scale one row. y_src is the row in the dicache buffer. */static void Dw_image_scale_row(DwImage * image, gint y_src){	DwWidget *widget;	guchar *src, *dest, *dest1;	gint w_src, w_dest, x_src, x_dest, y_dest1, y_dest2, y_dest, delta;	widget = DW_WIDGET(image);	w_src = image->width;	w_dest = widget->allocation.width;	y_dest1 = Dw_image_scaled_y(image, y_src);	y_dest2 = Dw_image_scaled_y(image, y_src + 1);	src = image->buffer + 3 * y_src * w_src;	if (y_dest1 != y_dest2) {		dest1 = image->scaled_buffer + 3 * y_dest1 * w_dest;		if (w_src == w_dest)			memcpy(dest1, src, 3 * w_src);		else if (w_dest > w_src) {			delta = w_src / 2;			x_src = 0;			x_dest = 0;			while (x_dest < w_dest) {				memcpy(dest1 + 3 * x_dest, src + 3 * x_src, 3);				x_dest++;				delta += w_src;				while (delta > w_dest) {					delta -= w_dest;					x_src++;				}			}		} else {			delta = w_dest / 2;			x_src = 0;			x_dest = 0;			while (x_src < w_src) {				memcpy(dest1 + 3 * x_dest, src + 3 * x_src, 3);				x_src++;				delta += w_dest;				while (delta > w_src) {					delta -= w_src;					x_dest++;				}			}		}		/* The other lines are simply copied. */		for (y_dest = y_dest1 + 1; y_dest < y_dest2; y_dest++) {			dest = image->scaled_buffer + 3 * y_dest * w_dest;			memcpy(dest, dest1, 3 * w_dest);		}	}}

⌨️ 快捷键说明

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