From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/extension/internal/gdkpixbuf-input.cpp | 257 +++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 src/extension/internal/gdkpixbuf-input.cpp (limited to 'src/extension/internal/gdkpixbuf-input.cpp') diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp new file mode 100644 index 0000000..7441879 --- /dev/null +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * TODO: insert short description here + *//* + * Authors: see git history + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include + +#include +#include +#include +#include +#include + +#include "document.h" +#include "document-undo.h" +#include "gdkpixbuf-input.h" +#include "image-resolution.h" +#include "preferences.h" +#include "selection-chemistry.h" + +#include "display/cairo-utils.h" + +#include "extension/input.h" +#include "extension/system.h" + +#include "io/dir-util.h" + +#include "object/sp-image.h" +#include "object/sp-root.h" + +#include "util/units.h" + +namespace Inkscape { + +namespace Extension { +namespace Internal { + +SPDocument * +GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) +{ + // Determine whether the image should be embedded + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool ask = prefs->getBool( "/dialogs/import/ask"); + bool forcexdpi = prefs->getBool( "/dialogs/import/forcexdpi"); + Glib::ustring link = prefs->getString("/dialogs/import/link"); + Glib::ustring scale = prefs->getString("/dialogs/import/scale"); + + // If we asked about import preferences, get values and update preferences. + if (ask) { + ask = !mod->get_param_bool("do_not_ask"); + forcexdpi = (strcmp(mod->get_param_optiongroup("dpi"), "from_default") == 0); + link = mod->get_param_optiongroup("link"); + scale = mod->get_param_optiongroup("scale"); + + prefs->setBool( "/dialogs/import/ask", ask ); + prefs->setBool( "/dialogs/import/forcexdpi", forcexdpi); + prefs->setString("/dialogs/import/link", link ); + prefs->setString("/dialogs/import/scale", scale ); + } + + bool embed = (link == "embed"); + + SPDocument *doc = nullptr; + std::unique_ptr pb(Inkscape::Pixbuf::create_from_file(uri)); + + // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage. + // Find a way to create the pixbuf only once. + + if (pb) { + doc = SPDocument::createNewDoc(nullptr, TRUE, TRUE); + bool saved = DocumentUndo::getUndoSensitive(doc); + DocumentUndo::setUndoSensitive(doc, false); // no need to undo in this temporary document + + double width = pb->width(); + double height = pb->height(); + double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px")); + + ImageResolution *ir = nullptr; + double xscale = 1; + double yscale = 1; + + + if (!ir && !forcexdpi) { + ir = new ImageResolution(uri); + } + if (ir && ir->ok()) { + xscale = 960.0 / round(10.*ir->x()); // round-off to 0.1 dpi + yscale = 960.0 / round(10.*ir->y()); + // prevent crash on image with too small dpi (bug 1479193) + if (ir->x() <= .05) + xscale = 960.0; + if (ir->y() <= .05) + yscale = 960.0; + } else { + xscale = 96.0 / defaultxdpi; + yscale = 96.0 / defaultxdpi; + } + + width *= xscale; + height *= yscale; + doc->setWidthAndHeight(Util::Quantity(width, "px"), Util::Quantity(height, "px")); + + delete ir; // deleting NULL is safe + + // Create image node + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); + image_node->setAttributeSvgDouble("width", width); + image_node->setAttributeSvgDouble("height", height); + + // Set default value as we honor "preserveAspectRatio". + image_node->setAttribute("preserveAspectRatio", "none"); + + // This is actually 'image-rendering'. + 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 ); + } + + if (embed) { + sp_embed_image(image_node, pb.get()); + } else { + // convert filename to uri + gchar* _uri = g_filename_to_uri(uri, nullptr, nullptr); + 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) { + // std::cerr << "Viewbox not set, setting" << std::endl; + doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDisplayUnit()), doc->getHeight().value(doc->getDisplayUnit()))); + } + + // restore undo, as now this document may be shown to the user if a bitmap was opened + DocumentUndo::setUndoSensitive(doc, saved); + } else { + printf("GdkPixbuf loader failed\n"); + } + + return doc; +} + +#include "clear-n_.h" + +void +GdkpixbufInput::init() +{ + static std::vector< Gdk::PixbufFormat > formatlist = Gdk::Pixbuf::get_formats(); + for (auto i: formatlist) { + GdkPixbufFormat *pixformat = i.gobj(); + + gchar *name = gdk_pixbuf_format_get_name(pixformat); + gchar *description = gdk_pixbuf_format_get_description(pixformat); + gchar **extensions = gdk_pixbuf_format_get_extensions(pixformat); + gchar **mimetypes = gdk_pixbuf_format_get_mime_types(pixformat); + + for (int i = 0; extensions[i] != nullptr; i++) { + for (int j = 0; mimetypes[j] != nullptr; j++) { + + /* thanks but no thanks, we'll handle SVG extensions... */ + if (strcmp(extensions[i], "svg") == 0) { + continue; + } + if (strcmp(extensions[i], "svgz") == 0) { + continue; + } + if (strcmp(extensions[i], "svg.gz") == 0) { + continue; + } + gchar *caption = g_strdup_printf(_("%s bitmap image import"), name); + + // clang-format off + gchar *xmlString = g_strdup_printf( + "\n" + "%s\n" + "org.inkscape.input.gdkpixbuf.%s\n" + + "\n" + "\n" + "\n" + "\n" + + "\n" + "\n" + "\n" + "\n" + + "\n" + "\n" + "\n" + "\n" + "\n" + + "false\n" + "\n" + ".%s\n" + "%s\n" + "%s (*.%s)\n" + "%s\n" + "\n" + "", + caption, + extensions[i], + extensions[i], + mimetypes[j], + name, + extensions[i], + description + ); + // clang-format off + + Inkscape::Extension::build_from_mem(xmlString, new GdkpixbufInput()); + g_free(xmlString); + g_free(caption); + }} + + g_free(name); + g_free(description); + g_strfreev(mimetypes); + g_strfreev(extensions); + } +} + +} } } /* namespace Inkscape, Extension, Implementation */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3