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