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