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