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