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