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
31 #include "label-text.h"
32 #include "label-box.h"
33 #include "label-line.h"
34 #include "label-ellipse.h"
35 #include "label-image.h"
36 #include "label-barcode.h"
43 #define ARC_FINE 2 /* Resolution in degrees of large arcs */
44 #define ARC_COURSE 5 /* Resolution in degrees of small arcs */
46 #define TICK_OFFSET 2.25
47 #define TICK_LENGTH 18.0
49 /*=========================================================================*/
51 /*=========================================================================*/
53 typedef struct _PrintInfo {
54 /* gnome print context */
55 GnomePrintContext *pc;
57 /* gnome print configuration */
58 GnomePrintConfig *config;
60 /* gLabels Template */
62 gboolean label_rotate_flag;
73 /*=========================================================================*/
74 /* Private function prototypes. */
75 /*=========================================================================*/
76 static PrintInfo *print_info_new (GnomePrintJob *job,
79 static void print_info_free (PrintInfo **pi);
82 static void print_page_begin (PrintInfo *pi);
84 static void print_page_end (PrintInfo *pi);
86 static void print_crop_marks (PrintInfo *pi);
88 static void print_label (PrintInfo *pi,
92 glMergeRecord *record,
93 gboolean outline_flag,
94 gboolean reverse_flag);
97 static void draw_label (PrintInfo *pi,
99 glMergeRecord *record);
102 static void draw_object (PrintInfo *pi,
103 glLabelObject *object,
104 glMergeRecord *record);
106 static void draw_text_object (PrintInfo *pi,
108 glMergeRecord *record);
110 static void draw_box_object (PrintInfo *pi,
113 static void draw_line_object (PrintInfo *pi,
114 glLabelLine *object);
116 static void draw_ellipse_object (PrintInfo *pi,
117 glLabelEllipse *object);
119 static void draw_image_object (PrintInfo *pi,
120 glLabelImage *object,
121 glMergeRecord *record);
123 static void draw_barcode_object (PrintInfo *pi,
124 glLabelBarcode *object,
125 glMergeRecord *record);
128 static void draw_outline (PrintInfo *pi,
131 static void clip_to_outline (PrintInfo *pi,
134 static void clip_punchouts (PrintInfo *pi,
138 static void create_rectangle_path (GnomePrintContext *pc,
144 static void create_ellipse_path (GnomePrintContext *pc,
150 static void create_rounded_rectangle_path (GnomePrintContext *pc,
157 static void create_clipped_circle_path (GnomePrintContext *pc,
164 #ifndef NO_ALPHA_HACK
165 static guchar * get_pixels_as_rgb (const GdkPixbuf *pixbuf);
169 /*****************************************************************************/
170 /* Simple (no merge data) print command. */
171 /*****************************************************************************/
173 gl_print_simple (GnomePrintJob *job,
181 gint i_sheet, i_label;
182 glTemplateOrigin *origins;
184 gl_debug (DEBUG_PRINT, "START");
186 pi = print_info_new (job, label);
188 origins = gl_template_get_origins (pi->template);
190 for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
192 print_page_begin (pi);
193 if (flags->crop_marks) {
194 print_crop_marks (pi);
197 for (i_label = first - 1; i_label < last; i_label++) {
199 print_label (pi, label,
200 origins[i_label].x, origins[i_label].y,
201 NULL, flags->outline, flags->reverse);
210 print_info_free (&pi);
212 gl_debug (DEBUG_PRINT, "END");
215 /*****************************************************************************/
216 /* Merge print command (collated copies) */
217 /*****************************************************************************/
219 gl_print_merge_collated (GnomePrintJob *job,
226 const GList *record_list;
228 gint i_sheet, i_label, n_labels_per_page, i_copy;
229 glMergeRecord *record;
231 glTemplateOrigin *origins;
233 gl_debug (DEBUG_PRINT, "START");
235 merge = gl_label_get_merge (label);
236 record_list = gl_merge_get_record_list (merge);
238 pi = print_info_new (job, label);
240 n_labels_per_page = gl_template_get_n_labels (pi->template);
241 origins = gl_template_get_origins (pi->template);
246 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
247 record = (glMergeRecord *)p->data;
249 if ( record->select_flag ) {
250 for (i_copy = 0; i_copy < n_copies; i_copy++) {
252 if ((i_label == 0) || (i_sheet == 0)) {
254 print_page_begin (pi);
255 if (flags->crop_marks) {
256 print_crop_marks (pi);
260 print_label (pi, label,
264 flags->outline, flags->reverse);
266 i_label = (i_label + 1) % n_labels_per_page;
280 print_info_free (&pi);
282 gl_debug (DEBUG_PRINT, "END");
285 /*****************************************************************************/
286 /* Merge print command (uncollated copies) */
287 /*****************************************************************************/
289 gl_print_merge_uncollated (GnomePrintJob *job,
296 const GList *record_list;
298 gint i_sheet, i_label, n_labels_per_page, i_copy;
299 glMergeRecord *record;
301 glTemplateOrigin *origins;
303 gl_debug (DEBUG_PRINT, "START");
305 merge = gl_label_get_merge (label);
306 record_list = gl_merge_get_record_list (merge);
308 pi = print_info_new (job, label);
310 n_labels_per_page = gl_template_get_n_labels (pi->template);
311 origins = gl_template_get_origins (pi->template);
316 for (i_copy = 0; i_copy < n_copies; i_copy++) {
318 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
319 record = (glMergeRecord *)p->data;
321 if ( record->select_flag ) {
324 if ((i_label == 0) || (i_sheet == 0)) {
326 print_page_begin (pi);
327 if (flags->crop_marks) {
328 print_crop_marks (pi);
332 print_label (pi, label,
336 flags->outline, flags->reverse);
338 i_label = (i_label + 1) % n_labels_per_page;
352 print_info_free (&pi);
354 gl_debug (DEBUG_PRINT, "END");
357 /*****************************************************************************/
358 /* Batch print. Call appropriate function above. */
359 /*****************************************************************************/
361 gl_print_batch (GnomePrintJob *job,
369 glTemplate *template;
371 gl_debug (DEBUG_PRINT, "START");
373 merge = gl_label_get_merge (label);
374 template = gl_label_get_template (label);
376 if ( merge == NULL ) {
377 n_per_page = gl_template_get_n_labels(template);
379 gl_print_simple (job, label, n_sheets, 1, n_per_page, flags);
381 gl_print_merge_collated (job, label, n_copies, 1, flags);
383 gl_template_free (&template);
385 gl_debug (DEBUG_PRINT, "END");
388 /*---------------------------------------------------------------------------*/
389 /* PRIVATE. new print info structure */
390 /*---------------------------------------------------------------------------*/
392 print_info_new (GnomePrintJob *job,
395 PrintInfo *pi = g_new0 (PrintInfo, 1);
396 glTemplate *template;
398 gl_debug (DEBUG_PRINT, "START");
400 g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
401 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
403 template = gl_label_get_template (label);
405 g_return_val_if_fail (template, NULL);
406 g_return_val_if_fail (template->page_size, NULL);
407 g_return_val_if_fail (template->page_width > 0, NULL);
408 g_return_val_if_fail (template->page_height > 0, NULL);
410 pi->pc = gnome_print_job_get_context (job);
411 pi->config = gnome_print_job_get_config (job);
413 gl_debug (DEBUG_PRINT,
414 "setting page size = \"%s\"", template->page_size);
416 gnome_print_config_set_length (pi->config,
417 GNOME_PRINT_KEY_PAPER_WIDTH,
418 template->page_width,
419 GNOME_PRINT_PS_UNIT);
420 gnome_print_config_set_length (pi->config,
421 GNOME_PRINT_KEY_PAPER_HEIGHT,
422 template->page_height,
423 GNOME_PRINT_PS_UNIT);
425 pi->page_width = template->page_width;
426 pi->page_height = template->page_height;
428 pi->template = template;
429 pi->label_rotate_flag = gl_label_get_rotate_flag (label);
433 gl_debug (DEBUG_PRINT, "END");
438 /*---------------------------------------------------------------------------*/
439 /* PRIVATE. free print info structure */
440 /*---------------------------------------------------------------------------*/
442 print_info_free (PrintInfo **pi)
444 gl_debug (DEBUG_PRINT, "START");
446 gl_template_free (&(*pi)->template);
448 gnome_print_context_close ((*pi)->pc);
453 gl_debug (DEBUG_PRINT, "END");
456 /*---------------------------------------------------------------------------*/
457 /* PRIVATE. Begin a new page. */
458 /*---------------------------------------------------------------------------*/
460 print_page_begin (PrintInfo *pi)
464 gl_debug (DEBUG_PRINT, "START");
468 str = g_strdup_printf ("sheet%02d", pi->sheet);
469 gnome_print_beginpage (pi->pc, str);
472 /* Translate and scale, so that our origin is at the upper left. */
473 gnome_print_translate (pi->pc, 0.0, pi->page_height);
474 gnome_print_scale (pi->pc, 1.0, -1.0);
476 gl_debug (DEBUG_PRINT, "END");
479 /*---------------------------------------------------------------------------*/
480 /* PRIVATE. End a page. */
481 /*---------------------------------------------------------------------------*/
483 print_page_end (PrintInfo *pi)
485 gl_debug (DEBUG_PRINT, "START");
487 gnome_print_showpage (pi->pc);
489 gl_debug (DEBUG_PRINT, "END");
492 /*---------------------------------------------------------------------------*/
493 /* PRIVATE. Print crop tick marks. */
494 /*---------------------------------------------------------------------------*/
496 print_crop_marks (PrintInfo *pi)
498 gdouble w, h, page_w, page_h;
500 glTemplateLayout *layout;
501 gdouble xmin, ymin, xmax, ymax, dx, dy;
502 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
505 gl_debug (DEBUG_PRINT, "START");
507 gl_template_get_label_size (pi->template, &w, &h);
509 page_w = pi->page_width;
510 page_h = pi->page_height;
512 gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
513 gnome_print_setopacity (pi->pc, 1.0);
514 gnome_print_setlinewidth (pi->pc, 0.25);
516 for (p=pi->template->label.any.layouts; p != NULL; p=p->next) {
518 layout = (glTemplateLayout *)p->data;
522 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
523 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
531 for (ix=0; ix < nx; ix++) {
536 y1 = MAX((ymin - TICK_OFFSET), 0.0);
537 y2 = MAX((y1 - TICK_LENGTH), 0.0);
539 y3 = MIN((ymax + TICK_OFFSET), page_h);
540 y4 = MIN((y3 + TICK_LENGTH), page_h);
542 gnome_print_moveto (pi->pc, x1, y1);
543 gnome_print_lineto (pi->pc, x1, y2);
544 gnome_print_stroke (pi->pc);
546 gnome_print_moveto (pi->pc, x2, y1);
547 gnome_print_lineto (pi->pc, x2, y2);
548 gnome_print_stroke (pi->pc);
550 gnome_print_moveto (pi->pc, x1, y3);
551 gnome_print_lineto (pi->pc, x1, y4);
552 gnome_print_stroke (pi->pc);
554 gnome_print_moveto (pi->pc, x2, y3);
555 gnome_print_lineto (pi->pc, x2, y4);
556 gnome_print_stroke (pi->pc);
560 for (iy=0; iy < ny; iy++) {
565 x1 = MAX((xmin - TICK_OFFSET), 0.0);
566 x2 = MAX((x1 - TICK_LENGTH), 0.0);
568 x3 = MIN((xmax + TICK_OFFSET), page_w);
569 x4 = MIN((x3 + TICK_LENGTH), page_w);
571 gnome_print_moveto (pi->pc, x1, y1);
572 gnome_print_lineto (pi->pc, x2, y1);
573 gnome_print_stroke (pi->pc);
575 gnome_print_moveto (pi->pc, x1, y2);
576 gnome_print_lineto (pi->pc, x2, y2);
577 gnome_print_stroke (pi->pc);
579 gnome_print_moveto (pi->pc, x3, y1);
580 gnome_print_lineto (pi->pc, x4, y1);
581 gnome_print_stroke (pi->pc);
583 gnome_print_moveto (pi->pc, x3, y2);
584 gnome_print_lineto (pi->pc, x4, y2);
585 gnome_print_stroke (pi->pc);
591 gl_debug (DEBUG_PRINT, "END");
594 /*---------------------------------------------------------------------------*/
595 /* PRIVATE. Print i'th label. */
596 /*---------------------------------------------------------------------------*/
598 print_label (PrintInfo *pi,
602 glMergeRecord *record,
603 gboolean outline_flag,
604 gboolean reverse_flag)
606 gdouble width, height;
607 glTemplate *template;
609 gl_debug (DEBUG_PRINT, "START");
611 template = gl_label_get_template (label);
613 gl_label_get_size (label, &width, &height);
615 gnome_print_gsave (pi->pc);
617 /* Transform coordinate system to be relative to upper corner */
618 /* of the current label */
619 gnome_print_translate (pi->pc, x, y);
620 if (gl_label_get_rotate_flag (label)) {
621 gl_debug (DEBUG_PRINT, "Rotate flag set");
622 gnome_print_rotate (pi->pc, -90.0);
623 gnome_print_translate (pi->pc, -width, 0.0);
625 if ( reverse_flag ) {
626 gnome_print_translate (pi->pc, width, 0.0);
627 gnome_print_scale (pi->pc, -1.0, 1.0);
630 clip_to_outline (pi, label);
631 draw_label (pi, label, record);
633 draw_outline (pi, label);
635 clip_punchouts (pi, label);
637 gnome_print_grestore (pi->pc);
639 gl_template_free (&template);
641 gl_debug (DEBUG_PRINT, "END");
644 /*---------------------------------------------------------------------------*/
645 /* PRIVATE. Draw label. */
646 /*---------------------------------------------------------------------------*/
648 draw_label (PrintInfo *pi,
650 glMergeRecord *record)
653 glLabelObject *object;
655 gl_debug (DEBUG_PRINT, "START");
657 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
658 object = (glLabelObject *) p_obj->data;
660 draw_object (pi, object, record);
663 gl_debug (DEBUG_PRINT, "END");
666 /*---------------------------------------------------------------------------*/
667 /* PRIVATE. Draw object. */
668 /*---------------------------------------------------------------------------*/
670 draw_object (PrintInfo *pi,
671 glLabelObject *object,
672 glMergeRecord *record)
677 gl_debug (DEBUG_PRINT, "START");
679 gl_label_object_get_position (object, &x0, &y0);
680 gl_label_object_get_affine (object, affine);
682 gnome_print_gsave (pi->pc);
684 gnome_print_translate (pi->pc, x0, y0);
685 gnome_print_concat (pi->pc, affine);
687 if (GL_IS_LABEL_TEXT(object)) {
688 draw_text_object (pi, GL_LABEL_TEXT(object), record);
689 } else if (GL_IS_LABEL_BOX(object)) {
690 draw_box_object (pi, GL_LABEL_BOX(object));
691 } else if (GL_IS_LABEL_LINE(object)) {
692 draw_line_object (pi, GL_LABEL_LINE(object));
693 } else if (GL_IS_LABEL_ELLIPSE(object)) {
694 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object));
695 } else if (GL_IS_LABEL_IMAGE(object)) {
696 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
697 } else if (GL_IS_LABEL_BARCODE(object)) {
698 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
701 gnome_print_grestore (pi->pc);
703 gl_debug (DEBUG_PRINT, "END");
706 /*---------------------------------------------------------------------------*/
707 /* PRIVATE. Draw text object. */
708 /*---------------------------------------------------------------------------*/
710 draw_text_object (PrintInfo *pi,
712 glMergeRecord *record)
717 gdouble x_offset, y_offset, w, object_w, object_h;
722 GnomeFontWeight font_weight;
723 gboolean font_italic_flag;
725 GtkJustification just;
726 GnomeGlyphList *glyphlist;
729 gdouble text_line_spacing;
732 gl_debug (DEBUG_PRINT, "START");
734 gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
735 lines = gl_label_text_get_lines (object);
736 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
737 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
738 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
739 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
740 color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
741 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
742 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
744 font = gnome_font_find_closest_from_weight_slant (
749 gnome_print_setfont (pi->pc, font);
751 gnome_print_setrgbcolor (pi->pc,
752 GL_COLOR_F_RED (color),
753 GL_COLOR_F_GREEN (color),
754 GL_COLOR_F_BLUE (color));
755 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
757 text = gl_text_node_lines_expand (lines, record);
758 line = g_strsplit (text, "\n", -1);
761 art_affine_identity (affine);
763 for (i = 0; line[i] != NULL; i++) {
765 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
769 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
773 case GTK_JUSTIFY_LEFT:
774 x_offset = GL_LABEL_TEXT_MARGIN;
776 case GTK_JUSTIFY_CENTER:
777 x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
779 case GTK_JUSTIFY_RIGHT:
780 x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
784 break; /* shouldn't happen */
787 /* Work out the y position to the BOTTOM of the first line */
788 y_offset = GL_LABEL_TEXT_MARGIN +
789 + gnome_font_get_descender (font)
790 + (i + 1) * font_size * text_line_spacing;
792 /* Remove any text line spacing from the first row. */
793 y_offset -= font_size * (text_line_spacing - 1);
796 gnome_print_moveto (pi->pc, x_offset, y_offset);
798 gnome_print_gsave (pi->pc);
799 gnome_print_scale (pi->pc, 1.0, -1.0);
800 gnome_print_show (pi->pc, line[i]);
801 gnome_print_grestore (pi->pc);
806 gl_text_node_lines_free (&lines);
807 g_free (font_family);
809 gl_debug (DEBUG_PRINT, "END");
812 /*---------------------------------------------------------------------------*/
813 /* PRIVATE. Draw box object. */
814 /*---------------------------------------------------------------------------*/
816 draw_box_object (PrintInfo *pi,
821 guint line_color, fill_color;
823 gl_debug (DEBUG_PRINT, "START");
825 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
826 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
827 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
828 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
830 /* Paint fill color */
831 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
832 gnome_print_setrgbcolor (pi->pc,
833 GL_COLOR_F_RED (fill_color),
834 GL_COLOR_F_GREEN (fill_color),
835 GL_COLOR_F_BLUE (fill_color));
836 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
837 gnome_print_fill (pi->pc);
840 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
841 gnome_print_setrgbcolor (pi->pc,
842 GL_COLOR_F_RED (line_color),
843 GL_COLOR_F_GREEN (line_color),
844 GL_COLOR_F_BLUE (line_color));
845 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
846 gnome_print_setlinewidth (pi->pc, line_width);
847 gnome_print_stroke (pi->pc);
849 gl_debug (DEBUG_PRINT, "END");
852 /*---------------------------------------------------------------------------*/
853 /* PRIVATE. Draw line object. */
854 /*---------------------------------------------------------------------------*/
856 draw_line_object (PrintInfo *pi,
863 gl_debug (DEBUG_PRINT, "START");
865 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
866 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
867 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
869 gnome_print_moveto (pi->pc, 0.0, 0.0);
870 gnome_print_lineto (pi->pc, w, h);
871 gnome_print_setrgbcolor (pi->pc,
872 GL_COLOR_F_RED (line_color),
873 GL_COLOR_F_GREEN (line_color),
874 GL_COLOR_F_BLUE (line_color));
875 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
876 gnome_print_setlinewidth (pi->pc, line_width);
877 gnome_print_stroke (pi->pc);
879 gl_debug (DEBUG_PRINT, "END");
882 /*---------------------------------------------------------------------------*/
883 /* PRIVATE. Draw ellipse object. */
884 /*---------------------------------------------------------------------------*/
886 draw_ellipse_object (PrintInfo *pi,
887 glLabelEllipse *object)
889 gdouble x0, y0, rx, ry, w, h;
891 guint line_color, fill_color;
893 gl_debug (DEBUG_PRINT, "START");
895 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
896 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
897 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
898 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
905 /* Paint fill color */
906 create_ellipse_path (pi->pc, x0, y0, rx, ry);
907 gnome_print_setrgbcolor (pi->pc,
908 GL_COLOR_F_RED (fill_color),
909 GL_COLOR_F_GREEN (fill_color),
910 GL_COLOR_F_BLUE (fill_color));
911 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
912 gnome_print_fill (pi->pc);
915 create_ellipse_path (pi->pc, x0, y0, rx, ry);
916 gnome_print_setrgbcolor (pi->pc,
917 GL_COLOR_F_RED (line_color),
918 GL_COLOR_F_GREEN (line_color),
919 GL_COLOR_F_BLUE (line_color));
920 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
921 gnome_print_setlinewidth (pi->pc, line_width);
922 gnome_print_stroke (pi->pc);
924 gl_debug (DEBUG_PRINT, "END");
927 /*---------------------------------------------------------------------------*/
928 /* PRIVATE. Draw image object. */
929 /*---------------------------------------------------------------------------*/
931 draw_image_object (PrintInfo *pi,
932 glLabelImage *object,
933 glMergeRecord *record)
936 const GdkPixbuf *pixbuf;
938 gint image_w, image_h, image_stride;
939 gboolean image_alpha_flag;
942 gl_debug (DEBUG_PRINT, "START");
944 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
946 pixbuf = gl_label_image_get_pixbuf (object, record);
947 image_data = gdk_pixbuf_get_pixels (pixbuf);
948 image_w = gdk_pixbuf_get_width (pixbuf);
949 image_h = gdk_pixbuf_get_height (pixbuf);
950 image_stride = gdk_pixbuf_get_rowstride(pixbuf);
951 image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
953 gnome_print_gsave (pi->pc);
954 gnome_print_translate (pi->pc, 0.0, h);
955 gnome_print_scale (pi->pc, w, -h);
956 if (image_alpha_flag) {
957 #ifndef NO_ALPHA_HACK
960 image_data2 = get_pixels_as_rgb (pixbuf);
961 ret = gnome_print_rgbimage (pi->pc, image_data2,
962 image_w, image_h, image_stride);
963 g_free (image_data2);
965 ret = gnome_print_rgbaimage (pi->pc, image_data,
966 image_w, image_h, image_stride);
969 ret = gnome_print_rgbimage (pi->pc, image_data,
970 image_w, image_h, image_stride);
972 gnome_print_grestore (pi->pc);
974 gl_debug (DEBUG_PRINT, "END");
977 /*---------------------------------------------------------------------------*/
978 /* PRIVATE. Draw box object. */
979 /*---------------------------------------------------------------------------*/
981 draw_barcode_object (PrintInfo *pi,
982 glLabelBarcode *object,
983 glMergeRecord *record)
987 glBarcodeChar *bchar;
991 gchar *text, *cstring;
992 glTextNode *text_node;
993 glBarcodeStyle style;
995 gboolean checksum_flag;
999 gl_debug (DEBUG_PRINT, "START");
1001 text_node = gl_label_barcode_get_data (object);
1002 gl_label_barcode_get_props (object,
1003 &style, &text_flag, &checksum_flag);
1004 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1005 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1007 text = gl_text_node_expand (text_node, record);
1008 gbc = gl_barcode_new (style, text_flag, checksum_flag, w, h, text);
1010 gl_text_node_free (&text_node);
1014 font = gnome_font_find_closest_from_weight_slant (
1015 GL_BARCODE_FONT_FAMILY,
1016 GL_BARCODE_FONT_WEIGHT,
1018 gnome_print_setfont (pi->pc, font);
1020 gnome_print_setrgbcolor (pi->pc,
1021 GL_COLOR_F_RED (color),
1022 GL_COLOR_F_GREEN (color),
1023 GL_COLOR_F_BLUE (color));
1024 gnome_print_setopacity (pi->pc,
1025 GL_COLOR_F_ALPHA (color));
1027 y_offset = 12.0 - gnome_font_get_descender (font);
1028 gnome_print_moveto (pi->pc, 0.0, y_offset);
1030 gnome_print_gsave (pi->pc);
1031 gnome_print_scale (pi->pc, 1.0, -1.0);
1032 gnome_print_show (pi->pc, _("Invalid barcode"));
1033 gnome_print_grestore (pi->pc);
1037 for (li = gbc->lines; li != NULL; li = li->next) {
1038 line = (glBarcodeLine *) li->data;
1040 gnome_print_moveto (pi->pc, line->x, line->y);
1041 gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1042 gnome_print_setrgbcolor (pi->pc,
1043 GL_COLOR_F_RED (color),
1044 GL_COLOR_F_GREEN (color),
1045 GL_COLOR_F_BLUE (color));
1046 gnome_print_setopacity (pi->pc,
1047 GL_COLOR_F_ALPHA (color));
1048 gnome_print_setlinewidth (pi->pc, line->width);
1049 gnome_print_stroke (pi->pc);
1052 for (li = gbc->chars; li != NULL; li = li->next) {
1053 bchar = (glBarcodeChar *) li->data;
1055 font = gnome_font_find_closest_from_weight_slant (
1056 GL_BARCODE_FONT_FAMILY,
1057 GL_BARCODE_FONT_WEIGHT,
1058 FALSE, bchar->fsize);
1059 gnome_print_setfont (pi->pc, font);
1061 gnome_print_setrgbcolor (pi->pc,
1062 GL_COLOR_F_RED (color),
1063 GL_COLOR_F_GREEN (color),
1064 GL_COLOR_F_BLUE (color));
1065 gnome_print_setopacity (pi->pc,
1066 GL_COLOR_F_ALPHA (color));
1069 bchar->y + bchar->fsize -
1070 gnome_font_get_descender (font);
1071 gnome_print_moveto (pi->pc, bchar->x, y_offset);
1073 cstring = g_strdup_printf ("%c", bchar->c);
1074 gnome_print_gsave (pi->pc);
1075 gnome_print_scale (pi->pc, 1.0, -1.0);
1076 gnome_print_show (pi->pc, cstring);
1077 gnome_print_grestore (pi->pc);
1082 gl_barcode_free (&gbc);
1086 gl_debug (DEBUG_PRINT, "END");
1089 /*---------------------------------------------------------------------------*/
1090 /* PRIVATE. Draw outline. */
1091 /*---------------------------------------------------------------------------*/
1093 draw_outline (PrintInfo *pi,
1098 glTemplate *template;
1100 gl_debug (DEBUG_PRINT, "START");
1102 template = gl_label_get_template (label);
1104 gnome_print_setrgbcolor (pi->pc, 0.25, 0.25, 0.25);
1105 gnome_print_setopacity (pi->pc, 1.0);
1106 gnome_print_setlinewidth (pi->pc, 0.25);
1108 switch (template->label.style) {
1110 case GL_TEMPLATE_STYLE_RECT:
1111 gl_label_get_size (label, &w, &h);
1112 r = template->label.rect.r;
1114 /* simple rectangle */
1115 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1117 /* rectangle with rounded corners */
1118 create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1121 gnome_print_stroke (pi->pc);
1124 case GL_TEMPLATE_STYLE_ROUND:
1126 r1 = template->label.round.r;
1127 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1128 gnome_print_stroke (pi->pc);
1131 case GL_TEMPLATE_STYLE_CD:
1132 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1133 /* CD style, round label w/ concentric round hole */
1134 r1 = template->label.cd.r1;
1135 r2 = template->label.cd.r2;
1136 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1137 gnome_print_stroke (pi->pc);
1138 create_ellipse_path (pi->pc, r1, r1, r2, r2);
1139 gnome_print_stroke (pi->pc);
1141 /* Business Card CD style, clipped round label w/ hole */
1142 gl_label_get_size (label, &w, &h);
1143 r1 = template->label.cd.r1;
1144 r2 = template->label.cd.r2;
1145 create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1146 gnome_print_stroke (pi->pc);
1147 create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1148 gnome_print_stroke (pi->pc);
1153 g_warning ("Unknown template label style");
1157 gl_template_free (&template);
1159 gl_debug (DEBUG_PRINT, "END");
1162 /*---------------------------------------------------------------------------*/
1163 /* PRIVATE. Clip to outline. */
1164 /*---------------------------------------------------------------------------*/
1166 clip_to_outline (PrintInfo *pi,
1172 glTemplate *template;
1174 gl_debug (DEBUG_PRINT, "START");
1176 template = gl_label_get_template (label);
1178 switch (template->label.style) {
1180 case GL_TEMPLATE_STYLE_RECT:
1181 gl_label_get_size (label, &w, &h);
1182 r = template->label.rect.r;
1183 waste = template->label.rect.waste;
1185 /* simple rectangle */
1186 create_rectangle_path (pi->pc,
1187 -waste, -waste, w+2*waste, h+2*waste);
1189 /* rectangle with rounded corners */
1190 create_rounded_rectangle_path (pi->pc, -waste, -waste,
1191 w+2*waste, h+2*waste, r);
1193 gnome_print_clip (pi->pc);
1196 case GL_TEMPLATE_STYLE_ROUND:
1197 r1 = template->label.round.r;
1198 waste = template->label.round.waste;
1199 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1200 gnome_print_clip (pi->pc);
1203 case GL_TEMPLATE_STYLE_CD:
1204 waste = template->label.cd.waste;
1205 if ((template->label.cd.h == 0) && (template->label.cd.w == 0)) {
1206 /* CD style, round label w/ concentric round hole */
1207 r1 = template->label.cd.r1;
1208 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1210 /* Business Card CD style, clipped round label w/ hole */
1211 gl_label_get_size (label, &w, &h);
1212 r1 = template->label.cd.r1;
1213 create_clipped_circle_path (pi->pc,
1215 w+2*waste, h+2*waste,
1218 gnome_print_clip (pi->pc);
1222 g_warning ("Unknown template label style");
1226 gl_template_free (&template);
1228 gl_debug (DEBUG_PRINT, "END");
1231 /*---------------------------------------------------------------------------*/
1232 /* PRIVATE. Clip punchouts. (Save some ink by not printing in CD holes) */
1234 /* Ideally this would be done in clip_to_outline, but I am not sure how to */
1235 /* invert the region for gnome_print_clip, so instead, I will just draw */
1236 /* a white circle on top of everything else. */
1237 /*---------------------------------------------------------------------------*/
1239 clip_punchouts (PrintInfo *pi,
1244 glTemplate *template;
1246 gl_debug (DEBUG_PRINT, "START");
1248 template = gl_label_get_template (label);
1250 switch (template->label.style) {
1252 case GL_TEMPLATE_STYLE_RECT:
1253 case GL_TEMPLATE_STYLE_ROUND:
1256 case GL_TEMPLATE_STYLE_CD:
1257 gl_label_get_size (label, &w, &h);
1258 waste = template->label.cd.waste;
1259 r2 = template->label.cd.r2;
1260 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1261 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1262 gnome_print_setopacity (pi->pc, 1.0);
1263 gnome_print_fill (pi->pc);
1267 g_warning ("Unknown template label style");
1271 gl_template_free (&template);
1273 gl_debug (DEBUG_PRINT, "END");
1276 /*---------------------------------------------------------------------------*/
1277 /* PRIVATE. Path creation utilities. */
1278 /*---------------------------------------------------------------------------*/
1280 create_rectangle_path (GnomePrintContext *pc,
1286 gl_debug (DEBUG_PRINT, "START");
1288 gnome_print_newpath (pc);
1289 gnome_print_moveto (pc, x0, y0);
1290 gnome_print_lineto (pc, x0 + w, y0);
1291 gnome_print_lineto (pc, x0 + w, y0 + h);
1292 gnome_print_lineto (pc, x0, y0 + h);
1293 gnome_print_lineto (pc, x0, y0);
1294 gnome_print_closepath (pc);
1296 gl_debug (DEBUG_PRINT, "END");
1300 create_ellipse_path (GnomePrintContext *pc,
1309 gl_debug (DEBUG_PRINT, "START");
1311 gnome_print_newpath (pc);
1312 gnome_print_moveto (pc, x0 + rx, y0);
1313 for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1314 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1315 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1316 gnome_print_lineto (pc, x, y);
1318 gnome_print_closepath (pc);
1320 gl_debug (DEBUG_PRINT, "END");
1324 create_rounded_rectangle_path (GnomePrintContext *pc,
1334 gl_debug (DEBUG_PRINT, "START");
1336 gnome_print_newpath (pc);
1338 gnome_print_moveto (pc, x0 + r, y0);
1339 for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1340 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1341 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1342 gnome_print_lineto (pc, x, y);
1344 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1345 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1346 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1347 gnome_print_lineto (pc, x, y);
1349 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1350 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1351 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1352 gnome_print_lineto (pc, x, y);
1354 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1355 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1356 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1357 gnome_print_lineto (pc, x, y);
1359 gnome_print_lineto (pc, x0 + r, y0);
1361 gnome_print_closepath (pc);
1363 gl_debug (DEBUG_PRINT, "END");
1367 create_clipped_circle_path (GnomePrintContext *pc,
1375 gdouble theta1, theta2;
1378 gl_debug (DEBUG_PRINT, "START");
1380 theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1381 theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1383 gnome_print_newpath (pc);
1385 x = x0 + r * cos (theta1 * G_PI / 180.0);
1386 y = y0 + r * sin (theta1 * G_PI / 180.0);
1387 gnome_print_moveto (pc, x, y);
1389 for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1390 x = x0 + r * cos (i_theta * G_PI / 180.0);
1391 y = y0 + r * sin (i_theta * G_PI / 180.0);
1392 gnome_print_lineto (pc, x, y);
1395 x = x0 + r * cos (theta2 * G_PI / 180.0);
1396 y = y0 + r * sin (theta2 * G_PI / 180.0);
1397 gnome_print_lineto (pc, x, y);
1399 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1400 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1401 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1402 gnome_print_lineto (pc, x, y);
1405 for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1406 x = x0 + r * cos (i_theta * G_PI / 180.0);
1407 y = y0 + r * sin (i_theta * G_PI / 180.0);
1408 gnome_print_lineto (pc, x, y);
1411 x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1412 y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1413 gnome_print_lineto (pc, x, y);
1415 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1416 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1417 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1418 gnome_print_lineto (pc, x, y);
1421 for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1422 x = x0 + r * cos (i_theta * G_PI / 180.0);
1423 y = y0 + r * sin (i_theta * G_PI / 180.0);
1424 gnome_print_lineto (pc, x, y);
1427 x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1428 y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1429 gnome_print_lineto (pc, x, y);
1431 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1432 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1433 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1434 gnome_print_lineto (pc, x, y);
1437 for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1438 x = x0 + r * cos (i_theta * G_PI / 180.0);
1439 y = y0 + r * sin (i_theta * G_PI / 180.0);
1440 gnome_print_lineto (pc, x, y);
1443 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1444 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1445 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1446 gnome_print_lineto (pc, x, y);
1449 x = x0 + r * cos (theta1 * G_PI / 180.0);
1450 y = y0 + r * sin (theta1 * G_PI / 180.0);
1451 gnome_print_lineto (pc, x, y);
1453 gnome_print_closepath (pc);
1455 gl_debug (DEBUG_PRINT, "END");
1458 #ifndef NO_ALPHA_HACK
1459 /*---------------------------------------------------------------------------*/
1460 /* PRIVATE. Extract a copy of rgba pixels, removing alpha by compositing */
1461 /* with a white background. */
1463 /* This is currently needed due to the lousy job gnome-print does in */
1464 /* rendering images with alpha channels to PS. This sacrafices the ability */
1465 /* to do compositing of images with other items in the background. */
1466 /*---------------------------------------------------------------------------*/
1468 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1470 gint bits_per_sample, channels;
1472 gint width, height, rowstride;
1474 guchar *buf_src, *buf_dest;
1475 guchar *p_src, *p_dest;
1478 gdouble alpha, beta;
1480 gl_debug (DEBUG_PRINT, "START");
1482 g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1484 /* extract pixels and parameters from pixbuf. */
1485 buf_src = gdk_pixbuf_get_pixels (pixbuf);
1486 bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1487 channels = gdk_pixbuf_get_n_channels (pixbuf);
1488 has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
1489 width = gdk_pixbuf_get_width (pixbuf);
1490 height = gdk_pixbuf_get_height (pixbuf);
1491 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1493 /* validate assumptions about pixbuf. */
1494 g_return_val_if_fail (buf_src, NULL);
1495 g_return_val_if_fail (bits_per_sample == 8, NULL);
1496 g_return_val_if_fail (channels == 4, NULL);
1497 g_return_val_if_fail (has_alpha, NULL);
1498 g_return_val_if_fail (width > 0, NULL);
1499 g_return_val_if_fail (height > 0, NULL);
1500 g_return_val_if_fail (rowstride > 0, NULL);
1502 /* Allocate a destination buffer */
1503 bytes = height * rowstride;
1504 gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1505 buf_dest = g_try_malloc (bytes);
1509 gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1511 /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1514 for ( iy=0; iy < height; iy++ ) {
1516 p_src = buf_src + iy*rowstride;
1517 p_dest = buf_dest + iy*rowstride;
1519 for ( ix=0; ix < width; ix++ ) {
1529 *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1530 *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1531 *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1537 gl_debug (DEBUG_PRINT, "START");