📄 dw_image.c
字号:
/* * File: dw_image.c * * Copyright (C) 2001 Sebastian Geerken <S.Geerken@ping.de>, * Jorge Arellano Cid <jcid@dillo.org> * * 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 "msg.h"#include "dw_image.h"#include "dw_gtk_viewport.h"#include "prefs.h"#include "dw_marshal.h"#include "list.h"#include "dicache.h"#include "debug.h"#include <gdk/gdk.h>#include <gtk/gtk.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 gboolean Dw_image_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_image_button_release (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_image_motion_notify (DwWidget *widget, gint32 x, gint32 y, GdkEventMotion *event);static gboolean Dw_image_enter_notify (DwWidget *widget, DwWidget *last_widget, GdkEventMotion *event);static gboolean Dw_image_leave_notify (DwWidget *widget, DwWidget *next_widget, GdkEventMotion *event);static DwIterator* Dw_image_iterator (DwWidget *widget, gint32 mask, gboolean at_end);static void Dw_image_iterator_highlight (DwIterator *it, gint start, gint end, DwHighlightLayer layer);static void Dw_image_find_link (DwImage *image, gint x, gint y, gint *link, gint *link_x, gint *link_y);static void Dw_image_scale_row (DwImage *image, gint y_dest);static void Dw_image_scale (DwImage *image);static gint Dw_image_map_list_find_link (DwImageMapList *list, DilloUrl *url, gint x, gint y);#define Dw_image_scaled_y(image, y_src) \ ( (y_src) * ( ((DwWidget*)(image))->allocation.ascent + \ ((DwWidget*)(image))->allocation.descent - \ p_Dw_style_box_diff_height ( ((DwWidget*)(image))->style ) ) \ / ((DwImage*)(image))->height )enum{ LINK_ENTERED, LINK_PRESSED, LINK_RELEASED, LINK_CLICKED, LAST_SIGNAL};static guint image_signals[LAST_SIGNAL] = { 0 };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, (GtkClassInitFunc) NULL }; type = gtk_type_unique (DW_TYPE_WIDGET, &info); } return type;}/* * Standard Gtk+ function. */DwWidget* a_Dw_image_new (DwImageType type, const gchar *alt_text){ GtkObject *object; DwImage *image; object = gtk_object_new (DW_TYPE_IMAGE, NULL); DBG_OBJ_CREATE (object, "DwImage"); image = DW_IMAGE(object); image->alt_text = g_strdup (alt_text); return DW_WIDGET (object);}/* * Standard Gtk+ function. */static void Dw_image_init (DwImage *image){ int i; image->url = NULL; image->width = 0; image->height = 0; image->alt_text_width = -1; /* not yet calculated */ image->buffer = NULL; image->scaled_buffer = NULL; image->alt_text = NULL; image->usemap_url = NULL; image->ismap = FALSE; for (i = 0; i < DW_HIGHLIGHT_NUM_LAYERS; i++) image->selected[i] = FALSE;}/* * 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; image_signals[LINK_ENTERED] = gtk_signal_new ("link_entered", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwImageClass, link_entered), p_Dw_marshal_link_enter, GTK_TYPE_BOOL, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); image_signals[LINK_PRESSED] = gtk_signal_new ("link_pressed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwImageClass, link_pressed), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); image_signals[LINK_RELEASED] = gtk_signal_new ("link_released", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwImageClass, link_released), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); image_signals[LINK_CLICKED] = gtk_signal_new ("link_clicked", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwImageClass, link_clicked), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); gtk_object_class_add_signals (object_class, image_signals, LAST_SIGNAL); 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->button_press_event = Dw_image_button_press; widget_class->button_release_event = Dw_image_button_release; 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; widget_class->iterator = Dw_image_iterator;}/* * Standard Gtk+ function. */static void Dw_image_destroy (GtkObject *object){ DwImage *image = DW_IMAGE (object); if (image->usemap_url) a_Url_free (image->usemap_url); if (image->url) a_Dicache_unref (image->url, image->version); g_free (image->alt_text); g_free (image->scaled_buffer); GTK_OBJECT_CLASS(parent_class)->destroy (object);}/* * Standard Dw function. */static void Dw_image_size_request (DwWidget *widget, DwRequisition *requisition){ DwImage *image; image = DW_IMAGE (widget); if (image->buffer != NULL || (image->alt_text == NULL || image->alt_text[0] == '\0')) { requisition->width = image->width; requisition->ascent = image->height; requisition->descent = 0; } else { if (image->alt_text_width == -1) image->alt_text_width = gdk_string_width (widget->style->font->font, image->alt_text); requisition->width = image->alt_text_width; requisition->ascent = widget->style->font->font->ascent; requisition->descent = widget->style->font->font->descent; } requisition->width += p_Dw_style_box_diff_width (widget->style); requisition->ascent += p_Dw_style_box_offset_y (widget->style); requisition->descent += p_Dw_style_box_rest_height (widget->style);}/* * 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 == DW_WIDGET_HEIGHT(widget)) 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){ gint32 vx, vy; DwRectangle content, intersection; GdkGC *gc; DwImage *image = DW_IMAGE (widget); guchar *buffer, *bstart; int i; gboolean selected = FALSE; if (image->buffer) { p_Dw_widget_draw_widget_box (widget, area, FALSE); content.x = p_Dw_style_box_offset_x (widget->style); content.y = p_Dw_style_box_offset_y (widget->style); content.width = DW_WIDGET_CONTENT_WIDTH(widget); content.height = DW_WIDGET_CONTENT_HEIGHT(widget); if (p_Dw_rectangle_intersect (area, &content, &intersection)) { vx = p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x); vy = p_Dw_widget_y_world_to_viewport (widget, widget->allocation.y); gc = widget->style->color->gc; if (image->scaled_buffer) buffer = image->scaled_buffer; else buffer = image->buffer; bstart = buffer + 3 * ( intersection.x - p_Dw_style_box_offset_x (widget->style)+ content.width * (intersection.y - p_Dw_style_box_offset_y (widget->style)) ); gdk_draw_rgb_image ( DW_WIDGET_WINDOW (widget), gc, vx + intersection.x, vy + intersection.y, intersection.width, intersection.height, GDK_RGB_DITHER_MAX, bstart, content.width * 3); } } else { if (image->alt_text && image->alt_text[0]) { if (image->alt_text_width == -1) image->alt_text_width = gdk_string_width (widget->style->font->font, image->alt_text); if (widget->allocation.width < image->alt_text_width || widget->allocation.ascent + widget->allocation.descent < widget->style->font->font->ascent + widget->style->font->font->descent) p_Dw_widget_will_clip (widget); p_Dw_widget_draw_widget_box (widget, area, FALSE); gdk_draw_string (DW_WIDGET_WINDOW (widget), widget->style->font->font, widget->style->color->gc, p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x), p_Dw_widget_y_world_to_viewport (widget, widget->allocation.y) + widget->style->font->font->ascent, image->alt_text); } } for (i = 0; i < DW_HIGHLIGHT_NUM_LAYERS && !selected; i++) selected = image->selected[i]; if (selected) p_Dw_widget_draw_selected (widget, area);}/* * Standard Dw function. */static gboolean Dw_image_enter_notify (DwWidget *widget, DwWidget *last_widget, GdkEventMotion *event){ return FALSE;}/* * Standard Dw function. */static gboolean Dw_image_leave_notify (DwWidget *widget, DwWidget *next_widget, GdkEventMotion *event){ DwImage *image = DW_IMAGE (widget); gboolean return_val = FALSE; if (image->hover_link != -1) { image->hover_link = -1; gtk_signal_emit (GTK_OBJECT (widget), image_signals[LINK_ENTERED], -1, -1, -1, &return_val); return return_val; } return FALSE;}/* * Standard Dw function. */static gboolean Dw_image_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event){ DwImage *image = DW_IMAGE (widget); gint link_x, link_y; gboolean return_val = FALSE; Dw_image_find_link (image, x, y, &image->pressed_link, &link_x, &link_y); if (image->pressed_link >= 0) gtk_signal_emit (GTK_OBJECT (widget), image_signals[LINK_PRESSED], image->pressed_link, link_x, link_y, event, &return_val); return return_val;}/* * Standard Dw function. */static gboolean Dw_image_button_release (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event){ DwImage *image = DW_IMAGE (widget); gint link_pressed, link_released, link_x, link_y; gboolean return_val1 = FALSE, return_val2 = FALSE; link_pressed = image->pressed_link; Dw_image_find_link (image, x, y, &link_released, &link_x, &link_y); image->pressed_link = -1; if (link_released >= 0) { gtk_signal_emit (GTK_OBJECT (widget), image_signals[LINK_RELEASED], link_released, link_x, link_y, event, &return_val1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -