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