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

source code of gtk/demos/gtk-demo/printing.c