]> git.donarmstrong.com Git - xournal.git/blob - src/xo-print.c
Initial revision
[xournal.git] / src / xo-print.c
1 #ifdef HAVE_CONFIG_H
2 #  include <config.h>
3 #endif
4
5 #include <gtk/gtk.h>
6 #include <libgnomecanvas/libgnomecanvas.h>
7 #include <libgnomeprint/gnome-print-job.h>
8
9 #include "xournal.h"
10 #include "xo-misc.h"
11 #include "xo-paint.h"
12 #include "xo-print.h"
13 #include "xo-file.h"
14
15 #define RGBA_RED(rgba) (((rgba>>24)&0xff)/255.0)
16 #define RGBA_GREEN(rgba) (((rgba>>16)&0xff)/255.0)
17 #define RGBA_BLUE(rgba) (((rgba>>8)&0xff)/255.0)
18 #define RGBA_ALPHA(rgba) (((rgba>>0)&0xff)/255.0)
19 #define RGBA_RGB(rgba) RGBA_RED(rgba), RGBA_GREEN(rgba), RGBA_BLUE(rgba)
20
21 // does the same job as update_canvas_bg(), but to a print context
22
23 void print_background(GnomePrintContext *gpc, struct Page *pg, gboolean *abort)
24 {
25   double x, y;
26   GdkPixbuf *pix;
27   BgPdfPage *pgpdf;
28
29   if (pg->bg->type == BG_SOLID) {
30     gnome_print_setopacity(gpc, 1.0);
31     gnome_print_setrgbcolor(gpc, RGBA_RGB(pg->bg->color_rgba));
32     gnome_print_rect_filled(gpc, 0, 0, pg->width, pg->height);
33
34     if (pg->bg->ruling == RULING_NONE) return;
35     gnome_print_setrgbcolor(gpc, RGBA_RGB(RULING_COLOR));
36     gnome_print_setlinewidth(gpc, RULING_THICKNESS);
37     
38     if (pg->bg->ruling == RULING_GRAPH) {
39       for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING)
40         gnome_print_line_stroked(gpc, x, 0, x, pg->height);
41       for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING)
42         gnome_print_line_stroked(gpc, 0, y, pg->width, y);
43       return;
44     }
45     
46     for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING)
47       gnome_print_line_stroked(gpc, 0, y, pg->width, y);
48     if (pg->bg->ruling == RULING_LINED) {
49       gnome_print_setrgbcolor(gpc, RGBA_RGB(RULING_MARGIN_COLOR));
50       gnome_print_line_stroked(gpc, RULING_LEFTMARGIN, 0, RULING_LEFTMARGIN, pg->height);
51     }
52     return;
53   }
54   else if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
55     if (pg->bg->type == BG_PDF) {
56       pgpdf = (struct BgPdfPage *)g_list_nth_data(bgpdf.pages, pg->bg->file_page_seq-1);
57       if (pgpdf == NULL) return;
58       if (pgpdf->dpi != PDFTOPPM_PRINTING_DPI) {
59         add_bgpdf_request(pg->bg->file_page_seq, 0, TRUE);
60         while (pgpdf->dpi != PDFTOPPM_PRINTING_DPI && bgpdf.status == STATUS_RUNNING) {
61           gtk_main_iteration();
62           if (*abort) return;
63         }
64       }
65       pix = pgpdf->pixbuf;
66     }
67     else pix = pg->bg->pixbuf;
68     if (gdk_pixbuf_get_bits_per_sample(pix) != 8) return;
69     if (gdk_pixbuf_get_colorspace(pix) != GDK_COLORSPACE_RGB) return;
70     gnome_print_gsave(gpc);
71     gnome_print_scale(gpc, pg->width, -pg->height);
72     gnome_print_translate(gpc, 0., -1.);
73     if (gdk_pixbuf_get_n_channels(pix) == 3)
74        gnome_print_rgbimage(gpc, gdk_pixbuf_get_pixels(pix),
75          gdk_pixbuf_get_width(pix), gdk_pixbuf_get_height(pix), gdk_pixbuf_get_rowstride(pix));
76     else if (gdk_pixbuf_get_n_channels(pix) == 4)
77        gnome_print_rgbaimage(gpc, gdk_pixbuf_get_pixels(pix),
78          gdk_pixbuf_get_width(pix), gdk_pixbuf_get_height(pix), gdk_pixbuf_get_rowstride(pix));
79     gnome_print_grestore(gpc);
80     return;
81   }
82 }
83
84 void print_page(GnomePrintContext *gpc, struct Page *pg, int pageno,
85                 double pgwidth, double pgheight, gboolean *abort)
86 {
87   char tmp[10];
88   gdouble scale;
89   guint old_rgba;
90   double old_thickness;
91   GList *layerlist, *itemlist;
92   struct Layer *l;
93   struct Item *item;
94   int i;
95   double *pt;
96   
97   if (pg==NULL) return;
98   
99   g_snprintf(tmp, 10, "Page %d", pageno);
100   gnome_print_beginpage(gpc, (guchar *)tmp);
101   gnome_print_gsave(gpc);
102   
103   scale = MIN(pgwidth/pg->width, pgheight/pg->height)*0.95;
104   gnome_print_translate(gpc,
105      (pgwidth - scale*pg->width)/2, (pgheight + scale*pg->height)/2);
106   gnome_print_scale(gpc, scale, -scale);
107   gnome_print_setlinejoin(gpc, 1); // round
108   gnome_print_setlinecap(gpc, 1); // round
109
110   print_background(gpc, pg, abort);
111
112   old_rgba = 0x12345678;    // not any values we use, so we'll reset them
113   old_thickness = 0.0;
114
115   for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
116     if (*abort) break;
117     l = (struct Layer *)layerlist->data;
118     for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
119       if (*abort) break;
120       item = (struct Item *)itemlist->data;
121       if (item->type == ITEM_STROKE) {
122         if ((item->brush.color_rgba & ~0xff) != (old_rgba & ~0xff))
123           gnome_print_setrgbcolor(gpc, RGBA_RGB(item->brush.color_rgba));
124         if ((item->brush.color_rgba & 0xff) != (old_rgba & 0xff))
125           gnome_print_setopacity(gpc, RGBA_ALPHA(item->brush.color_rgba));
126         if (item->brush.thickness != old_thickness)
127           gnome_print_setlinewidth(gpc, item->brush.thickness);
128         old_rgba = item->brush.color_rgba;
129         old_thickness = item->brush.thickness;
130         gnome_print_newpath(gpc);
131         pt = item->path->coords;
132         gnome_print_moveto(gpc, pt[0], pt[1]);
133         for (i=1, pt+=2; i<item->path->num_points; i++, pt+=2)
134           gnome_print_lineto(gpc, pt[0], pt[1]);
135         gnome_print_stroke(gpc);
136       }
137     }
138   }
139   
140   gnome_print_grestore(gpc);
141   gnome_print_showpage(gpc);
142 }
143
144 void cb_print_abort(GtkDialog *dialog, gint response, gboolean *abort)
145 {
146   *abort = TRUE;
147 }
148
149 void print_job_render(GnomePrintJob *gpj, int fromPage, int toPage)
150 {
151   GnomePrintConfig *config;
152   GnomePrintContext *gpc;
153   GtkWidget *wait_dialog;
154   double pgwidth, pgheight;
155   int i;
156   gboolean abort;
157   
158   config = gnome_print_job_get_config(gpj);
159   gnome_print_config_get_page_size(config, &pgwidth, &pgheight);
160   g_object_unref(G_OBJECT(config));
161
162   gpc = gnome_print_job_get_context(gpj);
163
164   abort = FALSE;
165   wait_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
166      GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, "Preparing print job");
167   gtk_widget_show(wait_dialog);
168   g_signal_connect(wait_dialog, "response", G_CALLBACK (cb_print_abort), &abort);
169   
170   for (i = fromPage; i <= toPage; i++) {
171     gtk_message_dialog_format_secondary_text(
172               GTK_MESSAGE_DIALOG(wait_dialog), "Page %d", i+1); 
173     while (gtk_events_pending()) gtk_main_iteration();
174     print_page(gpc, (struct Page *)g_list_nth_data(journal.pages, i), i+1,
175                                              pgwidth, pgheight, &abort);
176     if (abort) break;
177   }
178   gtk_message_dialog_format_secondary_text(
179               GTK_MESSAGE_DIALOG(wait_dialog), "Finalizing...");
180   while (gtk_events_pending()) gtk_main_iteration();
181
182   gnome_print_context_close(gpc);  
183   g_object_unref(G_OBJECT(gpc));  
184
185   gnome_print_job_close(gpj);
186   if (!abort) gnome_print_job_print(gpj);
187   g_object_unref(G_OBJECT(gpj));
188
189   gtk_widget_destroy(wait_dialog);
190 }