]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/printing.c
Formatting cleanups
[~andy/gtk] / demos / gtk-demo / printing.c
1 /* Printing
2  *
3  * GtkPrintOperation offers a simple API to support printing
4  * in a cross-platform way.
5  *
6  */
7
8 #include <math.h>
9 #include <gtk/gtk.h>
10 #include "demo-common.h"
11
12 /* In points */
13 #define HEADER_HEIGHT (10*72/25.4)
14 #define HEADER_GAP (3*72/25.4)
15
16 typedef struct
17 {
18   gchar *filename;
19   gdouble font_size;
20
21   gint lines_per_page;
22   gchar **lines;
23   gint num_lines;
24   gint num_pages;
25 } PrintData;
26
27 static void
28 begin_print (GtkPrintOperation *operation,
29              GtkPrintContext   *context,
30              gpointer           user_data)
31 {
32   PrintData *data = (PrintData *)user_data;
33   char *contents;
34   int i;
35   double height;
36
37   height = gtk_print_context_get_height (context) - HEADER_HEIGHT - HEADER_GAP;
38
39   data->lines_per_page = floor (height / data->font_size);
40
41   g_file_get_contents (data->filename, &contents, NULL, NULL);
42
43   data->lines = g_strsplit (contents, "\n", 0);
44   g_free (contents);
45
46   i = 0;
47   while (data->lines[i] != NULL)
48     i++;
49
50   data->num_lines = i;
51   data->num_pages = (data->num_lines - 1) / data->lines_per_page + 1;
52
53   gtk_print_operation_set_n_pages (operation, data->num_pages);
54 }
55
56 static void
57 draw_page (GtkPrintOperation *operation,
58            GtkPrintContext   *context,
59            gint               page_nr,
60            gpointer           user_data)
61 {
62   PrintData *data = (PrintData *)user_data;
63   cairo_t *cr;
64   PangoLayout *layout;
65   gint text_width, text_height;
66   gdouble width;
67   gint line, i;
68   PangoFontDescription *desc;
69   gchar *page_str;
70
71   cr = gtk_print_context_get_cairo_context (context);
72   width = gtk_print_context_get_width (context);
73
74   cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
75
76   cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
77   cairo_fill_preserve (cr);
78
79   cairo_set_source_rgb (cr, 0, 0, 0);
80   cairo_set_line_width (cr, 1);
81   cairo_stroke (cr);
82
83   layout = gtk_print_context_create_pango_layout (context);
84
85   desc = pango_font_description_from_string ("sans 14");
86   pango_layout_set_font_description (layout, desc);
87   pango_font_description_free (desc);
88
89   pango_layout_set_text (layout, data->filename, -1);
90   pango_layout_get_pixel_size (layout, &text_width, &text_height);
91
92   if (text_width > width)
93     {
94       pango_layout_set_width (layout, width);
95       pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_START);
96       pango_layout_get_pixel_size (layout, &text_width, &text_height);
97     }
98
99   cairo_move_to (cr, (width - text_width) / 2,  (HEADER_HEIGHT - text_height) / 2);
100   pango_cairo_show_layout (cr, layout);
101
102   page_str = g_strdup_printf ("%d/%d", page_nr + 1, data->num_pages);
103   pango_layout_set_text (layout, page_str, -1);
104   g_free (page_str);
105
106   pango_layout_set_width (layout, -1);
107   pango_layout_get_pixel_size (layout, &text_width, &text_height);
108   cairo_move_to (cr, width - text_width - 4, (HEADER_HEIGHT - text_height) / 2);
109   pango_cairo_show_layout (cr, layout);
110
111   g_object_unref (layout);
112
113   layout = gtk_print_context_create_pango_layout (context);
114
115   desc = pango_font_description_from_string ("monospace");
116   pango_font_description_set_size (desc, data->font_size * PANGO_SCALE);
117   pango_layout_set_font_description (layout, desc);
118   pango_font_description_free (desc);
119
120   cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP);
121   line = page_nr * data->lines_per_page;
122   for (i = 0; i < data->lines_per_page && line < data->num_lines; i++)
123     {
124       pango_layout_set_text (layout, data->lines[line], -1);
125       pango_cairo_show_layout (cr, layout);
126       cairo_rel_move_to (cr, 0, data->font_size);
127       line++;
128     }
129
130   g_object_unref (layout);
131 }
132
133 static void
134 end_print (GtkPrintOperation *operation,
135            GtkPrintContext   *context,
136            gpointer           user_data)
137 {
138   PrintData *data = (PrintData *)user_data;
139
140   g_free (data->filename);
141   g_strfreev (data->lines);
142   g_free (data);
143 }
144
145
146 GtkWidget *
147 do_printing (GtkWidget *do_widget)
148 {
149   GtkPrintOperation *operation;
150   GtkPrintSettings *settings;
151   PrintData *data;
152   gchar *uri, *ext;
153   const gchar *dir;
154   GError *error = NULL;
155
156   operation = gtk_print_operation_new ();
157   data = g_new0 (PrintData, 1);
158   data->filename = demo_find_file ("printing.c", NULL);
159   data->font_size = 12.0;
160
161   g_signal_connect (G_OBJECT (operation), "begin-print",
162                     G_CALLBACK (begin_print), data);
163   g_signal_connect (G_OBJECT (operation), "draw-page",
164                     G_CALLBACK (draw_page), data);
165   g_signal_connect (G_OBJECT (operation), "end-print",
166                     G_CALLBACK (end_print), data);
167
168   gtk_print_operation_set_use_full_page (operation, FALSE);
169   gtk_print_operation_set_unit (operation, GTK_UNIT_POINTS);
170   gtk_print_operation_set_embed_page_setup (operation, TRUE);
171
172   settings = gtk_print_settings_new ();
173   dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
174   if (dir == NULL)
175     dir = g_get_home_dir ();
176   if (g_strcmp0 (gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT), "ps") == 0)
177     ext = ".ps";
178   else if (g_strcmp0 (gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT), "svg") == 0)
179     ext = ".svg";
180   else
181     ext = ".pdf";
182
183   uri = g_strconcat ("file://", dir, "/", "gtk-demo", ext, NULL);
184   gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
185   gtk_print_operation_set_print_settings (operation, settings);
186
187   gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW (do_widget), &error);
188
189   g_object_unref (operation);
190   g_object_unref (settings);
191   g_free (uri);
192
193   if (error)
194     {
195       GtkWidget *dialog;
196
197       dialog = gtk_message_dialog_new (GTK_WINDOW (do_widget),
198                                        GTK_DIALOG_DESTROY_WITH_PARENT,
199                                        GTK_MESSAGE_ERROR,
200                                        GTK_BUTTONS_CLOSE,
201                                        "%s", error->message);
202       g_error_free (error);
203
204       g_signal_connect (dialog, "response",
205                         G_CALLBACK (gtk_widget_destroy), NULL);
206
207       gtk_widget_show (dialog);
208     }
209
210
211   return NULL;
212 }