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