[gthumb] rotate image: pass a cairo_surface to the rotate function, instead of a GdkPixbuf



commit 6316026c38e5187681b738bed9a54cc664f679cc
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon May 16 16:01:27 2011 +0200

    rotate image: pass a cairo_surface to the rotate function, instead of a GdkPixbuf

 extensions/file_tools/Makefile.am                  |    4 +-
 .../{gdk-pixbuf-rotate.c => cairo-rotate.c}        |  281 +++++++++-----------
 extensions/file_tools/cairo-rotate.h               |   50 ++++
 extensions/file_tools/gdk-pixbuf-rotate.h          |   56 ----
 extensions/file_tools/gth-file-tool-rotate.c       |  135 ++++++----
 5 files changed, 261 insertions(+), 265 deletions(-)
---
diff --git a/extensions/file_tools/Makefile.am b/extensions/file_tools/Makefile.am
index d8ea6dc..74a619a 100644
--- a/extensions/file_tools/Makefile.am
+++ b/extensions/file_tools/Makefile.am
@@ -9,7 +9,7 @@ ENUM_TYPES =		\
 
 HEADER_FILES = 				\
 	cairo-blur.h			\
-	gdk-pixbuf-rotate.h		\
+	cairo-rotate.h			\
 	gth-file-tool-adjust-colors.h	\
 	gth-file-tool-crop.h		\
 	gth-file-tool-desaturate.h	\
@@ -58,7 +58,7 @@ libfile_tools_la_SOURCES = 		\
 	callbacks.c			\
 	callbacks.h			\
 	cairo-blur.c			\
-	gdk-pixbuf-rotate.c		\
+	cairo-rotate.c			\
 	gth-file-tool-adjust-colors.c	\
 	gth-file-tool-crop.c		\
 	gth-file-tool-desaturate.c	\
diff --git a/extensions/file_tools/gdk-pixbuf-rotate.c b/extensions/file_tools/cairo-rotate.c
similarity index 55%
rename from extensions/file_tools/gdk-pixbuf-rotate.c
rename to extensions/file_tools/cairo-rotate.c
index 38a2984..7848548 100644
--- a/extensions/file_tools/gdk-pixbuf-rotate.c
+++ b/extensions/file_tools/cairo-rotate.c
@@ -21,22 +21,20 @@
 
 #include <math.h>
 #include <gthumb.h>
