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