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 + -
显示快捷键?