summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2018-05-13 14:35:04 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2018-05-13 14:35:04 +0000
commite6616e3a2aa1ffa83fe173e2180849d1ca14a49d (patch)
treee7b2d1392abea351244452fba0356d72509b900f /src
parentAdd preview for numeric OpenType features. (diff)
downloadinkscape-e6616e3a2aa1ffa83fe173e2180849d1ca14a49d.tar.gz
inkscape-e6616e3a2aa1ffa83fe173e2180849d1ca14a49d.zip
Fix bug embeding SVG as PNG
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp48
-rw-r--r--src/extension/internal/svg.cpp25
-rw-r--r--src/object/sp-image.cpp95
-rw-r--r--src/object/sp-image.h2
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp7
-rw-r--r--src/ui/dialog/inkscape-preferences.h1
6 files changed, 140 insertions, 38 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 29e542b01..eae6b0d19 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -212,6 +212,7 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data)
Pixbuf *pixbuf = NULL;
bool data_is_image = false;
+ bool data_is_svg = false;
bool data_is_base64 = false;
gchar const *data = uri_data;
@@ -243,6 +244,12 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data)
data_is_image = true;
data += 9;
}
+ else if (strncmp(data,"image/svg+xml",13) == 0) {
+ /* JPEG2000 image */
+ data_is_svg = true;
+ data_is_image = true;
+ data += 13;
+ }
else { /* unrecognized option; skip it */
while (*data) {
if (((*data) == ';') || ((*data) == ',')) {
@@ -261,7 +268,7 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data)
}
}
- if ((*data) && data_is_image && data_is_base64) {
+ if ((*data) && data_is_image && !data_is_svg && data_is_base64) {
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
if (!loader) return NULL;
@@ -288,6 +295,45 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data)
}
g_object_unref(loader);
}
+
+ if ((*data) && data_is_image && data_is_svg && data_is_base64) {
+ gsize decoded_len = 0;
+ guchar *decoded = g_base64_decode(data, &decoded_len);
+ SPDocument *svgDoc = SPDocument::createNewDocFromMem (reinterpret_cast<gchar const *>(decoded), decoded_len, false);
+ // 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));
+
+ GdkPixbuf *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) {
+ std::cerr << "Pixbuf::create_from_data: failed to load contents: " << std::endl;
+ g_free(decoded);
+ return NULL;
+ } else {
+ g_object_ref(buf);
+ pixbuf = new Pixbuf(buf);
+ pixbuf->_setMimeData(decoded, decoded_len, "svg+xml");
+ }
+ }
return pixbuf;
}
diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp
index bf4924b2a..41fca734f 100644
--- a/src/extension/internal/svg.cpp
+++ b/src/extension/internal/svg.cpp
@@ -137,12 +137,11 @@ Svg::init(void)
"<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
"<name>" N_("SVG Input") "</name>\n"
"<id>" SP_MODULE_KEY_INPUT_SVG "</id>\n"
- "<param name='method' type='optiongroup' appearance='full' _gui-text='" N_("Method to import SVG:") "' _gui-description='" N_("Select the way the SVG is imported.") "' >\n"
- "<_option value='include' >" N_("Include SVG image as editable object(s) in the current file") "</_option>\n"
- "<_option value='link' >" N_("Link the SVG file in a image tag (not editable in this document") "</_option>\n"
- "<_option value='embed' >" N_("Embed the SVG file in a image tag (not editable in this document") "</_option>\n"
+ "<param name='link_svg' type='optiongroup' appearance='full' _gui-text='" N_("SVG Image Import Type:") "' _gui-description='" N_("Include SVG image as editable object(s) in the current file, Embed the SVG file in a image tag (not editable in this document) or Link the SVG file in a image tag (not editable in this document).") "' >\n"
+ "<_option value='include' >" N_("Include") "</_option>\n"
+ "<_option value='embed' >" N_("Embed") "</_option>\n"
+ "<_option value='link' >" N_("Link") "</_option>\n"
"</param>\n"
-
"<param name='scale' appearance='minimal' type='optiongroup' _gui-text='" N_("Image Rendering Mode:") "' _gui-description='" N_("When an image is upscaled, apply smoothing or keep blocky (pixelated). (Will not work in all browsers.)") "' >\n"
"<_option value='auto' >" N_("None (auto)") "</_option>\n"
"<_option value='optimizeQuality' >" N_("Smooth (optimizeQuality)") "</_option>\n"
@@ -206,19 +205,19 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri)
const auto path = file->get_path();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool ask = prefs->getBool("/dialogs/import/ask");
- Glib::ustring method = prefs->getString("/dialogs/import/method");
+ Glib::ustring link_svg = prefs->getString("/dialogs/import/link_svg");
Glib::ustring scale = prefs->getString("/dialogs/import/scale");
bool is_import = false;
if (strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") == 0) {
is_import = true;
}
if(INKSCAPE.use_gui() && is_import && ask) {
- Glib::ustring mod_method = mod->get_param_optiongroup("method");
+ Glib::ustring mod_link_svg = mod->get_param_optiongroup("link_svg");
Glib::ustring mod_scale = mod->get_param_optiongroup("scale");
- if( method.compare( mod_method) != 0 ) {
- method = mod_method;
+ if( link_svg.compare( mod_link_svg) != 0 ) {
+ link_svg = mod_link_svg;
}
- prefs->setString("/dialogs/import/method", method );
+ prefs->setString("/dialogs/import/link_svg", link_svg );
if( scale.compare( mod_scale ) != 0 ) {
scale = mod_scale;
}
@@ -227,8 +226,8 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri)
}
SPDocument * doc = SPDocument::createNewDoc (NULL, TRUE, TRUE);
- if (method.compare("include") != 0 && is_import) {
- bool embed = ( method.compare( "embed" ) == 0 );
+ if (link_svg.compare("include") != 0 && is_import) {
+ bool embed = ( link_svg.compare( "embed" ) == 0 );
SPDocument * ret = SPDocument::createNewDoc(uri, TRUE);
SPNamedView *nv = sp_document_namedview(doc, NULL);
Glib::ustring display_unit = nv->display_units->abbr;
@@ -257,7 +256,7 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri)
if (embed) {
std::unique_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri));
if(pb) {
- sp_embed_image(image_node, pb.get());
+ sp_embed_svg(image_node, uri);
}
} else {
gchar* _uri = g_filename_to_uri(uri, NULL, NULL);
diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp
index 3a76b9633..cc319a924 100644
--- a/src/object/sp-image.cpp
+++ b/src/object/sp-image.cpp
@@ -125,7 +125,6 @@ SPImage::SPImage() : SPItem(), SPViewBox() {
this->color_profile = 0;
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
this->pixbuf = 0;
- this->on_construct = true;
}
SPImage::~SPImage() {
@@ -327,12 +326,9 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) {
SPDocument *doc = this->document;
SPItem::update(ctx, flags);
-
- if ((flags & SP_IMAGE_HREF_MODIFIED_FLAG) || this->on_construct) {
- this->on_construct = false;
+ if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) {
delete this->pixbuf;
this->pixbuf = NULL;
-
if (this->href) {
Inkscape::Pixbuf *pixbuf = NULL;
pixbuf = sp_image_repr_read_image (
@@ -512,24 +508,23 @@ gchar* SPImage::description() const {
this->pixbuf->height(),
href_desc) );
-// if (this->pixbuf == NULL &&
-// this->document)
-// {
-// Inkscape::Pixbuf * pb = NULL;
-// pb = sp_image_repr_read_image (
-// this->getRepr()->attribute("xlink:href"),
-// this->getRepr()->attribute("sodipodi:absref"),
-// this->document->getBase());
-
-// if (pb) {
-// ret = ( pb == NULL ? g_strdup_printf(_("[bad reference]: %s"), href_desc)
-// : g_strdup_printf(_("%d &#215; %d: %s"),
-// pb->width(),
-// pb->height(),
-// href_desc));
-// delete pb;
-// }
-// }
+ if (this->pixbuf == NULL &&
+ this->document)
+ {
+ Inkscape::Pixbuf * pb = NULL;
+ pb = sp_image_repr_read_image (
+ this->getRepr()->attribute("xlink:href"),
+ this->getRepr()->attribute("sodipodi:absref"),
+ this->document->getBase());
+
+ if (pb) {
+ ret = g_strdup_printf(_("%d &#215; %d: %s"),
+ pb->width(),
+ pb->height(),
+ href_desc);
+ delete pb;
+ }
+ }
g_free(href_desc);
return ret;
@@ -793,6 +788,60 @@ void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb)
if (free_data) g_free(data);
}
+void sp_embed_svg(Inkscape::XML::Node *image_node, std::string const &fn)
+{
+ if (!g_file_test(fn.c_str(), G_FILE_TEST_EXISTS)) {
+ return;
+ }
+ GStatBuf stdir;
+ int val = g_stat(fn.c_str(), &stdir);
+ if (val == 0 && stdir.st_mode & S_IFDIR){
+ return;
+ }
+
+ // we need to load the entire file into memory,
+ // since we'll store it as MIME data
+ gchar *data = NULL;
+ gsize len = 0;
+ GError *error = NULL;
+
+ if (g_file_get_contents(fn.c_str(), &data, &len, &error)) {
+
+ if (error != NULL) {
+ std::cerr << "Pixbuf::create_from_file: " << error->message << std::endl;
+ std::cerr << " (" << fn << ")" << std::endl;
+ return;
+ }
+
+ std::string data_mimetype = "image/svg+xml";
+
+
+ // Save base64 encoded data in image node
+ // this formula taken from Glib docs
+ gsize needed_size = len * 4 / 3 + len * 4 / (3 * 72) + 7;
+ needed_size += 5 + 8 + data_mimetype.size(); // 5 bytes for data: + 8 for ;base64,
+
+ gchar *buffer = (gchar *) g_malloc(needed_size);
+ gchar *buf_work = buffer;
+ buf_work += g_sprintf(buffer, "data:%s;base64,", data_mimetype.c_str());
+
+ gint state = 0;
+ gint save = 0;
+ gsize written = 0;
+ written += g_base64_encode_step(reinterpret_cast<guchar *>(data), len, TRUE, buf_work, &state, &save);
+ written += g_base64_encode_close(TRUE, buf_work + written, &state, &save);
+ buf_work[written] = 0; // null terminate
+
+ // TODO: this is very wasteful memory-wise.
+ // It would be better to only keep the binary data around,
+ // and base64 encode on the fly when saving the XML.
+ image_node->setAttribute("xlink:href", buffer);
+
+ g_free(buffer);
+ g_free(data);
+ }
+}
+
void sp_image_refresh_if_outdated( SPImage* image )
{
if ( image->href && image->pixbuf && image->pixbuf->modificationTime()) {
diff --git a/src/object/sp-image.h b/src/object/sp-image.h
index a5dd84fe2..9a45f819c 100644
--- a/src/object/sp-image.h
+++ b/src/object/sp-image.h
@@ -63,12 +63,12 @@ public:
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
void apply_profile(Inkscape::Pixbuf *pixbuf);
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- bool on_construct;
};
/* Return duplicate of curve or NULL */
SPCurve *sp_image_get_curve (SPImage *image);
void sp_embed_image(Inkscape::XML::Node *imgnode, Inkscape::Pixbuf *pb);
+void sp_embed_svg(Inkscape::XML::Node *image_node, std::string const &fn);
void sp_image_refresh_if_outdated( SPImage* image );
#endif
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index f0ac55736..6b55da0da 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -1563,6 +1563,13 @@ void InkscapePreferences::initPageBitmaps()
}
{
+ Glib::ustring labels[] = {_("Include"), _("Embed"), _("Link")};
+ Glib::ustring values[] = {"include", "embed", "link"};
+ _svg_link.init("/dialogs/import/link_svg", labels, values, G_N_ELEMENTS(values), "include");
+ _page_bitmaps.add_line( false, _("SVG link:"), _svg_link, "", "", false);
+ }
+
+ {
Glib::ustring labels[] = {_("None (auto)"), _("Smooth (optimizeQuality)"), _("Blocky (optimizeSpeed)") };
Glib::ustring values[] = {"auto", "optimizeQuality", "optimizeSpeed"};
_bitmap_scale.init("/dialogs/import/scale", labels, values, G_N_ELEMENTS(values), "scale");
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 80df5ed65..828859bb8 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -380,6 +380,7 @@ protected:
UI::Widget::PrefSpinButton _bitmap_copy_res;
UI::Widget::PrefCheckButton _bitmap_ask;
UI::Widget::PrefCombo _bitmap_link;
+ UI::Widget::PrefCombo _svg_link;
UI::Widget::PrefCombo _bitmap_scale;
UI::Widget::PrefSpinButton _bitmap_import_quality;