8032ac335045e0c39aa5b75013bea5e16d3a8cc4
[geeqie.git] / src / print.c
1 /*
2  * Copyright (C) 2018 The Geeqie Team
3  *
4  * Author: Colin Clark
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 of the License, or
9  * (at your option) 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 along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "main.h"
22 #include "print.h"
23
24 #include "exif.h"
25 #include "filedata.h"
26 #include "image-load.h"
27 #include "pixbuf_util.h"
28 #include "ui_misc.h"
29 #include "ui_fileops.h"
30
31 #define PRINT_SETTINGS "print_settings" // filename save printer settings
32 #define PAGE_SETUP "page_setup" // filename save page setup
33
34 /* padding between objects */
35 #define PRINT_TEXT_PADDING 3.0
36
37 /* method to use when scaling down image data */
38 #define PRINT_MAX_INTERP GDK_INTERP_HYPER
39
40 typedef enum {
41         TEXT_INFO_FILENAME = 1 << 0,
42         TEXT_INFO_FILEDATE = 1 << 1,
43         TEXT_INFO_FILESIZE = 1 << 2,
44         TEXT_INFO_DIMENSIONS = 1 << 3,
45         TEXT_INFO_FILEPATH = 1 << 4
46 } TextInfo;
47
48 /* reverse order is important */
49 typedef enum {
50         FOOTER_2,
51         FOOTER_1,
52         HEADER_2,
53         HEADER_1
54 } TextPosition;
55
56 typedef struct _PrintWindow PrintWindow;
57 struct _PrintWindow
58 {
59         GtkWidget *vbox;
60         GList *source_selection;
61
62         TextInfo        text_fields;
63         gint             job_page;
64         GtkTextBuffer *page_text;
65         ImageLoader     *job_loader;
66
67         GList *print_pixbuf_queue;
68         gboolean job_render_finished;
69         GSList *image_group;
70         GSList *page_group;
71 };
72
73 static gint print_layout_page_count(PrintWindow *pw)
74 {
75         gint images;
76
77         images = g_list_length(pw->source_selection);
78
79         if (images < 1 ) return 0;
80
81         return images;
82 }
83
84 static gboolean print_job_render_image(PrintWindow *pw);
85
86 static void print_job_render_image_loader_done(ImageLoader *il, gpointer data)
87 {
88         PrintWindow *pw = data;
89         GdkPixbuf *pixbuf;
90
91         pixbuf = image_loader_get_pixbuf(il);
92
93         g_object_ref(pixbuf);
94         pw->print_pixbuf_queue = g_list_append(pw->print_pixbuf_queue, pixbuf);
95
96         image_loader_free(pw->job_loader);
97         pw->job_loader = NULL;
98
99         pw->job_page++;
100
101         if (!print_job_render_image(pw))
102                 {
103                 pw->job_render_finished = TRUE;
104                 }
105 }
106
107 static gboolean print_job_render_image(PrintWindow *pw)
108 {
109         FileData *fd = NULL;
110
111         fd = g_list_nth_data(pw->source_selection, pw->job_page);
112         if (!fd) return FALSE;
113
114         image_loader_free(pw->job_loader);
115         pw->job_loader = NULL;
116
117         pw->job_loader = image_loader_new(fd);
118         g_signal_connect(G_OBJECT(pw->job_loader), "done",
119                                                 (GCallback)print_job_render_image_loader_done, pw);
120
121         if (!image_loader_start(pw->job_loader))
122                 {
123                 image_loader_free(pw->job_loader);
124                 pw->job_loader= NULL;
125                 }
126
127         return TRUE;
128 }
129
130 static void print_text_field_set(PrintWindow *pw, TextInfo field, gboolean active)
131 {
132         if (active)
133                 {
134                 pw->text_fields |= field;
135                 }
136         else
137                 {
138                 pw->text_fields &= ~field;
139                 }
140 }
141
142 static void print_text_cb_name(GtkWidget *widget, gpointer data)
143 {
144         PrintWindow *pw = data;
145         gboolean active;
146
147         active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
148         print_text_field_set(pw, TEXT_INFO_FILENAME, active);
149 }
150
151 static void print_text_cb_path(GtkWidget *widget, gpointer data)
152 {
153         PrintWindow *pw = data;
154         gboolean active;
155
156         active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
157         print_text_field_set(pw, TEXT_INFO_FILEPATH, active);
158 }
159
160 static void print_text_cb_date(GtkWidget *widget, gpointer data)
161 {
162         PrintWindow *pw = data;
163         gboolean active;
164
165         active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
166         print_text_field_set(pw, TEXT_INFO_FILEDATE, active);
167 }
168
169 static void print_text_cb_size(GtkWidget *widget, gpointer data)
170 {
171         PrintWindow *pw = data;
172         gboolean active;
173
174         active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
175         print_text_field_set(pw, TEXT_INFO_FILESIZE, active);
176 }
177
178 static void print_text_cb_dims(GtkWidget *widget, gpointer data)
179 {
180         PrintWindow *pw = data;
181         gboolean active;
182
183         active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
184         print_text_field_set(pw, TEXT_INFO_DIMENSIONS, active);
185 }
186
187 static void print_set_font_cb(GtkWidget *widget, gpointer data)
188 {
189         gpointer option;
190
191         if (g_strcmp0(data, "Image text font") == 0)
192                 {
193                 option = options->printer.image_font;
194                 }
195         else
196                 {
197                 option = options->printer.page_font;
198                 }
199
200 #if GTK_CHECK_VERSION(3,4,0)
201         GtkWidget *dialog;
202         char *font;
203         PangoFontDescription *font_desc;
204
205         dialog = gtk_font_chooser_dialog_new(data, GTK_WINDOW(gtk_widget_get_toplevel(widget)));
206         gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), option);
207
208         if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
209                 {
210                 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
211                 font = pango_font_description_to_string(font_desc);
212                 g_free(option);
213                 option = g_strdup(font);
214                 g_free(font);
215                 }
216
217         gtk_widget_destroy(dialog);
218 #else
219         const char *font;
220
221         font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
222         option = g_strdup(font);
223 #endif
224 }
225
226 static gint set_toggle(GSList *list, TextPosition pos)
227 {
228         GtkToggleButton *current_sel;
229         GtkToggleButton *new_sel;
230         gint new_pos = - 1;
231
232         current_sel = g_slist_nth(list, pos)->data;
233         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(current_sel)))
234                 {
235                 new_pos = (pos - 1);
236                 if (new_pos < 0)
237                         {
238                         new_pos = HEADER_1;
239                         }
240                 new_sel = g_slist_nth(list, new_pos)->data;
241                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(new_sel), TRUE);
242                 }
243         return new_pos;
244 }
245
246 static void image_text_position_h1_cb(GtkWidget *widget, gpointer data)
247 {
248         PrintWindow *pw = data;
249         gint new_set;
250
251         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
252                 {
253                 new_set = set_toggle(pw->page_group, HEADER_1);
254                 if (new_set >= 0)
255                         {
256                         options->printer.page_text_position = new_set;
257                         }
258                 options->printer.image_text_position = HEADER_1;
259                 }
260 }
261
262 static void image_text_position_h2_cb(GtkWidget *widget, gpointer data)
263 {
264         PrintWindow *pw = data;
265         gint new_set;
266
267         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
268                 {
269                 new_set = set_toggle(pw->page_group, HEADER_2);
270                 if (new_set >= 0)
271                         {
272                         options->printer.page_text_position = new_set;
273                         }
274                 options->printer.image_text_position = HEADER_2;
275                 }
276 }
277
278 static void image_text_position_f1_cb(GtkWidget *widget, gpointer data)
279 {
280         PrintWindow *pw = data;
281         gint new_set;
282
283         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
284                 {
285                 new_set = set_toggle(pw->page_group, FOOTER_1);
286                 if (new_set >= 0)
287                         {
288                         options->printer.page_text_position = new_set;
289                         }
290                 options->printer.image_text_position = FOOTER_1;
291                 }
292 }
293
294 static void image_text_position_f2_cb(GtkWidget *widget, gpointer data)
295 {
296         PrintWindow *pw = data;
297         gint new_set;
298
299         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
300                 {
301                 new_set = set_toggle(pw->page_group, FOOTER_2);
302                 if (new_set >= 0)
303                         {
304                         options->printer.page_text_position = new_set;
305                         }
306                 options->printer.image_text_position = FOOTER_2;
307                 }
308 }
309
310 static void page_text_position_h1_cb(GtkWidget *widget, gpointer data)
311 {
312         PrintWindow *pw = data;
313         gint new_set;
314
315         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
316                 {
317                 new_set = set_toggle(pw->image_group, HEADER_1);
318                 if (new_set >= 0)
319                         {
320                         options->printer.image_text_position = new_set;
321                         }
322                 options->printer.page_text_position = HEADER_1;
323                 }
324 }
325
326 static void page_text_position_h2_cb(GtkWidget *widget, gpointer data)
327 {
328         PrintWindow *pw = data;
329         gint new_set;
330
331         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
332                 {
333                 new_set = set_toggle(pw->image_group, HEADER_2);
334                 if (new_set >= 0)
335                         {
336                         options->printer.image_text_position = new_set;
337                         }
338                 options->printer.page_text_position = HEADER_2;
339                 }
340 }
341
342 static void page_text_position_f1_cb(GtkWidget *widget, gpointer data)
343 {
344         PrintWindow *pw = data;
345         gint new_set;
346
347         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
348                 {
349                 new_set = set_toggle(pw->image_group, FOOTER_1);
350                 if (new_set >= 0)
351                         {
352                         options->printer.image_text_position = new_set;
353                         }
354                 options->printer.page_text_position = FOOTER_1;
355                 }
356 }
357
358 static void page_text_position_f2_cb(GtkWidget *widget, gpointer data)
359 {
360         PrintWindow *pw = data;
361         gint new_set;
362
363         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
364                 {
365                 new_set = set_toggle(pw->image_group, FOOTER_2);
366                 if (new_set >= 0)
367                         {
368                         options->printer.image_text_position = new_set;
369                         }
370                 options->printer.page_text_position = FOOTER_2;
371                 }
372 }
373
374 static void print_text_menu(GtkWidget *box, PrintWindow *pw)
375 {
376         GtkWidget *group;
377         GtkWidget *hbox;
378         GtkWidget *button;
379         GtkWidget *button1;
380         GtkWidget *button2;
381         GtkWidget *image_text_button;
382         GtkWidget *page_text_button;
383         GtkWidget *subgroup;
384         GtkWidget *page_text_view;
385
386         group = pref_group_new(box, FALSE, _("Image text"), GTK_ORIENTATION_VERTICAL);
387
388         image_text_button = pref_checkbox_new_int(group, _("Show image text"),
389                                                                                 options->printer.show_image_text, &options->printer.show_image_text);
390
391         subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
392
393         pref_checkbox_link_sensitivity(image_text_button, subgroup);
394
395         hbox = gtk_hbox_new(FALSE, 0);
396         gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
397
398         /* order is important */
399         button1 = pref_radiobutton_new(hbox, NULL,  "Header 1",
400                                                         options->printer.image_text_position == HEADER_1,
401                                                         G_CALLBACK(image_text_position_h1_cb), pw);
402         button1 = pref_radiobutton_new(hbox, button1,  "Header 2",
403                                                         options->printer.image_text_position == HEADER_2,
404                                                         G_CALLBACK(image_text_position_h2_cb), pw);
405         button1 = pref_radiobutton_new(hbox, button1, "Footer 1",
406                                                         options->printer.image_text_position == FOOTER_1,
407                                                         G_CALLBACK(image_text_position_f1_cb), pw);
408         button1 = pref_radiobutton_new(hbox, button1, "Footer 2",
409                                                         options->printer.image_text_position == FOOTER_2,
410                                                         G_CALLBACK(image_text_position_f2_cb), pw);
411         gtk_widget_show(hbox);
412         pw->image_group = (gtk_radio_button_get_group(GTK_RADIO_BUTTON(button1)));
413
414         pref_checkbox_new(subgroup, _("Name"), (pw->text_fields & TEXT_INFO_FILENAME),
415                           G_CALLBACK(print_text_cb_name), pw);
416         pref_checkbox_new(subgroup, _("Path"), (pw->text_fields & TEXT_INFO_FILEPATH),
417                           G_CALLBACK(print_text_cb_path), pw);
418         pref_checkbox_new(subgroup, _("Date"), (pw->text_fields & TEXT_INFO_FILEDATE),
419                           G_CALLBACK(print_text_cb_date), pw);
420         pref_checkbox_new(subgroup, _("Size"), (pw->text_fields & TEXT_INFO_FILESIZE),
421                           G_CALLBACK(print_text_cb_size), pw);
422         pref_checkbox_new(subgroup, _("Dimensions"), (pw->text_fields & TEXT_INFO_DIMENSIONS),
423                           G_CALLBACK(print_text_cb_dims), pw);
424
425         hbox = pref_box_new(subgroup, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
426
427 #if GTK_CHECK_VERSION(3,4,0)
428         button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
429                                  G_CALLBACK(print_set_font_cb), "Image text font");
430 #else
431         button = gtk_font_button_new();
432         gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image text Font");
433         gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->printer.image_font);
434         g_signal_connect(G_OBJECT(button), "font-set",
435                                  G_CALLBACK(print_set_font_cb), "Image text font");
436 #endif
437         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
438         gtk_widget_show(button);
439
440         pref_spacer(group, PREF_PAD_GAP);
441
442         group = pref_group_new(box, FALSE, _("Page text"), GTK_ORIENTATION_VERTICAL);
443
444         page_text_button = pref_checkbox_new_int(group, _("Show page text"),
445                                           options->printer.show_page_text, &options->printer.show_page_text);
446
447         subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
448         pref_checkbox_link_sensitivity(page_text_button, subgroup);
449
450         hbox = gtk_hbox_new(FALSE, 0);
451         gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
452
453         /* order is important */
454         button2 = pref_radiobutton_new(hbox, NULL, "Header 1",
455                                                         options->printer.page_text_position == HEADER_1,
456                                                         G_CALLBACK(page_text_position_h1_cb), pw);
457         button2 = pref_radiobutton_new(hbox, button2,  "Header 2",
458                                                         options->printer.page_text_position == HEADER_2,
459                                                         G_CALLBACK(page_text_position_h2_cb), pw);
460         button2 = pref_radiobutton_new(hbox, button2, "Footer 1",
461                                                         options->printer.page_text_position == FOOTER_1,
462                                                         G_CALLBACK(page_text_position_f1_cb), pw);
463         button2 = pref_radiobutton_new(hbox, button2, "Footer 2",
464                                                         options->printer.page_text_position == FOOTER_2,
465                                                         G_CALLBACK(page_text_position_f2_cb), pw);
466         gtk_widget_show(hbox);
467         pw->page_group = (gtk_radio_button_get_group(GTK_RADIO_BUTTON(button2)));
468
469         GtkWidget *scrolled;
470
471         scrolled = gtk_scrolled_window_new(NULL, NULL);
472         gtk_widget_set_size_request(scrolled, 50, 50);
473         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
474         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
475                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
476         gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
477         gtk_widget_show(scrolled);
478
479         page_text_view = gtk_text_view_new();
480         pw->page_text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page_text_view ));
481         gtk_text_buffer_set_text(GTK_TEXT_BUFFER(pw->page_text), options->printer.page_text, -1);
482         g_object_ref(pw->page_text);
483
484         gtk_widget_set_tooltip_markup(page_text_view, ("Text shown on each page of a single or multi-page print job"));
485         gtk_container_add(GTK_CONTAINER(scrolled), page_text_view);
486         gtk_widget_show(page_text_view);
487
488         hbox = pref_box_new(subgroup, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
489
490 #if GTK_CHECK_VERSION(3,4,0)
491         button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
492                                  G_CALLBACK(print_set_font_cb), "Page text font");
493 #else
494         button = gtk_font_button_new();
495         gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Page text Font");
496         gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->printer.page_font);
497         g_signal_connect(G_OBJECT(button), "font-set",
498                                  G_CALLBACK(print_set_font_cb), "Page text font");
499 #endif
500         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
501         gtk_widget_show(button);
502 }
503
504 static gboolean paginate_cb(GtkPrintOperation *operation,
505                                                                         GtkPrintContext *context,
506                                                                         gpointer data)
507 {
508         PrintWindow *pw = data;
509
510         if (pw->job_render_finished)
511                 {
512                 return TRUE;
513                 }
514         else
515                 {
516                 return FALSE;
517                 }
518 }
519
520 static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
521                                                                         gint page_nr, gpointer data)
522 {
523         PrintWindow *pw = data;
524         FileData *fd;
525         cairo_t *cr;
526         gdouble context_width, context_height;
527         gdouble pixbuf_image_width, pixbuf_image_height;
528         gdouble width_offset;
529         gdouble height_offset;
530         GdkPixbuf *pixbuf;
531         GdkPixbuf *pixbuf_scaled;
532         GdkPixbuf *rotated = NULL;
533         PangoLayout *layout_image = NULL;
534         PangoLayout *layout_page = NULL;
535         PangoFontDescription *desc;
536         GString *image_text = g_string_new(NULL);
537         GString *page_text = g_string_new(NULL);
538         PangoRectangle ink_rect, logical_rect;
539         gdouble w, h, scale;
540         gdouble image_text_width, image_text_height, page_text_width, page_text_height;
541         gint image_y;
542         gint incr_y;
543         gdouble pango_height;
544         gdouble pango_image_height;
545         gdouble pango_page_height;
546         GtkTextIter start, end;
547         gchar *tmp;
548
549         fd = g_list_nth_data(pw->source_selection, page_nr);
550
551         pixbuf = g_list_nth_data(pw->print_pixbuf_queue, page_nr);
552         if (fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
553                 {
554                 rotated = pixbuf_apply_orientation(pixbuf, fd->exif_orientation);
555                 pixbuf = rotated;
556                 }
557
558         pixbuf_image_width = gdk_pixbuf_get_width(pixbuf);
559         pixbuf_image_height = gdk_pixbuf_get_height(pixbuf);
560
561         if (options->printer.show_image_text)
562                 {
563                 if (pw->text_fields & TEXT_INFO_FILENAME)
564                         {
565                         image_text = g_string_append(image_text, g_strdup(fd->name));
566                         image_text = g_string_append(image_text, "\n");
567                         }
568                 if (pw->text_fields & TEXT_INFO_FILEDATE)
569                         {
570                         image_text = g_string_append(image_text, g_strdup(text_from_time(fd->date)));
571                         image_text = g_string_append(image_text, "\n");
572                         }
573                 if (pw->text_fields & TEXT_INFO_FILESIZE)
574                         {
575                         image_text = g_string_append(image_text, g_strdup(text_from_size(fd->size)));
576                         image_text = g_string_append(image_text, "\n");
577                         }
578                 if (pw->text_fields & TEXT_INFO_DIMENSIONS)
579                         {
580                         g_string_append_printf(image_text, "%d x %d", (gint)pixbuf_image_width,
581                                                                                                 (gint)pixbuf_image_height);
582                         image_text = g_string_append(image_text, "\n");
583                         }
584                 if (pw->text_fields & TEXT_INFO_FILEPATH)
585                         {
586                         image_text = g_string_append(image_text, g_strdup(fd->path));
587                         image_text = g_string_append(image_text, "\n");
588                         }
589                 if (image_text->len > 0)
590                         {
591                         image_text = g_string_truncate(image_text, image_text->len - 1);
592                         }
593                 }
594
595         if (options->printer.show_page_text)
596                 {
597                 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(pw->page_text), &start, &end);
598
599                 tmp = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(pw->page_text), &start, &end, FALSE);
600                 page_text = g_string_append(page_text, tmp);
601
602                 g_free(tmp);
603                 }
604
605         cr = gtk_print_context_get_cairo_context(context);
606         context_width = gtk_print_context_get_width(context);
607         context_height = gtk_print_context_get_height(context);
608
609         pango_image_height = 0;
610         pango_page_height = 0;
611         image_text_width = 0;
612         page_text_width = 0;
613
614         if (image_text->len > 0)
615                 {
616                 layout_image = pango_cairo_create_layout(cr);
617
618                 pango_layout_set_text(layout_image, image_text->str, -1);
619                 desc = pango_font_description_from_string(options->printer.image_font);
620                 pango_layout_set_font_description(layout_image, desc);
621
622                 pango_layout_get_extents(layout_image, &ink_rect, &logical_rect);
623                 image_text_width = ((gdouble)logical_rect.width / PANGO_SCALE) ;
624                 image_text_height = ((gdouble)logical_rect.height / PANGO_SCALE);
625
626                 pango_layout_set_alignment(layout_image, PANGO_ALIGN_CENTER);
627                 pango_layout_set_text(layout_image, image_text->str, -1);
628
629                 pango_image_height = image_text_height + PRINT_TEXT_PADDING * 2;
630
631                 pango_font_description_free(desc);
632                 }
633
634         if (page_text->len > 0)
635                 {
636                 layout_page = pango_cairo_create_layout(cr);
637
638                 pango_layout_set_text(layout_page, page_text->str, -1);
639                 desc = pango_font_description_from_string(options->printer.page_font);
640                 pango_layout_set_font_description(layout_page, desc);
641
642                 pango_layout_get_extents(layout_page, &ink_rect, &logical_rect);
643                 page_text_width = ((gdouble)logical_rect.width / PANGO_SCALE) ;
644                 page_text_height = ((gdouble)logical_rect.height / PANGO_SCALE);
645
646                 pango_layout_set_alignment(layout_page, PANGO_ALIGN_CENTER);
647                 pango_layout_set_text(layout_page, page_text->str, -1);
648
649                 pango_page_height = page_text_height + PRINT_TEXT_PADDING * 2;
650
651                 pango_font_description_free(desc);
652                 }
653
654         pango_height = pango_image_height + pango_page_height;
655
656         if ((context_width / pixbuf_image_width) < ((context_height - pango_height) / pixbuf_image_height))
657                 {
658                 w = context_width;
659                 scale = context_width / pixbuf_image_width;
660                 h = pixbuf_image_height * scale;
661                 height_offset = (context_height - (h + pango_height)) / 2;
662                 width_offset = 0;
663                 }
664         else
665                 {
666                 h = context_height - pango_height ;
667                 scale = (context_height - pango_height) / pixbuf_image_height;
668                 w = pixbuf_image_width * scale;
669                 height_offset = 0;
670                 width_offset = (context_width - (pixbuf_image_width * scale)) / 2;
671                 }
672
673         incr_y = height_offset + PRINT_TEXT_PADDING;
674
675         if (options->printer.page_text_position == HEADER_1 && page_text->len > 0)
676                 {
677                 cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
678                 pango_cairo_show_layout(cr, layout_page);
679
680                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_page_height;
681                 }
682
683         if (options->printer.image_text_position == HEADER_1 && image_text->len > 0)
684                 {
685                 cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
686                 pango_cairo_show_layout(cr, layout_image);
687
688                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_image_height;
689                 }
690
691         if (options->printer.page_text_position == HEADER_2 && page_text->len > 0)
692                 {
693                 cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
694                 pango_cairo_show_layout(cr, layout_page);
695
696                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_page_height;
697                 }
698
699         if (options->printer.image_text_position == HEADER_2 && image_text->len > 0)
700                 {
701                 cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
702                 pango_cairo_show_layout(cr, layout_image);
703
704                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_image_height;
705                 }
706
707         image_y = incr_y;
708         incr_y = incr_y + h + PRINT_TEXT_PADDING;
709
710         if (options->printer.page_text_position == FOOTER_1 && page_text->len > 0)
711                 {
712                 cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
713                 pango_cairo_show_layout(cr, layout_page);
714
715                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_page_height;
716                 }
717
718         if (options->printer.image_text_position == FOOTER_1 && image_text->len > 0)
719                 {
720                 cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
721                 pango_cairo_show_layout(cr, layout_image);
722
723                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_image_height;
724                 }
725
726         if (options->printer.page_text_position == FOOTER_2 && page_text->len > 0)
727                 {
728                 cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
729                 pango_cairo_show_layout(cr, layout_page);
730
731                 incr_y = incr_y + PRINT_TEXT_PADDING + pango_page_height;
732                 }
733
734         if (options->printer.image_text_position == FOOTER_2 && image_text->len > 0)
735                 {
736                 cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
737                 pango_cairo_show_layout(cr, layout_image);
738                 }
739
740         pixbuf_scaled = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
741         gdk_pixbuf_scale(pixbuf, pixbuf_scaled, 0, 0, w, h, 0, 0,  scale, scale, PRINT_MAX_INTERP);
742
743         cairo_rectangle(cr, width_offset, image_y, w, h);
744
745         gdk_cairo_set_source_pixbuf(cr, pixbuf_scaled, width_offset, image_y);
746
747         cairo_fill(cr);
748
749         if (image_text->len > 0)
750                 {
751                 g_object_unref(layout_image);
752                 g_string_free(image_text, TRUE);
753                 }
754         if (page_text->len > 0)
755                 {
756                 g_object_unref(layout_page);
757                 g_string_free(page_text, TRUE);
758                 }
759
760         g_object_unref(pixbuf_scaled);
761         if (rotated) g_object_unref(rotated);
762
763         return;
764 }
765
766 static void begin_print(GtkPrintOperation *operation,
767                                                 GtkPrintContext *context,
768                                                 gpointer user_data)
769 {
770         PrintWindow *pw = user_data;
771         gint page_count;
772
773         page_count = print_layout_page_count(pw);
774         gtk_print_operation_set_n_pages (operation, page_count);
775
776         print_job_render_image(pw);
777 }
778
779
780 GObject *option_tab_cb(GtkPrintOperation *operation, gpointer user_data)
781 {
782         PrintWindow *pw = user_data;
783
784         return G_OBJECT(pw->vbox);
785 }
786
787 static void print_pref_store(PrintWindow *pw)
788 {
789         gchar *tmp;
790         GtkTextIter start, end;
791
792         options->printer.text_fields = pw->text_fields;
793
794         gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(pw->page_text), &start, &end);
795         tmp = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(pw->page_text), &start, &end, FALSE);
796         g_free(options->printer.page_text);
797         options->printer.page_text = g_strdup(tmp);
798         g_free(tmp);
799 }
800
801 static void end_print_cb(GtkPrintOperation *operation,
802                                                                 GtkPrintContext *context, gpointer data)
803 {
804         PrintWindow *pw = data;
805         GList *work;
806         GdkPixbuf *pixbuf;
807         gchar *path;
808         GtkPrintSettings *print_settings;
809         GtkPageSetup *page_setup;
810         GError *error = NULL;
811
812         print_settings = gtk_print_operation_get_print_settings(operation);
813         path = g_build_filename(get_rc_dir(), PRINT_SETTINGS, NULL);
814
815         gtk_print_settings_to_file(print_settings, path, &error);
816         if (error)
817                 {
818                 log_printf("Error: Print settings save failed:\n%s", error->message);
819                 g_error_free(error);
820                 error = NULL;
821                 }
822         g_free(path);
823         g_object_unref(print_settings);
824
825         page_setup = gtk_print_operation_get_default_page_setup(operation);
826         path = g_build_filename(get_rc_dir(), PAGE_SETUP, NULL);
827
828         gtk_page_setup_to_file(page_setup, path, &error);
829         if (error)
830                 {
831                 log_printf("Error: Print page setup save failed:\n%s", error->message);
832                 g_error_free(error);
833                 error = NULL;
834                 }
835         g_free(path);
836         g_object_unref(page_setup);
837
838         print_pref_store(pw);
839
840         work = pw->print_pixbuf_queue;
841         while (work)
842                 {
843                 pixbuf = work->data;
844                 if (pixbuf)
845                         {
846                         g_object_unref(pixbuf);
847                         }
848                 work = work->next;
849                 }
850         g_list_free(pw->print_pixbuf_queue);
851         g_object_unref(pw->page_text);
852         g_free(pw);
853 }
854
855 void print_window_new(FileData *fd, GList *selection, GList *list, GtkWidget *parent)
856 {
857         PrintWindow *pw;
858         GtkWidget *vbox;
859         GtkPrintOperation *operation;
860         GtkPageSetup *page_setup;
861         gchar *uri;
862         const gchar *dir;
863         GError *error = NULL;
864         gchar *path;
865         GtkPrintSettings *settings;
866
867         pw = g_new0(PrintWindow, 1);
868
869         pw->source_selection = file_data_process_groups_in_selection(selection, FALSE, NULL);
870         pw->text_fields = options->printer.text_fields;
871
872         if (print_layout_page_count(pw) == 0)
873                 {
874                 return;
875                 }
876
877         vbox = gtk_vbox_new(FALSE, 0);
878         gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
879         gtk_widget_show(vbox);
880
881         print_text_menu(vbox, pw);
882         pw->vbox = vbox;
883
884         pw->print_pixbuf_queue = NULL;
885         pw->job_render_finished = FALSE;
886         pw->job_page = 0;
887
888         operation = gtk_print_operation_new();
889         settings = gtk_print_settings_new();
890
891         gtk_print_operation_set_custom_tab_label(operation, "Options");
892         gtk_print_operation_set_use_full_page(operation, TRUE);
893         gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
894         gtk_print_operation_set_embed_page_setup(operation, TRUE);
895         gtk_print_operation_set_allow_async (operation, TRUE);
896         dir = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
897         if (dir == NULL)
898                 {
899                 dir = g_get_home_dir();
900                 }
901
902         uri = g_build_filename("file:/", dir, "geeqie-file.pdf", NULL);
903         gtk_print_settings_set(settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
904         g_free(uri);
905
906         path = g_build_filename(get_rc_dir(), PRINT_SETTINGS, NULL);
907         gtk_print_settings_load_file(settings, path, &error);
908         if (error)
909                 {
910                 log_printf("Error: Printer settings load failed:\n%s", error->message);
911                 g_error_free(error);
912                 error = NULL;
913                 }
914         gtk_print_operation_set_print_settings(operation, settings);
915         g_free(path);
916
917         page_setup = gtk_page_setup_new();
918         path = g_build_filename(get_rc_dir(), PAGE_SETUP, NULL);
919         gtk_page_setup_load_file(page_setup, path, &error);
920         if (error)
921                 {
922                 log_printf("Error: Print page setup load failed:\n%s", error->message);
923                 g_error_free(error);
924                 error = NULL;
925                 }
926         gtk_print_operation_set_default_page_setup(operation, page_setup);
927         g_free(path);
928
929         g_signal_connect (G_OBJECT (operation), "begin-print",
930                                         G_CALLBACK (begin_print), pw);
931         g_signal_connect (G_OBJECT (operation), "draw-page",
932                                         G_CALLBACK (draw_page), pw);
933         g_signal_connect (G_OBJECT (operation), "end-print",
934                                         G_CALLBACK (end_print_cb), pw);
935         g_signal_connect (G_OBJECT (operation), "create-custom-widget",
936                                         G_CALLBACK (option_tab_cb), pw);
937         g_signal_connect (G_OBJECT (operation), "paginate",
938                                         G_CALLBACK (paginate_cb), pw);
939
940         gtk_print_operation_set_n_pages(operation, print_layout_page_count(pw));
941
942         gtk_print_operation_run(operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
943                                                                                                 GTK_WINDOW (parent), &error);
944
945         if (error)
946                 {
947                 GtkWidget *dialog;
948
949                 dialog = gtk_message_dialog_new(GTK_WINDOW (parent),
950                                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
951                                                                 GTK_MESSAGE_ERROR,
952                                                                 GTK_BUTTONS_CLOSE,
953                                                                 "%s", error->message);
954                 g_error_free (error);
955
956                 g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
957
958                 gtk_widget_show (dialog);
959                 }
960
961         g_object_unref(page_setup);
962         g_object_unref(settings);
963 }
964 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */