[gthumb] adjust colors: apply the changes to a scaled image for a faster preview



commit 3e8f4995d3733a308a344abf79e80dc8a94a13f4
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Aug 23 18:37:54 2012 +0200

    adjust colors: apply the changes to a scaled image for a faster preview

 extensions/file_tools/Makefile.am                  |    2 +
 .../file_tools/gth-file-tool-adjust-colors.c       |  233 +++++++++-----
 extensions/file_tools/gth-preview-tool.c           |  354 ++++++++++++++++++++
 extensions/file_tools/gth-preview-tool.h           |   61 ++++
 4 files changed, 572 insertions(+), 78 deletions(-)
---
diff --git a/extensions/file_tools/Makefile.am b/extensions/file_tools/Makefile.am
index feab2a1..ca57dd3 100644
--- a/extensions/file_tools/Makefile.am
+++ b/extensions/file_tools/Makefile.am
@@ -30,6 +30,7 @@ HEADER_FILES = 				\
 	gth-file-tool-undo.h		\
 	gth-image-line-tool.h		\
 	gth-image-rotator.h		\
+	gth-preview-tool.h		\
 	preferences.h
 
 enum-types.h: $(HEADER_FILES)
@@ -77,6 +78,7 @@ libfile_tools_la_SOURCES = 		\
 	gth-file-tool-undo.c		\
 	gth-image-line-tool.c		\
 	gth-image-rotator.c		\
+	gth-preview-tool.c		\
 	main.c
 
 libfile_tools_la_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
diff --git a/extensions/file_tools/gth-file-tool-adjust-colors.c b/extensions/file_tools/gth-file-tool-adjust-colors.c
index f604cf4..f22a375 100644
--- a/extensions/file_tools/gth-file-tool-adjust-colors.c
+++ b/extensions/file_tools/gth-file-tool-adjust-colors.c
@@ -24,37 +24,41 @@
 #include <gthumb.h>
 #include <extensions/image_viewer/gth-image-viewer-page.h>
 #include "gth-file-tool-adjust-colors.h"
+#include "gth-preview-tool.h"
 
 
 #define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
 #define APPLY_DELAY 150
