[gthumb/ext: 2/20] load the images and draw the pages following the settings
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext: 2/20] load the images and draw the pages following the settings
- Date: Wed, 25 Nov 2009 17:13:00 +0000 (UTC)
commit 827a2cbfc2f266ddbeadc689b085e1619e91e675
Author: Paolo Bacchilega <paobac src gnome org>
Date: Thu Nov 19 01:32:25 2009 +0100
load the images and draw the pages following the settings
extensions/image_print/Makefile.am | 4 +
extensions/image_print/actions.c | 20 +-
extensions/image_print/gth-image-info.c | 130 +++++++
extensions/image_print/gth-image-info.h | 59 ++++
extensions/image_print/gth-image-print-job.c | 372 ++++++++++++++++-----
extensions/image_print/gth-image-print-job.h | 5 +-
extensions/image_print/gth-load-image-info-task.c | 211 ++++++++++++
extensions/image_print/gth-load-image-info-task.h | 58 ++++
gthumb/pixbuf-utils.c | 43 +++
gthumb/pixbuf-utils.h | 3 +
10 files changed, 813 insertions(+), 92 deletions(-)
---
diff --git a/extensions/image_print/Makefile.am b/extensions/image_print/Makefile.am
index a0f5a18..39641c1 100644
--- a/extensions/image_print/Makefile.am
+++ b/extensions/image_print/Makefile.am
@@ -8,8 +8,12 @@ libimage_print_la_SOURCES = \
actions.h \
callbacks.c \
callbacks.h \
+ gth-image-info.c \
+ gth-image-info.h \
gth-image-print-job.c \
gth-image-print-job.h \
+ gth-load-image-info-task.c \
+ gth-load-image-info-task.h \
main.c
libimage_print_la_CPPFLAGS = $(GTHUMB_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
diff --git a/extensions/image_print/actions.c b/extensions/image_print/actions.c
index 07aa398..6747733 100644
--- a/extensions/image_print/actions.c
+++ b/extensions/image_print/actions.c
@@ -31,10 +31,20 @@ void
gth_browser_activate_action_file_print (GtkAction *action,
GthBrowser *browser)
{
- GthImagePrintJob *print_job;
+ GList *items;
+ GList *file_list;
- print_job = gth_image_print_job_new (/* FIXME: pass the selected files */);
- gth_image_print_job_run (print_job,
- GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- GTK_WINDOW (browser));
+ items = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (browser)));
+ file_list = gth_file_list_get_files (GTH_FILE_LIST (gth_browser_get_file_list (browser)), items);
+ if (file_list != NULL) {
+ GthImagePrintJob *print_job;
+
+ print_job = gth_image_print_job_new (file_list);
+ gth_image_print_job_run (print_job,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ browser);
+ }
+
+ _g_object_list_unref (file_list);
+ _gtk_tree_path_list_free (items);
}
diff --git a/extensions/image_print/gth-image-info.c b/extensions/image_print/gth-image-info.c
new file mode 100644
index 0000000..35dc099
--- /dev/null
+++ b/extensions/image_print/gth-image-info.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include "gth-image-info.h"
+
+
+GthImageInfo *
+gth_image_info_new (GthFileData *file_data)
+{
+ GthImageInfo *image_info;
+
+ image_info = g_new0 (GthImageInfo, 1);
+ image_info->ref_count = 1;
+ image_info->file_data = g_object_ref (file_data);
+ image_info->pixbuf = NULL;
+ image_info->thumbnail = NULL;
+ image_info->thumbnail_active = NULL;
+ image_info->width = 0.0;
+ image_info->height = 0.0;
+ image_info->scale_x = 0.0;
+ image_info->scale_y = 0.0;
+ image_info->trans_x = 0.0;
+ image_info->trans_y = 0.0;
+ image_info->rotate = 0;
+ image_info->zoom = 0.0;
+ image_info->min_x = 0.0;
+ image_info->min_y = 0.0;
+ image_info->max_x = 0.0;
+ image_info->max_y = 0.0;
+ image_info->comment_height = 0.0;
+ image_info->print_comment = FALSE;
+
+ return image_info;
+}
+
+
+GthImageInfo *
+gth_image_info_ref (GthImageInfo *image_info)
+{
+ image_info->ref_count++;
+ return image_info;
+}
+
+
+void
+gth_image_info_unref (GthImageInfo *image_info)
+{
+ image_info->ref_count--;
+ if (image_info->ref_count > 0)
+ return;
+
+ _g_object_unref (image_info->file_data);
+ _g_object_unref (image_info->pixbuf);
+ _g_object_unref (image_info->thumbnail);
+ _g_object_unref (image_info->thumbnail_active);
+ g_free (image_info);
+}
+
+
+void
+gth_image_info_rotate (GthImageInfo *image_info,
+ int angle)
+{
+ GdkPixbuf *tmp_pixbuf;
+ GthTransform transform;
+
+ transform = GTH_TRANSFORM_NONE;
+ switch (angle) {
+ case 90:
+ transform = GTH_TRANSFORM_ROTATE_90;
+ break;
+ case 180:
+ transform = GTH_TRANSFORM_ROTATE_180;
+ break;
+ case 270:
+ transform = GTH_TRANSFORM_ROTATE_270;
+ break;
+ default:
+ break;
+ }
+
+ if (transform == GTH_TRANSFORM_NONE)
+ return;
+
+ tmp_pixbuf = image_info->pixbuf;
+ if (tmp_pixbuf != NULL) {
+ image_info->pixbuf = _gdk_pixbuf_transform (tmp_pixbuf, transform);
+ g_object_unref (tmp_pixbuf);
+ }
+
+ tmp_pixbuf = image_info->thumbnail;
+ if (tmp_pixbuf != NULL) {
+ image_info->thumbnail = _gdk_pixbuf_transform (tmp_pixbuf, transform);
+ g_object_unref (tmp_pixbuf);
+ }
+
+ tmp_pixbuf = image_info->thumbnail_active;
+ if (tmp_pixbuf != NULL) {
+ image_info->thumbnail_active = _gdk_pixbuf_transform (tmp_pixbuf, transform);
+ g_object_unref (tmp_pixbuf);
+ }
+
+ image_info->rotate = (image_info->rotate + angle) % 360;
+ if ((angle == 90) || (angle == 270)) {
+ int tmp = image_info->pixbuf_width;
+ image_info->pixbuf_width = image_info->pixbuf_height;
+ image_info->pixbuf_height = tmp;
+ }
+}
diff --git a/extensions/image_print/gth-image-info.h b/extensions/image_print/gth-image-info.h
new file mode 100644
index 0000000..07dacb4
--- /dev/null
+++ b/extensions/image_print/gth-image-info.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_IMAGE_INFO_H
+#define GTH_IMAGE_INFO_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+ int ref_count;
+ GthFileData *file_data;
+ int pixbuf_width;
+ int pixbuf_height;
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *thumbnail;
+ GdkPixbuf *thumbnail_active;
+ int n_page;
+ double width, height;
+ double scale_x, scale_y;
+ double trans_x, trans_y;
+ int rotate;
+ double zoom;
+ double min_x, min_y;
+ double max_x, max_y;
+ double comment_height;
+ gboolean print_comment;
+} GthImageInfo;
+
+GthImageInfo * gth_image_info_new (GthFileData *file_data);
+GthImageInfo * gth_image_info_ref (GthImageInfo *image_info);
+void gth_image_info_unref (GthImageInfo *image_info);
+void gth_image_info_rotate (GthImageInfo *image_info,
+ int angle);
+
+G_END_DECLS
+
+#endif /* GTH_IMAGE_INFO_H */
diff --git a/extensions/image_print/gth-image-print-job.c b/extensions/image_print/gth-image-print-job.c
index 83adf52..b60fad7 100644
--- a/extensions/image_print/gth-image-print-job.c
+++ b/extensions/image_print/gth-image-print-job.c
@@ -21,10 +21,13 @@
*/
#include <config.h>
+#include <math.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gthumb.h>
+#include "gth-image-info.h"
#include "gth-image-print-job.h"
+#include "gth-load-image-info-task.h"
#define GET_WIDGET(name) _gtk_builder_get_widget (self->priv->builder, (name))
@@ -33,77 +36,29 @@
static gpointer parent_class = NULL;
-typedef struct {
- GthFileData *file_data;
- char *comment;
- int pixbuf_width;
- int pixbuf_height;
- GdkPixbuf *thumbnail;
- GdkPixbuf *thumbnail_active;
- double width, height;
- double scale_x, scale_y;
- double trans_x, trans_y;
- int rotate;
- double zoom;
- double min_x, min_y;
- double max_x, max_y;
- double comment_height;
- gboolean print_comment;
-} ImageInfo;
-
-
-static ImageInfo *
-image_info_new (GthFileData *file_data)
-{
- ImageInfo *image = g_new0 (ImageInfo, 1);
-
- image->file_data = g_object_ref (file_data);
- image->comment = NULL;
- image->thumbnail = NULL;
- image->thumbnail_active = NULL;
- image->width = 0.0;
- image->height = 0.0;
- image->scale_x = 0.0;
- image->scale_y = 0.0;
- image->trans_x = 0.0;
- image->trans_y = 0.0;
- image->rotate = 0;
- image->zoom = 0.0;
- image->min_x = 0.0;
- image->min_y = 0.0;
- image->max_x = 0.0;
- image->max_y = 0.0;
- image->comment_height = 0.0;
- image->print_comment = FALSE;
-
- return image;
-}
-
-
-static void
-image_info_free (ImageInfo *image)
-{
- g_return_if_fail (image != NULL);
-
- g_object_unref (image->file_data);
- g_free (image->comment);
- _g_object_unref (image->thumbnail);
- _g_object_unref (image->thumbnail_active);
- g_free (image);
-}
-
-
-
struct _GthImagePrintJobPrivate {
- GtkWindow *parent;
+ GtkPrintOperationAction action;
+ GthBrowser *browser;
GtkPrintOperation *print_operation;
GtkBuilder *builder;
- ImageInfo **images;
+
+ /* settings */
+
+ GthImageInfo **images;
int n_images;
- int images_per_page;
+ int requested_images_per_page;
gboolean auto_sizing;
+ int image_width;
+ int image_height;
+ GtkPageSetup *page_setup;
+
+ /* layout info */
+
+ GthTask *task;
+ int real_images_per_page;
double max_image_width;
double max_image_height;
+ int n_pages;
};
@@ -115,11 +70,13 @@ gth_image_print_job_finalize (GObject *base)
self = GTH_IMAGE_PRINT_JOB (base);
+ _g_object_unref (self->priv->task);
_g_object_unref (self->priv->print_operation);
_g_object_unref (self->priv->builder);
for (i = 0; i < self->priv->n_images; i++)
- image_info_free (self->priv->images[i]);
+ gth_image_info_unref (self->priv->images[i]);
g_free (self->priv->images);
+ _g_object_unref (self->priv->page_setup);
G_OBJECT_CLASS (parent_class)->finalize (base);
}
@@ -143,6 +100,8 @@ gth_image_print_job_init (GthImagePrintJob *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE_PRINT_JOB, GthImagePrintJobPrivate);
self->priv->builder = NULL;
+ self->priv->task = NULL;
+ self->priv->page_setup = NULL;
}
@@ -202,22 +161,180 @@ operation_update_custom_widget_cb (GtkPrintOperation *operation,
GtkPrintSettings *settings,
gpointer user_data)
{
- /* FIXME */
+}
+
+
+enum {
+ IMAGES_PER_PAGE_1,
+ IMAGES_PER_PAGE_2,
+ IMAGES_PER_PAGE_4,
+ IMAGES_PER_PAGE_8,
+ IMAGES_PER_PAGE_16,
+ N_IMAGES_PER_PAGE
+};
+static int n_rows_for_ipp[N_IMAGES_PER_PAGE] = { 1, 2, 2, 4, 4 };
+static int n_cols_for_ipp[N_IMAGES_PER_PAGE] = { 1, 1, 2, 2, 4 };
+#define DEFAULT_PADDING 20.0
+
+
+static double
+_log2 (double x)
+{
+ return log (x) / log (2);
}
static void
print_operation_begin_print_cb (GtkPrintOperation *operation,
GtkPrintContext *context,
- GthImagePrintJob *self)
+ gpointer user_data)
{
- gtk_print_operation_set_n_pages (operation, 1);
+ GthImagePrintJob *self = user_data;
+ GtkPageSetup *setup;
+ gdouble page_width;
+ gdouble page_height;
+ double x_padding;
+ double y_padding;
+ int rows;
+ int cols;
+ int current_page;
+ int current_row;
+ int current_col;
+ int i;
- /* FIXME
- gtk_print_operation_set_n_pages (operation, (pci->n_images + pci->images_per_page - 1) / pci->images_per_page);
- gtk_print_operation_set_default_page_setup (operation, pci->page_setup);
- gtk_print_operation_set_show_progress (operation, TRUE);
- */
+ setup = gtk_print_context_get_page_setup (context);
+ page_width = gtk_print_context_get_width (context);
+ page_height = gtk_print_context_get_height (context);
+ x_padding = DEFAULT_PADDING;
+ y_padding = DEFAULT_PADDING;
+
+ if (self->priv->auto_sizing) {
+ int idx;
+
+ self->priv->real_images_per_page = self->priv->requested_images_per_page;
+
+ idx = (int) floor (_log2 (self->priv->real_images_per_page) + 0.5);
+ rows = n_rows_for_ipp[idx];
+ cols = n_cols_for_ipp[idx];
+ if ((gtk_page_setup_get_orientation (setup) == GTK_PAGE_ORIENTATION_LANDSCAPE)
+ || (gtk_page_setup_get_orientation (setup) == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE))
+ {
+ int tmp = rows;
+ rows = cols;
+ cols = tmp;
+ }
+
+ self->priv->max_image_width = (page_width - ((cols - 1) * x_padding)) / cols;
+ self->priv->max_image_height = (page_height - ((rows - 1) * y_padding)) / rows;
+ }
+ else {
+ double image_width;
+ double image_height;
+ double tmp_cols;
+ double tmp_rows;
+
+ image_width = self->priv->image_width;
+ image_height = self->priv->image_height;
+ tmp_cols = (int) floor ((page_width + x_padding) / (image_height + x_padding));
+ tmp_rows = (int) floor ((page_height + y_padding) / (image_width + y_padding));
+ cols = (int) floor ((page_width + x_padding) / (image_width + x_padding));
+ rows = (int) floor ((page_height + y_padding) / (image_height + y_padding));
+
+ if ((tmp_rows * tmp_cols > cols * rows)
+ && (image_height <= page_width)
+ && (image_width <= page_width))
+ {
+ double tmp = image_width;
+ image_width = image_height;
+ image_height = tmp;
+ rows = tmp_rows;
+ cols = tmp_cols;
+ }
+
+ if (rows == 0) {
+ rows = 1;
+ image_height = page_height - y_padding;
+ }
+
+ if (cols == 0) {
+ cols = 1;
+ image_width = page_width - x_padding;
+ }
+
+ self->priv->real_images_per_page = rows * cols;
+
+ if (cols > 1)
+ x_padding = (page_width - (cols * image_width)) / (cols - 1);
+ else
+ x_padding = page_width - image_width;
+
+ if (rows > 1)
+ y_padding = (page_height - (rows * image_height)) / (rows - 1);
+ else
+ y_padding = page_height - image_height;
+
+ self->priv->max_image_width = image_width;
+ self->priv->max_image_height = image_height;
+ }
+
+ self->priv->n_pages = MAX ((int) ceil ((double) self->priv->n_images / self->priv->real_images_per_page), 1);
+ gtk_print_operation_set_n_pages (operation, self->priv->n_pages);
+
+ current_page = 0;
+ current_row = 1;
+ current_col = 1;
+ for (i = 0; i < self->priv->n_images; i++) {
+ GthImageInfo *image_info = self->priv->images[i];
+ double max_image_width;
+ double max_image_height;
+ double image_width;
+ double image_height;
+ double factor;
+
+ image_info->n_page = current_page;
+
+ gth_image_info_rotate (image_info, (360 - image_info->rotate) % 360);
+ if (((self->priv->max_image_width > self->priv->max_image_height)
+ && (image_info->pixbuf_width < image_info->pixbuf_height))
+ || ((self->priv->max_image_width < self->priv->max_image_height)
+ && (image_info->pixbuf_width > image_info->pixbuf_height)))
+ {
+ gth_image_info_rotate (image_info, 270);
+ }
+
+ image_info->zoom = 1.0;
+ image_info->min_x = (current_col - 1) * (self->priv->max_image_width + x_padding);
+ image_info->min_y = (current_row - 1) * (self->priv->max_image_height + y_padding);
+ image_info->max_x = image_info->min_x + self->priv->max_image_width;
+ image_info->max_y = image_info->min_y + self->priv->max_image_height;
+
+ current_col++;
+ if (current_col > cols) {
+ current_row++;
+ current_col = 1;
+ }
+
+ max_image_width = self->priv->max_image_width;
+ max_image_height = self->priv->max_image_height;
+
+ /* FIXME: change max_image_width/max_image_height to make space to the comment */
+
+ image_width = (double) image_info->pixbuf_width;
+ image_height = (double) image_info->pixbuf_height;
+ factor = MIN (max_image_width / image_width, max_image_height / image_height);
+ image_info->width = image_width * factor;
+ image_info->height = image_height * factor;
+ image_info->trans_x = image_info->min_x + ((max_image_width - image_info->width) / 2);
+ image_info->trans_y = image_info->min_y + ((max_image_height - image_info->height) / 2);
+ image_info->scale_x = image_info->width * image_info->zoom;
+ image_info->scale_y = image_info->height * image_info->zoom;
+
+ if ((i + 1 < self->priv->n_images) && ((i + 1) % self->priv->real_images_per_page == 0)) {
+ current_page++;
+ current_col = 1;
+ current_row = 1;
+ }
+ }
}
@@ -227,14 +344,65 @@ print_operation_draw_page_cb (GtkPrintOperation *operation,
int page_nr,
GthImagePrintJob *self)
{
+ cairo_t *cr;
+ int i;
+
+ cr = gtk_print_context_get_cairo_context (context);
+
+ for (i = 0; i < self->priv->n_images; i++) {
+ GthImageInfo *image_info = self->priv->images[i];
+ double scale_factor;
+ GdkPixbuf *pixbuf;
+
+ if (image_info->n_page != page_nr)
+ continue;
+
+#if 0
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr,
+ image_info->trans_x,
+ image_info->trans_y,
+ image_info->width,
+ image_info->height);
+ cairo_stroke (cr);
+#endif
+
+ /* For higher-resolution images, cairo will render the bitmaps at a miserable
+ * 72 dpi unless we apply a scaling factor. This scaling boosts the output
+ * to 300 dpi (if required). */
+
+ scale_factor = MIN (image_info->pixbuf_width / image_info->scale_x, gtk_print_context_get_dpi_x (context) / 72.0);
+ pixbuf = gdk_pixbuf_scale_simple (image_info->pixbuf,
+ image_info->scale_x * scale_factor,
+ image_info->scale_y * scale_factor,
+ GDK_INTERP_BILINEAR);
+ cairo_save (cr);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, image_info->trans_x, image_info->trans_y);
+ cairo_rectangle (cr,
+ image_info->trans_x,
+ image_info->trans_y,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+ cairo_clip (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ g_object_unref (pixbuf);
+ }
+
+#if 0
cairo_t *cr;
PangoLayout *layout;
int y;
PangoRectangle rect;
+
cr = gtk_print_context_get_cairo_context (context);
cairo_set_source_rgb (cr, 0, 0, 0);
- cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), gtk_print_context_get_height (context));
+ cairo_rectangle (cr,
+ 0, 0,
+ gtk_print_context_get_width (context),
+ gtk_print_context_get_height (context));
cairo_stroke (cr);
layout = gtk_print_context_create_pango_layout (context);
@@ -273,6 +441,7 @@ print_operation_draw_page_cb (GtkPrintOperation *operation,
cairo_fill (cr);
g_object_unref (layout);
+#endif
}
@@ -287,7 +456,7 @@ print_operation_done_cb (GtkPrintOperation *operation,
GError *error = NULL;
gtk_print_operation_get_error (self->priv->print_operation, &error);
- _gtk_error_dialog_from_gerror_show (self->priv->parent, _("Could not print"), &error);
+ _gtk_error_dialog_from_gerror_show (GTK_WINDOW (self->priv->browser), _("Could not print"), &error);
return;
}
@@ -296,12 +465,24 @@ print_operation_done_cb (GtkPrintOperation *operation,
GthImagePrintJob *
-gth_image_print_job_new (void)
+gth_image_print_job_new (GList *file_data_list)
{
GthImagePrintJob *self;
+ GList *scan;
+ int n;
self = g_object_new (GTH_TYPE_IMAGE_PRINT_JOB, NULL);
+ self->priv->n_images = g_list_length (file_data_list);
+ self->priv->images = g_new (GthImageInfo *, self->priv->n_images + 1);
+ for (scan = file_data_list, n = 0; scan; scan = scan->next)
+ self->priv->images[n++] = gth_image_info_new ((GthFileData *) scan->data);
+ self->priv->images[n] = NULL;
+ self->priv->requested_images_per_page = 4; /* FIXME: set correct default values */
+ self->priv->auto_sizing = TRUE;
+ self->priv->image_width = 0;
+ self->priv->image_height = 0;
+
self->priv->print_operation = gtk_print_operation_new ();
gtk_print_operation_set_allow_async (self->priv->print_operation, TRUE);
gtk_print_operation_set_custom_tab_label (self->priv->print_operation, _("Layout"));
@@ -337,22 +518,43 @@ gth_image_print_job_new (void)
}
-void
-gth_image_print_job_run (GthImagePrintJob *self,
- GtkPrintOperationAction action,
- GtkWindow *parent)
+static void
+load_image_info_task_completed_cb (GthTask *task,
+ GError *error,
+ gpointer user_data)
{
+ GthImagePrintJob *self = user_data;
GtkPrintOperationResult result;
- GError *error = NULL;
- self->priv->parent = parent;
+ if (error != NULL) {
+ _gtk_error_dialog_from_gerror_show (GTK_WINDOW (self->priv->browser), _("Could not print"), &error);
+ return;
+ }
+
result = gtk_print_operation_run (self->priv->print_operation,
- action,
- parent,
+ self->priv->action,
+ GTK_WINDOW (self->priv->browser),
&error);
if (result == GTK_PRINT_OPERATION_RESULT_ERROR) {
- _gtk_error_dialog_from_gerror_show (parent, _("Could not print"), &error);
+ _gtk_error_dialog_from_gerror_show (GTK_WINDOW (self->priv->browser), _("Could not print"), &error);
return;
}
}
+
+void
+gth_image_print_job_run (GthImagePrintJob *self,
+ GtkPrintOperationAction action,
+ GthBrowser *browser)
+{
+ g_return_if_fail (self->priv->task == NULL);
+
+ self->priv->action = action;
+ self->priv->browser = browser;
+ self->priv->task = gth_load_image_info_task_new (self->priv->images, self->priv->n_images);
+ g_signal_connect (self->priv->task,
+ "completed",
+ G_CALLBACK (load_image_info_task_completed_cb),
+ self);
+ gth_browser_exec_task (browser, self->priv->task, FALSE);
+}
diff --git a/extensions/image_print/gth-image-print-job.h b/extensions/image_print/gth-image-print-job.h
index b762254..ffe198d 100644
--- a/extensions/image_print/gth-image-print-job.h
+++ b/extensions/image_print/gth-image-print-job.h
@@ -24,6 +24,7 @@
#define GTH_IMAGE_PRINT_JOB_H
#include <gtk/gtk.h>
+#include <gthumb.h>
G_BEGIN_DECLS
@@ -48,10 +49,10 @@ struct _GthImagePrintJobClass {
};
GType gth_image_print_job_get_type (void);
-GthImagePrintJob * gth_image_print_job_new (void);
+GthImagePrintJob * gth_image_print_job_new (GList *file_data_list);
void gth_image_print_job_run (GthImagePrintJob *self,
GtkPrintOperationAction action,
- GtkWindow *parent);
+ GthBrowser *browser);
G_END_DECLS
diff --git a/extensions/image_print/gth-load-image-info-task.c b/extensions/image_print/gth-load-image-info-task.c
new file mode 100644
index 0000000..2e6b8cd
--- /dev/null
+++ b/extensions/image_print/gth-load-image-info-task.c
@@ -0,0 +1,211 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gth-load-image-info-task.h"
+
+
+struct _GthLoadImageInfoTaskPrivate {
+ GthImageInfo **images;
+ int n_images;
+ int current;
+ GthImageLoader *loader;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_load_image_info_task_finalize (GObject *object)
+{
+ GthLoadImageInfoTask *self;
+ int i;
+
+ self = GTH_LOAD_IMAGE_INFO_TASK (object);
+
+ for (i = 0; i < self->priv->n_images; i++)
+ gth_image_info_unref (self->priv->images[i]);
+ g_free (self->priv->images);
+ g_object_unref (self->priv->loader);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void load_current_image (GthLoadImageInfoTask *self);
+
+
+static void
+image_loader_ready_cb (GthImageLoader *loader,
+ GError *error,
+ gpointer user_data)
+{
+ GthLoadImageInfoTask *self = user_data;
+ GdkPixbuf *pixbuf;
+
+ if (error != NULL) {
+ gth_task_completed (GTH_TASK (self), error);
+ return;
+ }
+
+ pixbuf = gth_image_loader_get_pixbuf (loader);
+ if (pixbuf != NULL) {
+ GthImageInfo *image_info;
+ int thumb_w, thumb_h;
+
+ image_info = self->priv->images[self->priv->current];
+ image_info->pixbuf = g_object_ref (pixbuf);
+
+ thumb_w = image_info->pixbuf_width = gdk_pixbuf_get_width (pixbuf);
+ thumb_h = image_info->pixbuf_height = gdk_pixbuf_get_height (pixbuf);
+ if (scale_keeping_ratio (&thumb_w, &thumb_h, 128, 128, FALSE))
+ image_info->thumbnail = gdk_pixbuf_scale_simple (pixbuf,
+ thumb_w,
+ thumb_h,
+ GDK_INTERP_BILINEAR);
+ else
+ image_info->thumbnail = g_object_ref (image_info->pixbuf);
+
+ if (image_info->thumbnail != NULL) {
+ image_info->thumbnail_active = gdk_pixbuf_copy (image_info->thumbnail);
+ _gdk_pixbuf_colorshift (image_info->thumbnail_active, image_info->thumbnail_active, 30);
+ }
+ }
+
+ self->priv->current++;
+ load_current_image (self);
+}
+
+
+static void
+load_current_image (GthLoadImageInfoTask *self)
+{
+ GthImageInfo *image_info;
+
+ if (self->priv->current >= self->priv->n_images) {
+ /* FIXME: read the required metadata as well */
+ gth_task_completed (GTH_TASK (self), NULL);
+ return;
+ }
+
+ image_info = self->priv->images[self->priv->current];
+ gth_image_loader_set_file_data (self->priv->loader, image_info->file_data);
+ gth_image_loader_load (self->priv->loader);
+}
+
+
+static void
+gth_load_image_info_task_exec (GthTask *task)
+{
+ GthLoadImageInfoTask *self;
+
+ g_return_if_fail (GTH_IS_LOAD_IMAGE_INFO_TASK (task));
+
+ self = GTH_LOAD_IMAGE_INFO_TASK (task);
+
+ load_current_image (self);
+}
+
+
+static void
+gth_load_image_info_task_cancelled (GthTask *task)
+{
+ /* FIXME */
+}
+
+
+static void
+gth_load_image_info_task_class_init (GthLoadImageInfoTaskClass *klass)
+{
+ GObjectClass *object_class;
+ GthTaskClass *task_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GthLoadImageInfoTaskPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gth_load_image_info_task_finalize;
+
+ task_class = GTH_TASK_CLASS (klass);
+ task_class->exec = gth_load_image_info_task_exec;
+ task_class->cancelled = gth_load_image_info_task_cancelled;
+}
+
+
+static void
+gth_load_image_info_task_init (GthLoadImageInfoTask *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_LOAD_IMAGE_INFO_TASK, GthLoadImageInfoTaskPrivate);
+ self->priv->loader = gth_image_loader_new (FALSE);
+ g_signal_connect (self->priv->loader,
+ "ready",
+ G_CALLBACK (image_loader_ready_cb),
+ self);
+}
+
+
+GType
+gth_load_image_info_task_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo type_info = {
+ sizeof (GthLoadImageInfoTaskClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gth_load_image_info_task_class_init,
+ NULL,
+ NULL,
+ sizeof (GthLoadImageInfoTask),
+ 0,
+ (GInstanceInitFunc) gth_load_image_info_task_init
+ };
+
+ type = g_type_register_static (GTH_TYPE_TASK,
+ "GthLoadImageInfoTask",
+ &type_info,
+ 0);
+ }
+
+ return type;
+}
+
+
+GthTask *
+gth_load_image_info_task_new (GthImageInfo **images,
+ int n_images)
+{
+ GthLoadImageInfoTask *self;
+ int n;
+
+ self = (GthLoadImageInfoTask *) g_object_new (GTH_TYPE_LOAD_IMAGE_INFO_TASK, NULL);
+ self->priv->images = g_new0 (GthImageInfo *, n_images + 1);
+ for (n = 0; n < n_images; n++)
+ self->priv->images[n] = gth_image_info_ref (images[n]);
+ self->priv->images[n] = NULL;
+ self->priv->n_images = n;
+ self->priv->current = 0;
+
+ return (GthTask *) self;
+}
diff --git a/extensions/image_print/gth-load-image-info-task.h b/extensions/image_print/gth-load-image-info-task.h
new file mode 100644
index 0000000..4a47e9b
--- /dev/null
+++ b/extensions/image_print/gth-load-image-info-task.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_LOAD_IMAGE_INFO_TASK_H
+#define GTH_LOAD_IMAGE_INFO_TASK_H
+
+#include <glib.h>
+#include <gthumb.h>
+#include "gth-image-info.h"
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_LOAD_IMAGE_INFO_TASK (gth_load_image_info_task_get_type ())
+#define GTH_LOAD_IMAGE_INFO_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_LOAD_IMAGE_INFO_TASK, GthLoadImageInfoTask))
+#define GTH_LOAD_IMAGE_INFO_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_LOAD_IMAGE_INFO_TASK, GthLoadImageInfoTaskClass))
+#define GTH_IS_LOAD_IMAGE_INFO_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_LOAD_IMAGE_INFO_TASK))
+#define GTH_IS_LOAD_IMAGE_INFO_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_LOAD_IMAGE_INFO_TASK))
+#define GTH_LOAD_IMAGE_INFO_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_LOAD_IMAGE_INFO_TASK, GthLoadImageInfoTaskClass))
+
+typedef struct _GthLoadImageInfoTask GthLoadImageInfoTask;
+typedef struct _GthLoadImageInfoTaskClass GthLoadImageInfoTaskClass;
+typedef struct _GthLoadImageInfoTaskPrivate GthLoadImageInfoTaskPrivate;
+
+struct _GthLoadImageInfoTask {
+ GthTask __parent;
+ GthLoadImageInfoTaskPrivate *priv;
+};
+
+struct _GthLoadImageInfoTaskClass {
+ GthTaskClass __parent;
+};
+
+GType gth_load_image_info_task_get_type (void);
+GthTask * gth_load_image_info_task_new (GthImageInfo **images,
+ int n_images);
+
+G_END_DECLS
+
+#endif /* GTH_LOAD_IMAGE_INFO_TASK_H */
diff --git a/gthumb/pixbuf-utils.c b/gthumb/pixbuf-utils.c
index bb16c8d..cbe0d1a 100644
--- a/gthumb/pixbuf-utils.c
+++ b/gthumb/pixbuf-utils.c
@@ -81,6 +81,49 @@ _gdk_pixbuf_transform (GdkPixbuf *src,
void
+_gdk_pixbuf_colorshift (GdkPixbuf *dest,
+ GdkPixbuf *src,
+ int shift)
+{
+ int i, j;
+ int width, height, has_alpha, srcrowstride, destrowstride;
+ guchar *target_pixels;
+ guchar *original_pixels;
+ guchar *pixsrc;
+ guchar *pixdest;
+ int val;
+ guchar r,g,b;
+
+ has_alpha = gdk_pixbuf_get_has_alpha (src);
+ width = gdk_pixbuf_get_width (src);
+ height = gdk_pixbuf_get_height (src);
+ srcrowstride = gdk_pixbuf_get_rowstride (src);
+ destrowstride = gdk_pixbuf_get_rowstride (dest);
+ target_pixels = gdk_pixbuf_get_pixels (dest);
+ original_pixels = gdk_pixbuf_get_pixels (src);
+
+ for (i = 0; i < height; i++) {
+ pixdest = target_pixels + i*destrowstride;
+ pixsrc = original_pixels + i*srcrowstride;
+ for (j = 0; j < width; j++) {
+ r = *(pixsrc++);
+ g = *(pixsrc++);
+ b = *(pixsrc++);
+ val = r + shift;
+ *(pixdest++) = CLAMP (val, 0, 255);
+ val = g + shift;
+ *(pixdest++) = CLAMP (val, 0, 255);
+ val = b + shift;
+ *(pixdest++) = CLAMP (val, 0, 255);
+
+ if (has_alpha)
+ *(pixdest++) = *(pixsrc++);
+ }
+ }
+}
+
+
+void
pixmap_from_xpm (const char **data,
GdkPixmap **pixmap,
GdkBitmap **mask)
diff --git a/gthumb/pixbuf-utils.h b/gthumb/pixbuf-utils.h
index e1d5efb..6cac12a 100644
--- a/gthumb/pixbuf-utils.h
+++ b/gthumb/pixbuf-utils.h
@@ -46,6 +46,9 @@ void _gdk_pixbuf_hv_gradient (GdkPixbuf *pixbuf,
guint32 vcolor2);
GdkPixbuf * _gdk_pixbuf_transform (GdkPixbuf *src,
GthTransform transform);
+void _gdk_pixbuf_colorshift (GdkPixbuf *dest,
+ GdkPixbuf *src,
+ int shift);
gboolean scale_keeping_ratio_min (int *width,
int *height,
int min_width,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]