1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * print.c: Print module
8 * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <glib/gi18n.h>
32 #include <gtk/gtkenums.h>
35 #include "label-text.h"
36 #include "label-box.h"
37 #include "label-line.h"
38 #include "label-ellipse.h"
39 #include "label-image.h"
40 #include "label-barcode.h"
42 #include <libglabels/template.h>
47 #define ARC_FINE 2 /* Resolution in degrees of large arcs */
49 #define FONT_SCALE (72.0/96.0)
50 #define TICK_OFFSET 2.25
51 #define TICK_LENGTH 18.0
53 /*=========================================================================*/
55 /*=========================================================================*/
57 typedef struct _PrintInfo {
60 /* gLabels Template */
62 gboolean label_rotate_flag;
71 /*=========================================================================*/
72 /* Private function prototypes. */
73 /*=========================================================================*/
74 static PrintInfo *print_info_new (cairo_t *cr,
77 static void print_info_free (PrintInfo **pi);
79 static void print_crop_marks (PrintInfo *pi);
81 static void print_label (PrintInfo *pi,
85 glMergeRecord *record,
86 gboolean outline_flag,
87 gboolean reverse_flag);
90 static void draw_label (PrintInfo *pi,
92 glMergeRecord *record);
95 static void draw_object (PrintInfo *pi,
96 glLabelObject *object,
97 glMergeRecord *record);
99 static void draw_text_object (PrintInfo *pi,
101 glMergeRecord *record);
103 static void draw_box_object (PrintInfo *pi,
105 glMergeRecord *record);
107 static void draw_line_object (PrintInfo *pi,
109 glMergeRecord *record);
111 static void draw_ellipse_object (PrintInfo *pi,
112 glLabelEllipse *object,
113 glMergeRecord *record);
115 static void draw_image_object (PrintInfo *pi,
116 glLabelImage *object,
117 glMergeRecord *record);
119 static void draw_barcode_object (PrintInfo *pi,
120 glLabelBarcode *object,
121 glMergeRecord *record);
124 static void draw_outline (PrintInfo *pi,
127 static void clip_to_outline (PrintInfo *pi,
130 static void clip_punchouts (PrintInfo *pi,
134 static void create_rounded_rectangle_path (cairo_t *cr,
141 static void create_ellipse_path (cairo_t *cr,
147 static void create_cd_path (cairo_t *cr,
156 /*****************************************************************************/
157 /* Print simple sheet (no merge data) command. */
158 /*****************************************************************************/
160 gl_print_simple_sheet (glLabel *label,
166 gboolean outline_flag,
167 gboolean reverse_flag,
168 gboolean crop_marks_flag)
171 const glTemplateLabelType *label_type;
173 glTemplateOrigin *origins;
175 gl_debug (DEBUG_PRINT, "START");
177 pi = print_info_new (cr, label);
179 label_type = gl_template_get_first_label_type (pi->template);
180 origins = gl_template_get_origins (label_type);
182 if (crop_marks_flag) {
183 print_crop_marks (pi);
186 for (i_label = first - 1; i_label < last; i_label++) {
188 print_label (pi, label,
189 origins[i_label].x, origins[i_label].y,
190 NULL, outline_flag, reverse_flag);
196 print_info_free (&pi);
198 gl_debug (DEBUG_PRINT, "END");
201 /*****************************************************************************/
202 /* Print collated merge sheet command */
203 /*****************************************************************************/
205 gl_print_collated_merge_sheet (glLabel *label,
210 gboolean outline_flag,
211 gboolean reverse_flag,
212 gboolean crop_marks_flag,
216 const GList *record_list;
218 const glTemplateLabelType *label_type;
219 gint i_label, n_labels_per_page, i_copy;
220 glMergeRecord *record;
222 glTemplateOrigin *origins;
224 gl_debug (DEBUG_PRINT, "START");
226 merge = gl_label_get_merge (label);
227 record_list = gl_merge_get_record_list (merge);
229 pi = print_info_new (cr, label);
230 label_type = gl_template_get_first_label_type (pi->template);
232 n_labels_per_page = gl_template_get_n_labels (label_type);
233 origins = gl_template_get_origins (label_type);
235 if (crop_marks_flag) {
236 print_crop_marks (pi);
242 state->p_record = (GList *)record_list;
252 for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
253 record = (glMergeRecord *)p->data;
255 if ( record->select_flag ) {
256 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
258 print_label (pi, label,
262 outline_flag, reverse_flag);
265 if (i_label == n_labels_per_page)
268 print_info_free (&pi);
270 state->i_copy = (i_copy+1) % n_copies;
271 if (state->i_copy == 0)
273 state->p_record = p->next;
287 print_info_free (&pi);
289 gl_debug (DEBUG_PRINT, "END");
292 /*****************************************************************************/
293 /* Print uncollated merge sheet command */
294 /*****************************************************************************/
296 gl_print_uncollated_merge_sheet (glLabel *label,
301 gboolean outline_flag,
302 gboolean reverse_flag,
303 gboolean crop_marks_flag,
307 const GList *record_list;
309 const glTemplateLabelType *label_type;
310 gint i_label, n_labels_per_page, i_copy;
311 glMergeRecord *record;
313 glTemplateOrigin *origins;
315 gl_debug (DEBUG_PRINT, "START");
317 merge = gl_label_get_merge (label);
318 record_list = gl_merge_get_record_list (merge);
320 pi = print_info_new (cr, label);
321 label_type = gl_template_get_first_label_type (pi->template);
323 n_labels_per_page = gl_template_get_n_labels (label_type);
324 origins = gl_template_get_origins (label_type);
326 if (crop_marks_flag) {
327 print_crop_marks (pi);
333 state->p_record = (GList *)record_list;
342 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
344 for ( p=state->p_record; p!=NULL; p=p->next ) {
345 record = (glMergeRecord *)p->data;
347 if ( record->select_flag ) {
349 print_label (pi, label,
353 outline_flag, reverse_flag);
356 if (i_label == n_labels_per_page)
359 print_info_free (&pi);
361 state->p_record = p->next;
362 if (state->p_record == NULL)
364 state->p_record = (GList *)record_list;
365 state->i_copy = i_copy + 1;
369 state->i_copy = i_copy;
375 state->p_record = (GList *)record_list;
380 print_info_free (&pi);
382 gl_debug (DEBUG_PRINT, "END");
386 /*****************************************************************************/
387 /* Batch print. Call appropriate function above. */
388 /*****************************************************************************/
390 gl_print_batch (GnomePrintJob *job,
398 glTemplate *template;
399 const glTemplateLabelType *label_type;
402 gl_debug (DEBUG_PRINT, "START");
404 merge = gl_label_get_merge (label);
405 template = gl_label_get_template (label);
406 label_type = gl_template_get_first_label_type (template);
408 if ( merge == NULL ) {
409 n_per_page = gl_template_get_n_labels(label_type);
411 gl_print_simple (job, label, n_sheets, first, n_per_page, flags);
413 gl_print_merge_collated (job, label, n_copies, first, flags);
415 gl_template_free (template);
417 gl_debug (DEBUG_PRINT, "END");
421 /*---------------------------------------------------------------------------*/
422 /* PRIVATE. new print info structure */
423 /*---------------------------------------------------------------------------*/
425 print_info_new (cairo_t *cr,
428 PrintInfo *pi = g_new0 (PrintInfo, 1);
429 glTemplate *template;
431 gl_debug (DEBUG_PRINT, "START");
433 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
435 template = gl_label_get_template (label);
437 g_return_val_if_fail (template, NULL);
438 g_return_val_if_fail (template->page_size, NULL);
439 g_return_val_if_fail (template->page_width > 0, NULL);
440 g_return_val_if_fail (template->page_height > 0, NULL);
444 gl_debug (DEBUG_PRINT,
445 "setting page size = \"%s\"", template->page_size);
447 pi->page_width = template->page_width;
448 pi->page_height = template->page_height;
450 pi->template = template;
451 pi->label_rotate_flag = gl_label_get_rotate_flag (label);
453 gl_debug (DEBUG_PRINT, "END");
458 /*---------------------------------------------------------------------------*/
459 /* PRIVATE. free print info structure */
460 /*---------------------------------------------------------------------------*/
462 print_info_free (PrintInfo **pi)
464 gl_debug (DEBUG_PRINT, "START");
466 gl_template_free ((*pi)->template);
467 (*pi)->template = NULL;
472 gl_debug (DEBUG_PRINT, "END");
475 /*---------------------------------------------------------------------------*/
476 /* PRIVATE. Print crop tick marks. */
477 /*---------------------------------------------------------------------------*/
479 print_crop_marks (PrintInfo *pi)
481 const glTemplateLabelType *label_type;
482 gdouble w, h, page_w, page_h;
484 glTemplateLayout *layout;
485 gdouble xmin, ymin, xmax, ymax, dx, dy;
486 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
489 gl_debug (DEBUG_PRINT, "START");
491 label_type = gl_template_get_first_label_type (pi->template);
493 gl_template_get_label_size (label_type, &w, &h);
495 page_w = pi->page_width;
496 page_h = pi->page_height;
500 cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
501 cairo_set_line_width (pi->cr, 0.25);
503 for (p=label_type->layouts; p != NULL; p=p->next) {
505 layout = (glTemplateLayout *)p->data;
509 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
510 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
518 for (ix=0; ix < nx; ix++) {
523 y1 = MAX((ymin - TICK_OFFSET), 0.0);
524 y2 = MAX((y1 - TICK_LENGTH), 0.0);
526 y3 = MIN((ymax + TICK_OFFSET), page_h);
527 y4 = MIN((y3 + TICK_LENGTH), page_h);
529 cairo_move_to (pi->cr, x1, y1);
530 cairo_line_to (pi->cr, x1, y2);
531 cairo_stroke (pi->cr);
533 cairo_move_to (pi->cr, x2, y1);
534 cairo_line_to (pi->cr, x2, y2);
535 cairo_stroke (pi->cr);
537 cairo_move_to (pi->cr, x1, y3);
538 cairo_line_to (pi->cr, x1, y4);
539 cairo_stroke (pi->cr);
541 cairo_move_to (pi->cr, x2, y3);
542 cairo_line_to (pi->cr, x2, y4);
543 cairo_stroke (pi->cr);
547 for (iy=0; iy < ny; iy++) {
552 x1 = MAX((xmin - TICK_OFFSET), 0.0);
553 x2 = MAX((x1 - TICK_LENGTH), 0.0);
555 x3 = MIN((xmax + TICK_OFFSET), page_w);
556 x4 = MIN((x3 + TICK_LENGTH), page_w);
558 cairo_move_to (pi->cr, x1, y1);
559 cairo_line_to (pi->cr, x2, y1);
560 cairo_stroke (pi->cr);
562 cairo_move_to (pi->cr, x1, y2);
563 cairo_line_to (pi->cr, x2, y2);
564 cairo_stroke (pi->cr);
566 cairo_move_to (pi->cr, x3, y1);
567 cairo_line_to (pi->cr, x4, y1);
568 cairo_stroke (pi->cr);
570 cairo_move_to (pi->cr, x3, y2);
571 cairo_line_to (pi->cr, x4, y2);
572 cairo_stroke (pi->cr);
578 cairo_restore (pi->cr);
580 gl_debug (DEBUG_PRINT, "END");
583 /*---------------------------------------------------------------------------*/
584 /* PRIVATE. Print i'th label. */
585 /*---------------------------------------------------------------------------*/
587 print_label (PrintInfo *pi,
591 glMergeRecord *record,
592 gboolean outline_flag,
593 gboolean reverse_flag)
595 const glTemplateLabelType *label_type;
596 gdouble width, height;
598 gl_debug (DEBUG_PRINT, "START");
600 label_type = gl_template_get_first_label_type (pi->template);
602 gl_label_get_size (label, &width, &height);
606 /* Transform coordinate system to be relative to upper corner */
607 /* of the current label */
608 cairo_translate (pi->cr, x, y);
609 if (gl_label_get_rotate_flag (label)) {
610 gl_debug (DEBUG_PRINT, "Rotate flag set");
611 cairo_rotate (pi->cr, -M_PI/2.0);
612 cairo_translate (pi->cr, -width, 0.0);
614 if ( reverse_flag ) {
615 cairo_translate (pi->cr, width, 0.0);
616 cairo_scale (pi->cr, -1.0, 1.0);
619 clip_to_outline (pi, label);
620 draw_label (pi, label, record);
622 draw_outline (pi, label);
625 cairo_restore (pi->cr);
627 gl_debug (DEBUG_PRINT, "END");
630 /*---------------------------------------------------------------------------*/
631 /* PRIVATE. Draw label. */
632 /*---------------------------------------------------------------------------*/
634 draw_label (PrintInfo *pi,
636 glMergeRecord *record)
639 glLabelObject *object;
641 gl_debug (DEBUG_PRINT, "START");
643 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
644 object = (glLabelObject *) p_obj->data;
646 draw_object (pi, object, record);
649 gl_debug (DEBUG_PRINT, "END");
652 /*---------------------------------------------------------------------------*/
653 /* PRIVATE. Draw object. */
654 /*---------------------------------------------------------------------------*/
656 draw_object (PrintInfo *pi,
657 glLabelObject *object,
658 glMergeRecord *record)
662 cairo_matrix_t matrix;
664 gl_debug (DEBUG_PRINT, "START");
666 gl_label_object_get_position (object, &x0, &y0);
667 gl_label_object_get_affine (object, a);
668 cairo_matrix_init (&matrix, a[0], a[1], a[2], a[3], a[4], a[5]);
672 cairo_translate (pi->cr, x0, y0);
673 cairo_transform (pi->cr, &matrix);
676 if (GL_IS_LABEL_TEXT(object)) {
677 draw_text_object (pi, GL_LABEL_TEXT(object), record);
678 } else if (GL_IS_LABEL_BOX(object)) {
679 draw_box_object (pi, GL_LABEL_BOX(object), record);
680 } else if (GL_IS_LABEL_LINE(object)) {
681 draw_line_object (pi, GL_LABEL_LINE(object), record);
682 } else if (GL_IS_LABEL_ELLIPSE(object)) {
683 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object), record);
684 } else if (GL_IS_LABEL_IMAGE(object)) {
685 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
686 } else if (GL_IS_LABEL_BARCODE(object)) {
687 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
690 cairo_restore (pi->cr);
692 gl_debug (DEBUG_PRINT, "END");
695 /*---------------------------------------------------------------------------*/
696 /* PRIVATE. Draw text object. */
697 /*---------------------------------------------------------------------------*/
699 draw_text_object (PrintInfo *pi,
701 glMergeRecord *record)
704 gdouble x_offset, y_offset, w, object_w, object_h;
709 GnomeFontWeight font_weight;
710 gboolean font_italic_flag;
712 glColorNode *color_node;
713 GtkJustification just;
714 gboolean auto_shrink;
717 gdouble text_line_spacing;
718 gboolean shadow_state;
719 gdouble shadow_x, shadow_y;
720 glColorNode *shadow_color_node;
721 gdouble shadow_opacity;
723 PangoAlignment alignment;
726 PangoFontDescription *desc;
729 gl_debug (DEBUG_PRINT, "START");
731 gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
732 lines = gl_label_text_get_lines (object);
733 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
734 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
735 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
736 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
738 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
739 color = gl_color_node_expand (color_node, record);
740 gl_color_node_free (&color_node);
742 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
744 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
745 auto_shrink = gl_label_text_get_auto_shrink (object);
747 shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
748 gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
749 shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
750 if (shadow_color_node->field_flag)
752 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
754 shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
755 shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
756 gl_color_node_free (&shadow_color_node);
758 text = gl_text_node_lines_expand (lines, record);
761 case GTK_JUSTIFY_LEFT:
762 alignment = PANGO_ALIGN_LEFT;
764 case GTK_JUSTIFY_CENTER:
765 alignment = PANGO_ALIGN_CENTER;
767 case GTK_JUSTIFY_RIGHT:
768 alignment = PANGO_ALIGN_RIGHT;
771 alignment = PANGO_ALIGN_LEFT;
772 break; /* shouldn't happen */
775 style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
778 if (record && auto_shrink) {
780 /* auto shrink text size to keep within text box limits. */
782 layout = pango_cairo_create_layout (pi->cr);
784 desc = pango_font_description_new ();
785 pango_font_description_set_family (desc, font_family);
786 pango_font_description_set_weight (desc, font_weight);
787 pango_font_description_set_style (desc, style);
788 pango_font_description_set_size (desc, font_size * PANGO_SCALE * FONT_SCALE);
789 pango_layout_set_font_description (layout, desc);
790 pango_font_description_free (desc);
792 pango_layout_set_text (layout, text, -1);
793 w = pango_layout_get_width (layout) / PANGO_SCALE;
795 g_object_unref (layout);
800 font_size *= (object_w-2*GL_LABEL_TEXT_MARGIN)/w;
802 /* Round down to nearest 1/2 point */
803 font_size = (int)(font_size*2.0) / 2.0;
805 /* don't get ridiculously small. */
814 layout = pango_cairo_create_layout (pi->cr);
816 desc = pango_font_description_new ();
817 pango_font_description_set_family (desc, font_family);
818 pango_font_description_set_weight (desc, font_weight);
819 pango_font_description_set_style (desc, style);
820 pango_font_description_set_size (desc, font_size * PANGO_SCALE * FONT_SCALE);
821 pango_layout_set_font_description (layout, desc);
822 pango_font_description_free (desc);
824 pango_layout_set_text (layout, text, -1);
825 pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE);
826 pango_layout_set_width (layout, object_w * PANGO_SCALE);
827 pango_layout_set_alignment (layout, alignment);
831 cairo_set_source_rgba (pi->cr,
832 GL_COLOR_F_RED (shadow_color),
833 GL_COLOR_F_GREEN (shadow_color),
834 GL_COLOR_F_BLUE (shadow_color),
835 GL_COLOR_F_ALPHA (shadow_color));
837 cairo_move_to (pi->cr, shadow_x + GL_LABEL_TEXT_MARGIN, shadow_y);
838 pango_cairo_show_layout (pi->cr, layout);
841 cairo_set_source_rgba (pi->cr,
842 GL_COLOR_F_RED (color),
843 GL_COLOR_F_GREEN (color),
844 GL_COLOR_F_BLUE (color),
845 GL_COLOR_F_ALPHA (color));
847 cairo_move_to (pi->cr, GL_LABEL_TEXT_MARGIN, 0);
848 pango_cairo_show_layout (pi->cr, layout);
850 g_object_unref (layout);
853 gl_text_node_lines_free (&lines);
854 g_free (font_family);
856 gl_debug (DEBUG_PRINT, "END");
859 /*---------------------------------------------------------------------------*/
860 /* PRIVATE. Draw box object. */
861 /*---------------------------------------------------------------------------*/
863 draw_box_object (PrintInfo *pi,
865 glMergeRecord *record)
870 glColorNode *line_color_node;
871 glColorNode *fill_color_node;
873 gboolean shadow_state;
874 gdouble shadow_x, shadow_y;
875 glColorNode *shadow_color_node;
876 gdouble shadow_opacity;
877 guint shadow_line_color;
878 guint shadow_fill_color;
880 gl_debug (DEBUG_PRINT, "START");
882 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
883 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
885 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
886 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
887 line_color = gl_color_node_expand (line_color_node, record);
888 fill_color = gl_color_node_expand (fill_color_node, record);
889 gl_color_node_free (&line_color_node);
890 gl_color_node_free (&fill_color_node);
892 shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
893 gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
894 shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
895 if (shadow_color_node->field_flag)
897 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
899 shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
900 shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
901 shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
902 gl_color_node_free (&shadow_color_node);
906 /* Draw fill shadow */
907 cairo_rectangle (pi->cr, shadow_x, shadow_y, w, h);
909 cairo_set_source_rgba (pi->cr,
910 GL_COLOR_F_RED (shadow_fill_color),
911 GL_COLOR_F_GREEN (shadow_fill_color),
912 GL_COLOR_F_BLUE (shadow_fill_color),
913 GL_COLOR_F_ALPHA (shadow_fill_color));
914 cairo_fill_preserve (pi->cr);
916 /* Draw outline shadow */
917 cairo_set_source_rgba (pi->cr,
918 GL_COLOR_F_RED (shadow_line_color),
919 GL_COLOR_F_GREEN (shadow_line_color),
920 GL_COLOR_F_BLUE (shadow_line_color),
921 GL_COLOR_F_ALPHA (shadow_line_color));
922 cairo_set_line_width (pi->cr, line_width);
923 cairo_stroke (pi->cr);
926 /* Paint fill color */
927 cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
928 cairo_set_source_rgba (pi->cr,
929 GL_COLOR_F_RED (fill_color),
930 GL_COLOR_F_GREEN (fill_color),
931 GL_COLOR_F_BLUE (fill_color),
932 GL_COLOR_F_ALPHA (fill_color));
933 cairo_fill_preserve (pi->cr);
936 cairo_set_source_rgba (pi->cr,
937 GL_COLOR_F_RED (line_color),
938 GL_COLOR_F_GREEN (line_color),
939 GL_COLOR_F_BLUE (line_color),
940 GL_COLOR_F_ALPHA (line_color));
941 cairo_set_line_width (pi->cr, line_width);
942 cairo_stroke (pi->cr);
944 gl_debug (DEBUG_PRINT, "END");
947 /*---------------------------------------------------------------------------*/
948 /* PRIVATE. Draw line object. */
949 /*---------------------------------------------------------------------------*/
951 draw_line_object (PrintInfo *pi,
953 glMergeRecord *record)
958 glColorNode *line_color_node;
959 gboolean shadow_state;
960 gdouble shadow_x, shadow_y;
961 glColorNode *shadow_color_node;
962 gdouble shadow_opacity;
963 guint shadow_line_color;
965 gl_debug (DEBUG_PRINT, "START");
967 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
968 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
970 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
971 line_color = gl_color_node_expand (line_color_node, record);
972 gl_color_node_free (&line_color_node);
974 shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
975 gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
976 shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
977 if (shadow_color_node->field_flag)
979 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
981 shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
982 shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
983 gl_color_node_free (&shadow_color_node);
987 cairo_move_to (pi->cr, shadow_x, shadow_y);
988 cairo_line_to (pi->cr, shadow_x + w, shadow_y + h);
989 cairo_set_source_rgba (pi->cr,
990 GL_COLOR_F_RED (shadow_line_color),
991 GL_COLOR_F_GREEN (shadow_line_color),
992 GL_COLOR_F_BLUE (shadow_line_color),
993 GL_COLOR_F_ALPHA (shadow_line_color));
994 cairo_set_line_width (pi->cr, line_width);
995 cairo_stroke (pi->cr);
998 cairo_move_to (pi->cr, 0.0, 0.0);
999 cairo_line_to (pi->cr, w, h);
1000 cairo_set_source_rgba (pi->cr,
1001 GL_COLOR_F_RED (line_color),
1002 GL_COLOR_F_GREEN (line_color),
1003 GL_COLOR_F_BLUE (line_color),
1004 GL_COLOR_F_ALPHA (line_color));
1005 cairo_set_line_width (pi->cr, line_width);
1006 cairo_stroke (pi->cr);
1008 gl_debug (DEBUG_PRINT, "END");
1011 /*---------------------------------------------------------------------------*/
1012 /* PRIVATE. Draw ellipse object. */
1013 /*---------------------------------------------------------------------------*/
1015 draw_ellipse_object (PrintInfo *pi,
1016 glLabelEllipse *object,
1017 glMergeRecord *record)
1019 gdouble x0, y0, rx, ry, w, h;
1021 glColorNode *line_color_node;
1022 glColorNode *fill_color_node;
1025 gboolean shadow_state;
1026 gdouble shadow_x, shadow_y;
1027 glColorNode *shadow_color_node;
1028 gdouble shadow_opacity;
1029 guint shadow_line_color;
1030 guint shadow_fill_color;
1032 gl_debug (DEBUG_PRINT, "START");
1034 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1035 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1037 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1038 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1039 line_color = gl_color_node_expand (line_color_node, record);
1040 fill_color = gl_color_node_expand (fill_color_node, record);
1041 gl_color_node_free (&line_color_node);
1042 gl_color_node_free (&fill_color_node);
1049 shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
1050 gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
1051 shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
1052 if (shadow_color_node->field_flag)
1054 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
1056 shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
1057 shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
1058 shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
1059 gl_color_node_free (&shadow_color_node);
1063 /* Draw fill shadow */
1064 create_ellipse_path (pi->cr, x0+shadow_x, y0+shadow_y, rx, ry);
1065 cairo_set_source_rgba (pi->cr,
1066 GL_COLOR_F_RED (shadow_fill_color),
1067 GL_COLOR_F_GREEN (shadow_fill_color),
1068 GL_COLOR_F_BLUE (shadow_fill_color),
1069 GL_COLOR_F_ALPHA (shadow_fill_color));
1070 cairo_fill_preserve (pi->cr);
1072 /* Draw outline shadow */
1073 cairo_set_source_rgba (pi->cr,
1074 GL_COLOR_F_RED (shadow_line_color),
1075 GL_COLOR_F_GREEN (shadow_line_color),
1076 GL_COLOR_F_BLUE (shadow_line_color),
1077 GL_COLOR_F_ALPHA (shadow_line_color));
1078 cairo_set_line_width (pi->cr, line_width);
1079 cairo_stroke (pi->cr);
1082 /* Paint fill color */
1083 create_ellipse_path (pi->cr, x0, y0, rx, ry);
1084 cairo_set_source_rgba (pi->cr,
1085 GL_COLOR_F_RED (fill_color),
1086 GL_COLOR_F_GREEN (fill_color),
1087 GL_COLOR_F_BLUE (fill_color),
1088 GL_COLOR_F_ALPHA (fill_color));
1089 cairo_fill_preserve (pi->cr);
1092 cairo_set_source_rgba (pi->cr,
1093 GL_COLOR_F_RED (line_color),
1094 GL_COLOR_F_GREEN (line_color),
1095 GL_COLOR_F_BLUE (line_color),
1096 GL_COLOR_F_ALPHA (line_color));
1097 cairo_set_line_width (pi->cr, line_width);
1098 cairo_stroke (pi->cr);
1100 gl_debug (DEBUG_PRINT, "END");
1103 /*---------------------------------------------------------------------------*/
1104 /* PRIVATE. Draw image object. */
1105 /*---------------------------------------------------------------------------*/
1107 draw_image_object (PrintInfo *pi,
1108 glLabelImage *object,
1109 glMergeRecord *record)
1112 const GdkPixbuf *pixbuf;
1113 gint image_w, image_h;
1115 gl_debug (DEBUG_PRINT, "START");
1117 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1119 pixbuf = gl_label_image_get_pixbuf (object, record);
1120 image_w = gdk_pixbuf_get_width (pixbuf);
1121 image_h = gdk_pixbuf_get_height (pixbuf);
1123 cairo_save (pi->cr);
1124 cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
1125 cairo_clip (pi->cr);
1126 cairo_scale (pi->cr, w/image_w, h/image_h);
1127 gdk_cairo_set_source_pixbuf (pi->cr, (GdkPixbuf *)pixbuf, 0, 0);
1128 cairo_paint (pi->cr);
1130 cairo_restore (pi->cr);
1132 gl_debug (DEBUG_PRINT, "END");
1135 /*---------------------------------------------------------------------------*/
1136 /* PRIVATE. Draw barcode object. */
1137 /*---------------------------------------------------------------------------*/
1139 draw_barcode_object (PrintInfo *pi,
1140 glLabelBarcode *object,
1141 glMergeRecord *record)
1144 glBarcodeLine *line;
1145 glBarcodeChar *bchar;
1148 PangoLayout *layout;
1149 PangoFontDescription *desc;
1150 gchar *text, *cstring;
1151 glTextNode *text_node;
1154 gboolean checksum_flag;
1156 glColorNode *color_node;
1157 guint format_digits;
1160 gl_debug (DEBUG_PRINT, "START");
1162 text_node = gl_label_barcode_get_data (object);
1163 gl_label_barcode_get_props (object,
1164 &id, &text_flag, &checksum_flag, &format_digits);
1166 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1167 color = gl_color_node_expand (color_node, record);
1168 gl_color_node_free (&color_node);
1170 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1172 text = gl_text_node_expand (text_node, record);
1174 if (text == NULL || *text == '\0') {
1177 gl_text_node_free(&text_node);
1183 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1185 gl_text_node_free (&text_node);
1188 cairo_set_source_rgba (pi->cr,
1189 GL_COLOR_F_RED (color),
1190 GL_COLOR_F_GREEN (color),
1191 GL_COLOR_F_BLUE (color),
1192 GL_COLOR_F_ALPHA (color));
1196 layout = pango_cairo_create_layout (pi->cr);
1198 desc = pango_font_description_new ();
1199 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
1200 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
1201 pango_layout_set_font_description (layout, desc);
1202 pango_font_description_free (desc);
1204 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
1206 pango_cairo_show_layout (pi->cr, layout);
1208 g_object_unref (layout);
1212 for (li = gbc->lines; li != NULL; li = li->next) {
1213 line = (glBarcodeLine *) li->data;
1215 cairo_move_to (pi->cr, line->x, line->y);
1216 cairo_line_to (pi->cr, line->x, line->y + line->length);
1217 cairo_set_line_width (pi->cr, line->width);
1218 cairo_stroke (pi->cr);
1221 for (li = gbc->chars; li != NULL; li = li->next) {
1222 bchar = (glBarcodeChar *) li->data;
1224 layout = pango_cairo_create_layout (pi->cr);
1226 desc = pango_font_description_new ();
1227 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
1228 pango_font_description_set_size (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
1229 pango_layout_set_font_description (layout, desc);
1230 pango_font_description_free (desc);
1232 cstring = g_strdup_printf ("%c", bchar->c);
1233 pango_layout_set_text (layout, cstring, -1);
1236 y_offset = 0.2 * bchar->fsize;
1238 cairo_move_to (pi->cr, bchar->x, bchar->y-y_offset);
1239 pango_cairo_show_layout (pi->cr, layout);
1241 g_object_unref (layout);
1245 gl_barcode_free (&gbc);
1249 gl_debug (DEBUG_PRINT, "END");
1252 /*---------------------------------------------------------------------------*/
1253 /* PRIVATE. Draw outline. */
1254 /*---------------------------------------------------------------------------*/
1256 draw_outline (PrintInfo *pi,
1259 const glTemplateLabelType *label_type;
1263 gl_debug (DEBUG_PRINT, "START");
1265 label_type = gl_template_get_first_label_type (pi->template);
1267 cairo_save (pi->cr);
1269 cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
1270 cairo_set_line_width (pi->cr, 0.25);
1272 switch (label_type->shape) {
1274 case GL_TEMPLATE_SHAPE_RECT:
1275 gl_label_get_size (label, &w, &h);
1276 r = label_type->size.rect.r;
1278 /* simple rectangle */
1279 cairo_rectangle (pi->cr, 0.0, 0.0, w, h);
1281 /* rectangle with rounded corners */
1282 create_rounded_rectangle_path (pi->cr, 0.0, 0.0,
1285 cairo_stroke (pi->cr);
1288 case GL_TEMPLATE_SHAPE_ROUND:
1290 r1 = label_type->size.round.r;
1291 create_ellipse_path (pi->cr, r1, r1, r1, r1);
1292 cairo_stroke (pi->cr);
1295 case GL_TEMPLATE_SHAPE_CD:
1296 r1 = label_type->size.cd.r1;
1297 r2 = label_type->size.cd.r2;
1298 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1299 /* CD style, round label w/ concentric round hole */
1300 create_cd_path (pi->cr, r1, r1, 2*r1, 2*r1, r1, r2);
1302 cairo_stroke (pi->cr);
1304 /* Business Card CD style, clipped round label w/ hole */
1305 gl_label_get_size (label, &w, &h);
1306 create_cd_path (pi->cr, w/2, h/2, w, h, r1, r2);
1307 cairo_stroke (pi->cr);
1312 g_message ("Unknown template label style");
1316 cairo_restore (pi->cr);
1318 gl_debug (DEBUG_PRINT, "END");
1321 /*---------------------------------------------------------------------------*/
1322 /* PRIVATE. Clip to outline. */
1323 /*---------------------------------------------------------------------------*/
1325 clip_to_outline (PrintInfo *pi,
1328 const glTemplateLabelType *label_type;
1331 gdouble waste, x_waste, y_waste;
1333 gl_debug (DEBUG_PRINT, "START");
1335 label_type = gl_template_get_first_label_type (pi->template);
1337 switch (label_type->shape) {
1339 case GL_TEMPLATE_SHAPE_RECT:
1340 gl_label_get_size (label, &w, &h);
1341 r = label_type->size.rect.r;
1342 x_waste = label_type->size.rect.x_waste;
1343 y_waste = label_type->size.rect.y_waste;
1345 /* simple rectangle */
1346 cairo_rectangle (pi->cr,
1348 w+2*x_waste, h+2*y_waste);
1350 /* rectangle with rounded corners */
1351 create_rounded_rectangle_path (pi->cr,
1353 w+2*x_waste, h+2*y_waste, r);
1355 cairo_clip (pi->cr);
1358 case GL_TEMPLATE_SHAPE_ROUND:
1359 r1 = label_type->size.round.r;
1360 waste = label_type->size.round.waste;
1361 create_ellipse_path (pi->cr, r1, r1, r1+waste, r1+waste);
1362 cairo_clip (pi->cr);
1365 case GL_TEMPLATE_SHAPE_CD:
1366 waste = label_type->size.cd.waste;
1367 r1 = label_type->size.cd.r1;
1368 r2 = label_type->size.cd.r2;
1369 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1370 /* CD style, round label w/ concentric round hole */
1371 create_cd_path (pi->cr,
1373 2*(r1+waste), 2*(r1+waste),
1377 /* Business Card CD style, clipped round label w/ hole */
1378 gl_label_get_size (label, &w, &h);
1379 create_cd_path (pi->cr,
1381 w+2*waste, h+2*waste,
1385 cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
1386 cairo_clip (pi->cr);
1390 g_message ("Unknown template label style");
1394 gl_debug (DEBUG_PRINT, "END");
1397 /*---------------------------------------------------------------------------*/
1398 /* PRIVATE. Path creation utilities. */
1399 /*---------------------------------------------------------------------------*/
1401 create_rounded_rectangle_path (cairo_t *cr,
1411 gl_debug (DEBUG_PRINT, "START");
1413 cairo_new_path (cr);
1415 cairo_arc_negative (cr, x0+r, y0+r, r, 3*M_PI/2, M_PI);
1416 cairo_arc_negative (cr, x0+r, y0+h-r, r, M_PI, M_PI/2);
1417 cairo_arc_negative (cr, x0+w-r, y0+h-r, r, M_PI/2, 0.);
1418 cairo_arc_negative (cr, x0+w-r, y0+r, r, 2*M_PI, 3*M_PI/2);
1419 cairo_close_path (cr);
1421 gl_debug (DEBUG_PRINT, "END");
1425 create_ellipse_path (cairo_t *cr,
1434 gl_debug (DEBUG_PRINT, "START");
1436 cairo_new_path (cr);
1437 cairo_move_to (cr, x0 + rx, y0);
1438 for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1439 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1440 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1441 cairo_line_to (cr, x, y);
1443 cairo_close_path (cr);
1445 gl_debug (DEBUG_PRINT, "END");
1449 create_cd_path (cairo_t *cr,
1457 gdouble theta1, theta2;
1459 gl_debug (DEBUG_PRINT, "START");
1462 * Outer radius. (may be clipped)
1464 theta1 = acos (w / (2.0*r1));
1465 theta2 = asin (h / (2.0*r1));
1467 cairo_new_path (cr);
1468 cairo_arc (cr, x0, y0, r1, theta1, theta2);
1469 cairo_arc (cr, x0, y0, r1, M_PI-theta2, M_PI-theta1);
1470 cairo_arc (cr, x0, y0, r1, M_PI+theta1, M_PI+theta2);
1471 cairo_arc (cr, x0, y0, r1, 2*M_PI-theta2, 2*M_PI-theta1);
1472 cairo_close_path (cr);
1475 * Inner radius. (hole)
1477 cairo_new_sub_path (cr);
1478 cairo_arc (cr, x0, y0, r2, 0.0, 2*M_PI);
1479 cairo_close_path (cr);
1481 gl_debug (DEBUG_PRINT, "END");