-
+#define PREVIEW_SIZE 0.9
 
 G_DEFINE_TYPE (GthFileToolAdjustColors, gth_file_tool_adjust_colors, GTH_TYPE_FILE_TOOL)
 
 
 struct _GthFileToolAdjustColorsPrivate {
-	cairo_surface_t *source;
-	cairo_surface_t *destination;
-	GtkBuilder      *builder;
-	GtkAdjustment   *gamma_adj;
-	GtkAdjustment   *brightness_adj;
-	GtkAdjustment   *contrast_adj;
-	GtkAdjustment   *saturation_adj;
-	GtkAdjustment   *cyan_red_adj;
-	GtkAdjustment   *magenta_green_adj;
-	GtkAdjustment   *yellow_blue_adj;
-	GtkWidget       *histogram_view;
-	GthHistogram    *histogram;
-	GthTask         *image_task;
-	guint            apply_event;
+	cairo_surface_t    *source;
+	cairo_surface_t    *destination;
+	cairo_surface_t    *preview;
+	GtkBuilder         *builder;
+	GtkAdjustment      *gamma_adj;
+	GtkAdjustment      *brightness_adj;
+	GtkAdjustment      *contrast_adj;
+	GtkAdjustment      *saturation_adj;
+	GtkAdjustment      *cyan_red_adj;
+	GtkAdjustment      *magenta_green_adj;
+	GtkAdjustment      *yellow_blue_adj;
+	GtkWidget          *histogram_view;
+	GthHistogram       *histogram;
+	GthTask            *image_task;
+	guint               apply_event;
+	GthImageViewerTool *preview_tool;
+	gboolean            apply_to_original;
+	gboolean            closing;
 };
 
 
 typedef struct {
 	GthFileToolAdjustColors *self;
 	cairo_surface_t         *source;
-	cairo_surface_t         *destination;
 	GtkWidget               *viewer_page;
 	double                   gamma;
 	double                   brightness;
@@ -114,22 +118,23 @@ adjust_colors_exec (GthAsyncTask *task,
 	unsigned char   *p_destination;
 	gboolean         cancelled;
 	double           progress;
-	gboolean         terminated;
 	int              x, y;
 	unsigned char    values[4];
 	int              channel;
 	unsigned char    value;
+	cairo_surface_t *destination;
+	GthImage        *destination_image;
 
 	format = cairo_image_surface_get_format (adjust_data->source);
 	width = cairo_image_surface_get_width (adjust_data->source);
 	height = cairo_image_surface_get_height (adjust_data->source);
 	source_stride = cairo_image_surface_get_stride (adjust_data->source);
 
-	adjust_data->destination = cairo_image_surface_create (format, width, height);
-	cairo_surface_flush (adjust_data->destination);
-	destination_stride = cairo_image_surface_get_stride (adjust_data->destination);
+	destination = cairo_image_surface_create (format, width, height);
+	cairo_surface_flush (destination);
+	destination_stride = cairo_image_surface_get_stride (destination);
 	p_source_line = cairo_image_surface_get_data (adjust_data->source);
-	p_destination_line = cairo_image_surface_get_data (adjust_data->destination);
+	p_destination_line = cairo_image_surface_get_data (destination);
 	for (y = 0; y < height; y++) {
 		gth_async_task_get_data (task, NULL, &cancelled, NULL);
 		if (cancelled)
@@ -209,48 +214,85 @@ adjust_colors_exec (GthAsyncTask *task,
 		p_destination_line += destination_stride;
 	}
 
-	cairo_surface_mark_dirty (adjust_data->destination);
-	terminated = TRUE;
-	gth_async_task_set_data (task, &terminated, NULL, NULL);
+	cairo_surface_mark_dirty (destination);
+
+	destination_image = gth_image_new_for_surface (destination);
+	gth_image_task_set_destination (GTH_IMAGE_TASK (task), destination_image);
+
+	_g_object_unref (destination_image);
+	cairo_surface_destroy (destination);
 
 	return NULL;
 }
 
 
 static void
-adjust_colors_after (GthAsyncTask *task,
-		     GError       *error,
-		     gpointer      user_data)
+adjust_data_free (gpointer user_data)
 {
-	AdjustData              *adjust_data = user_data;
-	GthFileToolAdjustColors *self = adjust_data->self;
-
-	if (error == NULL) {
-		cairo_surface_destroy (self->priv->destination);
-		self->priv->destination = cairo_surface_reference (adjust_data->destination);
-
-		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("preview_checkbutton"))))
-			gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (adjust_data->viewer_page), self->priv->destination, FALSE);
-		gth_histogram_calculate_for_image (self->priv->histogram, self->priv->destination);
-	}
+	AdjustData *adjust_data = user_data;
 
 	pixbuf_cache_free (adjust_data->cache);
-
-	if (self->priv->image_task == GTH_TASK (task))
-		self->priv->image_task = NULL;
-	g_object_unref (task);
+	cairo_surface_destroy (adjust_data->source);
+	g_object_unref (adjust_data->viewer_page);
+	g_free (adjust_data);
 }
 
 
+static void apply_changes (GthFileToolAdjustColors *self);
+static void gth_file_tool_adjust_colors_cancel (GthFileTool *file_tool);
+
+
 static void
-adjust_data_free (gpointer user_data)
+image_task_completed_cb (GthTask  *task,
+			 GError   *error,
+			 gpointer  user_data)
 {
-	AdjustData *adjust_data = user_data;
+	GthFileToolAdjustColors *self = user_data;
+	GthImage                *destination_image;
 
-	cairo_surface_destroy (adjust_data->destination);
-	cairo_surface_destroy (adjust_data->source);
-	g_object_unref (adjust_data->viewer_page);
-	g_free (adjust_data);
+	self->priv->image_task = NULL;
+
+	if (self->priv->closing) {
+		g_object_unref (task);
+		gth_file_tool_adjust_colors_cancel (GTH_FILE_TOOL (self));
+		return;
+	}
+
+	if (error != NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			apply_changes (self);
+		g_object_unref (task);
+		return;
+	}
+
+	destination_image = gth_image_task_get_destination (GTH_IMAGE_TASK (task));
+	if (destination_image == NULL) {
+		g_object_unref (task);
+		return;
+	}
+
+	cairo_surface_destroy (self->priv->destination);
+	self->priv->destination = gth_image_get_cairo_surface (destination_image);
+
+	if (self->priv->apply_to_original) {
+		if (self->priv->destination != NULL) {
+			GtkWidget *window;
+			GtkWidget *viewer_page;
+
+			window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
+			viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
+			gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->destination, TRUE);
+		}
+
+		gth_file_tool_hide_options (GTH_FILE_TOOL (self));
+	}
+	else {
+		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("preview_checkbutton"))))
+			gth_preview_tool_set_image (GTH_PREVIEW_TOOL (self->priv->preview_tool), self->priv->destination);
+		gth_histogram_calculate_for_image (self->priv->histogram, self->priv->destination);
+	}
+
+	g_object_unref (task);
 }
 
 