-#include "gdk-pixbuf-rotate.h"
+#include "cairo-rotate.h"
 
 
-#define PI 3.1415926535
-
 #define ROUND(x) ((int) floor ((x) + 0.5))
 
 #define INTERPOLATE(v00, v10, v01, v11, fx, fy) ((v00) + ((v10) - (v00)) * (fx) + ((v01) - (v00)) * (fy) + ((v00) - (v10) - (v01) + (v11)) * (fx) * (fy))
 
 #define GET_VALUES(r, g, b, a, x, y) \
 			if (x >= 0 && x < src_width && y >= 0 && y < src_height) { \
-				p_src2 = p_src + src_rowstride * y + n_channels * x; \
-				r = p_src2[RED_PIX]; \
-				g = p_src2[GREEN_PIX]; \
-				b = p_src2[BLUE_PIX]; \
-				a = (n_channels == 4) ? p_src2[ALPHA_PIX] : a0; \
+				p_src2 = p_src + src_rowstride * y + 4 * x; \
+				r = p_src2[CAIRO_RED]; \
+				g = p_src2[CAIRO_GREEN]; \
+				b = p_src2[CAIRO_BLUE]; \
+				a = p_src2[CAIRO_ALPHA]; \
 			} \
 			else { \
 				r = r0; \
@@ -47,10 +45,10 @@
 
 
 void
-_gdk_pixbuf_rotate_get_cropping_parameters (GdkPixbuf *src_pixbuf,
-					    double     angle,
-					    double    *p1_plus_p2,
-					    double    *p_min)
+_cairo_image_surface_rotate_get_cropping_parameters (cairo_surface_t *image,
+						     double           angle,
+						     double          *p1_plus_p2,
+						     double          *p_min)
 {
 	double angle_rad;
 	double cos_angle, sin_angle;
@@ -59,20 +57,20 @@ _gdk_pixbuf_rotate_get_cropping_parameters (GdkPixbuf *src_pixbuf,
 
 	angle = CLAMP (angle, -90.0, 90.0);
 
-	angle_rad = fabs (angle) / 180.0 * PI;
+	angle_rad = fabs (angle) / 180.0 * G_PI;
 
 	cos_angle = cos (angle_rad);
 	sin_angle = sin (angle_rad);
 
-	src_width  = gdk_pixbuf_get_width  (src_pixbuf) - 1;
-	src_height = gdk_pixbuf_get_height (src_pixbuf) - 1;
+	src_width  = cairo_image_surface_get_width  (image) - 1.0;
+	src_height = cairo_image_surface_get_height (image) - 1.0;
 
 	if (src_width > src_height) {
 		t1 = cos_angle * src_width - sin_angle * src_height;
 		t2 = sin_angle * src_width + cos_angle * src_height;
 
 		*p1_plus_p2  = 1.0 + (t1 * src_height) / (t2 * src_width);
-		
+
 		*p_min = src_height / src_width * sin_angle * cos_angle + (*p1_plus_p2 - 1) * cos_angle * cos_angle;
 	}
 	else {
@@ -80,37 +78,35 @@ _gdk_pixbuf_rotate_get_cropping_parameters (GdkPixbuf *src_pixbuf,
 		t2 = sin_angle * src_height + cos_angle * src_width;
 
 		*p1_plus_p2 = 1.0 + (t1 * src_width)  / (t2 * src_height);
-		
+
 		*p_min = src_width / src_height * sin_angle * cos_angle + (*p1_plus_p2 - 1) * cos_angle * cos_angle;
 	}
 }
 
 
 void
-_gdk_pixbuf_rotate_get_cropping_region (GdkPixbuf *src_pixbuf,
-					double        angle,
-					double        p1,
-					double        p2,
-					GdkRectangle *region)
+_cairo_image_surface_rotate_get_cropping_region (cairo_surface_t *image,
+						 double           angle,
+						 double           p1,
+						 double           p2,
+						 GdkRectangle    *region)
 {
 	double angle_rad;
 	double cos_angle, sin_angle;
 	double src_width, src_height;
 	double new_width;
-
 	double xx1, yy1, xx2, yy2;
 
 	angle = CLAMP (angle, -90.0, 90.0);
 	p1    = CLAMP (p1,      0.0,  1.0);
 	p2    = CLAMP (p2,      0.0,  1.0);
 
-	angle_rad = fabs (angle) / 180.0 * PI;
-
+	angle_rad = fabs (angle) / 180.0 * G_PI;
 	cos_angle = cos (angle_rad);
 	sin_angle = sin (angle_rad);
 
-	src_width  = gdk_pixbuf_get_width  (src_pixbuf) - 1;
-	src_height = gdk_pixbuf_get_height (src_pixbuf) - 1;
+	src_width  = cairo_image_surface_get_width  (image) - 1.0;
+	src_height = cairo_image_surface_get_height (image) - 1.0;
 
 	if (angle < 0) {
 
@@ -124,25 +120,20 @@ _gdk_pixbuf_rotate_get_cropping_region (GdkPixbuf *src_pixbuf,
 	}
 
 	if (src_width > src_height) {
-
 		xx1 = p1 * src_width * cos_angle + src_height * sin_angle;
 		yy1 = p1 * src_width * sin_angle;
-
 		xx2 = (1 - p2) * src_width * cos_angle;
 		yy2 = (1 - p2) * src_width * sin_angle + src_height * cos_angle;
 	}
 	else {
 		xx1 = p1       * src_height * sin_angle;
 		yy1 = (1 - p1) * src_height * cos_angle;
-
 		xx2 = (1 - p2) * src_height * sin_angle + src_width * cos_angle;
 		yy2 = p2       * src_height * cos_angle + src_width * sin_angle;
 	}
 
 	if (angle < 0) {
-
-		new_width  = cos_angle * src_width + sin_angle * src_height;
-
+		new_width = (cos_angle * src_width) + (sin_angle * src_height);
 		xx1 = new_width - xx1;
 		xx2 = new_width - xx2;
 	}
@@ -155,66 +146,88 @@ _gdk_pixbuf_rotate_get_cropping_region (GdkPixbuf *src_pixbuf,
 }
 
 
-static GdkPixbuf*
-rotate (GdkPixbuf *src_pixbuf,
-	double     angle,
-	gboolean   high_quality,
-	guchar     r0,
-	guchar     g0,
-	guchar     b0,
-	guchar     a0)
+double
+_cairo_image_surface_rotate_get_align_angle (gboolean vertical,
+					     GdkPoint p1,
+					     GdkPoint p2)
 {
-	GdkPixbuf *new_pixbuf;
-
-	double     angle_rad;
-	double     cos_angle, sin_angle;
-	double     src_width, src_height;
-	int        new_width, new_height;
-	int        src_rowstride, new_rowstride;
-	int        n_channels;
-	int        xi, yi;
-	double     x, y;
-	double     x2, y2;
-	int        x2min, y2min;
-	int        x2max, y2max;
-	double     fx, fy;
-	guchar    *p_src, *p_new;
-	guchar    *p_src2, *p_new2;
-
-	guchar     r00, r01, r10, r11;
-	guchar     g00, g01, g10, g11;
-	guchar     b00, b01, b10, b11;
-	guchar     a00, a01, a10, a11;
+	double angle;
 
-	angle = CLAMP (angle, -90.0, 90.0);
+	if (! vertical) {
+		if (p1.y == p2.y)
+			return 0.0;
 
-	angle_rad = angle / 180.0 * PI;
+		if (p2.x > p1.x)
+			angle = -atan2 (p2.y - p1.y, p2.x - p1.x);
+		else
+			angle = -atan2 (p1.y - p2.y, p1.x - p2.x);
+	}
+	else {
+		if (p1.x == p2.x)
+			return 0.0;
 
-	cos_angle = cos (angle_rad);
-	sin_angle = sin (angle_rad);
+		if (p2.y > p1.y)
+			angle = atan2 (p2.x - p1.x, p2.y - p1.y);
+		else
+			angle = atan2 (p1.x - p2.x, p1.y - p2.y);
+	}
+
+	angle = angle * 180.0 / G_PI;
+	angle = ROUND (angle * 10.0) / 10.0;
 
-	src_width  = gdk_pixbuf_get_width  (src_pixbuf) - 1;
-	src_height = gdk_pixbuf_get_height (src_pixbuf) - 1;
+	return angle;
+}
 
+
+static cairo_surface_t*
+rotate (cairo_surface_t *image,
+	double           angle,
+	gboolean         high_quality,
+	guchar           r0,
+	guchar           g0,
+	guchar           b0,
+	guchar           a0)
+{
+	cairo_surface_t *rotated;
+	double           angle_rad;
+	double           cos_angle, sin_angle;
+	double           src_width, src_height;
+	int              new_width, new_height;
+	int              src_rowstride, new_rowstride;
+	int              xi, yi;
+	double           x, y;
+	double           x2, y2;
+	int              x2min, y2min;
+	int              x2max, y2max;
+	double           fx, fy;
+	guchar          *p_src, *p_new;
+	guchar          *p_src2, *p_new2;
+	guchar           r00, r01, r10, r11;
+	guchar           g00, g01, g10, g11;
+	guchar           b00, b01, b10, b11;
+	guchar           a00, a01, a10, a11;
+	guchar           r, g, b, a;
+	guint32          pixel;
+
+	angle = CLAMP (angle, -90.0, 90.0);
+	angle_rad = angle / 180.0 * G_PI;
+	cos_angle = cos (angle_rad);
+	sin_angle = sin (angle_rad);
+	src_width  = cairo_image_surface_get_width  (image) - 1;
+	src_height = cairo_image_surface_get_height (image) - 1;
 	new_width  = ROUND (      cos_angle  * src_width + fabs(sin_angle) * src_height);
 	new_height = ROUND (fabs (sin_angle) * src_width +      cos_angle  * src_height);
 
-	new_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src_pixbuf),
-				     gdk_pixbuf_get_has_alpha (src_pixbuf),
-				     gdk_pixbuf_get_bits_per_sample (src_pixbuf),
-				     new_width,
-				     new_height);
-
-	p_src = gdk_pixbuf_get_pixels (src_pixbuf);
-	p_new = gdk_pixbuf_get_pixels (new_pixbuf);
+	rotated = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, new_width, new_height);
 
-	src_rowstride = gdk_pixbuf_get_rowstride (src_pixbuf);
-	new_rowstride = gdk_pixbuf_get_rowstride (new_pixbuf);
+	p_src = cairo_image_surface_get_data (image);
+	p_new = cairo_image_surface_get_data (rotated);
+	src_rowstride = cairo_image_surface_get_stride (image);
+	new_rowstride = cairo_image_surface_get_stride (rotated);
 
-	n_channels = gdk_pixbuf_get_n_channels (src_pixbuf);
+	cairo_surface_flush (rotated);
 
 	for (yi = 0; yi < new_height; yi++) {
-
 		p_new2 = p_new;
 
 		y = yi - new_height / 2.0;
@@ -227,8 +240,7 @@ rotate (GdkPixbuf *src_pixbuf,
 			y2 = sin_angle * x + cos_angle * y + src_height / 2.0;
 
 			if (high_quality) {
-
-				/* Bilinear interpolation */
+				/* Bilinear interpolation. FIXME: use a gaussian interpolation here */
 
 				x2min = (int) floor (x2);
 				y2min = (int) floor (y2);
@@ -244,12 +256,13 @@ rotate (GdkPixbuf *src_pixbuf,
 				GET_VALUES (r10, g10, b10, a10, x2min, y2max);
 				GET_VALUES (r11, g11, b11, a11, x2max, y2max);
 
-				p_new2[RED_PIX]   = CLAMP (INTERPOLATE (r00, r01, r10, r11, fx, fy), 0, 255);
-				p_new2[GREEN_PIX] = CLAMP (INTERPOLATE (g00, g01, g10, g11, fx, fy), 0, 255);
-				p_new2[BLUE_PIX]  = CLAMP (INTERPOLATE (b00, b01, b10, b11, fx, fy), 0, 255);
+				r = CLAMP (INTERPOLATE (r00, r01, r10, r11, fx, fy), 0, 255);
+				g = CLAMP (INTERPOLATE (g00, g01, g10, g11, fx, fy), 0, 255);
+				b = CLAMP (INTERPOLATE (b00, b01, b10, b11, fx, fy), 0, 255);
+				a = CLAMP (INTERPOLATE (a00, a01, a10, a11, fx, fy), 0, 255);
 
-				if (n_channels == 4)
-					p_new2[ALPHA_PIX]  = CLAMP (INTERPOLATE (a00, a01, a10, a11, fx, fy), 0, 255);
+				pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
+				memcpy (p_new2, &pixel, sizeof (guint32));
 			}
 			else {
 				/* Nearest neighbor */
@@ -257,84 +270,52 @@ rotate (GdkPixbuf *src_pixbuf,
 				x2min = ROUND (x2);
 				y2min = ROUND (y2);
 
-				if (n_channels == 4) {
-					GET_VALUES (p_new2[RED_PIX], p_new2[GREEN_PIX], p_new2[BLUE_PIX], p_new2[ALPHA_PIX], x2min, y2min);
-				}
-				else {
-					guchar t;
-					GET_VALUES (p_new2[RED_PIX], p_new2[GREEN_PIX], p_new2[BLUE_PIX], t, x2min, y2min);
-				}
+				GET_VALUES (p_new2[RED_PIX], p_new2[GREEN_PIX], p_new2[BLUE_PIX], p_new2[ALPHA_PIX], x2min, y2min);
 			}
 
-			p_new2 += n_channels;
+			p_new2 += 4;
 		}
 
 		p_new += new_rowstride;
 	}
 
-	return new_pixbuf;
-}
-
-
-double
-_gdk_pixbuf_rotate_get_align_angle (gboolean vertical,
-				    GdkPoint p1,
-				    GdkPoint p2)
-{
-	double angle;
-
-	if (! vertical) {
-
-		if (p1.y == p2.y)
-			return 0.0;
-
-		if (p2.x > p1.x)
-			angle = -atan2 (p2.y - p1.y, p2.x - p1.x);
-		else
-			angle = -atan2 (p1.y - p2.y, p1.x - p2.x);
-	}
-	else {
-
-		if (p1.x == p2.x)
-			return 0.0;
+	cairo_surface_mark_dirty (rotated);
 
-		if (p2.y > p1.y)
-			angle = atan2 (p2.x - p1.x, p2.y - p1.y);
-		else
-			angle = atan2 (p1.x - p2.x, p1.y - p2.y);
-	}
-
-	angle = angle * 180.0 / PI;
-	angle = ROUND (angle * 10.0) / 10.0;
-
-	return angle;
+	return rotated;
 }
 
 
-GdkPixbuf*
-_gdk_pixbuf_rotate (GdkPixbuf *src_pixbuf,
-		    double     angle,
-		    gboolean   high_quality,
-		    guchar     r0,
-		    guchar     g0,
-		    guchar     b0,
-		    guchar     a0)
+cairo_surface_t *
+_cairo_image_surface_rotate (cairo_surface_t   *image,
+		    	     double             angle,
+		    	     gboolean           high_quality,
+		    	     cairo_color_255_t *background_color)
 {
-	GdkPixbuf *new_pixbuf;
+	cairo_surface_t *rotated;
+	cairo_surface_t *tmp = NULL;
 
-	if (angle == 0.0) {
-		new_pixbuf = src_pixbuf;
-		g_object_ref (new_pixbuf);
-	}
-	else if (angle >= 90.0) {
-		new_pixbuf = gdk_pixbuf_rotate_simple (src_pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
+	if (angle >= 90.0) {
+		image = tmp = _cairo_image_surface_transform (image, GTH_TRANSFORM_ROTATE_90);
+		angle -= 90.0;
 	}
 	else if (angle <= -90.0) {
-		new_pixbuf = gdk_pixbuf_rotate_simple (src_pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
-	}
-	else {
-		new_pixbuf = rotate (src_pixbuf, -angle, high_quality, r0, g0, b0, a0);
+		image = tmp = _cairo_image_surface_transform (image, GTH_TRANSFORM_ROTATE_270);
+		angle += 90.0;
 	}
 
-	return new_pixbuf;
+	if (angle != 0.0)
+		rotated = rotate (image,
+				  -angle,
+				  high_quality,
+				  background_color->r,
+				  background_color->g,
+				  background_color->b,
+				  background_color->a);
+	else
+		rotated = cairo_surface_reference (image);
+
+	if (tmp != NULL)
+		cairo_surface_destroy (tmp);
+
+	return rotated;
 }
diff --git a/extensions/file_tools/cairo-rotate.h b/extensions/file_tools/cairo-rotate.h
new file mode 100644
index 0000000..dbf2030
--- /dev/null
+++ b/extensions/file_tools/cairo-rotate.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAIRO_ROTATE_H
+#define CAIRO_ROTATE_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+void               _cairo_image_surface_rotate_get_cropping_parameters (cairo_surface_t   *image,
+					   				double             angle,
+					   				double            *p1_plus_p2,
+					   				double            *p_min);
+void               _cairo_image_surface_rotate_get_cropping_region     (cairo_surface_t   *image,
+									double             angle,
+									double             p1,
+									double             p2,
+									GdkRectangle      *region);
+double             _cairo_image_surface_rotate_get_align_angle         (gboolean           vertical,
+					   	   	  	  	GdkPoint           p1,
+					   	   	  	  	GdkPoint           p2);
+cairo_surface_t *  _cairo_image_surface_rotate                         (cairo_surface_t   *image,
+		    	     	     	     	     	     	        double             angle,
+		    	     	     	     	     	     	        gboolean           high_quality,
+		    	     	     	     	     	     	        cairo_color_255_t *background_color);
+
+G_END_DECLS
+
+#endif /* CAIRO_ROTATE_H */
diff --git a/extensions/file_tools/gth-file-tool-rotate.c b/extensions/file_tools/gth-file-tool-rotate.c
index 4e6c756..c94a676 100644
--- a/extensions/file_tools/gth-file-tool-rotate.c
+++ b/extensions/file_tools/gth-file-tool-rotate.c
@@ -24,7 +24,7 @@
 #include <gthumb.h>
 #include <extensions/image_viewer/gth-image-viewer-page.h>
 #include "enum-types.h"
-#include "gdk-pixbuf-rotate.h"
+#include "cairo-rotate.h"
 #include "gth-file-tool-rotate.h"
 #include "gth-image-rotator.h"
 
@@ -37,29 +37,28 @@ static gpointer parent_class = NULL;
 
 
 struct _GthFileToolRotatePrivate {
-	GdkPixbuf        *src_pixbuf;
-	GdkPixbuf        *rotate_pixbuf;
-	gboolean          has_alpha;
-	GtkBuilder       *builder;
-	GtkWidget        *options;
-	GtkAdjustment    *rotation_angle_adj;
-	GtkWidget        *background_colorbutton;
-	GtkWidget        *background_transparent;
-	gboolean          crop_enabled;
-	GtkWidget        *show_grid;
-	GtkWidget        *keep_aspect_ratio;
-	GtkAdjustment    *crop_p1_adj;
-	GtkAdjustment    *crop_p2_adj;
-	double            crop_p1_plus_p2;
-	GtkWidget        *crop_grid;
-	GdkRectangle      crop_region;
-	GthImageSelector *selector_crop;
-	GthImageSelector *selector_align;
+	cairo_surface_t    *image;
+	gboolean            has_alpha;
+	GtkBuilder         *builder;
+	GtkWidget          *options;
+	GtkAdjustment      *rotation_angle_adj;
+	GtkWidget          *background_colorbutton;
+	GtkWidget          *background_transparent;
+	gboolean            crop_enabled;
+	GtkWidget          *show_grid;
+	GtkWidget          *keep_aspect_ratio;
+	GtkAdjustment      *crop_p1_adj;
+	GtkAdjustment      *crop_p2_adj;
+	double              crop_p1_plus_p2;
+	GtkWidget          *crop_grid;
+	GdkRectangle        crop_region;
+	GthImageSelector   *selector_crop;
+	GthImageSelector   *selector_align;
 	GthImageViewerTool *rotator;
-	guint             selector_align_direction;
-	guint             selector_align_point;
-	GdkPoint          align_points[2];
-	guint             apply_event;
+	guint               selector_align_direction;
+	guint               selector_align_point;
+	GdkPoint            align_points[2];
+	guint               apply_event;
 };
 
 
@@ -85,10 +84,10 @@ update_crop_parameters (GthFileToolRotate *self)
 			gtk_widget_set_sensitive (GET_WIDGET ("crop_p2_label"), FALSE);
 			gtk_widget_set_sensitive (GET_WIDGET ("crop_p2_hbox"), FALSE);
 
-			_gdk_pixbuf_rotate_get_cropping_parameters (self->priv->src_pixbuf,
-								    rotation_angle,
-								    &self->priv->crop_p1_plus_p2,
-								    &crop_p_min);
+			_cairo_image_surface_rotate_get_cropping_parameters (self->priv->image,
+								    	     rotation_angle,
+								    	     &self->priv->crop_p1_plus_p2,
+								    	     &crop_p_min);
 
 			/* This centers the cropping region in the middle of the rotated image */
 
@@ -133,11 +132,11 @@ update_crop_region (GthFileToolRotate *self)
 		rotation_angle = gtk_adjustment_get_value (self->priv->rotation_angle_adj);
 		crop_p1 = gtk_adjustment_get_value (self->priv->crop_p1_adj);
 		crop_p2 = gtk_adjustment_get_value (self->priv->crop_p2_adj);
-		_gdk_pixbuf_rotate_get_cropping_region (self->priv->src_pixbuf,
-							rotation_angle,
-							crop_p1,
-							crop_p2,
-							&self->priv->crop_region);
+		_cairo_image_surface_rotate_get_cropping_region (self->priv->image,
+								 rotation_angle,
+								 crop_p1,
+								 crop_p2,
+								 &self->priv->crop_region);
 		gth_image_rotator_set_crop_region (GTH_IMAGE_ROTATOR (self->priv->rotator), &self->priv->crop_region);
 	}
 	else
@@ -167,7 +166,8 @@ align_begin (GthFileToolRotate *self)
 
 	gtk_widget_set_sensitive (self->priv->options, FALSE);
 
-	gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->src_pixbuf, FALSE);
+	/* FIXME
+	gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->src_pixbuf, FALSE); */
 
 	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), (GthImageViewerTool *) self->priv->selector_align);
 }
@@ -178,16 +178,14 @@ align_end (GthFileToolRotate *self)
 {
 	GtkWidget *window;
 	GtkWidget *viewer_page;
-	GtkWidget *viewer;
 	double     angle;
 
 	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));
 
