]> git.sur5r.net Git - glabels/blob - glabels2/src/print.c
2003-12-30 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 "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         gl_debug (DEBUG_PRINT, "END");
386 }
387
388 /*---------------------------------------------------------------------------*/
389 /* PRIVATE.  new print info structure                                        */
390 /*---------------------------------------------------------------------------*/
391 static PrintInfo *
392 print_info_new (GnomePrintJob    *job,
393                 glLabel          *label)
394 {
395         PrintInfo            *pi = g_new0 (PrintInfo, 1);
396         glTemplate           *template;
397
398         gl_debug (DEBUG_PRINT, "START");
399
400         g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
401         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
402
403         template = gl_label_get_template (label);
404
405         g_return_val_if_fail (template, NULL);
406         g_return_val_if_fail (template->page_size, NULL);
407         g_return_val_if_fail (template->page_width > 0, NULL);
408         g_return_val_if_fail (template->page_height > 0, NULL);
409
410         pi->pc = gnome_print_job_get_context (job);
411         pi->config = gnome_print_job_get_config (job);
412
413         gl_debug (DEBUG_PRINT,
414                   "setting page size = \"%s\"", template->page_size);
415
416         gnome_print_config_set_length (pi->config,
417                                        GNOME_PRINT_KEY_PAPER_WIDTH,
418                                        template->page_width,
419                                        GNOME_PRINT_PS_UNIT);
420         gnome_print_config_set_length (pi->config,
421                                        GNOME_PRINT_KEY_PAPER_HEIGHT,
422                                        template->page_height,
423                                        GNOME_PRINT_PS_UNIT);
424
425         pi->page_width  = template->page_width;
426         pi->page_height = template->page_height;
427
428         pi->template = template;
429         pi->label_rotate_flag = gl_label_get_rotate_flag (label);
430
431         pi->sheet = 0;
432
433         gl_debug (DEBUG_PRINT, "END");
434
435         return pi;
436 }
437
438 /*---------------------------------------------------------------------------*/
439 /* PRIVATE.  free print info structure                                       */
440 /*---------------------------------------------------------------------------*/
441 static void
442 print_info_free (PrintInfo **pi)
443 {
444         gl_debug (DEBUG_PRINT, "START");
445
446         gl_template_free (&(*pi)->template);
447
448         gnome_print_context_close ((*pi)->pc);
449
450         g_free (*pi);
451         *pi = NULL;
452
453         gl_debug (DEBUG_PRINT, "END");
454 }
455
456 /*---------------------------------------------------------------------------*/
457 /* PRIVATE.  Begin a new page.                                               */
458 /*---------------------------------------------------------------------------*/
459 static void
460 print_page_begin (PrintInfo *pi)
461 {
462         gchar *str;
463
464         gl_debug (DEBUG_PRINT, "START");
465
466         pi->sheet++;
467
468         str = g_strdup_printf ("sheet%02d", pi->sheet);
469         gnome_print_beginpage (pi->pc, str);
470         g_free (str);
471
472         /* Translate and scale, so that our origin is at the upper left. */
473         gnome_print_translate (pi->pc, 0.0, pi->page_height);
474         gnome_print_scale (pi->pc, 1.0, -1.0);
475
476         gl_debug (DEBUG_PRINT, "END");
477 }
478
479 /*---------------------------------------------------------------------------*/
480 /* PRIVATE.  End a page.                                                     */
481 /*---------------------------------------------------------------------------*/
482 static void
483 print_page_end (PrintInfo *pi)
484 {
485         gl_debug (DEBUG_PRINT, "START");
486
487         gnome_print_showpage (pi->pc);
488
489         gl_debug (DEBUG_PRINT, "END");
490 }
491
492 /*---------------------------------------------------------------------------*/
493 /* PRIVATE.  Print crop tick marks.                                          */
494 /*---------------------------------------------------------------------------*/
495 static void
496 print_crop_marks (PrintInfo *pi)
497 {
498         gdouble           w, h, page_w, page_h;
499         GList            *p;
500         glTemplateLayout *layout;
501         gdouble           xmin, ymin, xmax, ymax, dx, dy;
502         gdouble           x1, y1, x2, y2, x3, y3, x4, y4;
503         gint              ix, iy, nx, ny;
504
505         gl_debug (DEBUG_PRINT, "START");
506
507         gl_template_get_label_size (pi->template, &w, &h);
508
509         page_w = pi->page_width;
510         page_h = pi->page_height;
511
512         gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
513         gnome_print_setopacity (pi->pc, 1.0);
514         gnome_print_setlinewidth (pi->pc, 0.25);
515
516         for (p=pi->template->label.any.layouts; p != NULL; p=p->next) {
517
518                 layout = (glTemplateLayout *)p->data;
519
520                 xmin = layout->x0;
521                 ymin = layout->y0;
522                 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
523                 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
524
525                 dx = layout->dx;
526                 dy = layout->dy;
527
528                 nx = layout->nx;
529                 ny = layout->ny;
530
531                 for (ix=0; ix < nx; ix++) {
532
533                         x1 = xmin + ix*dx;
534                         x2 = x1 + w;
535
536                         y1 = MAX((ymin - TICK_OFFSET), 0.0);
537                         y2 = MAX((y1 - TICK_LENGTH), 0.0);
538
539                         y3 = MIN((ymax + TICK_OFFSET), page_h);
540                         y4 = MIN((y3 + TICK_LENGTH), page_h);
541
542                         gnome_print_moveto (pi->pc, x1, y1);
543                         gnome_print_lineto (pi->pc, x1, y2);
544                         gnome_print_stroke (pi->pc);
545
546                         gnome_print_moveto (pi->pc, x2, y1);
547                         gnome_print_lineto (pi->pc, x2, y2);
548                         gnome_print_stroke (pi->pc);
549
550                         gnome_print_moveto (pi->pc, x1, y3);
551                         gnome_print_lineto (pi->pc, x1, y4);
552                         gnome_print_stroke (pi->pc);
553
554                         gnome_print_moveto (pi->pc, x2, y3);
555                         gnome_print_lineto (pi->pc, x2, y4);
556                         gnome_print_stroke (pi->pc);
557
558                 }
559
560                 for (iy=0; iy < ny; iy++) {
561
562                         y1 = ymin + iy*dy;
563                         y2 = y1 + h;
564
565                         x1 = MAX((xmin - TICK_OFFSET), 0.0);
566                         x2 = MAX((x1 - TICK_LENGTH), 0.0);
567
568                         x3 = MIN((xmax + TICK_OFFSET), page_w);
569                         x4 = MIN((x3 + TICK_LENGTH), page_w);
570
571                         gnome_print_moveto (pi->pc, x1, y1);
572                         gnome_print_lineto (pi->pc, x2, y1);
573                         gnome_print_stroke (pi->pc);
574
575                         gnome_print_moveto (pi->pc, x1, y2);
576                         gnome_print_lineto (pi->pc, x2, y2);
577                         gnome_print_stroke (pi->pc);
578
579                         gnome_print_moveto (pi->pc, x3, y1);
580                         gnome_print_lineto (pi->pc, x4, y1);
581                         gnome_print_stroke (pi->pc);
582
583                         gnome_print_moveto (pi->pc, x3, y2);
584                         gnome_print_lineto (pi->pc, x4, y2);
585                         gnome_print_stroke (pi->pc);
586
587                 }
588
589         }
590
591         gl_debug (DEBUG_PRINT, "END");
592 }
593
594 /*---------------------------------------------------------------------------*/
595 /* PRIVATE.  Print i'th label.                                               */
596 /*---------------------------------------------------------------------------*/
597 static void
598 print_label (PrintInfo     *pi,
599              glLabel       *label,
600              gdouble        x,
601              gdouble        y,
602              glMergeRecord *record,
603              gboolean       outline_flag,
604              gboolean       reverse_flag)
605 {
606         gdouble width, height;
607         glTemplate *template;
608
609         gl_debug (DEBUG_PRINT, "START");
610
611         template = gl_label_get_template (label);
612
613         gl_label_get_size (label, &width, &height);
614
615         gnome_print_gsave (pi->pc);
616
617         /* Transform coordinate system to be relative to upper corner */
618         /* of the current label */
619         gnome_print_translate (pi->pc, x, y);
620         if (gl_label_get_rotate_flag (label)) {
621                 gl_debug (DEBUG_PRINT, "Rotate flag set");
622                 gnome_print_rotate (pi->pc, -90.0);
623                 gnome_print_translate (pi->pc, -width, 0.0);
624         }
625         if ( reverse_flag ) {
626                 gnome_print_translate (pi->pc, width, 0.0);
627                 gnome_print_scale (pi->pc, -1.0, 1.0);
628         }
629
630         clip_to_outline (pi, label);
631         draw_label (pi, label, record);
632         if (outline_flag) {
633                 draw_outline (pi, label);
634         }
635         clip_punchouts (pi, label);
636
637         gnome_print_grestore (pi->pc);
638
639         gl_template_free (&template);
640
641         gl_debug (DEBUG_PRINT, "END");
642 }
643
644 /*---------------------------------------------------------------------------*/
645 /* PRIVATE.  Draw label.                                                     */
646 /*---------------------------------------------------------------------------*/
647 static void
648 draw_label (PrintInfo     *pi,
649             glLabel       *label,
650             glMergeRecord *record)
651 {
652         GList *p_obj;
653         glLabelObject *object;
654
655         gl_debug (DEBUG_PRINT, "START");
656
657         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
658                 object = (glLabelObject *) p_obj->data;
659
660                 draw_object (pi, object, record);
661         }
662
663         gl_debug (DEBUG_PRINT, "END");
664 }
665
666 /*---------------------------------------------------------------------------*/
667 /* PRIVATE.  Draw object.                                                    */
668 /*---------------------------------------------------------------------------*/
669 static void
670 draw_object (PrintInfo     *pi,
671              glLabelObject *object,
672              glMergeRecord *record)
673 {
674         gdouble x0, y0;
675         gdouble affine[6];
676
677         gl_debug (DEBUG_PRINT, "START");
678
679         gl_label_object_get_position (object, &x0, &y0);
680         gl_label_object_get_affine (object, affine);
681
682         gnome_print_gsave (pi->pc);
683
684         gnome_print_translate (pi->pc, x0, y0);
685         gnome_print_concat (pi->pc, affine);
686
687         if (GL_IS_LABEL_TEXT(object)) {
688                 draw_text_object (pi, GL_LABEL_TEXT(object), record);
689         } else if (GL_IS_LABEL_BOX(object)) {
690                 draw_box_object (pi, GL_LABEL_BOX(object));
691         } else if (GL_IS_LABEL_LINE(object)) {
692                 draw_line_object (pi, GL_LABEL_LINE(object));
693         } else if (GL_IS_LABEL_ELLIPSE(object)) {
694                 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object));
695         } else if (GL_IS_LABEL_IMAGE(object)) {
696                 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
697         } else if (GL_IS_LABEL_BARCODE(object)) {
698                 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
699         }
700
701         gnome_print_grestore (pi->pc);
702
703         gl_debug (DEBUG_PRINT, "END");
704 }
705
706 /*---------------------------------------------------------------------------*/
707 /* PRIVATE.  Draw text object.                                               */
708 /*---------------------------------------------------------------------------*/
709 static void
710 draw_text_object (PrintInfo     *pi,
711                   glLabelText   *object,
712                   glMergeRecord *record)
713 {
714         GnomeFont *font;
715         gchar **line;
716         gint i;
717         gdouble x_offset, y_offset, w, object_w, object_h;
718         gchar *text;
719         GList *lines;
720         gchar *font_family;
721         gdouble font_size;
722         GnomeFontWeight font_weight;
723         gboolean font_italic_flag;
724         guint color;
725         GtkJustification just;
726         GnomeGlyphList *glyphlist;
727         ArtDRect bbox;
728         gdouble affine[6];
729
730
731         gl_debug (DEBUG_PRINT, "START");
732
733         gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
734         lines = gl_label_text_get_lines (object);
735         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
736         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
737         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
738         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
739         color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
740         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
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_object_get_line_width (GL_LABEL_OBJECT(object));
819         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
820         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(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_object_get_line_width (GL_LABEL_OBJECT(object));
859         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(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_object_get_line_width (GL_LABEL_OBJECT(object));
889         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
890         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(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);
996         color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
997         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
998
999         text = gl_text_node_expand (text_node, record);
1000         gbc = gl_barcode_new (style, text_flag, checksum_flag, w, h, text);
1001         g_free (text);
1002         gl_text_node_free (&text_node);
1003
1004         if (gbc == NULL) {
1005
1006                 font = gnome_font_find_closest_from_weight_slant (
1007                                                GL_BARCODE_FONT_FAMILY,
1008                                                GL_BARCODE_FONT_WEIGHT,
1009                                                FALSE, 12.0);
1010                 gnome_print_setfont (pi->pc, font);
1011
1012                 gnome_print_setrgbcolor (pi->pc,
1013                                          GL_COLOR_F_RED (color),
1014                                          GL_COLOR_F_GREEN (color),
1015                                          GL_COLOR_F_BLUE (color));
1016                 gnome_print_setopacity (pi->pc,
1017                                         GL_COLOR_F_ALPHA (color));
1018
1019                 y_offset = 12.0 - gnome_font_get_descender (font);
1020                 gnome_print_moveto (pi->pc, 0.0, y_offset);
1021
1022                 gnome_print_gsave (pi->pc);
1023                 gnome_print_scale (pi->pc, 1.0, -1.0);
1024                 gnome_print_show (pi->pc, _("Invalid barcode"));
1025                 gnome_print_grestore (pi->pc);
1026
1027         } else {
1028
1029                 for (li = gbc->lines; li != NULL; li = li->next) {
1030                         line = (glBarcodeLine *) li->data;
1031
1032                         gnome_print_moveto (pi->pc, line->x, line->y);
1033                         gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1034                         gnome_print_setrgbcolor (pi->pc,
1035                                                  GL_COLOR_F_RED (color),
1036                                                  GL_COLOR_F_GREEN (color),
1037                                                  GL_COLOR_F_BLUE (color));
1038                         gnome_print_setopacity (pi->pc,
1039                                                 GL_COLOR_F_ALPHA (color));
1040                         gnome_print_setlinewidth (pi->pc, line->width);
1041                         gnome_print_stroke (pi->pc);
1042                 }
1043
1044                 for (li = gbc->chars; li != NULL; li = li->next) {
1045                         bchar = (glBarcodeChar *) li->data;
1046
1047                         font = gnome_font_find_closest_from_weight_slant (
1048                                                        GL_BARCODE_FONT_FAMILY,
1049                                                        GL_BARCODE_FONT_WEIGHT,
1050                                                        FALSE, bchar->fsize);
1051                         gnome_print_setfont (pi->pc, font);
1052
1053                         gnome_print_setrgbcolor (pi->pc,
1054                                                  GL_COLOR_F_RED (color),
1055                                                  GL_COLOR_F_GREEN (color),
1056                                                  GL_COLOR_F_BLUE (color));
1057                         gnome_print_setopacity (pi->pc,
1058                                                 GL_COLOR_F_ALPHA (color));
1059
1060                         y_offset =
1061                             bchar->y + bchar->fsize -
1062                             gnome_font_get_descender (font);
1063                         gnome_print_moveto (pi->pc, bchar->x, y_offset);
1064
1065                         cstring = g_strdup_printf ("%c", bchar->c);
1066                         gnome_print_gsave (pi->pc);
1067                         gnome_print_scale (pi->pc, 1.0, -1.0);
1068                         gnome_print_show (pi->pc, cstring);
1069                         gnome_print_grestore (pi->pc);
1070                         g_free (cstring);
1071
1072                 }
1073
1074                 gl_barcode_free (&gbc);
1075
1076         }
1077
1078         gl_debug (DEBUG_PRINT, "END");
1079 }
1080
1081 /*---------------------------------------------------------------------------*/
1082 /* PRIVATE.  Draw outline.                                                   */
1083 /*---------------------------------------------------------------------------*/
1084 static void
1085 draw_outline (PrintInfo *pi,
1086               glLabel   *label)
1087 {
1088         gdouble w, h, r;
1089         gdouble r1, r2;
1090         glTemplate *template;
1091
1092         gl_debug (DEBUG_PRINT, "START");
1093
1094         template = gl_label_get_template (label);
1095
1096         gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
1097         gnome_print_setopacity (pi->pc, 1.0);
1098         gnome_print_setlinewidth (pi->pc, 0.25);
1099
1100         switch (template->label.style) {
1101
1102         case GL_TEMPLATE_STYLE_RECT:
1103                 gl_label_get_size (label, &w, &h);
1104                 r = template->label.rect.r;
1105                 if (r == 0.0) {
1106                         /* simple rectangle */
1107                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1108                 } else {
1109                         /* rectangle with rounded corners */
1110                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1111                                                        w, h, r);
1112                 }
1113                 gnome_print_stroke (pi->pc);
1114                 break;
1115
1116         case GL_TEMPLATE_STYLE_ROUND:
1117                 /* Round style */
1118                 r1 = template->label.round.r;
1119                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1120                 gnome_print_stroke (pi->pc);
1121                 break;
1122
1123         case GL_TEMPLATE_STYLE_CD:
1124                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1125                         /* CD style, round label w/ concentric round hole */
1126                         r1 = template->label.cd.r1;
1127                         r2 = template->label.cd.r2;
1128                         create_ellipse_path (pi->pc, r1, r1, r1, r1);
1129                         gnome_print_stroke (pi->pc);
1130                         create_ellipse_path (pi->pc, r1, r1, r2, r2);
1131                         gnome_print_stroke (pi->pc);
1132                 } else {
1133                         /* Business Card CD style, clipped round label w/ hole */
1134                         gl_label_get_size (label, &w, &h);
1135                         r1 = template->label.cd.r1;
1136                         r2 = template->label.cd.r2;
1137                         create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1138                         gnome_print_stroke (pi->pc);
1139                         create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1140                         gnome_print_stroke (pi->pc);
1141                 }
1142                 break;
1143
1144         default:
1145                 g_warning ("Unknown template label style");
1146                 break;
1147         }
1148
1149         gl_template_free (&template);
1150
1151         gl_debug (DEBUG_PRINT, "END");
1152 }
1153
1154 /*---------------------------------------------------------------------------*/
1155 /* PRIVATE.  Clip to outline.                                                */
1156 /*---------------------------------------------------------------------------*/
1157 static void
1158 clip_to_outline (PrintInfo *pi,
1159                  glLabel   *label)
1160 {
1161         gdouble w, h, r;
1162         gdouble r1;
1163         gdouble waste;
1164         glTemplate *template;
1165
1166         gl_debug (DEBUG_PRINT, "START");
1167
1168         template = gl_label_get_template (label);
1169
1170         switch (template->label.style) {
1171
1172         case GL_TEMPLATE_STYLE_RECT:
1173                 gl_label_get_size (label, &w, &h);
1174                 r = template->label.rect.r;
1175                 waste = template->label.rect.waste;
1176                 if (r == 0.0) {
1177                         /* simple rectangle */
1178                         create_rectangle_path (pi->pc,
1179                                                -waste, -waste, w+2*waste, h+2*waste);
1180                 } else {
1181                         /* rectangle with rounded corners */
1182                         create_rounded_rectangle_path (pi->pc, -waste, -waste,
1183                                                        w+2*waste, h+2*waste, r);
1184                 }
1185                 gnome_print_clip (pi->pc);
1186                 break;
1187
1188         case GL_TEMPLATE_STYLE_ROUND:
1189                 r1 = template->label.round.r;
1190                 waste = template->label.round.waste;
1191                 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1192                 gnome_print_clip (pi->pc);
1193                 break;
1194
1195         case GL_TEMPLATE_STYLE_CD:
1196                 waste = template->label.cd.waste;
1197                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1198                         /* CD style, round label w/ concentric round hole */
1199                         r1 = template->label.cd.r1;
1200                         create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1201                 } else {
1202                         /* Business Card CD style, clipped round label w/ hole */
1203                         gl_label_get_size (label, &w, &h);
1204                         r1 = template->label.cd.r1;
1205                         create_clipped_circle_path (pi->pc,
1206                                                     w/2, h/2,
1207                                                     w+2*waste, h+2*waste,
1208                                                     r1+waste);
1209                 }
1210                 gnome_print_clip (pi->pc);
1211                 break;
1212
1213         default:
1214                 g_warning ("Unknown template label style");
1215                 break;
1216         }
1217
1218         gl_template_free (&template);
1219
1220         gl_debug (DEBUG_PRINT, "END");
1221 }
1222
1223 /*---------------------------------------------------------------------------*/
1224 /* PRIVATE.  Clip punchouts.  (Save some ink by not printing in CD holes)    */
1225 /*                                                                           */
1226 /* Ideally this would be done in clip_to_outline, but I am not sure how to   */
1227 /* invert the region for gnome_print_clip, so instead, I will just draw      */
1228 /* a white circle on top of everything else.                                 */
1229 /*---------------------------------------------------------------------------*/
1230 static void
1231 clip_punchouts (PrintInfo *pi,
1232                 glLabel   *label)
1233 {
1234         gdouble w, h, r2;
1235         gdouble waste;
1236         glTemplate *template;
1237
1238         gl_debug (DEBUG_PRINT, "START");
1239
1240         template = gl_label_get_template (label);
1241
1242         switch (template->label.style) {
1243
1244         case GL_TEMPLATE_STYLE_RECT:
1245         case GL_TEMPLATE_STYLE_ROUND:
1246                 break;
1247
1248         case GL_TEMPLATE_STYLE_CD:
1249                 gl_label_get_size (label, &w, &h);
1250                 waste = template->label.cd.waste;
1251                 r2    = template->label.cd.r2;
1252                 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1253                 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1254                 gnome_print_setopacity (pi->pc, 1.0);
1255                 gnome_print_fill (pi->pc);
1256                 break;
1257
1258         default:
1259                 g_warning ("Unknown template label style");
1260                 break;
1261         }
1262
1263         gl_template_free (&template);
1264
1265         gl_debug (DEBUG_PRINT, "END");
1266 }
1267
1268 /*---------------------------------------------------------------------------*/
1269 /* PRIVATE.  Path creation utilities.                                        */
1270 /*---------------------------------------------------------------------------*/
1271 static void
1272 create_rectangle_path (GnomePrintContext *pc,
1273                        gdouble            x0,
1274                        gdouble            y0,
1275                        gdouble            w,
1276                        gdouble            h)
1277 {
1278         gl_debug (DEBUG_PRINT, "START");
1279
1280         gnome_print_newpath (pc);
1281         gnome_print_moveto (pc, x0, y0);
1282         gnome_print_lineto (pc, x0 + w, y0);
1283         gnome_print_lineto (pc, x0 + w, y0 + h);
1284         gnome_print_lineto (pc, x0, y0 + h);
1285         gnome_print_lineto (pc, x0, y0);
1286         gnome_print_closepath (pc);
1287
1288         gl_debug (DEBUG_PRINT, "END");
1289 }
1290
1291 static void
1292 create_ellipse_path (GnomePrintContext *pc,
1293                      gdouble            x0,
1294                      gdouble            y0,
1295                      gdouble            rx,
1296                      gdouble            ry)
1297 {
1298         gdouble x, y;
1299         gint i_theta;
1300
1301         gl_debug (DEBUG_PRINT, "START");
1302
1303         gnome_print_newpath (pc);
1304         gnome_print_moveto (pc, x0 + rx, y0);
1305         for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1306                 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1307                 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1308                 gnome_print_lineto (pc, x, y);
1309         }
1310         gnome_print_closepath (pc);
1311
1312         gl_debug (DEBUG_PRINT, "END");
1313 }
1314
1315 static void
1316 create_rounded_rectangle_path (GnomePrintContext *pc,
1317                                gdouble            x0,
1318                                gdouble            y0,
1319                                gdouble            w,
1320                                gdouble            h,
1321                                gdouble            r)
1322 {
1323         gdouble x, y;
1324         gint i_theta;
1325
1326         gl_debug (DEBUG_PRINT, "START");
1327
1328         gnome_print_newpath (pc);
1329
1330         gnome_print_moveto (pc, x0 + r, y0);
1331         for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1332                 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1333                 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1334                 gnome_print_lineto (pc, x, y);
1335         }
1336         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1337                 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1338                 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1339                 gnome_print_lineto (pc, x, y);
1340         }
1341         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1342                 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1343                 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1344                 gnome_print_lineto (pc, x, y);
1345         }
1346         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1347                 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1348                 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1349                 gnome_print_lineto (pc, x, y);
1350         }
1351         gnome_print_lineto (pc, x0 + r, y0);
1352
1353         gnome_print_closepath (pc);
1354
1355         gl_debug (DEBUG_PRINT, "END");
1356 }
1357
1358 static void
1359 create_clipped_circle_path (GnomePrintContext *pc,
1360                             gdouble            x0,
1361                             gdouble            y0,
1362                             gdouble            w,
1363                             gdouble            h,
1364                             gdouble            r)
1365 {
1366         gdouble x, y;
1367         gdouble theta1, theta2;
1368         gint    i_theta;
1369
1370         gl_debug (DEBUG_PRINT, "START");
1371
1372         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1373         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1374
1375         gnome_print_newpath (pc);
1376
1377         x = x0 + r * cos (theta1 * G_PI / 180.0);
1378         y = y0 + r * sin (theta1 * G_PI / 180.0);
1379         gnome_print_moveto (pc, x, y);
1380
1381         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1382                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1383                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1384                 gnome_print_lineto (pc, x, y);
1385         }
1386
1387         x = x0 + r * cos (theta2 * G_PI / 180.0);
1388         y = y0 + r * sin (theta2 * G_PI / 180.0);
1389         gnome_print_lineto (pc, x, y);
1390
1391         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1392                 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1393                 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1394                 gnome_print_lineto (pc, x, y);
1395         }
1396
1397         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1398                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1399                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1400                 gnome_print_lineto (pc, x, y);
1401         }
1402
1403         x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1404         y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1405         gnome_print_lineto (pc, x, y);
1406
1407         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1408                 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1409                 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1410                 gnome_print_lineto (pc, x, y);
1411         }
1412
1413         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1414                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1415                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1416                 gnome_print_lineto (pc, x, y);
1417         }
1418
1419         x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1420         y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1421         gnome_print_lineto (pc, x, y);
1422
1423         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1424                 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1425                 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1426                 gnome_print_lineto (pc, x, y);
1427         }
1428
1429         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1430                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1431                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1432                 gnome_print_lineto (pc, x, y);
1433         }
1434
1435         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1436                 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1437                 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1438                 gnome_print_lineto (pc, x, y);
1439         }
1440
1441         x = x0 + r * cos (theta1 * G_PI / 180.0);
1442         y = y0 + r * sin (theta1 * G_PI / 180.0);
1443         gnome_print_lineto (pc, x, y);
1444
1445         gnome_print_closepath (pc);
1446
1447         gl_debug (DEBUG_PRINT, "END");
1448 }
1449
1450 #ifndef NO_ALPHA_HACK
1451 /*---------------------------------------------------------------------------*/
1452 /* PRIVATE.  Extract a copy of rgba pixels, removing alpha by compositing    */
1453 /* with a white background.                                                  */
1454 /*                                                                           */
1455 /* This is currently needed due to the lousy job gnome-print does in         */
1456 /* rendering images with alpha channels to PS.  This sacrafices the ability  */
1457 /* to do compositing of images with other items in the background.           */
1458 /*---------------------------------------------------------------------------*/
1459 static guchar *
1460 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1461 {
1462         gint             bits_per_sample, channels;
1463         gboolean         has_alpha;
1464         gint             width, height, rowstride;
1465         gulong           bytes;
1466         guchar          *buf_src, *buf_dest;
1467         guchar          *p_src, *p_dest;
1468         gint             ix, iy;
1469         guchar           r, g, b, a;
1470         gdouble          alpha, beta;
1471
1472         gl_debug (DEBUG_PRINT, "START");
1473
1474         g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1475
1476         /* extract pixels and parameters from pixbuf. */
1477         buf_src         = gdk_pixbuf_get_pixels (pixbuf);
1478         bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1479         channels        = gdk_pixbuf_get_n_channels (pixbuf);
1480         has_alpha       = gdk_pixbuf_get_has_alpha (pixbuf);
1481         width           = gdk_pixbuf_get_width (pixbuf);
1482         height          = gdk_pixbuf_get_height (pixbuf);
1483         rowstride       = gdk_pixbuf_get_rowstride (pixbuf);
1484
1485         /* validate assumptions about pixbuf. */
1486         g_return_val_if_fail (buf_src, NULL);
1487         g_return_val_if_fail (bits_per_sample == 8, NULL);
1488         g_return_val_if_fail (channels == 4, NULL);
1489         g_return_val_if_fail (has_alpha, NULL);
1490         g_return_val_if_fail (width > 0, NULL);
1491         g_return_val_if_fail (height > 0, NULL);
1492         g_return_val_if_fail (rowstride > 0, NULL);
1493
1494         /* Allocate a destination buffer */
1495         bytes = height * rowstride;
1496         gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1497         buf_dest = g_try_malloc (bytes);
1498         if (!buf_dest) {
1499                 return NULL;
1500         }
1501         gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1502
1503         /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1504         p_src  = buf_src;
1505         p_dest = buf_dest;
1506         for ( iy=0; iy < height; iy++ ) {
1507         
1508                 p_src  = buf_src + iy*rowstride;
1509                 p_dest = buf_dest + iy*rowstride;
1510
1511                 for ( ix=0; ix < width; ix++ ) {
1512
1513                         r = *p_src++;
1514                         g = *p_src++;
1515                         b = *p_src++;
1516                         a = *p_src++;
1517
1518                         alpha = a / 255.0;
1519                         beta  = 1.0 - alpha;
1520
1521                         *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1522                         *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1523                         *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1524
1525                 }
1526
1527         }
1528
1529         gl_debug (DEBUG_PRINT, "START");
1530
1531         return buf_dest;
1532 }
1533 #endif