@@ -275,16 +317,8 @@ ok_button_clicked_cb (GtkButton *button,
 {
 	GthFileToolAdjustColors *self = user_data;
 
-	if (self->priv->destination != NULL) {
-		GtkWidget *window;
-		GtkWidget *viewer_page;
-
-		window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
-		viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
-		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->destination, TRUE);
-	}
-
-	gth_file_tool_hide_options (GTH_FILE_TOOL (self));
+	self->priv->apply_to_original = TRUE;
+	apply_changes (self);
 }
 
 
@@ -316,15 +350,17 @@ apply_cb (gpointer user_data)
 		self->priv->apply_event = 0;
 	}
 
-	if (self->priv->image_task != NULL)
+	if (self->priv->image_task != NULL) {
 		gth_task_cancel (self->priv->image_task);
+		return FALSE;
+	}
 
 	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
 
 	adjust_data = g_new0 (AdjustData, 1);
 	adjust_data->self = self;
 	adjust_data->viewer_page = g_object_ref (gth_browser_get_viewer_page (GTH_BROWSER (window)));
-	adjust_data->source = cairo_surface_reference (self->priv->source);
+	adjust_data->source = cairo_surface_reference (self->priv->apply_to_original ? self->priv->source : self->priv->preview);
 	adjust_data->gamma = pow (10, - (gtk_adjustment_get_value (self->priv->gamma_adj) / 100.0));
 	adjust_data->brightness = gtk_adjustment_get_value (self->priv->brightness_adj) / 100.0 * -1.0;
 	adjust_data->contrast = gtk_adjustment_get_value (self->priv->contrast_adj) / 100.0 * -1.0;
@@ -333,11 +369,16 @@ apply_cb (gpointer user_data)
 	adjust_data->color_level[1] = gtk_adjustment_get_value (self->priv->magenta_green_adj);
 	adjust_data->color_level[2] = gtk_adjustment_get_value (self->priv->yellow_blue_adj);
 
-	self->priv->image_task = gth_async_task_new (adjust_colors_before,
+	self->priv->image_task = gth_image_task_new (_("Applying changes"),
+						     adjust_colors_before,
 						     adjust_colors_exec,
-						     adjust_colors_after,
+						     NULL,
 						     adjust_data,
 						     adjust_data_free);
+	g_signal_connect (self->priv->image_task,
+			  "completed",
+			  G_CALLBACK (image_task_completed_cb),
+			  self);
 	gth_browser_exec_task (GTH_BROWSER (window), self->priv->image_task, FALSE);
 
 	return FALSE;
@@ -345,8 +386,7 @@ apply_cb (gpointer user_data)
 
 
 static void
-value_changed_cb (GtkAdjustment           *adj,
-		  GthFileToolAdjustColors *self)
+apply_changes (GthFileToolAdjustColors *self)
 {
 	if (self->priv->apply_event != 0) {
 		g_source_remove (self->priv->apply_event);
@@ -357,19 +397,23 @@ value_changed_cb (GtkAdjustment           *adj,
 
 
 static void
+value_changed_cb (GtkAdjustment *adj,
+		  gpointer       user_data)
+{
+	apply_changes (GTH_FILE_TOOL_ADJUST_COLORS (user_data));
+}
+
+
+static void
 preview_checkbutton_toggled_cb (GtkToggleButton *togglebutton,
 				gpointer         user_data)
 {
 	GthFileToolAdjustColors *self = user_data;
-	GtkWidget               *window;
-	GtkWidget               *viewer_page;
 
-	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
-	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
 	if (gtk_toggle_button_get_active (togglebutton))
-		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->destination, FALSE);
+		gth_preview_tool_set_image (GTH_PREVIEW_TOOL (self->priv->preview_tool), self->priv->destination);
 	else
-		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->source, FALSE);
+		gth_preview_tool_set_image (GTH_PREVIEW_TOOL (self->priv->preview_tool), self->priv->preview);
 }
 
 
@@ -381,6 +425,8 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
 	GtkWidget               *viewer_page;
 	GtkWidget               *viewer;
 	GtkWidget               *options;
+	int                      width, height;
+	GtkAllocation            allocation;
 
 	self = (GthFileToolAdjustColors *) base;
 
@@ -391,13 +437,24 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
 
 	cairo_surface_destroy (self->priv->source);
 	cairo_surface_destroy (self->priv->destination);
+	cairo_surface_destroy (self->priv->preview);
 
 	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
 	self->priv->source = cairo_surface_reference (gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer)));
 	if (self->priv->source == NULL)
 		return NULL;
 
