1 /*
2  * pluma-print-preview.c
3  *
4  * Copyright (C) 2008 Paolo Borelli
5  * Copyright (C) 2012-2021 MATE Developers
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (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
15  * GNU 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, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 /*
24  * Modified by the pluma Team, 1998-2006. See the AUTHORS file for a
25  * list of people on the pluma Team.
26  * See the ChangeLog files for a list of changes.
27  *
28  * $Id: pluma-commands-search.c 5931 2007-09-25 20:05:40Z pborelli $
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include <math.h>
36 #include <stdlib.h>
37 #include <glib/gi18n.h>
38 #include <gtk/gtk.h>
39 #include <gdk/gdkkeysyms.h>
40 #include <cairo-pdf.h>
41 
42 #include "pluma-print-preview.h"
43 
44 #define PRINTER_DPI (72.)
45 
46 struct _PlumaPrintPreviewPrivate
47 {
48 	GtkPrintOperation *operation;
49 	GtkPrintContext *context;
50 	GtkPrintOperationPreview *gtk_preview;
51 
52 	GtkWidget *layout;
53 	GtkWidget *scrolled_window;
54 
55 	GtkToolItem *next;
56 	GtkToolItem *prev;
57 	GtkWidget   *page_entry;
58 	GtkWidget   *last;
59 	GtkToolItem *multi;
60 	GtkToolItem *zoom_one;
61 	GtkToolItem *zoom_fit;
62 	GtkToolItem *zoom_in;
63 	GtkToolItem *zoom_out;
64 
65 	/* real size of the page in inches */
66 	double paper_w;
67 	double paper_h;
68 	double dpi;
69 
70 	double scale;
71 
72 	/* size of the tile of a page (including padding
73 	 * and drop shadow) in pixels */
74 	gint tile_w;
75 	gint tile_h;
76 
77 	GtkPageOrientation orientation;
78 
79 	/* multipage support */
80 	gint rows;
81 	gint cols;
82 
83 	guint n_pages;
84 	guint cur_page;
85 };
86 
G_DEFINE_TYPE_WITH_PRIVATE(PlumaPrintPreview,pluma_print_preview,GTK_TYPE_BOX)87 G_DEFINE_TYPE_WITH_PRIVATE (PlumaPrintPreview, pluma_print_preview, GTK_TYPE_BOX)
88 
89 static void
90 pluma_print_preview_get_property (GObject    *object,
91 				  guint       prop_id,
92 				  GValue     *value,
93 				  GParamSpec *pspec)
94 {
95 	//PlumaPrintPreview *preview = PLUMA_PRINT_PREVIEW (object);
96 
97 	switch (prop_id)
98 	{
99 		default:
100 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101 			break;
102 	}
103 }
104 
105 static void
pluma_print_preview_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)106 pluma_print_preview_set_property (GObject      *object,
107 				  guint	        prop_id,
108 				  const GValue *value,
109 				  GParamSpec   *pspec)
110 {
111 	//PlumaPrintPreview *preview = PLUMA_PRINT_PREVIEW (object);
112 
113 	switch (prop_id)
114 	{
115 		default:
116 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117 			break;
118 	}
119 }
120 
121 static void
pluma_print_preview_finalize(GObject * object)122 pluma_print_preview_finalize (GObject *object)
123 {
124 	//PlumaPrintPreview *preview = PLUMA_PRINT_PREVIEW (object);
125 
126 	G_OBJECT_CLASS (pluma_print_preview_parent_class)->finalize (object);
127 }
128 
129 static void
pluma_print_preview_grab_focus(GtkWidget * widget)130 pluma_print_preview_grab_focus (GtkWidget *widget)
131 {
132 	PlumaPrintPreview *preview;
133 
134 	preview = PLUMA_PRINT_PREVIEW (widget);
135 
136 	gtk_widget_grab_focus (GTK_WIDGET (preview->priv->layout));
137 }
138 
139 static void
pluma_print_preview_class_init(PlumaPrintPreviewClass * klass)140 pluma_print_preview_class_init (PlumaPrintPreviewClass *klass)
141 {
142 	GObjectClass *object_class;
143 	GtkWidgetClass *widget_class;
144 
145 	object_class = G_OBJECT_CLASS (klass);
146 	widget_class = GTK_WIDGET_CLASS (klass);
147 
148 	object_class->get_property = pluma_print_preview_get_property;
149 	object_class->set_property = pluma_print_preview_set_property;
150 	object_class->finalize = pluma_print_preview_finalize;
151 
152 	widget_class->grab_focus = pluma_print_preview_grab_focus;
153 }
154 
155 static void
update_layout_size(PlumaPrintPreview * preview)156 update_layout_size (PlumaPrintPreview *preview)
157 {
158 	PlumaPrintPreviewPrivate *priv;
159 
160 	priv = preview->priv;
161 
162 	/* force size of the drawing area to make the scrolled window work */
163 	gtk_layout_set_size (GTK_LAYOUT (priv->layout),
164 			     priv->tile_w * priv->cols,
165 			     priv->tile_h * priv->rows);
166 
167 	gtk_widget_queue_draw (preview->priv->layout);
168 }
169 
170 static void
set_rows_and_cols(PlumaPrintPreview * preview,gint rows,gint cols)171 set_rows_and_cols (PlumaPrintPreview *preview,
172 		   gint	              rows,
173 		   gint	              cols)
174 {
175 	/* TODO: set the zoom appropriately */
176 
177 	preview->priv->rows = rows;
178 	preview->priv->cols = cols;
179 	update_layout_size (preview);
180 }
181 
182 /* get the paper size in points: these must be used only
183  * after the widget has been mapped and the dpi is known */
184 
185 static double
get_paper_width(PlumaPrintPreview * preview)186 get_paper_width (PlumaPrintPreview *preview)
187 {
188 	return preview->priv->paper_w * preview->priv->dpi;
189 }
190 
191 static double
get_paper_height(PlumaPrintPreview * preview)192 get_paper_height (PlumaPrintPreview *preview)
193 {
194 	return preview->priv->paper_h * preview->priv->dpi;
195 }
196 
197 #define PAGE_PAD 12
198 #define PAGE_SHADOW_OFFSET 5
199 
200 /* The tile size is the size of the area where a page
201  * will be drawn including the padding and idependent
202  * of the orientation */
203 
204 /* updates the tile size to the current zoom and page size */
205 static void
update_tile_size(PlumaPrintPreview * preview)206 update_tile_size (PlumaPrintPreview *preview)
207 {
208 	PlumaPrintPreviewPrivate *priv;
209 	gint w, h;
210 
211 	priv = preview->priv;
212 
213 	w = 2 * PAGE_PAD + floor (priv->scale * get_paper_width (preview) + 0.5);
214 	h = 2 * PAGE_PAD + floor (priv->scale * get_paper_height (preview) + 0.5);
215 
216 	if ((priv->orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
217 	    (priv->orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE))
218 	{
219 		priv->tile_w = h;
220 		priv->tile_h = w;
221 	}
222 	else
223 	{
224 		priv->tile_w = w;
225 		priv->tile_h = h;
226 	}
227 }
228 
229 /* Zoom should always be set with one of these two function
230  * so that the tile size is properly updated */
231 
232 static void
set_zoom_factor(PlumaPrintPreview * preview,double zoom)233 set_zoom_factor (PlumaPrintPreview *preview,
234 		 double	            zoom)
235 {
236 	PlumaPrintPreviewPrivate *priv;
237 
238 	priv = preview->priv;
239 
240 	priv->scale = zoom;
241 
242 	update_tile_size (preview);
243 	update_layout_size (preview);
244 }
245 
246 static void
set_zoom_fit_to_size(PlumaPrintPreview * preview)247 set_zoom_fit_to_size (PlumaPrintPreview *preview)
248 {
249 	PlumaPrintPreviewPrivate *priv;
250 	double width, height;
251 	double p_width, p_height;
252 	double zoomx, zoomy;
253 
254 	priv = preview->priv;
255 
256 	g_object_get (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (priv->layout)),
257 		      "page-size", &width,
258 		      NULL);
259 	g_object_get (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (priv->layout)),
260 		      "page-size", &height,
261 		      NULL);
262 
263 	width /= priv->cols;
264 	height /= priv->rows;
265 
266 	if ((priv->orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
267 	    (priv->orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE))
268 	{
269 		p_width = get_paper_height (preview);
270 		p_height = get_paper_width (preview);
271 	}
272 	else
273 	{
274 		p_width = get_paper_width (preview);
275 		p_height = get_paper_height (preview);
276 	}
277 
278 	zoomx = MAX (1, width - 2 * PAGE_PAD) / p_width;
279 	zoomy = MAX (1, height - 2 * PAGE_PAD) / p_height;
280 
281 	if (zoomx <= zoomy)
282 	{
283 		priv->tile_w = width;
284 		priv->tile_h = floor (0.5 + width * (p_height / p_width));
285 		priv->scale = zoomx;
286 	}
287 	else
288 	{
289 		priv->tile_w = floor (0.5 + height * (p_width / p_height));
290 		priv->tile_h = height;
291 		priv->scale = zoomy;
292 	}
293 
294 	update_layout_size (preview);
295 }
296 
297 #define ZOOM_IN_FACTOR (1.2)
298 #define ZOOM_OUT_FACTOR (1.0 / ZOOM_IN_FACTOR)
299 
300 static void
zoom_in(PlumaPrintPreview * preview)301 zoom_in (PlumaPrintPreview *preview)
302 {
303 	set_zoom_factor (preview,
304 			 preview->priv->scale * ZOOM_IN_FACTOR);
305 }
306 
307 static void
zoom_out(PlumaPrintPreview * preview)308 zoom_out (PlumaPrintPreview *preview)
309 {
310 	set_zoom_factor (preview,
311 			 preview->priv->scale * ZOOM_OUT_FACTOR);
312 }
313 
314 static void
goto_page(PlumaPrintPreview * preview,gint page)315 goto_page (PlumaPrintPreview *preview, gint page)
316 {
317 	gchar c[32];
318 
319 	g_snprintf (c, 32, "%d", page + 1);
320 	gtk_entry_set_text (GTK_ENTRY (preview->priv->page_entry), c);
321 
322 	gtk_widget_set_sensitive (GTK_WIDGET (preview->priv->prev),
323 				  (page > 0) && (preview->priv->n_pages > 1));
324 	gtk_widget_set_sensitive (GTK_WIDGET (preview->priv->next),
325 				  (page != (preview->priv->n_pages - 1)) &&
326 				  (preview->priv->n_pages > 1));
327 
328 	if (page != preview->priv->cur_page)
329 	{
330 		preview->priv->cur_page = page;
331 		if (preview->priv->n_pages > 0)
332 			gtk_widget_queue_draw (preview->priv->layout);
333 	}
334 }
335 
336 static void
prev_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)337 prev_button_clicked (GtkWidget         *button,
338 		     PlumaPrintPreview *preview)
339 {
340 	GdkEvent *event;
341 	gint page;
342 
343 	event = gtk_get_current_event ();
344 
345 	if (event->button.state & GDK_SHIFT_MASK)
346 		page = 0;
347 	else
348 		page = preview->priv->cur_page - preview->priv->rows * preview->priv->cols;
349 
350  	goto_page (preview, MAX (page, 0));
351 
352 	gdk_event_free (event);
353 }
354 
355 static void
next_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)356 next_button_clicked (GtkWidget         *button,
357 		     PlumaPrintPreview *preview)
358 {
359 	GdkEvent *event;
360 	gint page;
361 
362 	event = gtk_get_current_event ();
363 
364 	if (event->button.state & GDK_SHIFT_MASK)
365 		page = preview->priv->n_pages - 1;
366 	else
367 		page = preview->priv->cur_page + preview->priv->rows * preview->priv->cols;
368 
369  	goto_page (preview, MIN (page, preview->priv->n_pages - 1));
370 
371 	gdk_event_free (event);
372 }
373 
374 static void
page_entry_activated(GtkEntry * entry,PlumaPrintPreview * preview)375 page_entry_activated (GtkEntry          *entry,
376 		      PlumaPrintPreview *preview)
377 {
378 	const gchar *text;
379 	gint page;
380 
381 	text = gtk_entry_get_text (entry);
382 
383 	page = CLAMP (atoi (text), 1, preview->priv->n_pages) - 1;
384 	goto_page (preview, page);
385 
386 	gtk_widget_grab_focus (GTK_WIDGET (preview->priv->layout));
387 }
388 
389 static void
page_entry_insert_text(GtkEditable * editable,const gchar * text,gint length,gint * position)390 page_entry_insert_text (GtkEditable *editable,
391 			const gchar *text,
392 			gint         length,
393 			gint        *position)
394 {
395 	gunichar c;
396 	const gchar *p;
397  	const gchar *end;
398 
399 	p = text;
400 	end = text + length;
401 
402 	while (p != end)
403 	{
404 		const gchar *next;
405 		next = g_utf8_next_char (p);
406 
407 		c = g_utf8_get_char (p);
408 
409 		if (!g_unichar_isdigit (c))
410 		{
411 			g_signal_stop_emission_by_name (editable, "insert-text");
412 			break;
413 		}
414 
415 		p = next;
416 	}
417 }
418 
419 static gboolean
page_entry_focus_out(GtkWidget * widget,GdkEventFocus * event,PlumaPrintPreview * preview)420 page_entry_focus_out (GtkWidget         *widget,
421 		      GdkEventFocus     *event,
422 		      PlumaPrintPreview *preview)
423 {
424 	const gchar *text;
425 	gint page;
426 
427 	text = gtk_entry_get_text (GTK_ENTRY (widget));
428 	page = atoi (text) - 1;
429 
430 	/* Reset the page number only if really needed */
431 	if (page != preview->priv->cur_page)
432 	{
433 		gchar *str;
434 
435 		str = g_strdup_printf ("%d", preview->priv->cur_page + 1);
436 		gtk_entry_set_text (GTK_ENTRY (widget), str);
437 		g_free (str);
438 	}
439 
440 	return FALSE;
441 }
442 
443 static void
on_1x1_clicked(GtkMenuItem * i,PlumaPrintPreview * preview)444 on_1x1_clicked (GtkMenuItem *i, PlumaPrintPreview *preview)
445 {
446 	set_rows_and_cols (preview, 1, 1);
447 }
448 
449 static void
on_1x2_clicked(GtkMenuItem * i,PlumaPrintPreview * preview)450 on_1x2_clicked (GtkMenuItem *i, PlumaPrintPreview *preview)
451 {
452 	set_rows_and_cols (preview, 1, 2);
453 }
454 
455 static void
on_2x1_clicked(GtkMenuItem * i,PlumaPrintPreview * preview)456 on_2x1_clicked (GtkMenuItem *i, PlumaPrintPreview *preview)
457 {
458 	set_rows_and_cols (preview, 2, 1);
459 }
460 
461 static void
on_2x2_clicked(GtkMenuItem * i,PlumaPrintPreview * preview)462 on_2x2_clicked (GtkMenuItem *i, PlumaPrintPreview *preview)
463 {
464 	set_rows_and_cols (preview, 2, 2);
465 }
466 
467 static void
multi_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)468 multi_button_clicked (GtkWidget	 *button,
469 		      PlumaPrintPreview *preview)
470 {
471 	GtkWidget *m, *i;
472 
473 	m = gtk_menu_new ();
474 	gtk_widget_show (m);
475 	g_signal_connect (m,
476 			 "selection_done",
477 			  G_CALLBACK (gtk_widget_destroy),
478 			  m);
479 
480 	i = gtk_menu_item_new_with_label ("1x1");
481 	gtk_widget_show (i);
482 	gtk_menu_attach (GTK_MENU (m), i, 0, 1, 0, 1);
483 	g_signal_connect (i, "activate", G_CALLBACK (on_1x1_clicked), preview);
484 
485 	i = gtk_menu_item_new_with_label ("2x1");
486 	gtk_widget_show (i);
487 	gtk_menu_attach (GTK_MENU (m), i, 0, 1, 1, 2);
488 	g_signal_connect (i, "activate", G_CALLBACK (on_2x1_clicked), preview);
489 
490 	i = gtk_menu_item_new_with_label ("1x2");
491 	gtk_widget_show (i);
492 	gtk_menu_attach (GTK_MENU (m), i, 1, 2, 0, 1);
493 	g_signal_connect (i, "activate", G_CALLBACK (on_1x2_clicked), preview);
494 
495 	i = gtk_menu_item_new_with_label ("2x2");
496 	gtk_widget_show (i);
497 	gtk_menu_attach (GTK_MENU (m), i, 1, 2, 1, 2);
498 	g_signal_connect (i, "activate", G_CALLBACK (on_2x2_clicked), preview);
499 
500 	gtk_menu_popup_at_pointer (GTK_MENU (m), NULL);
501 }
502 
503 static void
zoom_one_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)504 zoom_one_button_clicked (GtkWidget         *button,
505 			 PlumaPrintPreview *preview)
506 {
507 	set_zoom_factor (preview, 1);
508 }
509 
510 static void
zoom_fit_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)511 zoom_fit_button_clicked (GtkWidget         *button,
512 			 PlumaPrintPreview *preview)
513 {
514 	set_zoom_fit_to_size (preview);
515 }
516 
517 static void
zoom_in_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)518 zoom_in_button_clicked (GtkWidget         *button,
519 			PlumaPrintPreview *preview)
520 {
521 	zoom_in (preview);
522 }
523 
524 static void
zoom_out_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)525 zoom_out_button_clicked (GtkWidget         *button,
526 			 PlumaPrintPreview *preview)
527 {
528 	zoom_out (preview);
529 }
530 
531 static void
close_button_clicked(GtkWidget * button,PlumaPrintPreview * preview)532 close_button_clicked (GtkWidget         *button,
533 		      PlumaPrintPreview *preview)
534 {
535 	gtk_widget_destroy (GTK_WIDGET (preview));
536 }
537 
538 static gboolean
ignore_mouse_buttons(GtkWidget * widget,GdkEventKey * event,PlumaPrintPreview * preview)539 ignore_mouse_buttons (GtkWidget         *widget,
540 		      GdkEventKey       *event,
541 		      PlumaPrintPreview *preview)
542 {
543 	return TRUE;
544 }
545 
546 static void
create_bar(PlumaPrintPreview * preview)547 create_bar (PlumaPrintPreview *preview)
548 {
549 	PlumaPrintPreviewPrivate *priv;
550 	GtkWidget *toolbar;
551 	GtkToolItem *i;
552 	AtkObject *atko;
553 	GtkWidget *status;
554 
555 	priv = preview->priv;
556 
557 	toolbar = gtk_toolbar_new ();
558 	gtk_toolbar_set_style (GTK_TOOLBAR (toolbar),
559 			       GTK_TOOLBAR_BOTH_HORIZ);
560 	gtk_widget_show (toolbar);
561 	gtk_box_pack_start (GTK_BOX (preview),
562 			    toolbar,
563 			    FALSE, FALSE, 0);
564 
565 	priv->prev = gtk_tool_button_new (NULL, NULL);
566 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->prev), "go-previous");
567 	gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->prev),
568 				   "P_revious Page");
569 	gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (priv->prev), TRUE);
570 	gtk_tool_item_set_tooltip_text (priv->prev, _("Show the previous page"));
571 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->prev, -1);
572 	g_signal_connect (priv->prev,
573 			  "clicked",
574 			  G_CALLBACK (prev_button_clicked),
575 			  preview);
576 	gtk_widget_show (GTK_WIDGET (priv->prev));
577 
578 	priv->next = gtk_tool_button_new (NULL, NULL);
579 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->next), "go-next");
580 	gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->next),
581 				   "_Next Page");
582 	gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (priv->next), TRUE);
583 	gtk_tool_item_set_tooltip_text (priv->next, _("Show the next page"));
584 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->next, -1);
585 	g_signal_connect (priv->next,
586 			  "clicked",
587 			  G_CALLBACK (next_button_clicked),
588 			  preview);
589 	gtk_widget_show (GTK_WIDGET (priv->next));
590 
591 	i = gtk_separator_tool_item_new ();
592 	gtk_widget_show (GTK_WIDGET (i));
593 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
594 
595 	status = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
596 	priv->page_entry = gtk_entry_new ();
597 	gtk_entry_set_width_chars (GTK_ENTRY (priv->page_entry), 3);
598 	gtk_entry_set_max_length (GTK_ENTRY (priv->page_entry), 6);
599 	gtk_widget_set_tooltip_text (priv->page_entry, _("Current page (Alt+P)"));
600 
601 	g_signal_connect (priv->page_entry,
602 			  "activate",
603 			  G_CALLBACK (page_entry_activated),
604 			  preview);
605 	g_signal_connect (priv->page_entry,
606 			  "insert-text",
607 			  G_CALLBACK (page_entry_insert_text),
608 			  NULL);
609 	g_signal_connect (priv->page_entry,
610 			  "focus-out-event",
611 			  G_CALLBACK (page_entry_focus_out),
612 			  preview);
613 
614 	gtk_box_pack_start (GTK_BOX (status),
615 			    priv->page_entry,
616 			    FALSE, FALSE, 0);
617 	/* gtk_label_set_mnemonic_widget ((GtkLabel *) l, mp->priv->page_entry); */
618 
619 	/* We are displaying 'XXX of XXX'. */
620 	gtk_box_pack_start (GTK_BOX (status),
621 	                    /* Translators: the "of" from "1 of 19" in print preview. */
622 			    gtk_label_new (_("of")),
623 			    FALSE, FALSE, 0);
624 
625 	priv->last = gtk_label_new ("");
626 	gtk_box_pack_start (GTK_BOX (status),
627 			    priv->last,
628 			    FALSE, FALSE, 0);
629 	atko = gtk_widget_get_accessible (priv->last);
630 	atk_object_set_name (atko, _("Page total"));
631 	atk_object_set_description (atko, _("The total number of pages in the document"));
632 
633 	gtk_widget_show_all (status);
634 
635 	i = gtk_tool_item_new ();
636 	gtk_container_add (GTK_CONTAINER (i), status);
637 	gtk_widget_show (GTK_WIDGET (i));
638 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
639 
640 	i = gtk_separator_tool_item_new ();
641 	gtk_widget_show (GTK_WIDGET (i));
642 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
643 
644 	priv->multi = gtk_tool_button_new (NULL, NULL);
645 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->multi), "dnd-multiple");
646 	gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->multi),
647 				   "_Show Multiple Pages");
648 	gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (priv->multi), TRUE);
649 	gtk_tool_item_set_tooltip_text (priv->multi, _("Show multiple pages"));
650 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->multi, -1);
651 	g_signal_connect (priv->multi,
652 			  "clicked",
653 			  G_CALLBACK (multi_button_clicked),
654 			  preview);
655 	gtk_widget_show (GTK_WIDGET (priv->multi));
656 
657 	i = gtk_separator_tool_item_new ();
658 	gtk_widget_show (GTK_WIDGET (i));
659 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
660 
661 	priv->zoom_one = gtk_tool_button_new (NULL, NULL);
662 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->zoom_one), "zoom-original");
663 	gtk_tool_item_set_tooltip_text (priv->zoom_one, _("Zoom 1:1"));
664 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->zoom_one, -1);
665 	g_signal_connect (priv->zoom_one,
666 			  "clicked",
667 			  G_CALLBACK (zoom_one_button_clicked),
668 			  preview);
669 	gtk_widget_show (GTK_WIDGET (priv->zoom_one));
670 
671 	priv->zoom_fit = gtk_tool_button_new (NULL, NULL);
672 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->zoom_fit), "zoom-fit-best");
673 	gtk_tool_item_set_tooltip_text (priv->zoom_fit,	_("Zoom to fit the whole page"));
674 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->zoom_fit, -1);
675 	g_signal_connect (priv->zoom_fit,
676 			  "clicked",
677 			  G_CALLBACK (zoom_fit_button_clicked),
678 			  preview);
679 	gtk_widget_show (GTK_WIDGET (priv->zoom_fit));
680 
681 	priv->zoom_in = gtk_tool_button_new (NULL, NULL);
682 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->zoom_in), "zoom-in");
683 	gtk_tool_item_set_tooltip_text (priv->zoom_in, _("Zoom the page in"));
684 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->zoom_in, -1);
685 	g_signal_connect (priv->zoom_in,
686 			  "clicked",
687 			  G_CALLBACK (zoom_in_button_clicked),
688 			  preview);
689 	gtk_widget_show (GTK_WIDGET (priv->zoom_in));
690 
691 	priv->zoom_out = gtk_tool_button_new (NULL, NULL);
692 	gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (priv->zoom_out), "zoom-out");
693 	gtk_tool_item_set_tooltip_text (priv->zoom_out, _("Zoom the page out"));
694 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->zoom_out, -1);
695 	g_signal_connect (priv->zoom_out,
696 			  "clicked",
697 			  G_CALLBACK (zoom_out_button_clicked),
698 			  preview);
699 	gtk_widget_show (GTK_WIDGET (priv->zoom_out));
700 
701 	i = gtk_separator_tool_item_new ();
702 	gtk_widget_show (GTK_WIDGET (i));
703 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
704 
705 	i = gtk_tool_button_new (NULL, _("_Close Preview"));
706 	gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (i), TRUE);
707 	gtk_tool_item_set_is_important (i, TRUE);
708 	gtk_tool_item_set_tooltip_text (i, _("Close print preview"));
709 	g_signal_connect (i, "clicked",
710 			  G_CALLBACK (close_button_clicked), preview);
711 	gtk_widget_show (GTK_WIDGET (i));
712 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), i, -1);
713 
714 	g_signal_connect (GTK_TOOLBAR (toolbar),
715 			  "button-press-event",
716 			  G_CALLBACK (ignore_mouse_buttons),
717 			  preview);
718 }
719 
720 static gint
get_first_page_displayed(PlumaPrintPreview * preview)721 get_first_page_displayed (PlumaPrintPreview *preview)
722 {
723 	PlumaPrintPreviewPrivate *priv;
724 
725 	priv = preview->priv;
726 
727 	return priv->cur_page - priv->cur_page % (priv->cols * priv->rows);
728 }
729 
730 /* returns the page number (starting from 0) or -1 if no page */
731 static gint
get_page_at_coords(PlumaPrintPreview * preview,gint x,gint y)732 get_page_at_coords (PlumaPrintPreview *preview,
733 		    gint               x,
734 		    gint               y)
735 {
736 	PlumaPrintPreviewPrivate *priv;
737 	GtkAdjustment *hadj, *vadj;
738 	gint r, c, pg;
739 
740 	priv = preview->priv;
741 
742 	if (priv->tile_h <= 0 || priv->tile_w <= 0)
743 		return -1;
744 
745 	hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (priv->layout));
746 	vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (priv->layout));
747 
748 	x += gtk_adjustment_get_value (hadj);
749 	y += gtk_adjustment_get_value (vadj);
750 
751 	r = 1 + y / (priv->tile_h);
752 	c = 1 + x / (priv->tile_w);
753 
754 	if (c > priv->cols)
755 		return -1;
756 
757 	pg = get_first_page_displayed (preview) - 1;
758 	pg += (r - 1) * priv->cols + c;
759 
760 	if (pg >= priv->n_pages)
761 		return -1;
762 
763 	/* FIXME: we could try to be picky and check
764 	 * if we actually are inside the page */
765 	return pg;
766 }
767 
768 static gboolean
preview_layout_query_tooltip(GtkWidget * widget,gint x,gint y,gboolean keyboard_tip,GtkTooltip * tooltip,PlumaPrintPreview * preview)769 preview_layout_query_tooltip (GtkWidget         *widget,
770 			      gint               x,
771 			      gint               y,
772 			      gboolean           keyboard_tip,
773 			      GtkTooltip        *tooltip,
774 			      PlumaPrintPreview *preview)
775 {
776 	gint pg;
777 	gchar *tip;
778 
779 	pg = get_page_at_coords (preview, x, y);
780 	if (pg < 0)
781 		return FALSE;
782 
783 	tip = g_strdup_printf (_("Page %d of %d"), pg + 1, preview->priv->n_pages);
784 	gtk_tooltip_set_text (tooltip, tip);
785 	g_free (tip);
786 
787 	return TRUE;
788 }
789 
790 static gint
preview_layout_key_press(GtkWidget * widget,GdkEventKey * event,PlumaPrintPreview * preview)791 preview_layout_key_press (GtkWidget         *widget,
792 			  GdkEventKey       *event,
793 			  PlumaPrintPreview *preview)
794 {
795 	PlumaPrintPreviewPrivate *priv;
796 	GtkAdjustment *hadj, *vadj;
797 	double x, y;
798 	guint h, w;
799 	double hlower, hupper, vlower, vupper;
800 	double hpage, vpage;
801 	double hstep, vstep;
802 	gboolean domove = FALSE;
803 	gboolean ret = TRUE;
804 
805 	priv = preview->priv;
806 
807 	hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (priv->layout));
808 	vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (priv->layout));
809 
810 	x = gtk_adjustment_get_value (hadj);
811 	y = gtk_adjustment_get_value (vadj);
812 
813 	g_object_get (hadj,
814 		      "lower", &hlower,
815 		      "upper", &hupper,
816 		      "page-size", &hpage,
817 		      NULL);
818 	g_object_get (vadj,
819 		      "lower", &vlower,
820 		      "upper", &vupper,
821 		      "page-size", &vpage,
822 		      NULL);
823 
824 	gtk_layout_get_size (GTK_LAYOUT (priv->layout), &w, &h);
825 
826 	hstep = 10;
827 	vstep = 10;
828 
829 	switch (event->keyval) {
830 	case '1':
831 		set_zoom_fit_to_size (preview);
832 		break;
833 	case '+':
834 	case '=':
835 	case GDK_KEY_KP_Add:
836 		zoom_in (preview);
837 		break;
838 	case '-':
839 	case '_':
840 	case GDK_KEY_KP_Subtract:
841 		zoom_out (preview);
842 		break;
843 	case GDK_KEY_KP_Right:
844 	case GDK_KEY_Right:
845 		if (event->state & GDK_SHIFT_MASK)
846 			x = hupper - hpage;
847 		else
848 			x = MIN (hupper - hpage, x + hstep);
849 		domove = TRUE;
850 		break;
851 	case GDK_KEY_KP_Left:
852 	case GDK_KEY_Left:
853 		if (event->state & GDK_SHIFT_MASK)
854 			x = hlower;
855 		else
856 			x = MAX (hlower, x - hstep);
857 		domove = TRUE;
858 		break;
859 	case GDK_KEY_KP_Up:
860 	case GDK_KEY_Up:
861 		if (event->state & GDK_SHIFT_MASK)
862 			goto page_up;
863 		y = MAX (vlower, y - vstep);
864 		domove = TRUE;
865 		break;
866 	case GDK_KEY_KP_Down:
867 	case GDK_KEY_Down:
868 		if (event->state & GDK_SHIFT_MASK)
869 			goto page_down;
870 		y = MIN (vupper - vpage, y + vstep);
871 		domove = TRUE;
872 		break;
873 	case GDK_KEY_KP_Page_Up:
874 	case GDK_KEY_Page_Up:
875 	case GDK_KEY_Delete:
876 	case GDK_KEY_KP_Delete:
877 	case GDK_KEY_BackSpace:
878 	page_up:
879 		if (y <= vlower)
880 		{
881 			if (preview->priv->cur_page > 0)
882 			{
883 				goto_page (preview, preview->priv->cur_page - 1);
884 				y = (vupper - vpage);
885 			}
886 		}
887 		else
888 		{
889 			y = vlower;
890 		}
891 		domove = TRUE;
892 		break;
893 	case GDK_KEY_KP_Page_Down:
894 	case GDK_KEY_Page_Down:
895 	case ' ':
896 	page_down:
897 		if (y >= (vupper - vpage))
898 		{
899 			if (preview->priv->cur_page < preview->priv->n_pages - 1)
900 			{
901 				goto_page (preview, preview->priv->cur_page + 1);
902 				y = vlower;
903 			}
904 		}
905 		else
906 		{
907 			y = (vupper - vpage);
908 		}
909 		domove = TRUE;
910 		break;
911 	case GDK_KEY_KP_Home:
912 	case GDK_KEY_Home:
913 		goto_page (preview, 0);
914 		y = 0;
915 		domove = TRUE;
916 		break;
917 	case GDK_KEY_KP_End:
918 	case GDK_KEY_End:
919 		goto_page (preview, preview->priv->n_pages - 1);
920 		y = 0;
921 		domove = TRUE;
922 		break;
923 	case GDK_KEY_Escape:
924 		gtk_widget_destroy (GTK_WIDGET (preview));
925 		break;
926 	case 'c':
927 		if (event->state & GDK_MOD1_MASK)
928 		{
929 			gtk_widget_destroy (GTK_WIDGET (preview));
930 		}
931 		break;
932 	case 'p':
933 		if (event->state & GDK_MOD1_MASK)
934 		{
935 			gtk_widget_grab_focus (preview->priv->page_entry);
936 		}
937 		break;
938 	default:
939 		/* by default do not stop the default handler */
940 		ret = FALSE;
941 	}
942 
943 	if (domove)
944 	{
945 		gtk_adjustment_set_value (hadj, x);
946 		gtk_adjustment_set_value (vadj, y);
947 	}
948 
949 	return ret;
950 }
951 
952 static void
create_preview_layout(PlumaPrintPreview * preview)953 create_preview_layout (PlumaPrintPreview *preview)
954 {
955 	PlumaPrintPreviewPrivate *priv;
956 	AtkObject *atko;
957 
958 	priv = preview->priv;
959 
960 	priv->layout = gtk_layout_new (NULL, NULL);
961 //	gtk_widget_set_double_buffered (priv->layout, FALSE);
962 
963 	atko = gtk_widget_get_accessible (GTK_WIDGET (priv->layout));
964 	atk_object_set_name (atko, _("Page Preview"));
965 	atk_object_set_description (atko, _("The preview of a page in the document to be printed"));
966 
967 	gtk_widget_add_events (priv->layout,
968 			       GDK_POINTER_MOTION_MASK |
969 			       GDK_BUTTON_PRESS_MASK |
970 			       GDK_KEY_PRESS_MASK);
971 
972 	gtk_widget_set_can_focus (priv->layout, TRUE);
973 
974   	g_signal_connect (priv->layout,
975 			  "key-press-event",
976 			  G_CALLBACK (preview_layout_key_press),
977 			  preview);
978 
979 	g_object_set (priv->layout, "has-tooltip", TRUE, NULL);
980   	g_signal_connect (priv->layout,
981 			  "query-tooltip",
982 			  G_CALLBACK (preview_layout_query_tooltip),
983 			  preview);
984 
985   	g_signal_connect (priv->layout,
986 			  "button-press-event",
987 			  G_CALLBACK (ignore_mouse_buttons),
988 			  preview);
989 
990 	priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
991 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window),
992 					GTK_POLICY_AUTOMATIC,
993 					GTK_POLICY_AUTOMATIC);
994 
995 	gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->layout);
996 	gtk_box_pack_end (GTK_BOX (preview),
997 			  priv->scrolled_window,
998 			  TRUE, TRUE, 0);
999 
1000 	gtk_widget_show_all (GTK_WIDGET (priv->scrolled_window));
1001 	gtk_widget_grab_focus (GTK_WIDGET (priv->layout));
1002 }
1003 
1004 static void
pluma_print_preview_init(PlumaPrintPreview * preview)1005 pluma_print_preview_init (PlumaPrintPreview *preview)
1006 {
1007 	PlumaPrintPreviewPrivate *priv;
1008 
1009 	priv = pluma_print_preview_get_instance_private (preview);
1010 
1011 	preview->priv = priv;
1012 
1013 	priv->operation = NULL;
1014 	priv->context = NULL;
1015 	priv->gtk_preview = NULL;
1016 
1017 	GtkStyleContext *context;
1018 
1019 	context = gtk_widget_get_style_context (GTK_WIDGET (preview));
1020 	gtk_style_context_add_class (context, "pluma-print-preview");
1021 	gtk_orientable_set_orientation (GTK_ORIENTABLE (preview),
1022 	                                GTK_ORIENTATION_VERTICAL);
1023 
1024 	create_bar (preview);
1025 	create_preview_layout (preview);
1026 
1027 	// FIXME
1028 	priv->cur_page = 0;
1029 	priv->paper_w = 0;
1030 	priv->paper_h = 0;
1031 	priv->dpi = PRINTER_DPI;
1032 	priv->scale = 1.0;
1033 	priv->rows = 1;
1034 	priv->cols = 1;
1035 }
1036 
1037 static void
draw_page_content(cairo_t * cr,gint page_number,PlumaPrintPreview * preview)1038 draw_page_content (cairo_t            *cr,
1039 		   gint	               page_number,
1040 		   PlumaPrintPreview  *preview)
1041 {
1042 	/* scale to the desired size */
1043 	cairo_scale (cr, preview->priv->scale, preview->priv->scale);
1044 
1045 	/* rotate acording to page orientation if needed */
1046 	if ((preview->priv->orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
1047 	    (preview->priv->orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE))
1048 	{
1049 		cairo_matrix_t matrix;
1050 
1051 		cairo_matrix_init (&matrix,
1052 				   0, -1,
1053 				   1,  0,
1054 				   0,  get_paper_width (preview));
1055 		cairo_transform (cr, &matrix);
1056 	}
1057 
1058 	gtk_print_context_set_cairo_context (preview->priv->context,
1059 					     cr,
1060 					     preview->priv->dpi,
1061 					     preview->priv->dpi);
1062 
1063 	gtk_print_operation_preview_render_page (preview->priv->gtk_preview,
1064 						 page_number);
1065 }
1066 
1067 /* For the frame, we scale and rotate manually, since
1068  * the line width should not depend on the zoom and
1069  * the drop shadow should be on the bottom right no matter
1070  * the orientation */
1071 static void
draw_page_frame(cairo_t * cr,PlumaPrintPreview * preview)1072 draw_page_frame (cairo_t            *cr,
1073 		 PlumaPrintPreview  *preview)
1074 {
1075 	double w, h;
1076 
1077 	w = get_paper_width (preview);
1078 	h = get_paper_height (preview);
1079 
1080 	if ((preview->priv->orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
1081 	    (preview->priv->orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE))
1082 	{
1083 		double tmp;
1084 
1085 		tmp = w;
1086 		w = h;
1087 		h = tmp;
1088 	}
1089 
1090 	w *= preview->priv->scale;
1091 	h *= preview->priv->scale;
1092 
1093 	/* drop shadow */
1094 	cairo_set_source_rgb (cr, 0, 0, 0);
1095 	cairo_rectangle (cr,
1096 			 PAGE_SHADOW_OFFSET, PAGE_SHADOW_OFFSET,
1097 			 w, h);
1098 	cairo_fill (cr);
1099 
1100 	/* page frame */
1101 	cairo_set_source_rgb (cr, 1, 1, 1);
1102 	cairo_rectangle (cr,
1103 			 0, 0,
1104 			 w, h);
1105 	cairo_fill_preserve (cr);
1106 	cairo_set_source_rgb (cr, 0, 0, 0);
1107 	cairo_set_line_width (cr, 1);
1108 	cairo_stroke (cr);
1109 }
1110 
1111 static void
draw_page(cairo_t * cr,double x,double y,gint page_number,PlumaPrintPreview * preview)1112 draw_page (cairo_t           *cr,
1113 	   double             x,
1114 	   double             y,
1115 	   gint	              page_number,
1116 	   PlumaPrintPreview *preview)
1117 {
1118 	cairo_save (cr);
1119 
1120 	/* move to the page top left corner */
1121 	cairo_translate (cr, x + PAGE_PAD, y + PAGE_PAD);
1122 
1123 	draw_page_frame (cr, preview);
1124 	draw_page_content (cr, page_number, preview);
1125 
1126 	cairo_restore (cr);
1127 }
1128 
1129 static gboolean
preview_draw(GtkWidget * widget,cairo_t * cr,PlumaPrintPreview * preview)1130 preview_draw (GtkWidget         *widget,
1131 		cairo_t *cr,
1132 		PlumaPrintPreview *preview)
1133 {
1134 	PlumaPrintPreviewPrivate *priv;
1135 	GdkWindow *bin_window;
1136 	gint pg;
1137 	gint i, j;
1138 
1139 	priv = preview->priv;
1140 
1141 	bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (priv->layout));
1142 
1143 	if (!gtk_cairo_should_draw_window (cr, bin_window))
1144 		return TRUE;
1145 
1146 	cairo_save (cr);
1147 
1148 	gtk_cairo_transform_to_window (cr, widget, bin_window);
1149 
1150 	/* get the first page to display */
1151 	pg = get_first_page_displayed (preview);
1152 
1153 	for (i = 0; i < priv->cols; ++i)
1154 	{
1155 		for (j = 0; j < priv->rows; ++j)
1156 		{
1157 			if (!gtk_print_operation_preview_is_selected (priv->gtk_preview,
1158 								      pg))
1159 			{
1160 				continue;
1161 			}
1162 
1163 			if (pg == priv->n_pages)
1164 				break;
1165 
1166 			draw_page (cr,
1167 				   j * priv->tile_w,
1168 				   i * priv->tile_h,
1169 				   pg,
1170 				   preview);
1171 
1172 			++pg;
1173 		}
1174 	}
1175 
1176 	cairo_restore (cr);
1177 
1178 	return TRUE;
1179 }
1180 
1181 static double
get_screen_dpi(PlumaPrintPreview * preview)1182 get_screen_dpi (PlumaPrintPreview *preview)
1183 {
1184 	GdkScreen *screen;
1185 	double dpi;
1186 
1187 	screen = gtk_widget_get_screen (GTK_WIDGET (preview));
1188 
1189 	dpi = gdk_screen_get_resolution (screen);
1190 	if (dpi < 30. || 600. < dpi)
1191 	{
1192 		g_warning ("Invalid the x-resolution for the screen, assuming 96dpi");
1193 		dpi = 96.;
1194 	}
1195 
1196 	return dpi;
1197 }
1198 
1199 static void
set_n_pages(PlumaPrintPreview * preview,gint n_pages)1200 set_n_pages (PlumaPrintPreview *preview,
1201 	     gint               n_pages)
1202 {
1203 	gchar *str;
1204 
1205 	preview->priv->n_pages = n_pages;
1206 
1207 	// FIXME: count the visible pages
1208 
1209 	str =  g_strdup_printf ("%d", n_pages);
1210 	gtk_label_set_markup (GTK_LABEL (preview->priv->last), str);
1211 	g_free (str);
1212 }
1213 
1214 static void
preview_ready(GtkPrintOperationPreview * gtk_preview,GtkPrintContext * context,PlumaPrintPreview * preview)1215 preview_ready (GtkPrintOperationPreview *gtk_preview,
1216 	       GtkPrintContext          *context,
1217 	       PlumaPrintPreview        *preview)
1218 {
1219 	gint n_pages;
1220 
1221 	g_object_get (preview->priv->operation, "n-pages", &n_pages, NULL);
1222 	set_n_pages (preview, n_pages);
1223 	goto_page (preview, 0);
1224 
1225 	/* figure out the dpi */
1226 	preview->priv->dpi = get_screen_dpi (preview);
1227 
1228 	set_zoom_factor (preview, 1.0);
1229 
1230 	/* let the default gtklayout handler clear the background */
1231 	g_signal_connect_after (preview->priv->layout,
1232 				"draw",
1233 				G_CALLBACK (preview_draw),
1234 				preview);
1235 
1236 	gtk_widget_queue_draw (preview->priv->layout);
1237 }
1238 
1239 static void
update_paper_size(PlumaPrintPreview * preview,GtkPageSetup * page_setup)1240 update_paper_size (PlumaPrintPreview *preview,
1241 		   GtkPageSetup      *page_setup)
1242 {
1243 	GtkPaperSize *paper_size;
1244 
1245 	paper_size = gtk_page_setup_get_paper_size (page_setup);
1246 
1247 	preview->priv->paper_w = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
1248 	preview->priv->paper_h = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
1249 
1250 	preview->priv->orientation = gtk_page_setup_get_orientation (page_setup);
1251 }
1252 
1253 static void
preview_got_page_size(GtkPrintOperationPreview * gtk_preview,GtkPrintContext * context,GtkPageSetup * page_setup,PlumaPrintPreview * preview)1254 preview_got_page_size (GtkPrintOperationPreview *gtk_preview,
1255 		       GtkPrintContext          *context,
1256 		       GtkPageSetup             *page_setup,
1257 		       PlumaPrintPreview        *preview)
1258 {
1259 	update_paper_size (preview, page_setup);
1260 }
1261 
1262 /* HACK: we need a dummy surface to paginate... can we use something simpler? */
1263 
1264 static cairo_status_t
dummy_write_func(G_GNUC_UNUSED gpointer closure,G_GNUC_UNUSED const guchar * data,G_GNUC_UNUSED guint length)1265 dummy_write_func (G_GNUC_UNUSED gpointer      closure,
1266 		  G_GNUC_UNUSED const guchar *data,
1267 		  G_GNUC_UNUSED guint         length)
1268 {
1269     return CAIRO_STATUS_SUCCESS;
1270 }
1271 
1272 #define PRINTER_DPI (72.)
1273 
1274 static cairo_surface_t *
create_preview_surface_platform(GtkPaperSize * paper_size,double * dpi_x,double * dpi_y)1275 create_preview_surface_platform (GtkPaperSize *paper_size,
1276 				 double       *dpi_x,
1277 				 double       *dpi_y)
1278 {
1279     double width, height;
1280     cairo_surface_t *sf;
1281 
1282     width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
1283     height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
1284 
1285     *dpi_x = *dpi_y = PRINTER_DPI;
1286 
1287     sf = cairo_pdf_surface_create_for_stream (dummy_write_func, NULL,
1288 					      width, height);
1289     return sf;
1290 }
1291 
1292 static cairo_surface_t *
create_preview_surface(PlumaPrintPreview * preview,double * dpi_x,double * dpi_y)1293 create_preview_surface (PlumaPrintPreview *preview,
1294 			double	  *dpi_x,
1295 			double	  *dpi_y)
1296 {
1297     GtkPageSetup *page_setup;
1298     GtkPaperSize *paper_size;
1299 
1300     page_setup = gtk_print_context_get_page_setup (preview->priv->context);
1301     /* gtk_page_setup_get_paper_size swaps width and height for landscape */
1302     paper_size = gtk_page_setup_get_paper_size (page_setup);
1303 
1304     return create_preview_surface_platform (paper_size, dpi_x, dpi_y);
1305 }
1306 
1307 GtkWidget *
pluma_print_preview_new(GtkPrintOperation * op,GtkPrintOperationPreview * gtk_preview,GtkPrintContext * context)1308 pluma_print_preview_new (GtkPrintOperation        *op,
1309 			 GtkPrintOperationPreview *gtk_preview,
1310 			 GtkPrintContext          *context)
1311 {
1312 	PlumaPrintPreview *preview;
1313 	GtkPageSetup *page_setup;
1314 	cairo_surface_t *surface;
1315 	cairo_t *cr;
1316 	double dpi_x, dpi_y;
1317 
1318 	g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
1319 	g_return_val_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (gtk_preview), NULL);
1320 
1321 	preview = g_object_new (PLUMA_TYPE_PRINT_PREVIEW, NULL);
1322 
1323 	preview->priv->operation = g_object_ref (op);
1324 	preview->priv->gtk_preview = g_object_ref (gtk_preview);
1325 	preview->priv->context = g_object_ref (context);
1326 
1327 	/* FIXME: is this legal?? */
1328 	gtk_print_operation_set_unit (op, GTK_UNIT_POINTS);
1329 
1330 	g_signal_connect (gtk_preview, "ready",
1331 			  G_CALLBACK (preview_ready), preview);
1332 	g_signal_connect (gtk_preview, "got-page-size",
1333 			  G_CALLBACK (preview_got_page_size), preview);
1334 
1335 	page_setup = gtk_print_context_get_page_setup (preview->priv->context);
1336 	update_paper_size (preview, page_setup);
1337 
1338 	/* FIXME: we need a cr to paginate... but we can't get the drawing
1339 	 * area surface because it's not there yet... for now I create
1340 	 * a dummy pdf surface */
1341 
1342 	surface = create_preview_surface (preview, &dpi_x, &dpi_y);
1343 	cr = cairo_create (surface);
1344 	gtk_print_context_set_cairo_context (context, cr, dpi_x, dpi_y);
1345 	cairo_destroy (cr);
1346 	cairo_surface_destroy (surface);
1347 
1348 	return GTK_WIDGET (preview);
1349 }
1350 
1351