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"
38 #include <libglabels/template.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 const glTemplateLabelType *label_type;
182 gint i_sheet, i_label;
183 glTemplateOrigin *origins;
185 gl_debug (DEBUG_PRINT, "START");
187 pi = print_info_new (job, label);
188 label_type = gl_template_get_first_label_type (pi->template);
190 origins = gl_template_get_origins (label_type);
192 for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
194 print_page_begin (pi);
195 if (flags->crop_marks) {
196 print_crop_marks (pi);
199 for (i_label = first - 1; i_label < last; i_label++) {
201 print_label (pi, label,
202 origins[i_label].x, origins[i_label].y,
203 NULL, flags->outline, flags->reverse);
212 print_info_free (&pi);
214 gl_debug (DEBUG_PRINT, "END");
217 /*****************************************************************************/
218 /* Merge print command (collated copies) */
219 /*****************************************************************************/
221 gl_print_merge_collated (GnomePrintJob *job,
228 const GList *record_list;
230 const glTemplateLabelType *label_type;
231 gint i_sheet, i_label, n_labels_per_page, i_copy;
232 glMergeRecord *record;
234 glTemplateOrigin *origins;
236 gl_debug (DEBUG_PRINT, "START");
238 merge = gl_label_get_merge (label);
239 record_list = gl_merge_get_record_list (merge);
241 pi = print_info_new (job, label);
242 label_type = gl_template_get_first_label_type (pi->template);
244 n_labels_per_page = gl_template_get_n_labels (label_type);
245 origins = gl_template_get_origins (label_type);
250 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
251 record = (glMergeRecord *)p->data;
253 if ( record->select_flag ) {
254 for (i_copy = 0; i_copy < n_copies; i_copy++) {
256 if ((i_label == 0) || (i_sheet == 0)) {
258 print_page_begin (pi);
259 if (flags->crop_marks) {
260 print_crop_marks (pi);
264 print_label (pi, label,
268 flags->outline, flags->reverse);
270 i_label = (i_label + 1) % n_labels_per_page;
284 print_info_free (&pi);
286 gl_debug (DEBUG_PRINT, "END");
289 /*****************************************************************************/
290 /* Merge print command (uncollated copies) */
291 /*****************************************************************************/
293 gl_print_merge_uncollated (GnomePrintJob *job,
300 const GList *record_list;
302 const glTemplateLabelType *label_type;
303 gint i_sheet, i_label, n_labels_per_page, i_copy;
304 glMergeRecord *record;
306 glTemplateOrigin *origins;
308 gl_debug (DEBUG_PRINT, "START");
310 merge = gl_label_get_merge (label);
311 record_list = gl_merge_get_record_list (merge);
313 pi = print_info_new (job, label);
314 label_type = gl_template_get_first_label_type (pi->template);
316 n_labels_per_page = gl_template_get_n_labels (label_type);
317 origins = gl_template_get_origins (label_type);
322 for (i_copy = 0; i_copy < n_copies; i_copy++) {
324 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
325 record = (glMergeRecord *)p->data;
327 if ( record->select_flag ) {
330 if ((i_label == 0) || (i_sheet == 0)) {
332 print_page_begin (pi);
333 if (flags->crop_marks) {
334 print_crop_marks (pi);
338 print_label (pi, label,
342 flags->outline, flags->reverse);
344 i_label = (i_label + 1) % n_labels_per_page;
358 print_info_free (&pi);
360 gl_debug (DEBUG_PRINT, "END");
363 /*****************************************************************************/
364 /* Batch print. Call appropriate function above. */
365 /*****************************************************************************/
367 gl_print_batch (GnomePrintJob *job,
374 glTemplate *template;
375 const glTemplateLabelType *label_type;
378 gl_debug (DEBUG_PRINT, "START");
380 merge = gl_label_get_merge (label);
381 template = gl_label_get_template (label);
382 label_type = gl_template_get_first_label_type (template);
384 if ( merge == NULL ) {
385 n_per_page = gl_template_get_n_labels(label_type);
387 gl_print_simple (job, label, n_sheets, 1, n_per_page, flags);
389 gl_print_merge_collated (job, label, n_copies, 1, flags);
391 gl_template_free (template);
393 gl_debug (DEBUG_PRINT, "END");
396 /*---------------------------------------------------------------------------*/
397 /* PRIVATE. new print info structure */
398 /*---------------------------------------------------------------------------*/
400 print_info_new (GnomePrintJob *job,
403 PrintInfo *pi = g_new0 (PrintInfo, 1);
404 glTemplate *template;
406 gl_debug (DEBUG_PRINT, "START");
408 g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
409 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
411 template = gl_label_get_template (label);
413 g_return_val_if_fail (template, NULL);
414 g_return_val_if_fail (template->page_size, NULL);
415 g_return_val_if_fail (template->page_width > 0, NULL);
416 g_return_val_if_fail (template->page_height > 0, NULL);
418 pi->pc = gnome_print_job_get_context (job);
419 pi->config = gnome_print_job_get_config (job);
421 gl_debug (DEBUG_PRINT,
422 "setting page size = \"%s\"", template->page_size);
424 gnome_print_config_set_length (pi->config,
425 GNOME_PRINT_KEY_PAPER_WIDTH,
426 template->page_width,
427 GNOME_PRINT_PS_UNIT);
428 gnome_print_config_set_length (pi->config,
429 GNOME_PRINT_KEY_PAPER_HEIGHT,
430 template->page_height,
431 GNOME_PRINT_PS_UNIT);
433 pi->page_width = template->page_width;
434 pi->page_height = template->page_height;
436 pi->template = template;
437 pi->label_rotate_flag = gl_label_get_rotate_flag (label);
441 gl_debug (DEBUG_PRINT, "END");
446 /*---------------------------------------------------------------------------*/
447 /* PRIVATE. free print info structure */
448 /*---------------------------------------------------------------------------*/
450 print_info_free (PrintInfo **pi)
452 gl_debug (DEBUG_PRINT, "START");
454 gl_template_free ((*pi)->template);
455 (*pi)->template = NULL;
457 gnome_print_context_close ((*pi)->pc);
462 gl_debug (DEBUG_PRINT, "END");
465 /*---------------------------------------------------------------------------*/
466 /* PRIVATE. Begin a new page. */
467 /*---------------------------------------------------------------------------*/
469 print_page_begin (PrintInfo *pi)
473 gl_debug (DEBUG_PRINT, "START");
477 str = g_strdup_printf ("sheet%02d", pi->sheet);
478 gnome_print_beginpage (pi->pc, str);
481 /* Translate and scale, so that our origin is at the upper left. */
482 gnome_print_translate (pi->pc, 0.0, pi->page_height);
483 gnome_print_scale (pi->pc, 1.0, -1.0);
485 gl_debug (DEBUG_PRINT, "END");
488 /*---------------------------------------------------------------------------*/
489 /* PRIVATE. End a page. */
490 /*---------------------------------------------------------------------------*/
492 print_page_end (PrintInfo *pi)
494 gl_debug (DEBUG_PRINT, "START");
496 gnome_print_showpage (pi->pc);
498 gl_debug (DEBUG_PRINT, "END");
501 /*---------------------------------------------------------------------------*/
502 /* PRIVATE. Print crop tick marks. */
503 /*---------------------------------------------------------------------------*/
505 print_crop_marks (PrintInfo *pi)
507 const glTemplateLabelType *label_type;
508 gdouble w, h, page_w, page_h;
510 glTemplateLayout *layout;
511 gdouble xmin, ymin, xmax, ymax, dx, dy;
512 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
515 gl_debug (DEBUG_PRINT, "START");
517 label_type = gl_template_get_first_label_type (pi->template);
519 gl_template_get_label_size (label_type, &w, &h);
521 page_w = pi->page_width;
522 page_h = pi->page_height;
524 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
525 gnome_print_setopacity (pi->pc, 1.0);
526 gnome_print_setlinewidth (pi->pc, 0.25);
528 for (p=label_type->layouts; p != NULL; p=p->next) {
530 layout = (glTemplateLayout *)p->data;
534 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
535 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
543 for (ix=0; ix < nx; ix++) {
548 y1 = MAX((ymin - TICK_OFFSET), 0.0);
549 y2 = MAX((y1 - TICK_LENGTH), 0.0);
551 y3 = MIN((ymax + TICK_OFFSET), page_h);
552 y4 = MIN((y3 + TICK_LENGTH), page_h);
554 gnome_print_moveto (pi->pc, x1, y1);
555 gnome_print_lineto (pi->pc, x1, y2);
556 gnome_print_stroke (pi->pc);
558 gnome_print_moveto (pi->pc, x2, y1);
559 gnome_print_lineto (pi->pc, x2, y2);
560 gnome_print_stroke (pi->pc);
562 gnome_print_moveto (pi->pc, x1, y3);
563 gnome_print_lineto (pi->pc, x1, y4);
564 gnome_print_stroke (pi->pc);
566 gnome_print_moveto (pi->pc, x2, y3);
567 gnome_print_lineto (pi->pc, x2, y4);
568 gnome_print_stroke (pi->pc);
572 for (iy=0; iy < ny; iy++) {
577 x1 = MAX((xmin - TICK_OFFSET), 0.0);
578 x2 = MAX((x1 - TICK_LENGTH), 0.0);
580 x3 = MIN((xmax + TICK_OFFSET), page_w);
581 x4 = MIN((x3 + TICK_LENGTH), page_w);
583 gnome_print_moveto (pi->pc, x1, y1);
584 gnome_print_lineto (pi->pc, x2, y1);
585 gnome_print_stroke (pi->pc);
587 gnome_print_moveto (pi->pc, x1, y2);
588 gnome_print_lineto (pi->pc, x2, y2);
589 gnome_print_stroke (pi->pc);
591 gnome_print_moveto (pi->pc, x3, y1);
592 gnome_print_lineto (pi->pc, x4, y1);
593 gnome_print_stroke (pi->pc);
595 gnome_print_moveto (pi->pc, x3, y2);
596 gnome_print_lineto (pi->pc, x4, y2);
597 gnome_print_stroke (pi->pc);
603 gl_debug (DEBUG_PRINT, "END");
606 /*---------------------------------------------------------------------------*/
607 /* PRIVATE. Print i'th label. */
608 /*---------------------------------------------------------------------------*/
610 print_label (PrintInfo *pi,
614 glMergeRecord *record,
615 gboolean outline_flag,
616 gboolean reverse_flag)
618 const glTemplateLabelType *label_type;
619 gdouble width, height;
621 gl_debug (DEBUG_PRINT, "START");
623 label_type = gl_template_get_first_label_type (pi->template);
625 gl_label_get_size (label, &width, &height);
627 gnome_print_gsave (pi->pc);
629 /* Transform coordinate system to be relative to upper corner */
630 /* of the current label */
631 gnome_print_translate (pi->pc, x, y);
632 if (gl_label_get_rotate_flag (label)) {
633 gl_debug (DEBUG_PRINT, "Rotate flag set");
634 gnome_print_rotate (pi->pc, -90.0);
635 gnome_print_translate (pi->pc, -width, 0.0);
637 if ( reverse_flag ) {
638 gnome_print_translate (pi->pc, width, 0.0);
639 gnome_print_scale (pi->pc, -1.0, 1.0);
642 clip_to_outline (pi, label);
643 draw_label (pi, label, record);
645 draw_outline (pi, label);
647 clip_punchouts (pi, label);
649 gnome_print_grestore (pi->pc);
651 gl_debug (DEBUG_PRINT, "END");
654 /*---------------------------------------------------------------------------*/
655 /* PRIVATE. Draw label. */
656 /*---------------------------------------------------------------------------*/
658 draw_label (PrintInfo *pi,
660 glMergeRecord *record)
663 glLabelObject *object;
665 gl_debug (DEBUG_PRINT, "START");
667 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
668 object = (glLabelObject *) p_obj->data;
670 draw_object (pi, object, record);
673 gl_debug (DEBUG_PRINT, "END");
676 /*---------------------------------------------------------------------------*/
677 /* PRIVATE. Draw object. */
678 /*---------------------------------------------------------------------------*/
680 draw_object (PrintInfo *pi,
681 glLabelObject *object,
682 glMergeRecord *record)
687 gl_debug (DEBUG_PRINT, "START");
689 gl_label_object_get_position (object, &x0, &y0);
690 gl_label_object_get_affine (object, affine);
692 gnome_print_gsave (pi->pc);
694 gnome_print_translate (pi->pc, x0, y0);
695 gnome_print_concat (pi->pc, affine);
697 if (GL_IS_LABEL_TEXT(object)) {
698 draw_text_object (pi, GL_LABEL_TEXT(object), record);
699 } else if (GL_IS_LABEL_BOX(object)) {
700 draw_box_object (pi, GL_LABEL_BOX(object));
701 } else if (GL_IS_LABEL_LINE(object)) {
702 draw_line_object (pi, GL_LABEL_LINE(object));
703 } else if (GL_IS_LABEL_ELLIPSE(object)) {
704 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object));
705 } else if (GL_IS_LABEL_IMAGE(object)) {
706 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
707 } else if (GL_IS_LABEL_BARCODE(object)) {
708 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
711 gnome_print_grestore (pi->pc);
713 gl_debug (DEBUG_PRINT, "END");
716 /*---------------------------------------------------------------------------*/
717 /* PRIVATE. Draw text object. */
718 /*---------------------------------------------------------------------------*/
720 draw_text_object (PrintInfo *pi,
722 glMergeRecord *record)
727 gdouble x_offset, y_offset, w, object_w, object_h;
732 GnomeFontWeight font_weight;
733 gboolean font_italic_flag;
735 GtkJustification just;
736 gboolean auto_shrink;
737 GnomeGlyphList *glyphlist;
740 gdouble text_line_spacing;
743 gl_debug (DEBUG_PRINT, "START");
745 gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
746 lines = gl_label_text_get_lines (object);
747 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
748 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
749 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
750 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
751 color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
752 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
754 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
755 auto_shrink = gl_label_text_get_auto_shrink (object);
757 text = gl_text_node_lines_expand (lines, record);
758 line = g_strsplit (text, "\n", -1);
761 art_affine_identity (affine);
763 if (record && auto_shrink) {
764 /* auto shrink text size to keep within text box limits. */
765 for (i = 0; line[i] != NULL; i++) {
767 font = gnome_font_find_closest_from_weight_slant (font_family,
771 glyphlist = gnome_glyphlist_from_text_dumb (font,
775 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
778 /* If width is too large, iteratively shrink font_size until this
779 line fits the width, or until the font size is ridiculously
781 while ( (w > object_w) && (font_size >= 1.0) ) {
785 font = gnome_font_find_closest_from_weight_slant (
790 glyphlist = gnome_glyphlist_from_text_dumb (font,
794 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
801 font = gnome_font_find_closest_from_weight_slant (
806 gnome_print_setfont (pi->pc, font);
808 gnome_print_setrgbcolor (pi->pc,
809 GL_COLOR_F_RED (color),
810 GL_COLOR_F_GREEN (color),
811 GL_COLOR_F_BLUE (color));
812 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
814 for (i = 0; line[i] != NULL; i++) {
816 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
820 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
824 case GTK_JUSTIFY_LEFT:
825 x_offset = GL_LABEL_TEXT_MARGIN;
827 case GTK_JUSTIFY_CENTER:
828 x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
830 case GTK_JUSTIFY_RIGHT:
831 x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
835 break; /* shouldn't happen */
838 /* Work out the y position to the BOTTOM of the first line */
839 y_offset = GL_LABEL_TEXT_MARGIN +
840 + gnome_font_get_descender (font)
841 + (i + 1) * font_size * text_line_spacing;
843 /* Remove any text line spacing from the first row. */
844 y_offset -= font_size * (text_line_spacing - 1);
847 gnome_print_moveto (pi->pc, x_offset, y_offset);
849 gnome_print_gsave (pi->pc);
850 gnome_print_scale (pi->pc, 1.0, -1.0);
851 gnome_print_show (pi->pc, line[i]);
852 gnome_print_grestore (pi->pc);
857 gl_text_node_lines_free (&lines);
858 g_free (font_family);
860 gl_debug (DEBUG_PRINT, "END");
863 /*---------------------------------------------------------------------------*/
864 /* PRIVATE. Draw box object. */
865 /*---------------------------------------------------------------------------*/
867 draw_box_object (PrintInfo *pi,
872 guint line_color, fill_color;
874 gl_debug (DEBUG_PRINT, "START");
876 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
877 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
878 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
879 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
881 /* Paint fill color */
882 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
883 gnome_print_setrgbcolor (pi->pc,
884 GL_COLOR_F_RED (fill_color),
885 GL_COLOR_F_GREEN (fill_color),
886 GL_COLOR_F_BLUE (fill_color));
887 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
888 gnome_print_fill (pi->pc);
891 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
892 gnome_print_setrgbcolor (pi->pc,
893 GL_COLOR_F_RED (line_color),
894 GL_COLOR_F_GREEN (line_color),
895 GL_COLOR_F_BLUE (line_color));
896 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
897 gnome_print_setlinewidth (pi->pc, line_width);
898 gnome_print_stroke (pi->pc);
900 gl_debug (DEBUG_PRINT, "END");
903 /*---------------------------------------------------------------------------*/
904 /* PRIVATE. Draw line object. */
905 /*---------------------------------------------------------------------------*/
907 draw_line_object (PrintInfo *pi,
914 gl_debug (DEBUG_PRINT, "START");
916 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
917 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
918 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
920 gnome_print_moveto (pi->pc, 0.0, 0.0);
921 gnome_print_lineto (pi->pc, w, h);
922 gnome_print_setrgbcolor (pi->pc,
923 GL_COLOR_F_RED (line_color),
924 GL_COLOR_F_GREEN (line_color),
925 GL_COLOR_F_BLUE (line_color));
926 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
927 gnome_print_setlinewidth (pi->pc, line_width);
928 gnome_print_stroke (pi->pc);
930 gl_debug (DEBUG_PRINT, "END");
933 /*---------------------------------------------------------------------------*/
934 /* PRIVATE. Draw ellipse object. */
935 /*---------------------------------------------------------------------------*/
937 draw_ellipse_object (PrintInfo *pi,
938 glLabelEllipse *object)
940 gdouble x0, y0, rx, ry, w, h;
942 guint line_color, fill_color;
944 gl_debug (DEBUG_PRINT, "START");
946 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
947 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
948 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
949 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
956 /* Paint fill color */
957 create_ellipse_path (pi->pc, x0, y0, rx, ry);
958 gnome_print_setrgbcolor (pi->pc,
959 GL_COLOR_F_RED (fill_color),
960 GL_COLOR_F_GREEN (fill_color),
961 GL_COLOR_F_BLUE (fill_color));
962 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
963 gnome_print_fill (pi->pc);
966 create_ellipse_path (pi->pc, x0, y0, rx, ry);
967 gnome_print_setrgbcolor (pi->pc,
968 GL_COLOR_F_RED (line_color),
969 GL_COLOR_F_GREEN (line_color),
970 GL_COLOR_F_BLUE (line_color));
971 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
972 gnome_print_setlinewidth (pi->pc, line_width);
973 gnome_print_stroke (pi->pc);
975 gl_debug (DEBUG_PRINT, "END");
978 /*---------------------------------------------------------------------------*/
979 /* PRIVATE. Draw image object. */
980 /*---------------------------------------------------------------------------*/
982 draw_image_object (PrintInfo *pi,
983 glLabelImage *object,
984 glMergeRecord *record)
987 const GdkPixbuf *pixbuf;
989 gint image_w, image_h, image_stride;
990 gboolean image_alpha_flag;
993 gl_debug (DEBUG_PRINT, "START");
995 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
997 pixbuf = gl_label_image_get_pixbuf (object, record);
998 image_data = gdk_pixbuf_get_pixels (pixbuf);
999 image_w = gdk_pixbuf_get_width (pixbuf);
1000 image_h = gdk_pixbuf_get_height (pixbuf);
1001 image_stride = gdk_pixbuf_get_rowstride(pixbuf);
1002 image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
1004 gnome_print_gsave (pi->pc);
1005 gnome_print_translate (pi->pc, 0.0, h);
1006 gnome_print_scale (pi->pc, w, -h);
1007 if (image_alpha_flag) {
1008 #ifndef NO_ALPHA_HACK
1009 guchar *image_data2;
1011 image_data2 = get_pixels_as_rgb (pixbuf);
1012 ret = gnome_print_rgbimage (pi->pc, image_data2,
1013 image_w, image_h, image_stride);
1014 g_free (image_data2);
1016 ret = gnome_print_rgbaimage (pi->pc, image_data,
1017 image_w, image_h, image_stride);
1020 ret = gnome_print_rgbimage (pi->pc, image_data,
1021 image_w, image_h, image_stride);
1023 gnome_print_grestore (pi->pc);
1025 gl_debug (DEBUG_PRINT, "END");
1028 /*---------------------------------------------------------------------------*/
1029 /* PRIVATE. Draw box object. */
1030 /*---------------------------------------------------------------------------*/
1032 draw_barcode_object (PrintInfo *pi,
1033 glLabelBarcode *object,
1034 glMergeRecord *record)
1037 glBarcodeLine *line;
1038 glBarcodeChar *bchar;
1042 gchar *text, *cstring;
1043 glTextNode *text_node;
1046 gboolean checksum_flag;
1050 gl_debug (DEBUG_PRINT, "START");
1052 text_node = gl_label_barcode_get_data (object);
1053 gl_label_barcode_get_props (object,
1054 &id, &text_flag, &checksum_flag);
1055 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1056 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1058 text = gl_text_node_expand (text_node, record);
1059 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1061 gl_text_node_free (&text_node);
1066 font = gnome_font_find_closest_from_weight_slant (
1067 GL_BARCODE_FONT_FAMILY,
1068 GL_BARCODE_FONT_WEIGHT,
1070 gnome_print_setfont (pi->pc, font);
1072 gnome_print_setrgbcolor (pi->pc,
1073 GL_COLOR_F_RED (color),
1074 GL_COLOR_F_GREEN (color),
1075 GL_COLOR_F_BLUE (color));
1076 gnome_print_setopacity (pi->pc,
1077 GL_COLOR_F_ALPHA (color));
1079 y_offset = 12.0 - fabs (gnome_font_get_descender (font));
1080 gnome_print_moveto (pi->pc, 0.0, y_offset);
1082 gnome_print_gsave (pi->pc);
1083 gnome_print_scale (pi->pc, 1.0, -1.0);
1084 gnome_print_show (pi->pc, _("Invalid barcode data"));
1085 gnome_print_grestore (pi->pc);
1089 for (li = gbc->lines; li != NULL; li = li->next) {
1090 line = (glBarcodeLine *) li->data;
1092 gnome_print_moveto (pi->pc, line->x, line->y);
1093 gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1094 gnome_print_setrgbcolor (pi->pc,
1095 GL_COLOR_F_RED (color),
1096 GL_COLOR_F_GREEN (color),
1097 GL_COLOR_F_BLUE (color));
1098 gnome_print_setopacity (pi->pc,
1099 GL_COLOR_F_ALPHA (color));
1100 gnome_print_setlinewidth (pi->pc, line->width);
1101 gnome_print_stroke (pi->pc);
1104 for (li = gbc->chars; li != NULL; li = li->next) {
1105 bchar = (glBarcodeChar *) li->data;
1107 font = gnome_font_find_closest_from_weight_slant (
1108 GL_BARCODE_FONT_FAMILY,
1109 GL_BARCODE_FONT_WEIGHT,
1110 FALSE, bchar->fsize);
1111 gnome_print_setfont (pi->pc, font);
1113 gnome_print_setrgbcolor (pi->pc,
1114 GL_COLOR_F_RED (color),
1115 GL_COLOR_F_GREEN (color),
1116 GL_COLOR_F_BLUE (color));
1117 gnome_print_setopacity (pi->pc,
1118 GL_COLOR_F_ALPHA (color));
1121 bchar->fsize - fabs (gnome_font_get_descender (font));
1123 gnome_print_moveto (pi->pc, bchar->x, bchar->y+y_offset);
1125 cstring = g_strdup_printf ("%c", bchar->c);
1126 gnome_print_gsave (pi->pc);
1127 gnome_print_scale (pi->pc, 1.0, -1.0);
1128 gnome_print_show (pi->pc, cstring);
1129 gnome_print_grestore (pi->pc);
1134 gl_barcode_free (&gbc);
1138 gl_debug (DEBUG_PRINT, "END");
1141 /*---------------------------------------------------------------------------*/
1142 /* PRIVATE. Draw outline. */
1143 /*---------------------------------------------------------------------------*/
1145 draw_outline (PrintInfo *pi,
1148 const glTemplateLabelType *label_type;
1152 gl_debug (DEBUG_PRINT, "START");
1154 label_type = gl_template_get_first_label_type (pi->template);
1156 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
1157 gnome_print_setopacity (pi->pc, 1.0);
1158 gnome_print_setlinewidth (pi->pc, 0.25);
1160 switch (label_type->shape) {
1162 case GL_TEMPLATE_SHAPE_RECT:
1163 gl_label_get_size (label, &w, &h);
1164 r = label_type->size.rect.r;
1166 /* simple rectangle */
1167 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1169 /* rectangle with rounded corners */
1170 create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1173 gnome_print_stroke (pi->pc);
1176 case GL_TEMPLATE_SHAPE_ROUND:
1178 r1 = label_type->size.round.r;
1179 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1180 gnome_print_stroke (pi->pc);
1183 case GL_TEMPLATE_SHAPE_CD:
1184 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1185 /* CD style, round label w/ concentric round hole */
1186 r1 = label_type->size.cd.r1;
1187 r2 = label_type->size.cd.r2;
1188 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1189 gnome_print_stroke (pi->pc);
1190 create_ellipse_path (pi->pc, r1, r1, r2, r2);
1191 gnome_print_stroke (pi->pc);
1193 /* Business Card CD style, clipped round label w/ hole */
1194 gl_label_get_size (label, &w, &h);
1195 r1 = label_type->size.cd.r1;
1196 r2 = label_type->size.cd.r2;
1197 create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1198 gnome_print_stroke (pi->pc);
1199 create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1200 gnome_print_stroke (pi->pc);
1205 g_warning ("Unknown template label style");
1209 gl_debug (DEBUG_PRINT, "END");
1212 /*---------------------------------------------------------------------------*/
1213 /* PRIVATE. Clip to outline. */
1214 /*---------------------------------------------------------------------------*/
1216 clip_to_outline (PrintInfo *pi,
1219 const glTemplateLabelType *label_type;
1222 gdouble waste, x_waste, y_waste;
1224 gl_debug (DEBUG_PRINT, "START");
1226 label_type = gl_template_get_first_label_type (pi->template);
1228 switch (label_type->shape) {
1230 case GL_TEMPLATE_SHAPE_RECT:
1231 gl_label_get_size (label, &w, &h);
1232 r = label_type->size.rect.r;
1233 x_waste = label_type->size.rect.x_waste;
1234 y_waste = label_type->size.rect.y_waste;
1236 /* simple rectangle */
1237 create_rectangle_path (pi->pc,
1239 w+2*x_waste, h+2*y_waste);
1241 /* rectangle with rounded corners */
1242 create_rounded_rectangle_path (pi->pc,
1244 w+2*x_waste, h+2*y_waste, r);
1246 gnome_print_clip (pi->pc);
1249 case GL_TEMPLATE_SHAPE_ROUND:
1250 r1 = label_type->size.round.r;
1251 waste = label_type->size.round.waste;
1252 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1253 gnome_print_clip (pi->pc);
1256 case GL_TEMPLATE_SHAPE_CD:
1257 waste = label_type->size.cd.waste;
1258 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1259 /* CD style, round label w/ concentric round hole */
1260 r1 = label_type->size.cd.r1;
1261 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1263 /* Business Card CD style, clipped round label w/ hole */
1264 gl_label_get_size (label, &w, &h);
1265 r1 = label_type->size.cd.r1;
1266 create_clipped_circle_path (pi->pc,
1268 w+2*waste, h+2*waste,
1271 gnome_print_clip (pi->pc);
1275 g_warning ("Unknown template label style");
1279 gl_debug (DEBUG_PRINT, "END");
1282 /*---------------------------------------------------------------------------*/
1283 /* PRIVATE. Clip punchouts. (Save some ink by not printing in CD holes) */
1285 /* Ideally this would be done in clip_to_outline, but I am not sure how to */
1286 /* invert the region for gnome_print_clip, so instead, I will just draw */
1287 /* a white circle on top of everything else. */
1288 /*---------------------------------------------------------------------------*/
1290 clip_punchouts (PrintInfo *pi,
1293 const glTemplateLabelType *label_type;
1297 gl_debug (DEBUG_PRINT, "START");
1299 label_type = gl_template_get_first_label_type (pi->template);
1301 switch (label_type->shape) {
1303 case GL_TEMPLATE_SHAPE_RECT:
1304 case GL_TEMPLATE_SHAPE_ROUND:
1307 case GL_TEMPLATE_SHAPE_CD:
1308 gl_label_get_size (label, &w, &h);
1309 waste = label_type->size.cd.waste;
1310 r2 = label_type->size.cd.r2;
1311 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1312 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1313 gnome_print_setopacity (pi->pc, 1.0);
1314 gnome_print_fill (pi->pc);
1318 g_warning ("Unknown template label style");
1322 gl_debug (DEBUG_PRINT, "END");
1325 /*---------------------------------------------------------------------------*/
1326 /* PRIVATE. Path creation utilities. */
1327 /*---------------------------------------------------------------------------*/
1329 create_rectangle_path (GnomePrintContext *pc,
1335 gl_debug (DEBUG_PRINT, "START");
1337 gnome_print_newpath (pc);
1338 gnome_print_moveto (pc, x0, y0);
1339 gnome_print_lineto (pc, x0 + w, y0);
1340 gnome_print_lineto (pc, x0 + w, y0 + h);
1341 gnome_print_lineto (pc, x0, y0 + h);
1342 gnome_print_lineto (pc, x0, y0);
1343 gnome_print_closepath (pc);
1345 gl_debug (DEBUG_PRINT, "END");
1349 create_ellipse_path (GnomePrintContext *pc,
1358 gl_debug (DEBUG_PRINT, "START");
1360 gnome_print_newpath (pc);
1361 gnome_print_moveto (pc, x0 + rx, y0);
1362 for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1363 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1364 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1365 gnome_print_lineto (pc, x, y);
1367 gnome_print_closepath (pc);
1369 gl_debug (DEBUG_PRINT, "END");
1373 create_rounded_rectangle_path (GnomePrintContext *pc,
1383 gl_debug (DEBUG_PRINT, "START");
1385 gnome_print_newpath (pc);
1387 gnome_print_moveto (pc, x0 + r, y0);
1388 for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1389 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1390 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1391 gnome_print_lineto (pc, x, y);
1393 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1394 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1395 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1396 gnome_print_lineto (pc, x, y);
1398 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1399 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1400 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1401 gnome_print_lineto (pc, x, y);
1403 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1404 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1405 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1406 gnome_print_lineto (pc, x, y);
1408 gnome_print_lineto (pc, x0 + r, y0);
1410 gnome_print_closepath (pc);
1412 gl_debug (DEBUG_PRINT, "END");
1416 create_clipped_circle_path (GnomePrintContext *pc,
1424 gdouble theta1, theta2;
1427 gl_debug (DEBUG_PRINT, "START");
1429 theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1430 theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1432 gnome_print_newpath (pc);
1434 x = x0 + r * cos (theta1 * G_PI / 180.0);
1435 y = y0 + r * sin (theta1 * G_PI / 180.0);
1436 gnome_print_moveto (pc, x, y);
1438 for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1439 x = x0 + r * cos (i_theta * G_PI / 180.0);
1440 y = y0 + r * sin (i_theta * G_PI / 180.0);
1441 gnome_print_lineto (pc, x, y);
1444 x = x0 + r * cos (theta2 * G_PI / 180.0);
1445 y = y0 + r * sin (theta2 * G_PI / 180.0);
1446 gnome_print_lineto (pc, x, y);
1448 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1449 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1450 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1451 gnome_print_lineto (pc, x, y);
1454 for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1455 x = x0 + r * cos (i_theta * G_PI / 180.0);
1456 y = y0 + r * sin (i_theta * G_PI / 180.0);
1457 gnome_print_lineto (pc, x, y);
1460 x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1461 y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1462 gnome_print_lineto (pc, x, y);
1464 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1465 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1466 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1467 gnome_print_lineto (pc, x, y);
1470 for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1471 x = x0 + r * cos (i_theta * G_PI / 180.0);
1472 y = y0 + r * sin (i_theta * G_PI / 180.0);
1473 gnome_print_lineto (pc, x, y);
1476 x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1477 y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1478 gnome_print_lineto (pc, x, y);
1480 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1481 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1482 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1483 gnome_print_lineto (pc, x, y);
1486 for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1487 x = x0 + r * cos (i_theta * G_PI / 180.0);
1488 y = y0 + r * sin (i_theta * G_PI / 180.0);
1489 gnome_print_lineto (pc, x, y);
1492 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1493 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1494 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1495 gnome_print_lineto (pc, x, y);
1498 x = x0 + r * cos (theta1 * G_PI / 180.0);
1499 y = y0 + r * sin (theta1 * G_PI / 180.0);
1500 gnome_print_lineto (pc, x, y);
1502 gnome_print_closepath (pc);
1504 gl_debug (DEBUG_PRINT, "END");
1507 #ifndef NO_ALPHA_HACK
1508 /*---------------------------------------------------------------------------*/
1509 /* PRIVATE. Extract a copy of rgba pixels, removing alpha by compositing */
1510 /* with a white background. */
1512 /* This is currently needed due to the lousy job gnome-print does in */
1513 /* rendering images with alpha channels to PS. This sacrafices the ability */
1514 /* to do compositing of images with other items in the background. */
1515 /*---------------------------------------------------------------------------*/
1517 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1519 gint bits_per_sample, channels;
1521 gint width, height, rowstride;
1523 guchar *buf_src, *buf_dest;
1524 guchar *p_src, *p_dest;
1527 gdouble alpha, beta;
1529 gl_debug (DEBUG_PRINT, "START");
1531 g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1533 /* extract pixels and parameters from pixbuf. */
1534 buf_src = gdk_pixbuf_get_pixels (pixbuf);
1535 bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1536 channels = gdk_pixbuf_get_n_channels (pixbuf);
1537 has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
1538 width = gdk_pixbuf_get_width (pixbuf);
1539 height = gdk_pixbuf_get_height (pixbuf);
1540 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1542 /* validate assumptions about pixbuf. */
1543 g_return_val_if_fail (buf_src, NULL);
1544 g_return_val_if_fail (bits_per_sample == 8, NULL);
1545 g_return_val_if_fail (channels == 4, NULL);
1546 g_return_val_if_fail (has_alpha, NULL);
1547 g_return_val_if_fail (width > 0, NULL);
1548 g_return_val_if_fail (height > 0, NULL);
1549 g_return_val_if_fail (rowstride > 0, NULL);
1551 /* Allocate a destination buffer */
1552 bytes = height * rowstride;
1553 gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1554 buf_dest = g_try_malloc (bytes);
1558 gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1560 /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1563 for ( iy=0; iy < height; iy++ ) {
1565 p_src = buf_src + iy*rowstride;
1566 p_dest = buf_dest + iy*rowstride;
1568 for ( ix=0; ix < width; ix++ ) {
1578 *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1579 *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1580 *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1586 gl_debug (DEBUG_PRINT, "START");