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