From dd26c61199616a5d8d83f9409da864a309441acc Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Mon, 21 May 2018 15:51:59 -0400 Subject: [PATCH 1/2] Print: C++ify Backport of commit a139e677581d6f82123a660e713958747753b8e0 --- src/ui/dialog/print.cpp | 147 ++++++++++++++++++---------------------- src/ui/dialog/print.h | 6 +- 2 files changed, 71 insertions(+), 82 deletions(-) diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index d3753f6bbf..7bbd6eb3e1 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -37,30 +37,71 @@ #include -static void draw_page( -#ifdef WIN32 - GtkPrintOperation *operation, -#else - GtkPrintOperation *, -#endif - GtkPrintContext *context, - gint /*page_nr*/, - gpointer user_data) +namespace Inkscape { +namespace UI { +namespace Dialog { + +Print::Print(SPDocument *doc, SPItem *base) : + _doc (doc), + _base (base) +{ + g_assert (_doc); + g_assert (_base); + + _printop = Gtk::PrintOperation::create(); + + // set up dialog title, based on document name + const Glib::ustring jobname = _doc->getName() ? _doc->getName() : _("SVG Document"); + Glib::ustring title = _("Print"); + title += " "; + title += jobname; + _printop->set_job_name(title); + + // set up paper size to match the document size + _printop->set_unit(Gtk::UNIT_POINTS); + Glib::RefPtr page_setup = Gtk::PageSetup::create(); + gdouble doc_width = _doc->getWidth().value("pt"); + gdouble doc_height = _doc->getHeight().value("pt"); + Gtk::PaperSize paper_size; + if (doc_width > doc_height) { + page_setup->set_orientation(Gtk::PAGE_ORIENTATION_PORTRAIT); + paper_size = Gtk::PaperSize("custom", "custom", doc_height, doc_width, Gtk::UNIT_POINTS); + } else { + page_setup->set_orientation(Gtk::PAGE_ORIENTATION_PORTRAIT); + paper_size = Gtk::PaperSize("custom", "custom", doc_width, doc_height, Gtk::UNIT_POINTS); + } + + page_setup->set_paper_size(paper_size); + _printop->set_default_page_setup(page_setup); + _printop->set_use_full_page(true); + + // set up signals + _workaround._doc = _doc; + _workaround._base = _base; + _workaround._tab = &_tab; + _printop->signal_create_custom_widget().connect(sigc::mem_fun(*this, &Print::create_custom_widget)); + _printop->signal_begin_print().connect(sigc::mem_fun(*this, &Print::begin_print)); + _printop->signal_draw_page().connect(sigc::mem_fun(*this, &Print::draw_page)); + + // build custom preferences tab + _printop->set_custom_tab_label(_("Rendering")); +} + +void Print::draw_page(const Glib::RefPtr& context, int /*page_nr*/) { // TODO: If the user prints multiple copies we render the whole page for each copy // It would be more efficient to render the page once (e.g. in "begin_print") // and simply print this result as often as necessary Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - struct workaround_gtkmm *junk = (struct workaround_gtkmm*)user_data; //printf("%s %d\n",__FUNCTION__, page_nr); - if (junk->_tab->as_bitmap()) { + if (_workaround._tab->as_bitmap()) { // Render as exported PNG prefs->setBool("/dialogs/printing/asbitmap", true); - gdouble width = (junk->_doc)->getWidth().value("px"); - gdouble height = (junk->_doc)->getHeight().value("px"); - gdouble dpi = junk->_tab->bitmap_dpi(); + gdouble width = (_workaround._doc)->getWidth().value("px"); + gdouble height = (_workaround._doc)->getHeight().value("px"); + gdouble dpi = _workaround._tab->bitmap_dpi(); prefs->setDouble("/dialogs/printing/dpi", dpi); std::string tmp_png; @@ -71,7 +112,7 @@ static void draw_page( close(tmp_fd); guint32 bgcolor = 0x00000000; - Inkscape::XML::Node *nv = sp_repr_lookup_name (junk->_doc->rroot, "sodipodi:namedview"); + Inkscape::XML::Node *nv = sp_repr_lookup_name (_workaround._doc->rroot, "sodipodi:namedview"); if (nv && nv->attribute("pagecolor")){ bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00); } @@ -81,7 +122,7 @@ static void draw_page( bgcolor |= SP_COLOR_F_TO_U(opacity); } - sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0, + sp_export_png_file(_workaround._doc, tmp_png.c_str(), 0.0, 0.0, width, height, (unsigned long)(Inkscape::Util::Quantity::convert(width, "px", "in") * dpi), (unsigned long)(Inkscape::Util::Quantity::convert(height, "px", "in") * dpi), @@ -98,7 +139,7 @@ static void draw_page( // so do it in C: { Cairo::RefPtr png = Cairo::ImageSurface::create_from_png (tmp_png); - cairo_t *cr = gtk_print_context_get_cairo_context (context); + cairo_t *cr = gtk_print_context_get_cairo_context (context->gobj()); cairo_matrix_t m; cairo_get_matrix(cr, &m); cairo_scale(cr, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi); @@ -126,16 +167,16 @@ static void draw_page( ctx->setFilterToBitmap(true); ctx->setBitmapResolution(72); - cairo_t *cr = gtk_print_context_get_cairo_context (context); + cairo_t *cr = gtk_print_context_get_cairo_context (context->gobj()); cairo_surface_t *surface = cairo_get_target(cr); cairo_matrix_t ctm; cairo_get_matrix(cr, &ctm); bool ret = ctx->setSurfaceTarget (surface, true, &ctm); if (ret) { - ret = renderer.setupDocument (ctx, junk->_doc, TRUE, 0., NULL); + ret = renderer.setupDocument (ctx, _workaround._doc, TRUE, 0., NULL); if (ret) { - renderer.renderItem(ctx, junk->_base); + renderer.renderItem(ctx, _workaround._base); ctx->finish(false); // do not finish the cairo_surface_t - it's owned by our GtkPrintContext! } else { @@ -152,77 +193,21 @@ static void draw_page( } -static GObject* create_custom_widget (GtkPrintOperation */*operation*/, - gpointer user_data) +Gtk::Widget *Print::create_custom_widget() { //printf("%s\n",__FUNCTION__); - return G_OBJECT(user_data); + return &_tab; } -static void begin_print (GtkPrintOperation *operation, - GtkPrintContext */*context*/, - gpointer /*user_data*/) +void Print::begin_print(const Glib::RefPtr&) { //printf("%s\n",__FUNCTION__); - gtk_print_operation_set_n_pages (operation, 1); -} - -namespace Inkscape { -namespace UI { -namespace Dialog { - -Print::Print(SPDocument *doc, SPItem *base) : - _doc (doc), - _base (base) -{ - g_assert (_doc); - g_assert (_base); - - _printop = gtk_print_operation_new (); - - // set up dialog title, based on document name - gchar const *jobname = _doc->getName() ? _doc->getName() : _("SVG Document"); - Glib::ustring title = _("Print"); - title += " "; - title += jobname; - gtk_print_operation_set_job_name (_printop, title.c_str()); - - // set up paper size to match the document size - gtk_print_operation_set_unit (_printop, GTK_UNIT_POINTS); - GtkPageSetup *page_setup = gtk_page_setup_new(); - gdouble doc_width = _doc->getWidth().value("pt"); - gdouble doc_height = _doc->getHeight().value("pt"); - GtkPaperSize *paper_size; - if (doc_width > doc_height) { - gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_LANDSCAPE); - paper_size = gtk_paper_size_new_custom("custom", "custom", - doc_height, doc_width, GTK_UNIT_POINTS); - } else { - gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_PORTRAIT); - paper_size = gtk_paper_size_new_custom("custom", "custom", - doc_width, doc_height, GTK_UNIT_POINTS); - } - - gtk_page_setup_set_paper_size (page_setup, paper_size); - gtk_print_operation_set_default_page_setup (_printop, page_setup); - gtk_print_operation_set_use_full_page (_printop, TRUE); - - // set up signals - _workaround._doc = _doc; - _workaround._base = _base; - _workaround._tab = &_tab; - g_signal_connect (_printop, "create-custom-widget", G_CALLBACK (create_custom_widget), _tab.gobj()); - g_signal_connect (_printop, "begin-print", G_CALLBACK (begin_print), NULL); - g_signal_connect (_printop, "draw-page", G_CALLBACK (draw_page), &_workaround); - - // build custom preferences tab - gtk_print_operation_set_custom_tab_label (_printop, _("Rendering")); + _printop->set_n_pages(1); } Gtk::PrintOperationResult Print::run(Gtk::PrintOperationAction, Gtk::Window &parent_window) { - gtk_print_operation_run (_printop, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, - parent_window.gobj(), NULL); + _printop->run(Gtk::PRINT_OPERATION_ACTION_PRINT_DIALOG, parent_window); return Gtk::PRINT_OPERATION_RESULT_APPLY; } diff --git a/src/ui/dialog/print.h b/src/ui/dialog/print.h index f81829d86d..0ce9e811ca 100644 --- a/src/ui/dialog/print.h +++ b/src/ui/dialog/print.h @@ -45,12 +45,16 @@ public: protected: private: - GtkPrintOperation *_printop; + Glib::RefPtr _printop; SPDocument *_doc; SPItem *_base; Inkscape::UI::Widget::RenderingOptions _tab; struct workaround_gtkmm _workaround; + + void draw_page(const Glib::RefPtr& context, int /*page_nr*/); + Gtk::Widget *create_custom_widget(); + void begin_print(const Glib::RefPtr&); }; } // namespace Dialog -- GitLab From 495bbd9eb0b1ad8c363b80d68e0334c2ce49fb8b Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Mon, 21 May 2018 16:18:59 -0400 Subject: [PATCH 2/2] Print: Match document size against known paper sizes Custom paper sizes work with some printer drivers but not others. EPSON's ESC/P-R CUPS driver for example scales a custom-sized document to ISO A4. (It apparently used to just bail on unknown page sizes.) Matching the document size against a known paper size in Inkscape prevents the driver from scaling to the wrong paper size. Fixes an issue discussed in comments 3, 4, 5, and 6 of . Backport of commit eaa134e8ea9e71489af1b5090bdee122d5b8d659 --- AUTHORS | 3 ++- src/ui/dialog/aboutbox.cpp | 1 + src/ui/dialog/print.cpp | 40 ++++++++++++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/AUTHORS b/AUTHORS index 7dafa6193c..d379387421 100644 --- a/AUTHORS +++ b/AUTHORS @@ -109,6 +109,7 @@ Ivan Masár Dmitry G. Mastrukov David Mathog Matiphas +Patrick McDermott Michael Meeks Federico Mena MenTaLguY @@ -173,4 +174,4 @@ Daniel Yacob David Yip Masatake Yamato Moritz Eberl -Sebastian Faubel \ No newline at end of file +Sebastian Faubel diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 7b30c36108..b097d2ab12 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -366,6 +366,7 @@ void AboutBox::initStrings() { "Dmitry G. Mastrukov\n" "David Mathog\n" "Matiphas\n" +"Patrick McDermott\n" "Michael Meeks\n" "Federico Mena\n" "MenTaLguY\n" diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index 7bbd6eb3e1..01421b5e50 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -5,8 +5,10 @@ /* Authors: * Kees Cook * Abhishek Sharma + * Patrick McDermott * * Copyright (C) 2007 Kees Cook + * Copyright (C) 2017 Patrick McDermott * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -14,6 +16,8 @@ # include #endif +#include + #include #ifdef WIN32 @@ -57,18 +61,38 @@ Print::Print(SPDocument *doc, SPItem *base) : title += jobname; _printop->set_job_name(title); - // set up paper size to match the document size _printop->set_unit(Gtk::UNIT_POINTS); Glib::RefPtr page_setup = Gtk::PageSetup::create(); - gdouble doc_width = _doc->getWidth().value("pt"); - gdouble doc_height = _doc->getHeight().value("pt"); - Gtk::PaperSize paper_size; - if (doc_width > doc_height) { - page_setup->set_orientation(Gtk::PAGE_ORIENTATION_PORTRAIT); - paper_size = Gtk::PaperSize("custom", "custom", doc_height, doc_width, Gtk::UNIT_POINTS); + + // get document width, height, and orientation + // height must be larger than width, as in GTK+'s known paper sizes + gdouble doc_width; + gdouble doc_height; + if (_doc->getWidth().value("pt") > _doc->getHeight().value("pt")) { + page_setup->set_orientation(Gtk::PAGE_ORIENTATION_LANDSCAPE); + doc_width = _doc->getHeight().value("pt"); + doc_height = _doc->getWidth().value("pt"); } else { page_setup->set_orientation(Gtk::PAGE_ORIENTATION_PORTRAIT); - paper_size = Gtk::PaperSize("custom", "custom", doc_width, doc_height, Gtk::UNIT_POINTS); + doc_width = _doc->getWidth().value("pt"); + doc_height = _doc->getHeight().value("pt"); + } + + // attempt to match document size against known paper sizes + Gtk::PaperSize paper_size("custom", "custom", doc_width, doc_height, Gtk::UNIT_POINTS); + std::vector known_sizes = Gtk::PaperSize::get_paper_sizes(false); + for (auto& size : known_sizes) { + if (fabs(size.get_width(Gtk::UNIT_POINTS) - doc_width) >= 1.0) { + // width (short edge) doesn't match + continue; + } + if (fabs(size.get_height(Gtk::UNIT_POINTS) - doc_height) >= 1.0) { + // height (short edge) doesn't match + continue; + } + // size matches + paper_size = size; + break; } page_setup->set_paper_size(paper_size); -- GitLab