]> git.sur5r.net Git - glabels/blob - glabels1/src/print.c
2009-09-22 Jim Evins <evins@snaught.com>
[glabels] / glabels1 / 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 <libgnome/gnome-paper.h>
28 #include <libgnomeprint/gnome-printer.h>
29
30 #include "print.h"
31 #include "label.h"
32 #include "bc.h"
33 #include "template.h"
34 #include "hack.h"
35
36 #include "debug.h"
37
38 #define GL_PRINT_DEFAULT_PAPER "US-Letter"
39
40 #define RED(x)   ( (((x)>>24) & 0xff) / 255.0 )
41 #define GREEN(x) ( (((x)>>16) & 0xff) / 255.0 )
42 #define BLUE(x)  ( (((x)>>8)  & 0xff) / 255.0 )
43 #define ALPHA(x) ( ( (x)      & 0xff) / 255.0 )
44
45 /*===========================================*/
46 /* Private types.                            */
47 /*===========================================*/
48 typedef struct _PrintInfo {
49         /* gnome print context */
50         GnomePrintContext *pc;
51
52         /* gLabels Template */
53         glTemplate *template;
54         gboolean label_rotate_flag;
55
56 } PrintInfo;
57
58 /*===========================================*/
59 /* Private function prototypes.              */
60 /*===========================================*/
61 static PrintInfo *print_info_new (GnomePrintMaster * master, glLabel * label);
62 static void print_info_free (PrintInfo ** pi);
63
64 static void print_label (PrintInfo * pi, glLabel * label, gint i,
65                          glMergeRecord * record, gboolean outline_flag,
66                          gboolean reverse_flag);
67
68 static void draw_label (PrintInfo * pi, glLabel * label,
69                         glMergeRecord * record);
70
71 static void draw_text_object (PrintInfo * pi, glLabelObject * object,
72                               glMergeRecord * record);
73 static void draw_box_object (PrintInfo * pi, glLabelObject * object);
74 static void draw_line_object (PrintInfo * pi, glLabelObject * object);
75 static void draw_ellipse_object (PrintInfo * pi, glLabelObject * object);
76 static void draw_image_object (PrintInfo * pi, glLabelObject * object);
77 static void draw_barcode_object (PrintInfo * pi, glLabelObject * object,
78                                  glMergeRecord * record);
79
80 static void draw_outline (PrintInfo * pi, glLabel * label);
81 #ifdef CLIP_LABEL
82 static void clip_to_outline (PrintInfo * pi, glLabel * label);
83 #endif
84
85 static void create_rectangle_path (GnomePrintContext * pc,
86                                    gdouble x0, gdouble y0,
87                                    gdouble w, gdouble h);
88 static void create_ellipse_path (GnomePrintContext * pc,
89                                  gdouble x0, gdouble y0,
90                                  gdouble rx, gdouble ry);
91 static void create_rounded_rectangle_path (GnomePrintContext * pc,
92                                            gdouble x0, gdouble y0,
93                                            gdouble w, gdouble h, gdouble r);
94 \f
95 /*****************************************************************************/
96 /* Simple (no merge data) print command.                                     */
97 /*****************************************************************************/
98 void
99 gl_print_simple (GnomePrintMaster * master,
100                  glLabel * label,
101                  gint n_sheets,
102                  gint first,
103                  gint last,
104                  gboolean outline_flag,
105                  gboolean reverse_flag)
106 {
107         PrintInfo *pi;
108         gint i_sheet, i_label;
109         gchar *page_str = NULL;
110
111         pi = print_info_new (master, label);
112
113         for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
114
115                 page_str = g_strdup_printf ("sheet %d", i_sheet + 1);
116                 gnome_print_beginpage (pi->pc, page_str);
117                 g_free (page_str);
118
119                 for (i_label = first - 1; i_label < last; i_label++) {
120
121                         print_label (pi, label, i_label, NULL,
122                                      outline_flag, reverse_flag);
123
124                 }
125
126                 gnome_print_showpage (pi->pc);
127         }
128
129         print_info_free (&pi);
130 }
131
132 /*****************************************************************************/
133 /* Merge print command (collated copies)                                     */
134 /*****************************************************************************/
135 void
136 gl_print_merge_collated (GnomePrintMaster * master,
137                          glLabel * label,
138                          GList * record_list,
139                          gint n_copies,
140                          gint first,
141                          gboolean outline_flag,
142                          gboolean reverse_flag)
143 {
144         PrintInfo *pi;
145         gint i_sheet, i_label, n_labels_per_page, i_copy;
146         gchar *str = NULL;
147         glMergeRecord *record;
148         GList *p;
149
150         pi = print_info_new (master, label);
151
152         n_labels_per_page = (pi->template->nx) * (pi->template->ny);
153
154         i_sheet = 0;
155         i_label = first - 1;
156
157         for ( p=record_list; p!=NULL; p=p->next ) {
158                 record = (glMergeRecord *)p->data;
159                         
160                 if ( record->select_flag ) {
161                         for (i_copy = 0; i_copy < n_copies; i_copy++) {
162
163                                 if ((i_label == 0) || (i_sheet == 0)) {
164                                         str = g_strdup_printf ("sheet %d",
165                                                                ++i_sheet);
166                                         gnome_print_beginpage (pi->pc, str);
167                                         g_free (str);
168                                 }
169
170                                 print_label (pi, label, i_label, record,
171                                              outline_flag, reverse_flag);
172
173                                 i_label = (i_label + 1) % n_labels_per_page;
174                                 if (i_label == 0) {
175                                         gnome_print_showpage (pi->pc);
176                                 }
177                         }
178                 }
179         }
180
181         if (i_label != 0) {
182                 gnome_print_showpage (pi->pc);
183         }
184
185         print_info_free (&pi);
186 }
187
188 /*****************************************************************************/
189 /* Merge print command (uncollated copies)                                   */
190 /*****************************************************************************/
191 void
192 gl_print_merge_uncollated (GnomePrintMaster * master,
193                            glLabel * label,
194                            GList * record_list,
195                            gint n_copies,
196                            gint first,
197                            gboolean outline_flag,
198                            gboolean reverse_flag)
199 {
200         PrintInfo *pi;
201         gint i_sheet, i_label, n_labels_per_page, i_copy;
202         gchar *str = NULL;
203         glMergeRecord *record;
204         GList *p;
205
206         pi = print_info_new (master, label);
207
208         n_labels_per_page = (pi->template->nx) * (pi->template->ny);
209
210         i_sheet = 0;
211         i_label = first - 1;
212
213         for (i_copy = 0; i_copy < n_copies; i_copy++) {
214
215                 for ( p=record_list; p!=NULL; p=p->next ) {
216                         record = (glMergeRecord *)p->data;
217                         
218                         if ( record->select_flag ) {
219
220
221                                 if ((i_label == 0) || (i_sheet == 0)) {
222                                         str = g_strdup_printf ("sheet %d",
223                                                                ++i_sheet);
224                                         gnome_print_beginpage (pi->pc, str);
225                                         g_free (str);
226                                 }
227
228                                 print_label (pi, label, i_label, record,
229                                              outline_flag, reverse_flag);
230
231                                 i_label = (i_label + 1) % n_labels_per_page;
232                                 if (i_label == 0) {
233                                         gnome_print_showpage (pi->pc);
234                                 }
235                         }
236                 }
237
238         }
239         if (i_label != 0) {
240                 gnome_print_showpage (pi->pc);
241         }
242
243         print_info_free (&pi);
244 }
245
246 /*****************************************************************************/
247 /* Batch print.  Call appropriate function above.                            */
248 /*****************************************************************************/
249 void
250 gl_print_batch (GnomePrintMaster * master, glLabel * label,
251                 gint n_sheets, gint n_copies,
252                 gboolean outline_flag, gboolean reverse_flag)
253 {
254         gint n_per_page;
255         GList *record_list = NULL;
256
257         if ( label->merge_type == GL_MERGE_NONE ) {
258                 n_per_page = (label->template->nx)*(label->template->ny);
259
260                 gl_print_simple (master, label, n_sheets, 1, n_per_page,
261                                  outline_flag, reverse_flag);
262         } else {
263                 record_list = gl_merge_read_data (label->merge_type,
264                                                   label->merge_fields,
265                                                   label->merge_src);
266
267                 gl_print_merge_collated (master, label, record_list,
268                                          n_copies, 1,
269                                          outline_flag, reverse_flag);
270         }
271 }
272
273 /*---------------------------------------------------------------------------*/
274 /* PRIVATE.  new print info structure                                        */
275 /*---------------------------------------------------------------------------*/
276 static PrintInfo *
277 print_info_new (GnomePrintMaster * master,
278                 glLabel * label)
279 {
280         const GnomePaper *paper;
281         PrintInfo *pi = g_new0 (PrintInfo, 1);
282         glTemplate *template = label->template;
283
284         if (template == NULL) {
285                 WARN ("Undefined template \"%s\"", label->template_name);
286                 return NULL;
287         }
288
289         pi->pc = gnome_print_master_get_context (master);
290
291         if ((template != NULL) && (template->page_size != NULL)) {
292                 paper = gnome_paper_with_name (template->page_size);
293         } else {
294                 paper = gnome_paper_with_name (GL_PRINT_DEFAULT_PAPER);
295         }
296         gnome_print_master_set_paper (master, paper);
297
298         pi->template = template;
299         pi->label_rotate_flag = label->rotate_flag;
300
301         return pi;
302 }
303
304 /*---------------------------------------------------------------------------*/
305 /* PRIVATE.  free print info structure                                       */
306 /*---------------------------------------------------------------------------*/
307 static void
308 print_info_free (PrintInfo ** pi)
309 {
310         gnome_print_context_close ((*pi)->pc);
311
312         g_free (*pi);
313         *pi = NULL;
314 }
315
316 /*---------------------------------------------------------------------------*/
317 /* PRIVATE.  Print i'th label.                                               */
318 /*---------------------------------------------------------------------------*/
319 static void
320 print_label (PrintInfo * pi,
321              glLabel * label,
322              gint i_label,
323              glMergeRecord * record,
324              gboolean outline_flag,
325              gboolean reverse_flag)
326 {
327         gdouble a[6];
328         gint ix, iy;
329
330         ix = i_label % (pi->template->nx);
331         iy = ((pi->template->ny) - 1) - (i_label / (pi->template->nx));
332
333         gnome_print_gsave (pi->pc);
334
335         /* Transform coordinate system to be relative to upper corner */
336         /* of the current label */
337         gnome_print_translate (pi->pc,
338                                ix * (pi->template->dx) + pi->template->x0,
339                                iy * (pi->template->dy) + pi->template->y0);
340         if (!label->rotate_flag) {
341                 art_affine_scale (a, 1.0, -1.0);
342                 a[5] = label->height;
343                 gnome_print_concat (pi->pc, a);
344         } else {
345                 gnome_print_rotate (pi->pc, 90.0);
346                 gnome_print_scale (pi->pc, 1.0, -1.0);
347         }
348         if ( reverse_flag ) {
349                 gnome_print_translate (pi->pc, label->width, 0.0);
350                 art_affine_scale (a, -1.0, 1.0);
351                 gnome_print_concat (pi->pc, a);
352         }
353         if (outline_flag) {
354                 draw_outline (pi, label);
355         }
356 #ifdef CLIP_LABEL /* FIXME: this may be causing problems for some people. */
357         clip_to_outline (pi, label);
358 #endif
359         draw_label (pi, label, record);
360
361         gnome_print_grestore (pi->pc);
362
363 }
364
365 /*---------------------------------------------------------------------------*/
366 /* PRIVATE.  Draw label.                                                     */
367 /*---------------------------------------------------------------------------*/
368 static void
369 draw_label (PrintInfo * pi,
370             glLabel * label,
371             glMergeRecord * record)
372 {
373         GList *p_obj;
374         glLabelObject *object;
375
376         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
377                 object = (glLabelObject *) p_obj->data;
378
379                 if (object->type == GL_LABEL_OBJECT_TEXT) {
380                         draw_text_object (pi, object, record);
381                 } else if (object->type == GL_LABEL_OBJECT_BOX) {
382                         draw_box_object (pi, object);
383                 } else if (object->type == GL_LABEL_OBJECT_LINE) {
384                         draw_line_object (pi, object);
385                 } else if (object->type == GL_LABEL_OBJECT_ELLIPSE) {
386                         draw_ellipse_object (pi, object);
387                 } else if (object->type == GL_LABEL_OBJECT_IMAGE) {
388                         draw_image_object (pi, object);
389                 } else if (object->type == GL_LABEL_OBJECT_BARCODE) {
390                         draw_barcode_object (pi, object, record);
391                 }
392
393         }
394
395 }
396
397 /*---------------------------------------------------------------------------*/
398 /* PRIVATE.  Draw text object.                                               */
399 /*---------------------------------------------------------------------------*/
400 static void
401 draw_text_object (PrintInfo * pi,
402                   glLabelObject * object,
403                   glMergeRecord * record)
404 {
405         GnomeFont *font;
406         gchar **line;
407         gint i;
408         gdouble w;
409         gdouble x_offset, y_offset;
410         gdouble x, y;
411         gchar *text, *utf8_text;
412
413         font = gnome_font_new_closest (object->arg.text.font_family,
414                                        object->arg.text.font_weight,
415                                        object->arg.text.font_italic_flag,
416                                        object->arg.text.font_size);
417         gnome_print_setfont (pi->pc, font);
418
419         gnome_print_setrgbcolor (pi->pc,
420                                  RED (object->arg.text.color),
421                                  GREEN (object->arg.text.color),
422                                  BLUE (object->arg.text.color));
423         gnome_print_setopacity (pi->pc, ALPHA (object->arg.text.color));
424
425         text = gl_text_node_lines_expand (object->arg.text.lines, record);
426         line = g_strsplit (text, "\n", -1);
427         g_free (text);
428
429         for (i = 0; line[i] != NULL; i++) {
430
431                 utf8_text = gl_hack_text_to_utf8 (line[i]);
432
433                 w = gl_hack_get_width_string (font, line[i]);
434
435                 switch (object->arg.text.just) {
436                 case GTK_JUSTIFY_LEFT:
437                         x_offset = 0.0;
438                         break;
439                 case GTK_JUSTIFY_CENTER:
440                         x_offset = -w / 2.0;
441                         break;
442                 case GTK_JUSTIFY_RIGHT:
443                         x_offset = -w;
444                         break;
445                 default:
446                         x_offset = 0.0;
447                         break;  /* shouldn't happen */
448                 }
449
450                 y_offset = (i + 1) * object->arg.text.font_size
451                     - gnome_font_get_descender (font);
452
453                 x = object->x + x_offset;
454                 y = object->y + y_offset;
455                 gnome_print_moveto (pi->pc, x, y);
456
457                 gnome_print_gsave (pi->pc);
458                 gnome_print_scale (pi->pc, 1.0, -1.0);
459                 gnome_print_show (pi->pc, utf8_text);
460                 gnome_print_grestore (pi->pc);
461
462                 g_free (utf8_text);
463         }
464
465         g_strfreev (line);
466
467 }
468
469 /*---------------------------------------------------------------------------*/
470 /* PRIVATE.  Draw box object.                                                */
471 /*---------------------------------------------------------------------------*/
472 static void
473 draw_box_object (PrintInfo * pi,
474                  glLabelObject * object)
475 {
476         gdouble x, y, w, h;
477
478         x = object->x;
479         y = object->y;
480         w = object->arg.box.w;
481         h = object->arg.box.h;
482
483         /* Paint fill color */
484         create_rectangle_path (pi->pc, x, y, w, h);
485         gnome_print_setrgbcolor (pi->pc,
486                                  RED (object->arg.box.fill_color),
487                                  GREEN (object->arg.box.fill_color),
488                                  BLUE (object->arg.box.fill_color));
489         gnome_print_setopacity (pi->pc, ALPHA (object->arg.box.fill_color));
490         gnome_print_fill (pi->pc);
491
492         /* Draw outline */
493         create_rectangle_path (pi->pc, x, y, w, h);
494         gnome_print_setrgbcolor (pi->pc,
495                                  RED (object->arg.box.line_color),
496                                  GREEN (object->arg.box.line_color),
497                                  BLUE (object->arg.box.line_color));
498         gnome_print_setopacity (pi->pc, ALPHA (object->arg.box.line_color));
499         gnome_print_setlinewidth (pi->pc, object->arg.box.line_width);
500         gnome_print_stroke (pi->pc);
501 }
502
503 /*---------------------------------------------------------------------------*/
504 /* PRIVATE.  Draw line object.                                               */
505 /*---------------------------------------------------------------------------*/
506 static void
507 draw_line_object (PrintInfo * pi,
508                   glLabelObject * object)
509 {
510         gdouble x, y, dx, dy;
511
512         x = object->x;
513         y = object->y;
514         dx = object->arg.line.dx;
515         dy = object->arg.line.dy;
516
517         gnome_print_moveto (pi->pc, x, y);
518         gnome_print_lineto (pi->pc, x + dx, y + dy);
519         gnome_print_setrgbcolor (pi->pc,
520                                  RED (object->arg.line.line_color),
521                                  GREEN (object->arg.line.line_color),
522                                  BLUE (object->arg.line.line_color));
523         gnome_print_setopacity (pi->pc, ALPHA (object->arg.line.line_color));
524         gnome_print_setlinewidth (pi->pc, object->arg.line.line_width);
525         gnome_print_stroke (pi->pc);
526 }
527
528 /*---------------------------------------------------------------------------*/
529 /* PRIVATE.  Draw ellipse object.                                            */
530 /*---------------------------------------------------------------------------*/
531 static void
532 draw_ellipse_object (PrintInfo * pi,
533                      glLabelObject * object)
534 {
535         gdouble x0, y0, rx, ry;
536
537         rx = object->arg.ellipse.w / 2.0;
538         ry = object->arg.ellipse.h / 2.0;
539         x0 = object->x + rx;
540         y0 = object->y + ry;
541
542         /* Paint fill color */
543         create_ellipse_path (pi->pc, x0, y0, rx, ry);
544         gnome_print_setrgbcolor (pi->pc,
545                                  RED (object->arg.ellipse.fill_color),
546                                  GREEN (object->arg.ellipse.fill_color),
547                                  BLUE (object->arg.ellipse.fill_color));
548         gnome_print_setopacity (pi->pc, ALPHA (object->arg.ellipse.fill_color));
549         gnome_print_fill (pi->pc);
550
551         /* Draw outline */
552         create_ellipse_path (pi->pc, x0, y0, rx, ry);
553         gnome_print_setrgbcolor (pi->pc,
554                                  RED (object->arg.ellipse.line_color),
555                                  GREEN (object->arg.ellipse.line_color),
556                                  BLUE (object->arg.ellipse.line_color));
557         gnome_print_setopacity (pi->pc, ALPHA (object->arg.ellipse.line_color));
558         gnome_print_setlinewidth (pi->pc, object->arg.ellipse.line_width);
559         gnome_print_stroke (pi->pc);
560 }
561
562 /*---------------------------------------------------------------------------*/
563 /* PRIVATE.  Draw image object.                                              */
564 /*---------------------------------------------------------------------------*/
565 static void
566 draw_image_object (PrintInfo * pi,
567                    glLabelObject * object)
568 {
569         gdouble x, y, w, h;
570         GdkPixbuf *pixbuf;
571
572         x = object->x;
573         y = object->y;
574         w = object->arg.image.w;
575         h = object->arg.image.h;
576
577         pixbuf = object->arg.image.image;
578
579         gnome_print_gsave (pi->pc);
580         gnome_print_translate (pi->pc, x, y + h);
581         gnome_print_scale (pi->pc, w, -h);
582         gnome_print_pixbuf (pi->pc, pixbuf);
583         gnome_print_grestore (pi->pc);
584
585 }
586
587 /*---------------------------------------------------------------------------*/
588 /* PRIVATE.  Draw box object.                                                */
589 /*---------------------------------------------------------------------------*/
590 static void
591 draw_barcode_object (PrintInfo * pi,
592                      glLabelObject * object,
593                      glMergeRecord * record)
594 {
595         glBarcode *gbc;
596         glBarcodeLine *line;
597         glBarcodeChar *bchar;
598         GList *li;
599         gdouble x, y, y_offset;
600         GnomeFont *font;
601         gchar *text, *cstring;
602
603         x = object->x;
604         y = object->y;
605
606         text = gl_text_node_expand (object->arg.barcode.text_node, record);
607         gbc = gl_barcode (object->arg.barcode.style,
608                           object->arg.barcode.text_flag,
609                           object->arg.barcode.scale, text);
610         g_free (text);
611
612         if (gbc == NULL) {
613
614                 font = gnome_font_new_closest (GL_BARCODE_FONT_FAMILY,
615                                                GL_BARCODE_FONT_WEIGHT,
616                                                FALSE, 12.0);
617                 gnome_print_setfont (pi->pc, font);
618
619                 gnome_print_setrgbcolor (pi->pc,
620                                          RED (object->arg.barcode.color),
621                                          GREEN (object->arg.barcode.color),
622                                          BLUE (object->arg.barcode.color));
623                 gnome_print_setopacity (pi->pc,
624                                         ALPHA (object->arg.barcode.color));
625
626                 y_offset = 12.0 - gnome_font_get_descender (font);
627                 gnome_print_moveto (pi->pc, x, y + y_offset);
628
629                 gnome_print_gsave (pi->pc);
630                 gnome_print_scale (pi->pc, 1.0, -1.0);
631                 gnome_print_show (pi->pc, _("Invalid barcode"));
632                 gnome_print_grestore (pi->pc);
633
634         } else {
635
636                 for (li = gbc->lines; li != NULL; li = li->next) {
637                         line = (glBarcodeLine *) li->data;
638
639                         gnome_print_moveto (pi->pc, x + line->x, y + line->y);
640                         gnome_print_lineto (pi->pc, x + line->x,
641                                             y + line->y + line->length);
642                         gnome_print_setrgbcolor (pi->pc,
643                                                  RED (object->arg.barcode.
644                                                       color),
645                                                  GREEN (object->arg.barcode.
646                                                         color),
647                                                  BLUE (object->arg.barcode.
648                                                        color));
649                         gnome_print_setopacity (pi->pc,
650                                                 ALPHA (object->arg.barcode.
651                                                        color));
652                         gnome_print_setlinewidth (pi->pc, line->width);
653                         gnome_print_stroke (pi->pc);
654                 }
655
656                 for (li = gbc->chars; li != NULL; li = li->next) {
657                         bchar = (glBarcodeChar *) li->data;
658
659                         font = gnome_font_new_closest (GL_BARCODE_FONT_FAMILY,
660                                                        GL_BARCODE_FONT_WEIGHT,
661                                                        FALSE, bchar->fsize);
662                         gnome_print_setfont (pi->pc, font);
663
664                         gnome_print_setrgbcolor (pi->pc,
665                                                  RED (object->arg.barcode.
666                                                       color),
667                                                  GREEN (object->arg.barcode.
668                                                         color),
669                                                  BLUE (object->arg.barcode.
670                                                        color));
671                         gnome_print_setopacity (pi->pc,
672                                                 ALPHA (object->arg.barcode.
673                                                        color));
674
675                         y_offset =
676                             bchar->y + bchar->fsize -
677                             gnome_font_get_descender (font);
678                         gnome_print_moveto (pi->pc, x + bchar->x, y + y_offset);
679
680                         cstring = g_strdup_printf ("%c", bchar->c);
681                         gnome_print_gsave (pi->pc);
682                         gnome_print_scale (pi->pc, 1.0, -1.0);
683                         gnome_print_show (pi->pc, cstring);
684                         gnome_print_grestore (pi->pc);
685                         g_free (cstring);
686
687                 }
688
689                 gl_barcode_free (&gbc);
690
691         }
692
693 }
694
695 /*---------------------------------------------------------------------------*/
696 /* PRIVATE.  Draw outline.                                                   */
697 /*---------------------------------------------------------------------------*/
698 static void
699 draw_outline (PrintInfo * pi,
700               glLabel * label)
701 {
702         gdouble w, h, r;
703         gdouble r1, r2;
704
705         gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
706         gnome_print_setopacity (pi->pc, 1.0);
707         gnome_print_setlinewidth (pi->pc, 0.25);
708
709         switch (label->template->style) {
710
711         case GL_TEMPLATE_STYLE_RECT:
712                 w = label->width;
713                 h = label->height;
714                 r = label->template->label_round;
715                 if (r == 0.0) {
716                         /* simple rectangle */
717                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
718                 } else {
719                         /* rectangle with rounded corners */
720                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
721                                                        w, h, r);
722                 }
723                 gnome_print_stroke (pi->pc);
724                 break;
725
726         case GL_TEMPLATE_STYLE_ROUND:
727                 /* Round style */
728                 r1 = label->template->label_radius;
729                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
730                 gnome_print_stroke (pi->pc);
731                 break;
732
733         case GL_TEMPLATE_STYLE_CD:
734                 /* CD style, round label w/ concentric round hole */
735                 r1 = label->template->label_radius;
736                 r2 = label->template->label_hole;
737                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
738                 gnome_print_stroke (pi->pc);
739                 create_ellipse_path (pi->pc, r1, r1, r2, r2);
740                 gnome_print_stroke (pi->pc);
741                 break;
742
743         default:
744                 WARN ("Unknown template label style");
745                 break;
746         }
747
748 }
749
750 #ifdef CLIP_LABEL
751 /*---------------------------------------------------------------------------*/
752 /* PRIVATE.  Clip to outline.                                                */
753 /*---------------------------------------------------------------------------*/
754 static void
755 clip_to_outline (PrintInfo * pi,
756                  glLabel * label)
757 {
758         gdouble w, h, r;
759         gdouble r1;
760
761         switch (label->template->style) {
762
763         case GL_TEMPLATE_STYLE_RECT:
764                 w = label->width;
765                 h = label->height;
766                 r = label->template->label_round;
767                 if (r == 0.0) {
768                         /* simple rectangle */
769                         create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
770                 } else {
771                         /* rectangle with rounded corners */
772                         create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
773                                                        w, h, r);
774                 }
775                 gnome_print_clip (pi->pc);
776                 break;
777
778         case GL_TEMPLATE_STYLE_ROUND:
779         case GL_TEMPLATE_STYLE_CD:
780                 r1 = label->template->label_radius;
781                 create_ellipse_path (pi->pc, r1, r1, r1, r1);
782                 gnome_print_clip (pi->pc);
783                 break;
784
785         default:
786                 WARN ("Unknown template label style");
787                 break;
788         }
789
790 }
791 #endif
792
793 /*---------------------------------------------------------------------------*/
794 /* PRIVATE.  Path creation utilities.                                        */
795 /*---------------------------------------------------------------------------*/
796 static void
797 create_rectangle_path (GnomePrintContext * pc,
798                        gdouble x0,
799                        gdouble y0,
800                        gdouble w,
801                        gdouble h)
802 {
803         gnome_print_newpath (pc);
804         gnome_print_moveto (pc, x0, y0);
805         gnome_print_lineto (pc, x0 + w, y0);
806         gnome_print_lineto (pc, x0 + w, y0 + h);
807         gnome_print_lineto (pc, x0, y0 + h);
808         gnome_print_lineto (pc, x0, y0);
809         gnome_print_closepath (pc);
810 }
811
812 static void
813 create_ellipse_path (GnomePrintContext * pc,
814                      gdouble x0,
815                      gdouble y0,
816                      gdouble rx,
817                      gdouble ry)
818 {
819         gdouble x, y;
820         gint i_theta;
821
822         gnome_print_newpath (pc);
823         gnome_print_moveto (pc, x0 + rx, y0);
824         for (i_theta = 2; i_theta <= 360; i_theta += 2) {
825                 x = x0 + rx * cos (i_theta * M_PI / 180.0);
826                 y = y0 + ry * sin (i_theta * M_PI / 180.0);
827                 gnome_print_lineto (pc, x, y);
828         }
829         gnome_print_closepath (pc);
830 }
831
832 static void
833 create_rounded_rectangle_path (GnomePrintContext * pc,
834                                gdouble x0,
835                                gdouble y0,
836                                gdouble w,
837                                gdouble h,
838                                gdouble r)
839 {
840         gdouble x, y;
841         gint i_theta;
842
843         gnome_print_newpath (pc);
844
845         gnome_print_moveto (pc, x0 + r, y0);
846         for (i_theta = 5; i_theta <= 90; i_theta += 5) {
847                 x = x0 + r - r * sin (i_theta * M_PI / 180.0);
848                 y = y0 + r - r * cos (i_theta * M_PI / 180.0);
849                 gnome_print_lineto (pc, x, y);
850         }
851         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
852                 x = x0 + r - r * cos (i_theta * M_PI / 180.0);
853                 y = y0 + (h - r) + r * sin (i_theta * M_PI / 180.0);
854                 gnome_print_lineto (pc, x, y);
855         }
856         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
857                 x = x0 + (w - r) + r * sin (i_theta * M_PI / 180.0);
858                 y = y0 + (h - r) + r * cos (i_theta * M_PI / 180.0);
859                 gnome_print_lineto (pc, x, y);
860         }
861         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
862                 x = x0 + (w - r) + r * cos (i_theta * M_PI / 180.0);
863                 y = y0 + r - r * sin (i_theta * M_PI / 180.0);
864                 gnome_print_lineto (pc, x, y);
865         }
866         gnome_print_lineto (pc, x0 + r, y0);
867
868         gnome_print_closepath (pc);
869 }