1 /* gdict-print.c - print-related helper functions
2 *
3 * This file is part of GNOME Dictionary
4 *
5 * Copyright (C) 2005 Emmanuele Bassi
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <math.h>
26
27 #include <glib/gi18n.h>
28 #include <gio/gio.h>
29 #include <gtk/gtk.h>
30
31 #include "gdict-pref-dialog.h"
32 #include "gdict-print.h"
33
34 #define HEADER_HEIGHT(lines) ((lines) * 72 / 25.4)
35 #define HEADER_GAP(lines) ((lines) * 72 / 25.4)
36
37 typedef struct _GdictPrintData
38 {
39 GdictDefbox *defbox;
40 gchar *word;
41
42 PangoFontDescription *font_desc;
43 gdouble font_size;
44
45 gchar **lines;
46
47 gint n_lines;
48 gint lines_per_page;
49 gint n_pages;
50 } GdictPrintData;
51
52 static void
begin_print(GtkPrintOperation * operation,GtkPrintContext * context,gpointer user_data)53 begin_print (GtkPrintOperation *operation,
54 GtkPrintContext *context,
55 gpointer user_data)
56 {
57 GdictPrintData *data = user_data;
58 gchar *contents;
59 gdouble height;
60
61 height = gtk_print_context_get_height (context)
62 - HEADER_HEIGHT (10)
63 - HEADER_GAP (3);
64
65 contents = gdict_defbox_get_text (data->defbox, NULL);
66
67 data->lines = g_strsplit (contents, "\n", 0);
68 data->n_lines = g_strv_length (data->lines);
69 data->lines_per_page = floor (height / data->font_size);
70
71 data->n_pages = (data->n_lines - 1) / data->lines_per_page + 1;
72
73 gtk_print_operation_set_n_pages (operation, data->n_pages);
74
75 g_free (contents);
76 }
77
78 static void
draw_page(GtkPrintOperation * operation,GtkPrintContext * context,gint page_number,gpointer user_data)79 draw_page (GtkPrintOperation *operation,
80 GtkPrintContext *context,
81 gint page_number,
82 gpointer user_data)
83 {
84 GdictPrintData *data = user_data;
85 cairo_t *cr;
86 PangoLayout *layout;
87 gint text_width, text_height;
88 gdouble width;
89 gint line, i;
90 PangoFontDescription *desc;
91 gchar *page_str;
92
93 cr = gtk_print_context_get_cairo_context (context);
94 width = gtk_print_context_get_width (context);
95
96 cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT (10));
97
98 cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
99 cairo_fill_preserve (cr);
100
101 cairo_set_source_rgb (cr, 0, 0, 0);
102 cairo_set_line_width (cr, 1);
103 cairo_stroke (cr);
104
105 /* header */
106 layout = gtk_print_context_create_pango_layout (context);
107
108 desc = pango_font_description_from_string ("sans 14");
109 pango_layout_set_font_description (layout, desc);
110 pango_font_description_free (desc);
111
112 pango_layout_set_text (layout, data->word, -1);
113 pango_layout_get_pixel_size (layout, &text_width, &text_height);
114
115 if (text_width > width)
116 {
117 pango_layout_set_width (layout, width);
118 pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_START);
119 pango_layout_get_pixel_size (layout, &text_width, &text_height);
120 }
121
122 cairo_move_to (cr, (width - text_width) / 2,
123 (HEADER_HEIGHT (10) - text_height) / 2);
124 pango_cairo_show_layout (cr, layout);
125
126 page_str = g_strdup_printf ("%d/%d", page_number + 1, data->n_pages);
127 pango_layout_set_text (layout, page_str, -1);
128 g_free (page_str);
129
130 pango_layout_set_width (layout, -1);
131 pango_layout_get_pixel_size (layout, &text_width, &text_height);
132 cairo_move_to (cr, width - text_width - 4,
133 (HEADER_HEIGHT (10) - text_height) / 2);
134 pango_cairo_show_layout (cr, layout);
135
136 g_object_unref (layout);
137
138 /* text */
139 layout = gtk_print_context_create_pango_layout (context);
140 pango_font_description_set_size (data->font_desc,
141 data->font_size * PANGO_SCALE);
142 pango_layout_set_font_description (layout, data->font_desc);
143
144 cairo_move_to (cr, 0, HEADER_HEIGHT (10) + HEADER_GAP (3));
145 line = page_number * data->lines_per_page;
146 for (i = 0; i < data->lines_per_page && line < data->n_lines; i++)
147 {
148 pango_layout_set_text (layout, data->lines[line], -1);
149
150 pango_cairo_show_layout (cr, layout);
151 cairo_rel_move_to (cr, 0, data->font_size);
152 line++;
153 }
154
155 g_object_unref (layout);
156 }
157
158 static void
end_print(GtkPrintOperation * operation,GtkPrintContext * context,gpointer user_data)159 end_print (GtkPrintOperation *operation,
160 GtkPrintContext *context,
161 gpointer user_data)
162 {
163 GdictPrintData *data = user_data;
164
165 pango_font_description_free (data->font_desc);
166 g_free (data->word);
167 g_strfreev (data->lines);
168 g_free (data);
169 }
170
171 static gchar *
get_print_font(void)172 get_print_font (void)
173 {
174 static GSettings *settings = NULL;
175
176 if (settings == NULL)
177 settings = g_settings_new ("org.gnome.dictionary");
178
179 return g_settings_get_string (settings, "print-font");
180 }
181
182 void
gdict_show_print_preview(GtkWindow * parent,GdictDefbox * defbox)183 gdict_show_print_preview (GtkWindow *parent,
184 GdictDefbox *defbox)
185 {
186 GtkPrintOperation *operation;
187 GdictPrintData *data;
188 gchar *print_font;
189 gchar *word;
190 GError *error;
191
192 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
193 g_return_if_fail (GDICT_IS_DEFBOX (defbox));
194
195 g_object_get (defbox, "word", &word, NULL);
196 if (!word)
197 {
198 g_warning ("Preview should be disabled.");
199 return;
200 }
201
202 data = g_new0 (GdictPrintData, 1);
203 data->defbox = defbox;
204 data->word = word;
205
206 operation = gtk_print_operation_new ();
207 print_font = get_print_font ();
208 data->font_desc = pango_font_description_from_string (print_font);
209 data->font_size = pango_font_description_get_size (data->font_desc)
210 / PANGO_SCALE;
211 g_free (print_font);
212
213 g_signal_connect (operation, "begin-print",
214 G_CALLBACK (begin_print), data);
215 g_signal_connect (operation, "draw-page",
216 G_CALLBACK (draw_page), data);
217 g_signal_connect (operation, "end-print",
218 G_CALLBACK (end_print), data);
219
220 error = NULL;
221 gtk_print_operation_run (operation,
222 GTK_PRINT_OPERATION_ACTION_PREVIEW,
223 parent,
224 &error);
225 g_object_unref (operation);
226
227 if (error)
228 {
229 GtkWidget *dialog;
230
231 dialog = gtk_message_dialog_new (parent,
232 GTK_DIALOG_DESTROY_WITH_PARENT,
233 GTK_MESSAGE_ERROR,
234 GTK_BUTTONS_CLOSE,
235 _("Unable to display the preview: %s"),
236 error->message);
237 g_error_free (error);
238
239 g_signal_connect (dialog, "response",
240 G_CALLBACK (gtk_widget_destroy), NULL);
241
242 gtk_widget_show (dialog);
243 }
244 }
245
246 void
gdict_show_print_dialog(GtkWindow * parent,GdictDefbox * defbox)247 gdict_show_print_dialog (GtkWindow *parent,
248 GdictDefbox *defbox)
249 {
250 GtkPrintOperation *operation;
251 GdictPrintData *data;
252 gchar *print_font;
253 gchar *word;
254 GError *error;
255
256 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
257 g_return_if_fail (GDICT_IS_DEFBOX (defbox));
258
259 g_object_get (defbox, "word", &word, NULL);
260 if (!word)
261 {
262 g_warning ("Print should be disabled.");
263 return;
264 }
265
266 data = g_new0 (GdictPrintData, 1);
267 data->defbox = defbox;
268 data->word = word;
269
270 operation = gtk_print_operation_new ();
271 print_font = get_print_font ();
272 data->font_desc = pango_font_description_from_string (print_font);
273 data->font_size = pango_font_description_get_size (data->font_desc)
274 / PANGO_SCALE;
275 g_free (print_font);
276
277 g_signal_connect (operation, "begin-print",
278 G_CALLBACK (begin_print), data);
279 g_signal_connect (operation, "draw-page",
280 G_CALLBACK (draw_page), data);
281 g_signal_connect (operation, "end-print",
282 G_CALLBACK (end_print), data);
283
284 error = NULL;
285 gtk_print_operation_run (operation,
286 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
287 parent,
288 &error);
289 g_object_unref (operation);
290
291 if (error)
292 {
293 GtkWidget *dialog;
294
295 dialog = gtk_message_dialog_new (parent,
296 GTK_DIALOG_DESTROY_WITH_PARENT,
297 GTK_MESSAGE_ERROR,
298 GTK_BUTTONS_CLOSE,
299 _("Unable to display the preview: %s"),
300 error->message);
301 g_error_free (error);
302
303 g_signal_connect (dialog, "response",
304 G_CALLBACK (gtk_widget_destroy), NULL);
305
306 gtk_widget_show (dialog);
307 }
308 }
309