-	self->priv->destination = NULL;
+	width = cairo_image_surface_get_width (self->priv->source);
+	height = cairo_image_surface_get_height (self->priv->source);
+	gtk_widget_get_allocation (GTK_WIDGET (viewer), &allocation);
+	if (scale_keeping_ratio (&width, &height, PREVIEW_SIZE * allocation.width, PREVIEW_SIZE * allocation.height, FALSE))
+		self->priv->preview = _cairo_image_surface_scale_bilinear (self->priv->source, width, height);
+	else
+		self->priv->preview = cairo_surface_reference (self->priv->source);
+
+	self->priv->destination = cairo_surface_reference (self->priv->preview);
+	self->priv->apply_to_original = FALSE;
+	self->priv->closing = FALSE;
 
 	self->priv->builder = _gtk_builder_new_from_file ("adjust-colors-options.ui", "file_tools");
 	options = _gtk_builder_get_widget (self->priv->builder, "options");
@@ -474,7 +531,10 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
 			  G_CALLBACK (preview_checkbutton_toggled_cb),
 			  self);
 
-	gth_histogram_calculate_for_image (self->priv->histogram, self->priv->source);
+	self->priv->preview_tool = gth_preview_tool_new ();
+	gth_preview_tool_set_image (GTH_PREVIEW_TOOL (self->priv->preview_tool), self->priv->preview);
+	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), self->priv->preview_tool);
+	gth_histogram_calculate_for_image (self->priv->histogram, self->priv->preview);
 
 	return options;
 }
@@ -484,6 +544,9 @@ static void
 gth_file_tool_adjust_colors_destroy_options (GthFileTool *base)
 {
 	GthFileToolAdjustColors *self;
+	GtkWidget               *window;
+	GtkWidget               *viewer_page;
+	GtkWidget               *viewer;
 
 	self = (GthFileToolAdjustColors *) base;
 
@@ -492,12 +555,16 @@ gth_file_tool_adjust_colors_destroy_options (GthFileTool *base)
 		self->priv->apply_event = 0;
 	}
 
-	cairo_surface_destroy (self->priv->source);
-	cairo_surface_destroy (self->priv->destination);
-	_g_object_unref (self->priv->builder);
-	self->priv->source = NULL;
-	self->priv->destination = NULL;
-	self->priv->builder = NULL;
+	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
+	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
+	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
+	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), NULL);
+	gth_viewer_page_update_sensitivity (GTH_VIEWER_PAGE (viewer_page));
+
+	_cairo_clear_surface (&self->priv->preview);
+	_cairo_clear_surface (&self->priv->source);
+	_cairo_clear_surface (&self->priv->destination);
+	_g_clear_object (&self->priv->builder);
 }
 
 
@@ -515,6 +582,11 @@ gth_file_tool_adjust_colors_cancel (GthFileTool *file_tool)
 	GtkWidget               *window;
 	GtkWidget               *viewer_page;
 
+	if (self->priv->image_task != NULL) {
+		self->priv->closing = TRUE;
+		return;
+	}
+
 	if (self->priv->apply_event != 0) {
 		g_source_remove (self->priv->apply_event);
 		self->priv->apply_event = 0;
@@ -531,6 +603,10 @@ gth_file_tool_adjust_colors_init (GthFileToolAdjustColors *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_FILE_TOOL_ADJUST_COLORS, GthFileToolAdjustColorsPrivate);
 	self->priv->histogram = gth_histogram_new ();
+	self->priv->preview = NULL;
+	self->priv->source = NULL;
+	self->priv->destination = NULL;
+	self->priv->builder = NULL;
 
 	gth_file_tool_construct (GTH_FILE_TOOL (self), "tool-adjust-colors", _("Adjust Colors..."), _("Adjust Colors"), FALSE);
 	gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("Change brightness, contrast, saturation and gamma level of the image"));
