]> git.sur5r.net Git - glabels/blob - src/print.c
Imported Upstream version 3.0.0
[glabels] / src / print.c
1 /*
2  *  print.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels 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 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "print.h"
24
25 #include <glib/gi18n.h>
26 #include <math.h>
27 #include <time.h>
28 #include <ctype.h>
29
30 #include <libglabels.h>
31 #include "label.h"
32 #include "cairo-label-path.h"
33
34 #include "debug.h"
35
36
37 /*===========================================*/
38 /* Private macros and constants.             */
39 /*===========================================*/
40
41 #define OUTLINE_RGB_ARGS          0.0,   0.0,   0.0
42
43 #define OUTLINE_WIDTH 0.25
44
45 #define TICK_OFFSET  2.25
46 #define TICK_LENGTH 18.0
47
48
49 /*=========================================================================*/
50 /* Private types.                                                          */
51 /*=========================================================================*/
52
53 typedef struct _PrintInfo {
54         cairo_t    *cr;
55
56         /* gLabels Template */
57         const lglTemplate *template;
58         gboolean           rotate_flag;
59
60         /* page size */
61         gdouble page_width;
62         gdouble page_height;
63
64 } PrintInfo;
65
66
67 /*=========================================================================*/
68 /* Private function prototypes.                                            */
69 /*=========================================================================*/
70 static PrintInfo *print_info_new              (cairo_t          *cr,
71                                                glLabel          *label);
72
73 static void       print_info_free             (PrintInfo       **pi);
74
75 static void       print_crop_marks            (PrintInfo        *pi);
76
77 static void       print_label                 (PrintInfo        *pi,
78                                                glLabel          *label,
79                                                gdouble           x,
80                                                gdouble           y,
81                                                glMergeRecord    *record,
82                                                gboolean          outline_flag,
83                                                gboolean          reverse_flag);
84
85
86 static void       draw_outline                (PrintInfo        *pi,
87                                                glLabel          *label);
88
89 static void       clip_to_outline             (PrintInfo        *pi,
90                                                glLabel          *label);
91
92
93 /*****************************************************************************/
94 /* Print simple sheet (no merge data) command.                               */
95 /*****************************************************************************/
96 void
97 gl_print_simple_sheet (glLabel          *label,
98                        cairo_t          *cr,
99                        gint              page,
100                        gint              n_sheets,
101                        gint              first,
102                        gint              last,
103                        gboolean          outline_flag,
104                        gboolean          reverse_flag,
105                        gboolean          crop_marks_flag)
106 {
107         PrintInfo              *pi;
108         const lglTemplateFrame *frame;
109         gint                    i_label;
110         lglTemplateOrigin      *origins;
111
112         gl_debug (DEBUG_PRINT, "START");
113
114         pi         = print_info_new (cr, label);
115
116         frame = (lglTemplateFrame *)pi->template->frames->data;
117         origins = lgl_template_frame_get_origins (frame);
118
119         if (crop_marks_flag) {
120                 print_crop_marks (pi);
121         }
122
123         for (i_label = first - 1; i_label < last; i_label++) {
124
125                 print_label (pi, label,
126                              origins[i_label].x, origins[i_label].y,
127                              NULL, outline_flag, reverse_flag);
128
129         }
130
131         g_free (origins);
132
133         print_info_free (&pi);
134
135         gl_debug (DEBUG_PRINT, "END");
136 }
137
138
139 /*****************************************************************************/
140 /* Print collated merge sheet command                                        */
141 /*****************************************************************************/
142 void
143 gl_print_collated_merge_sheet   (glLabel          *label,
144                                  cairo_t          *cr,
145                                  gint              page,
146                                  gint              n_copies,
147                                  gint              first,
148                                  gboolean          outline_flag,
149                                  gboolean          reverse_flag,
150                                  gboolean          crop_marks_flag,
151                                  glPrintState     *state)
152 {
153         glMerge                   *merge;
154         const GList               *record_list;
155         PrintInfo                 *pi;
156         const lglTemplateFrame    *frame;
157         gint                       i_label, n_labels_per_page, i_copy;
158         glMergeRecord             *record;
159         GList                     *p;
160         lglTemplateOrigin         *origins;
161
162         gl_debug (DEBUG_PRINT, "START");
163
164         merge = gl_label_get_merge (label);
165         record_list = gl_merge_get_record_list (merge);
166
167         pi = print_info_new (cr, label);
168         frame = (lglTemplateFrame *)pi->template->frames->data;
169
170         n_labels_per_page = lgl_template_frame_get_n_labels (frame);
171         origins = lgl_template_frame_get_origins (frame);
172
173         if (crop_marks_flag) {
174                 print_crop_marks (pi);
175         }
176
177         if (page == 0)
178         {
179                 state->i_copy  = 0;
180                 state->p_record = (GList *)record_list;
181
182                 i_label = first - 1;
183         }
184         else
185         {
186                 i_label = 0;
187         }
188
189
190         for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
191                 record = (glMergeRecord *)p->data;
192                         
193                 if ( record->select_flag ) {
194                         for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
195
196                                 print_label (pi, label,
197                                              origins[i_label].x,
198                                              origins[i_label].y,
199                                              record,
200                                              outline_flag, reverse_flag);
201
202                                 i_label++;
203                                 if (i_label == n_labels_per_page)
204                                 {
205                                         g_free (origins);
206                                         print_info_free (&pi);
207
208                                         state->i_copy = (i_copy+1) % n_copies;
209                                         if (state->i_copy == 0)
210                                         {
211                                                 state->p_record = p->next;
212                                         }
213                                         else
214                                         {
215                                                 state->p_record = p;
216                                         }
217                                         return;
218                                 }
219                         }
220                         state->i_copy = 0;
221                 }
222         }
223
224         g_free (origins);
225         print_info_free (&pi);
226
227         gl_debug (DEBUG_PRINT, "END");
228 }
229
230
231 /*****************************************************************************/
232 /* Print uncollated merge sheet command                                      */
233 /*****************************************************************************/
234 void
235 gl_print_uncollated_merge_sheet (glLabel          *label,
236                                  cairo_t          *cr,
237                                  gint              page,
238                                  gint              n_copies,
239                                  gint              first,
240                                  gboolean          outline_flag,
241                                  gboolean          reverse_flag,
242                                  gboolean          crop_marks_flag,
243                                  glPrintState     *state)
244 {
245         glMerge                   *merge;
246         const GList               *record_list;
247         PrintInfo                 *pi;
248         const lglTemplateFrame    *frame;
249         gint                       i_label, n_labels_per_page, i_copy;
250         glMergeRecord             *record;
251         GList                     *p;
252         lglTemplateOrigin         *origins;
253
254         gl_debug (DEBUG_PRINT, "START");
255
256         merge = gl_label_get_merge (label);
257         record_list = gl_merge_get_record_list (merge);
258
259         pi = print_info_new (cr, label);
260         frame = (lglTemplateFrame *)pi->template->frames->data;
261
262         n_labels_per_page = lgl_template_frame_get_n_labels (frame);
263         origins = lgl_template_frame_get_origins (frame);
264
265         if (crop_marks_flag) {
266                 print_crop_marks (pi);
267         }
268
269         if (page == 0)
270         {
271                 state->i_copy  = 0;
272                 state->p_record = (GList *)record_list;
273
274                 i_label = first - 1;
275         }
276         else
277         {
278                 i_label = 0;
279         }
280
281         for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
282
283                 for ( p=state->p_record; p!=NULL; p=p->next ) {
284                         record = (glMergeRecord *)p->data;
285                         
286                         if ( record->select_flag ) {
287
288                                 print_label (pi, label,
289                                              origins[i_label].x,
290                                              origins[i_label].y,
291                                              record,
292                                              outline_flag, reverse_flag);
293
294                                 i_label++;
295                                 if (i_label == n_labels_per_page)
296                                 {
297                                         g_free (origins);
298                                         print_info_free (&pi);
299
300                                         state->p_record = p->next;
301                                         if (state->p_record == NULL)
302                                         {
303                                                 state->p_record = (GList *)record_list;
304                                                 state->i_copy = i_copy + 1;
305                                         }
306                                         else
307                                         {
308                                                 state->i_copy = i_copy;
309                                         }
310                                         return;
311                                 }
312                         }
313                 }
314                 state->p_record = (GList *)record_list;
315
316         }
317
318         g_free (origins);
319         print_info_free (&pi);
320
321         gl_debug (DEBUG_PRINT, "END");
322 }
323
324
325 /*---------------------------------------------------------------------------*/
326 /* PRIVATE.  new print info structure                                        */
327 /*---------------------------------------------------------------------------*/
328 static PrintInfo *
329 print_info_new (cairo_t          *cr,
330                 glLabel          *label)
331 {
332         PrintInfo            *pi = g_new0 (PrintInfo, 1);
333         const lglTemplate    *template;
334         gboolean              rotate_flag;
335
336         gl_debug (DEBUG_PRINT, "START");
337
338         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
339
340         template    = gl_label_get_template (label);
341         rotate_flag = gl_label_get_rotate_flag (label);
342
343         g_return_val_if_fail (template, NULL);
344         g_return_val_if_fail (template->paper_id, NULL);
345         g_return_val_if_fail (template->page_width > 0, NULL);
346         g_return_val_if_fail (template->page_height > 0, NULL);
347
348         pi->cr = cr;
349
350         gl_debug (DEBUG_PRINT,
351                   "setting page size = \"%s\"", template->paper_id);
352
353         pi->page_width  = template->page_width;
354         pi->page_height = template->page_height;
355
356         pi->template = template;
357         pi->rotate_flag = rotate_flag;
358
359         gl_debug (DEBUG_PRINT, "END");
360
361         return pi;
362 }
363
364
365 /*---------------------------------------------------------------------------*/
366 /* PRIVATE.  free print info structure                                       */
367 /*---------------------------------------------------------------------------*/
368 static void
369 print_info_free (PrintInfo **pi)
370 {
371         gl_debug (DEBUG_PRINT, "START");
372
373
374         g_free (*pi);
375         *pi = NULL;
376
377         gl_debug (DEBUG_PRINT, "END");
378 }
379
380
381 /*---------------------------------------------------------------------------*/
382 /* PRIVATE.  Print crop tick marks.                                          */
383 /*---------------------------------------------------------------------------*/
384 static void
385 print_crop_marks (PrintInfo *pi)
386 {
387         const lglTemplateFrame    *frame;
388         gdouble                    w, h, page_w, page_h;
389         GList                     *p;
390         lglTemplateLayout         *layout;
391         gdouble                    xmin, ymin, xmax, ymax, dx, dy;
392         gdouble                    x1, y1, x2, y2, x3, y3, x4, y4;
393         gint                       ix, iy, nx, ny;
394
395         gl_debug (DEBUG_PRINT, "START");
396
397         frame = (lglTemplateFrame *)pi->template->frames->data;
398
399         lgl_template_frame_get_size (frame, &w, &h);
400
401         page_w = pi->page_width;
402         page_h = pi->page_height;
403
404         cairo_save (pi->cr);
405
406         cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
407         cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
408
409         for (p=frame->all.layouts; p != NULL; p=p->next) {
410
411                 layout = (lglTemplateLayout *)p->data;
412
413                 xmin = layout->x0;
414                 ymin = layout->y0;
415                 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
416                 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
417
418                 dx = layout->dx;
419                 dy = layout->dy;
420
421                 nx = layout->nx;
422                 ny = layout->ny;
423
424                 for (ix=0; ix < nx; ix++) {
425
426                         x1 = xmin + ix*dx;
427                         x2 = x1 + w;
428
429                         y1 = MAX((ymin - TICK_OFFSET), 0.0);
430                         y2 = MAX((y1 - TICK_LENGTH), 0.0);
431
432                         y3 = MIN((ymax + TICK_OFFSET), page_h);
433                         y4 = MIN((y3 + TICK_LENGTH), page_h);
434
435                         cairo_move_to (pi->cr, x1, y1);
436                         cairo_line_to (pi->cr, x1, y2);
437                         cairo_stroke  (pi->cr);
438
439                         cairo_move_to (pi->cr, x2, y1);
440                         cairo_line_to (pi->cr, x2, y2);
441                         cairo_stroke  (pi->cr);
442
443                         cairo_move_to (pi->cr, x1, y3);
444                         cairo_line_to (pi->cr, x1, y4);
445                         cairo_stroke  (pi->cr);
446
447                         cairo_move_to (pi->cr, x2, y3);
448                         cairo_line_to (pi->cr, x2, y4);
449                         cairo_stroke  (pi->cr);
450
451                 }
452
453                 for (iy=0; iy < ny; iy++) {
454
455                         y1 = ymin + iy*dy;
456                         y2 = y1 + h;
457
458                         x1 = MAX((xmin - TICK_OFFSET), 0.0);
459                         x2 = MAX((x1 - TICK_LENGTH), 0.0);
460
461                         x3 = MIN((xmax + TICK_OFFSET), page_w);
462                         x4 = MIN((x3 + TICK_LENGTH), page_w);
463
464                         cairo_move_to (pi->cr, x1, y1);
465                         cairo_line_to (pi->cr, x2, y1);
466                         cairo_stroke  (pi->cr);
467
468                         cairo_move_to (pi->cr, x1, y2);
469                         cairo_line_to (pi->cr, x2, y2);
470                         cairo_stroke  (pi->cr);
471
472                         cairo_move_to (pi->cr, x3, y1);
473                         cairo_line_to (pi->cr, x4, y1);
474                         cairo_stroke  (pi->cr);
475
476                         cairo_move_to (pi->cr, x3, y2);
477                         cairo_line_to (pi->cr, x4, y2);
478                         cairo_stroke  (pi->cr);
479
480                 }
481
482         }
483
484         cairo_restore (pi->cr);
485
486         gl_debug (DEBUG_PRINT, "END");
487 }
488
489
490 /*---------------------------------------------------------------------------*/
491 /* PRIVATE.  Print i'th label.                                               */
492 /*---------------------------------------------------------------------------*/
493 static void
494 print_label (PrintInfo     *pi,
495              glLabel       *label,
496              gdouble        x,
497              gdouble        y,
498              glMergeRecord *record,
499              gboolean       outline_flag,
500              gboolean       reverse_flag)
501 {
502         gdouble                 width, height;
503
504         gl_debug (DEBUG_PRINT, "START");
505
506         gl_label_get_size (label, &width, &height);
507
508         cairo_save (pi->cr);
509
510         /* Transform coordinate system to be relative to upper corner */
511         /* of the current label */
512         cairo_translate (pi->cr, x, y);
513
514         cairo_save (pi->cr);
515
516         clip_to_outline (pi, label);
517
518         cairo_save (pi->cr);
519
520         /* Special transformations. */
521         if (pi->rotate_flag) {
522                 gl_debug (DEBUG_PRINT, "Rotate flag set");
523                 cairo_rotate (pi->cr, G_PI/2.0);
524                 cairo_translate (pi->cr, 0.0, -height);
525         }
526         if ( reverse_flag ) {
527                 cairo_translate (pi->cr, width, 0.0);
528                 cairo_scale (pi->cr, -1.0, 1.0);
529         }
530
531         gl_label_draw (label, pi->cr, FALSE, record);
532
533         cairo_restore (pi->cr); /* From special transformations. */
534
535         cairo_restore (pi->cr); /* From clip to outline. */
536
537         if (outline_flag) {
538                 draw_outline (pi, label);
539         }
540
541         cairo_restore (pi->cr); /* From translation. */
542
543         gl_debug (DEBUG_PRINT, "END");
544 }
545
546
547 /*---------------------------------------------------------------------------*/
548 /* PRIVATE.  Draw outline.                                                   */
549 /*---------------------------------------------------------------------------*/
550 static void
551 draw_outline (PrintInfo *pi,
552               glLabel   *label)
553 {
554         gl_debug (DEBUG_PRINT, "START");
555
556         cairo_save (pi->cr);
557
558         cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
559         cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
560
561         gl_cairo_label_path (pi->cr, pi->template, FALSE, FALSE);
562
563         cairo_stroke (pi->cr);
564
565         cairo_restore (pi->cr);
566
567         gl_debug (DEBUG_PRINT, "END");
568 }
569
570
571 /*---------------------------------------------------------------------------*/
572 /* PRIVATE.  Clip to outline.                                                */
573 /*---------------------------------------------------------------------------*/
574 static void
575 clip_to_outline (PrintInfo *pi,
576                  glLabel   *label)
577 {
578         gl_debug (DEBUG_PRINT, "START");
579
580         gl_cairo_label_path (pi->cr, pi->template, FALSE, TRUE);
581
582         cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
583         cairo_clip (pi->cr);
584
585         gl_debug (DEBUG_PRINT, "END");
586 }
587
588
589
590
591
592 /*
593  * Local Variables:       -- emacs
594  * mode: C                -- emacs
595  * c-basic-offset: 8      -- emacs
596  * tab-width: 8           -- emacs
597  * indent-tabs-mode: nil  -- emacs
598  * End:                   -- emacs
599  */