From 3929cc2624e54f73d17a5b5851303559c44e4d36 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Tue, 18 Sep 2007 17:58:21 +0000 Subject: [PATCH] 2007-09-18 [colin] 3.0.1cvs7 * src/prefs_common.c * src/prefs_common.h * src/prefs_image_viewer.c * src/printing.c GtkPrintOperation: - add image printing support - add option to print images - add preview widget - add saving of a few Page Setup parameters --- ChangeLog | 12 ++ PATCHSETS | 1 + configure.ac | 2 +- src/prefs_common.c | 16 ++ src/prefs_common.h | 8 + src/prefs_image_viewer.c | 17 +- src/printing.c | 405 ++++++++++++++++++++++++++++++++++----- 7 files changed, 416 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8040de082..db4891bde 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-09-18 [colin] 3.0.1cvs7 + + * src/prefs_common.c + * src/prefs_common.h + * src/prefs_image_viewer.c + * src/printing.c + GtkPrintOperation: + - add image printing support + - add option to print images + - add preview widget + - add saving of a few Page Setup parameters + 2007-09-18 [colin] 3.0.1cvs6 * AUTHORS diff --git a/PATCHSETS b/PATCHSETS index 9d4d84a11..d2991e33e 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -2870,3 +2870,4 @@ ( cvs diff -u -r 1.43.2.82 -r 1.43.2.83 src/toolbar.c; ) > 3.0.1cvs4.patchset ( cvs diff -u -r 1.36.2.111 -r 1.36.2.112 src/common/utils.c; ) > 3.0.1cvs5.patchset ( cvs diff -u -r 1.100.2.52 -r 1.100.2.53 AUTHORS; cvs diff -u -r 1.1.2.39 -r 1.1.2.40 src/gtk/authors.h; ) > 3.0.1cvs6.patchset +( cvs diff -u -r 1.204.2.147 -r 1.204.2.148 src/prefs_common.c; cvs diff -u -r 1.103.2.93 -r 1.103.2.94 src/prefs_common.h; cvs diff -u -r 1.1.2.9 -r 1.1.2.10 src/prefs_image_viewer.c; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/printing.c; ) > 3.0.1cvs7.patchset diff --git a/configure.ac b/configure.ac index 1d488378b..ae08fa77a 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=0 MICRO_VERSION=1 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=6 +EXTRA_VERSION=7 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/prefs_common.c b/src/prefs_common.c index d3c9fe647..3d46370cd 100644 --- a/src/prefs_common.c +++ b/src/prefs_common.c @@ -1051,6 +1051,22 @@ static PrefParam param[] = { {"real_time_sync", "TRUE", &prefs_common.real_time_sync, P_BOOL, NULL, NULL, NULL}, #endif + + {"print_paper_type", NULL, &prefs_common.print_paper_type, P_STRING, + NULL, NULL, NULL}, + {"print_paper_orientation", "0", &prefs_common.print_paper_orientation, P_INT, + NULL, NULL, NULL}, + {"print_use_color", "0", &prefs_common.print_use_color, P_INT, + NULL, NULL, NULL}, + {"print_use_collate", "0", &prefs_common.print_use_collate, P_INT, + NULL, NULL, NULL}, + {"print_use_reverse", "0", &prefs_common.print_use_reverse, P_INT, + NULL, NULL, NULL}, + {"print_use_duplex", "0", &prefs_common.print_use_duplex, P_INT, + NULL, NULL, NULL}, + {"print_imgs", "1", &prefs_common.print_imgs, P_INT, + NULL, NULL, NULL}, + {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL} }; diff --git a/src/prefs_common.h b/src/prefs_common.h index 363ee7eb6..648eb575a 100644 --- a/src/prefs_common.h +++ b/src/prefs_common.h @@ -463,6 +463,14 @@ struct _PrefsCommon gint hide_quotes; gboolean unsafe_ssl_certs; gboolean real_time_sync; + + gchar *print_paper_type; + gint print_paper_orientation; + gint print_use_color; + gint print_use_collate; + gint print_use_reverse; + gint print_use_duplex; + gint print_imgs; }; extern PrefsCommon prefs_common; diff --git a/src/prefs_image_viewer.c b/src/prefs_image_viewer.c index 35ed90b14..cf3f02b11 100644 --- a/src/prefs_image_viewer.c +++ b/src/prefs_image_viewer.c @@ -44,6 +44,7 @@ typedef struct _ImageViewerPage GtkWidget *autoload_img; GtkWidget *resize_img; GtkWidget *inline_img; + GtkWidget *print_imgs; }ImageViewerPage; static void imageviewer_create_widget_func(PrefsPage * _page, @@ -56,9 +57,10 @@ static void imageviewer_create_widget_func(PrefsPage * _page, GtkWidget *autoload_img; GtkWidget *resize_img; GtkWidget *inline_img; + GtkWidget *print_imgs; GtkTooltips *resize_tooltip; - table = gtk_table_new(3, 1, FALSE); + table = gtk_table_new(4, 1, FALSE); gtk_widget_show(table); gtk_container_set_border_width(GTK_CONTAINER(table), VBOX_BORDER); gtk_table_set_row_spacings(GTK_TABLE(table), 4); @@ -87,14 +89,24 @@ static void imageviewer_create_widget_func(PrefsPage * _page, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); + print_imgs = gtk_check_button_new_with_label(_("Print images")); +#if !defined(USE_GNOMEPRINT) && GTK_CHECK_VERSION(2,10,0) + gtk_widget_show(print_imgs); +#endif + gtk_table_attach(GTK_TABLE(table), print_imgs, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resize_img), prefs_common.resize_img); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autoload_img), prefs_common.display_img); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(inline_img), prefs_common.inline_img); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_imgs), prefs_common.print_imgs); prefs_imageviewer->window = GTK_WIDGET(window); prefs_imageviewer->autoload_img = autoload_img; prefs_imageviewer->resize_img = resize_img; prefs_imageviewer->inline_img = inline_img; + prefs_imageviewer->print_imgs = print_imgs; prefs_imageviewer->page.widget = table; } @@ -116,6 +128,9 @@ static void imageviewer_save_func(PrefsPage * _page) prefs_common.inline_img = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (imageviewer->inline_img)); + prefs_common.print_imgs = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON + (imageviewer->print_imgs)); } ImageViewerPage *prefs_imageviewer; diff --git a/src/printing.c b/src/printing.c index 6cb6bdbf7..f4ab09d03 100644 --- a/src/printing.c +++ b/src/printing.c @@ -22,12 +22,16 @@ #endif #include "printing.h" +#include "image_viewer.h" #if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT) +#include "gtkutils.h" #include "prefs_common.h" #include +#include +#include #include #include @@ -39,6 +43,10 @@ typedef struct { GtkTextBuffer *buffer; gint sel_start; gint sel_end; + GHashTable *images; + gint img_cnt; + gboolean print_started; + gchar *old_print_preview; } PrintData; @@ -51,10 +59,142 @@ static GtkPrintSettings *settings = NULL; static GtkPageSetup *page_setup = NULL; /* other static functions */ -static void printing_layout_set_text_attributes(PrintData*); +static void printing_layout_set_text_attributes(PrintData*, GtkPrintContext *); static gboolean printing_is_pango_gdk_color_equal(PangoColor*, GdkColor*); static gint printing_text_iter_get_offset_bytes(PrintData *, const GtkTextIter*); +static gboolean claws_draw_page(GtkPrintOperation *op, GtkPrintContext *context, gint page_nr, gpointer user_data); + +#define PREVIEW_SCALE 72 +static void preview_destroy (GtkWindow *window, GtkPrintOperationPreview *preview) +{ + gtk_print_operation_preview_end_preview (preview); +} + +static gboolean preview_close(GtkWidget *widget, GdkEventAny *event, + gpointer data) +{ + if (event->type == GDK_KEY_PRESS) + if (((GdkEventKey *)event)->keyval != GDK_Escape) + return FALSE; + + gtk_widget_destroy(widget); + return FALSE; +} + +static gboolean cb_preview (GtkPrintOperation *operation, + GtkPrintOperationPreview *preview, + GtkPrintContext *context, + GtkWindow *parent, + PrintData *print_data) +{ + GtkPageSetup *page_setup = gtk_print_context_get_page_setup (context); + GtkPaperSize *paper_size; + gdouble paper_width; + gdouble paper_height; + gdouble top_margin; + gdouble bottom_margin; + gdouble left_margin; + gdouble right_margin; + gint preview_width; + gint preview_height; + gint num_pages = 0, i = 0; + cairo_t *cr; + cairo_surface_t *surface; + GtkPageOrientation orientation; + cairo_status_t status; + gchar *fname; + GtkWidget *dialog = NULL; + GtkWidget *image, *notebook; + GSList *pages = NULL, *cur; + + paper_size = gtk_page_setup_get_paper_size (page_setup); + paper_width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH); + paper_height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH); + top_margin = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_INCH); + bottom_margin = gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_INCH); + left_margin = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_INCH); + right_margin = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_INCH); + + /* the print context does not have the page orientation, it is transformed */ + orientation = gtk_page_setup_get_orientation (page_setup); + + if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT || + orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT) + { + preview_width = PREVIEW_SCALE * paper_width; + preview_height = PREVIEW_SCALE * paper_height; + } + else + { + preview_width = PREVIEW_SCALE * paper_height; + preview_height = PREVIEW_SCALE * paper_width; + } + + + num_pages = 1; + for (i = 0; i < num_pages; i++) { + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + preview_width, preview_height); + + if (CAIRO_STATUS_SUCCESS != cairo_surface_status (surface)) { + g_message ("Unable to create preview (not enough memory?)"); + return TRUE; + } + + cr = cairo_create (surface); + gtk_print_context_set_cairo_context (context, cr, PREVIEW_SCALE, PREVIEW_SCALE); + + /* fill page with white */ + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_new_path (cr); + cairo_rectangle (cr, 0, 0, preview_width, preview_height); + cairo_fill (cr); + + cairo_translate (cr, left_margin * PREVIEW_SCALE, right_margin * PREVIEW_SCALE); + + claws_draw_page (operation, context, i, print_data); + num_pages = g_list_length(print_data->page_breaks) + 1; + + fname = get_tmp_file(); + status = cairo_surface_write_to_png (surface, fname); + cairo_destroy (cr); + cairo_surface_destroy (surface); + if (status == CAIRO_STATUS_SUCCESS) { + image = gtk_image_new_from_file (fname); + g_unlink (fname); + g_free (fname); + pages = g_slist_prepend(pages, image); + debug_print("added one page\n"); + } + } + pages = g_slist_reverse(pages); + + dialog = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "print_preview"); + gtk_window_set_title(GTK_WINDOW(dialog), _("Print preview")); + notebook = gtk_notebook_new(); + gtk_container_add(GTK_CONTAINER(dialog), notebook); + i = 0; + for (cur = pages; cur; cur = cur->next) { + image = (GtkImage *)cur->data; + if (gtk_print_operation_preview_is_selected(preview, i)) { + debug_print("page %d sel\n", i); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), image, NULL); + } + i++; + } + g_slist_free(pages); + + gtk_widget_show_all(dialog); + + g_signal_connect (dialog, "destroy", + G_CALLBACK (preview_destroy), preview); + g_signal_connect (dialog, "key_press_event", + G_CALLBACK (preview_close), preview); + + return TRUE; +} + void printing_print(GtkTextView *text_view, GtkWindow *parent, gint sel_start, gint sel_end) { GtkPrintOperation *op; @@ -67,6 +207,7 @@ void printing_print(GtkTextView *text_view, GtkWindow *parent, gint sel_start, g print_data = g_new0(PrintData,1); + print_data->images = g_hash_table_new(g_direct_hash, g_direct_equal); print_data->pango_context=gtk_widget_get_pango_context(GTK_WIDGET(text_view)); /* get text */ @@ -84,15 +225,29 @@ void printing_print(GtkTextView *text_view, GtkWindow *parent, gint sel_start, g print_data->text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); + if (settings == NULL) { + settings = gtk_print_settings_new(); + gtk_print_settings_set_use_color(settings, prefs_common.print_use_color); + gtk_print_settings_set_collate(settings, prefs_common.print_use_collate); + gtk_print_settings_set_reverse(settings, prefs_common.print_use_reverse); + gtk_print_settings_set_duplex(settings, prefs_common.print_use_duplex); + } + if (page_setup == NULL) { + GtkPaperSize *paper = gtk_paper_size_new(prefs_common.print_paper_type); + page_setup = gtk_page_setup_new(); + gtk_page_setup_set_paper_size(page_setup, paper); + gtk_paper_size_free(paper); + gtk_page_setup_set_orientation(page_setup, prefs_common.print_paper_orientation); + } + /* Config for printing */ - if(settings != NULL) - gtk_print_operation_set_print_settings(op, settings); - if(page_setup != NULL) - gtk_print_operation_set_default_page_setup(op, page_setup); + gtk_print_operation_set_print_settings(op, settings); + gtk_print_operation_set_default_page_setup(op, page_setup); /* signals */ g_signal_connect(op, "begin_print", G_CALLBACK(cb_begin_print), print_data); g_signal_connect(op, "draw_page", G_CALLBACK(cb_draw_page), print_data); + g_signal_connect(op, "preview", G_CALLBACK(cb_preview), print_data); /* Start printing process */ res = gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, @@ -109,13 +264,26 @@ void printing_print(GtkTextView *text_view, GtkWindow *parent, gint sel_start, g if(settings != NULL) g_object_unref(settings); settings = g_object_ref(gtk_print_operation_get_print_settings(op)); + prefs_common.print_use_color = gtk_print_settings_get_use_color(settings); + prefs_common.print_use_collate = gtk_print_settings_get_collate(settings); + prefs_common.print_use_reverse = gtk_print_settings_get_reverse(settings); + prefs_common.print_use_duplex = gtk_print_settings_get_duplex(settings); } + g_hash_table_destroy(print_data->images); if(print_data->text) g_free(print_data->text); g_list_free(print_data->page_breaks); if(print_data->layout) g_object_unref(print_data->layout); + + if (print_data->old_print_preview) { + g_object_set(gtk_settings_get_default(), + "gtk-print-preview-command", print_data->old_print_preview, NULL); + g_free(print_data->old_print_preview); + print_data->old_print_preview = NULL; + } + g_free(print_data); g_object_unref(op); @@ -126,8 +294,20 @@ void printing_page_setup(GtkWindow *parent) { GtkPageSetup *new_page_setup; - if(settings == NULL) + if(settings == NULL) { settings = gtk_print_settings_new(); + gtk_print_settings_set_use_color(settings, prefs_common.print_use_color); + gtk_print_settings_set_collate(settings, prefs_common.print_use_collate); + gtk_print_settings_set_reverse(settings, prefs_common.print_use_reverse); + gtk_print_settings_set_duplex(settings, prefs_common.print_use_duplex); + } + if (page_setup == NULL) { + GtkPaperSize *paper = gtk_paper_size_new(prefs_common.print_paper_type); + page_setup = gtk_page_setup_new(); + gtk_page_setup_set_paper_size(page_setup, paper); + gtk_paper_size_free(paper); + gtk_page_setup_set_orientation(page_setup, prefs_common.print_paper_orientation); + } new_page_setup = gtk_print_run_page_setup_dialog(parent,page_setup,settings); @@ -135,26 +315,38 @@ void printing_page_setup(GtkWindow *parent) g_object_unref(page_setup); page_setup = new_page_setup; + + g_free(prefs_common.print_paper_type); + prefs_common.print_paper_type = g_strdup(gtk_paper_size_get_name( + gtk_page_setup_get_paper_size(page_setup))); + prefs_common.print_paper_orientation = gtk_page_setup_get_orientation(page_setup); } static void cb_begin_print(GtkPrintOperation *op, GtkPrintContext *context, gpointer user_data) { double width, height; - int num_lines, line; + int num_lines; double page_height; GList *page_breaks; PrintData *print_data; - PangoLayoutLine *layout_line; PangoFontDescription *desc; + int start, ii; + PangoLayoutIter *iter; + double start_pos; + double line_height =0.; + print_data = (PrintData*) user_data; + + if (print_data->print_started) + return; debug_print("Preparing print job...\n"); - print_data = (PrintData*) user_data; width = gtk_print_context_get_width(context); height = gtk_print_context_get_height(context); - print_data->layout = gtk_print_context_create_pango_layout(context); + if (print_data->layout == NULL) + print_data->layout = gtk_print_context_create_pango_layout(context); if(prefs_common.use_different_print_font) desc = pango_font_description_from_string(prefs_common.printfont); @@ -168,41 +360,43 @@ static void cb_begin_print(GtkPrintOperation *op, GtkPrintContext *context, pango_layout_set_width(print_data->layout, width * PANGO_SCALE); pango_layout_set_text(print_data->layout, print_data->text, -1); - printing_layout_set_text_attributes(print_data); + printing_layout_set_text_attributes(print_data, context); num_lines = pango_layout_get_line_count(print_data->layout); page_breaks = NULL; page_height = 0; - for(line = 0; line < num_lines; line++) { - PangoRectangle ink_rect, logical_rect; - double line_height; - -#define PANGO_HAS_READONLY 0 -#if defined(PANGO_VERSION_CHECK) -#if PANGO_VERSION_CHECK(1,16,0) -#define PANGO_HAS_READONLY 1 -#endif -#endif + start = 0; + ii = 0; + start_pos = 0.; + iter = pango_layout_get_iter(print_data->layout); + do { + PangoRectangle logical_rect; + PangoLayoutLine *line; + PangoAttrShape *attr = NULL; + int baseline; -#if PANGO_HAS_READONLY - layout_line = pango_layout_get_line_readonly(print_data->layout, line); -#else - layout_line = pango_layout_get_line(print_data->layout, line); -#endif - pango_layout_line_get_extents(layout_line, &ink_rect, &logical_rect); + if(ii >= start) { + line = pango_layout_iter_get_line(iter); - line_height = ((double)logical_rect.height) / PANGO_SCALE; + pango_layout_iter_get_line_extents(iter, NULL, &logical_rect); + baseline = pango_layout_iter_get_baseline(iter); - /* TODO: Check if there is a pixbuf in that line */ - + if ((attr = g_hash_table_lookup(print_data->images, GINT_TO_POINTER(pango_layout_iter_get_index(iter)))) != NULL) { + line_height = (double)gdk_pixbuf_get_height(GDK_PIXBUF(attr->data)); + } else { + line_height = ((double)logical_rect.height) / PANGO_SCALE; + } + } if((page_height + line_height) > height) { - page_breaks = g_list_prepend(page_breaks, GINT_TO_POINTER(line)); + page_breaks = g_list_prepend(page_breaks, GINT_TO_POINTER(ii)); page_height = 0; } page_height += line_height; - } + ii++; + } while(ii < num_lines && pango_layout_iter_next_line(iter)); + pango_layout_iter_free(iter); page_breaks = g_list_reverse(page_breaks); gtk_print_operation_set_n_pages(op, g_list_length(page_breaks) + 1); @@ -210,10 +404,88 @@ static void cb_begin_print(GtkPrintOperation *op, GtkPrintContext *context, print_data->page_breaks = page_breaks; debug_print("Starting print job...\n"); + print_data->print_started = TRUE; } -static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context, - int page_nr, gpointer user_data) +static cairo_surface_t *pixbuf_to_surface(GdkPixbuf *pixbuf) +{ + cairo_surface_t *surface; + cairo_format_t format; + static const cairo_user_data_key_t key; + guchar *pixels = g_malloc( + 4* + gdk_pixbuf_get_width(pixbuf)* + gdk_pixbuf_get_height(pixbuf)); + guchar *src_pixels = gdk_pixbuf_get_pixels (pixbuf); + gint width = gdk_pixbuf_get_width(pixbuf); + gint height = gdk_pixbuf_get_height(pixbuf); + gint nchans = gdk_pixbuf_get_n_channels (pixbuf); + gint stride = gdk_pixbuf_get_rowstride (pixbuf); + gint j; + + if (nchans == 3) + format = CAIRO_FORMAT_RGB24; + else + format = CAIRO_FORMAT_ARGB32; + surface = cairo_image_surface_create_for_data (pixels, + format, width, height, 4*width); + cairo_surface_set_user_data (surface, &key, + pixels, (cairo_destroy_func_t)g_free); + + for (j = height; j; j--) { + guchar *p = src_pixels; + guchar *q = pixels; + + if (nchans == 3) { + guchar *end = p + 3 * width; + + while (p < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + q[0] = p[2]; + q[1] = p[1]; + q[2] = p[0]; +#else + q[1] = p[0]; + q[2] = p[1]; + q[3] = p[2]; +#endif + p += 3; + q += 4; + } + } else { + guchar *end = p + 4 * width; + guint t1,t2,t3; + +#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END + + while (p < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + MULT(q[0], p[2], p[3], t1); + MULT(q[1], p[1], p[3], t2); + MULT(q[2], p[0], p[3], t3); + q[3] = p[3]; +#else + q[0] = p[3]; + MULT(q[1], p[0], p[3], t1); + MULT(q[2], p[1], p[3], t2); + MULT(q[3], p[2], p[3], t3); +#endif + + p += 4; + q += 4; + } + +#undef MULT + } + + src_pixels += stride; + pixels += 4 * width; + } + + return surface; +} + +static gboolean claws_draw_page(GtkPrintOperation *op, GtkPrintContext *context, gint page_nr, gpointer user_data) { cairo_t *cr; PrintData *print_data; @@ -221,12 +493,14 @@ static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context, GList *pagebreak; PangoLayoutIter *iter; double start_pos; - + gboolean notlast = TRUE; print_data = (PrintData*) user_data; - if (page_nr == 0) + if (print_data->print_started == FALSE) + cb_begin_print(op, context, print_data); + if (page_nr == 0) { start = 0; - else { + } else { pagebreak = g_list_nth(print_data->page_breaks, page_nr - 1); start = GPOINTER_TO_INT(pagebreak->data); } @@ -246,6 +520,7 @@ static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context, do { PangoRectangle logical_rect; PangoLayoutLine *line; + PangoAttrShape *attr = NULL; int baseline; if(ii >= start) { @@ -260,17 +535,35 @@ static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context, cairo_move_to(cr, ((double)logical_rect.x) / PANGO_SCALE, ((double)baseline) / PANGO_SCALE - start_pos); - pango_cairo_show_layout_line(cr, line); + + if ((attr = g_hash_table_lookup(print_data->images, GINT_TO_POINTER(pango_layout_iter_get_index(iter)))) != NULL) { + cairo_surface_t *surface; + + surface = pixbuf_to_surface(GDK_PIXBUF(attr->data)); + cairo_set_source_surface (cr, surface, + ((double)logical_rect.x) / PANGO_SCALE, + ((double)baseline) / PANGO_SCALE - start_pos); + cairo_paint (cr); + cairo_surface_destroy (surface); + g_object_unref(GDK_PIXBUF(attr->data)); + } else { + pango_cairo_show_layout_line(cr, line); + } } ii++; - } while(ii < end && pango_layout_iter_next_line(iter)); - + } while(ii < end && (notlast = pango_layout_iter_next_line(iter))); pango_layout_iter_free(iter); - + return TRUE; +} + +static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context, + int page_nr, gpointer user_data) +{ + claws_draw_page(op, context, page_nr, user_data); debug_print("Sent page %d to printer\n", page_nr+1); } -static void printing_layout_set_text_attributes(PrintData *print_data) +static void printing_layout_set_text_attributes(PrintData *print_data, GtkPrintContext *context) { GtkTextIter iter; PangoAttrList *attr_list; @@ -292,6 +585,32 @@ static void printing_layout_set_text_attributes(PrintData *print_data) GdkColor *color; PangoUnderline underline; gboolean strikethrough; + GdkPixbuf *image; + + if (prefs_common.print_imgs && (image = gtk_text_iter_get_pixbuf(&iter)) != NULL) { + PangoRectangle rect = {0, 0, 0, 0}; + gint startpos = printing_text_iter_get_offset_bytes(print_data, &iter); + gint h = gdk_pixbuf_get_height(image); + gint w = gdk_pixbuf_get_width(image); + gint a_h = gtk_print_context_get_height(context); + gint a_w = gtk_print_context_get_width(context); + gint r_h, r_w; + GdkPixbuf *scaled = NULL; + image_viewer_get_resized_size(w, h, a_w, a_h, &r_w, &r_h); + rect.x = 0; + rect.y = 0; + rect.width = r_w * PANGO_SCALE; + rect.height = r_h * PANGO_SCALE; + + scaled = gdk_pixbuf_scale_simple(image, r_w, r_h, GDK_INTERP_BILINEAR); + attr = pango_attr_shape_new_with_data (&rect, &rect, + scaled, NULL, NULL); + attr->start_index = startpos; + attr->end_index = startpos+1; + pango_attr_list_insert(attr_list, attr); + g_hash_table_insert(print_data->images, GINT_TO_POINTER(startpos), attr); + print_data->img_cnt++; + } if(gtk_text_iter_ends_tag(&iter, NULL)) { PangoAttrColor *attr_color; @@ -466,7 +785,7 @@ static gint printing_text_iter_get_offset_bytes(PrintData *print_data, const Gtk } else { gtk_text_buffer_get_iter_at_offset(gtk_text_iter_get_buffer(iter), &start, print_data->sel_start); } - text = gtk_text_iter_get_slice(&start, iter); + text = gtk_text_iter_get_text(&start, iter); off_bytes = strlen(text); g_free(text); return off_bytes; -- 2.25.1