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