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