1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * print.c: Print module
8 * Copyright (C) 2001 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <glib/gi18n.h>
32 #include <gtk/gtkenums.h>
35 #include "label-text.h"
36 #include "label-box.h"
37 #include "label-line.h"
38 #include "label-ellipse.h"
39 #include "label-image.h"
40 #include "label-barcode.h"
42 #include <libglabels/template.h>
47 #define ARC_FINE 2 /* Resolution in degrees of large arcs */
48 #define ARC_COURSE 5 /* Resolution in degrees of small arcs */
50 #define TICK_OFFSET 2.25
51 #define TICK_LENGTH 18.0
53 /*=========================================================================*/
55 /*=========================================================================*/
57 typedef struct _PrintInfo {
58 /* gnome print context */
59 GnomePrintContext *pc;
61 /* gnome print configuration */
62 GnomePrintConfig *config;
64 /* gLabels Template */
66 gboolean label_rotate_flag;
77 /*=========================================================================*/
78 /* Private function prototypes. */
79 /*=========================================================================*/
80 static PrintInfo *print_info_new (GnomePrintJob *job,
83 static void print_info_free (PrintInfo **pi);
86 static void print_page_begin (PrintInfo *pi);
88 static void print_page_end (PrintInfo *pi);
90 static void print_crop_marks (PrintInfo *pi);
92 static void print_label (PrintInfo *pi,
96 glMergeRecord *record,
97 gboolean outline_flag,
98 gboolean reverse_flag);
101 static void draw_label (PrintInfo *pi,
103 glMergeRecord *record);
106 static void draw_object (PrintInfo *pi,
107 glLabelObject *object,
108 glMergeRecord *record);
110 static void draw_text_object (PrintInfo *pi,
112 glMergeRecord *record);
114 static void draw_box_object (PrintInfo *pi,
116 glMergeRecord *record);
118 static void draw_line_object (PrintInfo *pi,
120 glMergeRecord *record);
122 static void draw_ellipse_object (PrintInfo *pi,
123 glLabelEllipse *object,
124 glMergeRecord *record);
126 static void draw_image_object (PrintInfo *pi,
127 glLabelImage *object,
128 glMergeRecord *record);
130 static void draw_barcode_object (PrintInfo *pi,
131 glLabelBarcode *object,
132 glMergeRecord *record);
135 static void draw_outline (PrintInfo *pi,
138 static void clip_to_outline (PrintInfo *pi,
141 static void clip_punchouts (PrintInfo *pi,
145 static void create_rectangle_path (GnomePrintContext *pc,
151 static void create_ellipse_path (GnomePrintContext *pc,
157 static void create_rounded_rectangle_path (GnomePrintContext *pc,
164 static void create_clipped_circle_path (GnomePrintContext *pc,
171 #ifndef NO_ALPHA_HACK
172 static guchar * get_pixels_as_rgb (const GdkPixbuf *pixbuf);
176 /*****************************************************************************/
177 /* Simple (no merge data) print command. */
178 /*****************************************************************************/
180 gl_print_simple (GnomePrintJob *job,
188 const glTemplateLabelType *label_type;
189 gint i_sheet, i_label;
190 glTemplateOrigin *origins;
192 gl_debug (DEBUG_PRINT, "START");
194 pi = print_info_new (job, label);
195 label_type = gl_template_get_first_label_type (pi->template);
197 origins = gl_template_get_origins (label_type);
199 for (i_sheet = 0; i_sheet < n_sheets; i_sheet++) {
201 print_page_begin (pi);
202 if (flags->crop_marks) {
203 print_crop_marks (pi);
206 for (i_label = first - 1; i_label < last; i_label++) {
208 print_label (pi, label,
209 origins[i_label].x, origins[i_label].y,
210 NULL, flags->outline, flags->reverse);
219 print_info_free (&pi);
221 gl_debug (DEBUG_PRINT, "END");
224 /*****************************************************************************/
225 /* Merge print command (collated copies) */
226 /*****************************************************************************/
228 gl_print_merge_collated (GnomePrintJob *job,
235 const GList *record_list;
237 const glTemplateLabelType *label_type;
238 gint i_sheet, i_label, n_labels_per_page, i_copy;
239 glMergeRecord *record;
241 glTemplateOrigin *origins;
243 gl_debug (DEBUG_PRINT, "START");
245 merge = gl_label_get_merge (label);
246 record_list = gl_merge_get_record_list (merge);
248 pi = print_info_new (job, label);
249 label_type = gl_template_get_first_label_type (pi->template);
251 n_labels_per_page = gl_template_get_n_labels (label_type);
252 origins = gl_template_get_origins (label_type);
257 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
258 record = (glMergeRecord *)p->data;
260 if ( record->select_flag ) {
261 for (i_copy = 0; i_copy < n_copies; i_copy++) {
263 if ((i_label == 0) || (i_sheet == 0)) {
265 print_page_begin (pi);
266 if (flags->crop_marks) {
267 print_crop_marks (pi);
271 print_label (pi, label,
275 flags->outline, flags->reverse);
277 i_label = (i_label + 1) % n_labels_per_page;
291 print_info_free (&pi);
293 gl_debug (DEBUG_PRINT, "END");
296 /*****************************************************************************/
297 /* Merge print command (uncollated copies) */
298 /*****************************************************************************/
300 gl_print_merge_uncollated (GnomePrintJob *job,
307 const GList *record_list;
309 const glTemplateLabelType *label_type;
310 gint i_sheet, i_label, n_labels_per_page, i_copy;
311 glMergeRecord *record;
313 glTemplateOrigin *origins;
315 gl_debug (DEBUG_PRINT, "START");
317 merge = gl_label_get_merge (label);
318 record_list = gl_merge_get_record_list (merge);
320 pi = print_info_new (job, label);
321 label_type = gl_template_get_first_label_type (pi->template);
323 n_labels_per_page = gl_template_get_n_labels (label_type);
324 origins = gl_template_get_origins (label_type);
329 for (i_copy = 0; i_copy < n_copies; i_copy++) {
331 for ( p=(GList *)record_list; p!=NULL; p=p->next ) {
332 record = (glMergeRecord *)p->data;
334 if ( record->select_flag ) {
337 if ((i_label == 0) || (i_sheet == 0)) {
339 print_page_begin (pi);
340 if (flags->crop_marks) {
341 print_crop_marks (pi);
345 print_label (pi, label,
349 flags->outline, flags->reverse);
351 i_label = (i_label + 1) % n_labels_per_page;
365 print_info_free (&pi);
367 gl_debug (DEBUG_PRINT, "END");
370 /*****************************************************************************/
371 /* Batch print. Call appropriate function above. */
372 /*****************************************************************************/
374 gl_print_batch (GnomePrintJob *job,
382 glTemplate *template;
383 const glTemplateLabelType *label_type;
386 gl_debug (DEBUG_PRINT, "START");
388 merge = gl_label_get_merge (label);
389 template = gl_label_get_template (label);
390 label_type = gl_template_get_first_label_type (template);
392 if ( merge == NULL ) {
393 n_per_page = gl_template_get_n_labels(label_type);
395 gl_print_simple (job, label, n_sheets, first, n_per_page, flags);
397 gl_print_merge_collated (job, label, n_copies, first, flags);
399 gl_template_free (template);
401 gl_debug (DEBUG_PRINT, "END");
404 /*---------------------------------------------------------------------------*/
405 /* PRIVATE. new print info structure */
406 /*---------------------------------------------------------------------------*/
408 print_info_new (GnomePrintJob *job,
411 PrintInfo *pi = g_new0 (PrintInfo, 1);
412 glTemplate *template;
414 gl_debug (DEBUG_PRINT, "START");
416 g_return_val_if_fail (job && GNOME_IS_PRINT_JOB (job), NULL);
417 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
419 template = gl_label_get_template (label);
421 g_return_val_if_fail (template, NULL);
422 g_return_val_if_fail (template->page_size, NULL);
423 g_return_val_if_fail (template->page_width > 0, NULL);
424 g_return_val_if_fail (template->page_height > 0, NULL);
426 pi->pc = gnome_print_job_get_context (job);
427 pi->config = gnome_print_job_get_config (job);
429 gl_debug (DEBUG_PRINT,
430 "setting page size = \"%s\"", template->page_size);
432 gnome_print_config_set_length (pi->config,
433 (guchar *)GNOME_PRINT_KEY_PAPER_WIDTH,
434 template->page_width,
435 GNOME_PRINT_PS_UNIT);
436 gnome_print_config_set_length (pi->config,
437 (guchar *)GNOME_PRINT_KEY_PAPER_HEIGHT,
438 template->page_height,
439 GNOME_PRINT_PS_UNIT);
441 pi->page_width = template->page_width;
442 pi->page_height = template->page_height;
444 pi->template = template;
445 pi->label_rotate_flag = gl_label_get_rotate_flag (label);
449 gl_debug (DEBUG_PRINT, "END");
454 /*---------------------------------------------------------------------------*/
455 /* PRIVATE. free print info structure */
456 /*---------------------------------------------------------------------------*/
458 print_info_free (PrintInfo **pi)
460 gl_debug (DEBUG_PRINT, "START");
462 gl_template_free ((*pi)->template);
463 (*pi)->template = NULL;
465 gnome_print_context_close ((*pi)->pc);
470 gl_debug (DEBUG_PRINT, "END");
473 /*---------------------------------------------------------------------------*/
474 /* PRIVATE. Begin a new page. */
475 /*---------------------------------------------------------------------------*/
477 print_page_begin (PrintInfo *pi)
481 gl_debug (DEBUG_PRINT, "START");
485 str = g_strdup_printf ("sheet%02d", pi->sheet);
486 gnome_print_beginpage (pi->pc, (guchar *)str);
489 /* Translate and scale, so that our origin is at the upper left. */
490 gnome_print_translate (pi->pc, 0.0, pi->page_height);
491 gnome_print_scale (pi->pc, 1.0, -1.0);
493 gl_debug (DEBUG_PRINT, "END");
496 /*---------------------------------------------------------------------------*/
497 /* PRIVATE. End a page. */
498 /*---------------------------------------------------------------------------*/
500 print_page_end (PrintInfo *pi)
502 gl_debug (DEBUG_PRINT, "START");
504 gnome_print_showpage (pi->pc);
506 gl_debug (DEBUG_PRINT, "END");
509 /*---------------------------------------------------------------------------*/
510 /* PRIVATE. Print crop tick marks. */
511 /*---------------------------------------------------------------------------*/
513 print_crop_marks (PrintInfo *pi)
515 const glTemplateLabelType *label_type;
516 gdouble w, h, page_w, page_h;
518 glTemplateLayout *layout;
519 gdouble xmin, ymin, xmax, ymax, dx, dy;
520 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
523 gl_debug (DEBUG_PRINT, "START");
525 label_type = gl_template_get_first_label_type (pi->template);
527 gl_template_get_label_size (label_type, &w, &h);
529 page_w = pi->page_width;
530 page_h = pi->page_height;
532 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
533 gnome_print_setopacity (pi->pc, 1.0);
534 gnome_print_setlinewidth (pi->pc, 0.25);
536 for (p=label_type->layouts; p != NULL; p=p->next) {
538 layout = (glTemplateLayout *)p->data;
542 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
543 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
551 for (ix=0; ix < nx; ix++) {
556 y1 = MAX((ymin - TICK_OFFSET), 0.0);
557 y2 = MAX((y1 - TICK_LENGTH), 0.0);
559 y3 = MIN((ymax + TICK_OFFSET), page_h);
560 y4 = MIN((y3 + TICK_LENGTH), page_h);
562 gnome_print_moveto (pi->pc, x1, y1);
563 gnome_print_lineto (pi->pc, x1, y2);
564 gnome_print_stroke (pi->pc);
566 gnome_print_moveto (pi->pc, x2, y1);
567 gnome_print_lineto (pi->pc, x2, y2);
568 gnome_print_stroke (pi->pc);
570 gnome_print_moveto (pi->pc, x1, y3);
571 gnome_print_lineto (pi->pc, x1, y4);
572 gnome_print_stroke (pi->pc);
574 gnome_print_moveto (pi->pc, x2, y3);
575 gnome_print_lineto (pi->pc, x2, y4);
576 gnome_print_stroke (pi->pc);
580 for (iy=0; iy < ny; iy++) {
585 x1 = MAX((xmin - TICK_OFFSET), 0.0);
586 x2 = MAX((x1 - TICK_LENGTH), 0.0);
588 x3 = MIN((xmax + TICK_OFFSET), page_w);
589 x4 = MIN((x3 + TICK_LENGTH), page_w);
591 gnome_print_moveto (pi->pc, x1, y1);
592 gnome_print_lineto (pi->pc, x2, y1);
593 gnome_print_stroke (pi->pc);
595 gnome_print_moveto (pi->pc, x1, y2);
596 gnome_print_lineto (pi->pc, x2, y2);
597 gnome_print_stroke (pi->pc);
599 gnome_print_moveto (pi->pc, x3, y1);
600 gnome_print_lineto (pi->pc, x4, y1);
601 gnome_print_stroke (pi->pc);
603 gnome_print_moveto (pi->pc, x3, y2);
604 gnome_print_lineto (pi->pc, x4, y2);
605 gnome_print_stroke (pi->pc);
611 gl_debug (DEBUG_PRINT, "END");
614 /*---------------------------------------------------------------------------*/
615 /* PRIVATE. Print i'th label. */
616 /*---------------------------------------------------------------------------*/
618 print_label (PrintInfo *pi,
622 glMergeRecord *record,
623 gboolean outline_flag,
624 gboolean reverse_flag)
626 const glTemplateLabelType *label_type;
627 gdouble width, height;
629 gl_debug (DEBUG_PRINT, "START");
631 label_type = gl_template_get_first_label_type (pi->template);
633 gl_label_get_size (label, &width, &height);
635 gnome_print_gsave (pi->pc);
637 /* Transform coordinate system to be relative to upper corner */
638 /* of the current label */
639 gnome_print_translate (pi->pc, x, y);
640 if (gl_label_get_rotate_flag (label)) {
641 gl_debug (DEBUG_PRINT, "Rotate flag set");
642 gnome_print_rotate (pi->pc, -90.0);
643 gnome_print_translate (pi->pc, -width, 0.0);
645 if ( reverse_flag ) {
646 gnome_print_translate (pi->pc, width, 0.0);
647 gnome_print_scale (pi->pc, -1.0, 1.0);
650 clip_to_outline (pi, label);
651 draw_label (pi, label, record);
653 draw_outline (pi, label);
655 clip_punchouts (pi, label);
657 gnome_print_grestore (pi->pc);
659 gl_debug (DEBUG_PRINT, "END");
662 /*---------------------------------------------------------------------------*/
663 /* PRIVATE. Draw label. */
664 /*---------------------------------------------------------------------------*/
666 draw_label (PrintInfo *pi,
668 glMergeRecord *record)
671 glLabelObject *object;
673 gl_debug (DEBUG_PRINT, "START");
675 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
676 object = (glLabelObject *) p_obj->data;
678 draw_object (pi, object, record);
681 gl_debug (DEBUG_PRINT, "END");
684 /*---------------------------------------------------------------------------*/
685 /* PRIVATE. Draw object. */
686 /*---------------------------------------------------------------------------*/
688 draw_object (PrintInfo *pi,
689 glLabelObject *object,
690 glMergeRecord *record)
695 gl_debug (DEBUG_PRINT, "START");
697 gl_label_object_get_position (object, &x0, &y0);
698 gl_label_object_get_affine (object, affine);
700 gnome_print_gsave (pi->pc);
702 gnome_print_translate (pi->pc, x0, y0);
703 gnome_print_concat (pi->pc, affine);
705 if (GL_IS_LABEL_TEXT(object)) {
706 draw_text_object (pi, GL_LABEL_TEXT(object), record);
707 } else if (GL_IS_LABEL_BOX(object)) {
708 draw_box_object (pi, GL_LABEL_BOX(object), record);
709 } else if (GL_IS_LABEL_LINE(object)) {
710 draw_line_object (pi, GL_LABEL_LINE(object), record);
711 } else if (GL_IS_LABEL_ELLIPSE(object)) {
712 draw_ellipse_object (pi, GL_LABEL_ELLIPSE(object), record);
713 } else if (GL_IS_LABEL_IMAGE(object)) {
714 draw_image_object (pi, GL_LABEL_IMAGE(object), record);
715 } else if (GL_IS_LABEL_BARCODE(object)) {
716 draw_barcode_object (pi, GL_LABEL_BARCODE(object), record);
719 gnome_print_grestore (pi->pc);
721 gl_debug (DEBUG_PRINT, "END");
724 /*---------------------------------------------------------------------------*/
725 /* PRIVATE. Draw text object. */
726 /*---------------------------------------------------------------------------*/
728 draw_text_object (PrintInfo *pi,
730 glMergeRecord *record)
735 gdouble x_offset, y_offset, w, object_w, object_h;
740 GnomeFontWeight font_weight;
741 gboolean font_italic_flag;
743 glColorNode *color_node;
744 GtkJustification just;
745 gboolean auto_shrink;
746 GnomeGlyphList *glyphlist;
749 gdouble text_line_spacing;
752 gl_debug (DEBUG_PRINT, "START");
754 gl_label_object_get_size (GL_LABEL_OBJECT(object), &object_w, &object_h);
755 lines = gl_label_text_get_lines (object);
756 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object));
757 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object));
758 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object));
759 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object));
761 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object));
762 color = gl_color_node_expand (color_node, record);
763 gl_color_node_free (&color_node);
765 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object));
767 gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object));
768 auto_shrink = gl_label_text_get_auto_shrink (object);
770 text = gl_text_node_lines_expand (lines, record);
771 line = g_strsplit (text, "\n", -1);
774 art_affine_identity (affine);
776 if (record && auto_shrink) {
777 /* auto shrink text size to keep within text box limits. */
778 for (i = 0; line[i] != NULL; i++) {
780 font = gnome_font_find_closest_from_weight_slant (
781 (guchar *)font_family,
785 glyphlist = gnome_glyphlist_from_text_dumb (
790 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
792 gnome_glyphlist_unref (glyphlist);
794 /* If width is too large, iteratively shrink font_size until this
795 line fits the width, or until the font size is ridiculously
797 while ( (w > object_w) && (font_size >= 1.0) ) {
801 font = gnome_font_find_closest_from_weight_slant (
802 (guchar *)font_family,
806 glyphlist = gnome_glyphlist_from_text_dumb (
811 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
813 gnome_glyphlist_unref (glyphlist);
819 font = gnome_font_find_closest_from_weight_slant (
820 (guchar *)font_family,
824 gnome_print_setfont (pi->pc, font);
826 gnome_print_setrgbcolor (pi->pc,
827 GL_COLOR_F_RED (color),
828 GL_COLOR_F_GREEN (color),
829 GL_COLOR_F_BLUE (color));
830 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (color));
832 for (i = 0; line[i] != NULL; i++) {
834 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
838 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
840 gnome_glyphlist_unref (glyphlist);
843 case GTK_JUSTIFY_LEFT:
844 x_offset = GL_LABEL_TEXT_MARGIN;
846 case GTK_JUSTIFY_CENTER:
847 x_offset = (object_w - GL_LABEL_TEXT_MARGIN - w) / 2.0;
849 case GTK_JUSTIFY_RIGHT:
850 x_offset = object_w - GL_LABEL_TEXT_MARGIN - w;
854 break; /* shouldn't happen */
857 /* Work out the y position to the BOTTOM of the first line */
858 y_offset = GL_LABEL_TEXT_MARGIN +
859 + gnome_font_get_descender (font)
860 + (i + 1) * font_size * text_line_spacing;
862 /* Remove any text line spacing from the first row. */
863 y_offset -= font_size * (text_line_spacing - 1);
866 gnome_print_moveto (pi->pc, x_offset, y_offset);
868 gnome_print_gsave (pi->pc);
869 gnome_print_scale (pi->pc, 1.0, -1.0);
870 gnome_print_show (pi->pc, (guchar *)line[i]);
871 gnome_print_grestore (pi->pc);
876 gl_text_node_lines_free (&lines);
877 g_free (font_family);
879 gl_debug (DEBUG_PRINT, "END");
882 /*---------------------------------------------------------------------------*/
883 /* PRIVATE. Draw box object. */
884 /*---------------------------------------------------------------------------*/
886 draw_box_object (PrintInfo *pi,
888 glMergeRecord *record)
893 glColorNode *line_color_node;
894 glColorNode *fill_color_node;
896 gboolean shadow_state;
897 gdouble shadow_x, shadow_y;
898 glColorNode *shadow_color_node;
899 gdouble shadow_opacity;
900 guint shadow_line_color;
901 guint shadow_fill_color;
903 gl_debug (DEBUG_PRINT, "START");
905 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
906 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
908 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
909 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
910 line_color = gl_color_node_expand (line_color_node, record);
911 fill_color = gl_color_node_expand (fill_color_node, record);
912 gl_color_node_free (&line_color_node);
913 gl_color_node_free (&fill_color_node);
915 shadow_state = gl_label_object_get_shadow_state (GL_LABEL_OBJECT (object));
916 gl_label_object_get_shadow_offset (GL_LABEL_OBJECT (object), &shadow_x, &shadow_y);
917 shadow_color_node = gl_label_object_get_shadow_color (GL_LABEL_OBJECT (object));
918 if (shadow_color_node->field_flag)
920 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
922 shadow_opacity = gl_label_object_get_shadow_opacity (GL_LABEL_OBJECT (object));
923 shadow_line_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, line_color);
924 shadow_fill_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, fill_color);
925 gl_color_node_free (&shadow_color_node);
929 /* Draw fill shadow */
930 create_rectangle_path (pi->pc, shadow_x, shadow_y, w, h);
931 gnome_print_setrgbcolor (pi->pc,
932 GL_COLOR_F_RED (shadow_fill_color),
933 GL_COLOR_F_GREEN (shadow_fill_color),
934 GL_COLOR_F_BLUE (shadow_fill_color));
935 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (shadow_fill_color));
936 gnome_print_fill (pi->pc);
938 /* Draw outline shadow */
939 create_rectangle_path (pi->pc, shadow_x, shadow_y, w, h);
940 gnome_print_setrgbcolor (pi->pc,
941 GL_COLOR_F_RED (shadow_line_color),
942 GL_COLOR_F_GREEN (shadow_line_color),
943 GL_COLOR_F_BLUE (shadow_line_color));
944 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (shadow_line_color));
945 gnome_print_setlinewidth (pi->pc, line_width);
946 gnome_print_stroke (pi->pc);
949 /* Paint fill color */
950 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
951 gnome_print_setrgbcolor (pi->pc,
952 GL_COLOR_F_RED (fill_color),
953 GL_COLOR_F_GREEN (fill_color),
954 GL_COLOR_F_BLUE (fill_color));
955 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
956 gnome_print_fill (pi->pc);
959 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
960 gnome_print_setrgbcolor (pi->pc,
961 GL_COLOR_F_RED (line_color),
962 GL_COLOR_F_GREEN (line_color),
963 GL_COLOR_F_BLUE (line_color));
964 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
965 gnome_print_setlinewidth (pi->pc, line_width);
966 gnome_print_stroke (pi->pc);
968 gl_debug (DEBUG_PRINT, "END");
971 /*---------------------------------------------------------------------------*/
972 /* PRIVATE. Draw line object. */
973 /*---------------------------------------------------------------------------*/
975 draw_line_object (PrintInfo *pi,
977 glMergeRecord *record)
982 glColorNode *line_color_node;
984 gl_debug (DEBUG_PRINT, "START");
986 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
987 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
989 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
990 line_color = gl_color_node_expand (line_color_node, record);
991 gl_color_node_free (&line_color_node);
993 gnome_print_moveto (pi->pc, 0.0, 0.0);
994 gnome_print_lineto (pi->pc, w, h);
995 gnome_print_setrgbcolor (pi->pc,
996 GL_COLOR_F_RED (line_color),
997 GL_COLOR_F_GREEN (line_color),
998 GL_COLOR_F_BLUE (line_color));
999 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
1000 gnome_print_setlinewidth (pi->pc, line_width);
1001 gnome_print_stroke (pi->pc);
1003 gl_debug (DEBUG_PRINT, "END");
1006 /*---------------------------------------------------------------------------*/
1007 /* PRIVATE. Draw ellipse object. */
1008 /*---------------------------------------------------------------------------*/
1010 draw_ellipse_object (PrintInfo *pi,
1011 glLabelEllipse *object,
1012 glMergeRecord *record)
1014 gdouble x0, y0, rx, ry, w, h;
1016 glColorNode *line_color_node;
1017 glColorNode *fill_color_node;
1021 gl_debug (DEBUG_PRINT, "START");
1023 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1024 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1026 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1027 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1028 line_color = gl_color_node_expand (line_color_node, record);
1029 fill_color = gl_color_node_expand (fill_color_node, record);
1030 gl_color_node_free (&line_color_node);
1031 gl_color_node_free (&fill_color_node);
1038 /* Paint fill color */
1039 create_ellipse_path (pi->pc, x0, y0, rx, ry);
1040 gnome_print_setrgbcolor (pi->pc,
1041 GL_COLOR_F_RED (fill_color),
1042 GL_COLOR_F_GREEN (fill_color),
1043 GL_COLOR_F_BLUE (fill_color));
1044 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (fill_color));
1045 gnome_print_fill (pi->pc);
1048 create_ellipse_path (pi->pc, x0, y0, rx, ry);
1049 gnome_print_setrgbcolor (pi->pc,
1050 GL_COLOR_F_RED (line_color),
1051 GL_COLOR_F_GREEN (line_color),
1052 GL_COLOR_F_BLUE (line_color));
1053 gnome_print_setopacity (pi->pc, GL_COLOR_F_ALPHA (line_color));
1054 gnome_print_setlinewidth (pi->pc, line_width);
1055 gnome_print_stroke (pi->pc);
1057 gl_debug (DEBUG_PRINT, "END");
1060 /*---------------------------------------------------------------------------*/
1061 /* PRIVATE. Draw image object. */
1062 /*---------------------------------------------------------------------------*/
1064 draw_image_object (PrintInfo *pi,
1065 glLabelImage *object,
1066 glMergeRecord *record)
1069 const GdkPixbuf *pixbuf;
1071 gint image_w, image_h, image_stride;
1072 gboolean image_alpha_flag;
1075 gl_debug (DEBUG_PRINT, "START");
1077 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1079 pixbuf = gl_label_image_get_pixbuf (object, record);
1080 image_data = gdk_pixbuf_get_pixels (pixbuf);
1081 image_w = gdk_pixbuf_get_width (pixbuf);
1082 image_h = gdk_pixbuf_get_height (pixbuf);
1083 image_stride = gdk_pixbuf_get_rowstride(pixbuf);
1084 image_alpha_flag = gdk_pixbuf_get_has_alpha(pixbuf);
1086 gnome_print_gsave (pi->pc);
1087 gnome_print_translate (pi->pc, 0.0, h);
1088 gnome_print_scale (pi->pc, w, -h);
1089 if (image_alpha_flag) {
1090 #ifndef NO_ALPHA_HACK
1091 guchar *image_data2;
1093 image_data2 = get_pixels_as_rgb (pixbuf);
1094 ret = gnome_print_rgbimage (pi->pc, image_data2,
1095 image_w, image_h, image_stride);
1096 g_free (image_data2);
1098 ret = gnome_print_rgbaimage (pi->pc, image_data,
1099 image_w, image_h, image_stride);
1102 ret = gnome_print_rgbimage (pi->pc, image_data,
1103 image_w, image_h, image_stride);
1105 gnome_print_grestore (pi->pc);
1107 gl_debug (DEBUG_PRINT, "END");
1110 /*---------------------------------------------------------------------------*/
1111 /* PRIVATE. Draw box object. */
1112 /*---------------------------------------------------------------------------*/
1114 draw_barcode_object (PrintInfo *pi,
1115 glLabelBarcode *object,
1116 glMergeRecord *record)
1119 glBarcodeLine *line;
1120 glBarcodeChar *bchar;
1124 gchar *text, *cstring;
1125 glTextNode *text_node;
1128 gboolean checksum_flag;
1130 glColorNode *color_node;
1131 guint format_digits;
1134 gl_debug (DEBUG_PRINT, "START");
1136 text_node = gl_label_barcode_get_data (object);
1137 gl_label_barcode_get_props (object,
1138 &id, &text_flag, &checksum_flag, &format_digits);
1140 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1141 color = gl_color_node_expand (color_node, record);
1142 gl_color_node_free (&color_node);
1144 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1146 text = gl_text_node_expand (text_node, record);
1147 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
1149 gl_text_node_free (&text_node);
1154 font = gnome_font_find_closest_from_weight_slant (
1155 (guchar *)GL_BARCODE_FONT_FAMILY,
1156 GL_BARCODE_FONT_WEIGHT,
1158 gnome_print_setfont (pi->pc, font);
1160 gnome_print_setrgbcolor (pi->pc,
1161 GL_COLOR_F_RED (color),
1162 GL_COLOR_F_GREEN (color),
1163 GL_COLOR_F_BLUE (color));
1164 gnome_print_setopacity (pi->pc,
1165 GL_COLOR_F_ALPHA (color));
1167 y_offset = 12.0 - fabs (gnome_font_get_descender (font));
1168 gnome_print_moveto (pi->pc, 0.0, y_offset);
1170 gnome_print_gsave (pi->pc);
1171 gnome_print_scale (pi->pc, 1.0, -1.0);
1172 gnome_print_show (pi->pc, (guchar *)_("Invalid barcode data"));
1173 gnome_print_grestore (pi->pc);
1177 for (li = gbc->lines; li != NULL; li = li->next) {
1178 line = (glBarcodeLine *) li->data;
1180 gnome_print_moveto (pi->pc, line->x, line->y);
1181 gnome_print_lineto (pi->pc, line->x, line->y + line->length);
1182 gnome_print_setrgbcolor (pi->pc,
1183 GL_COLOR_F_RED (color),
1184 GL_COLOR_F_GREEN (color),
1185 GL_COLOR_F_BLUE (color));
1186 gnome_print_setopacity (pi->pc,
1187 GL_COLOR_F_ALPHA (color));
1188 gnome_print_setlinewidth (pi->pc, line->width);
1189 gnome_print_stroke (pi->pc);
1192 for (li = gbc->chars; li != NULL; li = li->next) {
1193 bchar = (glBarcodeChar *) li->data;
1195 font = gnome_font_find_closest_from_weight_slant (
1196 (guchar *)GL_BARCODE_FONT_FAMILY,
1197 GL_BARCODE_FONT_WEIGHT,
1198 FALSE, bchar->fsize);
1199 gnome_print_setfont (pi->pc, font);
1201 gnome_print_setrgbcolor (pi->pc,
1202 GL_COLOR_F_RED (color),
1203 GL_COLOR_F_GREEN (color),
1204 GL_COLOR_F_BLUE (color));
1205 gnome_print_setopacity (pi->pc,
1206 GL_COLOR_F_ALPHA (color));
1209 bchar->fsize - fabs (gnome_font_get_descender (font));
1211 gnome_print_moveto (pi->pc, bchar->x, bchar->y+y_offset);
1213 cstring = g_strdup_printf ("%c", bchar->c);
1214 gnome_print_gsave (pi->pc);
1215 gnome_print_scale (pi->pc, 1.0, -1.0);
1216 gnome_print_show (pi->pc, (guchar *)cstring);
1217 gnome_print_grestore (pi->pc);
1222 gl_barcode_free (&gbc);
1226 gl_debug (DEBUG_PRINT, "END");
1229 /*---------------------------------------------------------------------------*/
1230 /* PRIVATE. Draw outline. */
1231 /*---------------------------------------------------------------------------*/
1233 draw_outline (PrintInfo *pi,
1236 const glTemplateLabelType *label_type;
1240 gl_debug (DEBUG_PRINT, "START");
1242 label_type = gl_template_get_first_label_type (pi->template);
1244 gnome_print_setrgbcolor (pi->pc, 0.0, 0.0, 0.0);
1245 gnome_print_setopacity (pi->pc, 1.0);
1246 gnome_print_setlinewidth (pi->pc, 0.25);
1248 switch (label_type->shape) {
1250 case GL_TEMPLATE_SHAPE_RECT:
1251 gl_label_get_size (label, &w, &h);
1252 r = label_type->size.rect.r;
1254 /* simple rectangle */
1255 create_rectangle_path (pi->pc, 0.0, 0.0, w, h);
1257 /* rectangle with rounded corners */
1258 create_rounded_rectangle_path (pi->pc, 0.0, 0.0,
1261 gnome_print_stroke (pi->pc);
1264 case GL_TEMPLATE_SHAPE_ROUND:
1266 r1 = label_type->size.round.r;
1267 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1268 gnome_print_stroke (pi->pc);
1271 case GL_TEMPLATE_SHAPE_CD:
1272 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1273 /* CD style, round label w/ concentric round hole */
1274 r1 = label_type->size.cd.r1;
1275 r2 = label_type->size.cd.r2;
1276 create_ellipse_path (pi->pc, r1, r1, r1, r1);
1277 gnome_print_stroke (pi->pc);
1278 create_ellipse_path (pi->pc, r1, r1, r2, r2);
1279 gnome_print_stroke (pi->pc);
1281 /* Business Card CD style, clipped round label w/ hole */
1282 gl_label_get_size (label, &w, &h);
1283 r1 = label_type->size.cd.r1;
1284 r2 = label_type->size.cd.r2;
1285 create_clipped_circle_path (pi->pc, w/2, h/2, w, h, r1);
1286 gnome_print_stroke (pi->pc);
1287 create_ellipse_path (pi->pc, w/2, h/2, r2, r2);
1288 gnome_print_stroke (pi->pc);
1293 g_message ("Unknown template label style");
1297 gl_debug (DEBUG_PRINT, "END");
1300 /*---------------------------------------------------------------------------*/
1301 /* PRIVATE. Clip to outline. */
1302 /*---------------------------------------------------------------------------*/
1304 clip_to_outline (PrintInfo *pi,
1307 const glTemplateLabelType *label_type;
1310 gdouble waste, x_waste, y_waste;
1312 gl_debug (DEBUG_PRINT, "START");
1314 label_type = gl_template_get_first_label_type (pi->template);
1316 switch (label_type->shape) {
1318 case GL_TEMPLATE_SHAPE_RECT:
1319 gl_label_get_size (label, &w, &h);
1320 r = label_type->size.rect.r;
1321 x_waste = label_type->size.rect.x_waste;
1322 y_waste = label_type->size.rect.y_waste;
1324 /* simple rectangle */
1325 create_rectangle_path (pi->pc,
1327 w+2*x_waste, h+2*y_waste);
1329 /* rectangle with rounded corners */
1330 create_rounded_rectangle_path (pi->pc,
1332 w+2*x_waste, h+2*y_waste, r);
1334 gnome_print_clip (pi->pc);
1337 case GL_TEMPLATE_SHAPE_ROUND:
1338 r1 = label_type->size.round.r;
1339 waste = label_type->size.round.waste;
1340 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1341 gnome_print_clip (pi->pc);
1344 case GL_TEMPLATE_SHAPE_CD:
1345 waste = label_type->size.cd.waste;
1346 if ((label_type->size.cd.h == 0) && (label_type->size.cd.w == 0)) {
1347 /* CD style, round label w/ concentric round hole */
1348 r1 = label_type->size.cd.r1;
1349 create_ellipse_path (pi->pc, r1, r1, r1+waste, r1+waste);
1351 /* Business Card CD style, clipped round label w/ hole */
1352 gl_label_get_size (label, &w, &h);
1353 r1 = label_type->size.cd.r1;
1354 create_clipped_circle_path (pi->pc,
1356 w+2*waste, h+2*waste,
1359 gnome_print_clip (pi->pc);
1363 g_message ("Unknown template label style");
1367 gl_debug (DEBUG_PRINT, "END");
1370 /*---------------------------------------------------------------------------*/
1371 /* PRIVATE. Clip punchouts. (Save some ink by not printing in CD holes) */
1373 /* Ideally this would be done in clip_to_outline, but I am not sure how to */
1374 /* invert the region for gnome_print_clip, so instead, I will just draw */
1375 /* a white circle on top of everything else. */
1376 /*---------------------------------------------------------------------------*/
1378 clip_punchouts (PrintInfo *pi,
1381 const glTemplateLabelType *label_type;
1385 gl_debug (DEBUG_PRINT, "START");
1387 label_type = gl_template_get_first_label_type (pi->template);
1389 switch (label_type->shape) {
1391 case GL_TEMPLATE_SHAPE_RECT:
1392 case GL_TEMPLATE_SHAPE_ROUND:
1395 case GL_TEMPLATE_SHAPE_CD:
1396 gl_label_get_size (label, &w, &h);
1397 waste = label_type->size.cd.waste;
1398 r2 = label_type->size.cd.r2;
1399 create_ellipse_path (pi->pc, w/2, h/2, r2-waste, r2-waste);
1400 gnome_print_setrgbcolor (pi->pc, 1.0, 1.0, 1.0);
1401 gnome_print_setopacity (pi->pc, 1.0);
1402 gnome_print_fill (pi->pc);
1406 g_message ("Unknown template label style");
1410 gl_debug (DEBUG_PRINT, "END");
1413 /*---------------------------------------------------------------------------*/
1414 /* PRIVATE. Path creation utilities. */
1415 /*---------------------------------------------------------------------------*/
1417 create_rectangle_path (GnomePrintContext *pc,
1423 gl_debug (DEBUG_PRINT, "START");
1425 gnome_print_newpath (pc);
1426 gnome_print_moveto (pc, x0, y0);
1427 gnome_print_lineto (pc, x0 + w, y0);
1428 gnome_print_lineto (pc, x0 + w, y0 + h);
1429 gnome_print_lineto (pc, x0, y0 + h);
1430 gnome_print_lineto (pc, x0, y0);
1431 gnome_print_closepath (pc);
1433 gl_debug (DEBUG_PRINT, "END");
1437 create_ellipse_path (GnomePrintContext *pc,
1446 gl_debug (DEBUG_PRINT, "START");
1448 gnome_print_newpath (pc);
1449 gnome_print_moveto (pc, x0 + rx, y0);
1450 for (i_theta = ARC_FINE; i_theta <= 360; i_theta += ARC_FINE) {
1451 x = x0 + rx * cos (i_theta * G_PI / 180.0);
1452 y = y0 + ry * sin (i_theta * G_PI / 180.0);
1453 gnome_print_lineto (pc, x, y);
1455 gnome_print_closepath (pc);
1457 gl_debug (DEBUG_PRINT, "END");
1461 create_rounded_rectangle_path (GnomePrintContext *pc,
1471 gl_debug (DEBUG_PRINT, "START");
1473 gnome_print_newpath (pc);
1475 gnome_print_moveto (pc, x0 + r, y0);
1476 for (i_theta = ARC_COURSE; i_theta <= 90; i_theta += ARC_COURSE) {
1477 x = x0 + r - r * sin (i_theta * G_PI / 180.0);
1478 y = y0 + r - r * cos (i_theta * G_PI / 180.0);
1479 gnome_print_lineto (pc, x, y);
1481 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1482 x = x0 + r - r * cos (i_theta * G_PI / 180.0);
1483 y = y0 + (h - r) + r * sin (i_theta * G_PI / 180.0);
1484 gnome_print_lineto (pc, x, y);
1486 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1487 x = x0 + (w - r) + r * sin (i_theta * G_PI / 180.0);
1488 y = y0 + (h - r) + r * cos (i_theta * G_PI / 180.0);
1489 gnome_print_lineto (pc, x, y);
1491 for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1492 x = x0 + (w - r) + r * cos (i_theta * G_PI / 180.0);
1493 y = y0 + r - r * sin (i_theta * G_PI / 180.0);
1494 gnome_print_lineto (pc, x, y);
1496 gnome_print_lineto (pc, x0 + r, y0);
1498 gnome_print_closepath (pc);
1500 gl_debug (DEBUG_PRINT, "END");
1504 create_clipped_circle_path (GnomePrintContext *pc,
1512 gdouble theta1, theta2;
1515 gl_debug (DEBUG_PRINT, "START");
1517 theta1 = (180.0/G_PI) * acos (w / (2.0*r));
1518 theta2 = (180.0/G_PI) * asin (h / (2.0*r));
1520 gnome_print_newpath (pc);
1522 x = x0 + r * cos (theta1 * G_PI / 180.0);
1523 y = y0 + r * sin (theta1 * G_PI / 180.0);
1524 gnome_print_moveto (pc, x, y);
1526 for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1527 x = x0 + r * cos (i_theta * G_PI / 180.0);
1528 y = y0 + r * sin (i_theta * G_PI / 180.0);
1529 gnome_print_lineto (pc, x, y);
1532 x = x0 + r * cos (theta2 * G_PI / 180.0);
1533 y = y0 + r * sin (theta2 * G_PI / 180.0);
1534 gnome_print_lineto (pc, x, y);
1536 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1537 x = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1538 y = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1539 gnome_print_lineto (pc, x, y);
1542 for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1543 x = x0 + r * cos (i_theta * G_PI / 180.0);
1544 y = y0 + r * sin (i_theta * G_PI / 180.0);
1545 gnome_print_lineto (pc, x, y);
1548 x = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1549 y = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1550 gnome_print_lineto (pc, x, y);
1552 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1553 x = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1554 y = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1555 gnome_print_lineto (pc, x, y);
1558 for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1559 x = x0 + r * cos (i_theta * G_PI / 180.0);
1560 y = y0 + r * sin (i_theta * G_PI / 180.0);
1561 gnome_print_lineto (pc, x, y);
1564 x = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1565 y = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1566 gnome_print_lineto (pc, x, y);
1568 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1569 x = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1570 y = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1571 gnome_print_lineto (pc, x, y);
1574 for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1575 x = x0 + r * cos (i_theta * G_PI / 180.0);
1576 y = y0 + r * sin (i_theta * G_PI / 180.0);
1577 gnome_print_lineto (pc, x, y);
1580 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1581 x = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1582 y = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1583 gnome_print_lineto (pc, x, y);
1586 x = x0 + r * cos (theta1 * G_PI / 180.0);
1587 y = y0 + r * sin (theta1 * G_PI / 180.0);
1588 gnome_print_lineto (pc, x, y);
1590 gnome_print_closepath (pc);
1592 gl_debug (DEBUG_PRINT, "END");
1595 #ifndef NO_ALPHA_HACK
1596 /*---------------------------------------------------------------------------*/
1597 /* PRIVATE. Extract a copy of rgba pixels, removing alpha by compositing */
1598 /* with a white background. */
1600 /* This is currently needed due to the lousy job gnome-print does in */
1601 /* rendering images with alpha channels to PS. This sacrafices the ability */
1602 /* to do compositing of images with other items in the background. */
1603 /*---------------------------------------------------------------------------*/
1605 get_pixels_as_rgb (const GdkPixbuf *pixbuf)
1607 gint bits_per_sample, channels;
1609 gint width, height, rowstride;
1611 guchar *buf_src, *buf_dest;
1612 guchar *p_src, *p_dest;
1615 gdouble alpha, beta;
1617 gl_debug (DEBUG_PRINT, "START");
1619 g_return_val_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf), NULL);
1621 /* extract pixels and parameters from pixbuf. */
1622 buf_src = gdk_pixbuf_get_pixels (pixbuf);
1623 bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
1624 channels = gdk_pixbuf_get_n_channels (pixbuf);
1625 has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
1626 width = gdk_pixbuf_get_width (pixbuf);
1627 height = gdk_pixbuf_get_height (pixbuf);
1628 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1630 /* validate assumptions about pixbuf. */
1631 g_return_val_if_fail (buf_src, NULL);
1632 g_return_val_if_fail (bits_per_sample == 8, NULL);
1633 g_return_val_if_fail (channels == 4, NULL);
1634 g_return_val_if_fail (has_alpha, NULL);
1635 g_return_val_if_fail (width > 0, NULL);
1636 g_return_val_if_fail (height > 0, NULL);
1637 g_return_val_if_fail (rowstride > 0, NULL);
1639 /* Allocate a destination buffer */
1640 bytes = height * rowstride;
1641 gl_debug (DEBUG_PRINT, "bytes = %d", bytes);
1642 buf_dest = g_try_malloc (bytes);
1646 gl_debug (DEBUG_PRINT, "buf_dest = %x", buf_dest);
1648 /* Copy pixels, transforming rgba to rgb by compositing with a white bg. */
1651 for ( iy=0; iy < height; iy++ ) {
1653 p_src = buf_src + iy*rowstride;
1654 p_dest = buf_dest + iy*rowstride;
1656 for ( ix=0; ix < width; ix++ ) {
1666 *p_dest++ = (guchar) (alpha*r + beta*255 + 0.5);
1667 *p_dest++ = (guchar) (alpha*g + beta*255 + 0.5);
1668 *p_dest++ = (guchar) (alpha*b + beta*255 + 0.5);
1674 gl_debug (DEBUG_PRINT, "START");