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