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