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