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