]> git.sur5r.net Git - glabels/blob - glabels2/src/print.c
2003-12-30 Wayne Schuller <k_wayne@linuxpower.org>
[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         gdouble text_line_spacing;
730
731
732         gl_debug (DEBUG_PRINT, "START");
733
734         gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
735         lines = gl_label_text_get_lines (object);
736         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
737         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
738         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
739         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
740         color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
741         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
742         text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
743
744         font = gnome_font_find_closest_from_weight_slant (
745                                        font_family,
746                                        font_weight,
747                                        font_italic_flag,
748                                        font_size);
749         gnome_print_setfont (pi->pc, font);
750
751         gnome_print_setrgbcolor (pi->pc,
752                                  GL_COLOR_F_RED (color),
753                                  GL_COLOR_F_GREEN (color),
754                                  GL_COLOR_F_BLUE (color));
755         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
756
757         text = gl_text_node_lines_expand (lines, record);
758         line = g_strsplit (text, "\n", -1);
759         g_free (text);
760
761         art_affine_identity (affine);
762
763         for (i = 0; line[i] != NULL; i++) {
764
765                 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
766                                                             0.0, 0.0,
767                                                             line[i]);
768
769                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
770                 w = bbox.x1;
771
772                 switch (just) {
773                 case GTK_JUSTIFY_LEFT:
774                         x_offset = GL_LABEL_TEXT_MARGIN;
775                         break;
776                 case GTK_JUSTIFY_CENTER:
777                         x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
778                         break;
779                 case GTK_JUSTIFY_RIGHT:
780                         x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
781                         break;
782                 default:
783                         x_offset = 0.0;
784                         break;  /* shouldn't happen */
785                 }
786
787                 /* Work out the y position to the BOTTOM of the first line */
788                 y_offset = GL_LABEL_TEXT_MARGIN +
789                            + gnome_font_get_descender (font)
790                            + (i + 1) * font_size * text_line_spacing;
791
792                 /* Remove any text line spacing from the first row. */
793                 y_offset -= font_size * (text_line_spacing - 1);
794
795
796                 gnome_print_moveto (pi->pc, x_offset, y_offset);
797
798                 gnome_print_gsave (pi->pc);
799                 gnome_print_scale (pi->pc, 1.0, -1.0);
800                 gnome_print_show (pi->pc, line[i]);
801                 gnome_print_grestore (pi->pc);
802         }
803
804         g_strfreev (line);
805
806         gl_text_node_lines_free (&lines);
807         g_free (font_family);
808
809         gl_debug (DEBUG_PRINT, "END");
810 }
811
812 /*---------------------------------------------------------------------------*/
813 /* PRIVATE.  Draw box object.                                                */
814 /*---------------------------------------------------------------------------*/
815 static void
816 draw_box_object (PrintInfo  *pi,
817                  glLabelBox *object)
818 {
819         gdouble w, h;
820         gdouble line_width;
821         guint line_color, fill_color;
822
823         gl_debug (DEBUG_PRINT, "START");
824
825         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
826         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
827         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
828         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
829
830         /* Paint fill color */
831         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
832         gnome_print_setrgbcolor (pi->pc,
833                                  GL_COLOR_F_RED (fill_color),
834                                  GL_COLOR_F_GREEN (fill_color),
835                                  GL_COLOR_F_BLUE (fill_color));
836         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
837         gnome_print_fill (pi->pc);
838
839         /* Draw outline */
840         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
841         gnome_print_setrgbcolor (pi->pc,
842                                  GL_COLOR_F_RED (line_color),
843                                  GL_COLOR_F_GREEN (line_color),
844                                  GL_COLOR_F_BLUE (line_color));
845         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
846         gnome_print_setlinewidth (pi->pc, line_width);
847         gnome_print_stroke (pi->pc);
848
849         gl_debug (DEBUG_PRINT, "END");
850 }
851
852 /*---------------------------------------------------------------------------*/
853 /* PRIVATE.  Draw line object.                                               */
854 /*---------------------------------------------------------------------------*/
855 static void
856 draw_line_object (PrintInfo   *pi,
857                   glLabelLine *object)
858 {
859         gdouble w, h;
860         gdouble line_width;
861         guint line_color;
862
863         gl_debug (DEBUG_PRINT, "START");
864
865         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
866         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
867         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
868
869         gnome_print_moveto (pi->pc, 0.0, 0.0);
870         gnome_print_lineto (pi->pc, w, h);
871         gnome_print_setrgbcolor (pi->pc,
872                                  GL_COLOR_F_RED (line_color),
873                                  GL_COLOR_F_GREEN (line_color),
874                                  GL_COLOR_F_BLUE (line_color));
875         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
876         gnome_print_setlinewidth (pi->pc, line_width);
877         gnome_print_stroke (pi->pc);
878
879         gl_debug (DEBUG_PRINT, "END");
880 }
881
882 /*---------------------------------------------------------------------------*/
883 /* PRIVATE.  Draw ellipse object.                                            */
884 /*---------------------------------------------------------------------------*/
885 static void
886 draw_ellipse_object (PrintInfo      *pi,
887                      glLabelEllipse *object)
888 {
889         gdouble x0, y0, rx, ry, w, h;
890         gdouble line_width;
891         guint line_color, fill_color;
892
893         gl_debug (DEBUG_PRINT, "START");
894
895         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
896         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
897         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
898         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
899
900         rx = w / 2.0;
901         ry = h / 2.0;
902         x0 = rx;
903         y0 = ry;
904
905         /* Paint fill color */
906         create_ellipse_path (pi->pc, x0, y0, rx, ry);
907         gnome_print_setrgbcolor (pi->pc,
908                                  GL_COLOR_F_RED (fill_color),
909                                  GL_COLOR_F_GREEN (fill_color),
910                                  GL_COLOR_F_BLUE (fill_color));
911         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
912         gnome_print_fill (pi->pc);
913
914         /* Draw outline */
915         create_ellipse_path (pi->pc, x0, y0, rx, ry);
916         gnome_print_setrgbcolor (pi->pc,
917                                  GL_COLOR_F_RED (line_color),
918                                  GL_COLOR_F_GREEN (line_color),
919                                  GL_COLOR_F_BLUE (line_color));
920         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
921         gnome_print_setlinewidth (pi->pc, line_width);
922         gnome_print_stroke (pi->pc);
923
924         gl_debug (DEBUG_PRINT, "END");
925 }
926
927 /*---------------------------------------------------------------------------*/
928 /* PRIVATE.  Draw image object.                                              */
929 /*---------------------------------------------------------------------------*/
930 static void
931 draw_image_object (PrintInfo     *pi,
932                    glLabelImage  *object,
933                    glMergeRecord *record)
934 {
935         gdouble w, h;
936         const GdkPixbuf *pixbuf;
937         guchar *image_data;
938         gint image_w, image_h, image_stride;
939         gboolean image_alpha_flag;
940         gint ret;
941
942         gl_debug (DEBUG_PRINT, "START");
943
944         gl_label_object_get_size     (GL_LABEL_OBJECT(object), &w, &h);
945
946         pixbuf = gl_label_image_get_pixbuf (object, record);
947         image_data = gdk_pixbuf_get_pixels (pixbuf);
948         image_w = gdk_pixbuf_get_width (pixbuf);
949         image_h = gdk_pixbuf_get_height (pixbuf);
950         image_stride = gdk_pixbuf_get_rowstride(pixbuf);
951         image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
952
953         gnome_print_gsave (pi->pc);
954         gnome_print_translate (pi->pc, 0.0, h);
955         gnome_print_scale (pi->pc, w, -h);
956         if (image_alpha_flag) {
957 #ifndef NO_ALPHA_HACK
958                 guchar *image_data2;
959
960                 image_data2 = get_pixels_as_rgb (pixbuf);
961                 ret = gnome_print_rgbimage (pi->pc, image_data2,
962                                             image_w, image_h, image_stride);
963                 g_free (image_data2);
964 #else
965                 ret = gnome_print_rgbaimage (pi->pc, image_data,
966                                             image_w, image_h, image_stride);
967 #endif
968         } else {
969                 ret = gnome_print_rgbimage (pi->pc, image_data,
970                                             image_w, image_h, image_stride);
971         }
972         gnome_print_grestore (pi->pc);
973
974         gl_debug (DEBUG_PRINT, "END");
975 }
976
977 /*---------------------------------------------------------------------------*/
978 /* PRIVATE.  Draw box object.                                                */
979 /*---------------------------------------------------------------------------*/
980 static void
981 draw_barcode_object (PrintInfo      *pi,
982                      glLabelBarcode *object,
983                      glMergeRecord  *record)
984 {
985         glBarcode *gbc;
986         glBarcodeLine *line;
987         glBarcodeChar *bchar;
988         GList *li;
989         gdouble y_offset;
990         GnomeFont *font;
991         gchar *text, *cstring;
992         glTextNode          *text_node;
993         glBarcodeStyle      style;
994         gboolean            text_flag;
995         gboolean            checksum_flag;
996         guint               color;
997         gdouble             w, h;
998
999         gl_debug (DEBUG_PRINT, "START");
1000
1001         text_node = gl_label_barcode_get_data (object);
1002         gl_label_barcode_get_props (object,
1003                                     &style, &text_flag, &checksum_flag);
1004         color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1005         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1006
1007         text = gl_text_node_expand (text_node, record);
1008         gbc = gl_barcode_new (style, text_flag, checksum_flag, w, h, text);
1009         g_free (text);
1010         gl_text_node_free (&text_node);
1011
1012         if (gbc == NULL) {
1013
1014                 font = gnome_font_find_closest_from_weight_slant (
1015                                                GL_BARCODE_FONT_FAMILY,
1016                                                GL_BARCODE_FONT_WEIGHT,
1017                                                FALSE, 12.0);
1018                 gnome_print_setfont (pi->pc, font);
1019
1020                 gnome_print_setrgbcolor (pi->pc,
1021                                          GL_COLOR_F_RED (color),
1022                                          GL_COLOR_F_GREEN (color),
1023                                          GL_COLOR_F_BLUE (color));
1024                 gnome_print_setopacity (pi->pc,
1025                                         GL_COLOR_F_ALPHA (color));
1026
1027                 y_offset = 12.0 - gnome_font_get_descender (font);
1028                 gnome_print_moveto (pi->pc, 0.0, y_offset);
1029
1030                 gnome_print_gsave (pi->pc);
1031                 gnome_print_scale (pi->pc, 1.0, -1.0);
1032                 gnome_print_show (pi->pc, _("Invalid barcode"));
1033                 gnome_print_grestore (pi->pc);
1034
1035         } else {
1036
1037                 for (li = gbc->lines; li != NULL; li = li->next) {
1038                         line = (glBarcodeLine *) li->data;
1039
1040                         gnome_print_moveto (pi->pc, line->x, line->y);
1041                         gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1042                         gnome_print_setrgbcolor (pi->pc,
1043                                                  GL_COLOR_F_RED (color),
1044                                                  GL_COLOR_F_GREEN (color),
1045                                                  GL_COLOR_F_BLUE (color));
1046                         gnome_print_setopacity (pi->pc,
1047                                                 GL_COLOR_F_ALPHA (color));
1048                         gnome_print_setlinewidth (pi->pc, line->width);
1049                         gnome_print_stroke (pi->pc);
1050                 }
1051
1052                 for (li = gbc->chars; li != NULL; li = li->next) {
1053                         bchar = (glBarcodeChar *) li->data;
1054
1055                         font = gnome_font_find_closest_from_weight_slant (
1056                                                        GL_BARCODE_FONT_FAMILY,
1057                                                        GL_BARCODE_FONT_WEIGHT,
1058                                                        FALSE, bchar->fsize);
1059                         gnome_print_setfont (pi->pc, font);
1060
1061                         gnome_print_setrgbcolor (pi->pc,
1062                                                  GL_COLOR_F_RED (color),
1063                                                  GL_COLOR_F_GREEN (color),
1064                                                  GL_COLOR_F_BLUE (color));
1065                         gnome_print_setopacity (pi->pc,
1066                                                 GL_COLOR_F_ALPHA (color));
1067
1068                         y_offset =
1069                             bchar->y + bchar->fsize -
1070                             gnome_font_get_descender (font);
1071                         gnome_print_moveto (pi->pc, bchar->x, y_offset);
1072
1073                         cstring = g_strdup_printf ("%c", bchar->c);
1074                         gnome_print_gsave (pi->pc);
1075                         gnome_print_scale (pi->pc, 1.0, -1.0);
1076                         gnome_print_show (pi->pc, cstring);
1077                         gnome_print_grestore (pi->pc);
1078                         g_free (cstring);
1079
1080                 }
1081
1082                 gl_barcode_free (&gbc);
1083
1084         }
1085
1086         gl_debug (DEBUG_PRINT, "END");
1087 }
1088
1089 /*---------------------------------------------------------------------------*/
1090 /* PRIVATE.  Draw outline.                                                   */
1091 /*---------------------------------------------------------------------------*/
1092 static void
1093 draw_outline (PrintInfo *pi,
1094               glLabel   *label)
1095 {
1096         gdouble w, h, r;
1097         gdouble r1, r2;
1098         glTemplate *template;
1099
1100         gl_debug (DEBUG_PRINT, "START");
1101
1102         template = gl_label_get_template (label);
1103
1104         gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
1105         gnome_print_setopacity (pi->pc, 1.0);
1106         gnome_print_setlinewidth (pi->pc, 0.25);
1107
1108         switch (template->label.style) {
1109
1110         case GL_TEMPLATE_STYLE_RECT:
1111                 gl_label_get_size (label, &w, &h);
1112                 r = template->label.rect.r;
1113                 if (r == 0.0) {
1114                         /* simple rectangle */
1115                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1116                 } else {
1117                         /* rectangle with rounded corners */
1118                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1119                                                        w, h, r);
1120                 }
1121                 gnome_print_stroke (pi->pc);
1122                 break;
1123
1124         case GL_TEMPLATE_STYLE_ROUND:
1125                 /* Round style */
1126                 r1 = template->label.round.r;
1127                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1128                 gnome_print_stroke (pi->pc);
1129                 break;
1130
1131         case GL_TEMPLATE_STYLE_CD:
1132                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1133                         /* CD style, round label w/ concentric round hole */
1134                         r1 = template->label.cd.r1;
1135                         r2 = template->label.cd.r2;
1136                         create_ellipse_path (pi->pc, r1, r1, r1, r1);
1137                         gnome_print_stroke (pi->pc);
1138                         create_ellipse_path (pi->pc, r1, r1, r2, r2);
1139                         gnome_print_stroke (pi->pc);
1140                 } else {
1141                         /* Business Card CD style, clipped round label w/ hole */
1142                         gl_label_get_size (label, &w, &h);
1143                         r1 = template->label.cd.r1;
1144                         r2 = template->label.cd.r2;
1145                         create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1146                         gnome_print_stroke (pi->pc);
1147                         create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1148                         gnome_print_stroke (pi->pc);
1149                 }
1150                 break;
1151
1152         default:
1153                 g_warning ("Unknown template label style");
1154                 break;
1155         }
1156
1157         gl_template_free (&template);
1158
1159         gl_debug (DEBUG_PRINT, "END");
1160 }
1161
1162 /*---------------------------------------------------------------------------*/
1163 /* PRIVATE.  Clip to outline.                                                */
1164 /*---------------------------------------------------------------------------*/
1165 static void
1166 clip_to_outline (PrintInfo *pi,
1167                  glLabel   *label)
1168 {
1169         gdouble w, h, r;
1170         gdouble r1;
1171         gdouble waste;
1172         glTemplate *template;
1173
1174         gl_debug (DEBUG_PRINT, "START");
1175
1176         template = gl_label_get_template (label);
1177
1178         switch (template->label.style) {
1179
1180         case GL_TEMPLATE_STYLE_RECT:
1181                 gl_label_get_size (label, &w, &h);
1182                 r = template->label.rect.r;
1183                 waste = template->label.rect.waste;
1184                 if (r == 0.0) {
1185                         /* simple rectangle */
1186                         create_rectangle_path (pi->pc,
1187                                                -waste, -waste, w+2*waste, h+2*waste);
1188                 } else {
1189                         /* rectangle with rounded corners */
1190                         create_rounded_rectangle_path (pi->pc, -waste, -waste,
1191                                                        w+2*waste, h+2*waste, r);
1192                 }
1193                 gnome_print_clip (pi->pc);
1194                 break;
1195
1196         case GL_TEMPLATE_STYLE_ROUND:
1197                 r1 = template->label.round.r;
1198                 waste = template->label.round.waste;
1199                 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1200                 gnome_print_clip (pi->pc);
1201                 break;
1202
1203         case GL_TEMPLATE_STYLE_CD:
1204                 waste = template->label.cd.waste;
1205                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1206                         /* CD style, round label w/ concentric round hole */
1207                         r1 = template->label.cd.r1;
1208                         create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1209                 } else {
1210                         /* Business Card CD style, clipped round label w/ hole */
1211                         gl_label_get_size (label, &w, &h);
1212                         r1 = template->label.cd.r1;
1213                         create_clipped_circle_path (pi->pc,
1214                                                     w/2, h/2,
1215                                                     w+2*waste, h+2*waste,
1216                                                     r1+waste);
1217                 }
1218                 gnome_print_clip (pi->pc);
1219                 break;
1220
1221         default:
1222                 g_warning ("Unknown template label style");
1223                 break;
1224         }
1225
1226         gl_template_free (&template);
1227
1228         gl_debug (DEBUG_PRINT, "END");
1229 }
1230
1231 /*---------------------------------------------------------------------------*/
1232 /* PRIVATE.  Clip punchouts.  (Save some ink by not printing in CD holes)    */
1233 /*                                                                           */
1234 /* Ideally this would be done in clip_to_outline, but I am not sure how to   */
1235 /* invert the region for gnome_print_clip, so instead, I will just draw      */
1236 /* a white circle on top of everything else.                                 */
1237 /*---------------------------------------------------------------------------*/
1238 static void
1239 clip_punchouts (PrintInfo *pi,
1240                 glLabel   *label)
1241 {
1242         gdouble w, h, r2;
1243         gdouble waste;
1244         glTemplate *template;
1245
1246         gl_debug (DEBUG_PRINT, "START");
1247
1248         template = gl_label_get_template (label);
1249
1250         switch (template->label.style) {
1251
1252         case GL_TEMPLATE_STYLE_RECT:
1253         case GL_TEMPLATE_STYLE_ROUND:
1254                 break;
1255
1256         case GL_TEMPLATE_STYLE_CD:
1257                 gl_label_get_size (label, &w, &h);
1258                 waste = template->label.cd.waste;
1259                 r2    = template->label.cd.r2;
1260                 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1261                 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1262                 gnome_print_setopacity (pi->pc, 1.0);
1263                 gnome_print_fill (pi->pc);
1264                 break;
1265
1266         default:
1267                 g_warning ("Unknown template label style");
1268                 break;
1269         }
1270
1271         gl_template_free (&template);
1272
1273         gl_debug (DEBUG_PRINT, "END");
1274 }
1275
1276 /*---------------------------------------------------------------------------*/
1277 /* PRIVATE.  Path creation utilities.                                        */
1278 /*---------------------------------------------------------------------------*/
1279 static void
1280 create_rectangle_path (GnomePrintContext *pc,
1281                        gdouble            x0,
1282                        gdouble            y0,
1283                        gdouble            w,
1284                        gdouble            h)
1285 {
1286         gl_debug (DEBUG_PRINT, "START");
1287
1288         gnome_print_newpath (pc);
1289         gnome_print_moveto (pc, x0, y0);
1290         gnome_print_lineto (pc, x0 + w, y0);
1291         gnome_print_lineto (pc, x0 + w, y0 + h);
1292         gnome_print_lineto (pc, x0, y0 + h);
1293         gnome_print_lineto (pc, x0, y0);
1294         gnome_print_closepath (pc);
1295
1296         gl_debug (DEBUG_PRINT, "END");
1297 }
1298
1299 static void
1300 create_ellipse_path (GnomePrintContext *pc,
1301                      gdouble            x0,
1302                      gdouble            y0,
1303                      gdouble            rx,
1304                      gdouble            ry)
1305 {
1306         gdouble x, y;
1307         gint i_theta;
1308
1309         gl_debug (DEBUG_PRINT, "START");
1310
1311         gnome_print_newpath (pc);
1312         gnome_print_moveto (pc, x0 + rx, y0);
1313         for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1314                 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1315                 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1316                 gnome_print_lineto (pc, x, y);
1317         }
1318         gnome_print_closepath (pc);
1319
1320         gl_debug (DEBUG_PRINT, "END");
1321 }
1322
1323 static void
1324 create_rounded_rectangle_path (GnomePrintContext *pc,
1325                                gdouble            x0,
1326                                gdouble            y0,
1327                                gdouble            w,
1328                                gdouble            h,
1329                                gdouble            r)
1330 {
1331         gdouble x, y;
1332         gint i_theta;
1333
1334         gl_debug (DEBUG_PRINT, "START");
1335
1336         gnome_print_newpath (pc);
1337
1338         gnome_print_moveto (pc, x0 + r, y0);
1339         for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1340                 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1341                 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1342                 gnome_print_lineto (pc, x, y);
1343         }
1344         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1345                 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1346                 y = y0 + (h - r) + r * sin (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 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1351                 y = y0 + (h - r) + r * cos (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 * cos (i_theta * G_PI / 180.0);
1356                 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1357                 gnome_print_lineto (pc, x, y);
1358         }
1359         gnome_print_lineto (pc, x0 + r, y0);
1360
1361         gnome_print_closepath (pc);
1362
1363         gl_debug (DEBUG_PRINT, "END");
1364 }
1365
1366 static void
1367 create_clipped_circle_path (GnomePrintContext *pc,
1368                             gdouble            x0,
1369                             gdouble            y0,
1370                             gdouble            w,
1371                             gdouble            h,
1372                             gdouble            r)
1373 {
1374         gdouble x, y;
1375         gdouble theta1, theta2;
1376         gint    i_theta;
1377
1378         gl_debug (DEBUG_PRINT, "START");
1379
1380         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1381         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1382
1383         gnome_print_newpath (pc);
1384
1385         x = x0 + r * cos (theta1 * G_PI / 180.0);
1386         y = y0 + r * sin (theta1 * G_PI / 180.0);
1387         gnome_print_moveto (pc, x, y);
1388
1389         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1390                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1391                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1392                 gnome_print_lineto (pc, x, y);
1393         }
1394
1395         x = x0 + r * cos (theta2 * G_PI / 180.0);
1396         y = y0 + r * sin (theta2 * G_PI / 180.0);
1397         gnome_print_lineto (pc, x, y);
1398
1399         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1400                 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1401                 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1402                 gnome_print_lineto (pc, x, y);
1403         }
1404
1405         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1406                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1407                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1408                 gnome_print_lineto (pc, x, y);
1409         }
1410
1411         x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1412         y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1413         gnome_print_lineto (pc, x, y);
1414
1415         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
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
1421         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1422                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1423                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1424                 gnome_print_lineto (pc, x, y);
1425         }
1426
1427         x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1428         y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1429         gnome_print_lineto (pc, x, y);
1430
1431         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1432                 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1433                 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1434                 gnome_print_lineto (pc, x, y);
1435         }
1436
1437         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1438                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1439                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1440                 gnome_print_lineto (pc, x, y);
1441         }
1442
1443         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1444                 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1445                 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1446                 gnome_print_lineto (pc, x, y);
1447         }
1448
1449         x = x0 + r * cos (theta1 * G_PI / 180.0);
1450         y = y0 + r * sin (theta1 * G_PI / 180.0);
1451         gnome_print_lineto (pc, x, y);
1452
1453         gnome_print_closepath (pc);
1454
1455         gl_debug (DEBUG_PRINT, "END");
1456 }
1457
1458 #ifndef NO_ALPHA_HACK
1459 /*---------------------------------------------------------------------------*/
1460 /* PRIVATE.  Extract a copy of rgba pixels, removing alpha by compositing    */
1461 /* with a white background.                                                  */
1462 /*                                                                           */
1463 /* This is currently needed due to the lousy job gnome-print does in         */
1464 /* rendering images with alpha channels to PS.  This sacrafices the ability  */
1465 /* to do compositing of images with other items in the background.           */
1466 /*---------------------------------------------------------------------------*/
1467 static guchar *
1468 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1469 {
1470         gint             bits_per_sample, channels;
1471         gboolean         has_alpha;
1472         gint             width, height, rowstride;
1473         gulong           bytes;
1474         guchar          *buf_src, *buf_dest;
1475         guchar          *p_src, *p_dest;
1476         gint             ix, iy;
1477         guchar           r, g, b, a;
1478         gdouble          alpha, beta;
1479
1480         gl_debug (DEBUG_PRINT, "START");
1481
1482         g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1483
1484         /* extract pixels and parameters from pixbuf. */
1485         buf_src         = gdk_pixbuf_get_pixels (pixbuf);
1486         bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1487         channels        = gdk_pixbuf_get_n_channels (pixbuf);
1488         has_alpha       = gdk_pixbuf_get_has_alpha (pixbuf);
1489         width           = gdk_pixbuf_get_width (pixbuf);
1490         height          = gdk_pixbuf_get_height (pixbuf);
1491         rowstride       = gdk_pixbuf_get_rowstride (pixbuf);
1492
1493         /* validate assumptions about pixbuf. */
1494         g_return_val_if_fail (buf_src, NULL);
1495         g_return_val_if_fail (bits_per_sample == 8, NULL);
1496         g_return_val_if_fail (channels == 4, NULL);
1497         g_return_val_if_fail (has_alpha, NULL);
1498         g_return_val_if_fail (width > 0, NULL);
1499         g_return_val_if_fail (height > 0, NULL);
1500         g_return_val_if_fail (rowstride > 0, NULL);
1501
1502         /* Allocate a destination buffer */
1503         bytes = height * rowstride;
1504         gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1505         buf_dest = g_try_malloc (bytes);
1506         if (!buf_dest) {
1507                 return NULL;
1508         }
1509         gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1510
1511         /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1512         p_src  = buf_src;
1513         p_dest = buf_dest;
1514         for ( iy=0; iy < height; iy++ ) {
1515         
1516                 p_src  = buf_src + iy*rowstride;
1517                 p_dest = buf_dest + iy*rowstride;
1518
1519                 for ( ix=0; ix < width; ix++ ) {
1520
1521                         r = *p_src++;
1522                         g = *p_src++;
1523                         b = *p_src++;
1524                         a = *p_src++;
1525
1526                         alpha = a / 255.0;
1527                         beta  = 1.0 - alpha;
1528
1529                         *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1530                         *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1531                         *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1532
1533                 }
1534
1535         }
1536
1537         gl_debug (DEBUG_PRINT, "START");
1538
1539         return buf_dest;
1540 }
1541 #endif