-	angle = _gdk_pixbuf_rotate_get_align_angle (self->priv->selector_align_direction == 1,
-						    self->priv->align_points[0],
-						    self->priv->align_points[1]),
+	angle = _cairo_image_surface_rotate_get_align_angle (self->priv->selector_align_direction == 1,
+						    	     self->priv->align_points[0],
+						    	     self->priv->align_points[1]),
 
 	self->priv->selector_align_direction = 0;
 	self->priv->selector_align_point = 0;
@@ -198,7 +196,9 @@ align_end (GthFileToolRotate *self)
 
 		/* We already have the pixmap ready */
 
+		/* FIXME
 		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->rotate_pixbuf, FALSE);
+		*/
 
 		update_crop_parameters (self);
 		update_crop_region (self);
@@ -313,9 +313,13 @@ static void
 apply_button_clicked_cb (GtkButton         *button,
 			 GthFileToolRotate *self)
 {
-	GtkWidget       *window;
-	GtkWidget       *viewer_page;
-	cairo_surface_t *image;
+	GtkWidget         *window;
+	GtkWidget         *viewer_page;
+	double             rotation_angle;
+	GdkColor           color;
+	cairo_color_255_t  background_color;
+	cairo_surface_t   *rotated;
+	cairo_surface_t   *image;
 
 #if 0
 	if (self->priv->rotate_pixbuf != self->priv->src_pixbuf) {
@@ -347,12 +351,31 @@ apply_button_clicked_cb (GtkButton         *button,
 	}
 #endif
 
+	rotation_angle = gtk_adjustment_get_value (self->priv->rotation_angle_adj);
+
+	gtk_color_button_get_color (GTK_COLOR_BUTTON (self->priv->background_colorbutton), &color);
+	background_color.r = color.red;
+	background_color.g = color.green;
+	background_color.b = color.blue;
+	background_color.a = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (self->priv->background_colorbutton));
+
+	rotated = _cairo_image_surface_rotate (self->priv->image, rotation_angle, TRUE, &background_color);
+	if (self->priv->crop_enabled)
+		image = _cairo_image_surface_copy_subsurface (rotated,
+							      self->priv->crop_region.x,
+							      self->priv->crop_region.y,
+							      self->priv->crop_region.width,
+							      self->priv->crop_region.height);
+	else
+		image = cairo_surface_reference (rotated);
+	/*image = gth_image_rotator_get_result (GTH_IMAGE_ROTATOR (self->priv->rotator)); FIXME*/
+
 	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
 	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
-
-	image = gth_image_rotator_get_result (GTH_IMAGE_ROTATOR (self->priv->rotator));
 	gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), image, TRUE);
