]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * viking -- GPS Data and Topo Analyzer, Explorer, and Manager | |
3 | * | |
4 | * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net> | |
5 | * | |
6 | * print.c | |
7 | * Copyright (C) 2007, Quy Tonthat <qtonthat@gmail.com> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | * | |
23 | */ | |
24 | #ifdef HAVE_CONFIG_H | |
25 | #include "config.h" | |
26 | #endif | |
27 | ||
28 | #include <string.h> | |
29 | #include <glib/gprintf.h> | |
30 | #include <glib/gi18n.h> | |
31 | #include <gtk/gtk.h> | |
32 | ||
33 | #if GTK_CHECK_VERSION(2,10,0) | |
34 | ||
35 | #include "viking.h" | |
36 | #include "print.h" | |
37 | #include "print-preview.h" | |
38 | ||
39 | typedef enum | |
40 | { | |
41 | VIK_PRINT_CENTER_NONE = 0, | |
42 | VIK_PRINT_CENTER_HORIZONTALLY, | |
43 | VIK_PRINT_CENTER_VERTICALLY, | |
44 | VIK_PRINT_CENTER_BOTH, | |
45 | } PrintCenterMode; | |
46 | ||
47 | typedef struct { | |
48 | gchar *name; | |
49 | PrintCenterMode mode; | |
50 | } PrintCenterName; | |
51 | ||
52 | static const PrintCenterName center_modes[] = { | |
53 | {N_("None"), VIK_PRINT_CENTER_NONE}, | |
54 | {N_("Horizontally"), VIK_PRINT_CENTER_HORIZONTALLY}, | |
55 | {N_("Vertically"), VIK_PRINT_CENTER_VERTICALLY}, | |
56 | {N_("Both"), VIK_PRINT_CENTER_BOTH}, | |
57 | {NULL, -1} | |
58 | }; | |
59 | ||
60 | typedef struct { | |
61 | gint num_pages; | |
62 | gboolean show_info_header; | |
63 | VikWindow *vw; | |
64 | VikViewport *vvp; | |
65 | gdouble xmpp, ympp; /* zoom level (meters/pixel) */ | |
66 | gdouble xres; | |
67 | gdouble yres; | |
68 | gint width; | |
69 | gint height; | |
70 | gdouble offset_x; | |
71 | gdouble offset_y; | |
72 | PrintCenterMode center; | |
73 | gboolean use_full_page; | |
74 | GtkPrintOperation *operation; | |
75 | } PrintData; | |
76 | ||
77 | static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data); | |
78 | static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data); | |
79 | static void draw_page(GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, PrintData *data); | |
80 | static void end_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data); | |
81 | ||
82 | void a_print(VikWindow *vw, VikViewport *vvp) | |
83 | { | |
84 | /* TODO: make print_settings non-static when saving_settings_to_file is | |
85 | * implemented. Keep it static for now to retain settings for each | |
86 | * viking session | |
87 | */ | |
88 | static GtkPrintSettings *print_settings = NULL; | |
89 | ||
90 | GtkPrintOperation *print_oper; | |
91 | GtkPrintOperationResult res; | |
92 | PrintData data; | |
93 | ||
94 | print_oper = gtk_print_operation_new (); | |
95 | ||
96 | data.num_pages = 1; | |
97 | data.vw = vw; | |
98 | data.vvp = vvp; | |
99 | data.offset_x = 0; | |
100 | data.offset_y = 0; | |
101 | data.center = VIK_PRINT_CENTER_BOTH; | |
102 | data.use_full_page = FALSE; | |
103 | data.operation = print_oper; | |
104 | ||
105 | data.xmpp = vik_viewport_get_xmpp(vvp); | |
106 | data.ympp = vik_viewport_get_ympp(vvp); | |
107 | data.width = vik_viewport_get_width(vvp); | |
108 | data.height = vik_viewport_get_height(vvp); | |
109 | ||
110 | data.xres = data.yres = 230; /* FIXME */ | |
111 | ||
112 | if (print_settings != NULL) | |
113 | gtk_print_operation_set_print_settings (print_oper, print_settings); | |
114 | ||
115 | g_signal_connect (print_oper, "begin_print", G_CALLBACK (begin_print), &data); | |
116 | g_signal_connect (print_oper, "draw_page", G_CALLBACK (draw_page), &data); | |
117 | g_signal_connect (print_oper, "end-print", G_CALLBACK (end_print), &data); | |
118 | g_signal_connect (print_oper, "create-custom-widget", G_CALLBACK (create_custom_widget_cb), &data); | |
119 | ||
120 | gtk_print_operation_set_custom_tab_label (print_oper, _("Image Settings")); | |
121 | ||
122 | res = gtk_print_operation_run (print_oper, | |
123 | GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, | |
124 | GTK_WINDOW (vw), NULL); | |
125 | ||
126 | if (res == GTK_PRINT_OPERATION_RESULT_APPLY) { | |
127 | if (print_settings != NULL) | |
128 | g_object_unref (print_settings); | |
129 | print_settings = g_object_ref (gtk_print_operation_get_print_settings (print_oper)); | |
130 | } | |
131 | ||
132 | g_object_unref (print_oper); | |
133 | } | |
134 | ||
135 | static void begin_print(GtkPrintOperation *operation, | |
136 | GtkPrintContext *context, | |
137 | PrintData *data) | |
138 | { | |
139 | // fputs("DEBUG: begin_print() called\n", stderr); | |
140 | gtk_print_operation_set_n_pages (operation, data->num_pages); | |
141 | gtk_print_operation_set_use_full_page (operation, data->use_full_page); | |
142 | ||
143 | } | |
144 | ||
145 | static void end_print(GtkPrintOperation *operation, | |
146 | GtkPrintContext *context, | |
147 | PrintData *data) | |
148 | { | |
149 | // fputs("DEBUG: end_print() called\n", stderr); | |
150 | ||
151 | } | |
152 | ||
153 | static void copy_row_from_rgb(guchar *surface_pixels, guchar *pixbuf_pixels, gint width) | |
154 | { | |
155 | guint32 *cairo_data = (guint32 *) surface_pixels; | |
156 | guchar *p; | |
157 | gint i; | |
158 | ||
159 | for (i = 0, p = pixbuf_pixels; i < width; i++) { | |
160 | guint32 r = *p++; | |
161 | guint32 g = *p++; | |
162 | guint32 b = *p++; | |
163 | cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b; | |
164 | } | |
165 | } | |
166 | ||
167 | #define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8)) | |
168 | #define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b)) | |
169 | static void copy_row_from_rgba(guchar *surface_pixels, guchar *pixbuf_pixels, gint width) | |
170 | { | |
171 | guint32 *cairo_data = (guint32 *) surface_pixels; | |
172 | guchar *p; | |
173 | gint i; | |
174 | ||
175 | for (i = 0, p = pixbuf_pixels; i < width; i++) { | |
176 | guint32 r = *p++; | |
177 | guint32 g = *p++; | |
178 | guint32 b = *p++; | |
179 | guint32 a = *p++; | |
180 | ||
181 | if (a != 255) { | |
182 | guint32 tmp; | |
183 | /* composite on a white background */ | |
184 | r = INT_BLEND (r, 255, a, tmp); | |
185 | g = INT_BLEND (g, 255, a, tmp); | |
186 | b = INT_BLEND (b, 255, a, tmp); | |
187 | } | |
188 | cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b; | |
189 | } | |
190 | } | |
191 | ||
192 | static void draw_page_cairo(GtkPrintContext *context, PrintData *data) | |
193 | { | |
194 | cairo_t *cr; | |
195 | GdkPixbuf *pixbuf_to_draw; | |
196 | cairo_surface_t *surface; | |
197 | guchar *surface_pixels; | |
198 | guchar *pixbuf_pixels; | |
199 | gint stride; | |
200 | gint pixbuf_stride; | |
201 | gint pixbuf_n_channels; | |
202 | gdouble cr_width; | |
203 | gdouble cr_height; | |
204 | gdouble cr_dpi_x; | |
205 | gdouble cr_dpi_y; | |
206 | gdouble scale_x; | |
207 | gdouble scale_y; | |
208 | gint y; | |
209 | ||
210 | cr = gtk_print_context_get_cairo_context(context); | |
211 | pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL, | |
212 | GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)), | |
213 | NULL, 0, 0, 0, 0, data->width, data->height); | |
214 | surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, | |
215 | data->width, data->height); | |
216 | ||
217 | cr_width = gtk_print_context_get_width (context); | |
218 | cr_height = gtk_print_context_get_height (context); | |
219 | cr_dpi_x = gtk_print_context_get_dpi_x (context); | |
220 | cr_dpi_y = gtk_print_context_get_dpi_y (context); | |
221 | ||
222 | scale_x = cr_dpi_x / data->xres; | |
223 | scale_y = cr_dpi_y / data->yres; | |
224 | ||
225 | cairo_translate (cr, | |
226 | data->offset_x / cr_dpi_x * 72.0, | |
227 | data->offset_y / cr_dpi_y * 72.0); | |
228 | cairo_scale (cr, scale_x, scale_y); | |
229 | ||
230 | surface_pixels = cairo_image_surface_get_data (surface); | |
231 | stride = cairo_image_surface_get_stride (surface); | |
232 | pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw); | |
233 | pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw); | |
234 | pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw); | |
235 | ||
236 | // fprintf(stderr, "DEBUG: %s() surface_pixels=%p pixbuf_pixels=%p size=%d surface_width=%d surface_height=%d stride=%d data_height=%d pixmap_stride=%d pixmap_nchannels=%d pixmap_bit_per_Sample=%d\n", __PRETTY_FUNCTION__, surface_pixels, pixbuf_pixels, stride * data->height, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), stride, data->height, gdk_pixbuf_get_rowstride(pixbuf_to_draw), gdk_pixbuf_get_n_channels(pixbuf_to_draw), gdk_pixbuf_get_bits_per_sample(pixbuf_to_draw)); | |
237 | ||
238 | /* Assume the pixbuf has 8 bits per channel */ | |
239 | for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) { | |
240 | switch (pixbuf_n_channels) { | |
241 | case 3: | |
242 | copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width); | |
243 | break; | |
244 | case 4: | |
245 | copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width); | |
246 | break; | |
247 | } | |
248 | } | |
249 | ||
250 | g_object_unref(G_OBJECT(pixbuf_to_draw)); | |
251 | ||
252 | cairo_set_source_surface(cr, surface, 0, 0); | |
253 | cairo_rectangle(cr, 0, 0, data->width, data->height); | |
254 | cairo_fill(cr); | |
255 | cairo_surface_destroy(surface); | |
256 | } | |
257 | ||
258 | static void draw_page(GtkPrintOperation *print, | |
259 | GtkPrintContext *context, | |
260 | gint page_nr, | |
261 | PrintData *data) | |
262 | { | |
263 | // fprintf(stderr, "DEBUG: draw_page() page_nr=%d\n", page_nr); | |
264 | draw_page_cairo(context, data); | |
265 | ||
266 | } | |
267 | ||
268 | /*********************** page layout gui *********************/ | |
269 | typedef struct | |
270 | { | |
271 | PrintData *data; | |
272 | GtkWidget *center_combo; | |
273 | GtkWidget *scale; | |
274 | GtkWidget *scale_label; | |
275 | GtkWidget *preview; | |
276 | } CustomWidgetInfo; | |
277 | ||
278 | enum | |
279 | { | |
280 | BOTTOM, | |
281 | TOP, | |
282 | RIGHT, | |
283 | LEFT, | |
284 | WIDTH, | |
285 | HEIGHT | |
286 | }; | |
287 | ||
288 | static gboolean scale_change_value_cb(GtkRange *range, GtkScrollType scroll, gdouble value, CustomWidgetInfo *pinfo); | |
289 | static void get_page_dimensions (CustomWidgetInfo *info, gdouble *page_width, gdouble *page_height, GtkUnit unit); | |
290 | static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info); | |
291 | static void get_max_offsets (CustomWidgetInfo *info, gdouble *offset_x_max, gdouble *offset_y_max); | |
292 | static void update_offsets (CustomWidgetInfo *info); | |
293 | ||
294 | static void set_scale_label(CustomWidgetInfo *pinfo, gdouble scale_val) | |
295 | { | |
296 | static const gdouble inch_to_mm = 25.4; | |
297 | gchar label_text[64]; | |
298 | ||
299 | g_snprintf(label_text, sizeof(label_text), "<i>%.0fx%0.f mm (%.0f%%)</i>", | |
300 | inch_to_mm * pinfo->data->width / pinfo->data->xres, | |
301 | inch_to_mm * pinfo->data->height / pinfo->data->yres, | |
302 | scale_val); | |
303 | gtk_label_set_markup (GTK_LABEL (pinfo->scale_label), label_text); | |
304 | } | |
305 | ||
306 | static void set_scale_value(CustomWidgetInfo *pinfo) | |
307 | { | |
308 | gdouble width; | |
309 | gdouble height; | |
310 | gdouble ratio, ratio_w, ratio_h; | |
311 | ||
312 | ||
313 | get_page_dimensions (pinfo, &width, &height, GTK_UNIT_INCH); | |
314 | ratio_w = 100 * pinfo->data->width / pinfo->data->xres / width; | |
315 | ratio_h = 100 * pinfo->data->height / pinfo->data->yres / height; | |
316 | ||
317 | ratio = MAX(ratio_w, ratio_h); | |
318 | g_signal_handlers_block_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo); | |
319 | gtk_range_set_value(GTK_RANGE(pinfo->scale), ratio); | |
320 | g_signal_handlers_unblock_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo); | |
321 | set_scale_label(pinfo, ratio); | |
322 | } | |
323 | ||
324 | static void update_page_setup (CustomWidgetInfo *pinfo) | |
325 | { | |
326 | gdouble paper_width; | |
327 | gdouble paper_height; | |
328 | gdouble offset_x_max, offset_y_max; | |
329 | PrintData *data = pinfo->data; | |
330 | ||
331 | get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH); | |
332 | if ((paper_width < (pinfo->data->width / data->xres)) || | |
333 | (paper_height < (pinfo->data->height / data->yres))) { | |
334 | gdouble xres, yres; | |
335 | xres = (gdouble) pinfo->data->width / paper_width; | |
336 | yres = (gdouble) pinfo->data->height / paper_height; | |
337 | data->xres = data->yres = MAX(xres, yres); | |
338 | vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview), | |
339 | data->xres, data->yres); | |
340 | } | |
341 | get_max_offsets (pinfo, &offset_x_max, &offset_y_max); | |
342 | vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview), | |
343 | offset_x_max, offset_y_max); | |
344 | update_offsets (pinfo); | |
345 | set_scale_value(pinfo); | |
346 | if (pinfo->preview) | |
347 | vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview), | |
348 | pinfo->data->offset_x, pinfo->data->offset_y); | |
349 | ||
350 | } | |
351 | ||
352 | static void page_setup_cb (GtkWidget *widget, CustomWidgetInfo *info) | |
353 | { | |
354 | PrintData *data = info->data; | |
355 | GtkPrintOperation *operation = data->operation; | |
356 | GtkPrintSettings *settings; | |
357 | GtkPageSetup *page_setup; | |
358 | GtkWidget *toplevel; | |
359 | ||
360 | toplevel = gtk_widget_get_toplevel (widget); | |
361 | if (! GTK_WIDGET_TOPLEVEL (toplevel)) | |
362 | toplevel = NULL; | |
363 | ||
364 | settings = gtk_print_operation_get_print_settings (operation); | |
365 | if (! settings) | |
366 | settings = gtk_print_settings_new (); | |
367 | ||
368 | page_setup = gtk_print_operation_get_default_page_setup (operation); | |
369 | ||
370 | page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (toplevel), | |
371 | page_setup, settings); | |
372 | ||
373 | gtk_print_operation_set_default_page_setup (operation, page_setup); | |
374 | ||
375 | vik_print_preview_set_page_setup (VIK_PRINT_PREVIEW (info->preview), | |
376 | page_setup); | |
377 | ||
378 | update_page_setup (info); | |
379 | ||
380 | } | |
381 | ||
382 | static void full_page_toggled_cb (GtkWidget *widget, CustomWidgetInfo *pinfo) | |
383 | { | |
384 | gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
385 | ||
386 | pinfo->data->use_full_page = active; | |
387 | update_page_setup (pinfo); | |
388 | vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(pinfo->preview), | |
389 | active); | |
390 | } | |
391 | ||
392 | static void set_center_none (CustomWidgetInfo *info) | |
393 | { | |
394 | info->data->center = VIK_PRINT_CENTER_NONE; | |
395 | ||
396 | if (info->center_combo) { | |
397 | g_signal_handlers_block_by_func (info->center_combo, | |
398 | center_changed_cb, info); | |
399 | ||
400 | info->data->center = VIK_PRINT_CENTER_NONE; | |
401 | gtk_combo_box_set_active(GTK_COMBO_BOX(info->center_combo), info->data->center); | |
402 | g_signal_handlers_unblock_by_func (info->center_combo, | |
403 | center_changed_cb, info); | |
404 | } | |
405 | } | |
406 | ||
407 | static void preview_offsets_changed_cb (GtkWidget *widget, | |
408 | gdouble offset_x, gdouble offset_y, | |
409 | CustomWidgetInfo *info) | |
410 | { | |
411 | set_center_none (info); | |
412 | ||
413 | info->data->offset_x = offset_x; | |
414 | info->data->offset_y = offset_y; | |
415 | ||
416 | update_offsets (info); | |
417 | ||
418 | } | |
419 | ||
420 | static void get_page_dimensions (CustomWidgetInfo *info, | |
421 | gdouble *page_width, | |
422 | gdouble *page_height, | |
423 | GtkUnit unit) | |
424 | { | |
425 | GtkPageSetup *setup; | |
426 | ||
427 | setup = gtk_print_operation_get_default_page_setup (info->data->operation); | |
428 | ||
429 | *page_width = gtk_page_setup_get_paper_width (setup, unit); | |
430 | *page_height = gtk_page_setup_get_paper_height (setup, unit); | |
431 | ||
432 | if (!info->data->use_full_page) { | |
433 | gdouble left_margin = gtk_page_setup_get_left_margin (setup, unit); | |
434 | gdouble right_margin = gtk_page_setup_get_right_margin (setup, unit); | |
435 | gdouble top_margin = gtk_page_setup_get_top_margin (setup, unit); | |
436 | gdouble bottom_margin = gtk_page_setup_get_bottom_margin (setup, unit); | |
437 | ||
438 | *page_width -= left_margin + right_margin; | |
439 | *page_height -= top_margin + bottom_margin; | |
440 | } | |
441 | ||
442 | } | |
443 | ||
444 | static void get_max_offsets (CustomWidgetInfo *info, | |
445 | gdouble *offset_x_max, | |
446 | gdouble *offset_y_max) | |
447 | { | |
448 | gdouble width; | |
449 | gdouble height; | |
450 | ||
451 | get_page_dimensions (info, &width, &height, GTK_UNIT_POINTS); | |
452 | ||
453 | *offset_x_max = width - 72.0 * info->data->width / info->data->xres; | |
454 | *offset_x_max = MAX (0, *offset_x_max); | |
455 | ||
456 | *offset_y_max = height - 72.0 * info->data->height / info->data->yres; | |
457 | *offset_y_max = MAX (0, *offset_y_max); | |
458 | } | |
459 | ||
460 | static void update_offsets (CustomWidgetInfo *info) | |
461 | { | |
462 | PrintData *data = info->data; | |
463 | gdouble offset_x_max; | |
464 | gdouble offset_y_max; | |
465 | ||
466 | get_max_offsets (info, &offset_x_max, &offset_y_max); | |
467 | ||
468 | switch (data->center) { | |
469 | case VIK_PRINT_CENTER_NONE: | |
470 | if (data->offset_x > offset_x_max) | |
471 | data->offset_x = offset_x_max; | |
472 | if (data->offset_y > offset_y_max) | |
473 | data->offset_y = offset_y_max; | |
474 | break; | |
475 | ||
476 | case VIK_PRINT_CENTER_HORIZONTALLY: | |
477 | data->offset_x = offset_x_max / 2.0; | |
478 | break; | |
479 | ||
480 | case VIK_PRINT_CENTER_VERTICALLY: | |
481 | data->offset_y = offset_y_max / 2.0; | |
482 | break; | |
483 | ||
484 | case VIK_PRINT_CENTER_BOTH: | |
485 | data->offset_x = offset_x_max / 2.0; | |
486 | data->offset_y = offset_y_max / 2.0; | |
487 | break; | |
488 | } | |
489 | } | |
490 | ||
491 | static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info) | |
492 | { | |
493 | info->data->center = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); | |
494 | update_offsets (info); | |
495 | ||
496 | if (info->preview) | |
497 | vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (info->preview), | |
498 | info->data->offset_x, info->data->offset_y); | |
499 | } | |
500 | ||
501 | static gboolean scale_change_value_cb(GtkRange *range, | |
502 | GtkScrollType scroll, | |
503 | gdouble value, | |
504 | CustomWidgetInfo *pinfo) | |
505 | { | |
506 | gdouble paper_width; | |
507 | gdouble paper_height; | |
508 | gdouble xres, yres, res; | |
509 | gdouble offset_x_max, offset_y_max; | |
510 | gdouble scale = CLAMP(value, 1, 100); | |
511 | ||
512 | get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH); | |
513 | xres = pinfo->data->width * 100 / paper_width / scale; | |
514 | yres = pinfo->data->height * 100 / paper_height / scale; | |
515 | res = MAX(xres, yres); | |
516 | pinfo->data->xres = pinfo->data->yres = res; | |
517 | get_max_offsets (pinfo, &offset_x_max, &offset_y_max); | |
518 | update_offsets (pinfo); | |
519 | if (pinfo->preview) { | |
520 | vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview), | |
521 | pinfo->data->xres, pinfo->data->yres); | |
522 | vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview), | |
523 | pinfo->data->offset_x, pinfo->data->offset_y); | |
524 | vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview), | |
525 | offset_x_max, offset_y_max); | |
526 | } | |
527 | ||
528 | set_scale_label(pinfo, scale); | |
529 | ||
530 | return FALSE; | |
531 | } | |
532 | ||
533 | static void custom_widgets_cleanup(CustomWidgetInfo *info) | |
534 | { | |
535 | g_free(info); | |
536 | } | |
537 | ||
538 | static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data) | |
539 | { | |
540 | GtkWidget *layout; | |
541 | GtkWidget *main_hbox; | |
542 | GtkWidget *main_vbox; | |
543 | GtkWidget *hbox; | |
544 | GtkWidget *vbox; | |
545 | GtkWidget *button; | |
546 | GtkWidget *label; | |
547 | GtkPageSetup *setup; | |
548 | ||
549 | CustomWidgetInfo *info = g_malloc0(sizeof(CustomWidgetInfo)); | |
550 | g_signal_connect_swapped (data->operation, _("done"), G_CALLBACK (custom_widgets_cleanup), info); | |
551 | ||
552 | ||
553 | info->data = data; | |
554 | ||
555 | setup = gtk_print_operation_get_default_page_setup (data->operation); | |
556 | if (! setup) { | |
557 | setup = gtk_page_setup_new (); | |
558 | gtk_print_operation_set_default_page_setup (data->operation, setup); | |
559 | } | |
560 | ||
561 | layout = gtk_vbox_new (FALSE, 6); | |
562 | gtk_container_set_border_width (GTK_CONTAINER (layout), 12); | |
563 | ||
564 | /* main hbox */ | |
565 | main_hbox = gtk_hbox_new (FALSE, 12); | |
566 | gtk_box_pack_start (GTK_BOX (layout), main_hbox, TRUE, TRUE, 0); | |
567 | gtk_widget_show (main_hbox); | |
568 | ||
569 | /* main vbox */ | |
570 | main_vbox = gtk_vbox_new (FALSE, 12); | |
571 | gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, FALSE, FALSE, 0); | |
572 | gtk_widget_show (main_vbox); | |
573 | ||
574 | vbox = gtk_vbox_new (FALSE, 6); | |
575 | gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); | |
576 | gtk_widget_show (vbox); | |
577 | ||
578 | /* Page Size */ | |
579 | button = gtk_button_new_with_mnemonic (_("_Adjust Page Size " | |
580 | "and Orientation")); | |
581 | gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0); | |
582 | g_signal_connect (G_OBJECT (button), "clicked", | |
583 | G_CALLBACK (page_setup_cb), | |
584 | info); | |
585 | gtk_widget_show (button); | |
586 | ||
587 | /* Center */ | |
588 | GtkWidget *combo; | |
589 | const PrintCenterName *center; | |
590 | ||
591 | hbox = gtk_hbox_new (FALSE, 6); | |
592 | gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); | |
593 | gtk_widget_show (hbox); | |
594 | ||
595 | label = gtk_label_new_with_mnemonic (_("C_enter:")); | |
596 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); | |
597 | gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); | |
598 | gtk_widget_show (label); | |
599 | ||
600 | combo = gtk_combo_box_new_text (); | |
601 | for (center = center_modes; center->name; center++) { | |
602 | gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(center->name)); | |
603 | } | |
604 | gtk_combo_box_set_active(GTK_COMBO_BOX(combo), VIK_PRINT_CENTER_BOTH); | |
605 | gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); | |
606 | gtk_widget_show (combo); | |
607 | gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); | |
608 | g_signal_connect(combo, "changed", | |
609 | G_CALLBACK(center_changed_cb), info); | |
610 | info->center_combo = combo; | |
611 | ||
612 | /* ignore page margins */ | |
613 | button = gtk_check_button_new_with_mnemonic (_("Ignore Page _Margins")); | |
614 | ||
615 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), | |
616 | data->use_full_page); | |
617 | gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0); | |
618 | g_signal_connect (button, "toggled", | |
619 | G_CALLBACK (full_page_toggled_cb), | |
620 | info); | |
621 | gtk_widget_show (button); | |
622 | ||
623 | /* scale */ | |
624 | vbox = gtk_vbox_new (FALSE, 1); | |
625 | gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); | |
626 | gtk_widget_show (vbox); | |
627 | ||
628 | hbox = gtk_hbox_new (FALSE, 6); | |
629 | gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); | |
630 | gtk_widget_show (hbox); | |
631 | ||
632 | label = gtk_label_new_with_mnemonic (_("Image S_ize:")); | |
633 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); | |
634 | gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); | |
635 | gtk_widget_show (label); | |
636 | ||
637 | label = gtk_label_new (NULL); | |
638 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); | |
639 | info->scale_label = label; | |
640 | gtk_box_pack_start (GTK_BOX (hbox), info->scale_label, TRUE, TRUE, 0); | |
641 | gtk_widget_show (info->scale_label); | |
642 | ||
643 | info->scale = gtk_hscale_new_with_range(1, 100, 1); | |
644 | gtk_box_pack_start (GTK_BOX (vbox), info->scale, TRUE, TRUE, 0); | |
645 | gtk_scale_set_draw_value(GTK_SCALE(info->scale), FALSE); | |
646 | gtk_widget_show (info->scale); | |
647 | gtk_label_set_mnemonic_widget (GTK_LABEL (label), info->scale); | |
648 | ||
649 | g_signal_connect(info->scale, "change_value", | |
650 | G_CALLBACK(scale_change_value_cb), info); | |
651 | ||
652 | ||
653 | info->preview = vik_print_preview_new (setup, GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp))); | |
654 | vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(info->preview), | |
655 | data->use_full_page); | |
656 | gtk_box_pack_start (GTK_BOX (main_hbox), info->preview, TRUE, TRUE, 0); | |
657 | gtk_widget_show (info->preview); | |
658 | ||
659 | g_signal_connect (info->preview, "offsets-changed", | |
660 | G_CALLBACK (preview_offsets_changed_cb), | |
661 | info); | |
662 | ||
663 | update_page_setup (info); | |
664 | ||
665 | gdouble offset_x_max, offset_y_max; | |
666 | get_max_offsets (info, &offset_x_max, &offset_y_max); | |
667 | vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (info->preview), | |
668 | offset_x_max, offset_y_max); | |
669 | ||
670 | set_scale_value(info); | |
671 | ||
672 | return layout; | |
673 | } | |
674 | ||
675 | #endif |