@@ -547,6 +623,7 @@ gth_file_tool_adjust_colors_finalize (GObject *object)
 
 	self = (GthFileToolAdjustColors *) object;
 
+	cairo_surface_destroy (self->priv->preview);
 	cairo_surface_destroy (self->priv->source);
 	cairo_surface_destroy (self->priv->destination);
 	_g_object_unref (self->priv->builder);
diff --git a/extensions/file_tools/gth-preview-tool.c b/extensions/file_tools/gth-preview-tool.c
new file mode 100644
index 0000000..4689ae6
--- /dev/null
+++ b/extensions/file_tools/gth-preview-tool.c
@@ -0,0 +1,354 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <math.h>
+#include <gthumb.h>
+#include "gth-preview-tool.h"
+
+
+static void gth_preview_tool_gth_image_tool_interface_init (GthImageViewerToolInterface *iface);
+
+
+G_DEFINE_TYPE_WITH_CODE (GthPreviewTool,
+			 gth_preview_tool,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTH_TYPE_IMAGE_VIEWER_TOOL,
+					        gth_preview_tool_gth_image_tool_interface_init))
+
+
+
+struct _GthPreviewToolPrivate {
+	GthImageViewer        *viewer;
+	GthFit                 original_fit_mode;
+	gboolean               original_zoom_enabled;
+	cairo_surface_t       *preview_image;
+	cairo_rectangle_int_t  preview_image_area;
+	cairo_color_t          background_color;
+};
+
+
+static void
+gth_preview_tool_set_viewer (GthImageViewerTool *base,
+			     GthImageViewer     *viewer)
+{
+	GthPreviewTool *self = GTH_PREVIEW_TOOL (base);
+	GdkCursor      *cursor;
+
+	self->priv->viewer = viewer;
+	self->priv->original_fit_mode = gth_image_viewer_get_fit_mode (GTH_IMAGE_VIEWER (viewer));
+	self->priv->original_zoom_enabled = gth_image_viewer_get_zoom_enabled (GTH_IMAGE_VIEWER (viewer));
+	gth_image_viewer_set_fit_mode (GTH_IMAGE_VIEWER (viewer), GTH_FIT_SIZE_IF_LARGER);
+	gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), FALSE);
+
+	cursor = gdk_cursor_new (GDK_LEFT_PTR);
+	gth_image_viewer_set_cursor (self->priv->viewer, cursor);
+
+	g_object_unref (cursor);
+}
+
+
+static void
+gth_preview_tool_unset_viewer (GthImageViewerTool *base,
+			       GthImageViewer     *viewer)
+{
+	GthPreviewTool *self = GTH_PREVIEW_TOOL (base);
+
+	gth_image_viewer_set_fit_mode (GTH_IMAGE_VIEWER (viewer), self->priv->original_fit_mode);
+	gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), self->priv->original_zoom_enabled);
+	self->priv->viewer = NULL;
+}
+
+
+static void
+gth_preview_tool_realize (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+static void
+gth_preview_tool_unrealize (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+#if 0
+
+
+static void
+update_preview_image (GthPreviewTool *self)
+{
+	cairo_surface_t *image;
+	int              width;
+	int              height;
+	GtkAllocation    allocation;
+	int              max_size;
+
+	if (self->priv->preview_image != NULL) {
+		cairo_surface_destroy (self->priv->preview_image);
+		self->priv->preview_image = NULL;
+	}
+
+	image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (self->priv->viewer));
+	if (image == NULL)
+		return;
+
+	width = cairo_image_surface_get_width (image);
+	height = cairo_image_surface_get_height (image);
+	gtk_widget_get_allocation (GTK_WIDGET (self->priv->viewer), &allocation);
+	max_size = MAX (allocation.width, allocation.height) / G_SQRT2 + 2;
+	if (scale_keeping_ratio (&width, &height, max_size, max_size, FALSE))
+		self->priv->preview_image = _cairo_image_surface_scale_bilinear (image, width, height);
+	else
+		self->priv->preview_image = cairo_surface_reference (image);
+
+	self->priv->preview_image_area.width = width;
+	self->priv->preview_image_area.height = height;
+	self->priv->preview_image_area.x = MAX ((allocation.width - self->priv->preview_image_area.width) / 2 - 0.5, 0);
+	self->priv->preview_image_area.y = MAX ((allocation.height - self->priv->preview_image_area.height) / 2 - 0.5, 0);
+}
+
+
+#endif
+
+
+static void
+update_preview_image_area (GthPreviewTool *self)
+{
+	int           width;
+	int           height;
+	GtkAllocation allocation;
+
+	if ((self->priv->preview_image == NULL) || (self->priv->viewer == NULL))
+		return;
+
+	if (! gtk_widget_get_realized (GTK_WIDGET (self->priv->viewer)))
+		return;
+
+	width = cairo_image_surface_get_width (self->priv->preview_image);
+	height = cairo_image_surface_get_height (self->priv->preview_image);
+	gtk_widget_get_allocation (GTK_WIDGET (self->priv->viewer), &allocation);
+
+	self->priv->preview_image_area.width = width;
+	self->priv->preview_image_area.height = height;
+	self->priv->preview_image_area.x = MAX ((allocation.width - self->priv->preview_image_area.width) / 2 - 0.5, 0);
+	self->priv->preview_image_area.y = MAX ((allocation.height - self->priv->preview_image_area.height) / 2 - 0.5, 0);
+}
+
+
+static void
+gth_preview_tool_size_allocate (GthImageViewerTool *base,
+				GtkAllocation      *allocation)
+{
+	update_preview_image_area (GTH_PREVIEW_TOOL (base));
+}
+
+
+static void
+gth_preview_tool_map (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+static void
+gth_preview_tool_unmap (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+static void
+gth_preview_tool_draw (GthImageViewerTool *base,
+		       cairo_t            *cr)
+{
+	GthPreviewTool *self = GTH_PREVIEW_TOOL (base);
+	GtkAllocation   allocation;
+
+  	/* background */
+
+	cairo_save (cr);
+	gtk_widget_get_allocation (GTK_WIDGET (self->priv->viewer), &allocation);
+	cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
+
+  	cairo_set_source_rgba (cr,
+  			       self->priv->background_color.r,
+  			       self->priv->background_color.g,
+  			       self->priv->background_color.b,
+  			       self->priv->background_color.a);
+	cairo_fill (cr);
+	cairo_restore (cr);
+
+	/* image */
+
+	cairo_save (cr);
+
+	if (self->priv->preview_image != NULL) {
+		cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+		cairo_set_source_surface (cr, self->priv->preview_image,
+					  self->priv->preview_image_area.x,
+					  self->priv->preview_image_area.y);
+		cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_FAST);
+		cairo_rectangle (cr,
+				 self->priv->preview_image_area.x,
+				 self->priv->preview_image_area.y,
+				 self->priv->preview_image_area.width,
+				 self->priv->preview_image_area.height);
+		cairo_fill (cr);
+	}
+
+  	cairo_restore (cr);
+}
+
+
+static gboolean
+gth_preview_tool_button_release (GthImageViewerTool *base,
+				 GdkEventButton     *event)
+{
+	/* void */
+
+	return FALSE;
+}
+
+
+static gboolean
+gth_preview_tool_button_press (GthImageViewerTool *base,
+			       GdkEventButton     *event)
+{
+	/* void */
+
+	return FALSE;
+}
+
+
+static gboolean
+gth_preview_tool_motion_notify (GthImageViewerTool *base,
+				GdkEventMotion     *event)
+{
+	/* void */
+
+	return FALSE;
+}
+
+
+static void
+gth_preview_tool_image_changed (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+static void
+gth_preview_tool_zoom_changed (GthImageViewerTool *base)
+{
+	/* void */
+}
+
+
+static void
+gth_preview_tool_finalize (GObject *object)
+{
+	GthPreviewTool *self;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GTH_IS_PREVIEW_TOOL (object));
+
+	self = (GthPreviewTool *) object;
+	cairo_surface_destroy (self->priv->preview_image);
+
+	/* Chain up */
+	G_OBJECT_CLASS (gth_preview_tool_parent_class)->finalize (object);
+}
+
+
+static void
+gth_preview_tool_class_init (GthPreviewToolClass *class)
+{
+	GObjectClass *gobject_class;
+
+	g_type_class_add_private (class, sizeof (GthPreviewToolPrivate));
+
+	gobject_class = (GObjectClass*) class;
+	gobject_class->finalize = gth_preview_tool_finalize;
+}
+
+
+static void
+gth_preview_tool_gth_image_tool_interface_init (GthImageViewerToolInterface *iface)
+{
+	iface->set_viewer = gth_preview_tool_set_viewer;
+	iface->unset_viewer = gth_preview_tool_unset_viewer;
+	iface->realize = gth_preview_tool_realize;
+	iface->unrealize = gth_preview_tool_unrealize;
+	iface->size_allocate = gth_preview_tool_size_allocate;
+	iface->map = gth_preview_tool_map;
+	iface->unmap = gth_preview_tool_unmap;
+	iface->draw = gth_preview_tool_draw;
+	iface->button_press = gth_preview_tool_button_press;
+	iface->button_release = gth_preview_tool_button_release;
+	iface->motion_notify = gth_preview_tool_motion_notify;
+	iface->image_changed = gth_preview_tool_image_changed;
+	iface->zoom_changed = gth_preview_tool_zoom_changed;
+}
+
+
+static void
+gth_preview_tool_init (GthPreviewTool *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_PREVIEW_TOOL, GthPreviewToolPrivate);
+	self->priv->preview_image = NULL;
+	self->priv->background_color.r = 0.2;
+	self->priv->background_color.g = 0.2;
+	self->priv->background_color.b = 0.2;
+	self->priv->background_color.a = 1.0;
+}
+
+
+GthImageViewerTool *
+gth_preview_tool_new (void)
+{
+	return GTH_IMAGE_VIEWER_TOOL ( g_object_new (GTH_TYPE_PREVIEW_TOOL, NULL));
+}
+
+
+void
+gth_preview_tool_set_image (GthPreviewTool  *self,
+			    cairo_surface_t *modified)
+{
+	_cairo_clear_surface (&self->priv->preview_image);
+	if (modified != NULL) {
+		self->priv->preview_image = cairo_surface_reference (modified);
+		update_preview_image_area (self);
+	}
+
+	if (self->priv->viewer)
+		gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
+}
+
+
+cairo_surface_t *
+gth_preview_tool_get_image (GthPreviewTool *self)
+{
+	return self->priv->preview_image;
+}
diff --git a/extensions/file_tools/gth-preview-tool.h b/extensions/file_tools/gth-preview-tool.h
new file mode 100644
index 0000000..94f857a
--- /dev/null
+++ b/extensions/file_tools/gth-preview-tool.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_PREVIEW_TOOL_H
+#define GTH_PREVIEW_TOOL_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_PREVIEW_TOOL            (gth_preview_tool_get_type ())
+#define GTH_PREVIEW_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_PREVIEW_TOOL, GthPreviewTool))
+#define GTH_PREVIEW_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_PREVIEW_TOOL, GthPreviewToolClass))
+#define GTH_IS_PREVIEW_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_PREVIEW_TOOL))
+#define GTH_IS_PREVIEW_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_PREVIEW_TOOL))
+#define GTH_PREVIEW_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_PREVIEW_TOOL, GthPreviewToolClass))
+
+typedef struct _GthPreviewTool         GthPreviewTool;
+typedef struct _GthPreviewToolClass    GthPreviewToolClass;
+typedef struct _GthPreviewToolPrivate  GthPreviewToolPrivate;
+
+struct _GthPreviewTool
+{
+	GObject __parent;
+	GthPreviewToolPrivate *priv;
+};
+
+struct _GthPreviewToolClass
+{
+	GObjectClass __parent_class;
+};
+
+GType                 gth_preview_tool_get_type        (void);
+GthImageViewerTool *  gth_preview_tool_new             (void);
+void                  gth_preview_tool_set_image       (GthPreviewTool  *self,
+                                 	 	 	cairo_surface_t *image);
+cairo_surface_t *     gth_preview_tool_get_image       (GthPreviewTool  *self);
+
+G_END_DECLS
+
+#endif /* GTH_PREVIEW_TOOL_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]