2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * print.c: Print module
6 * Copyright (C) 2001 Jim Evins <evins@snaught.com>.
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.
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.
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
26 #include <glib/gi18n.h>
30 #include <gtk/gtkenums.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"
40 #include <libglabels/template.h>
45 #define ARC_FINE 2 /* Resolution in degrees of large arcs */
46 #define ARC_COURSE 5 /* Resolution in degrees of small arcs */
48 #define TICK_OFFSET 2.25
49 #define TICK_LENGTH 18.0
51 /*=========================================================================*/
53 /*=========================================================================*/
55 typedef struct _PrintInfo {
56 /* gnome print context */
57 GnomePrintContext *pc;
59 /* gnome print configuration */
60 GnomePrintConfig *config;
62 /* gLabels Template */
64 gboolean label_rotate_flag;
75 /*=========================================================================*/
76 /* Private function prototypes. */
77 /*=========================================================================*/
78 static PrintInfo *print_info_new (GnomePrintJob *job,
81 static void print_info_free (PrintInfo **pi);
84 static void print_page_begin (PrintInfo *pi);
86 static void print_page_end (PrintInfo *pi);
88 static void print_crop_marks (PrintInfo *pi);
90 static void print_label (PrintInfo *pi,
94 glMergeRecord *record,
95 gboolean outline_flag,
96 gboolean reverse_flag);
99 static void draw_label (PrintInfo *pi,
101 glMergeRecord *record);
104 static void draw_object (PrintInfo *pi,
105 glLabelObject *object,
106 glMergeRecord *record);
108 static void draw_text_object (PrintInfo *pi,
110 glMergeRecord *record);
112 static void draw_box_object (PrintInfo *pi,
114 glMergeRecord *record);
116 static void draw_line_object (PrintInfo *pi,
118 glMergeRecord *record);
120 static void draw_ellipse_object (PrintInfo *pi,
121 glLabelEllipse *object,
122 glMergeRecord *record);
124 static void draw_image_object (PrintInfo *pi,
125 glLabelImage *object,
126 glMergeRecord *record);
128 static void draw_barcode_object (PrintInfo *pi,
129 glLabelBarcode *object,
130 glMergeRecord *record);
133 static void draw_outline (PrintInfo *pi,
136 static void clip_to_outline (PrintInfo *pi,
139 static void clip_punchouts (PrintInfo *pi,
143 static void create_rectangle_path (GnomePrintContext *pc,
149 static void create_ellipse_path (GnomePrintContext *pc,
155 static void create_rounded_rectangle_path (GnomePrintContext *pc,
162 static void create_clipped_circle_path (GnomePrintContext *pc,
169 #ifndef NO_ALPHA_HACK
170 static guchar * get_pixels_as_rgb (const GdkPixbuf *pixbuf);
174 /*****************************************************************************/
175 /* Simple (no merge data) print command. */
176 /*****************************************************************************/
178 gl_print_simple (GnomePrintJob *job,
186 const glTemplateLabelType *label_type;
187 gint i_sheet, i_label;
188 glTemplateOrigin *origins;
190 gl_debug (DEBUG_PRINT, "START");
192 pi = print_info_new (job, label);
193 label_type = gl_template_get_first_label_type (pi->template);
195 origins = gl_template_get_origins (label_type);
197 for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
199 print_page_begin (pi);
200 if (flags->crop_marks) {
201 print_crop_marks (pi);
204 for (i_label = first - 1; i_label < last; i_label++) {
206 print_label (pi, label,
207 origins[i_label].x, origins[i_label].y,
208 NULL, flags->outline, flags->reverse);
217 print_info_free (&pi);
219 gl_debug (DEBUG_PRINT, "END");
222 /*****************************************************************************/
223 /* Merge print command (collated copies) */
224 /*****************************************************************************/
226 gl_print_merge_collated (GnomePrintJob *job,
233 const GList *record_list;
235 const glTemplateLabelType *label_type;
236 gint i_sheet, i_label, n_labels_per_page, i_copy;
237 glMergeRecord *record;
239 glTemplateOrigin *origins;
241 gl_debug (DEBUG_PRINT, "START");
243 merge = gl_label_get_merge (label);
244 record_list = gl_merge_get_record_list (merge);
246 pi = print_info_new (job, label);
247 label_type = gl_template_get_first_label_type (pi->template);
249 n_labels_per_page = gl_template_get_n_labels (label_type);
250 origins = gl_template_get_origins (label_type);
255 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
256 record = (glMergeRecord *)p->data;
258 if ( record->select_flag ) {
259 for (i_copy = 0; i_copy < n_copies; i_copy++) {
261 if ((i_label == 0) || (i_sheet == 0)) {
263 print_page_begin (pi);
264 if (flags->crop_marks) {
265 print_crop_marks (pi);
269 print_label (pi, label,
273 flags->outline, flags->reverse);
275 i_label = (i_label + 1) % n_labels_per_page;
289 print_info_free (&pi);
291 gl_debug (DEBUG_PRINT, "END");
294 /*****************************************************************************/
295 /* Merge print command (uncollated copies) */
296 /*****************************************************************************/
298 gl_print_merge_uncollated (GnomePrintJob *job,
305 const GList *record_list;
307 const glTemplateLabelType *label_type;
308 gint i_sheet, i_label, n_labels_per_page, i_copy;
309 glMergeRecord *record;
311 glTemplateOrigin *origins;
313 gl_debug (DEBUG_PRINT, "START");
315 merge = gl_label_get_merge (label);
316 record_list = gl_merge_get_record_list (merge);
318 pi = print_info_new (job, label);
319 label_type = gl_template_get_first_label_type (pi->template);
321 n_labels_per_page = gl_template_get_n_labels (label_type);
322 origins = gl_template_get_origins (label_type);
327 for (i_copy = 0; i_copy < n_copies; i_copy++) {
329 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
330 record = (glMergeRecord *)p->data;
332 if ( record->select_flag ) {
335 if ((i_label == 0) || (i_sheet == 0)) {
337 print_page_begin (pi);
338 if (flags->crop_marks) {
339 print_crop_marks (pi);
343 print_label (pi, label,
347 flags->outline, flags->reverse);
349 i_label = (i_label + 1) % n_labels_per_page;
363 print_info_free (&pi);
365 gl_debug (DEBUG_PRINT, "END");
368 /*****************************************************************************/
369 /* Batch print. Call appropriate function above. */
370 /*****************************************************************************/
372 gl_print_batch (GnomePrintJob *job,
380 glTemplate *template;
381 const glTemplateLabelType *label_type;
384 gl_debug (DEBUG_PRINT, "START");
386 merge = gl_label_get_merge (label);
387 template = gl_label_get_template (label);
388 label_type = gl_template_get_first_label_type (template);
390 if ( merge == NULL ) {
391 n_per_page = gl_template_get_n_labels(label_type);
393 gl_print_simple (job, label, n_sheets, first, n_per_page, flags);
395 gl_print_merge_collated (job, label, n_copies, first, flags);
397 gl_template_free (template);
399 gl_debug (DEBUG_PRINT, "END");
402 /*---------------------------------------------------------------------------*/
403 /* PRIVATE. new print info structure */
404 /*---------------------------------------------------------------------------*/
406 print_info_new (GnomePrintJob *job,
409 PrintInfo *pi = g_new0 (PrintInfo, 1);
410 glTemplate *template;
412 gl_debug (DEBUG_PRINT, "START");
414 g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
415 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
417 template = gl_label_get_template (label);
419 g_return_val_if_fail (template, NULL);
420 g_return_val_if_fail (template->page_size, NULL);
421 g_return_val_if_fail (template->page_width > 0, NULL);
422 g_return_val_if_fail (template->page_height > 0, NULL);
424 pi->pc = gnome_print_job_get_context (job);
425 pi->config = gnome_print_job_get_config (job);
427 gl_debug (DEBUG_PRINT,
428 "setting page size = \"%s\"", template->page_size);
430 gnome_print_config_set_length (pi->config,
431 GNOME_PRINT_KEY_PAPER_WIDTH,
432 template->page_width,
433 GNOME_PRINT_PS_UNIT);
434 gnome_print_config_set_length (pi->config,
435 GNOME_PRINT_KEY_PAPER_HEIGHT,
436 template->page_height,
437 GNOME_PRINT_PS_UNIT);
439 pi->page_width = template->page_width;
440 pi->page_height = template->page_height;
442 pi->template = template;
443 pi->label_rotate_flag = gl_label_get_rotate_flag (label);
447 gl_debug (DEBUG_PRINT, "END");
452 /*---------------------------------------------------------------------------*/
453 /* PRIVATE. free print info structure */
454 /*---------------------------------------------------------------------------*/
456 print_info_free (PrintInfo **pi)
458 gl_debug (DEBUG_PRINT, "START");
460 gl_template_free ((*pi)->template);
461 (*pi)->template = NULL;
463 gnome_print_context_close ((*pi)->pc);
468 gl_debug (DEBUG_PRINT, "END");
471 /*---------------------------------------------------------------------------*/
472 /* PRIVATE. Begin a new page. */
473 /*---------------------------------------------------------------------------*/
475 print_page_begin (PrintInfo *pi)
479 gl_debug (DEBUG_PRINT, "START");
483 str = g_strdup_printf ("sheet%02d", pi->sheet);
484 gnome_print_beginpage (pi->pc, str);
487 /* Translate and scale, so that our origin is at the upper left. */
488 gnome_print_translate (pi->pc, 0.0, pi->page_height);
489 gnome_print_scale (pi->pc, 1.0, -1.0);
491 gl_debug (DEBUG_PRINT, "END");
494 /*---------------------------------------------------------------------------*/
495 /* PRIVATE. End a page. */
496 /*---------------------------------------------------------------------------*/
498 print_page_end (PrintInfo *pi)
500 gl_debug (DEBUG_PRINT, "START");
502 gnome_print_showpage (pi->pc);
504 gl_debug (DEBUG_PRINT, "END");
507 /*---------------------------------------------------------------------------*/
508 /* PRIVATE. Print crop tick marks. */
509 /*---------------------------------------------------------------------------*/
511 print_crop_marks (PrintInfo *pi)
513 const glTemplateLabelType *label_type;
514 gdouble w, h, page_w, page_h;
516 glTemplateLayout *layout;
517 gdouble xmin, ymin, xmax, ymax, dx, dy;
518 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
521 gl_debug (DEBUG_PRINT, "START");
523 label_type = gl_template_get_first_label_type (pi->template);
525 gl_template_get_label_size (label_type, &w, &h);
527 page_w = pi->page_width;
528 page_h = pi->page_height;
530 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
531 gnome_print_setopacity (pi->pc, 1.0);
532 gnome_print_setlinewidth (pi->pc, 0.25);
534 for (p=label_type->layouts; p != NULL; p=p->next) {
536 layout = (glTemplateLayout *)p->data;
540 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
541 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
549 for (ix=0; ix < nx; ix++) {
554 y1 = MAX((ymin - TICK_OFFSET), 0.0);
555 y2 = MAX((y1 - TICK_LENGTH), 0.0);
557 y3 = MIN((ymax + TICK_OFFSET), page_h);
558 y4 = MIN((y3 + TICK_LENGTH), page_h);
560 gnome_print_moveto (pi->pc, x1, y1);
561 gnome_print_lineto (pi->pc, x1, y2);
562 gnome_print_stroke (pi->pc);
564 gnome_print_moveto (pi->pc, x2, y1);
565 gnome_print_lineto (pi->pc, x2, y2);
566 gnome_print_stroke (pi->pc);
568 gnome_print_moveto (pi->pc, x1, y3);
569 gnome_print_lineto (pi->pc, x1, y4);
570 gnome_print_stroke (pi->pc);
572 gnome_print_moveto (pi->pc, x2, y3);
573 gnome_print_lineto (pi->pc, x2, y4);
574 gnome_print_stroke (pi->pc);
578 for (iy=0; iy < ny; iy++) {
583 x1 = MAX((xmin - TICK_OFFSET), 0.0);
584 x2 = MAX((x1 - TICK_LENGTH), 0.0);
586 x3 = MIN((xmax + TICK_OFFSET), page_w);
587 x4 = MIN((x3 + TICK_LENGTH), page_w);
589 gnome_print_moveto (pi->pc, x1, y1);
590 gnome_print_lineto (pi->pc, x2, y1);
591 gnome_print_stroke (pi->pc);
593 gnome_print_moveto (pi->pc, x1, y2);
594 gnome_print_lineto (pi->pc, x2, y2);
595 gnome_print_stroke (pi->pc);
597 gnome_print_moveto (pi->pc, x3, y1);
598 gnome_print_lineto (pi->pc, x4, y1);
599 gnome_print_stroke (pi->pc);
601 gnome_print_moveto (pi->pc, x3, y2);
602 gnome_print_lineto (pi->pc, x4, y2);
603 gnome_print_stroke (pi->pc);
609 gl_debug (DEBUG_PRINT, "END");
612 /*---------------------------------------------------------------------------*/
613 /* PRIVATE. Print i'th label. */
614 /*---------------------------------------------------------------------------*/
616 print_label (PrintInfo *pi,
620 glMergeRecord *record,
621 gboolean outline_flag,
622 gboolean reverse_flag)
624 const glTemplateLabelType *label_type;
625 gdouble width, height;
627 gl_debug (DEBUG_PRINT, "START");
629 label_type = gl_template_get_first_label_type (pi->template);
631 gl_label_get_size (label, &width, &height);
633 gnome_print_gsave (pi->pc);
635 /* Transform coordinate system to be relative to upper corner */
636 /* of the current label */
637 gnome_print_translate (pi->pc, x, y);
638 if (gl_label_get_rotate_flag (label)) {
639 gl_debug (DEBUG_PRINT, "Rotate flag set");
640 gnome_print_rotate (pi->pc, -90.0);
641 gnome_print_translate (pi->pc, -width, 0.0);
643 if ( reverse_flag ) {
644 gnome_print_translate (pi->pc, width, 0.0);
645 gnome_print_scale (pi->pc, -1.0, 1.0);
648 clip_to_outline (pi, label);
649 draw_label (pi, label, record);
651 draw_outline (pi, label);
653 clip_punchouts (pi, label);
655 gnome_print_grestore (pi->pc);
657 gl_debug (DEBUG_PRINT, "END");
660 /*---------------------------------------------------------------------------*/
661 /* PRIVATE. Draw label. */
662 /*---------------------------------------------------------------------------*/
664 draw_label (PrintInfo *pi,
666 glMergeRecord *record)
669 glLabelObject *object;
671 gl_debug (DEBUG_PRINT, "START");
673 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
674 object = (glLabelObject *) p_obj->data;
676 draw_object (pi, object, record);
679 gl_debug (DEBUG_PRINT, "END");
682 /*---------------------------------------------------------------------------*/
683 /* PRIVATE. Draw object. */
684 /*---------------------------------------------------------------------------*/
686 draw_object (PrintInfo *pi,
687 glLabelObject *object,
688 glMergeRecord *record)
693 gl_debug (DEBUG_PRINT, "START");
695 gl_label_object_get_position (object, &x0, &y0);
696 gl_label_object_get_affine (object, affine);
698 gnome_print_gsave (pi->pc);
700 gnome_print_translate (pi->pc, x0, y0);
701 gnome_print_concat (pi->pc, affine);
703 if (GL_IS_LABEL_TEXT(object)) {
704 draw_text_object (pi, GL_LABEL_TEXT(object), record);
705 } else if (GL_IS_LABEL_BOX(object)) {
706 draw_box_object (pi, GL_LABEL_BOX(object), record);
707 } else if (GL_IS_LABEL_LINE(object)) {
708 draw_line_object (pi, GL_LABEL_LINE(object), record);
709 } else if (GL_IS_LABEL_ELLIPSE(object)) {
710 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object), record);
711 } else if (GL_IS_LABEL_IMAGE(object)) {
712 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
713 } else if (GL_IS_LABEL_BARCODE(object)) {
714 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
717 gnome_print_grestore (pi->pc);
719 gl_debug (DEBUG_PRINT, "END");
722 /*---------------------------------------------------------------------------*/
723 /* PRIVATE. Draw text object. */
724 /*---------------------------------------------------------------------------*/
726 draw_text_object (PrintInfo *pi,
728 glMergeRecord *record)
733 gdouble x_offset, y_offset, w, object_w, object_h;
738 GnomeFontWeight font_weight;
739 gboolean font_italic_flag;
741 glColorNode *color_node;
742 GtkJustification just;
743 gboolean auto_shrink;
744 GnomeGlyphList *glyphlist;
747 gdouble text_line_spacing;
750 gl_debug (DEBUG_PRINT, "START");
752 gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
753 lines = gl_label_text_get_lines (object);
754 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
755 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
756 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
757 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
759 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
760 color = gl_color_node_expand (color_node, record);
761 gl_color_node_free (&color_node);
763 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
765 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
766 auto_shrink = gl_label_text_get_auto_shrink (object);
768 text = gl_text_node_lines_expand (lines, record);
769 line = g_strsplit (text, "\n", -1);
772 art_affine_identity (affine);
774 if (record && auto_shrink) {
775 /* auto shrink text size to keep within text box limits. */
776 for (i = 0; line[i] != NULL; i++) {
778 font = gnome_font_find_closest_from_weight_slant (font_family,
782 glyphlist = gnome_glyphlist_from_text_dumb (font,
786 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
788 gnome_glyphlist_unref (glyphlist);
790 /* If width is too large, iteratively shrink font_size until this
791 line fits the width, or until the font size is ridiculously
793 while ( (w > object_w) && (font_size >= 1.0) ) {
797 font = gnome_font_find_closest_from_weight_slant (
802 glyphlist = gnome_glyphlist_from_text_dumb (font,
806 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
808 gnome_glyphlist_unref (glyphlist);
814 font = gnome_font_find_closest_from_weight_slant (
819 gnome_print_setfont (pi->pc, font);
821 gnome_print_setrgbcolor (pi->pc,
822 GL_COLOR_F_RED (color),
823 GL_COLOR_F_GREEN (color),
824 GL_COLOR_F_BLUE (color));
825 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
827 for (i = 0; line[i] != NULL; i++) {
829 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
833 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
835 gnome_glyphlist_unref (glyphlist);
838 case GTK_JUSTIFY_LEFT:
839 x_offset = GL_LABEL_TEXT_MARGIN;
841 case GTK_JUSTIFY_CENTER:
842 x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
844 case GTK_JUSTIFY_RIGHT:
845 x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
849 break; /* shouldn't happen */
852 /* Work out the y position to the BOTTOM of the first line */
853 y_offset = GL_LABEL_TEXT_MARGIN +
854 + gnome_font_get_descender (font)
855 + (i + 1) * font_size * text_line_spacing;
857 /* Remove any text line spacing from the first row. */
858 y_offset -= font_size * (text_line_spacing - 1);
861 gnome_print_moveto (pi->pc, x_offset, y_offset);
863 gnome_print_gsave (pi->pc);
864 gnome_print_scale (pi->pc, 1.0, -1.0);
865 gnome_print_show (pi->pc, line[i]);
866 gnome_print_grestore (pi->pc);
871 gl_text_node_lines_free (&lines);
872 g_free (font_family);
874 gl_debug (DEBUG_PRINT, "END");
877 /*---------------------------------------------------------------------------*/
878 /* PRIVATE. Draw box object. */
879 /*---------------------------------------------------------------------------*/
881 draw_box_object (PrintInfo *pi,
883 glMergeRecord *record)
888 glColorNode *line_color_node;
889 glColorNode *fill_color_node;
892 gl_debug (DEBUG_PRINT, "START");
894 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
895 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
897 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
898 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
899 line_color = gl_color_node_expand (line_color_node, record);
900 fill_color = gl_color_node_expand (fill_color_node, record);
901 gl_color_node_free (&line_color_node);
902 gl_color_node_free (&fill_color_node);
904 /* Paint fill color */
905 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
906 gnome_print_setrgbcolor (pi->pc,
907 GL_COLOR_F_RED (fill_color),
908 GL_COLOR_F_GREEN (fill_color),
909 GL_COLOR_F_BLUE (fill_color));
910 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
911 gnome_print_fill (pi->pc);
914 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
915 gnome_print_setrgbcolor (pi->pc,
916 GL_COLOR_F_RED (line_color),
917 GL_COLOR_F_GREEN (line_color),
918 GL_COLOR_F_BLUE (line_color));
919 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
920 gnome_print_setlinewidth (pi->pc, line_width);
921 gnome_print_stroke (pi->pc);
923 gl_debug (DEBUG_PRINT, "END");
926 /*---------------------------------------------------------------------------*/
927 /* PRIVATE. Draw line object. */
928 /*---------------------------------------------------------------------------*/
930 draw_line_object (PrintInfo *pi,
932 glMergeRecord *record)
937 glColorNode *line_color_node;
939 gl_debug (DEBUG_PRINT, "START");
941 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
942 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
944 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
945 line_color = gl_color_node_expand (line_color_node, record);
946 gl_color_node_free (&line_color_node);
948 gnome_print_moveto (pi->pc, 0.0, 0.0);
949 gnome_print_lineto (pi->pc, w, h);
950 gnome_print_setrgbcolor (pi->pc,
951 GL_COLOR_F_RED (line_color),
952 GL_COLOR_F_GREEN (line_color),
953 GL_COLOR_F_BLUE (line_color));
954 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
955 gnome_print_setlinewidth (pi->pc, line_width);
956 gnome_print_stroke (pi->pc);
958 gl_debug (DEBUG_PRINT, "END");
961 /*---------------------------------------------------------------------------*/
962 /* PRIVATE. Draw ellipse object. */
963 /*---------------------------------------------------------------------------*/
965 draw_ellipse_object (PrintInfo *pi,
966 glLabelEllipse *object,
967 glMergeRecord *record)
969 gdouble x0, y0, rx, ry, w, h;
971 glColorNode *line_color_node;
972 glColorNode *fill_color_node;
976 gl_debug (DEBUG_PRINT, "START");
978 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
979 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
981 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
982 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
983 line_color = gl_color_node_expand (line_color_node, record);
984 fill_color = gl_color_node_expand (fill_color_node, record);
985 gl_color_node_free (&line_color_node);
986 gl_color_node_free (&fill_color_node);
993 /* Paint fill color */
994 create_ellipse_path (pi->pc, x0, y0, rx, ry);
995 gnome_print_setrgbcolor (pi->pc,
996 GL_COLOR_F_RED (fill_color),
997 GL_COLOR_F_GREEN (fill_color),
998 GL_COLOR_F_BLUE (fill_color));
999 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
1000 gnome_print_fill (pi->pc);
1003 create_ellipse_path (pi->pc, x0, y0, rx, ry);
1004 gnome_print_setrgbcolor (pi->pc,
1005 GL_COLOR_F_RED (line_color),
1006 GL_COLOR_F_GREEN (line_color),
1007 GL_COLOR_F_BLUE (line_color));
1008 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
1009 gnome_print_setlinewidth (pi->pc, line_width);
1010 gnome_print_stroke (pi->pc);
1012 gl_debug (DEBUG_PRINT, "END");
1015 /*---------------------------------------------------------------------------*/
1016 /* PRIVATE. Draw image object. */
1017 /*---------------------------------------------------------------------------*/
1019 draw_image_object (PrintInfo *pi,
1020 glLabelImage *object,
1021 glMergeRecord *record)
1024 const GdkPixbuf *pixbuf;
1026 gint image_w, image_h, image_stride;
1027 gboolean image_alpha_flag;
1030 gl_debug (DEBUG_PRINT, "START");
1032 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1034 pixbuf = gl_label_image_get_pixbuf (object, record);
1035 image_data = gdk_pixbuf_get_pixels (pixbuf);
1036 image_w = gdk_pixbuf_get_width (pixbuf);
1037 image_h = gdk_pixbuf_get_height (pixbuf);
1038 image_stride = gdk_pixbuf_get_rowstride(pixbuf);
1039 image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
1041 gnome_print_gsave (pi->pc);
1042 gnome_print_translate (pi->pc, 0.0, h);
1043 gnome_print_scale (pi->pc, w, -h);
1044 if (image_alpha_flag) {
1045 #ifndef NO_ALPHA_HACK
1046 guchar *image_data2;
1048 image_data2 = get_pixels_as_rgb (pixbuf);
1049 ret = gnome_print_rgbimage (pi->pc, image_data2,
1050 image_w, image_h, image_stride);
1051 g_free (image_data2);
1053 ret = gnome_print_rgbaimage (pi->pc, image_data,
1054 image_w, image_h, image_stride);
1057 ret = gnome_print_rgbimage (pi->pc, image_data,
1058 image_w, image_h, image_stride);
1060 gnome_print_grestore (pi->pc);
1062 gl_debug (DEBUG_PRINT, "END");
1065 /*---------------------------------------------------------------------------*/
1066 /* PRIVATE. Draw box object. */
1067 /*---------------------------------------------------------------------------*/
1069 draw_barcode_object (PrintInfo *pi,
1070 glLabelBarcode *object,
1071 glMergeRecord *record)
1074 glBarcodeLine *line;
1075 glBarcodeChar *bchar;
1079 gchar *text, *cstring;
1080 glTextNode *text_node;
1083 gboolean checksum_flag;
1085 glColorNode *color_node;
1086 guint format_digits;
1089 gl_debug (DEBUG_PRINT, "START");
1091 text_node = gl_label_barcode_get_data (object);
1092 gl_label_barcode_get_props (object,
1093 &id, &text_flag, &checksum_flag, &format_digits);
1095 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1096 color = gl_color_node_expand (color_node, record);
1097 gl_color_node_free (&color_node);
1099 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1101 text = gl_text_node_expand (text_node, record);
1102 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1104 gl_text_node_free (&text_node);
1109 font = gnome_font_find_closest_from_weight_slant (
1110 GL_BARCODE_FONT_FAMILY,
1111 GL_BARCODE_FONT_WEIGHT,
1113 gnome_print_setfont (pi->pc, font);
1115 gnome_print_setrgbcolor (pi->pc,
1116 GL_COLOR_F_RED (color),
1117 GL_COLOR_F_GREEN (color),
1118 GL_COLOR_F_BLUE (color));
1119 gnome_print_setopacity (pi->pc,
1120 GL_COLOR_F_ALPHA (color));
1122 y_offset = 12.0 - fabs (gnome_font_get_descender (font));
1123 gnome_print_moveto (pi->pc, 0.0, y_offset);
1125 gnome_print_gsave (pi->pc);
1126 gnome_print_scale (pi->pc, 1.0, -1.0);
1127 gnome_print_show (pi->pc, _("Invalid barcode data"));
1128 gnome_print_grestore (pi->pc);
1132 for (li = gbc->lines; li != NULL; li = li->next) {
1133 line = (glBarcodeLine *) li->data;
1135 gnome_print_moveto (pi->pc, line->x, line->y);
1136 gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1137 gnome_print_setrgbcolor (pi->pc,
1138 GL_COLOR_F_RED (color),
1139 GL_COLOR_F_GREEN (color),
1140 GL_COLOR_F_BLUE (color));
1141 gnome_print_setopacity (pi->pc,
1142 GL_COLOR_F_ALPHA (color));
1143 gnome_print_setlinewidth (pi->pc, line->width);
1144 gnome_print_stroke (pi->pc);
1147 for (li = gbc->chars; li != NULL; li = li->next) {
1148 bchar = (glBarcodeChar *) li->data;
1150 font = gnome_font_find_closest_from_weight_slant (
1151 GL_BARCODE_FONT_FAMILY,
1152 GL_BARCODE_FONT_WEIGHT,
1153 FALSE, bchar->fsize);
1154 gnome_print_setfont (pi->pc, font);
1156 gnome_print_setrgbcolor (pi->pc,
1157 GL_COLOR_F_RED (color),
1158 GL_COLOR_F_GREEN (color),
1159 GL_COLOR_F_BLUE (color));
1160 gnome_print_setopacity (pi->pc,
1161 GL_COLOR_F_ALPHA (color));
1164 bchar->fsize - fabs (gnome_font_get_descender (font));
1166 gnome_print_moveto (pi->pc, bchar->x, bchar->y+y_offset);
1168 cstring = g_strdup_printf ("%c", bchar->c);
1169 gnome_print_gsave (pi->pc);
1170 gnome_print_scale (pi->pc, 1.0, -1.0);
1171 gnome_print_show (pi->pc, cstring);
1172 gnome_print_grestore (pi->pc);
1177 gl_barcode_free (&gbc);
1181 gl_debug (DEBUG_PRINT, "END");
1184 /*---------------------------------------------------------------------------*/
1185 /* PRIVATE. Draw outline. */
1186 /*---------------------------------------------------------------------------*/
1188 draw_outline (PrintInfo *pi,
1191 const glTemplateLabelType *label_type;
1195 gl_debug (DEBUG_PRINT, "START");
1197 label_type = gl_template_get_first_label_type (pi->template);
1199 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
1200 gnome_print_setopacity (pi->pc, 1.0);
1201 gnome_print_setlinewidth (pi->pc, 0.25);
1203 switch (label_type->shape) {
1205 case GL_TEMPLATE_SHAPE_RECT:
1206 gl_label_get_size (label, &w, &h);
1207 r = label_type->size.rect.r;
1209 /* simple rectangle */
1210 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1212 /* rectangle with rounded corners */
1213 create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1216 gnome_print_stroke (pi->pc);
1219 case GL_TEMPLATE_SHAPE_ROUND:
1221 r1 = label_type->size.round.r;
1222 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1223 gnome_print_stroke (pi->pc);
1226 case GL_TEMPLATE_SHAPE_CD:
1227 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1228 /* CD style, round label w/ concentric round hole */
1229 r1 = label_type->size.cd.r1;
1230 r2 = label_type->size.cd.r2;
1231 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1232 gnome_print_stroke (pi->pc);
1233 create_ellipse_path (pi->pc, r1, r1, r2, r2);
1234 gnome_print_stroke (pi->pc);
1236 /* Business Card CD style, clipped round label w/ hole */
1237 gl_label_get_size (label, &w, &h);
1238 r1 = label_type->size.cd.r1;
1239 r2 = label_type->size.cd.r2;
1240 create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1241 gnome_print_stroke (pi->pc);
1242 create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1243 gnome_print_stroke (pi->pc);
1248 g_warning ("Unknown template label style");
1252 gl_debug (DEBUG_PRINT, "END");
1255 /*---------------------------------------------------------------------------*/
1256 /* PRIVATE. Clip to outline. */
1257 /*---------------------------------------------------------------------------*/
1259 clip_to_outline (PrintInfo *pi,
1262 const glTemplateLabelType *label_type;
1265 gdouble waste, x_waste, y_waste;
1267 gl_debug (DEBUG_PRINT, "START");
1269 label_type = gl_template_get_first_label_type (pi->template);
1271 switch (label_type->shape) {
1273 case GL_TEMPLATE_SHAPE_RECT:
1274 gl_label_get_size (label, &w, &h);
1275 r = label_type->size.rect.r;
1276 x_waste = label_type->size.rect.x_waste;
1277 y_waste = label_type->size.rect.y_waste;
1279 /* simple rectangle */
1280 create_rectangle_path (pi->pc,
1282 w+2*x_waste, h+2*y_waste);
1284 /* rectangle with rounded corners */
1285 create_rounded_rectangle_path (pi->pc,
1287 w+2*x_waste, h+2*y_waste, r);
1289 gnome_print_clip (pi->pc);
1292 case GL_TEMPLATE_SHAPE_ROUND:
1293 r1 = label_type->size.round.r;
1294 waste = label_type->size.round.waste;
1295 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1296 gnome_print_clip (pi->pc);
1299 case GL_TEMPLATE_SHAPE_CD:
1300 waste = label_type->size.cd.waste;
1301 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1302 /* CD style, round label w/ concentric round hole */
1303 r1 = label_type->size.cd.r1;
1304 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1306 /* Business Card CD style, clipped round label w/ hole */
1307 gl_label_get_size (label, &w, &h);
1308 r1 = label_type->size.cd.r1;
1309 create_clipped_circle_path (pi->pc,
1311 w+2*waste, h+2*waste,
1314 gnome_print_clip (pi->pc);
1318 g_warning ("Unknown template label style");
1322 gl_debug (DEBUG_PRINT, "END");
1325 /*---------------------------------------------------------------------------*/
1326 /* PRIVATE. Clip punchouts. (Save some ink by not printing in CD holes) */
1328 /* Ideally this would be done in clip_to_outline, but I am not sure how to */
1329 /* invert the region for gnome_print_clip, so instead, I will just draw */
1330 /* a white circle on top of everything else. */
1331 /*---------------------------------------------------------------------------*/
1333 clip_punchouts (PrintInfo *pi,
1336 const glTemplateLabelType *label_type;
1340 gl_debug (DEBUG_PRINT, "START");
1342 label_type = gl_template_get_first_label_type (pi->template);
1344 switch (label_type->shape) {
1346 case GL_TEMPLATE_SHAPE_RECT:
1347 case GL_TEMPLATE_SHAPE_ROUND:
1350 case GL_TEMPLATE_SHAPE_CD:
1351 gl_label_get_size (label, &w, &h);
1352 waste = label_type->size.cd.waste;
1353 r2 = label_type->size.cd.r2;
1354 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1355 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1356 gnome_print_setopacity (pi->pc, 1.0);
1357 gnome_print_fill (pi->pc);
1361 g_warning ("Unknown template label style");
1365 gl_debug (DEBUG_PRINT, "END");
1368 /*---------------------------------------------------------------------------*/
1369 /* PRIVATE. Path creation utilities. */
1370 /*---------------------------------------------------------------------------*/
1372 create_rectangle_path (GnomePrintContext *pc,
1378 gl_debug (DEBUG_PRINT, "START");
1380 gnome_print_newpath (pc);
1381 gnome_print_moveto (pc, x0, y0);
1382 gnome_print_lineto (pc, x0 + w, y0);
1383 gnome_print_lineto (pc, x0 + w, y0 + h);
1384 gnome_print_lineto (pc, x0, y0 + h);
1385 gnome_print_lineto (pc, x0, y0);
1386 gnome_print_closepath (pc);
1388 gl_debug (DEBUG_PRINT, "END");
1392 create_ellipse_path (GnomePrintContext *pc,
1401 gl_debug (DEBUG_PRINT, "START");
1403 gnome_print_newpath (pc);
1404 gnome_print_moveto (pc, x0 + rx, y0);
1405 for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1406 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1407 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1408 gnome_print_lineto (pc, x, y);
1410 gnome_print_closepath (pc);
1412 gl_debug (DEBUG_PRINT, "END");
1416 create_rounded_rectangle_path (GnomePrintContext *pc,
1426 gl_debug (DEBUG_PRINT, "START");
1428 gnome_print_newpath (pc);
1430 gnome_print_moveto (pc, x0 + r, y0);
1431 for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1432 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1433 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1434 gnome_print_lineto (pc, x, y);
1436 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1437 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1438 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1439 gnome_print_lineto (pc, x, y);
1441 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1442 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1443 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1444 gnome_print_lineto (pc, x, y);
1446 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1447 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1448 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1449 gnome_print_lineto (pc, x, y);
1451 gnome_print_lineto (pc, x0 + r, y0);
1453 gnome_print_closepath (pc);
1455 gl_debug (DEBUG_PRINT, "END");
1459 create_clipped_circle_path (GnomePrintContext *pc,
1467 gdouble theta1, theta2;
1470 gl_debug (DEBUG_PRINT, "START");
1472 theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1473 theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1475 gnome_print_newpath (pc);
1477 x = x0 + r * cos (theta1 * G_PI / 180.0);
1478 y = y0 + r * sin (theta1 * G_PI / 180.0);
1479 gnome_print_moveto (pc, x, y);
1481 for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1482 x = x0 + r * cos (i_theta * G_PI / 180.0);
1483 y = y0 + r * sin (i_theta * G_PI / 180.0);
1484 gnome_print_lineto (pc, x, y);
1487 x = x0 + r * cos (theta2 * G_PI / 180.0);
1488 y = y0 + r * sin (theta2 * G_PI / 180.0);
1489 gnome_print_lineto (pc, x, y);
1491 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1492 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1493 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1494 gnome_print_lineto (pc, x, y);
1497 for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1498 x = x0 + r * cos (i_theta * G_PI / 180.0);
1499 y = y0 + r * sin (i_theta * G_PI / 180.0);
1500 gnome_print_lineto (pc, x, y);
1503 x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1504 y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1505 gnome_print_lineto (pc, x, y);
1507 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1508 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1509 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1510 gnome_print_lineto (pc, x, y);
1513 for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1514 x = x0 + r * cos (i_theta * G_PI / 180.0);
1515 y = y0 + r * sin (i_theta * G_PI / 180.0);
1516 gnome_print_lineto (pc, x, y);
1519 x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1520 y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1521 gnome_print_lineto (pc, x, y);
1523 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1524 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1525 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1526 gnome_print_lineto (pc, x, y);
1529 for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1530 x = x0 + r * cos (i_theta * G_PI / 180.0);
1531 y = y0 + r * sin (i_theta * G_PI / 180.0);
1532 gnome_print_lineto (pc, x, y);
1535 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1536 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1537 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1538 gnome_print_lineto (pc, x, y);
1541 x = x0 + r * cos (theta1 * G_PI / 180.0);
1542 y = y0 + r * sin (theta1 * G_PI / 180.0);
1543 gnome_print_lineto (pc, x, y);
1545 gnome_print_closepath (pc);
1547 gl_debug (DEBUG_PRINT, "END");
1550 #ifndef NO_ALPHA_HACK
1551 /*---------------------------------------------------------------------------*/
1552 /* PRIVATE. Extract a copy of rgba pixels, removing alpha by compositing */
1553 /* with a white background. */
1555 /* This is currently needed due to the lousy job gnome-print does in */
1556 /* rendering images with alpha channels to PS. This sacrafices the ability */
1557 /* to do compositing of images with other items in the background. */
1558 /*---------------------------------------------------------------------------*/
1560 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1562 gint bits_per_sample, channels;
1564 gint width, height, rowstride;
1566 guchar *buf_src, *buf_dest;
1567 guchar *p_src, *p_dest;
1570 gdouble alpha, beta;
1572 gl_debug (DEBUG_PRINT, "START");
1574 g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1576 /* extract pixels and parameters from pixbuf. */
1577 buf_src = gdk_pixbuf_get_pixels (pixbuf);
1578 bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1579 channels = gdk_pixbuf_get_n_channels (pixbuf);
1580 has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
1581 width = gdk_pixbuf_get_width (pixbuf);
1582 height = gdk_pixbuf_get_height (pixbuf);
1583 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1585 /* validate assumptions about pixbuf. */
1586 g_return_val_if_fail (buf_src, NULL);
1587 g_return_val_if_fail (bits_per_sample == 8, NULL);
1588 g_return_val_if_fail (channels == 4, NULL);
1589 g_return_val_if_fail (has_alpha, NULL);
1590 g_return_val_if_fail (width > 0, NULL);
1591 g_return_val_if_fail (height > 0, NULL);
1592 g_return_val_if_fail (rowstride > 0, NULL);
1594 /* Allocate a destination buffer */
1595 bytes = height * rowstride;
1596 gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1597 buf_dest = g_try_malloc (bytes);
1601 gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1603 /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1606 for ( iy=0; iy < height; iy++ ) {
1608 p_src = buf_src + iy*rowstride;
1609 p_dest = buf_dest + iy*rowstride;
1611 for ( ix=0; ix < width; ix++ ) {
1621 *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1622 *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1623 *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1629 gl_debug (DEBUG_PRINT, "START");