]> git.sur5r.net Git - glabels/blob - glabels2/src/print.c
- xml-template.c: use page size name as a fallback if id doesn't exist.
[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 /*=========================================================================*/
47 /* Private types.                                                          */
48 /*=========================================================================*/
49
50 typedef struct _PrintInfo {
51         /* gnome print context */
52         GnomePrintContext *pc;
53
54         /* gnome print configuration */
55         GnomePrintConfig *config;
56
57         /* gLabels Template */
58         glTemplate *template;
59         gboolean label_rotate_flag;
60
61         /* page size */
62         gdouble page_width;
63         gdouble page_height;
64
65         /* page counter */
66         gint sheet;
67 } PrintInfo;
68
69
70 /*=========================================================================*/
71 /* Private function prototypes.                                            */
72 /*=========================================================================*/
73 static PrintInfo *print_info_new              (GnomePrintJob    *job,
74                                                glLabel          *label);
75
76 static void       print_info_free             (PrintInfo       **pi);
77
78
79 static void       print_page_begin            (PrintInfo        *pi);
80
81 static void       print_page_end              (PrintInfo        *pi);
82
83 static void       print_label                 (PrintInfo        *pi,
84                                                glLabel          *label,
85                                                gdouble           x,
86                                                gdouble           y,
87                                                glMergeRecord    *record,
88                                                gboolean          outline_flag,
89                                                gboolean          reverse_flag);
90
91
92 static void       draw_label                  (PrintInfo        *pi,
93                                                glLabel          *label,
94                                                glMergeRecord    *record);
95
96
97 static void       draw_object                 (PrintInfo        *pi,
98                                                glLabelObject    *object,
99                                                glMergeRecord    *record);
100
101 static void       draw_text_object            (PrintInfo        *pi,
102                                                glLabelText      *object,
103                                                glMergeRecord    *record);
104
105 static void       draw_box_object             (PrintInfo        *pi,
106                                                glLabelBox       *object);
107
108 static void       draw_line_object            (PrintInfo        *pi,
109                                                glLabelLine      *object);
110
111 static void       draw_ellipse_object         (PrintInfo        *pi,
112                                                glLabelEllipse   *object);
113
114 static void       draw_image_object           (PrintInfo        *pi,
115                                                glLabelImage     *object,
116                                                glMergeRecord    *record);
117
118 static void       draw_barcode_object         (PrintInfo        *pi,
119                                                glLabelBarcode   *object,
120                                                glMergeRecord    *record);
121
122
123 static void       draw_outline                (PrintInfo        *pi,
124                                                glLabel          *label);
125
126 static void       clip_to_outline             (PrintInfo        *pi,
127                                                glLabel          *label);
128
129
130 static void       create_rectangle_path         (GnomePrintContext *pc,
131                                                  gdouble            x0,
132                                                  gdouble            y0,
133                                                  gdouble            w,
134                                                  gdouble            h);
135
136 static void       create_ellipse_path           (GnomePrintContext *pc,
137                                                  gdouble            x0,
138                                                  gdouble            y0,
139                                                  gdouble            rx,
140                                                  gdouble            ry);
141
142 static void       create_rounded_rectangle_path (GnomePrintContext *pc,
143                                                  gdouble            x0,
144                                                  gdouble            y0,
145                                                  gdouble            w,
146                                                  gdouble            h,
147                                                  gdouble            r);
148
149 static void       create_clipped_circle_path    (GnomePrintContext *pc,
150                                                  gdouble            x0,
151                                                  gdouble            y0,
152                                                  gdouble            w,
153                                                  gdouble            h,
154                                                  gdouble            r);
155
156 \f
157 /*****************************************************************************/
158 /* Simple (no merge data) print command.                                     */
159 /*****************************************************************************/
160 void
161 gl_print_simple (GnomePrintJob    *job,
162                  glLabel          *label,
163                  gint              n_sheets,
164                  gint              first,
165                  gint              last,
166                  gboolean          outline_flag,
167                  gboolean          reverse_flag)
168 {
169         PrintInfo *pi;
170         gint i_sheet, i_label;
171         glTemplateOrigin *origins;
172
173         gl_debug (DEBUG_PRINT, "START");
174
175         pi = print_info_new (job, label);
176
177         origins = gl_template_get_origins (pi->template);
178
179         for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
180
181                 print_page_begin (pi);
182
183                 for (i_label = first - 1; i_label < last; i_label++) {
184
185                         print_label (pi, label,
186                                      origins[i_label].x, origins[i_label].y,
187                                      NULL, outline_flag, reverse_flag);
188
189                 }
190
191                 print_page_end (pi);
192         }
193
194         g_free (origins);
195
196         print_info_free (&pi);
197
198         gl_debug (DEBUG_PRINT, "END");
199 }
200
201 /*****************************************************************************/
202 /* Merge print command (collated copies)                                     */
203 /*****************************************************************************/
204 void
205 gl_print_merge_collated (GnomePrintJob    *job,
206                          glLabel          *label,
207                          gint              n_copies,
208                          gint              first,
209                          gboolean          outline_flag,
210                          gboolean          reverse_flag)
211 {
212         glMerge                *merge;
213         const GList            *record_list;
214         PrintInfo              *pi;
215         gint                    i_sheet, i_label, n_labels_per_page, i_copy;
216         glMergeRecord          *record;
217         GList                  *p;
218         glTemplateOrigin       *origins;
219
220         gl_debug (DEBUG_PRINT, "START");
221
222         merge = gl_label_get_merge (label);
223         record_list = gl_merge_get_record_list (merge);
224
225         pi = print_info_new (job, label);
226
227         n_labels_per_page = gl_template_get_n_labels (pi->template);
228         origins = gl_template_get_origins (pi->template);
229
230         i_sheet = 0;
231         i_label = first - 1;
232
233         for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
234                 record = (glMergeRecord *)p->data;
235                         
236                 if ( record->select_flag ) {
237                         for (i_copy = 0; i_copy < n_copies; i_copy++) {
238
239                                 if ((i_label == 0) || (i_sheet == 0)) {
240                                         i_sheet++;
241                                         print_page_begin (pi);
242                                 }
243
244                                 print_label (pi, label,
245                                              origins[i_label].x,
246                                              origins[i_label].y,
247                                              record,
248                                              outline_flag, reverse_flag);
249
250                                 i_label = (i_label + 1) % n_labels_per_page;
251                                 if (i_label == 0) {
252                                         print_page_end (pi);
253                                 }
254                         }
255                 }
256         }
257
258         if (i_label != 0) {
259                 print_page_end (pi);
260         }
261
262         g_free (origins);
263
264         print_info_free (&pi);
265
266         gl_debug (DEBUG_PRINT, "END");
267 }
268
269 /*****************************************************************************/
270 /* Merge print command (uncollated copies)                                   */
271 /*****************************************************************************/
272 void
273 gl_print_merge_uncollated (GnomePrintJob    *job,
274                            glLabel          *label,
275                            gint              n_copies,
276                            gint              first,
277                            gboolean          outline_flag,
278                            gboolean          reverse_flag)
279 {
280         glMerge                *merge;
281         const GList            *record_list;
282         PrintInfo              *pi;
283         gint                    i_sheet, i_label, n_labels_per_page, i_copy;
284         glMergeRecord          *record;
285         GList                  *p;
286         glTemplateOrigin       *origins;
287
288         gl_debug (DEBUG_PRINT, "START");
289
290         merge = gl_label_get_merge (label);
291         record_list = gl_merge_get_record_list (merge);
292
293         pi = print_info_new (job, label);
294
295         n_labels_per_page = gl_template_get_n_labels (pi->template);
296         origins = gl_template_get_origins (pi->template);
297
298         i_sheet = 0;
299         i_label = first - 1;
300
301         for (i_copy = 0; i_copy < n_copies; i_copy++) {
302
303                 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
304                         record = (glMergeRecord *)p->data;
305                         
306                         if ( record->select_flag ) {
307
308
309                                 if ((i_label == 0) || (i_sheet == 0)) {
310                                         i_sheet++;
311                                         print_page_begin (pi);
312                                 }
313
314                                 print_label (pi, label,
315                                              origins[i_label].x,
316                                              origins[i_label].y,
317                                              record,
318                                              outline_flag, reverse_flag);
319
320                                 i_label = (i_label + 1) % n_labels_per_page;
321                                 if (i_label == 0) {
322                                         print_page_end (pi);
323                                 }
324                         }
325                 }
326
327         }
328         if (i_label != 0) {
329                 print_page_end (pi);
330         }
331
332         g_free (origins);
333
334         print_info_free (&pi);
335
336         gl_debug (DEBUG_PRINT, "END");
337 }
338
339 /*****************************************************************************/
340 /* Batch print.  Call appropriate function above.                            */
341 /*****************************************************************************/
342 void
343 gl_print_batch (GnomePrintJob    *job,
344                 glLabel          *label,
345                 gint              n_sheets,
346                 gint              n_copies,
347                 gboolean          outline_flag,
348                 gboolean          reverse_flag)
349 {
350         gint n_per_page;
351         glMerge *merge;
352         glTemplate *template;
353         
354         gl_debug (DEBUG_PRINT, "START");
355
356         merge = gl_label_get_merge (label);
357         template = gl_label_get_template (label);
358
359         if ( merge == NULL ) {
360                 n_per_page = gl_template_get_n_labels(template);
361
362                 gl_print_simple (job, label, n_sheets, 1, n_per_page,
363                                  outline_flag, reverse_flag);
364         } else {
365                 gl_print_merge_collated (job, label, n_copies, 1,
366                                          outline_flag, reverse_flag);
367         }
368         gl_template_free (&template);
369
370         g_object_unref (G_OBJECT(merge));
371
372         gl_debug (DEBUG_PRINT, "END");
373 }
374
375 /*---------------------------------------------------------------------------*/
376 /* PRIVATE.  new print info structure                                        */
377 /*---------------------------------------------------------------------------*/
378 static PrintInfo *
379 print_info_new (GnomePrintJob    *job,
380                 glLabel          *label)
381 {
382         PrintInfo            *pi = g_new0 (PrintInfo, 1);
383         glTemplate           *template;
384
385         gl_debug (DEBUG_PRINT, "START");
386
387         g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
388         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
389
390         template = gl_label_get_template (label);
391
392         g_return_val_if_fail (template, NULL);
393         g_return_val_if_fail (template->page_size, NULL);
394         g_return_val_if_fail (template->page_width > 0, NULL);
395         g_return_val_if_fail (template->page_height > 0, NULL);
396
397         pi->pc = gnome_print_job_get_context (job);
398         pi->config = gnome_print_job_get_config (job);
399
400         gl_debug (DEBUG_PRINT,
401                   "setting page size = \"%s\"", template->page_size);
402
403         gnome_print_config_set_length (pi->config,
404                                        GNOME_PRINT_KEY_PAPER_WIDTH,
405                                        template->page_width,
406                                        GNOME_PRINT_PS_UNIT);
407         gnome_print_config_set_length (pi->config,
408                                        GNOME_PRINT_KEY_PAPER_HEIGHT,
409                                        template->page_height,
410                                        GNOME_PRINT_PS_UNIT);
411
412         pi->page_width  = template->page_width;
413         pi->page_height = template->page_height;
414
415         pi->template = template;
416         pi->label_rotate_flag = gl_label_get_rotate_flag (label);
417
418         pi->sheet = 0;
419
420         gl_debug (DEBUG_PRINT, "END");
421
422         return pi;
423 }
424
425 /*---------------------------------------------------------------------------*/
426 /* PRIVATE.  free print info structure                                       */
427 /*---------------------------------------------------------------------------*/
428 static void
429 print_info_free (PrintInfo **pi)
430 {
431         gl_debug (DEBUG_PRINT, "START");
432
433         gl_template_free (&(*pi)->template);
434
435         gnome_print_context_close ((*pi)->pc);
436
437         g_free (*pi);
438         *pi = NULL;
439
440         gl_debug (DEBUG_PRINT, "END");
441 }
442
443 /*---------------------------------------------------------------------------*/
444 /* PRIVATE.  Begin a new page.                                               */
445 /*---------------------------------------------------------------------------*/
446 static void
447 print_page_begin (PrintInfo *pi)
448 {
449         gchar *str;
450
451         gl_debug (DEBUG_PRINT, "START");
452
453         pi->sheet++;
454
455         str = g_strdup_printf ("sheet%02d", pi->sheet);
456         gnome_print_beginpage (pi->pc, str);
457         g_free (str);
458
459         /* Translate and scale, so that our origin is at the upper left. */
460         gnome_print_translate (pi->pc, 0.0, pi->page_height);
461         gnome_print_scale (pi->pc, 1.0, -1.0);
462
463         gl_debug (DEBUG_PRINT, "END");
464 }
465
466 /*---------------------------------------------------------------------------*/
467 /* PRIVATE.  End a page.                                                     */
468 /*---------------------------------------------------------------------------*/
469 static void
470 print_page_end (PrintInfo *pi)
471 {
472         gl_debug (DEBUG_PRINT, "START");
473
474         gnome_print_showpage (pi->pc);
475
476         gl_debug (DEBUG_PRINT, "END");
477 }
478
479 /*---------------------------------------------------------------------------*/
480 /* PRIVATE.  Print i'th label.                                               */
481 /*---------------------------------------------------------------------------*/
482 static void
483 print_label (PrintInfo     *pi,
484              glLabel       *label,
485              gdouble        x,
486              gdouble        y,
487              glMergeRecord *record,
488              gboolean       outline_flag,
489              gboolean       reverse_flag)
490 {
491         gdouble width, height;
492         glTemplate *template;
493
494         gl_debug (DEBUG_PRINT, "START");
495
496         template = gl_label_get_template (label);
497
498         gl_label_get_size (label, &width, &height);
499
500         gnome_print_gsave (pi->pc);
501
502         /* Transform coordinate system to be relative to upper corner */
503         /* of the current label */
504         gnome_print_translate (pi->pc, x, y);
505         if (gl_label_get_rotate_flag (label)) {
506                 gl_debug (DEBUG_PRINT, "Rotate flag set");
507                 gnome_print_rotate (pi->pc, -90.0);
508                 gnome_print_translate (pi->pc, -width, 0.0);
509         }
510         if ( reverse_flag ) {
511                 gnome_print_translate (pi->pc, width, 0.0);
512                 gnome_print_scale (pi->pc, -1.0, 1.0);
513         }
514         if (outline_flag) {
515                 draw_outline (pi, label);
516         }
517         clip_to_outline (pi, label);
518         draw_label (pi, label, record);
519
520         gnome_print_grestore (pi->pc);
521
522         gl_template_free (&template);
523
524         gl_debug (DEBUG_PRINT, "END");
525 }
526
527 /*---------------------------------------------------------------------------*/
528 /* PRIVATE.  Draw label.                                                     */
529 /*---------------------------------------------------------------------------*/
530 static void
531 draw_label (PrintInfo     *pi,
532             glLabel       *label,
533             glMergeRecord *record)
534 {
535         GList *p_obj;
536         glLabelObject *object;
537
538         gl_debug (DEBUG_PRINT, "START");
539
540         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
541                 object = (glLabelObject *) p_obj->data;
542
543                 draw_object (pi, object, record);
544         }
545
546         gl_debug (DEBUG_PRINT, "END");
547 }
548
549 /*---------------------------------------------------------------------------*/
550 /* PRIVATE.  Draw object.                                                    */
551 /*---------------------------------------------------------------------------*/
552 static void
553 draw_object (PrintInfo     *pi,
554              glLabelObject *object,
555              glMergeRecord *record)
556 {
557         gdouble x0, y0;
558         gdouble affine[6];
559
560         gl_debug (DEBUG_PRINT, "START");
561
562         gl_label_object_get_position (object, &x0, &y0);
563         gl_label_object_get_affine (object, affine);
564
565         gnome_print_gsave (pi->pc);
566
567         gnome_print_translate (pi->pc, x0, y0);
568         gnome_print_concat (pi->pc, affine);
569
570         if (GL_IS_LABEL_TEXT(object)) {
571                 draw_text_object (pi, GL_LABEL_TEXT(object), record);
572         } else if (GL_IS_LABEL_BOX(object)) {
573                 draw_box_object (pi, GL_LABEL_BOX(object));
574         } else if (GL_IS_LABEL_LINE(object)) {
575                 draw_line_object (pi, GL_LABEL_LINE(object));
576         } else if (GL_IS_LABEL_ELLIPSE(object)) {
577                 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object));
578         } else if (GL_IS_LABEL_IMAGE(object)) {
579                 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
580         } else if (GL_IS_LABEL_BARCODE(object)) {
581                 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
582         }
583
584         gnome_print_grestore (pi->pc);
585
586         gl_debug (DEBUG_PRINT, "END");
587 }
588
589 /*---------------------------------------------------------------------------*/
590 /* PRIVATE.  Draw text object.                                               */
591 /*---------------------------------------------------------------------------*/
592 static void
593 draw_text_object (PrintInfo     *pi,
594                   glLabelText   *object,
595                   glMergeRecord *record)
596 {
597         GnomeFont *font;
598         gchar **line;
599         gint i;
600         gdouble x_offset, y_offset, w, object_w, object_h;
601         gchar *text;
602         GList *lines;
603         gchar *font_family;
604         gdouble font_size;
605         GnomeFontWeight font_weight;
606         gboolean font_italic_flag;
607         guint color;
608         GtkJustification just;
609         GnomeGlyphList *glyphlist;
610         ArtDRect bbox;
611         gdouble affine[6];
612
613
614         gl_debug (DEBUG_PRINT, "START");
615
616         gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
617         lines = gl_label_text_get_lines (object);
618         gl_label_text_get_props (object,
619                                  &font_family, &font_size, &font_weight,
620                                  &font_italic_flag,
621                                  &color, &just);
622
623         font = gnome_font_find_closest_from_weight_slant (
624                                        font_family,
625                                        font_weight,
626                                        font_italic_flag,
627                                        font_size);
628         gnome_print_setfont (pi->pc, font);
629
630         gnome_print_setrgbcolor (pi->pc,
631                                  GL_COLOR_F_RED (color),
632                                  GL_COLOR_F_GREEN (color),
633                                  GL_COLOR_F_BLUE (color));
634         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
635
636         text = gl_text_node_lines_expand (lines, record);
637         line = g_strsplit (text, "\n", -1);
638         g_free (text);
639
640         art_affine_identity (affine);
641
642         for (i = 0; line[i] != NULL; i++) {
643
644                 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
645                                                             0.0, 0.0,
646                                                             line[i]);
647
648                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
649                 w = bbox.x1;
650
651                 switch (just) {
652                 case GTK_JUSTIFY_LEFT:
653                         x_offset = GL_LABEL_TEXT_MARGIN;
654                         break;
655                 case GTK_JUSTIFY_CENTER:
656                         x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
657                         break;
658                 case GTK_JUSTIFY_RIGHT:
659                         x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
660                         break;
661                 default:
662                         x_offset = 0.0;
663                         break;  /* shouldn't happen */
664                 }
665
666                 y_offset = GL_LABEL_TEXT_MARGIN + (i + 1) * font_size
667                         + gnome_font_get_descender (font);
668
669                 gnome_print_moveto (pi->pc, x_offset, y_offset);
670
671                 gnome_print_gsave (pi->pc);
672                 gnome_print_scale (pi->pc, 1.0, -1.0);
673                 gnome_print_show (pi->pc, line[i]);
674                 gnome_print_grestore (pi->pc);
675         }
676
677         g_strfreev (line);
678
679         gl_text_node_lines_free (&lines);
680         g_free (font_family);
681
682         gl_debug (DEBUG_PRINT, "END");
683 }
684
685 /*---------------------------------------------------------------------------*/
686 /* PRIVATE.  Draw box object.                                                */
687 /*---------------------------------------------------------------------------*/
688 static void
689 draw_box_object (PrintInfo  *pi,
690                  glLabelBox *object)
691 {
692         gdouble w, h;
693         gdouble line_width;
694         guint line_color, fill_color;
695
696         gl_debug (DEBUG_PRINT, "START");
697
698         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
699         line_width = gl_label_box_get_line_width (object);
700         line_color = gl_label_box_get_line_color (object);
701         fill_color = gl_label_box_get_fill_color (object);
702
703         /* Paint fill color */
704         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
705         gnome_print_setrgbcolor (pi->pc,
706                                  GL_COLOR_F_RED (fill_color),
707                                  GL_COLOR_F_GREEN (fill_color),
708                                  GL_COLOR_F_BLUE (fill_color));
709         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
710         gnome_print_fill (pi->pc);
711
712         /* Draw outline */
713         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
714         gnome_print_setrgbcolor (pi->pc,
715                                  GL_COLOR_F_RED (line_color),
716                                  GL_COLOR_F_GREEN (line_color),
717                                  GL_COLOR_F_BLUE (line_color));
718         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
719         gnome_print_setlinewidth (pi->pc, line_width);
720         gnome_print_stroke (pi->pc);
721
722         gl_debug (DEBUG_PRINT, "END");
723 }
724
725 /*---------------------------------------------------------------------------*/
726 /* PRIVATE.  Draw line object.                                               */
727 /*---------------------------------------------------------------------------*/
728 static void
729 draw_line_object (PrintInfo   *pi,
730                   glLabelLine *object)
731 {
732         gdouble w, h;
733         gdouble line_width;
734         guint line_color;
735
736         gl_debug (DEBUG_PRINT, "START");
737
738         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
739         line_width = gl_label_line_get_line_width (object);
740         line_color = gl_label_line_get_line_color (object);
741
742         gnome_print_moveto (pi->pc, 0.0, 0.0);
743         gnome_print_lineto (pi->pc, w, h);
744         gnome_print_setrgbcolor (pi->pc,
745                                  GL_COLOR_F_RED (line_color),
746                                  GL_COLOR_F_GREEN (line_color),
747                                  GL_COLOR_F_BLUE (line_color));
748         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
749         gnome_print_setlinewidth (pi->pc, line_width);
750         gnome_print_stroke (pi->pc);
751
752         gl_debug (DEBUG_PRINT, "END");
753 }
754
755 /*---------------------------------------------------------------------------*/
756 /* PRIVATE.  Draw ellipse object.                                            */
757 /*---------------------------------------------------------------------------*/
758 static void
759 draw_ellipse_object (PrintInfo      *pi,
760                      glLabelEllipse *object)
761 {
762         gdouble x0, y0, rx, ry, w, h;
763         gdouble line_width;
764         guint line_color, fill_color;
765
766         gl_debug (DEBUG_PRINT, "START");
767
768         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
769         line_width = gl_label_ellipse_get_line_width (object);
770         line_color = gl_label_ellipse_get_line_color (object);
771         fill_color = gl_label_ellipse_get_fill_color (object);
772
773         rx = w / 2.0;
774         ry = h / 2.0;
775         x0 = rx;
776         y0 = ry;
777
778         /* Paint fill color */
779         create_ellipse_path (pi->pc, x0, y0, rx, ry);
780         gnome_print_setrgbcolor (pi->pc,
781                                  GL_COLOR_F_RED (fill_color),
782                                  GL_COLOR_F_GREEN (fill_color),
783                                  GL_COLOR_F_BLUE (fill_color));
784         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
785         gnome_print_fill (pi->pc);
786
787         /* Draw outline */
788         create_ellipse_path (pi->pc, x0, y0, rx, ry);
789         gnome_print_setrgbcolor (pi->pc,
790                                  GL_COLOR_F_RED (line_color),
791                                  GL_COLOR_F_GREEN (line_color),
792                                  GL_COLOR_F_BLUE (line_color));
793         gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
794         gnome_print_setlinewidth (pi->pc, line_width);
795         gnome_print_stroke (pi->pc);
796
797         gl_debug (DEBUG_PRINT, "END");
798 }
799
800 /*---------------------------------------------------------------------------*/
801 /* PRIVATE.  Draw image object.                                              */
802 /*---------------------------------------------------------------------------*/
803 static void
804 draw_image_object (PrintInfo     *pi,
805                    glLabelImage  *object,
806                    glMergeRecord *record)
807 {
808         gdouble w, h;
809         const GdkPixbuf *pixbuf;
810         guchar *image_data;
811         gint image_w, image_h, image_stride;
812         gboolean image_alpha_flag;
813         gint ret;
814
815         gl_debug (DEBUG_PRINT, "START");
816
817         gl_label_object_get_size     (GL_LABEL_OBJECT(object), &w, &h);
818
819         pixbuf = gl_label_image_get_pixbuf (object, record);
820         image_data = gdk_pixbuf_get_pixels (pixbuf);
821         image_w = gdk_pixbuf_get_width (pixbuf);
822         image_h = gdk_pixbuf_get_height (pixbuf);
823         image_stride = gdk_pixbuf_get_rowstride(pixbuf);
824         image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
825
826         gnome_print_gsave (pi->pc);
827         gnome_print_translate (pi->pc, 0.0, h);
828         gnome_print_scale (pi->pc, w, -h);
829         if (image_alpha_flag) {
830                 ret = gnome_print_rgbaimage (pi->pc, image_data,
831                                              image_w, image_h, image_stride);
832                 gl_debug (DEBUG_PRINT, "Ret a = %d", ret);
833         } else {
834                 ret = gnome_print_rgbimage (pi->pc, image_data,
835                                             image_w, image_h, image_stride);
836                 gl_debug (DEBUG_PRINT, "Ret = %d", ret);
837         }
838         gnome_print_grestore (pi->pc);
839
840         gl_debug (DEBUG_PRINT, "END");
841 }
842
843 /*---------------------------------------------------------------------------*/
844 /* PRIVATE.  Draw box object.                                                */
845 /*---------------------------------------------------------------------------*/
846 static void
847 draw_barcode_object (PrintInfo      *pi,
848                      glLabelBarcode *object,
849                      glMergeRecord  *record)
850 {
851         glBarcode *gbc;
852         glBarcodeLine *line;
853         glBarcodeChar *bchar;
854         GList *li;
855         gdouble y_offset;
856         GnomeFont *font;
857         gchar *text, *cstring;
858         glTextNode          *text_node;
859         glBarcodeStyle      style;
860         gboolean            text_flag;
861         gboolean            checksum_flag;
862         guint               color;
863         gdouble             w, h;
864
865         gl_debug (DEBUG_PRINT, "START");
866
867         text_node = gl_label_barcode_get_data (object);
868         gl_label_barcode_get_props (object,
869                                     &style, &text_flag, &checksum_flag, &color);
870         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
871
872         text = gl_text_node_expand (text_node, record);
873         gbc = gl_barcode_new (style, text_flag, checksum_flag, w, h, text);
874         g_free (text);
875         gl_text_node_free (&text_node);
876
877         if (gbc == NULL) {
878
879                 font = gnome_font_find_closest_from_weight_slant (
880                                                GL_BARCODE_FONT_FAMILY,
881                                                GL_BARCODE_FONT_WEIGHT,
882                                                FALSE, 12.0);
883                 gnome_print_setfont (pi->pc, font);
884
885                 gnome_print_setrgbcolor (pi->pc,
886                                          GL_COLOR_F_RED (color),
887                                          GL_COLOR_F_GREEN (color),
888                                          GL_COLOR_F_BLUE (color));
889                 gnome_print_setopacity (pi->pc,
890                                         GL_COLOR_F_ALPHA (color));
891
892                 y_offset = 12.0 - gnome_font_get_descender (font);
893                 gnome_print_moveto (pi->pc, 0.0, y_offset);
894
895                 gnome_print_gsave (pi->pc);
896                 gnome_print_scale (pi->pc, 1.0, -1.0);
897                 gnome_print_show (pi->pc, _("Invalid barcode"));
898                 gnome_print_grestore (pi->pc);
899
900         } else {
901
902                 for (li = gbc->lines; li != NULL; li = li->next) {
903                         line = (glBarcodeLine *) li->data;
904
905                         gnome_print_moveto (pi->pc, line->x, line->y);
906                         gnome_print_lineto (pi->pc, line->x, line->y + line->length);
907                         gnome_print_setrgbcolor (pi->pc,
908                                                  GL_COLOR_F_RED (color),
909                                                  GL_COLOR_F_GREEN (color),
910                                                  GL_COLOR_F_BLUE (color));
911                         gnome_print_setopacity (pi->pc,
912                                                 GL_COLOR_F_ALPHA (color));
913                         gnome_print_setlinewidth (pi->pc, line->width);
914                         gnome_print_stroke (pi->pc);
915                 }
916
917                 for (li = gbc->chars; li != NULL; li = li->next) {
918                         bchar = (glBarcodeChar *) li->data;
919
920                         font = gnome_font_find_closest_from_weight_slant (
921                                                        GL_BARCODE_FONT_FAMILY,
922                                                        GL_BARCODE_FONT_WEIGHT,
923                                                        FALSE, bchar->fsize);
924                         gnome_print_setfont (pi->pc, font);
925
926                         gnome_print_setrgbcolor (pi->pc,
927                                                  GL_COLOR_F_RED (color),
928                                                  GL_COLOR_F_GREEN (color),
929                                                  GL_COLOR_F_BLUE (color));
930                         gnome_print_setopacity (pi->pc,
931                                                 GL_COLOR_F_ALPHA (color));
932
933                         y_offset =
934                             bchar->y + bchar->fsize -
935                             gnome_font_get_descender (font);
936                         gnome_print_moveto (pi->pc, bchar->x, y_offset);
937
938                         cstring = g_strdup_printf ("%c", bchar->c);
939                         gnome_print_gsave (pi->pc);
940                         gnome_print_scale (pi->pc, 1.0, -1.0);
941                         gnome_print_show (pi->pc, cstring);
942                         gnome_print_grestore (pi->pc);
943                         g_free (cstring);
944
945                 }
946
947                 gl_barcode_free (&gbc);
948
949         }
950
951         gl_debug (DEBUG_PRINT, "END");
952 }
953
954 /*---------------------------------------------------------------------------*/
955 /* PRIVATE.  Draw outline.                                                   */
956 /*---------------------------------------------------------------------------*/
957 static void
958 draw_outline (PrintInfo *pi,
959               glLabel   *label)
960 {
961         gdouble w, h, r;
962         gdouble r1, r2;
963         glTemplate *template;
964
965         gl_debug (DEBUG_PRINT, "START");
966
967         template = gl_label_get_template (label);
968
969         gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
970         gnome_print_setopacity (pi->pc, 1.0);
971         gnome_print_setlinewidth (pi->pc, 0.25);
972
973         switch (template->label.style) {
974
975         case GL_TEMPLATE_STYLE_RECT:
976                 gl_label_get_size (label, &w, &h);
977                 r = template->label.rect.r;
978                 if (r == 0.0) {
979                         /* simple rectangle */
980                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
981                 } else {
982                         /* rectangle with rounded corners */
983                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
984                                                        w, h, r);
985                 }
986                 gnome_print_stroke (pi->pc);
987                 break;
988
989         case GL_TEMPLATE_STYLE_ROUND:
990                 /* Round style */
991                 r1 = template->label.round.r;
992                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
993                 gnome_print_stroke (pi->pc);
994                 break;
995
996         case GL_TEMPLATE_STYLE_CD:
997                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
998                         /* CD style, round label w/ concentric round hole */
999                         r1 = template->label.cd.r1;
1000                         r2 = template->label.cd.r2;
1001                         create_ellipse_path (pi->pc, r1, r1, r1, r1);
1002                         gnome_print_stroke (pi->pc);
1003                         create_ellipse_path (pi->pc, r1, r1, r2, r2);
1004                         gnome_print_stroke (pi->pc);
1005                 } else {
1006                         /* Business Card CD style, clipped round label w/ hole */
1007                         gl_label_get_size (label, &w, &h);
1008                         r1 = template->label.cd.r1;
1009                         r2 = template->label.cd.r2;
1010                         create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1011                         gnome_print_stroke (pi->pc);
1012                         create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1013                         gnome_print_stroke (pi->pc);
1014                 }
1015                 break;
1016
1017         default:
1018                 g_warning ("Unknown template label style");
1019                 break;
1020         }
1021
1022         gl_template_free (&template);
1023
1024         gl_debug (DEBUG_PRINT, "END");
1025 }
1026
1027 /*---------------------------------------------------------------------------*/
1028 /* PRIVATE.  Clip to outline.                                                */
1029 /*---------------------------------------------------------------------------*/
1030 static void
1031 clip_to_outline (PrintInfo *pi,
1032                  glLabel   *label)
1033 {
1034         gdouble w, h, r;
1035         gdouble r1;
1036         glTemplate *template;
1037
1038         gl_debug (DEBUG_PRINT, "START");
1039
1040         template = gl_label_get_template (label);
1041
1042         switch (template->label.style) {
1043
1044         case GL_TEMPLATE_STYLE_RECT:
1045                 gl_label_get_size (label, &w, &h);
1046                 r = template->label.rect.r;
1047                 if (r == 0.0) {
1048                         /* simple rectangle */
1049                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1050                 } else {
1051                         /* rectangle with rounded corners */
1052                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1053                                                        w, h, r);
1054                 }
1055                 gnome_print_clip (pi->pc);
1056                 break;
1057
1058         case GL_TEMPLATE_STYLE_ROUND:
1059                 r1 = template->label.round.r;
1060                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1061                 gnome_print_clip (pi->pc);
1062                 break;
1063
1064         case GL_TEMPLATE_STYLE_CD:
1065                 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1066                         /* CD style, round label w/ concentric round hole */
1067                         r1 = template->label.cd.r1;
1068                         create_ellipse_path (pi->pc, r1, r1, r1, r1);
1069                         gnome_print_clip (pi->pc);
1070                 } else {
1071                         /* Business Card CD style, clipped round label w/ hole */
1072                         gl_label_get_size (label, &w, &h);
1073                         r1 = template->label.cd.r1;
1074                         create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1075                         gnome_print_clip (pi->pc);
1076                 }
1077                 break;
1078
1079         default:
1080                 g_warning ("Unknown template label style");
1081                 break;
1082         }
1083
1084         gl_template_free (&template);
1085
1086         gl_debug (DEBUG_PRINT, "END");
1087 }
1088
1089 /*---------------------------------------------------------------------------*/
1090 /* PRIVATE.  Path creation utilities.                                        */
1091 /*---------------------------------------------------------------------------*/
1092 static void
1093 create_rectangle_path (GnomePrintContext *pc,
1094                        gdouble            x0,
1095                        gdouble            y0,
1096                        gdouble            w,
1097                        gdouble            h)
1098 {
1099         gl_debug (DEBUG_PRINT, "START");
1100
1101         gnome_print_newpath (pc);
1102         gnome_print_moveto (pc, x0, y0);
1103         gnome_print_lineto (pc, x0 + w, y0);
1104         gnome_print_lineto (pc, x0 + w, y0 + h);
1105         gnome_print_lineto (pc, x0, y0 + h);
1106         gnome_print_lineto (pc, x0, y0);
1107         gnome_print_closepath (pc);
1108
1109         gl_debug (DEBUG_PRINT, "END");
1110 }
1111
1112 static void
1113 create_ellipse_path (GnomePrintContext *pc,
1114                      gdouble            x0,
1115                      gdouble            y0,
1116                      gdouble            rx,
1117                      gdouble            ry)
1118 {
1119         gdouble x, y;
1120         gint i_theta;
1121
1122         gl_debug (DEBUG_PRINT, "START");
1123
1124         gnome_print_newpath (pc);
1125         gnome_print_moveto (pc, x0 + rx, y0);
1126         for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1127                 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1128                 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1129                 gnome_print_lineto (pc, x, y);
1130         }
1131         gnome_print_closepath (pc);
1132
1133         gl_debug (DEBUG_PRINT, "END");
1134 }
1135
1136 static void
1137 create_rounded_rectangle_path (GnomePrintContext *pc,
1138                                gdouble            x0,
1139                                gdouble            y0,
1140                                gdouble            w,
1141                                gdouble            h,
1142                                gdouble            r)
1143 {
1144         gdouble x, y;
1145         gint i_theta;
1146
1147         gl_debug (DEBUG_PRINT, "START");
1148
1149         gnome_print_newpath (pc);
1150
1151         gnome_print_moveto (pc, x0 + r, y0);
1152         for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1153                 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1154                 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1155                 gnome_print_lineto (pc, x, y);
1156         }
1157         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1158                 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1159                 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1160                 gnome_print_lineto (pc, x, y);
1161         }
1162         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1163                 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1164                 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1165                 gnome_print_lineto (pc, x, y);
1166         }
1167         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1168                 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1169                 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1170                 gnome_print_lineto (pc, x, y);
1171         }
1172         gnome_print_lineto (pc, x0 + r, y0);
1173
1174         gnome_print_closepath (pc);
1175
1176         gl_debug (DEBUG_PRINT, "END");
1177 }
1178
1179 static void
1180 create_clipped_circle_path (GnomePrintContext *pc,
1181                             gdouble            x0,
1182                             gdouble            y0,
1183                             gdouble            w,
1184                             gdouble            h,
1185                             gdouble            r)
1186 {
1187         gdouble x, y;
1188         gdouble theta1, theta2;
1189         gint    i_theta;
1190
1191         gl_debug (DEBUG_PRINT, "START");
1192
1193         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1194         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1195
1196         gnome_print_newpath (pc);
1197
1198         x = x0 + r * cos (theta1 * G_PI / 180.0);
1199         y = y0 + r * sin (theta1 * G_PI / 180.0);
1200         gnome_print_moveto (pc, x, y);
1201
1202         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1203                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1204                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1205                 gnome_print_lineto (pc, x, y);
1206         }
1207
1208         x = x0 + r * cos (theta2 * G_PI / 180.0);
1209         y = y0 + r * sin (theta2 * G_PI / 180.0);
1210         gnome_print_lineto (pc, x, y);
1211
1212         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1213                 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1214                 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1215                 gnome_print_lineto (pc, x, y);
1216         }
1217
1218         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1219                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1220                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1221                 gnome_print_lineto (pc, x, y);
1222         }
1223
1224         x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1225         y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1226         gnome_print_lineto (pc, x, y);
1227
1228         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1229                 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1230                 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1231                 gnome_print_lineto (pc, x, y);
1232         }
1233
1234         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1235                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1236                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1237                 gnome_print_lineto (pc, x, y);
1238         }
1239
1240         x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1241         y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1242         gnome_print_lineto (pc, x, y);
1243
1244         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1245                 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1246                 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1247                 gnome_print_lineto (pc, x, y);
1248         }
1249
1250         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1251                 x = x0 + r * cos (i_theta * G_PI / 180.0);
1252                 y = y0 + r * sin (i_theta * G_PI / 180.0);
1253                 gnome_print_lineto (pc, x, y);
1254         }
1255
1256         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1257                 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1258                 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1259                 gnome_print_lineto (pc, x, y);
1260         }
1261
1262         x = x0 + r * cos (theta1 * G_PI / 180.0);
1263         y = y0 + r * sin (theta1 * G_PI / 180.0);
1264         gnome_print_lineto (pc, x, y);
1265
1266         gnome_print_closepath (pc);
1267
1268         gl_debug (DEBUG_PRINT, "END");
1269 }
1270