]> git.sur5r.net Git - glabels/blob - glabels2/src/print.c
2006-01-19 Jim Evins <evins@snaught.com>
[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  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 #define ARC_COURSE 5  /* Resolution in degrees of small arcs */
49
50 #define TICK_OFFSET  2.25
51 #define TICK_LENGTH 18.0
52
53 /*=========================================================================*/
54 /* Private types.                                                          */
55 /*=========================================================================*/
56
57 typedef struct _PrintInfo {
58         /* gnome print context */
59         GnomePrintContext *pc;
60
61         /* gnome print configuration */
62         GnomePrintConfig *config;
63
64         /* gLabels Template */
65         glTemplate *template;
66         gboolean label_rotate_flag;
67
68         /* page size */
69         gdouble page_width;
70         gdouble page_height;
71
72         /* page counter */
73         gint sheet;
74 } PrintInfo;
75
76
77 /*=========================================================================*/
78 /* Private function prototypes.                                            */
79 /*=========================================================================*/
80 static PrintInfo *print_info_new              (GnomePrintJob    *job,
81                                                glLabel          *label);
82
83 static void       print_info_free             (PrintInfo       **pi);
84
85
86 static void       print_page_begin            (PrintInfo        *pi);
87
88 static void       print_page_end              (PrintInfo        *pi);
89
90 static void       print_crop_marks            (PrintInfo        *pi);
91
92 static void       print_label                 (PrintInfo        *pi,
93                                                glLabel          *label,
94                                                gdouble           x,
95                                                gdouble           y,
96                                                glMergeRecord    *record,
97                                                gboolean          outline_flag,
98                                                gboolean          reverse_flag);
99
100
101 static void       draw_label                  (PrintInfo        *pi,
102                                                glLabel          *label,
103                                                glMergeRecord    *record);
104
105
106 static void       draw_object                 (PrintInfo        *pi,
107                                                glLabelObject    *object,
108                                                glMergeRecord    *record);
109
110 static void       draw_text_object            (PrintInfo        *pi,
111                                                glLabelText      *object,
112                                                glMergeRecord    *record);
113
114 static void       draw_box_object             (PrintInfo        *pi,
115                                                glLabelBox       *object,
116                                                glMergeRecord    *record);
117
118 static void       draw_line_object            (PrintInfo        *pi,
119                                                glLabelLine      *object,
120                                                glMergeRecord    *record);                                                  
121
122 static void       draw_ellipse_object         (PrintInfo        *pi,
123                                                glLabelEllipse   *object,
124                                                glMergeRecord    *record);
125
126 static void       draw_image_object           (PrintInfo        *pi,
127                                                glLabelImage     *object,
128                                                glMergeRecord    *record);
129
130 static void       draw_barcode_object         (PrintInfo        *pi,
131                                                glLabelBarcode   *object,
132                                                glMergeRecord    *record);
133
134
135 static void       draw_outline                (PrintInfo        *pi,
136                                                glLabel          *label);
137
138 static void       clip_to_outline             (PrintInfo        *pi,
139                                                glLabel          *label);
140
141 static void       clip_punchouts              (PrintInfo        *pi,
142                                                glLabel          *label);
143
144
145 static void       create_rectangle_path         (GnomePrintContext *pc,
146                                                  gdouble            x0,
147                                                  gdouble            y0,
148                                                  gdouble            w,
149                                                  gdouble            h);
150
151 static void       create_ellipse_path           (GnomePrintContext *pc,
152                                                  gdouble            x0,
153                                                  gdouble            y0,
154                                                  gdouble            rx,
155                                                  gdouble            ry);
156
157 static void       create_rounded_rectangle_path (GnomePrintContext *pc,
158                                                  gdouble            x0,
159                                                  gdouble            y0,
160                                                  gdouble            w,
161                                                  gdouble            h,
162                                                  gdouble            r);
163
164 static void       create_clipped_circle_path    (GnomePrintContext *pc,
165                                                  gdouble            x0,
166                                                  gdouble            y0,
167                                                  gdouble            w,
168                                                  gdouble            h,
169                                                  gdouble            r);
170
171 #ifndef NO_ALPHA_HACK
172 static guchar *   get_pixels_as_rgb             (const GdkPixbuf   *pixbuf);
173 #endif
174
175 \f
176 /*****************************************************************************/
177 /* Simple (no merge data) print command.                                     */
178 /*****************************************************************************/
179 void
180 gl_print_simple (GnomePrintJob    *job,
181                  glLabel          *label,
182                  gint              n_sheets,
183                  gint              first,
184                  gint              last,
185                  glPrintFlags     *flags)
186 {
187         PrintInfo                 *pi;
188         const glTemplateLabelType *label_type;
189         gint                       i_sheet, i_label;
190         glTemplateOrigin          *origins;
191
192         gl_debug (DEBUG_PRINT, "START");
193
194         pi         = print_info_new (job, label);
195         label_type = gl_template_get_first_label_type (pi->template);
196
197         origins = gl_template_get_origins (label_type);
198
199         for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
200
201                 print_page_begin (pi);
202                 if (flags->crop_marks) {
203                         print_crop_marks (pi);
204                 }
205
206                 for (i_label = first - 1; i_label < last; i_label++) {
207
208                         print_label (pi, label,
209                                      origins[i_label].x, origins[i_label].y,
210                                      NULL, flags->outline, flags->reverse);
211
212                 }
213
214                 print_page_end (pi);
215         }
216
217         g_free (origins);
218
219         print_info_free (&pi);
220
221         gl_debug (DEBUG_PRINT, "END");
222 }
223
224 /*****************************************************************************/
225 /* Merge print command (collated copies)                                     */
226 /*****************************************************************************/
227 void
228 gl_print_merge_collated (GnomePrintJob    *job,
229                          glLabel          *label,
230                          gint              n_copies,
231                          gint              first,
232                          glPrintFlags     *flags)
233 {
234         glMerge                   *merge;
235         const GList               *record_list;
236         PrintInfo                 *pi;
237         const glTemplateLabelType *label_type;
238         gint                       i_sheet, i_label, n_labels_per_page, i_copy;
239         glMergeRecord             *record;
240         GList                     *p;
241         glTemplateOrigin          *origins;
242
243         gl_debug (DEBUG_PRINT, "START");
244
245         merge = gl_label_get_merge (label);
246         record_list = gl_merge_get_record_list (merge);
247
248         pi = print_info_new (job, label);
249         label_type = gl_template_get_first_label_type (pi->template);
250
251         n_labels_per_page = gl_template_get_n_labels (label_type);
252         origins = gl_template_get_origins (label_type);
253
254         i_sheet = 0;
255         i_label = first - 1;
256
257         for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
258                 record = (glMergeRecord *)p->data;
259                         
260                 if ( record->select_flag ) {
261                         for (i_copy = 0; i_copy < n_copies; i_copy++) {
262
263                                 if ((i_label == 0) || (i_sheet == 0)) {
264                                         i_sheet++;
265                                         print_page_begin (pi);
266                                         if (flags->crop_marks) {
267                                                 print_crop_marks (pi);
268                                         }
269                                 }
270
271                                 print_label (pi, label,
272                                              origins[i_label].x,
273                                              origins[i_label].y,
274                                              record,
275                                              flags->outline, flags->reverse);
276
277                                 i_label = (i_label + 1) % n_labels_per_page;
278                                 if (i_label == 0) {
279                                         print_page_end (pi);
280                                 }
281                         }
282                 }
283         }
284
285         if (i_label != 0) {
286                 print_page_end (pi);
287         }
288
289         g_free (origins);
290
291         print_info_free (&pi);
292
293         gl_debug (DEBUG_PRINT, "END");
294 }
295
296 /*****************************************************************************/
297 /* Merge print command (uncollated copies)                                   */
298 /*****************************************************************************/
299 void
300 gl_print_merge_uncollated (GnomePrintJob    *job,
301                            glLabel          *label,
302                            gint              n_copies,
303                            gint              first,
304                            glPrintFlags     *flags)
305 {
306         glMerge                   *merge;
307         const GList               *record_list;
308         PrintInfo                 *pi;
309         const glTemplateLabelType *label_type;
310         gint                       i_sheet, 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 (job, 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         i_sheet = 0;
327         i_label = first - 1;
328
329         for (i_copy = 0; i_copy < n_copies; i_copy++) {
330
331                 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
332                         record = (glMergeRecord *)p->data;
333                         
334                         if ( record->select_flag ) {
335
336
337                                 if ((i_label == 0) || (i_sheet == 0)) {
338                                         i_sheet++;
339                                         print_page_begin (pi);
340                                         if (flags->crop_marks) {
341                                                 print_crop_marks (pi);
342                                         }
343                                 }
344
345                                 print_label (pi, label,
346                                              origins[i_label].x,
347                                              origins[i_label].y,
348                                              record,
349                                              flags->outline, flags->reverse);
350
351                                 i_label = (i_label + 1) % n_labels_per_page;
352                                 if (i_label == 0) {
353                                         print_page_end (pi);
354                                 }
355                         }
356                 }
357
358         }
359         if (i_label != 0) {
360                 print_page_end (pi);
361         }
362
363         g_free (origins);
364
365         print_info_free (&pi);
366
367         gl_debug (DEBUG_PRINT, "END");
368 }
369
370 /*****************************************************************************/
371 /* Batch print.  Call appropriate function above.                            */
372 /*****************************************************************************/
373 void
374 gl_print_batch (GnomePrintJob    *job,
375                 glLabel          *label,
376                 gint              n_sheets,
377                 gint              n_copies,
378                 gint              first,
379                 glPrintFlags     *flags)
380 {
381         glMerge                   *merge;
382         glTemplate                *template;
383         const glTemplateLabelType *label_type;
384         gint                       n_per_page;
385         
386         gl_debug (DEBUG_PRINT, "START");
387
388         merge = gl_label_get_merge (label);
389         template = gl_label_get_template (label);
390         label_type = gl_template_get_first_label_type (template);
391
392         if ( merge == NULL ) {
393                 n_per_page = gl_template_get_n_labels(label_type);
394
395                 gl_print_simple (job, label, n_sheets, first, n_per_page, flags);
396         } else {
397                 gl_print_merge_collated (job, label, n_copies, first, flags);
398         }
399         gl_template_free (template);
400
401         gl_debug (DEBUG_PRINT, "END");
402 }
403
404 /*---------------------------------------------------------------------------*/
405 /* PRIVATE.  new print info structure                                        */
406 /*---------------------------------------------------------------------------*/
407 static PrintInfo *
408 print_info_new (GnomePrintJob    *job,
409                 glLabel          *label)
410 {
411         PrintInfo            *pi = g_new0 (PrintInfo, 1);
412         glTemplate           *template;
413
414         gl_debug (DEBUG_PRINT, "START");
415
416         g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
417         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
418
419         template = gl_label_get_template (label);
420
421         g_return_val_if_fail (template, NULL);
422         g_return_val_if_fail (template->page_size, NULL);
423         g_return_val_if_fail (template->page_width > 0, NULL);
424         g_return_val_if_fail (template->page_height > 0, NULL);
425
426         pi->pc = gnome_print_job_get_context (job);
427         pi->config = gnome_print_job_get_config (job);
428
429         gl_debug (DEBUG_PRINT,
430                   "setting page size = \"%s\"", template->page_size);
431
432         gnome_print_config_set_length (pi->config,
433                                        (guchar *)GNOME_PRINT_KEY_PAPER_WIDTH,
434                                        template->page_width,
435                                        GNOME_PRINT_PS_UNIT);
436         gnome_print_config_set_length (pi->config,
437                                        (guchar *)GNOME_PRINT_KEY_PAPER_HEIGHT,
438                                        template->page_height,
439                                        GNOME_PRINT_PS_UNIT);
440
441         pi->page_width  = template->page_width;
442         pi->page_height = template->page_height;
443
444         pi->template = template;
445         pi->label_rotate_flag = gl_label_get_rotate_flag (label);
446
447         pi->sheet = 0;
448
449         gl_debug (DEBUG_PRINT, "END");
450
451         return pi;
452 }
453
454 /*---------------------------------------------------------------------------*/
455 /* PRIVATE.  free print info structure                                       */
456 /*---------------------------------------------------------------------------*/
457 static void
458 print_info_free (PrintInfo **pi)
459 {
460         gl_debug (DEBUG_PRINT, "START");
461
462         gl_template_free ((*pi)->template);
463         (*pi)->template = NULL;
464
465         gnome_print_context_close ((*pi)->pc);
466
467         g_free (*pi);
468         *pi = NULL;
469
470         gl_debug (DEBUG_PRINT, "END");
471 }
472
473 /*---------------------------------------------------------------------------*/
474 /* PRIVATE.  Begin a new page.                                               */
475 /*---------------------------------------------------------------------------*/
476 static void
477 print_page_begin (PrintInfo *pi)
478 {
479         gchar *str;
480
481         gl_debug (DEBUG_PRINT, "START");
482
483         pi->sheet++;
484
485         str = g_strdup_printf ("sheet%02d", pi->sheet);
486         gnome_print_beginpage (pi->pc, (guchar *)str);
487         g_free (str);
488
489         /* Translate and scale, so that our origin is at the upper left. */
490         gnome_print_translate (pi->pc, 0.0, pi->page_height);
491         gnome_print_scale (pi->pc, 1.0, -1.0);
492
493         gl_debug (DEBUG_PRINT, "END");
494 }
495
496 /*---------------------------------------------------------------------------*/
497 /* PRIVATE.  End a page.                                                     */
498 /*---------------------------------------------------------------------------*/
499 static void
500 print_page_end (PrintInfo *pi)
501 {
502         gl_debug (DEBUG_PRINT, "START");
503
504         gnome_print_showpage (pi->pc);
505
506         gl_debug (DEBUG_PRINT, "END");
507 }
508
509 /*---------------------------------------------------------------------------*/
510 /* PRIVATE.  Print crop tick marks.                                          */
511 /*---------------------------------------------------------------------------*/
512 static void
513 print_crop_marks (PrintInfo *pi)
514 {
515         const glTemplateLabelType *label_type;
516         gdouble                    w, h, page_w, page_h;
517         GList                     *p;
518         glTemplateLayout          *layout;
519         gdouble                    xmin, ymin, xmax, ymax, dx, dy;
520         gdouble                    x1, y1, x2, y2, x3, y3, x4, y4;
521         gint                       ix, iy, nx, ny;
522
523         gl_debug (DEBUG_PRINT, "START");
524
525         label_type = gl_template_get_first_label_type (pi->template);
526
527         gl_template_get_label_size (label_type, &w, &h);
528
529         page_w = pi->page_width;
530         page_h = pi->page_height;
531
532         gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
533         gnome_print_setopacity (pi->pc, 1.0);
534         gnome_print_setlinewidth (pi->pc, 0.25);
535
536         for (p=label_type->layouts; p != NULL; p=p->next) {
537
538                 layout = (glTemplateLayout *)p->data;
539
540                 xmin = layout->x0;
541                 ymin = layout->y0;
542                 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
543                 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
544
545                 dx = layout->dx;
546                 dy = layout->dy;
547
548                 nx = layout->nx;
549                 ny = layout->ny;
550
551                 for (ix=0; ix < nx; ix++) {
552
553                         x1 = xmin + ix*dx;
554                         x2 = x1 + w;
555
556                         y1 = MAX((ymin - TICK_OFFSET), 0.0);
557                         y2 = MAX((y1 - TICK_LENGTH), 0.0);
558
559                         y3 = MIN((ymax + TICK_OFFSET), page_h);
560                         y4 = MIN((y3 + TICK_LENGTH), page_h);
561
562                         gnome_print_moveto (pi->pc, x1, y1);
563                         gnome_print_lineto (pi->pc, x1, y2);
564                         gnome_print_stroke (pi->pc);
565
566                         gnome_print_moveto (pi->pc, x2, y1);
567                         gnome_print_lineto (pi->pc, x2, y2);
568                         gnome_print_stroke (pi->pc);
569
570                         gnome_print_moveto (pi->pc, x1, y3);
571                         gnome_print_lineto (pi->pc, x1, y4);
572                         gnome_print_stroke (pi->pc);
573
574                         gnome_print_moveto (pi->pc, x2, y3);
575                         gnome_print_lineto (pi->pc, x2, y4);
576                         gnome_print_stroke (pi->pc);
577
578                 }
579
580                 for (iy=0; iy < ny; iy++) {
581
582                         y1 = ymin + iy*dy;
583                         y2 = y1 + h;
584
585                         x1 = MAX((xmin - TICK_OFFSET), 0.0);
586                         x2 = MAX((x1 - TICK_LENGTH), 0.0);
587
588                         x3 = MIN((xmax + TICK_OFFSET), page_w);
589                         x4 = MIN((x3 + TICK_LENGTH), page_w);
590
591                         gnome_print_moveto (pi->pc, x1, y1);
592                         gnome_print_lineto (pi->pc, x2, y1);
593                         gnome_print_stroke (pi->pc);
594
595                         gnome_print_moveto (pi->pc, x1, y2);
596                         gnome_print_lineto (pi->pc, x2, y2);
597                         gnome_print_stroke (pi->pc);
598
599                         gnome_print_moveto (pi->pc, x3, y1);
600                         gnome_print_lineto (pi->pc, x4, y1);
601                         gnome_print_stroke (pi->pc);
602
603                         gnome_print_moveto (pi->pc, x3, y2);
604                         gnome_print_lineto (pi->pc, x4, y2);
605                         gnome_print_stroke (pi->pc);
606
607                 }
608
609         }
610
611         gl_debug (DEBUG_PRINT, "END");
612 }
613
614 /*---------------------------------------------------------------------------*/
615 /* PRIVATE.  Print i'th label.                                               */
616 /*---------------------------------------------------------------------------*/
617 static void
618 print_label (PrintInfo     *pi,
619              glLabel       *label,
620              gdouble        x,
621              gdouble        y,
622              glMergeRecord *record,
623              gboolean       outline_flag,
624              gboolean       reverse_flag)
625 {
626         const glTemplateLabelType *label_type;
627         gdouble                    width, height;
628
629         gl_debug (DEBUG_PRINT, "START");
630
631         label_type = gl_template_get_first_label_type (pi->template);
632
633         gl_label_get_size (label, &width, &height);
634
635         gnome_print_gsave (pi->pc);
636
637         /* Transform coordinate system to be relative to upper corner */
638         /* of the current label */
639         gnome_print_translate (pi->pc, x, y);
640         if (gl_label_get_rotate_flag (label)) {
641                 gl_debug (DEBUG_PRINT, "Rotate flag set");
642                 gnome_print_rotate (pi->pc, -90.0);
643                 gnome_print_translate (pi->pc, -width, 0.0);
644         }
645         if ( reverse_flag ) {
646                 gnome_print_translate (pi->pc, width, 0.0);
647                 gnome_print_scale (pi->pc, -1.0, 1.0);
648         }
649
650         clip_to_outline (pi, label);
651         draw_label (pi, label, record);
652         if (outline_flag) {
653                 draw_outline (pi, label);
654         }
655         clip_punchouts (pi, label);
656
657         gnome_print_grestore (pi->pc);
658
659         gl_debug (DEBUG_PRINT, "END");
660 }
661
662 /*---------------------------------------------------------------------------*/
663 /* PRIVATE.  Draw label.                                                     */
664 /*---------------------------------------------------------------------------*/
665 static void
666 draw_label (PrintInfo     *pi,
667             glLabel       *label,
668             glMergeRecord *record)
669 {
670         GList *p_obj;
671         glLabelObject *object;
672
673         gl_debug (DEBUG_PRINT, "START");
674
675         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
676                 object = (glLabelObject *) p_obj->data;
677
678                 draw_object (pi, object, record);
679         }
680
681         gl_debug (DEBUG_PRINT, "END");
682 }
683
684 /*---------------------------------------------------------------------------*/
685 /* PRIVATE.  Draw object.                                                    */
686 /*---------------------------------------------------------------------------*/
687 static void
688 draw_object (PrintInfo     *pi,
689              glLabelObject *object,
690              glMergeRecord *record)
691 {
692         gdouble x0, y0;
693         gdouble affine[6];
694
695         gl_debug (DEBUG_PRINT, "START");
696
697         gl_label_object_get_position (object, &x0, &y0);
698         gl_label_object_get_affine (object, affine);
699
700         gnome_print_gsave (pi->pc);
701
702         gnome_print_translate (pi->pc, x0, y0);
703         gnome_print_concat (pi->pc, affine);
704
705         if (GL_IS_LABEL_TEXT(object)) {
706                 draw_text_object (pi, GL_LABEL_TEXT(object), record);
707         } else if (GL_IS_LABEL_BOX(object)) {
708                 draw_box_object (pi, GL_LABEL_BOX(object), record);
709         } else if (GL_IS_LABEL_LINE(object)) {
710                 draw_line_object (pi, GL_LABEL_LINE(object), record);
711         } else if (GL_IS_LABEL_ELLIPSE(object)) {
712                 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object), record);
713         } else if (GL_IS_LABEL_IMAGE(object)) {
714                 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
715         } else if (GL_IS_LABEL_BARCODE(object)) {
716                 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
717         }
718
719         gnome_print_grestore (pi->pc);
720
721         gl_debug (DEBUG_PRINT, "END");
722 }
723
724 /*---------------------------------------------------------------------------*/
725 /* PRIVATE.  Draw text object.                                               */
726 /*---------------------------------------------------------------------------*/
727 static void
728 draw_text_object (PrintInfo     *pi,
729                   glLabelText   *object,
730                   glMergeRecord *record)
731 {
732         GnomeFont       *font;
733         gchar          **line;
734         gint             i;
735         gdouble          x_offset, y_offset, w, object_w, object_h;
736         gchar           *text;
737         GList           *lines;
738         gchar           *font_family;
739         gdouble          font_size;
740         GnomeFontWeight  font_weight;
741         gboolean         font_italic_flag;
742         guint            color;
743         glColorNode     *color_node;
744         GtkJustification just;
745         gboolean         auto_shrink;
746         GnomeGlyphList  *glyphlist;
747         ArtDRect         bbox;
748         gdouble          affine[6];
749         gdouble          text_line_spacing;
750
751
752         gl_debug (DEBUG_PRINT, "START");
753
754         gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
755         lines = gl_label_text_get_lines (object);
756         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
757         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
758         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
759         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
760
761         color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
762         color = gl_color_node_expand (color_node, record);
763         gl_color_node_free (&color_node);
764         
765         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
766         text_line_spacing =
767                 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
768         auto_shrink = gl_label_text_get_auto_shrink (object);
769
770         text = gl_text_node_lines_expand (lines, record);
771         line = g_strsplit (text, "\n", -1);
772         g_free (text);
773
774         art_affine_identity (affine);
775
776         if (record && auto_shrink) {
777                 /* auto shrink text size to keep within text box limits. */
778                 for (i = 0; line[i] != NULL; i++) {
779
780                         font = gnome_font_find_closest_from_weight_slant (
781                                 (guchar *)font_family,
782                                 font_weight,
783                                 font_italic_flag,
784                                 font_size);
785                         glyphlist = gnome_glyphlist_from_text_dumb (
786                                 font,
787                                 color,
788                                 0.0, 0.0,
789                                 (guchar *)line[i]);
790                         gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
791                         w = bbox.x1;
792                         gnome_glyphlist_unref (glyphlist);
793
794                         /* If width is too large, iteratively shrink font_size until this
795                            line fits the width, or until the font size is ridiculously
796                            small. */
797                         while ( (w > object_w) && (font_size >= 1.0) ) {
798
799                                 font_size -= 0.5;
800
801                                 font = gnome_font_find_closest_from_weight_slant (
802                                         (guchar *)font_family,
803                                         font_weight,
804                                         font_italic_flag,
805                                         font_size);
806                                 glyphlist = gnome_glyphlist_from_text_dumb (
807                                         font,
808                                         color,
809                                         0.0, 0.0,
810                                         (guchar *)line[i]);
811                                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
812                                 w = bbox.x1;
813                                 gnome_glyphlist_unref (glyphlist);
814                         }
815                 }
816
817         }
818
819         font = gnome_font_find_closest_from_weight_slant (
820                                        (guchar *)font_family,
821                                        font_weight,
822                                        font_italic_flag,
823                                        font_size);
824         gnome_print_setfont (pi->pc, font);
825
826         gnome_print_setrgbcolor (pi->pc,
827                                  GL_COLOR_F_RED (color),
828                                  GL_COLOR_F_GREEN (color),
829                                  GL_COLOR_F_BLUE (color));
830         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
831
832         for (i = 0; line[i] != NULL; i++) {
833
834                 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
835                                                             0.0, 0.0,
836                                                             (guchar *)line[i]);
837
838                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
839                 w = bbox.x1;
840                 gnome_glyphlist_unref (glyphlist);
841
842                 switch (just) {
843                 case GTK_JUSTIFY_LEFT:
844                         x_offset = GL_LABEL_TEXT_MARGIN;
845                         break;
846                 case GTK_JUSTIFY_CENTER:
847                         x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
848                         break;
849                 case GTK_JUSTIFY_RIGHT:
850                         x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
851                         break;
852                 default:
853                         x_offset = 0.0;
854                         break;  /* shouldn't happen */
855                 }
856
857                 /* Work out the y position to the BOTTOM of the first line */
858                 y_offset = GL_LABEL_TEXT_MARGIN +
859                            + gnome_font_get_descender (font)
860                            + (i + 1) * font_size * text_line_spacing;
861
862                 /* Remove any text line spacing from the first row. */
863                 y_offset -= font_size * (text_line_spacing - 1);
864
865
866                 gnome_print_moveto (pi->pc, x_offset, y_offset);
867
868                 gnome_print_gsave (pi->pc);
869                 gnome_print_scale (pi->pc, 1.0, -1.0);
870                 gnome_print_show (pi->pc, (guchar *)line[i]);
871                 gnome_print_grestore (pi->pc);
872         }
873
874         g_strfreev (line);
875
876         gl_text_node_lines_free (&lines);
877         g_free (font_family);
878
879         gl_debug (DEBUG_PRINT, "END");
880 }
881
882 /*---------------------------------------------------------------------------*/
883 /* PRIVATE.  Draw box object.                                                */
884 /*---------------------------------------------------------------------------*/
885 static void
886 draw_box_object (PrintInfo  *pi,
887                  glLabelBox *object,
888                  glMergeRecord  *record)
889 {
890         gdouble      w, h;
891         gdouble      line_width;
892         guint        line_color;
893         glColorNode *line_color_node;
894         glColorNode *fill_color_node;
895         guint        fill_color;
896         gboolean     shadow_state;
897         gdouble      shadow_x, shadow_y;
898         glColorNode *shadow_color_node;
899         gdouble      shadow_opacity;
900         guint        shadow_line_color;
901         guint        shadow_fill_color;
902
903         gl_debug (DEBUG_PRINT, "START");
904
905         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
906         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
907         
908         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
909         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
910         line_color = gl_color_node_expand (line_color_node, record);
911         fill_color = gl_color_node_expand (fill_color_node, record);
912         gl_color_node_free (&line_color_node);
913         gl_color_node_free (&fill_color_node);
914
915         shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
916         gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
917         shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
918         if (shadow_color_node->field_flag)
919         {
920                 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
921         }
922         shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
923         shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
924         shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
925         gl_color_node_free (&shadow_color_node);
926         
927         if (shadow_state)
928         {
929                 /* Draw fill shadow */
930                 create_rectangle_path (pi->pc, shadow_x, shadow_y, w, h);
931                 gnome_print_setrgbcolor (pi->pc,
932                                          GL_COLOR_F_RED (shadow_fill_color),
933                                          GL_COLOR_F_GREEN (shadow_fill_color),
934                                          GL_COLOR_F_BLUE (shadow_fill_color));
935                 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (shadow_fill_color));
936                 gnome_print_fill (pi->pc);
937
938                 /* Draw outline shadow */
939                 create_rectangle_path (pi->pc, shadow_x, shadow_y, w, h);
940                 gnome_print_setrgbcolor (pi->pc,
941                                          GL_COLOR_F_RED (shadow_line_color),
942                                          GL_COLOR_F_GREEN (shadow_line_color),
943                                          GL_COLOR_F_BLUE (shadow_line_color));
944                 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (shadow_line_color));
945                 gnome_print_setlinewidth (pi->pc, line_width);
946                 gnome_print_stroke (pi->pc);
947         }
948
949         /* Paint fill color */
950         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
951         gnome_print_setrgbcolor (pi->pc,
952                                  GL_COLOR_F_RED (fill_color),
953                                  GL_COLOR_F_GREEN (fill_color),
954                                  GL_COLOR_F_BLUE (fill_color));
955         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
956         gnome_print_fill (pi->pc);
957
958         /* Draw outline */
959         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
960         gnome_print_setrgbcolor (pi->pc,
961                                  GL_COLOR_F_RED (line_color),
962                                  GL_COLOR_F_GREEN (line_color),
963                                  GL_COLOR_F_BLUE (line_color));
964         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
965         gnome_print_setlinewidth (pi->pc, line_width);
966         gnome_print_stroke (pi->pc);
967
968         gl_debug (DEBUG_PRINT, "END");
969 }
970
971 /*---------------------------------------------------------------------------*/
972 /* PRIVATE.  Draw line object.                                               */
973 /*---------------------------------------------------------------------------*/
974 static void
975 draw_line_object (PrintInfo   *pi,
976                   glLabelLine *object,
977                   glMergeRecord  *record)
978 {
979         gdouble      w, h;
980         gdouble      line_width;
981         guint        line_color;
982         glColorNode *line_color_node;
983
984         gl_debug (DEBUG_PRINT, "START");
985
986         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
987         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
988         
989         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
990         line_color = gl_color_node_expand (line_color_node, record);
991         gl_color_node_free (&line_color_node);
992
993         gnome_print_moveto (pi->pc, 0.0, 0.0);
994         gnome_print_lineto (pi->pc, w, h);
995         gnome_print_setrgbcolor (pi->pc,
996                                  GL_COLOR_F_RED (line_color),
997                                  GL_COLOR_F_GREEN (line_color),
998                                  GL_COLOR_F_BLUE (line_color));
999         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
1000         gnome_print_setlinewidth (pi->pc, line_width);
1001         gnome_print_stroke (pi->pc);
1002
1003         gl_debug (DEBUG_PRINT, "END");
1004 }
1005
1006 /*---------------------------------------------------------------------------*/
1007 /* PRIVATE.  Draw ellipse object.                                            */
1008 /*---------------------------------------------------------------------------*/
1009 static void
1010 draw_ellipse_object (PrintInfo      *pi,
1011                      glLabelEllipse *object,
1012                      glMergeRecord  *record)
1013 {
1014         gdouble      x0, y0, rx, ry, w, h;
1015         gdouble      line_width;
1016         glColorNode *line_color_node;
1017         glColorNode *fill_color_node;
1018         guint        line_color;
1019         guint        fill_color;
1020
1021         gl_debug (DEBUG_PRINT, "START");
1022
1023         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1024         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1025         
1026         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1027         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1028         line_color = gl_color_node_expand (line_color_node, record);
1029         fill_color = gl_color_node_expand (fill_color_node, record);
1030         gl_color_node_free (&line_color_node);
1031         gl_color_node_free (&fill_color_node);
1032
1033         rx = w / 2.0;
1034         ry = h / 2.0;
1035         x0 = rx;
1036         y0 = ry;
1037
1038         /* Paint fill color */
1039         create_ellipse_path (pi->pc, x0, y0, rx, ry);
1040         gnome_print_setrgbcolor (pi->pc,
1041                                  GL_COLOR_F_RED (fill_color),
1042                                  GL_COLOR_F_GREEN (fill_color),
1043                                  GL_COLOR_F_BLUE (fill_color));
1044         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
1045         gnome_print_fill (pi->pc);
1046
1047         /* Draw outline */
1048         create_ellipse_path (pi->pc, x0, y0, rx, ry);
1049         gnome_print_setrgbcolor (pi->pc,
1050                                  GL_COLOR_F_RED (line_color),
1051                                  GL_COLOR_F_GREEN (line_color),
1052                                  GL_COLOR_F_BLUE (line_color));
1053         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
1054         gnome_print_setlinewidth (pi->pc, line_width);
1055         gnome_print_stroke (pi->pc);
1056
1057         gl_debug (DEBUG_PRINT, "END");
1058 }
1059
1060 /*---------------------------------------------------------------------------*/
1061 /* PRIVATE.  Draw image object.                                              */
1062 /*---------------------------------------------------------------------------*/
1063 static void
1064 draw_image_object (PrintInfo     *pi,
1065                    glLabelImage  *object,
1066                    glMergeRecord *record)
1067 {
1068         gdouble w, h;
1069         const GdkPixbuf *pixbuf;
1070         guchar *image_data;
1071         gint image_w, image_h, image_stride;
1072         gboolean image_alpha_flag;
1073         gint ret;
1074
1075         gl_debug (DEBUG_PRINT, "START");
1076
1077         gl_label_object_get_size     (GL_LABEL_OBJECT(object), &w, &h);
1078
1079         pixbuf = gl_label_image_get_pixbuf (object, record);
1080         image_data = gdk_pixbuf_get_pixels (pixbuf);
1081         image_w = gdk_pixbuf_get_width (pixbuf);
1082         image_h = gdk_pixbuf_get_height (pixbuf);
1083         image_stride = gdk_pixbuf_get_rowstride(pixbuf);
1084         image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
1085
1086         gnome_print_gsave (pi->pc);
1087         gnome_print_translate (pi->pc, 0.0, h);
1088         gnome_print_scale (pi->pc, w, -h);
1089         if (image_alpha_flag) {
1090 #ifndef NO_ALPHA_HACK
1091                 guchar *image_data2;
1092
1093                 image_data2 = get_pixels_as_rgb (pixbuf);
1094                 ret = gnome_print_rgbimage (pi->pc, image_data2,
1095                                             image_w, image_h, image_stride);
1096                 g_free (image_data2);
1097 #else
1098                 ret = gnome_print_rgbaimage (pi->pc, image_data,
1099                                             image_w, image_h, image_stride);
1100 #endif
1101         } else {
1102                 ret = gnome_print_rgbimage (pi->pc, image_data,
1103                                             image_w, image_h, image_stride);
1104         }
1105         gnome_print_grestore (pi->pc);
1106
1107         gl_debug (DEBUG_PRINT, "END");
1108 }
1109
1110 /*---------------------------------------------------------------------------*/
1111 /* PRIVATE.  Draw box object.                                                */
1112 /*---------------------------------------------------------------------------*/
1113 static void
1114 draw_barcode_object (PrintInfo      *pi,
1115                      glLabelBarcode *object,
1116                      glMergeRecord  *record)
1117 {
1118         glBarcode          *gbc;
1119         glBarcodeLine      *line;
1120         glBarcodeChar      *bchar;
1121         GList              *li;
1122         gdouble             y_offset;
1123         GnomeFont          *font;
1124         gchar              *text, *cstring;
1125         glTextNode         *text_node;
1126         gchar              *id;
1127         gboolean            text_flag;
1128         gboolean            checksum_flag;
1129         guint               color;
1130         glColorNode        *color_node;
1131         guint               format_digits;
1132         gdouble             w, h;
1133
1134         gl_debug (DEBUG_PRINT, "START");
1135
1136         text_node = gl_label_barcode_get_data (object);
1137         gl_label_barcode_get_props (object,
1138                                     &id, &text_flag, &checksum_flag, &format_digits);
1139                                         
1140         color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1141         color = gl_color_node_expand (color_node, record);
1142         gl_color_node_free (&color_node);
1143         
1144         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1145
1146         text = gl_text_node_expand (text_node, record);
1147         gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1148         g_free (text);
1149         gl_text_node_free (&text_node);
1150         g_free (id);
1151
1152         if (gbc == NULL) {
1153
1154                 font = gnome_font_find_closest_from_weight_slant (
1155                         (guchar *)GL_BARCODE_FONT_FAMILY,
1156                         GL_BARCODE_FONT_WEIGHT,
1157                         FALSE, 12.0);
1158                 gnome_print_setfont (pi->pc, font);
1159
1160                 gnome_print_setrgbcolor (pi->pc,
1161                                          GL_COLOR_F_RED (color),
1162                                          GL_COLOR_F_GREEN (color),
1163                                          GL_COLOR_F_BLUE (color));
1164                 gnome_print_setopacity (pi->pc,
1165                                         GL_COLOR_F_ALPHA (color));
1166
1167                 y_offset = 12.0 - fabs (gnome_font_get_descender (font));
1168                 gnome_print_moveto (pi->pc, 0.0, y_offset);
1169
1170                 gnome_print_gsave (pi->pc);
1171                 gnome_print_scale (pi->pc, 1.0, -1.0);
1172                 gnome_print_show (pi->pc, (guchar *)_("Invalid barcode data"));
1173                 gnome_print_grestore (pi->pc);
1174
1175         } else {
1176
1177                 for (li = gbc->lines; li != NULL; li = li->next) {
1178                         line = (glBarcodeLine *) li->data;
1179
1180                         gnome_print_moveto (pi->pc, line->x, line->y);
1181                         gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1182                         gnome_print_setrgbcolor (pi->pc,
1183                                                  GL_COLOR_F_RED (color),
1184                                                  GL_COLOR_F_GREEN (color),
1185                                                  GL_COLOR_F_BLUE (color));
1186                         gnome_print_setopacity (pi->pc,
1187                                                 GL_COLOR_F_ALPHA (color));
1188                         gnome_print_setlinewidth (pi->pc, line->width);
1189                         gnome_print_stroke (pi->pc);
1190                 }
1191
1192                 for (li = gbc->chars; li != NULL; li = li->next) {
1193                         bchar = (glBarcodeChar *) li->data;
1194
1195                         font = gnome_font_find_closest_from_weight_slant (
1196                                 (guchar *)GL_BARCODE_FONT_FAMILY,
1197                                 GL_BARCODE_FONT_WEIGHT,
1198                                 FALSE, bchar->fsize);
1199                         gnome_print_setfont (pi->pc, font);
1200
1201                         gnome_print_setrgbcolor (pi->pc,
1202                                                  GL_COLOR_F_RED (color),
1203                                                  GL_COLOR_F_GREEN (color),
1204                                                  GL_COLOR_F_BLUE (color));
1205                         gnome_print_setopacity (pi->pc,
1206                                                 GL_COLOR_F_ALPHA (color));
1207
1208                         y_offset =
1209                             bchar->fsize - fabs (gnome_font_get_descender (font));
1210
1211                         gnome_print_moveto (pi->pc, bchar->x, bchar->y+y_offset);
1212
1213                         cstring = g_strdup_printf ("%c", bchar->c);
1214                         gnome_print_gsave (pi->pc);
1215                         gnome_print_scale (pi->pc, 1.0, -1.0);
1216                         gnome_print_show (pi->pc, (guchar *)cstring);
1217                         gnome_print_grestore (pi->pc);
1218                         g_free (cstring);
1219
1220                 }
1221
1222                 gl_barcode_free (&gbc);
1223
1224         }
1225
1226         gl_debug (DEBUG_PRINT, "END");
1227 }
1228
1229 /*---------------------------------------------------------------------------*/
1230 /* PRIVATE.  Draw outline.                                                   */
1231 /*---------------------------------------------------------------------------*/
1232 static void
1233 draw_outline (PrintInfo *pi,
1234               glLabel   *label)
1235 {
1236         const glTemplateLabelType *label_type;
1237         gdouble                    w, h, r;
1238         gdouble                    r1, r2;
1239
1240         gl_debug (DEBUG_PRINT, "START");
1241
1242         label_type = gl_template_get_first_label_type (pi->template);
1243
1244         gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
1245         gnome_print_setopacity (pi->pc, 1.0);
1246         gnome_print_setlinewidth (pi->pc, 0.25);
1247
1248         switch (label_type->shape) {
1249
1250         case GL_TEMPLATE_SHAPE_RECT:
1251                 gl_label_get_size (label, &w, &h);
1252                 r = label_type->size.rect.r;
1253                 if (r == 0.0) {
1254                         /* simple rectangle */
1255                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1256                 } else {
1257                         /* rectangle with rounded corners */
1258                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1259                                                        w, h, r);
1260                 }
1261                 gnome_print_stroke (pi->pc);
1262                 break;
1263
1264         case GL_TEMPLATE_SHAPE_ROUND:
1265                 /* Round style */
1266                 r1 = label_type->size.round.r;
1267                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1268                 gnome_print_stroke (pi->pc);
1269                 break;
1270
1271         case GL_TEMPLATE_SHAPE_CD:
1272                 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1273                         /* CD style, round label w/ concentric round hole */
1274                         r1 = label_type->size.cd.r1;
1275                         r2 = label_type->size.cd.r2;
1276                         create_ellipse_path (pi->pc, r1, r1, r1, r1);
1277                         gnome_print_stroke (pi->pc);
1278                         create_ellipse_path (pi->pc, r1, r1, r2, r2);
1279                         gnome_print_stroke (pi->pc);
1280                 } else {
1281                         /* Business Card CD style, clipped round label w/ hole */
1282                         gl_label_get_size (label, &w, &h);
1283                         r1 = label_type->size.cd.r1;
1284                         r2 = label_type->size.cd.r2;
1285                         create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1286                         gnome_print_stroke (pi->pc);
1287                         create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1288                         gnome_print_stroke (pi->pc);
1289                 }
1290                 break;
1291
1292         default:
1293                 g_message ("Unknown template label style");
1294                 break;
1295         }
1296
1297         gl_debug (DEBUG_PRINT, "END");
1298 }
1299
1300 /*---------------------------------------------------------------------------*/
1301 /* PRIVATE.  Clip to outline.                                                */
1302 /*---------------------------------------------------------------------------*/
1303 static void
1304 clip_to_outline (PrintInfo *pi,
1305                  glLabel   *label)
1306 {
1307         const glTemplateLabelType *label_type;
1308         gdouble                    w, h, r;
1309         gdouble                    r1;
1310         gdouble                    waste, x_waste, y_waste;
1311
1312         gl_debug (DEBUG_PRINT, "START");
1313
1314         label_type = gl_template_get_first_label_type (pi->template);
1315
1316         switch (label_type->shape) {
1317
1318         case GL_TEMPLATE_SHAPE_RECT:
1319                 gl_label_get_size (label, &w, &h);
1320                 r = label_type->size.rect.r;
1321                 x_waste = label_type->size.rect.x_waste;
1322                 y_waste = label_type->size.rect.y_waste;
1323                 if (r == 0.0) {
1324                         /* simple rectangle */
1325                         create_rectangle_path (pi->pc,
1326                                                -x_waste, -y_waste,
1327                                                w+2*x_waste, h+2*y_waste);
1328                 } else {
1329                         /* rectangle with rounded corners */
1330                         create_rounded_rectangle_path (pi->pc,
1331                                                        -x_waste, -y_waste,
1332                                                        w+2*x_waste, h+2*y_waste, r);
1333                 }
1334                 gnome_print_clip (pi->pc);
1335                 break;
1336
1337         case GL_TEMPLATE_SHAPE_ROUND:
1338                 r1 = label_type->size.round.r;
1339                 waste = label_type->size.round.waste;
1340                 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1341                 gnome_print_clip (pi->pc);
1342                 break;
1343
1344         case GL_TEMPLATE_SHAPE_CD:
1345                 waste = label_type->size.cd.waste;
1346                 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1347                         /* CD style, round label w/ concentric round hole */
1348                         r1 = label_type->size.cd.r1;
1349                         create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1350                 } else {
1351                         /* Business Card CD style, clipped round label w/ hole */
1352                         gl_label_get_size (label, &w, &h);
1353                         r1 = label_type->size.cd.r1;
1354                         create_clipped_circle_path (pi->pc,
1355                                                     w/2, h/2,
1356                                                     w+2*waste, h+2*waste,
1357                                                     r1+waste);
1358                 }
1359                 gnome_print_clip (pi->pc);
1360                 break;
1361
1362         default:
1363                 g_message ("Unknown template label style");
1364                 break;
1365         }
1366
1367         gl_debug (DEBUG_PRINT, "END");
1368 }
1369
1370 /*---------------------------------------------------------------------------*/
1371 /* PRIVATE.  Clip punchouts.  (Save some ink by not printing in CD holes)    */
1372 /*                                                                           */
1373 /* Ideally this would be done in clip_to_outline, but I am not sure how to   */
1374 /* invert the region for gnome_print_clip, so instead, I will just draw      */
1375 /* a white circle on top of everything else.                                 */
1376 /*---------------------------------------------------------------------------*/
1377 static void
1378 clip_punchouts (PrintInfo *pi,
1379                 glLabel   *label)
1380 {
1381         const glTemplateLabelType *label_type;
1382         gdouble                    w, h, r2;
1383         gdouble                    waste;
1384
1385         gl_debug (DEBUG_PRINT, "START");
1386
1387         label_type = gl_template_get_first_label_type (pi->template);
1388
1389         switch (label_type->shape) {
1390
1391         case GL_TEMPLATE_SHAPE_RECT:
1392         case GL_TEMPLATE_SHAPE_ROUND:
1393                 break;
1394
1395         case GL_TEMPLATE_SHAPE_CD:
1396                 gl_label_get_size (label, &w, &h);
1397                 waste = label_type->size.cd.waste;
1398                 r2    = label_type->size.cd.r2;
1399                 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1400                 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1401                 gnome_print_setopacity (pi->pc, 1.0);
1402                 gnome_print_fill (pi->pc);
1403                 break;
1404
1405         default:
1406                 g_message ("Unknown template label style");
1407                 break;
1408         }
1409
1410         gl_debug (DEBUG_PRINT, "END");
1411 }
1412
1413 /*---------------------------------------------------------------------------*/
1414 /* PRIVATE.  Path creation utilities.                                        */
1415 /*---------------------------------------------------------------------------*/
1416 static void
1417 create_rectangle_path (GnomePrintContext *pc,
1418                        gdouble            x0,
1419                        gdouble            y0,
1420                        gdouble            w,
1421                        gdouble            h)
1422 {
1423         gl_debug (DEBUG_PRINT, "START");
1424
1425         gnome_print_newpath (pc);
1426         gnome_print_moveto (pc, x0, y0);
1427         gnome_print_lineto (pc, x0 + w, y0);
1428         gnome_print_lineto (pc, x0 + w, y0 + h);
1429         gnome_print_lineto (pc, x0, y0 + h);
1430         gnome_print_lineto (pc, x0, y0);
1431         gnome_print_closepath (pc);
1432
1433         gl_debug (DEBUG_PRINT, "END");
1434 }
1435
1436 static void
1437 create_ellipse_path (GnomePrintContext *pc,
1438                      gdouble            x0,
1439                      gdouble            y0,
1440                      gdouble            rx,
1441                      gdouble            ry)
1442 {
1443         gdouble x, y;
1444         gint i_theta;
1445
1446         gl_debug (DEBUG_PRINT, "START");
1447
1448         gnome_print_newpath (pc);
1449         gnome_print_moveto (pc, x0 + rx, y0);
1450         for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1451                 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1452                 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1453                 gnome_print_lineto (pc, x, y);
1454         }
1455         gnome_print_closepath (pc);
1456
1457         gl_debug (DEBUG_PRINT, "END");
1458 }
1459
1460 static void
1461 create_rounded_rectangle_path (GnomePrintContext *pc,
1462                                gdouble            x0,
1463                                gdouble            y0,
1464                                gdouble            w,
1465                                gdouble            h,
1466                                gdouble            r)
1467 {
1468         gdouble x, y;
1469         gint i_theta;
1470
1471         gl_debug (DEBUG_PRINT, "START");
1472
1473         gnome_print_newpath (pc);
1474
1475         gnome_print_moveto (pc, x0 + r, y0);
1476         for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1477                 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1478                 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1479                 gnome_print_lineto (pc, x, y);
1480         }
1481         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1482                 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1483                 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1484                 gnome_print_lineto (pc, x, y);
1485         }
1486         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1487                 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1488                 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1489                 gnome_print_lineto (pc, x, y);
1490         }
1491         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1492                 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1493                 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1494                 gnome_print_lineto (pc, x, y);
1495         }
1496         gnome_print_lineto (pc, x0 + r, y0);
1497
1498         gnome_print_closepath (pc);
1499
1500         gl_debug (DEBUG_PRINT, "END");
1501 }
1502
1503 static void
1504 create_clipped_circle_path (GnomePrintContext *pc,
1505                             gdouble            x0,
1506                             gdouble            y0,
1507                             gdouble            w,
1508                             gdouble            h,
1509                             gdouble            r)
1510 {
1511         gdouble x, y;
1512         gdouble theta1, theta2;
1513         gint    i_theta;
1514
1515         gl_debug (DEBUG_PRINT, "START");
1516
1517         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1518         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1519
1520         gnome_print_newpath (pc);
1521
1522         x = x0 + r * cos (theta1 * G_PI / 180.0);
1523         y = y0 + r * sin (theta1 * G_PI / 180.0);
1524         gnome_print_moveto (pc, x, y);
1525
1526         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1527                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1528                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1529                 gnome_print_lineto (pc, x, y);
1530         }
1531
1532         x = x0 + r * cos (theta2 * G_PI / 180.0);
1533         y = y0 + r * sin (theta2 * G_PI / 180.0);
1534         gnome_print_lineto (pc, x, y);
1535
1536         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1537                 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1538                 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1539                 gnome_print_lineto (pc, x, y);
1540         }
1541
1542         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1543                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1544                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1545                 gnome_print_lineto (pc, x, y);
1546         }
1547
1548         x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1549         y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1550         gnome_print_lineto (pc, x, y);
1551
1552         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1553                 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1554                 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1555                 gnome_print_lineto (pc, x, y);
1556         }
1557
1558         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1559                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1560                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1561                 gnome_print_lineto (pc, x, y);
1562         }
1563
1564         x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1565         y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1566         gnome_print_lineto (pc, x, y);
1567
1568         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1569                 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1570                 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1571                 gnome_print_lineto (pc, x, y);
1572         }
1573
1574         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1575                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1576                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1577                 gnome_print_lineto (pc, x, y);
1578         }
1579
1580         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1581                 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1582                 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1583                 gnome_print_lineto (pc, x, y);
1584         }
1585
1586         x = x0 + r * cos (theta1 * G_PI / 180.0);
1587         y = y0 + r * sin (theta1 * G_PI / 180.0);
1588         gnome_print_lineto (pc, x, y);
1589
1590         gnome_print_closepath (pc);
1591
1592         gl_debug (DEBUG_PRINT, "END");
1593 }
1594
1595 #ifndef NO_ALPHA_HACK
1596 /*---------------------------------------------------------------------------*/
1597 /* PRIVATE.  Extract a copy of rgba pixels, removing alpha by compositing    */
1598 /* with a white background.                                                  */
1599 /*                                                                           */
1600 /* This is currently needed due to the lousy job gnome-print does in         */
1601 /* rendering images with alpha channels to PS.  This sacrafices the ability  */
1602 /* to do compositing of images with other items in the background.           */
1603 /*---------------------------------------------------------------------------*/
1604 static guchar *
1605 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1606 {
1607         gint             bits_per_sample, channels;
1608         gboolean         has_alpha;
1609         gint             width, height, rowstride;
1610         gulong           bytes;
1611         guchar          *buf_src, *buf_dest;
1612         guchar          *p_src, *p_dest;
1613         gint             ix, iy;
1614         guchar           r, g, b, a;
1615         gdouble          alpha, beta;
1616
1617         gl_debug (DEBUG_PRINT, "START");
1618
1619         g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1620
1621         /* extract pixels and parameters from pixbuf. */
1622         buf_src         = gdk_pixbuf_get_pixels (pixbuf);
1623         bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1624         channels        = gdk_pixbuf_get_n_channels (pixbuf);
1625         has_alpha       = gdk_pixbuf_get_has_alpha (pixbuf);
1626         width           = gdk_pixbuf_get_width (pixbuf);
1627         height          = gdk_pixbuf_get_height (pixbuf);
1628         rowstride       = gdk_pixbuf_get_rowstride (pixbuf);
1629
1630         /* validate assumptions about pixbuf. */
1631         g_return_val_if_fail (buf_src, NULL);
1632         g_return_val_if_fail (bits_per_sample == 8, NULL);
1633         g_return_val_if_fail (channels == 4, NULL);
1634         g_return_val_if_fail (has_alpha, NULL);
1635         g_return_val_if_fail (width > 0, NULL);
1636         g_return_val_if_fail (height > 0, NULL);
1637         g_return_val_if_fail (rowstride > 0, NULL);
1638
1639         /* Allocate a destination buffer */
1640         bytes = height * rowstride;
1641         gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1642         buf_dest = g_try_malloc (bytes);
1643         if (!buf_dest) {
1644                 return NULL;
1645         }
1646         gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1647
1648         /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1649         p_src  = buf_src;
1650         p_dest = buf_dest;
1651         for ( iy=0; iy < height; iy++ ) {
1652         
1653                 p_src  = buf_src + iy*rowstride;
1654                 p_dest = buf_dest + iy*rowstride;
1655
1656                 for ( ix=0; ix < width; ix++ ) {
1657
1658                         r = *p_src++;
1659                         g = *p_src++;
1660                         b = *p_src++;
1661                         a = *p_src++;
1662
1663                         alpha = a / 255.0;
1664                         beta  = 1.0 - alpha;
1665
1666                         *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1667                         *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1668                         *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1669
1670                 }
1671
1672         }
1673
1674         gl_debug (DEBUG_PRINT, "START");
1675
1676         return buf_dest;
1677 }
1678 #endif