/* multiply a projective matrix by an affine matrix */ TransfMat3x4 TransfMat3x4::operator*(Geom::Matrix const &A) const { TransfMat3x4 ret; // Is it safe to always use the currently active document? double h = sp_document_height(inkscape_active_document()); /* * Note: The strange multiplication involving the document height is due to the buggy * intertwining of SVG and document coordinates. Essentially, what we do is first * convert from "real-world" to SVG coordinates, then apply the transformation A * (by multiplying with the Geom::Matrix) and then convert back from SVG to real-world * coordinates. Maybe there is even a more Inkscape-ish way to achieve this? * Once Inkscape has gotton rid of the two different coordiate systems, we can change * this function to an ordinary matrix multiplication. */ for (int j = 0; j < 4; ++j) { ret.tmat[0][j] = A[0]*tmat[0][j] + A[2]*(h*tmat[2][j] - tmat[1][j]) + A[4]*tmat[2][j]; ret.tmat[1][j] = A[1]*tmat[0][j] + A[3]*(h*tmat[2][j] - tmat[1][j]) + A[5]*tmat[2][j]; ret.tmat[2][j] = tmat[2][j]; ret.tmat[1][j] = h*ret.tmat[2][j] - ret.tmat[1][j]; // switch back from SVG to desktop coordinates } return ret; }
void sp_help_about (void) { SPDocument *doc; SPObject *title; GtkWidget *v; gint width, height; if (!w) { doc = sp_document_new (INKSCAPE_PIXMAPDIR "/about.svg", FALSE, TRUE); g_return_if_fail (doc != NULL); title = sp_document_lookup_id (doc, "title"); if (title && SP_IS_TEXT (title)) { gchar *t; t = g_strdup_printf ("Inkscape %s", INKSCAPE_VERSION); sp_text_set_repr_text_multiline (SP_TEXT (title), t); g_free (t); } sp_document_ensure_up_to_date (doc); w = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (w), _("About Inkscape")); width = INK_STATIC_CAST( gint, CLAMP( sp_document_width(doc), WINDOW_MIN, WINDOW_MAX ) ); height = INK_STATIC_CAST( gint, CLAMP( sp_document_height(doc), WINDOW_MIN, WINDOW_MAX ) ); gtk_window_set_default_size (GTK_WINDOW (w), width, height ); gtk_window_set_position(GTK_WINDOW(w), GTK_WIN_POS_CENTER); #if 1 gtk_window_set_policy (GTK_WINDOW (w), TRUE, TRUE, FALSE); #endif gtk_signal_connect (GTK_OBJECT (w), "delete_event", GTK_SIGNAL_FUNC (sp_help_about_delete), NULL); v = sp_svg_view_widget_new (doc); sp_svg_view_widget_set_resize (SP_SVG_VIEW_WIDGET (v), FALSE, sp_document_width (doc), sp_document_height (doc)); sp_document_unref (doc); gtk_widget_show (v); gtk_container_add (GTK_CONTAINER (w), v); } gtk_window_present ((GtkWindow *) w); }
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 *jobname = _doc->name ? _doc->name : _("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 = sp_document_width(_doc) * PT_PER_PX; gdouble doc_height = sp_document_height(_doc) * PT_PER_PX; GtkPaperSize *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); #ifndef WIN32 gtk_print_operation_set_default_page_setup (_printop, page_setup); #endif 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")); }
/** * Given a Geom::Rect that may, for example, correspond to the bbox of an object, * this function fits the canvas to that rect by resizing the canvas * and translating the document root into position. */ void SPDocument::fitToRect(Geom::Rect const &rect) { double const w = rect.width(); double const h = rect.height(); double const old_height = sp_document_height(this); SPUnit const &px(sp_unit_get_by_id(SP_UNIT_PX)); sp_document_set_width(this, w, &px); sp_document_set_height(this, h, &px); Geom::Translate const tr(Geom::Point(0, (old_height - h)) - to_2geom(rect.min())); SP_GROUP(root)->translateChildItems(tr); SPNamedView *nv = sp_document_namedview(this, 0); if(nv) { Geom::Translate tr2(-rect.min()); nv->translateGuides(tr2); // update the viewport so the drawing appears to stay where it was nv->scrollAllDesktops(-tr2[0], tr2[1], false); } }
Geom::Point sp_document_dimensions(SPDocument *doc) { return Geom::Point(sp_document_width(doc), sp_document_height(doc)); }
static void draw_page (GtkPrintOperation */*operation*/, GtkPrintContext *context, gint /*page_nr*/, gpointer user_data) { struct workaround_gtkmm *junk = (struct workaround_gtkmm*)user_data; //printf("%s %d\n",__FUNCTION__, page_nr); if (junk->_tab->as_bitmap()) { // Render as exported PNG gdouble width = sp_document_width(junk->_doc); gdouble height = sp_document_height(junk->_doc); gdouble dpi = junk->_tab->bitmap_dpi(); std::string tmp_png; std::string tmp_base = "inkscape-print-png-XXXXXX"; int tmp_fd; if ( (tmp_fd = Inkscape::IO::file_open_tmp (tmp_png, tmp_base)) >= 0) { close(tmp_fd); guint32 bgcolor = 0x00000000; Inkscape::XML::Node *nv = sp_repr_lookup_name (junk->_doc->rroot, "sodipodi:namedview"); if (nv && nv->attribute("pagecolor")) bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00); if (nv && nv->attribute("inkscape:pageopacity")) bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0)); sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0, width, height, (unsigned long)(width * dpi / PX_PER_IN), (unsigned long)(height * dpi / PX_PER_IN), dpi, dpi, bgcolor, NULL, NULL, true, NULL); // This doesn't seem to work: //context->set_cairo_context ( Cairo::Context::create (Cairo::ImageSurface::create_from_png (tmp_png) ), dpi, dpi ); // // so we'll use a surface pattern blat instead... // // but the C++ interface isn't implemented in cairomm: //context->get_cairo_context ()->set_source_surface(Cairo::ImageSurface::create_from_png (tmp_png) ); // // so do it in C: { Cairo::RefPtr<Cairo::ImageSurface> png = Cairo::ImageSurface::create_from_png (tmp_png); cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_matrix_t m; cairo_get_matrix(cr, &m); cairo_scale(cr, PT_PER_IN / dpi, PT_PER_IN / dpi); // FIXME: why is the origin offset?? cairo_set_source_surface(cr, png->cobj(), -16.0, -16.0); cairo_paint(cr); cairo_set_matrix(cr, &m); } // Clean up unlink (tmp_png.c_str()); } else { g_warning(_("Could not open temporary PNG for bitmap printing")); } } else { // Render as vectors Inkscape::Extension::Internal::CairoRenderer renderer; Inkscape::Extension::Internal::CairoRenderContext *ctx = renderer.createContext(); // ctx->setPSLevel(CAIRO_PS_LEVEL_3); ctx->setTextToPath(false); ctx->setFilterToBitmap(true); ctx->setBitmapResolution(72); cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_surface_t *surface = cairo_get_target(cr); /** Call cairo_win32_printing_surface directly as a workaround until GTK uses this call. When GTK uses cairo_win32_printing_surface this automatically reverts. */ #ifdef WIN32 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_WIN32) { HDC dc = cairo_win32_surface_get_dc (surface); surface = _cairo_win32_printing_surface_create (dc); } #endif bool ret = ctx->setSurfaceTarget (surface, true); if (ret) { ret = renderer.setupDocument (ctx, junk->_doc, TRUE, NULL); if (ret) { renderer.renderItem(ctx, junk->_base); ret = ctx->finish(); } else { g_warning(_("Could not set up Document")); } } else { g_warning(_("Failed to set CairoRenderContext")); } // Clean up renderer.destroyContext(ctx); } }
void sp_align_arrange_clicked (GtkWidget *widget, const gchar *aligns) { float mx0, mx1, my0, my1; float sx0, sx1, sy0, sy1; SPDesktop * desktop; SPSelection * selection; GSList * slist; SPItem * master, * item; NRRectF b; NRPointF mp, sp; GSList * l; gboolean changed; mx0 = 0.5 * aligns[0]; mx1 = 0.5 * aligns[1]; my0 = 0.5 * aligns[2]; my1 = 0.5 * aligns[3]; sx0 = 0.5 * aligns[4]; sx1 = 0.5 * aligns[5]; sy0 = 0.5 * aligns[6]; sy1 = 0.5 * aligns[7]; desktop = SP_ACTIVE_DESKTOP; if (!desktop) return; selection = SP_DT_SELECTION (desktop); slist = (GSList *) sp_selection_item_list (selection); if (!slist) return; switch (base) { case SP_ALIGN_LAST: case SP_ALIGN_FIRST: case SP_ALIGN_BIGGEST: case SP_ALIGN_SMALLEST: if (!slist->next) return; slist = g_slist_copy (slist); master = sp_quick_align_find_master (slist, (mx0 != 0.0) || (mx1 != 0.0)); slist = g_slist_remove (slist, master); sp_item_bbox_desktop (master, &b); mp.x = mx0 * b.x0 + mx1 * b.x1; mp.y = my0 * b.y0 + my1 * b.y1; break; case SP_ALIGN_PAGE: slist = g_slist_copy (slist); mp.x = mx1 * sp_document_width (SP_DT_DOCUMENT (desktop)); mp.y = my1 * sp_document_height (SP_DT_DOCUMENT (desktop)); break; case SP_ALIGN_DRAWING: slist = g_slist_copy (slist); sp_item_bbox_desktop ((SPItem *) sp_document_root (SP_DT_DOCUMENT (desktop)), &b); mp.x = mx0 * b.x0 + mx1 * b.x1; mp.y = my0 * b.y0 + my1 * b.y1; break; case SP_ALIGN_SELECTION: slist = g_slist_copy (slist); sp_selection_bbox (selection, &b); mp.x = mx0 * b.x0 + mx1 * b.x1; mp.y = my0 * b.y0 + my1 * b.y1; break; default: g_assert_not_reached (); break; }; changed = FALSE; for (l = slist; l != NULL; l = l->next) { item = (SPItem *) l->data; sp_item_bbox_desktop (item, &b); sp.x = sx0 * b.x0 + sx1 * b.x1; sp.y = sy0 * b.y0 + sy1 * b.y1; if ((fabs (mp.x - sp.x) > 1e-9) || (fabs (mp.y - sp.y) > 1e-9)) { sp_item_move_rel (item, mp.x - sp.x, mp.y - sp.y); changed = TRUE; } } g_slist_free (slist); if (changed) { sp_selection_changed (selection); sp_document_done (SP_DT_DOCUMENT (desktop)); } }