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