+
 	cairo_surface_destroy (image);
+	cairo_surface_destroy (rotated);
 
 	gth_file_tool_hide_options (GTH_FILE_TOOL (self));
 }
@@ -475,15 +498,14 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 	if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page))
 		return NULL;
 
-	_g_clear_object (&self->priv->src_pixbuf);
-	_g_clear_object (&self->priv->rotate_pixbuf);
+	cairo_surface_destroy (self->priv->image);
 
 	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
-	self->priv->src_pixbuf = gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (viewer));
-	if (self->priv->src_pixbuf == NULL)
+	self->priv->image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+	if (self->priv->image == NULL)
 		return NULL;
 
-	self->priv->rotate_pixbuf = g_object_ref (self->priv->src_pixbuf);
+	cairo_surface_reference (self->priv->image);
 
 	self->priv->builder = _gtk_builder_new_from_file ("rotate-options.ui", "file_tools");
 
@@ -496,7 +518,7 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 	self->priv->background_colorbutton = _gtk_builder_get_widget (self->priv->builder, "background_colorbutton");
 	self->priv->background_transparent = _gtk_builder_get_widget (self->priv->builder, "background_transparent_checkbutton");
 
-	self->priv->has_alpha = gdk_pixbuf_get_n_channels (self->priv->src_pixbuf) == 4;
+	self->priv->has_alpha = _cairo_image_surface_get_has_alpha (self->priv->image);
 	if (self->priv->has_alpha) {
 		gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (self->priv->background_colorbutton), TRUE);
 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->background_transparent), TRUE);
