1 /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
2 /* Balsa E-Mail Client
3  * Copyright (C) 1997-2013 Stuart Parmenter and others
4  * Written by (C) Albrecht Dre� <albrecht.dress@arcor.de> 2007
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  */
21 
22 #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
23 # include "config.h"
24 #endif                          /* HAVE_CONFIG_H */
25 #include "balsa-print-object-image.h"
26 #include "balsa-print-object-default.h"
27 
28 #include <gtk/gtk.h>
29 
30 /* object related functions */
31 static void
32 balsa_print_object_image_class_init(BalsaPrintObjectImageClass * klass);
33 static void balsa_print_object_image_init (GTypeInstance *instance,
34 					   gpointer g_class);
35 static void balsa_print_object_image_destroy(GObject * self);
36 
37 static void balsa_print_object_image_draw(BalsaPrintObject * self,
38 					  GtkPrintContext * context,
39 					  cairo_t * cairo_ctx);
40 
41 
42 static BalsaPrintObjectClass *parent_class = NULL;
43 
44 
45 GType
balsa_print_object_image_get_type()46 balsa_print_object_image_get_type()
47 {
48     static GType balsa_print_object_image_type = 0;
49 
50     if (!balsa_print_object_image_type) {
51 	static const GTypeInfo balsa_print_object_image_info = {
52 	    sizeof(BalsaPrintObjectImageClass),
53 	    NULL,		/* base_init */
54 	    NULL,		/* base_finalize */
55 	    (GClassInitFunc) balsa_print_object_image_class_init,
56 	    NULL,		/* class_finalize */
57 	    NULL,		/* class_data */
58 	    sizeof(BalsaPrintObjectImage),
59 	    0,			/* n_preallocs */
60 	    (GInstanceInitFunc) balsa_print_object_image_init
61 	};
62 
63 	balsa_print_object_image_type =
64 	    g_type_register_static(BALSA_TYPE_PRINT_OBJECT,
65 				   "BalsaPrintObjectImage",
66 				   &balsa_print_object_image_info, 0);
67     }
68 
69     return balsa_print_object_image_type;
70 }
71 
72 
73 static void
balsa_print_object_image_class_init(BalsaPrintObjectImageClass * klass)74 balsa_print_object_image_class_init(BalsaPrintObjectImageClass * klass)
75 {
76     parent_class = g_type_class_ref(BALSA_TYPE_PRINT_OBJECT);
77     BALSA_PRINT_OBJECT_CLASS(klass)->draw =
78 	balsa_print_object_image_draw;
79     G_OBJECT_CLASS(klass)->finalize = balsa_print_object_image_destroy;
80 }
81 
82 
83 static void
balsa_print_object_image_init(GTypeInstance * instance,gpointer g_class)84 balsa_print_object_image_init(GTypeInstance * instance, gpointer g_class)
85 {
86     BalsaPrintObjectImage *po = BALSA_PRINT_OBJECT_IMAGE(instance);
87 
88     po->pixbuf = NULL;
89     po->scale = 1.0;
90 }
91 
92 
93 static void
balsa_print_object_image_destroy(GObject * self)94 balsa_print_object_image_destroy(GObject * self)
95 {
96     BalsaPrintObjectImage *po = BALSA_PRINT_OBJECT_IMAGE(self);
97 
98     if (po->pixbuf)
99 	g_object_unref(po->pixbuf);
100 
101     G_OBJECT_CLASS(parent_class)->finalize(self);
102 }
103 
104 
105 GList *
balsa_print_object_image(GList * list,GtkPrintContext * context,LibBalsaMessageBody * body,BalsaPrintSetup * psetup)106 balsa_print_object_image(GList * list, GtkPrintContext *context,
107 			 LibBalsaMessageBody *body, BalsaPrintSetup * psetup)
108 {
109     BalsaPrintObjectImage *poi;
110     BalsaPrintObject *po;
111     GdkPixbuf *pixbuf;
112     GError *err = NULL;
113     gdouble c_use_width;
114     gdouble c_img_width;
115     gdouble c_img_height;
116 
117     /* check if we can handle the image */
118     pixbuf = libbalsa_message_body_get_pixbuf(body, &err);
119     if (err) {
120 	g_message("Error loading image from file: %s", err->message);
121 	g_error_free(err);
122     }
123 
124     /* fall back to default if the pixbuf could no be loaded */
125     if (!pixbuf)
126       return balsa_print_object_default(list, context, body, psetup);
127 
128     /* create the part */
129     poi = g_object_new(BALSA_TYPE_PRINT_OBJECT_IMAGE, NULL);
130     g_assert(poi != NULL);
131     po = BALSA_PRINT_OBJECT(poi);
132     po->depth = psetup->curr_depth;
133     poi->pixbuf = pixbuf;
134     c_use_width = psetup->c_width - 2 * psetup->curr_depth * C_LABEL_SEP;
135     c_img_width = gdk_pixbuf_get_width(pixbuf);
136     c_img_height = gdk_pixbuf_get_height(pixbuf);
137     poi->scale = 1.0;
138 
139     /* check if we should scale the width */
140     if (c_img_width > c_use_width) {
141 	poi->scale = c_use_width / c_img_width;
142 	c_img_height *= poi->scale;
143 	c_img_width = c_use_width;
144     }
145 
146     /* check if the image is too high for one full page */
147     if (c_img_height > psetup->c_height) {
148 	gdouble hscale = psetup->c_height / c_img_height;
149 	poi->scale *= hscale;
150 	c_img_width *= hscale;
151 	c_img_height = psetup->c_height;
152     }
153 
154     /* check if we should move to the next page */
155     if (psetup->c_y_pos + c_img_height > psetup->c_height) {
156 	psetup->c_y_pos = 0;
157 	psetup->page_count++;
158     }
159 
160     /* remember the extent */
161     po->on_page = psetup->page_count - 1;
162     po->c_at_x = psetup->c_x0 + psetup->curr_depth * C_LABEL_SEP;
163     po->c_at_y = psetup->c_y0 + psetup->c_y_pos;
164     po->c_width = c_img_width;
165     poi->c_img_offs = 0.5 * (c_use_width - c_img_width);
166     po->c_height = c_img_height;
167 
168     /* adjust the y position */
169     psetup->c_y_pos += c_img_height;
170 
171     return g_list_append(list, po);
172 }
173 
174 
175 static void
balsa_print_object_image_draw(BalsaPrintObject * self,GtkPrintContext * context,cairo_t * cairo_ctx)176 balsa_print_object_image_draw(BalsaPrintObject * self,
177 			      GtkPrintContext * context,
178 			      cairo_t * cairo_ctx)
179 {
180     BalsaPrintObjectImage *poi;
181 
182     /* prepare */
183     poi = BALSA_PRINT_OBJECT_IMAGE(self);
184     g_assert(poi != NULL);
185 
186     /* print the image */
187     cairo_print_pixbuf(cairo_ctx, poi->pixbuf, self->c_at_x + poi->c_img_offs,
188 		       self->c_at_y, poi->scale);
189 }
190