]> git.sur5r.net Git - glabels/blob - glabels2/src/print.c
29dbb6428010ef186ac3eba8dbf0cbfa8152ba27
[glabels] / glabels2 / src / print.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  print.c:  Print module
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <config.h>
25
26 #include "print.h"
27
28 #include <glib/gi18n.h>
29 #include <math.h>
30 #include <time.h>
31 #include <ctype.h>
32 #include <gtk/gtkenums.h>
33
34 #include "label.h"
35 #include "label-text.h"
36 #include "label-box.h"
37 #include "label-line.h"
38 #include "label-ellipse.h"
39 #include "label-image.h"
40 #include "label-barcode.h"
41 #include "bc.h"
42 #include <libglabels/template.h>
43 #include "color.h"
44
45 #include "debug.h"
46
47 #define ARC_FINE   2  /* Resolution in degrees of large arcs */
48
49 #define FONT_SCALE (72.0/96.0)
50 #define TICK_OFFSET  2.25
51 #define TICK_LENGTH 18.0
52
53 /*=========================================================================*/
54 /* Private types.                                                          */
55 /*=========================================================================*/
56
57 typedef struct _PrintInfo {
58         cairo_t    *cr;
59
60         /* gLabels Template */
61         glTemplate *template;
62         gboolean    label_rotate_flag;
63
64         /* page size */
65         gdouble page_width;
66         gdouble page_height;
67
68 } PrintInfo;
69
70
71 /*=========================================================================*/
72 /* Private function prototypes.                                            */
73 /*=========================================================================*/
74 static PrintInfo *print_info_new              (cairo_t          *cr,
75                                                glLabel          *label);
76
77 static void       print_info_free             (PrintInfo       **pi);
78
79 static void       print_crop_marks            (PrintInfo        *pi);
80
81 static void       print_label                 (PrintInfo        *pi,
82                                                glLabel          *label,
83                                                gdouble           x,
84                                                gdouble           y,
85                                                glMergeRecord    *record,
86                                                gboolean          outline_flag,
87                                                gboolean          reverse_flag);
88
89
90 static void       draw_label                  (PrintInfo        *pi,
91                                                glLabel          *label,
92                                                glMergeRecord    *record);
93
94
95 static void       draw_object                 (PrintInfo        *pi,
96                                                glLabelObject    *object,
97                                                glMergeRecord    *record);
98
99 static void       draw_text_object            (PrintInfo        *pi,
100                                                glLabelText      *object,
101                                                glMergeRecord    *record);
102
103 static void       draw_box_object             (PrintInfo        *pi,
104                                                glLabelBox       *object,
105                                                glMergeRecord    *record);
106
107 static void       draw_line_object            (PrintInfo        *pi,
108                                                glLabelLine      *object,
109                                                glMergeRecord    *record);                                                  
110
111 static void       draw_ellipse_object         (PrintInfo        *pi,
112                                                glLabelEllipse   *object,
113                                                glMergeRecord    *record);
114
115 static void       draw_image_object           (PrintInfo        *pi,
116                                                glLabelImage     *object,
117                                                glMergeRecord    *record);
118
119 static void       draw_barcode_object         (PrintInfo        *pi,
120                                                glLabelBarcode   *object,
121                                                glMergeRecord    *record);
122
123
124 static void       draw_outline                (PrintInfo        *pi,
125                                                glLabel          *label);
126
127 static void       clip_to_outline             (PrintInfo        *pi,
128                                                glLabel          *label);
129
130 static void       clip_punchouts              (PrintInfo        *pi,
131                                                glLabel          *label);
132
133
134 static void       create_rounded_rectangle_path (cairo_t           *cr,
135                                                  gdouble            x0,
136                                                  gdouble            y0,
137                                                  gdouble            w,
138                                                  gdouble            h,
139                                                  gdouble            r);
140
141 static void       create_ellipse_path           (cairo_t           *cr,
142                                                  gdouble            x0,
143                                                  gdouble            y0,
144                                                  gdouble            rx,
145                                                  gdouble            ry);
146
147 static void       create_cd_path                (cairo_t           *cr,
148                                                  gdouble            x0,
149                                                  gdouble            y0,
150                                                  gdouble            w,
151                                                  gdouble            h,
152                                                  gdouble            r1,
153                                                  gdouble            r2);
154
155 \f
156 /*****************************************************************************/
157 /* Print simple sheet (no merge data) command.                               */
158 /*****************************************************************************/
159 void
160 gl_print_simple_sheet (glLabel          *label,
161                        cairo_t          *cr,
162                        gint              page,
163                        gint              n_sheets,
164                        gint              first,
165                        gint              last,
166                        gboolean          outline_flag,
167                        gboolean          reverse_flag,
168                        gboolean          crop_marks_flag)
169 {
170         PrintInfo                 *pi;
171         const glTemplateLabelType *label_type;
172         gint                       i_label;
173         glTemplateOrigin          *origins;
174
175         gl_debug (DEBUG_PRINT, "START");
176
177         pi         = print_info_new (cr, label);
178
179         label_type = gl_template_get_first_label_type (pi->template);
180         origins = gl_template_get_origins (label_type);
181
182         if (crop_marks_flag) {
183                 print_crop_marks (pi);
184         }
185
186         for (i_label = first - 1; i_label < last; i_label++) {
187
188                 print_label (pi, label,
189                              origins[i_label].x, origins[i_label].y,
190                              NULL, outline_flag, reverse_flag);
191
192         }
193
194         g_free (origins);
195
196         print_info_free (&pi);
197
198         gl_debug (DEBUG_PRINT, "END");
199 }
200
201 /*****************************************************************************/
202 /* Print collated merge sheet command                                        */
203 /*****************************************************************************/
204 void
205 gl_print_collated_merge_sheet   (glLabel          *label,
206                                  cairo_t          *cr,
207                                  gint              page,
208                                  gint              n_copies,
209                                  gint              first,
210                                  gboolean          outline_flag,
211                                  gboolean          reverse_flag,
212                                  gboolean          crop_marks_flag,
213                                  glPrintState     *state)
214 {
215         glMerge                   *merge;
216         const GList               *record_list;
217         PrintInfo                 *pi;
218         const glTemplateLabelType *label_type;
219         gint                       i_label, n_labels_per_page, i_copy;
220         glMergeRecord             *record;
221         GList                     *p;
222         glTemplateOrigin          *origins;
223
224         gl_debug (DEBUG_PRINT, "START");
225
226         merge = gl_label_get_merge (label);
227         record_list = gl_merge_get_record_list (merge);
228
229         pi = print_info_new (cr, label);
230         label_type = gl_template_get_first_label_type (pi->template);
231
232         n_labels_per_page = gl_template_get_n_labels (label_type);
233         origins = gl_template_get_origins (label_type);
234
235         if (crop_marks_flag) {
236                 print_crop_marks (pi);
237         }
238
239         if (page == 0)
240         {
241                 state->i_copy  = 0;
242                 state->p_record = (GList *)record_list;
243
244                 i_label = first - 1;
245         }
246         else
247         {
248                 i_label = 0;
249         }
250
251
252         for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
253                 record = (glMergeRecord *)p->data;
254                         
255                 if ( record->select_flag ) {
256                         for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
257
258                                 print_label (pi, label,
259                                              origins[i_label].x,
260                                              origins[i_label].y,
261                                              record,
262                                              outline_flag, reverse_flag);
263
264                                 i_label++;
265                                 if (i_label == n_labels_per_page)
266                                 {
267                                         g_free (origins);
268                                         print_info_free (&pi);
269
270                                         state->i_copy = (i_copy+1) % n_copies;
271                                         if (state->i_copy == 0)
272                                         {
273                                                 state->p_record = p->next;
274                                         }
275                                         else
276                                         {
277                                                 state->p_record = p;
278                                         }
279                                         return;
280                                 }
281                         }
282                         state->i_copy = 0;
283                 }
284         }
285
286         g_free (origins);
287         print_info_free (&pi);
288
289         gl_debug (DEBUG_PRINT, "END");
290 }
291
292 /*****************************************************************************/
293 /* Print uncollated merge sheet command                                      */
294 /*****************************************************************************/
295 void
296 gl_print_uncollated_merge_sheet (glLabel          *label,
297                                  cairo_t          *cr,
298                                  gint              page,
299                                  gint              n_copies,
300                                  gint              first,
301                                  gboolean          outline_flag,
302                                  gboolean          reverse_flag,
303                                  gboolean          crop_marks_flag,
304                                  glPrintState     *state)
305 {
306         glMerge                   *merge;
307         const GList               *record_list;
308         PrintInfo                 *pi;
309         const glTemplateLabelType *label_type;
310         gint                       i_label, n_labels_per_page, i_copy;
311         glMergeRecord             *record;
312         GList                     *p;
313         glTemplateOrigin          *origins;
314
315         gl_debug (DEBUG_PRINT, "START");
316
317         merge = gl_label_get_merge (label);
318         record_list = gl_merge_get_record_list (merge);
319
320         pi = print_info_new (cr, label);
321         label_type = gl_template_get_first_label_type (pi->template);
322
323         n_labels_per_page = gl_template_get_n_labels (label_type);
324         origins = gl_template_get_origins (label_type);
325
326         if (crop_marks_flag) {
327                 print_crop_marks (pi);
328         }
329
330         if (page == 0)
331         {
332                 state->i_copy  = 0;
333                 state->p_record = (GList *)record_list;
334
335                 i_label = first - 1;
336         }
337         else
338         {
339                 i_label = 0;
340         }
341
342         for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
343
344                 for ( p=state->p_record; p!=NULL; p=p->next ) {
345                         record = (glMergeRecord *)p->data;
346                         
347                         if ( record->select_flag ) {
348
349                                 print_label (pi, label,
350                                              origins[i_label].x,
351                                              origins[i_label].y,
352                                              record,
353                                              outline_flag, reverse_flag);
354
355                                 i_label++;
356                                 if (i_label == n_labels_per_page)
357                                 {
358                                         g_free (origins);
359                                         print_info_free (&pi);
360
361                                         state->p_record = p->next;
362                                         if (state->p_record == NULL)
363                                         {
364                                                 state->p_record = (GList *)record_list;
365                                                 state->i_copy = i_copy + 1;
366                                         }
367                                         else
368                                         {
369                                                 state->i_copy = i_copy;
370                                         }
371                                         return;
372                                 }
373                         }
374                 }
375                 state->p_record = (GList *)record_list;
376
377         }
378
379         g_free (origins);
380         print_info_free (&pi);
381
382         gl_debug (DEBUG_PRINT, "END");
383 }
384
385 #ifdef TODO
386 /*****************************************************************************/
387 /* Batch print.  Call appropriate function above.                            */
388 /*****************************************************************************/
389 void
390 gl_print_batch (GnomePrintJob    *job,
391                 glLabel          *label,
392                 gint              n_sheets,
393                 gint              n_copies,
394                 gint              first,
395                 glPrintFlags     *flags)
396 {
397         glMerge                   *merge;
398         glTemplate                *template;
399         const glTemplateLabelType *label_type;
400         gint                       n_per_page;
401         
402         gl_debug (DEBUG_PRINT, "START");
403
404         merge = gl_label_get_merge (label);
405         template = gl_label_get_template (label);
406         label_type = gl_template_get_first_label_type (template);
407
408         if ( merge == NULL ) {
409                 n_per_page = gl_template_get_n_labels(label_type);
410
411                 gl_print_simple (job, label, n_sheets, first, n_per_page, flags);
412         } else {
413                 gl_print_merge_collated (job, label, n_copies, first, flags);
414         }
415         gl_template_free (template);
416
417         gl_debug (DEBUG_PRINT, "END");
418 }
419 #endif
420
421 /*---------------------------------------------------------------------------*/
422 /* PRIVATE.  new print info structure                                        */
423 /*---------------------------------------------------------------------------*/
424 static PrintInfo *
425 print_info_new (cairo_t          *cr,
426                 glLabel          *label)
427 {
428         PrintInfo            *pi = g_new0 (PrintInfo, 1);
429         glTemplate           *template;
430
431         gl_debug (DEBUG_PRINT, "START");
432
433         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
434
435         template = gl_label_get_template (label);
436
437         g_return_val_if_fail (template, NULL);
438         g_return_val_if_fail (template->page_size, NULL);
439         g_return_val_if_fail (template->page_width > 0, NULL);
440         g_return_val_if_fail (template->page_height > 0, NULL);
441
442         pi->cr = cr;
443
444         gl_debug (DEBUG_PRINT,
445                   "setting page size = \"%s\"", template->page_size);
446
447         pi->page_width  = template->page_width;
448         pi->page_height = template->page_height;
449
450         pi->template = template;
451         pi->label_rotate_flag = gl_label_get_rotate_flag (label);
452
453         gl_debug (DEBUG_PRINT, "END");
454
455         return pi;
456 }
457
458 /*---------------------------------------------------------------------------*/
459 /* PRIVATE.  free print info structure                                       */
460 /*---------------------------------------------------------------------------*/
461 static void
462 print_info_free (PrintInfo **pi)
463 {
464         gl_debug (DEBUG_PRINT, "START");
465
466         gl_template_free ((*pi)->template);
467         (*pi)->template = NULL;
468
469         g_free (*pi);
470         *pi = NULL;
471
472         gl_debug (DEBUG_PRINT, "END");
473 }
474
475 /*---------------------------------------------------------------------------*/
476 /* PRIVATE.  Print crop tick marks.                                          */
477 /*---------------------------------------------------------------------------*/
478 static void
479 print_crop_marks (PrintInfo *pi)
480 {
481         const glTemplateLabelType *label_type;
482         gdouble                    w, h, page_w, page_h;
483         GList                     *p;
484         glTemplateLayout          *layout;
485         gdouble                    xmin, ymin, xmax, ymax, dx, dy;
486         gdouble                    x1, y1, x2, y2, x3, y3, x4, y4;
487         gint                       ix, iy, nx, ny;
488
489         gl_debug (DEBUG_PRINT, "START");
490
491         label_type = gl_template_get_first_label_type (pi->template);
492
493         gl_template_get_label_size (label_type, &w, &h);
494
495         page_w = pi->page_width;
496         page_h = pi->page_height;
497
498         cairo_save (pi->cr);
499
500         cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
501         cairo_set_line_width  (pi->cr, 0.25);
502
503         for (p=label_type->layouts; p != NULL; p=p->next) {
504
505                 layout = (glTemplateLayout *)p->data;
506
507                 xmin = layout->x0;
508                 ymin = layout->y0;
509                 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
510                 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
511
512                 dx = layout->dx;
513                 dy = layout->dy;
514
515                 nx = layout->nx;
516                 ny = layout->ny;
517
518                 for (ix=0; ix < nx; ix++) {
519
520                         x1 = xmin + ix*dx;
521                         x2 = x1 + w;
522
523                         y1 = MAX((ymin - TICK_OFFSET), 0.0);
524                         y2 = MAX((y1 - TICK_LENGTH), 0.0);
525
526                         y3 = MIN((ymax + TICK_OFFSET), page_h);
527                         y4 = MIN((y3 + TICK_LENGTH), page_h);
528
529                         cairo_move_to (pi->cr, x1, y1);
530                         cairo_line_to (pi->cr, x1, y2);
531                         cairo_stroke  (pi->cr);
532
533                         cairo_move_to (pi->cr, x2, y1);
534                         cairo_line_to (pi->cr, x2, y2);
535                         cairo_stroke  (pi->cr);
536
537                         cairo_move_to (pi->cr, x1, y3);
538                         cairo_line_to (pi->cr, x1, y4);
539                         cairo_stroke  (pi->cr);
540
541                         cairo_move_to (pi->cr, x2, y3);
542                         cairo_line_to (pi->cr, x2, y4);
543                         cairo_stroke  (pi->cr);
544
545                 }
546
547                 for (iy=0; iy < ny; iy++) {
548
549                         y1 = ymin + iy*dy;
550                         y2 = y1 + h;
551
552                         x1 = MAX((xmin - TICK_OFFSET), 0.0);
553                         x2 = MAX((x1 - TICK_LENGTH), 0.0);
554
555                         x3 = MIN((xmax + TICK_OFFSET), page_w);
556                         x4 = MIN((x3 + TICK_LENGTH), page_w);
557
558                         cairo_move_to (pi->cr, x1, y1);
559                         cairo_line_to (pi->cr, x2, y1);
560                         cairo_stroke  (pi->cr);
561
562                         cairo_move_to (pi->cr, x1, y2);
563                         cairo_line_to (pi->cr, x2, y2);
564                         cairo_stroke  (pi->cr);
565
566                         cairo_move_to (pi->cr, x3, y1);
567                         cairo_line_to (pi->cr, x4, y1);
568                         cairo_stroke  (pi->cr);
569
570                         cairo_move_to (pi->cr, x3, y2);
571                         cairo_line_to (pi->cr, x4, y2);
572                         cairo_stroke  (pi->cr);
573
574                 }
575
576         }
577
578         cairo_restore (pi->cr);
579
580         gl_debug (DEBUG_PRINT, "END");
581 }
582
583 /*---------------------------------------------------------------------------*/
584 /* PRIVATE.  Print i'th label.                                               */
585 /*---------------------------------------------------------------------------*/
586 static void
587 print_label (PrintInfo     *pi,
588              glLabel       *label,
589              gdouble        x,
590              gdouble        y,
591              glMergeRecord *record,
592              gboolean       outline_flag,
593              gboolean       reverse_flag)
594 {
595         const glTemplateLabelType *label_type;
596         gdouble                    width, height;
597
598         gl_debug (DEBUG_PRINT, "START");
599
600         label_type = gl_template_get_first_label_type (pi->template);
601
602         gl_label_get_size (label, &width, &height);
603
604         cairo_save (pi->cr);
605
606         /* Transform coordinate system to be relative to upper corner */
607         /* of the current label */
608         cairo_translate (pi->cr, x, y);
609         if (gl_label_get_rotate_flag (label)) {
610                 gl_debug (DEBUG_PRINT, "Rotate flag set");
611                 cairo_rotate (pi->cr, -M_PI/2.0);
612                 cairo_translate (pi->cr, -width, 0.0);
613         }
614         if ( reverse_flag ) {
615                 cairo_translate (pi->cr, width, 0.0);
616                 cairo_scale (pi->cr, -1.0, 1.0);
617         }
618
619         clip_to_outline (pi, label);
620         draw_label (pi, label, record);
621         if (outline_flag) {
622                 draw_outline (pi, label);
623         }
624
625         cairo_restore (pi->cr);
626
627         gl_debug (DEBUG_PRINT, "END");
628 }
629
630 /*---------------------------------------------------------------------------*/
631 /* PRIVATE.  Draw label.                                                     */
632 /*---------------------------------------------------------------------------*/
633 static void
634 draw_label (PrintInfo     *pi,
635             glLabel       *label,
636             glMergeRecord *record)
637 {
638         GList *p_obj;
639         glLabelObject *object;
640
641         gl_debug (DEBUG_PRINT, "START");
642
643         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
644                 object = (glLabelObject *) p_obj->data;
645
646                 draw_object (pi, object, record);
647         }
648
649         gl_debug (DEBUG_PRINT, "END");
650 }
651
652 /*---------------------------------------------------------------------------*/
653 /* PRIVATE.  Draw object.                                                    */
654 /*---------------------------------------------------------------------------*/
655 static void
656 draw_object (PrintInfo     *pi,
657              glLabelObject *object,
658              glMergeRecord *record)
659 {
660         gdouble x0, y0;
661         gdouble a[6];
662         cairo_matrix_t matrix;
663
664         gl_debug (DEBUG_PRINT, "START");
665
666         gl_label_object_get_position (object, &x0, &y0);
667         gl_label_object_get_affine (object, a);
668         cairo_matrix_init (&matrix, a[0], a[1], a[2], a[3], a[4], a[5]);
669
670         cairo_save (pi->cr);
671
672         cairo_translate (pi->cr, x0, y0);
673         cairo_transform (pi->cr, &matrix);
674
675
676         if (GL_IS_LABEL_TEXT(object)) {
677                 draw_text_object (pi, GL_LABEL_TEXT(object), record);
678         } else if (GL_IS_LABEL_BOX(object)) {
679                 draw_box_object (pi, GL_LABEL_BOX(object), record);
680         } else if (GL_IS_LABEL_LINE(object)) {
681                 draw_line_object (pi, GL_LABEL_LINE(object), record);
682         } else if (GL_IS_LABEL_ELLIPSE(object)) {
683                 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object), record);
684         } else if (GL_IS_LABEL_IMAGE(object)) {
685                 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
686         } else if (GL_IS_LABEL_BARCODE(object)) {
687                 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
688         }
689
690         cairo_restore (pi->cr);
691
692         gl_debug (DEBUG_PRINT, "END");
693 }
694
695 /*---------------------------------------------------------------------------*/
696 /* PRIVATE.  Draw text object.                                               */
697 /*---------------------------------------------------------------------------*/
698 static void
699 draw_text_object (PrintInfo     *pi,
700                   glLabelText   *object,
701                   glMergeRecord *record)
702 {
703         gint             i;
704         gdouble          x_offset, y_offset, w, object_w, object_h;
705         gchar           *text;
706         GList           *lines;
707         gchar           *font_family;
708         gdouble          font_size;
709         GnomeFontWeight  font_weight;
710         gboolean         font_italic_flag;
711         guint            color;
712         glColorNode     *color_node;
713         GtkJustification just;
714         gboolean         auto_shrink;
715         ArtDRect         bbox;
716         gdouble          affine[6];
717         gdouble          text_line_spacing;
718         gboolean         shadow_state;
719         gdouble          shadow_x, shadow_y;
720         glColorNode     *shadow_color_node;
721         gdouble          shadow_opacity;
722         guint            shadow_color;
723         PangoAlignment   alignment;
724         PangoStyle       style;
725         PangoLayout     *layout;
726         PangoFontDescription *desc;
727
728
729         gl_debug (DEBUG_PRINT, "START");
730
731         gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
732         lines = gl_label_text_get_lines (object);
733         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
734         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
735         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
736         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
737
738         color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
739         color = gl_color_node_expand (color_node, record);
740         gl_color_node_free (&color_node);
741         
742         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
743         text_line_spacing =
744                 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
745         auto_shrink = gl_label_text_get_auto_shrink (object);
746
747         shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
748         gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
749         shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
750         if (shadow_color_node->field_flag)
751         {
752                 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
753         }
754         shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
755         shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
756         gl_color_node_free (&shadow_color_node);
757
758         text = gl_text_node_lines_expand (lines, record);
759
760         switch (just) {
761         case GTK_JUSTIFY_LEFT:
762                 alignment = PANGO_ALIGN_LEFT;
763                 break;
764         case GTK_JUSTIFY_CENTER:
765                 alignment = PANGO_ALIGN_CENTER;
766                 break;
767         case GTK_JUSTIFY_RIGHT:
768                 alignment = PANGO_ALIGN_RIGHT;
769                 break;
770         default:
771                 alignment = PANGO_ALIGN_LEFT;
772                 break;  /* shouldn't happen */
773         }
774
775         style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
776
777
778         if (record && auto_shrink) {
779
780                 /* auto shrink text size to keep within text box limits. */
781
782                 layout = pango_cairo_create_layout (pi->cr);
783
784                 desc = pango_font_description_new ();
785                 pango_font_description_set_family (desc, font_family);
786                 pango_font_description_set_weight (desc, font_weight);
787                 pango_font_description_set_style  (desc, style);
788                 pango_font_description_set_size   (desc, font_size * PANGO_SCALE * FONT_SCALE);
789                 pango_layout_set_font_description (layout, desc);
790                 pango_font_description_free       (desc);
791
792                 pango_layout_set_text (layout, text, -1);
793                 w = pango_layout_get_width (layout) / PANGO_SCALE;
794
795                 g_object_unref (layout);
796
797                 if ( w > object_w )
798                 {
799                         /* Scale down. */
800                         font_size *= (object_w-2*GL_LABEL_TEXT_MARGIN)/w;
801
802                         /* Round down to nearest 1/2 point */
803                         font_size = (int)(font_size*2.0) / 2.0;
804
805                         /* don't get ridiculously small. */
806                         if (font_size < 1.0)
807                         {
808                                 font_size = 1.0;
809                         }
810                 }
811         }
812
813
814         layout = pango_cairo_create_layout (pi->cr);
815
816         desc = pango_font_description_new ();
817         pango_font_description_set_family (desc, font_family);
818         pango_font_description_set_weight (desc, font_weight);
819         pango_font_description_set_style  (desc, style);
820         pango_font_description_set_size   (desc, font_size * PANGO_SCALE * FONT_SCALE);
821         pango_layout_set_font_description (layout, desc);
822         pango_font_description_free       (desc);
823
824         pango_layout_set_text (layout, text, -1);
825         pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE);
826         pango_layout_set_width (layout, object_w * PANGO_SCALE);
827         pango_layout_set_alignment (layout, alignment);
828
829         if (shadow_state)
830         {
831                 cairo_set_source_rgba (pi->cr,
832                                        GL_COLOR_F_RED (shadow_color),
833                                        GL_COLOR_F_GREEN (shadow_color),
834                                        GL_COLOR_F_BLUE (shadow_color),
835                                        GL_COLOR_F_ALPHA (shadow_color));
836
837                 cairo_move_to (pi->cr, shadow_x + GL_LABEL_TEXT_MARGIN, shadow_y);
838                 pango_cairo_show_layout (pi->cr, layout);
839         }
840
841         cairo_set_source_rgba (pi->cr,
842                                GL_COLOR_F_RED (color),
843                                GL_COLOR_F_GREEN (color),
844                                GL_COLOR_F_BLUE (color),
845                                GL_COLOR_F_ALPHA (color));
846
847         cairo_move_to (pi->cr, GL_LABEL_TEXT_MARGIN, 0);
848         pango_cairo_show_layout (pi->cr, layout);
849
850         g_object_unref (layout);
851
852
853         gl_text_node_lines_free (&lines);
854         g_free (font_family);
855
856         gl_debug (DEBUG_PRINT, "END");
857 }
858
859 /*---------------------------------------------------------------------------*/
860 /* PRIVATE.  Draw box object.                                                */
861 /*---------------------------------------------------------------------------*/
862 static void
863 draw_box_object (PrintInfo  *pi,
864                  glLabelBox *object,
865                  glMergeRecord  *record)
866 {
867         gdouble      w, h;
868         gdouble      line_width;
869         guint        line_color;
870         glColorNode *line_color_node;
871         glColorNode *fill_color_node;
872         guint        fill_color;
873         gboolean     shadow_state;
874         gdouble      shadow_x, shadow_y;
875         glColorNode *shadow_color_node;
876         gdouble      shadow_opacity;
877         guint        shadow_line_color;
878         guint        shadow_fill_color;
879
880         gl_debug (DEBUG_PRINT, "START");
881
882         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
883         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
884         
885         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
886         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
887         line_color = gl_color_node_expand (line_color_node, record);
888         fill_color = gl_color_node_expand (fill_color_node, record);
889         gl_color_node_free (&line_color_node);
890         gl_color_node_free (&fill_color_node);
891
892         shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
893         gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
894         shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
895         if (shadow_color_node->field_flag)
896         {
897                 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
898         }
899         shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
900         shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
901         shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
902         gl_color_node_free (&shadow_color_node);
903         
904         if (shadow_state)
905         {
906                 /* Draw fill shadow */
907                 cairo_rectangle (pi->cr, shadow_x, shadow_y, w, h);
908
909                 cairo_set_source_rgba (pi->cr,
910                                        GL_COLOR_F_RED (shadow_fill_color),
911                                        GL_COLOR_F_GREEN (shadow_fill_color),
912                                        GL_COLOR_F_BLUE (shadow_fill_color),
913                                        GL_COLOR_F_ALPHA (shadow_fill_color));
914                 cairo_fill_preserve (pi->cr);
915
916                 /* Draw outline shadow */
917                 cairo_set_source_rgba (pi->cr,
918                                        GL_COLOR_F_RED (shadow_line_color),
919                                        GL_COLOR_F_GREEN (shadow_line_color),
920                                        GL_COLOR_F_BLUE (shadow_line_color),
921                                        GL_COLOR_F_ALPHA (shadow_line_color));
922                 cairo_set_line_width (pi->cr, line_width);
923                 cairo_stroke (pi->cr);
924         }
925
926         /* Paint fill color */
927         cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
928         cairo_set_source_rgba (pi->cr,
929                                GL_COLOR_F_RED (fill_color),
930                                GL_COLOR_F_GREEN (fill_color),
931                                GL_COLOR_F_BLUE (fill_color),
932                                GL_COLOR_F_ALPHA (fill_color));
933         cairo_fill_preserve (pi->cr);
934
935         /* Draw outline */
936         cairo_set_source_rgba (pi->cr,
937                                GL_COLOR_F_RED (line_color),
938                                GL_COLOR_F_GREEN (line_color),
939                                GL_COLOR_F_BLUE (line_color),
940                                GL_COLOR_F_ALPHA (line_color));
941         cairo_set_line_width (pi->cr, line_width);
942         cairo_stroke (pi->cr);
943
944         gl_debug (DEBUG_PRINT, "END");
945 }
946
947 /*---------------------------------------------------------------------------*/
948 /* PRIVATE.  Draw line object.                                               */
949 /*---------------------------------------------------------------------------*/
950 static void
951 draw_line_object (PrintInfo   *pi,
952                   glLabelLine *object,
953                   glMergeRecord  *record)
954 {
955         gdouble      w, h;
956         gdouble      line_width;
957         guint        line_color;
958         glColorNode *line_color_node;
959         gboolean     shadow_state;
960         gdouble      shadow_x, shadow_y;
961         glColorNode *shadow_color_node;
962         gdouble      shadow_opacity;
963         guint        shadow_line_color;
964
965         gl_debug (DEBUG_PRINT, "START");
966
967         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
968         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
969         
970         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
971         line_color = gl_color_node_expand (line_color_node, record);
972         gl_color_node_free (&line_color_node);
973
974         shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
975         gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
976         shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
977         if (shadow_color_node->field_flag)
978         {
979                 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
980         }
981         shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
982         shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
983         gl_color_node_free (&shadow_color_node);
984
985         if (shadow_state)
986         {
987                 cairo_move_to (pi->cr, shadow_x, shadow_y);
988                 cairo_line_to (pi->cr, shadow_x + w, shadow_y + h);
989                 cairo_set_source_rgba (pi->cr,
990                                        GL_COLOR_F_RED (shadow_line_color),
991                                        GL_COLOR_F_GREEN (shadow_line_color),
992                                        GL_COLOR_F_BLUE (shadow_line_color),
993                                        GL_COLOR_F_ALPHA (shadow_line_color));
994                 cairo_set_line_width (pi->cr, line_width);
995                 cairo_stroke (pi->cr);
996         }
997
998         cairo_move_to (pi->cr, 0.0, 0.0);
999         cairo_line_to (pi->cr, w, h);
1000         cairo_set_source_rgba (pi->cr,
1001                                GL_COLOR_F_RED (line_color),
1002                                GL_COLOR_F_GREEN (line_color),
1003                                GL_COLOR_F_BLUE (line_color),
1004                                GL_COLOR_F_ALPHA (line_color));
1005         cairo_set_line_width (pi->cr, line_width);
1006         cairo_stroke (pi->cr);
1007
1008         gl_debug (DEBUG_PRINT, "END");
1009 }
1010
1011 /*---------------------------------------------------------------------------*/
1012 /* PRIVATE.  Draw ellipse object.                                            */
1013 /*---------------------------------------------------------------------------*/
1014 static void
1015 draw_ellipse_object (PrintInfo      *pi,
1016                      glLabelEllipse *object,
1017                      glMergeRecord  *record)
1018 {
1019         gdouble      x0, y0, rx, ry, w, h;
1020         gdouble      line_width;
1021         glColorNode *line_color_node;
1022         glColorNode *fill_color_node;
1023         guint        line_color;
1024         guint        fill_color;
1025         gboolean     shadow_state;
1026         gdouble      shadow_x, shadow_y;
1027         glColorNode *shadow_color_node;
1028         gdouble      shadow_opacity;
1029         guint        shadow_line_color;
1030         guint        shadow_fill_color;
1031
1032         gl_debug (DEBUG_PRINT, "START");
1033
1034         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1035         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1036         
1037         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1038         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1039         line_color = gl_color_node_expand (line_color_node, record);
1040         fill_color = gl_color_node_expand (fill_color_node, record);
1041         gl_color_node_free (&line_color_node);
1042         gl_color_node_free (&fill_color_node);
1043
1044         rx = w / 2.0;
1045         ry = h / 2.0;
1046         x0 = rx;
1047         y0 = ry;
1048
1049         shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
1050         gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
1051         shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
1052         if (shadow_color_node->field_flag)
1053         {
1054                 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
1055         }
1056         shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
1057         shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
1058         shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
1059         gl_color_node_free (&shadow_color_node);
1060         
1061         if (shadow_state)
1062         {
1063                 /* Draw fill shadow */
1064                 create_ellipse_path (pi->cr, x0+shadow_x, y0+shadow_y, rx, ry);
1065                 cairo_set_source_rgba (pi->cr,
1066                                        GL_COLOR_F_RED (shadow_fill_color),
1067                                        GL_COLOR_F_GREEN (shadow_fill_color),
1068                                        GL_COLOR_F_BLUE (shadow_fill_color),
1069                                        GL_COLOR_F_ALPHA (shadow_fill_color));
1070                 cairo_fill_preserve (pi->cr);
1071
1072                 /* Draw outline shadow */
1073                 cairo_set_source_rgba (pi->cr,
1074                                        GL_COLOR_F_RED (shadow_line_color),
1075                                        GL_COLOR_F_GREEN (shadow_line_color),
1076                                        GL_COLOR_F_BLUE (shadow_line_color),
1077                                        GL_COLOR_F_ALPHA (shadow_line_color));
1078                 cairo_set_line_width (pi->cr, line_width);
1079                 cairo_stroke (pi->cr);
1080         }
1081
1082         /* Paint fill color */
1083         create_ellipse_path (pi->cr, x0, y0, rx, ry);
1084         cairo_set_source_rgba (pi->cr,
1085                                GL_COLOR_F_RED (fill_color),
1086                                GL_COLOR_F_GREEN (fill_color),
1087                                GL_COLOR_F_BLUE (fill_color),
1088                                GL_COLOR_F_ALPHA (fill_color));
1089         cairo_fill_preserve (pi->cr);
1090
1091         /* Draw outline */
1092         cairo_set_source_rgba (pi->cr,
1093                                GL_COLOR_F_RED (line_color),
1094                                GL_COLOR_F_GREEN (line_color),
1095                                GL_COLOR_F_BLUE (line_color),
1096                                GL_COLOR_F_ALPHA (line_color));
1097         cairo_set_line_width (pi->cr, line_width);
1098         cairo_stroke (pi->cr);
1099
1100         gl_debug (DEBUG_PRINT, "END");
1101 }
1102
1103 /*---------------------------------------------------------------------------*/
1104 /* PRIVATE.  Draw image object.                                              */
1105 /*---------------------------------------------------------------------------*/
1106 static void
1107 draw_image_object (PrintInfo     *pi,
1108                    glLabelImage  *object,
1109                    glMergeRecord *record)
1110 {
1111         gdouble w, h;
1112         const GdkPixbuf *pixbuf;
1113         gint image_w, image_h;
1114
1115         gl_debug (DEBUG_PRINT, "START");
1116
1117         gl_label_object_get_size     (GL_LABEL_OBJECT(object), &w, &h);
1118
1119         pixbuf = gl_label_image_get_pixbuf (object, record);
1120         image_w = gdk_pixbuf_get_width (pixbuf);
1121         image_h = gdk_pixbuf_get_height (pixbuf);
1122
1123         cairo_save (pi->cr);
1124         cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
1125         cairo_clip (pi->cr);
1126         cairo_scale (pi->cr, w/image_w, h/image_h);
1127         gdk_cairo_set_source_pixbuf (pi->cr, (GdkPixbuf *)pixbuf, 0, 0);
1128         cairo_paint (pi->cr);
1129
1130         cairo_restore (pi->cr);
1131
1132         gl_debug (DEBUG_PRINT, "END");
1133 }
1134
1135 /*---------------------------------------------------------------------------*/
1136 /* PRIVATE.  Draw barcode object.                                            */
1137 /*---------------------------------------------------------------------------*/
1138 static void
1139 draw_barcode_object (PrintInfo      *pi,
1140                      glLabelBarcode *object,
1141                      glMergeRecord  *record)
1142 {
1143         glBarcode          *gbc;
1144         glBarcodeLine      *line;
1145         glBarcodeChar      *bchar;
1146         GList              *li;
1147         gdouble             y_offset;
1148         PangoLayout        *layout;
1149         PangoFontDescription *desc;
1150         gchar              *text, *cstring;
1151         glTextNode         *text_node;
1152         gchar              *id;
1153         gboolean            text_flag;
1154         gboolean            checksum_flag;
1155         guint               color;
1156         glColorNode        *color_node;
1157         guint               format_digits;
1158         gdouble             w, h;
1159
1160         gl_debug (DEBUG_PRINT, "START");
1161
1162         text_node = gl_label_barcode_get_data (object);
1163         gl_label_barcode_get_props (object,
1164                                     &id, &text_flag, &checksum_flag, &format_digits);
1165                                         
1166         color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1167         color = gl_color_node_expand (color_node, record);
1168         gl_color_node_free (&color_node);
1169         
1170         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1171
1172         text = gl_text_node_expand (text_node, record);
1173
1174         if (text == NULL || *text == '\0') {
1175
1176                 g_free(text);
1177                 gl_text_node_free(&text_node);
1178                 g_free(id);
1179
1180                 return;
1181         }
1182
1183         gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1184         g_free (text);
1185         gl_text_node_free (&text_node);
1186         g_free (id);
1187
1188         cairo_set_source_rgba (pi->cr,
1189                                GL_COLOR_F_RED (color),
1190                                GL_COLOR_F_GREEN (color),
1191                                GL_COLOR_F_BLUE (color),
1192                                GL_COLOR_F_ALPHA (color));
1193
1194         if (gbc == NULL) {
1195
1196                 layout = pango_cairo_create_layout (pi->cr);
1197
1198                 desc = pango_font_description_new ();
1199                 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
1200                 pango_font_description_set_size   (desc, 12 * PANGO_SCALE * FONT_SCALE);
1201                 pango_layout_set_font_description (layout, desc);
1202                 pango_font_description_free       (desc);
1203
1204                 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
1205
1206                 pango_cairo_show_layout (pi->cr, layout);
1207
1208                 g_object_unref (layout);
1209
1210         } else {
1211
1212                 for (li = gbc->lines; li != NULL; li = li->next) {
1213                         line = (glBarcodeLine *) li->data;
1214
1215                         cairo_move_to (pi->cr, line->x, line->y);
1216                         cairo_line_to (pi->cr, line->x, line->y + line->length);
1217                         cairo_set_line_width (pi->cr, line->width);
1218                         cairo_stroke (pi->cr);
1219                 }
1220
1221                 for (li = gbc->chars; li != NULL; li = li->next) {
1222                         bchar = (glBarcodeChar *) li->data;
1223
1224                         layout = pango_cairo_create_layout (pi->cr);
1225
1226                         desc = pango_font_description_new ();
1227                         pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
1228                         pango_font_description_set_size   (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
1229                         pango_layout_set_font_description (layout, desc);
1230                         pango_font_description_free       (desc);
1231
1232                         cstring = g_strdup_printf ("%c", bchar->c);
1233                         pango_layout_set_text (layout, cstring, -1);
1234                         g_free (cstring);
1235
1236                         y_offset = 0.2 * bchar->fsize;
1237
1238                         cairo_move_to (pi->cr, bchar->x, bchar->y-y_offset);
1239                         pango_cairo_show_layout (pi->cr, layout);
1240
1241                         g_object_unref (layout);
1242
1243                 }
1244
1245                 gl_barcode_free (&gbc);
1246
1247         }
1248
1249         gl_debug (DEBUG_PRINT, "END");
1250 }
1251
1252 /*---------------------------------------------------------------------------*/
1253 /* PRIVATE.  Draw outline.                                                   */
1254 /*---------------------------------------------------------------------------*/
1255 static void
1256 draw_outline (PrintInfo *pi,
1257               glLabel   *label)
1258 {
1259         const glTemplateLabelType *label_type;
1260         gdouble                    w, h, r;
1261         gdouble                    r1, r2;
1262
1263         gl_debug (DEBUG_PRINT, "START");
1264
1265         label_type = gl_template_get_first_label_type (pi->template);
1266
1267         cairo_save (pi->cr);
1268
1269         cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
1270         cairo_set_line_width  (pi->cr, 0.25);
1271
1272         switch (label_type->shape) {
1273
1274         case GL_TEMPLATE_SHAPE_RECT:
1275                 gl_label_get_size (label, &w, &h);
1276                 r = label_type->size.rect.r;
1277                 if (r == 0.0) {
1278                         /* simple rectangle */
1279                         cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
1280                 } else {
1281                         /* rectangle with rounded corners */
1282                         create_rounded_rectangle_path (pi->cr, 0.0, 0.0,
1283                                                        w, h, r);
1284                 }
1285                 cairo_stroke (pi->cr);
1286                 break;
1287
1288         case GL_TEMPLATE_SHAPE_ROUND:
1289                 /* Round style */
1290                 r1 = label_type->size.round.r;
1291                 create_ellipse_path (pi->cr, r1, r1, r1, r1);
1292                 cairo_stroke (pi->cr);
1293                 break;
1294
1295         case GL_TEMPLATE_SHAPE_CD:
1296                 r1 = label_type->size.cd.r1;
1297                 r2 = label_type->size.cd.r2;
1298                 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1299                         /* CD style, round label w/ concentric round hole */
1300                         create_cd_path (pi->cr, r1, r1, 2*r1, 2*r1, r1, r2);
1301
1302                         cairo_stroke (pi->cr);
1303                 } else {
1304                         /* Business Card CD style, clipped round label w/ hole */
1305                         gl_label_get_size (label, &w, &h);
1306                         create_cd_path (pi->cr, w/2, h/2, w, h, r1, r2);
1307                         cairo_stroke (pi->cr);
1308                 }
1309                 break;
1310
1311         default:
1312                 g_message ("Unknown template label style");
1313                 break;
1314         }
1315
1316         cairo_restore (pi->cr);
1317
1318         gl_debug (DEBUG_PRINT, "END");
1319 }
1320
1321 /*---------------------------------------------------------------------------*/
1322 /* PRIVATE.  Clip to outline.                                                */
1323 /*---------------------------------------------------------------------------*/
1324 static void
1325 clip_to_outline (PrintInfo *pi,
1326                  glLabel   *label)
1327 {
1328         const glTemplateLabelType *label_type;
1329         gdouble                    w, h, r;
1330         gdouble                    r1, r2;
1331         gdouble                    waste, x_waste, y_waste;
1332
1333         gl_debug (DEBUG_PRINT, "START");
1334
1335         label_type = gl_template_get_first_label_type (pi->template);
1336
1337         switch (label_type->shape) {
1338
1339         case GL_TEMPLATE_SHAPE_RECT:
1340                 gl_label_get_size (label, &w, &h);
1341                 r = label_type->size.rect.r;
1342                 x_waste = label_type->size.rect.x_waste;
1343                 y_waste = label_type->size.rect.y_waste;
1344                 if (r == 0.0) {
1345                         /* simple rectangle */
1346                         cairo_rectangle (pi->cr,
1347                                          -x_waste, -y_waste,
1348                                          w+2*x_waste, h+2*y_waste);
1349                 } else {
1350                         /* rectangle with rounded corners */
1351                         create_rounded_rectangle_path (pi->cr,
1352                                                        -x_waste, -y_waste,
1353                                                        w+2*x_waste, h+2*y_waste, r);
1354                 }
1355                 cairo_clip (pi->cr);
1356                 break;
1357
1358         case GL_TEMPLATE_SHAPE_ROUND:
1359                 r1 = label_type->size.round.r;
1360                 waste = label_type->size.round.waste;
1361                 create_ellipse_path (pi->cr, r1, r1, r1+waste, r1+waste);
1362                 cairo_clip (pi->cr);
1363                 break;
1364
1365         case GL_TEMPLATE_SHAPE_CD:
1366                 waste = label_type->size.cd.waste;
1367                 r1    = label_type->size.cd.r1;
1368                 r2    = label_type->size.cd.r2;
1369                 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1370                         /* CD style, round label w/ concentric round hole */
1371                         create_cd_path (pi->cr,
1372                                         r1, r1,
1373                                         2*(r1+waste), 2*(r1+waste),
1374                                         r1+waste,
1375                                         r2-waste);
1376                 } else {
1377                         /* Business Card CD style, clipped round label w/ hole */
1378                         gl_label_get_size (label, &w, &h);
1379                         create_cd_path (pi->cr,
1380                                         w/2, h/2,
1381                                         w+2*waste, h+2*waste,
1382                                         r1+waste,
1383                                         r2-waste);
1384                 }
1385                 cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
1386                 cairo_clip (pi->cr);
1387                 break;
1388
1389         default:
1390                 g_message ("Unknown template label style");
1391                 break;
1392         }
1393
1394         gl_debug (DEBUG_PRINT, "END");
1395 }
1396
1397 /*---------------------------------------------------------------------------*/
1398 /* PRIVATE.  Path creation utilities.                                        */
1399 /*---------------------------------------------------------------------------*/
1400 static void
1401 create_rounded_rectangle_path (cairo_t           *cr,
1402                                gdouble            x0,
1403                                gdouble            y0,
1404                                gdouble            w,
1405                                gdouble            h,
1406                                gdouble            r)
1407 {
1408         gdouble x, y;
1409         gint i_theta;
1410
1411         gl_debug (DEBUG_PRINT, "START");
1412
1413         cairo_new_path (cr);
1414
1415         cairo_arc_negative (cr, x0+r,   y0+r,   r, 3*M_PI/2, M_PI);
1416         cairo_arc_negative (cr, x0+r,   y0+h-r, r, M_PI,     M_PI/2);
1417         cairo_arc_negative (cr, x0+w-r, y0+h-r, r, M_PI/2,   0.);
1418         cairo_arc_negative (cr, x0+w-r, y0+r,   r, 2*M_PI,   3*M_PI/2);
1419         cairo_close_path (cr);
1420
1421         gl_debug (DEBUG_PRINT, "END");
1422 }
1423
1424 static void
1425 create_ellipse_path (cairo_t           *cr,
1426                      gdouble            x0,
1427                      gdouble            y0,
1428                      gdouble            rx,
1429                      gdouble            ry)
1430 {
1431         gdouble x, y;
1432         gint i_theta;
1433
1434         gl_debug (DEBUG_PRINT, "START");
1435
1436         cairo_new_path (cr);
1437         cairo_move_to (cr, x0 + rx, y0);
1438         for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1439                 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1440                 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1441                 cairo_line_to (cr, x, y);
1442         }
1443         cairo_close_path (cr);
1444
1445         gl_debug (DEBUG_PRINT, "END");
1446 }
1447
1448 static void
1449 create_cd_path (cairo_t           *cr,
1450                 gdouble            x0,
1451                 gdouble            y0,
1452                 gdouble            w,
1453                 gdouble            h,
1454                 gdouble            r1,
1455                 gdouble            r2)
1456 {
1457         gdouble theta1, theta2;
1458
1459         gl_debug (DEBUG_PRINT, "START");
1460
1461         /*
1462          * Outer radius.  (may be clipped)
1463          */
1464         theta1 = acos (w / (2.0*r1));
1465         theta2 = asin (h / (2.0*r1));
1466
1467         cairo_new_path (cr);
1468         cairo_arc (cr, x0, y0, r1, theta1,        theta2);
1469         cairo_arc (cr, x0, y0, r1, M_PI-theta2,   M_PI-theta1);
1470         cairo_arc (cr, x0, y0, r1, M_PI+theta1,   M_PI+theta2);
1471         cairo_arc (cr, x0, y0, r1, 2*M_PI-theta2, 2*M_PI-theta1);
1472         cairo_close_path (cr);
1473
1474         /*
1475          * Inner radius.  (hole)
1476          */
1477         cairo_new_sub_path (cr);
1478         cairo_arc (cr, x0, y0, r2, 0.0, 2*M_PI);
1479         cairo_close_path (cr);
1480
1481         gl_debug (DEBUG_PRINT, "END");
1482 }