@@ -537,8 +559,8 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 
 	self->priv->rotator = gth_image_rotator_new (GTH_IMAGE_VIEWER (viewer));
 	gth_image_rotator_set_center (GTH_IMAGE_ROTATOR (self->priv->rotator),
-				      gdk_pixbuf_get_width (self->priv->src_pixbuf) / 2,
-				      gdk_pixbuf_get_height (self->priv->src_pixbuf) / 2);
+				      cairo_image_surface_get_width (self->priv->image) / 2,
+				      cairo_image_surface_get_height (self->priv->image) / 2);
 	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), self->priv->rotator);
 	gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), FALSE);
 	gth_viewer_page_update_sensitivity (GTH_VIEWER_PAGE (viewer_page));
@@ -549,8 +571,8 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 	self->priv->crop_enabled = TRUE;
 	self->priv->crop_region.x = 0;
 	self->priv->crop_region.y = 0;
-	self->priv->crop_region.width = gdk_pixbuf_get_width (self->priv->src_pixbuf);
-	self->priv->crop_region.height = gdk_pixbuf_get_height (self->priv->src_pixbuf);
+	self->priv->crop_region.width = cairo_image_surface_get_width (self->priv->image);
+	self->priv->crop_region.height = cairo_image_surface_get_height (self->priv->image);
 
 	g_signal_connect (GET_WIDGET ("apply_button"),
 			  "clicked",
@@ -639,8 +661,8 @@ gth_file_tool_rotate_destroy_options (GthFileTool *base)
 	gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), TRUE);
 	gth_viewer_page_update_sensitivity (GTH_VIEWER_PAGE (viewer_page));
 
-	_g_clear_object (&self->priv->src_pixbuf);
-	_g_clear_object (&self->priv->rotate_pixbuf);
+	cairo_surface_destroy (self->priv->image);
+	self->priv->image = NULL;
 	_g_clear_object (&self->priv->builder);
 	_g_clear_object (&self->priv->selector_crop);
 	_g_clear_object (&self->priv->selector_align);
@@ -676,8 +698,7 @@ gth_file_tool_rotate_finalize (GObject *object)
 
 	self = (GthFileToolRotate *) object;
 
-	_g_object_unref (self->priv->src_pixbuf);
-	_g_object_unref (self->priv->rotate_pixbuf);
+	cairo_surface_destroy (self->priv->image);
 	_g_object_unref (self->priv->builder);
 
 	/* Chain up */



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