diff options
| author | Jabiertxo Arraiza Cenoz <jtx@jtx.markerlab.es> | 2018-05-04 14:37:02 +0000 |
|---|---|---|
| committer | Jabiertxo Arraiza Cenoz <jtx@jtx.markerlab.es> | 2018-05-10 16:46:08 +0000 |
| commit | 21abf74176d6a2db53a274f13421b84ee17714e7 (patch) | |
| tree | 591bfa96068a2c6b5b02224f49023d6ce3a5b3f4 /src | |
| parent | Improve sort handling in XML (diff) | |
| download | inkscape-21abf74176d6a2db53a274f13421b84ee17714e7.tar.gz inkscape-21abf74176d6a2db53a274f13421b84ee17714e7.zip | |
Allow link a SVG as image
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/cairo-utils.cpp | 96 | ||||
| -rw-r--r-- | src/extension/internal/svg.cpp | 105 | ||||
| -rw-r--r-- | src/object/sp-lpe-item.cpp | 13 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 2 | ||||
| -rw-r--r-- | src/verbs.cpp | 5 |
5 files changed, 190 insertions, 31 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 82373c27c..29e542b01 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -28,11 +28,17 @@ #include <2geom/transforms.h> #include <2geom/sbasis-to-bezier.h> +#include <boost/algorithm/string.hpp> #include <boost/operators.hpp> #include <boost/optional/optional.hpp> #include "color.h" #include "cairo-templates.h" +#include "document.h" +#include "preferences.h" +#include "util/units.h" +#include "helper/pixbuf-ops.h" + /** * Key for cairo_surface_t to keep track of current color interpolation value @@ -312,37 +318,81 @@ Pixbuf *Pixbuf::create_from_file(std::string const &fn) std::cerr << " (" << fn << ")" << std::endl; return NULL; } - - GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(loader, (guchar *) data, len, &error); - if (error != NULL) { - std::cerr << "Pixbuf::create_from_file: " << error->message << std::endl; - std::cerr << " (" << fn << ")" << std::endl; - g_free(data); - g_object_unref(loader); - return NULL; + GdkPixbuf *buf = NULL; + GdkPixbufLoader *loader = NULL; + std::string::size_type idx; + idx = fn.rfind('.'); + bool is_svg = false; + if(idx != std::string::npos) + { + if (boost::iequals(fn.substr(idx+1).c_str(), "svg")) { + SPDocument *svgDoc = SPDocument::createNewDoc(fn.c_str(), TRUE); + // Check the document loaded properly + if (svgDoc == NULL) { + return NULL; + } + if (svgDoc->getRoot() == NULL) + { + svgDoc->doUnref(); + return NULL; + } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + const double dpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", 96.0); + // Get the size of the document + Inkscape::Util::Quantity svgWidth = svgDoc->getWidth(); + Inkscape::Util::Quantity svgHeight = svgDoc->getHeight(); + const double svgWidth_px = svgWidth.value("px"); + const double svgHeight_px = svgHeight.value("px"); + + // Now get the resized values + const int scaledSvgWidth = round(svgWidth_px/(96.0/dpi)); + const int scaledSvgHeight = round(svgHeight_px/(96.0/dpi)); + + buf = sp_generate_internal_bitmap(svgDoc, NULL, 0, 0, svgWidth_px, svgHeight_px, scaledSvgWidth, scaledSvgHeight, dpi, dpi, (guint32) 0xffffff00, NULL)->getPixbufRaw(); + + // Tidy up + svgDoc->doUnref(); + if (buf == NULL) { + return NULL; + } + is_svg = true; + } } + if (!is_svg) { + loader = gdk_pixbuf_loader_new(); + gdk_pixbuf_loader_write(loader, (guchar *) data, len, &error); + if (error != NULL) { + std::cerr << "Pixbuf::create_from_file: " << error->message << std::endl; + std::cerr << " (" << fn << ")" << std::endl; + g_free(data); + g_object_unref(loader); + return NULL; + } - gdk_pixbuf_loader_close(loader, &error); - if (error != NULL) { - std::cerr << "Pixbuf::create_from_file: " << error->message << std::endl; - std::cerr << " (" << fn << ")" << std::endl; - g_free(data); - g_object_unref(loader); - return NULL; + gdk_pixbuf_loader_close(loader, &error); + if (error != NULL) { + std::cerr << "Pixbuf::create_from_file: " << error->message << std::endl; + std::cerr << " (" << fn << ")" << std::endl; + g_free(data); + g_object_unref(loader); + return NULL; + } + + buf = gdk_pixbuf_loader_get_pixbuf(loader); } - - GdkPixbuf *buf = gdk_pixbuf_loader_get_pixbuf(loader); if (buf) { g_object_ref(buf); pb = new Pixbuf(buf); pb->_mod_time = stdir.st_mtime; pb->_path = fn; - - GdkPixbufFormat *fmt = gdk_pixbuf_loader_get_format(loader); - gchar *fmt_name = gdk_pixbuf_format_get_name(fmt); - pb->_setMimeData((guchar *) data, len, fmt_name); - g_free(fmt_name); + if (!is_svg) { + GdkPixbufFormat *fmt = gdk_pixbuf_loader_get_format(loader); + gchar *fmt_name = gdk_pixbuf_format_get_name(fmt); + pb->_setMimeData((guchar *) data, len, fmt_name); + g_free(fmt_name); + } else { + pb->_setMimeData((guchar *) data, len, "svg"); + } } else { std::cerr << "Pixbuf::create_from_file: failed to load contents: " << fn << std::endl; g_free(data); diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index 7bf4f34e6..27a1efef0 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -18,17 +18,32 @@ # include <config.h> #endif +#include <gtkmm.h> + +#include <giomm/file.h> #include <vector> #include <giomm/file.h> - +#include "document.h" +#include "inkscape.h" +#include "preferences.h" +#include "extension/output.h" +#include "extension/system.h" +#include "file.h" #include "svg.h" #include "file.h" #include "extension/system.h" #include "extension/output.h" #include "xml/attribute-record.h" #include "xml/simple-document.h" -#include "document.h" + +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "util/units.h" +#include "selection-chemistry.h" + +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace Extension { @@ -173,7 +188,93 @@ Svg::open (Inkscape::Extension::Input */*mod*/, const gchar *uri) { auto file = Gio::File::create_for_uri(uri); const auto path = file->get_path(); + bool link = false; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool is_import = false; + if (strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") == 0) { + is_import = true; + } + if (INKSCAPE.use_gui() && is_import) { + Gtk::Dialog svg_open_dialog(_("Select how to import your SVG")); + svg_open_dialog.set_transient_for( *(INKSCAPE.active_desktop()->getToplevel()) ); + svg_open_dialog.set_border_width(10); + svg_open_dialog.set_resizable(false); + Gtk::Label explanation; + explanation.set_markup(Glib::ustring("How you want the SVG become imported?")); + explanation.set_line_wrap(true); + explanation.set_size_request(600,-1); + Gtk::RadioButton::Group c1, c2; + Gtk::Label choice1_label; + choice1_label.set_markup( + _("The SVG is incrusted inside document, you could edit it")); + Gtk::RadioButton choice1(c1); + choice1.add(choice1_label); + Gtk::RadioButton choice2(c1, _("The SVG is linked from outside document as a image, you can edit only original file")); + Gtk::Box *content = svg_open_dialog.get_content_area(); + content->pack_start(explanation, false, false, 5); + content->pack_start(choice1, false, false, 5); + content->pack_start(choice2, false, false, 5); + Gtk::Button *ok_button = svg_open_dialog.add_button(_("OK"), GTK_RESPONSE_ACCEPT); + svg_open_dialog.show_all_children(); + ok_button->grab_focus(); + int status = svg_open_dialog.run(); + if ( status == GTK_RESPONSE_ACCEPT ) { + link = choice2.get_active(); + } + } + + SPDocument * doc = SPDocument::createNewDoc (NULL, TRUE, TRUE); + if (link) { + + SPDocument * ret = SPDocument::createNewDoc(uri, TRUE); + SPNamedView *nv = sp_document_namedview(doc, NULL); + Glib::ustring display_unit = nv->display_units->abbr; + if (display_unit.empty()) { + display_unit = "px"; + } + double width = ret->getWidth().value(display_unit); + double height = ret->getHeight().value(display_unit); + // Create image node + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); + + // Added 11 Feb 2014 as we now honor "preserveAspectRatio" and this is + // what Inkscaper's expect. + image_node->setAttribute("preserveAspectRatio", "none"); + image_node->setAttribute("width", Glib::ustring::format(width)); + image_node->setAttribute("height", Glib::ustring::format(height)); + Glib::ustring scale = prefs->getString("/dialogs/import/scale"); + if( scale.compare( "auto" ) != 0 ) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "image-rendering", scale.c_str()); + sp_repr_css_set(image_node, css, "style"); + sp_repr_css_attr_unref( css ); + } + // convert filename to uri + gchar* _uri = g_filename_to_uri(uri, NULL, NULL); + if(_uri) { + image_node->setAttribute("xlink:href", _uri); + g_free(_uri); + } else { + image_node->setAttribute("xlink:href", uri); + } + // Add it to the current layer + Inkscape::XML::Node *layer_node = xml_doc->createElement("svg:g"); + layer_node->setAttribute("inkscape:groupmode", "layer"); + layer_node->setAttribute("inkscape:label", "Image"); + doc->getRoot()->appendChildRepr(layer_node); + layer_node->appendChild(image_node); + Inkscape::GC::release(image_node); + Inkscape::GC::release(layer_node); + fit_canvas_to_drawing(doc); + + // Set viewBox if it doesn't exist + if (!doc->getRoot()->viewBox_set) { + doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDisplayUnit()), doc->getHeight().value(doc->getDisplayUnit()))); + } + return doc; + } if (!file->get_uri_scheme().empty()) { if (path.empty()) { try { diff --git a/src/object/sp-lpe-item.cpp b/src/object/sp-lpe-item.cpp index c7c925c55..98c99e3ae 100644 --- a/src/object/sp-lpe-item.cpp +++ b/src/object/sp-lpe-item.cpp @@ -391,7 +391,9 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths, std::vector<SPObject*> clip_path_list = clip_path->childList(true); for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { SPLPEItem* clip_data = dynamic_cast<SPLPEItem*>(*iter); - sp_lpe_item_cleanup_original_path_recursive(clip_data, keep_paths, lpeitem && !lpeitem->hasPathEffectRecursive(), true); + if (clip_data) { + sp_lpe_item_cleanup_original_path_recursive(clip_data, keep_paths, lpeitem && !lpeitem->hasPathEffectRecursive(), true); + } } } @@ -400,7 +402,9 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths, std::vector<SPObject*> mask_path_list = mask_path->childList(true); for ( std::vector<SPObject*>::const_iterator iter = mask_path_list.begin(); iter != mask_path_list.end();++iter) { SPLPEItem* mask_data = dynamic_cast<SPLPEItem*>(*iter); - sp_lpe_item_cleanup_original_path_recursive(mask_data, keep_paths, lpeitem && !lpeitem->hasPathEffectRecursive(), true); + if (mask_data) { + sp_lpe_item_cleanup_original_path_recursive(mask_data, keep_paths, lpeitem && !lpeitem->hasPathEffectRecursive(), true); + } } } @@ -408,8 +412,9 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths, std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPLPEItem* subitem = dynamic_cast<SPLPEItem*>(*iter); - sp_lpe_item_cleanup_original_path_recursive(subitem, keep_paths); - + if (subitem) { + sp_lpe_item_cleanup_original_path_recursive(subitem, keep_paths); + } } } else if (path) { Inkscape::XML::Node *repr = lpeitem->getRepr(); diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 96c446d0c..18b38c68d 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1570,7 +1570,7 @@ void InkscapePreferences::initPageBitmaps() /* Note: /dialogs/import/quality removed use of in r12542 */ _importexport_import_res.init("/dialogs/import/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, Inkscape::Util::Quantity::convert(1, "in", "px"), true, false); _page_bitmaps.add_line( false, _("Default _import resolution:"), _importexport_import_res, _("dpi"), - _("Default bitmap resolution (in dots per inch) for bitmap import"), false); + _("Default bitmap resolution (in dots per inch) for bitmap and SVG import"), false); _importexport_import_res_override.init(_("Override file resolution"), "/dialogs/import/forcexdpi", false); _page_bitmaps.add_line( false, "", _importexport_import_res_override, "", _("Use default bitmap resolution in favor of information from file")); diff --git a/src/verbs.cpp b/src/verbs.cpp index 0c51c5314..4ac94ec1b 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -877,7 +877,7 @@ void FileVerb::perform(SPAction *action, void *data) if (handled) { return; } - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); g_return_if_fail(ensure_desktop_valid(action)); SPDesktop *desktop = sp_action_get_desktop(action); @@ -889,6 +889,7 @@ void FileVerb::perform(SPAction *action, void *data) sp_file_new_default(); break; case SP_VERB_FILE_OPEN: + prefs->setString("/options/openmethod/value", "open"); sp_file_open_dialog(*parent, NULL, NULL); break; case SP_VERB_FILE_REVERT: @@ -910,12 +911,14 @@ void FileVerb::perform(SPAction *action, void *data) sp_file_print(*parent); break; case SP_VERB_FILE_IMPORT: + prefs->setString("/options/openmethod/value","import"); sp_file_import(*parent); break; // case SP_VERB_FILE_EXPORT: // sp_file_export_dialog(*parent); // break; case SP_VERB_FILE_IMPORT_FROM_OCAL: + prefs->setString("/options/openmethod/value", "ocal"); sp_file_import_from_ocal(*parent); break; // case SP_VERB_FILE_EXPORT_TO_OCAL: |
