From 11a87b3029773a8f70a914dbd514a3ae232e0c9d Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Sun, 9 Sep 2018 22:41:10 +0200 Subject: [PATCH 1/8] Add widgets to handle DPI when SVG is loaded or after --- .vscode/settings.json | 13 +++++++++++ src/attributes.cpp | 1 + src/attributes.h | 1 + src/display/cairo-utils.cpp | 16 +++++++++---- src/display/cairo-utils.h | 4 ++-- src/extension/internal/svg.cpp | 5 +++- src/object/sp-image.cpp | 36 +++++++++++++++++++++-------- src/object/sp-image.h | 1 + src/ui/dialog/object-attributes.cpp | 4 ++++ src/ui/dialog/object-properties.cpp | 2 ++ src/ui/dialog/object-properties.h | 4 ++++ testfiles/src/attributes-test.cpp | 1 + 12 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..4275c979aa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "files.associations": { + "*.ipp": "cpp", + "ratio": "cpp", + "system_error": "cpp", + "istream": "cpp", + "optional": "cpp", + "ostream": "cpp", + "type_traits": "cpp", + "atomic": "cpp", + "chrono": "cpp" + } +} \ No newline at end of file diff --git a/src/attributes.cpp b/src/attributes.cpp index b2c676e884..e98f84700c 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -137,6 +137,7 @@ static SPStyleProp const props[] = { /* SPImage */ {SP_ATTR_X, "x"}, {SP_ATTR_Y, "y"}, + {SP_ATTR_SVG_DPI, "inkscape:svg-dpi"}, /* SPPath */ {SP_ATTR_INKSCAPE_ORIGINAL_D, "inkscape:original-d"}, /* (Note: XML representation of connectors may change in future.) */ diff --git a/src/attributes.h b/src/attributes.h index caad42f71d..c840161386 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -145,6 +145,7 @@ enum SPAttributeEnum { /* SPImage, SPRect, etc. */ SP_ATTR_X, SP_ATTR_Y, + SP_ATTR_SVG_DPI, /* SPPath */ // SP_ATTR_D, Promoted to property in SVG 2 SP_ATTR_INKSCAPE_ORIGINAL_D, diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index e34e4cd6b7..02425163d7 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -207,7 +207,7 @@ Pixbuf::~Pixbuf() } } -Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data) +Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data, char const *svgdpi) { Pixbuf *pixbuf = nullptr; @@ -310,7 +310,11 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data) return nullptr; } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - const double dpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", 96.0); + double dpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", 96.0); + if (svgdpi && atof(svgdpi) > 0) { + dpi = atof(svgdpi); + } + std::cout << dpi << "dpi" << std::endl; // Get the size of the document Inkscape::Util::Quantity svgWidth = svgDoc->getWidth(); Inkscape::Util::Quantity svgHeight = svgDoc->getHeight(); @@ -338,7 +342,7 @@ Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data) return pixbuf; } -Pixbuf *Pixbuf::create_from_file(std::string const &fn) +Pixbuf *Pixbuf::create_from_file(std::string const &fn, char const *svgdpi) { Pixbuf *pb = nullptr; // test correctness of filename @@ -383,7 +387,11 @@ Pixbuf *Pixbuf::create_from_file(std::string const &fn) return nullptr; } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - const double dpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", 96.0); + double dpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", 96.0); + if (svgdpi && atof(svgdpi) > 0) { + dpi = atof(svgdpi); + } + std::cout << dpi << "dpi" << std::endl; // Get the size of the document Inkscape::Util::Quantity svgWidth = svgDoc->getWidth(); Inkscape::Util::Quantity svgHeight = svgDoc->getHeight(); diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index bada170ca1..c8abad1cc4 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -117,8 +117,8 @@ public: PixelFormat pixelFormat() const { return _pixel_format; } void ensurePixelFormat(PixelFormat fmt); - static Pixbuf *create_from_data_uri(gchar const *uri); - static Pixbuf *create_from_file(std::string const &fn); + static Pixbuf *create_from_data_uri(gchar const *uri, char const *svgdpi = NULL); + static Pixbuf *create_from_file(std::string const &fn, char const *svgddpi = NULL); private: void _ensurePixelsARGB32(); diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index 189ef3c585..e26c7c7938 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -142,6 +142,7 @@ Svg::init() "<_option value='embed' >" N_("Embed the SVG file in a image tag (not editable in this document)") "\n" "<_option value='link' >" N_("Link the SVG file in a image tag (not editable in this document).") "\n" "\n" + "96.00\n" "\n" "<_option value='auto' >" N_("None (auto)") "\n" "<_option value='optimizeQuality' >" N_("Smooth (optimizeQuality)") "\n" @@ -243,6 +244,8 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) // Added 11 Feb 2014 as we now honor "preserveAspectRatio" and this is // what Inkscaper's expect. image_node->setAttribute("preserveAspectRatio", "none"); + Glib::ustring svgdpi = Glib::ustring::format(mod->get_param_float("svgdpi")); + image_node->setAttribute("inkscape:svg-dpi", svgdpi.c_str()); image_node->setAttribute("width", Glib::ustring::format(width)); image_node->setAttribute("height", Glib::ustring::format(height)); Glib::ustring scale = prefs->getString("/dialogs/import/scale"); @@ -258,7 +261,7 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) if(pb) { sp_embed_svg(image_node, uri); } - } else { + } else { gchar* _uri = g_filename_to_uri(uri, nullptr, nullptr); if(_uri) { image_node->setAttribute("xlink:href", _uri); diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp index a5bc115ce6..bd8d7ef697 100644 --- a/src/object/sp-image.cpp +++ b/src/object/sp-image.cpp @@ -72,7 +72,7 @@ static void sp_image_set_curve(SPImage *image); -static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base ); +static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base , char const *svgdpi); static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai); static void sp_image_update_canvas_image (SPImage *image); @@ -117,7 +117,7 @@ SPImage::SPImage() : SPItem(), SPViewBox() { this->clipbox = Geom::Rect(); this->sx = this->sy = 1.0; this->ox = this->oy = 0.0; - + this->dpi = 96.00; this->curve = nullptr; this->href = nullptr; @@ -137,6 +137,7 @@ void SPImage::build(SPDocument *document, Inkscape::XML::Node *repr) { this->readAttr( "y" ); this->readAttr( "width" ); this->readAttr( "height" ); + this->readAttr( "inkscape:svg-dpi" ); this->readAttr( "preserveAspectRatio" ); this->readAttr( "color-profile" ); @@ -215,6 +216,10 @@ void SPImage::set(unsigned int key, const gchar* value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; + + case SP_ATTR_SVG_DPI: + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); + break; case SP_ATTR_PRESERVEASPECTRATIO: set_preserveAspectRatio( value ); @@ -330,10 +335,16 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { this->pixbuf = nullptr; if (this->href) { Inkscape::Pixbuf *pixbuf = nullptr; + const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + if (!svgdpi) { + svgdpi = "96"; + } + this->dpi = atof(svgdpi); pixbuf = sp_image_repr_read_image ( this->getRepr()->attribute("xlink:href"), this->getRepr()->attribute("sodipodi:absref"), - doc->getBase()); + doc->getBase(), + svgdpi); if (pixbuf) { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) @@ -437,7 +448,7 @@ Inkscape::XML::Node *SPImage::write(Inkscape::XML::Document *xml_doc, Inkscape:: if (this->height._set) { sp_repr_set_svg_double(repr, "height", this->height.computed); } - + repr->setAttribute("inkscape:svg-dpi", this->getRepr()->attribute("inkscape:svg-dpi")); //XML Tree being used directly here while it shouldn't be... repr->setAttribute("preserveAspectRatio", this->getRepr()->attribute("preserveAspectRatio")); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) @@ -511,10 +522,15 @@ gchar* SPImage::description() const { this->document) { Inkscape::Pixbuf * pb = nullptr; + const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + if (!svgdpi) { + svgdpi = "96"; + } pb = sp_image_repr_read_image ( this->getRepr()->attribute("xlink:href"), this->getRepr()->attribute("sodipodi:absref"), - this->document->getBase()); + this->document->getBase(), + svgdpi); if (pb) { ret = g_strdup_printf(_("%d × %d: %s"), @@ -537,7 +553,7 @@ Inkscape::DrawingItem* SPImage::show(Inkscape::Drawing &drawing, unsigned int /* return ai; } -Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base) +Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base, char const *svgdpi) { Inkscape::Pixbuf *inkpb = nullptr; @@ -547,7 +563,7 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre if (strncmp (filename,"file:",5) == 0) { gchar *fullname = g_filename_from_uri(filename, nullptr, nullptr); if (fullname) { - inkpb = Inkscape::Pixbuf::create_from_file(fullname); + inkpb = Inkscape::Pixbuf::create_from_file(fullname, svgdpi); g_free(fullname); if (inkpb != nullptr) { return inkpb; @@ -556,7 +572,7 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre } else if (strncmp (filename,"data:",5) == 0) { /* data URI - embedded image */ filename += 5; - inkpb = Inkscape::Pixbuf::create_from_data_uri(filename); + inkpb = Inkscape::Pixbuf::create_from_data_uri(filename, svgdpi); if (inkpb != nullptr) { return inkpb; } @@ -585,7 +601,7 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre /* try filename as absolute */ if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) { - inkpb = Inkscape::Pixbuf::create_from_file(filename); + inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); if (inkpb != nullptr) { return inkpb; } @@ -603,7 +619,7 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref); } - inkpb = Inkscape::Pixbuf::create_from_file(filename); + inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); if (inkpb != nullptr) { return inkpb; } diff --git a/src/object/sp-image.h b/src/object/sp-image.h index 464d0f144b..521e0c4db1 100644 --- a/src/object/sp-image.h +++ b/src/object/sp-image.h @@ -35,6 +35,7 @@ public: Geom::Rect clipbox; double sx, sy; double ox, oy; + double dpi; SPCurve *curve; // This curve is at the image's boundary for snapping diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp index ec3ce1b716..09441342de 100644 --- a/src/ui/dialog/object-attributes.cpp +++ b/src/ui/dialog/object-attributes.cpp @@ -68,6 +68,8 @@ static const SPAttrDesc image_desc[] = { { N_("Width:"), "width"}, { N_("Height:"), "height"}, { N_("Image Rendering:"), "image-rendering"}, + { N_("SVG DPI:"), "inkscape:svg-dpi"}, + { N_("Preserve Aspect Ratio:"), "preserveAspectRatio"}, { nullptr, nullptr} }; @@ -76,6 +78,8 @@ static const SPAttrDesc image_nohref_desc[] = { { N_("Y:"), "y"}, { N_("Width:"), "width"}, { N_("Height:"), "height"}, + { N_("SVG DPI:"), "inkscape:svg-dpi"}, + { N_("Preserve Aspect Ratio:"), "preserveAspectRatio"}, { nullptr, nullptr} }; diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index 8daa83e9c3..f23adab961 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -54,6 +54,7 @@ ObjectProperties::ObjectProperties() , _label_label(_("_Label:"), true) , _label_title(_("_Title:"), true) , _label_image_rendering(_("_Image Rendering:"), true) + , _dpi_value( 96.00) , _cb_hide(_("_Hide"), true) , _cb_lock(_("L_ock"), true) , _attr_table(Gtk::manage(new SPAttributeTable())) @@ -207,6 +208,7 @@ void ObjectProperties::_init() sigc::mem_fun(this, &ObjectProperties::_imageRenderingChanged) ); + /* Check boxes */ Gtk::HBox *hb_checkboxes = Gtk::manage(new Gtk::HBox()); contents->pack_start(*hb_checkboxes, FALSE, FALSE, 0); diff --git a/src/ui/dialog/object-properties.h b/src/ui/dialog/object-properties.h index 4ce72ae1a1..7fba052ead 100644 --- a/src/ui/dialog/object-properties.h +++ b/src/ui/dialog/object-properties.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,7 @@ private: Gtk::Entry _entry_label; //the entry for the object label Gtk::Label _label_title; //the label for the object title Gtk::Entry _entry_title; //the entry for the object title + Gtk::Label _label_image_rendering; // the label for 'image-rendering' Gtk::ComboBoxText _combo_image_rendering; // the combo box text for 'image-rendering' @@ -94,6 +96,8 @@ private: Gtk::CheckButton _cb_hide; //the check button hide Gtk::CheckButton _cb_lock; //the check button lock + Gtk::Label _label_dpi; //the entry for the dpi value + Gtk::SpinButton _dpi_value; //the expander for interactivity Gtk::Expander _exp_interactivity; //the expander for interactivity SPAttributeTable *_attr_table; //the widget for showing the on... names at the bottom diff --git a/testfiles/src/attributes-test.cpp b/testfiles/src/attributes-test.cpp index e6fbe8eceb..34963f22d2 100644 --- a/testfiles/src/attributes-test.cpp +++ b/testfiles/src/attributes-test.cpp @@ -463,6 +463,7 @@ std::vector getKnownAttrs() AttributeInfo("inkscape:window-x", true), AttributeInfo("inkscape:window-y", true), AttributeInfo("inkscape:zoom", true), + AttributeInfo("inkscape:svg-dpi", true), AttributeInfo("osb:paint", true), AttributeInfo("sodipodi:arc-type", true), AttributeInfo("sodipodi:arg1", true), -- GitLab From 968ddbd1be8eeb311f6071532a8b503a40383171 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 00:47:49 +0200 Subject: [PATCH 2/8] add suport to auto update image size if href change --- .vscode/settings.json | 51 +++++++++++++++++- src/extension/internal/svg.cpp | 4 +- src/extension/system.cpp | 4 +- src/object/sp-image.cpp | 28 +++++++++- src/object/sp-image.h | 1 + src/ui/dialog/object-attributes.cpp | 5 -- src/ui/dialog/object-properties.cpp | 84 +++++++++++++++++++++++++++-- src/ui/dialog/object-properties.h | 6 ++- 8 files changed, 167 insertions(+), 16 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4275c979aa..6ce99071c2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,55 @@ "ostream": "cpp", "type_traits": "cpp", "atomic": "cpp", - "chrono": "cpp" + "chrono": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "strstream": "cpp", + "cinttypes": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "slist": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "mutex": "cpp", + "thread": "cpp", + "typeindex": "cpp", + "array": "cpp", + "bitset": "cpp", + "complex": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "iomanip": "cpp", + "iostream": "cpp", + "limits": "cpp", + "memory": "cpp", + "new": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "typeinfo": "cpp", + "utility": "cpp", + "valarray": "cpp", + "algorithm": "cpp" } } \ No newline at end of file diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index e26c7c7938..c89424b140 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -209,7 +209,9 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) 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) { + if (strcmp(prefs->getString("/options/openmethod/value").c_str(), "done") == 0 || + strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") == 0) + { is_import = true; } if(INKSCAPE.use_gui() && is_import && ask) { diff --git a/src/extension/system.cpp b/src/extension/system.cpp index 6802050b0c..66a0491888 100644 --- a/src/extension/system.cpp +++ b/src/extension/system.cpp @@ -100,7 +100,9 @@ SPDocument *open(Extension *key, gchar const *filename) bool ask = prefs->getBool("/dialogs/import/ask"); Glib::ustring id = Glib::ustring(imod->get_id(), 22); if (id.compare( "org.inkscape.input.svg") == 0 && - (strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") != 0 || !ask)) + ((strcmp(prefs->getString("/options/openmethod/value").c_str(), "done") != 0 && + strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") != 0) || + !ask)) { show = false; imod->set_gui(false); diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp index bd8d7ef697..5408ec81d7 100644 --- a/src/object/sp-image.cpp +++ b/src/object/sp-image.cpp @@ -118,6 +118,8 @@ SPImage::SPImage() : SPItem(), SPViewBox() { this->sx = this->sy = 1.0; this->ox = this->oy = 0.0; this->dpi = 96.00; + this->prev_width = 0.0; + this->prev_height = 0.0; this->curve = nullptr; this->href = nullptr; @@ -359,7 +361,6 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { // Why continue without a pixbuf? So we can display "Missing Image" png. // Eventually, we should properly support SVG image type (i.e. render it ourselves). - if (this->pixbuf) { if (!this->x._set) { this->x.unit = SVGLength::PX; @@ -407,10 +408,34 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { this->oy = c2p[5]; this->sx = c2p[0]; this->sy = c2p[3]; + } + + // TODO: eliminate ox, oy, sx, sy + sp_image_update_canvas_image ((SPImage *) this); + double proportion_pixbuf = this->pixbuf->height()/(double)this->pixbuf->width(); + double proportion_image = this->height.computed/(double)this->width.computed; + if (this->prev_width && (this->prev_width != this->pixbuf->width() || this->prev_height != this->pixbuf->height())) { + if (std::abs(this->prev_width - this->pixbuf->width()) > std::abs(this->prev_height - this->pixbuf->height())) { + proportion_pixbuf = this->pixbuf->width()/(double)this->pixbuf->height(); + proportion_image = this->width.computed/(double)this->height.computed; + if(proportion_pixbuf != proportion_image) { + double new_height = this->height.computed * proportion_pixbuf; + sp_repr_set_svg_double(this->getRepr(), "width", new_height); + + } + } else { + if(proportion_pixbuf != proportion_image) { + double new_width = this->width.computed * proportion_pixbuf; + sp_repr_set_svg_double(this->getRepr(), "height", new_width); + } + } + } + this->prev_width = this->pixbuf->width(); + this->prev_height = this->pixbuf->height(); } void SPImage::modified(unsigned int flags) { @@ -649,7 +674,6 @@ sp_image_update_arenaitem (SPImage *image, Inkscape::DrawingImage *ai) static void sp_image_update_canvas_image(SPImage *image) { SPItem *item = SP_ITEM(image); - for (SPItemView *v = item->display; v != nullptr; v = v->next) { sp_image_update_arenaitem(image, dynamic_cast(v->arenaitem)); } diff --git a/src/object/sp-image.h b/src/object/sp-image.h index 521e0c4db1..7d62e756a8 100644 --- a/src/object/sp-image.h +++ b/src/object/sp-image.h @@ -36,6 +36,7 @@ public: double sx, sy; double ox, oy; double dpi; + double prev_width, prev_height; SPCurve *curve; // This curve is at the image's boundary for snapping diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp index 09441342de..6801afa9c2 100644 --- a/src/ui/dialog/object-attributes.cpp +++ b/src/ui/dialog/object-attributes.cpp @@ -67,9 +67,6 @@ static const SPAttrDesc image_desc[] = { { N_("Y:"), "y"}, { N_("Width:"), "width"}, { N_("Height:"), "height"}, - { N_("Image Rendering:"), "image-rendering"}, - { N_("SVG DPI:"), "inkscape:svg-dpi"}, - { N_("Preserve Aspect Ratio:"), "preserveAspectRatio"}, { nullptr, nullptr} }; @@ -78,8 +75,6 @@ static const SPAttrDesc image_nohref_desc[] = { { N_("Y:"), "y"}, { N_("Width:"), "width"}, { N_("Height:"), "height"}, - { N_("SVG DPI:"), "inkscape:svg-dpi"}, - { N_("Preserve Aspect Ratio:"), "preserveAspectRatio"}, { nullptr, nullptr} }; diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index f23adab961..021246f21d 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -53,10 +53,11 @@ ObjectProperties::ObjectProperties() , _label_id(_("_ID:"), true) , _label_label(_("_Label:"), true) , _label_title(_("_Title:"), true) + , _label_dpi(_("_DPI SVG:"), true) , _label_image_rendering(_("_Image Rendering:"), true) - , _dpi_value( 96.00) , _cb_hide(_("_Hide"), true) , _cb_lock(_("L_ock"), true) + , _cb_aspect_ratio(_("Pereserve Ratio"), true) , _attr_table(Gtk::manage(new SPAttributeTable())) , _desktop(nullptr) { @@ -186,12 +187,39 @@ void ObjectProperties::_init() _ft_description.add(_tv_description); _tv_description.add_mnemonic_label(*label_desc); + /* Create the text view box for the DPI svg */ + _ft_description.set_border_width(4); + _ft_description.set_sensitive(FALSE); + frame_desc->add(_ft_description); + _ft_description.set_shadow_type(Gtk::SHADOW_IN); + + _tv_description.set_wrap_mode(Gtk::WRAP_WORD); + _tv_description.get_buffer()->set_text(""); + _ft_description.add(_tv_description); + _tv_description.add_mnemonic_label(*label_desc); + + /* Create the label for the object title */ + _label_dpi.set_label(_label_dpi.get_label() + " "); + _label_dpi.set_halign(Gtk::ALIGN_END); + _label_dpi.set_valign(Gtk::ALIGN_CENTER); + grid_top->attach(_label_dpi, 0, 3, 1, 1); + + /* Create the entry box for the SVG DPI */ + _spin_dpi.set_digits(2); + _spin_dpi.set_range (1,1200); + grid_top->attach(_spin_dpi, 1, 3, 1, 1); + + _label_dpi.set_mnemonic_widget(_spin_dpi); + // pressing enter in the label field is the same as clicking Set: + _spin_dpi.signal_activate().connect(sigc::mem_fun(this, &ObjectProperties::_labelChanged)); + + /* Image rendering */ /* Create the label for the object ImageRendering */ _label_image_rendering.set_label(_label_image_rendering.get_label() + " "); _label_image_rendering.set_halign(Gtk::ALIGN_END); _label_image_rendering.set_valign(Gtk::ALIGN_CENTER); - grid_top->attach(_label_image_rendering, 0, 3, 1, 1); + grid_top->attach(_label_image_rendering, 0, 4, 1, 1); /* Create the combo box text for the 'image-rendering' property */ _combo_image_rendering.append( "auto" ); @@ -200,7 +228,7 @@ void ObjectProperties::_init() _combo_image_rendering.set_tooltip_text(_("The 'image-rendering' property can influence how a bitmap is up-scaled:\n\t'auto' no preference;\n\t'optimizeQuality' smooth;\n\t'optimizeSpeed' blocky.\nNote that this behaviour is not defined in the SVG 1.1 specification and not all browsers follow this interpretation.")); _combo_image_rendering.set_valign(Gtk::ALIGN_CENTER); - grid_top->attach(_combo_image_rendering, 1, 3, 1, 1); + grid_top->attach(_combo_image_rendering, 1, 4, 1, 1); _label_image_rendering.set_mnemonic_widget(_combo_image_rendering); @@ -209,6 +237,8 @@ void ObjectProperties::_init() ); + + /* Check boxes */ Gtk::HBox *hb_checkboxes = Gtk::manage(new Gtk::HBox()); contents->pack_start(*hb_checkboxes, FALSE, FALSE, 0); @@ -237,12 +267,20 @@ void ObjectProperties::_init() _cb_lock.signal_toggled().connect(sigc::mem_fun(this, &ObjectProperties::_sensitivityToggled)); + /* Preserve aspect ratio */ + _cb_aspect_ratio.set_tooltip_text (_("Check to preserve aspect ratio on images")); + _cb_aspect_ratio.set_hexpand(); + _cb_aspect_ratio.set_valign(Gtk::ALIGN_CENTER); + grid_cb->attach(_cb_aspect_ratio, 0, 1, 1, 1); + + _cb_aspect_ratio.signal_toggled().connect(sigc::mem_fun(this, &ObjectProperties::_aspectRatioToggled)); + /* Button for setting the object's id, label, title and description. */ Gtk::Button *btn_set = Gtk::manage(new Gtk::Button(_("_Set"), true)); btn_set->set_hexpand(); btn_set->set_valign(Gtk::ALIGN_CENTER); - grid_cb->attach(*btn_set, 2, 0, 1, 1); + grid_cb->attach(*btn_set, 1, 1, 1, 1); btn_set->signal_clicked().connect(sigc::mem_fun(this, &ObjectProperties::_labelChanged)); @@ -286,7 +324,7 @@ void ObjectProperties::update() return; } _blocked = true; - + _cb_aspect_ratio.set_active(item->getAttribute("preserveAspectRatio") == "true"); _cb_lock.set_active(item->isLocked()); /* Sensitive */ _cb_hide.set_active(item->isExplicitlyHidden()); /* Hidden */ @@ -411,6 +449,14 @@ void ObjectProperties::_labelChanged() _("Set object title")); } + /* Retrieve the DPI */ + if (SP_IS_IMAGE(obj)) { + Glib::ustring dpi_value = Glib::ustring::format(_spin_dpi.get_value()); + obj->setAttribute("inkscape:svg-dpi", dpi_value); + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, + _("Set image DPI")); + } + /* Retrieve the description */ Gtk::TextBuffer::iterator start, end; _tv_description.get_buffer()->get_bounds(start, end); @@ -466,6 +512,34 @@ void ObjectProperties::_sensitivityToggled() _blocked = false; } +void ObjectProperties::_aspectRatioToggled() +{ + if (_blocked) { + return; + } + + SPItem *item = SP_ACTIVE_DESKTOP->getSelection()->singleItem(); + g_return_if_fail(item != nullptr); + + _blocked = true; + + item->setLocked(_cb_aspect_ratio.get_active()); + const char *active; + if(_cb_aspect_ratio.get_active()) { + active = "true"; + } else { + active = "none"; + } + /* Retrieve the DPI */ + if (SP_IS_IMAGE(item)) { + Glib::ustring dpi_value = Glib::ustring::format(_spin_dpi.get_value()); + item->setAttribute("preserveAspectRatio", active); + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, + _("Set preserve ratio")); + } + _blocked = false; +} + void ObjectProperties::_hiddenToggled() { if (_blocked) { diff --git a/src/ui/dialog/object-properties.h b/src/ui/dialog/object-properties.h index 7fba052ead..f603219c4e 100644 --- a/src/ui/dialog/object-properties.h +++ b/src/ui/dialog/object-properties.h @@ -95,9 +95,10 @@ private: Gtk::CheckButton _cb_hide; //the check button hide Gtk::CheckButton _cb_lock; //the check button lock + Gtk::CheckButton _cb_aspect_ratio; //the preserve aspect ratio of images Gtk::Label _label_dpi; //the entry for the dpi value - Gtk::SpinButton _dpi_value; //the expander for interactivity + Gtk::SpinButton _spin_dpi; //the expander for interactivity Gtk::Expander _exp_interactivity; //the expander for interactivity SPAttributeTable *_attr_table; //the widget for showing the on... names at the bottom @@ -122,6 +123,9 @@ private: /// Callback for checkbox Hide. void _hiddenToggled(); + /// Callback for checkbox Preserve Aspect Ratio. + void _aspectRatioToggled(); + /// Can be invoked for setting the desktop. Currently not used. void _setDesktop(SPDesktop *desktop); -- GitLab From d7706d3ee0ac849620fce6253e8ff566854c608f Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 00:59:31 +0200 Subject: [PATCH 3/8] fixing coding style --- src/display/cairo-utils.h | 2 +- src/extension/internal/svg.cpp | 8 +- src/extension/system.cpp | 9 +- src/object/sp-image.cpp | 51 +- src/object/sp-image.cpp.orig | 913 ++++++++++++++++++++++++++++ src/ui/dialog/object-properties.cpp | 22 +- 6 files changed, 955 insertions(+), 50 deletions(-) create mode 100644 src/object/sp-image.cpp.orig diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index c8abad1cc4..256bda94c3 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -120,7 +120,7 @@ public: static Pixbuf *create_from_data_uri(gchar const *uri, char const *svgdpi = NULL); static Pixbuf *create_from_file(std::string const &fn, char const *svgddpi = NULL); -private: + private: void _ensurePixelsARGB32(); void _ensurePixelsPixbuf(); void _forceAlpha(); diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index c89424b140..0931d964a1 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -209,9 +209,8 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) 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(), "done") == 0 || - strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") == 0) - { + if (strcmp(prefs->getString("/options/openmethod/value").c_str(), "done") == 0 || + strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") == 0) { is_import = true; } if(INKSCAPE.use_gui() && is_import && ask) { @@ -263,7 +262,8 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) if(pb) { sp_embed_svg(image_node, uri); } - } else { + } + else { gchar* _uri = g_filename_to_uri(uri, nullptr, nullptr); if(_uri) { image_node->setAttribute("xlink:href", _uri); diff --git a/src/extension/system.cpp b/src/extension/system.cpp index 66a0491888..2a74c6b0cc 100644 --- a/src/extension/system.cpp +++ b/src/extension/system.cpp @@ -99,11 +99,10 @@ SPDocument *open(Extension *key, gchar const *filename) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool ask = prefs->getBool("/dialogs/import/ask"); Glib::ustring id = Glib::ustring(imod->get_id(), 22); - if (id.compare( "org.inkscape.input.svg") == 0 && - ((strcmp(prefs->getString("/options/openmethod/value").c_str(), "done") != 0 && - strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") != 0) || - !ask)) - { + if (id.compare("org.inkscape.input.svg") == 0 && + ((strcmp(prefs->getString("/options/openmethod/value").c_str(), "done") != 0 && + strcmp(prefs->getString("/options/openmethod/value").c_str(), "import") != 0) || + !ask)) { show = false; imod->set_gui(false); } else if(strlen(imod->get_id()) > 27) { diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp index 5408ec81d7..e12c7105b8 100644 --- a/src/object/sp-image.cpp +++ b/src/object/sp-image.cpp @@ -72,7 +72,8 @@ static void sp_image_set_curve(SPImage *image); -static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base , char const *svgdpi); +static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base, + char const *svgdpi); static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai); static void sp_image_update_canvas_image (SPImage *image); @@ -139,7 +140,7 @@ void SPImage::build(SPDocument *document, Inkscape::XML::Node *repr) { this->readAttr( "y" ); this->readAttr( "width" ); this->readAttr( "height" ); - this->readAttr( "inkscape:svg-dpi" ); + this->readAttr("inkscape:svg-dpi"); this->readAttr( "preserveAspectRatio" ); this->readAttr( "color-profile" ); @@ -218,7 +219,7 @@ void SPImage::set(unsigned int key, const gchar* value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; - + case SP_ATTR_SVG_DPI: this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); break; @@ -337,17 +338,14 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { this->pixbuf = nullptr; if (this->href) { Inkscape::Pixbuf *pixbuf = nullptr; - const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + const gchar *svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); if (!svgdpi) { svgdpi = "96"; } this->dpi = atof(svgdpi); - pixbuf = sp_image_repr_read_image ( - this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), - doc->getBase(), - svgdpi); - + pixbuf = sp_image_repr_read_image(this->getRepr()->attribute("xlink:href"), + this->getRepr()->attribute("sodipodi:absref"), doc->getBase(), svgdpi); + if (pixbuf) { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) if ( this->color_profile ) apply_profile( pixbuf ); @@ -408,27 +406,27 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { this->oy = c2p[5]; this->sx = c2p[0]; this->sy = c2p[3]; - } - + // TODO: eliminate ox, oy, sx, sy sp_image_update_canvas_image ((SPImage *) this); - double proportion_pixbuf = this->pixbuf->height()/(double)this->pixbuf->width(); - double proportion_image = this->height.computed/(double)this->width.computed; - if (this->prev_width && (this->prev_width != this->pixbuf->width() || this->prev_height != this->pixbuf->height())) { + double proportion_pixbuf = this->pixbuf->height() / (double)this->pixbuf->width(); + double proportion_image = this->height.computed / (double)this->width.computed; + if (this->prev_width && + (this->prev_width != this->pixbuf->width() || this->prev_height != this->pixbuf->height())) { if (std::abs(this->prev_width - this->pixbuf->width()) > std::abs(this->prev_height - this->pixbuf->height())) { - proportion_pixbuf = this->pixbuf->width()/(double)this->pixbuf->height(); - proportion_image = this->width.computed/(double)this->height.computed; - if(proportion_pixbuf != proportion_image) { + proportion_pixbuf = this->pixbuf->width() / (double)this->pixbuf->height(); + proportion_image = this->width.computed / (double)this->height.computed; + if (proportion_pixbuf != proportion_image) { double new_height = this->height.computed * proportion_pixbuf; - sp_repr_set_svg_double(this->getRepr(), "width", new_height); - + sp_repr_set_svg_double(this->getRepr(), "width", new_height); } - } else { - if(proportion_pixbuf != proportion_image) { + } + else { + if (proportion_pixbuf != proportion_image) { double new_width = this->width.computed * proportion_pixbuf; sp_repr_set_svg_double(this->getRepr(), "height", new_width); } @@ -547,15 +545,12 @@ gchar* SPImage::description() const { this->document) { Inkscape::Pixbuf * pb = nullptr; - const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + const gchar *svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); if (!svgdpi) { svgdpi = "96"; } - pb = sp_image_repr_read_image ( - this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), - this->document->getBase(), - svgdpi); + pb = sp_image_repr_read_image(this->getRepr()->attribute("xlink:href"), + this->getRepr()->attribute("sodipodi:absref"), this->document->getBase(), svgdpi); if (pb) { ret = g_strdup_printf(_("%d × %d: %s"), diff --git a/src/object/sp-image.cpp.orig b/src/object/sp-image.cpp.orig new file mode 100644 index 0000000000..5408ec81d7 --- /dev/null +++ b/src/object/sp-image.cpp.orig @@ -0,0 +1,913 @@ +/* + * SVG implementation + * + * Authors: + * Lauris Kaplinski + * Edward Flick (EAF) + * Abhishek Sharma + * Jon A. Cruz + * + * Copyright (C) 1999-2005 Authors + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include <2geom/rect.h> +#include <2geom/transforms.h> +#include + +#include "display/drawing-image.h" +#include "display/cairo-utils.h" +#include "display/curve.h" +//Added for preserveAspectRatio support -- EAF +#include "attributes.h" +#include "print.h" +#include "brokenimage.xpm" +#include "document.h" +#include "sp-image.h" +#include "sp-clippath.h" +#include "xml/quote.h" +#include "preferences.h" +#include "io/sys.h" + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +#include "cms-system.h" +#include "color-profile.h" + +#if HAVE_LIBLCMS2 +# include +#elif HAVE_LIBLCMS1 +# include +#endif // HAVE_LIBLCMS2 + +//#define DEBUG_LCMS +#ifdef DEBUG_LCMS +#define DEBUG_MESSAGE(key, ...)\ +{\ + g_message( __VA_ARGS__ );\ +} +#include +#else +#define DEBUG_MESSAGE(key, ...) +#endif // DEBUG_LCMS +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +/* + * SPImage + */ + +// TODO: give these constants better names: +#define MAGIC_EPSILON 1e-9 +#define MAGIC_EPSILON_TOO 1e-18 +// TODO: also check if it is correct to be using two different epsilon values + +static void sp_image_set_curve(SPImage *image); + +static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base , char const *svgdpi); +static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai); +static void sp_image_update_canvas_image (SPImage *image); + +#ifdef DEBUG_LCMS +extern guint update_in_progress; +#define DEBUG_MESSAGE_SCISLAC(key, ...) \ +{\ + Inkscape::Preferences *prefs = Inkscape::Preferences::get();\ + bool dump = prefs->getBool("/options/scislac/" #key);\ + bool dumpD = prefs->getBool("/options/scislac/" #key "D");\ + bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2");\ + dumpD &&= ( (update_in_progress == 0) || dumpD2 );\ + if ( dump )\ + {\ + g_message( __VA_ARGS__ );\ +\ + }\ + if ( dumpD )\ + {\ + GtkWidget *dialog = gtk_message_dialog_new(NULL,\ + GTK_DIALOG_DESTROY_WITH_PARENT, \ + GTK_MESSAGE_INFO, \ + GTK_BUTTONS_OK, \ + __VA_ARGS__ \ + );\ + g_signal_connect_swapped(dialog, "response",\ + G_CALLBACK(gtk_widget_destroy), \ + dialog); \ + gtk_widget_show_all( dialog );\ + }\ +} +#else // DEBUG_LCMS +#define DEBUG_MESSAGE_SCISLAC(key, ...) +#endif // DEBUG_LCMS + +SPImage::SPImage() : SPItem(), SPViewBox() { + + this->x.unset(); + this->y.unset(); + this->width.unset(); + this->height.unset(); + this->clipbox = Geom::Rect(); + this->sx = this->sy = 1.0; + this->ox = this->oy = 0.0; + this->dpi = 96.00; + this->prev_width = 0.0; + this->prev_height = 0.0; + this->curve = nullptr; + + this->href = nullptr; +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + this->color_profile = nullptr; +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + this->pixbuf = nullptr; +} + +SPImage::~SPImage() = default; + +void SPImage::build(SPDocument *document, Inkscape::XML::Node *repr) { + SPItem::build(document, repr); + + this->readAttr( "xlink:href" ); + this->readAttr( "x" ); + this->readAttr( "y" ); + this->readAttr( "width" ); + this->readAttr( "height" ); + this->readAttr( "inkscape:svg-dpi" ); + this->readAttr( "preserveAspectRatio" ); + this->readAttr( "color-profile" ); + + /* Register */ + document->addResource("image", this); +} + +void SPImage::release() { + if (this->document) { + // Unregister ourselves + this->document->removeResource("image", this); + } + + if (this->href) { + g_free (this->href); + this->href = nullptr; + } + + delete this->pixbuf; + this->pixbuf = nullptr; + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + if (this->color_profile) { + g_free (this->color_profile); + this->color_profile = nullptr; + } +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + if (this->curve) { + this->curve = this->curve->unref(); + } + + SPItem::release(); +} + +void SPImage::set(unsigned int key, const gchar* value) { + switch (key) { + case SP_ATTR_XLINK_HREF: + g_free (this->href); + this->href = (value) ? g_strdup (value) : nullptr; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); + break; + + case SP_ATTR_X: + /* ex, em not handled correctly. */ + if (!this->x.read(value)) { + this->x.unset(); + } + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_Y: + /* ex, em not handled correctly. */ + if (!this->y.read(value)) { + this->y.unset(); + } + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_WIDTH: + /* ex, em not handled correctly. */ + if (!this->width.read(value)) { + this->width.unset(); + } + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_HEIGHT: + /* ex, em not handled correctly. */ + if (!this->height.read(value)) { + this->height.unset(); + } + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_SVG_DPI: + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); + break; + + case SP_ATTR_PRESERVEASPECTRATIO: + set_preserveAspectRatio( value ); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); + break; + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + case SP_PROP_COLOR_PROFILE: + if ( this->color_profile ) { + g_free (this->color_profile); + } + + this->color_profile = (value) ? g_strdup (value) : nullptr; + + if ( value ) { + DEBUG_MESSAGE( lcmsFour, " color-profile set to '%s'", value ); + } else { + DEBUG_MESSAGE( lcmsFour, " color-profile cleared" ); + } + + // TODO check on this HREF_MODIFIED flag + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); + break; + +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + default: + SPItem::set(key, value); + break; + } + + sp_image_set_curve(this); //creates a curve at the image's boundary for snapping +} + +// BLIP +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +void SPImage::apply_profile(Inkscape::Pixbuf *pixbuf) { + + // TODO: this will prevent using MIME data when exporting. + // Integrate color correction into loading. + pixbuf->ensurePixelFormat(Inkscape::Pixbuf::PF_GDK); + int imagewidth = pixbuf->width(); + int imageheight = pixbuf->height(); + int rowstride = pixbuf->rowstride();; + guchar* px = pixbuf->pixels(); + + if ( px ) { + DEBUG_MESSAGE( lcmsFive, "in 's sp_image_update. About to call colorprofile_get_handle()" ); + + guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN; + cmsHPROFILE prof = Inkscape::CMSSystem::getHandle( this->document, + &profIntent, + this->color_profile ); + if ( prof ) { + cmsProfileClassSignature profileClass = cmsGetDeviceClass( prof ); + if ( profileClass != cmsSigNamedColorClass ) { + int intent = INTENT_PERCEPTUAL; + + switch ( profIntent ) { + case Inkscape::RENDERING_INTENT_RELATIVE_COLORIMETRIC: + intent = INTENT_RELATIVE_COLORIMETRIC; + break; + case Inkscape::RENDERING_INTENT_SATURATION: + intent = INTENT_SATURATION; + break; + case Inkscape::RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: + intent = INTENT_ABSOLUTE_COLORIMETRIC; + break; + case Inkscape::RENDERING_INTENT_PERCEPTUAL: + case Inkscape::RENDERING_INTENT_UNKNOWN: + case Inkscape::RENDERING_INTENT_AUTO: + default: + intent = INTENT_PERCEPTUAL; + } + + cmsHPROFILE destProf = cmsCreate_sRGBProfile(); + cmsHTRANSFORM transf = cmsCreateTransform( prof, + TYPE_RGBA_8, + destProf, + TYPE_RGBA_8, + intent, 0 ); + if ( transf ) { + guchar* currLine = px; + for ( int y = 0; y < imageheight; y++ ) { + // Since the types are the same size, we can do the transformation in-place + cmsDoTransform( transf, currLine, currLine, imagewidth ); + currLine += rowstride; + } + + cmsDeleteTransform( transf ); + } else { + DEBUG_MESSAGE( lcmsSix, "in 's sp_image_update. Unable to create LCMS transform." ); + } + + cmsCloseProfile( destProf ); + } else { + DEBUG_MESSAGE( lcmsSeven, "in 's sp_image_update. Profile type is named color. Can't transform." ); + } + } else { + DEBUG_MESSAGE( lcmsEight, "in 's sp_image_update. No profile found." ); + } + } +} +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +void SPImage::update(SPCtx *ctx, unsigned int flags) { + + SPDocument *doc = this->document; + + SPItem::update(ctx, flags); + if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) { + delete this->pixbuf; + this->pixbuf = nullptr; + if (this->href) { + Inkscape::Pixbuf *pixbuf = nullptr; + const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + if (!svgdpi) { + svgdpi = "96"; + } + this->dpi = atof(svgdpi); + pixbuf = sp_image_repr_read_image ( + this->getRepr()->attribute("xlink:href"), + this->getRepr()->attribute("sodipodi:absref"), + doc->getBase(), + svgdpi); + + if (pixbuf) { +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + if ( this->color_profile ) apply_profile( pixbuf ); +#endif + this->pixbuf = pixbuf; + } + } + } + + SPItemCtx *ictx = (SPItemCtx *) ctx; + + // Why continue without a pixbuf? So we can display "Missing Image" png. + // Eventually, we should properly support SVG image type (i.e. render it ourselves). + if (this->pixbuf) { + if (!this->x._set) { + this->x.unit = SVGLength::PX; + this->x.computed = 0; + } + + if (!this->y._set) { + this->y.unit = SVGLength::PX; + this->y.computed = 0; + } + + if (!this->width._set) { + this->width.unit = SVGLength::PX; + this->width.computed = this->pixbuf->width(); + } + + if (!this->height._set) { + this->height.unit = SVGLength::PX; + this->height.computed = this->pixbuf->height(); + } + } + + // Calculate x, y, width, height from parent/initial viewport, see sp-root.cpp + this->calcDimsFromParentViewport(ictx); + + // Image creates a new viewport + ictx->viewport= Geom::Rect::from_xywh( this->x.computed, this->y.computed, + this->width.computed, this->height.computed); + + this->clipbox = ictx->viewport; + + this->ox = this->x.computed; + this->oy = this->y.computed; + + if (this->pixbuf) { + + // Viewbox is either from SVG (not supported) or dimensions of pixbuf (PNG, JPG) + this->viewBox = Geom::Rect::from_xywh(0, 0, this->pixbuf->width(), this->pixbuf->height()); + this->viewBox_set = true; + + // SPItemCtx rctx = + get_rctx( ictx ); + + this->ox = c2p[4]; + this->oy = c2p[5]; + this->sx = c2p[0]; + this->sy = c2p[3]; + + } + + + + // TODO: eliminate ox, oy, sx, sy + + sp_image_update_canvas_image ((SPImage *) this); + double proportion_pixbuf = this->pixbuf->height()/(double)this->pixbuf->width(); + double proportion_image = this->height.computed/(double)this->width.computed; + if (this->prev_width && (this->prev_width != this->pixbuf->width() || this->prev_height != this->pixbuf->height())) { + if (std::abs(this->prev_width - this->pixbuf->width()) > std::abs(this->prev_height - this->pixbuf->height())) { + proportion_pixbuf = this->pixbuf->width()/(double)this->pixbuf->height(); + proportion_image = this->width.computed/(double)this->height.computed; + if(proportion_pixbuf != proportion_image) { + double new_height = this->height.computed * proportion_pixbuf; + sp_repr_set_svg_double(this->getRepr(), "width", new_height); + + } + } else { + if(proportion_pixbuf != proportion_image) { + double new_width = this->width.computed * proportion_pixbuf; + sp_repr_set_svg_double(this->getRepr(), "height", new_width); + } + } + } + this->prev_width = this->pixbuf->width(); + this->prev_height = this->pixbuf->height(); +} + +void SPImage::modified(unsigned int flags) { +// SPItem::onModified(flags); + + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + for (SPItemView *v = this->display; v != nullptr; v = v->next) { + Inkscape::DrawingImage *img = dynamic_cast(v->arenaitem); + img->setStyle(this->style); + } + } +} + + +Inkscape::XML::Node *SPImage::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags ) { + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("svg:image"); + } + + repr->setAttribute("xlink:href", this->href); + + /* fixme: Reset attribute if needed (Lauris) */ + if (this->x._set) { + sp_repr_set_svg_double(repr, "x", this->x.computed); + } + + if (this->y._set) { + sp_repr_set_svg_double(repr, "y", this->y.computed); + } + + if (this->width._set) { + sp_repr_set_svg_double(repr, "width", this->width.computed); + } + + if (this->height._set) { + sp_repr_set_svg_double(repr, "height", this->height.computed); + } + repr->setAttribute("inkscape:svg-dpi", this->getRepr()->attribute("inkscape:svg-dpi")); + //XML Tree being used directly here while it shouldn't be... + repr->setAttribute("preserveAspectRatio", this->getRepr()->attribute("preserveAspectRatio")); +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + if (this->color_profile) { + repr->setAttribute("color-profile", this->color_profile); + } +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + SPItem::write(xml_doc, repr, flags); + + return repr; +} + +Geom::OptRect SPImage::bbox(Geom::Affine const &transform, SPItem::BBoxType /*type*/) const { + Geom::OptRect bbox; + + if ((this->width.computed > 0.0) && (this->height.computed > 0.0)) { + bbox = Geom::Rect::from_xywh(this->x.computed, this->y.computed, this->width.computed, this->height.computed); + *bbox *= transform; + } + + return bbox; +} + +void SPImage::print(SPPrintContext *ctx) { + if (this->pixbuf && (this->width.computed > 0.0) && (this->height.computed > 0.0) ) { + Inkscape::Pixbuf *pb = new Inkscape::Pixbuf(*this->pixbuf); + pb->ensurePixelFormat(Inkscape::Pixbuf::PF_GDK); + + guchar *px = pb->pixels(); + int w = pb->width(); + int h = pb->height(); + int rs = pb->rowstride(); + + double vx = this->ox; + double vy = this->oy; + + Geom::Affine t; + Geom::Translate tp(vx, vy); + Geom::Scale s(this->sx, this->sy); + t = s * tp; + ctx->image_R8G8B8A8_N(px, w, h, rs, t, this->style); + delete pb; + } +} + +const char* SPImage::displayName() const { + return _("Image"); +} + +gchar* SPImage::description() const { + char *href_desc; + + if (this->href) { + href_desc = (strncmp(this->href, "data:", 5) == 0) + ? g_strdup(_("embedded")) + : xml_quote_strdup(this->href); + } else { + g_warning("Attempting to call strncmp() with a null pointer."); + href_desc = g_strdup("(null_pointer)"); // we call g_free() on href_desc + } + + char *ret = ( this->pixbuf == nullptr + ? g_strdup_printf(_("[bad reference]: %s"), href_desc) + : g_strdup_printf(_("%d × %d: %s"), + this->pixbuf->width(), + this->pixbuf->height(), + href_desc) ); + + if (this->pixbuf == nullptr && + this->document) + { + Inkscape::Pixbuf * pb = nullptr; + const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); + if (!svgdpi) { + svgdpi = "96"; + } + pb = sp_image_repr_read_image ( + this->getRepr()->attribute("xlink:href"), + this->getRepr()->attribute("sodipodi:absref"), + this->document->getBase(), + svgdpi); + + if (pb) { + ret = g_strdup_printf(_("%d × %d: %s"), + pb->width(), + pb->height(), + href_desc); + delete pb; + } + } + + g_free(href_desc); + return ret; +} + +Inkscape::DrawingItem* SPImage::show(Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) { + Inkscape::DrawingImage *ai = new Inkscape::DrawingImage(drawing); + + sp_image_update_arenaitem(this, ai); + + return ai; +} + +Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base, char const *svgdpi) +{ + Inkscape::Pixbuf *inkpb = nullptr; + + gchar const *filename = href; + + if (filename != nullptr) { + if (strncmp (filename,"file:",5) == 0) { + gchar *fullname = g_filename_from_uri(filename, nullptr, nullptr); + if (fullname) { + inkpb = Inkscape::Pixbuf::create_from_file(fullname, svgdpi); + g_free(fullname); + if (inkpb != nullptr) { + return inkpb; + } + } + } else if (strncmp (filename,"data:",5) == 0) { + /* data URI - embedded image */ + filename += 5; + inkpb = Inkscape::Pixbuf::create_from_data_uri(filename, svgdpi); + if (inkpb != nullptr) { + return inkpb; + } + } else { + + if (!g_path_is_absolute (filename)) { + /* try to load from relative pos combined with document base*/ + const gchar *docbase = base; + if (!docbase) { + docbase = "."; + } + gchar *fullname = g_build_filename(docbase, filename, NULL); + + // document base can be wrong (on the temporary doc when importing bitmap from a + // different dir) or unset (when doc is not saved yet), so we check for base+href existence first, + // and if it fails, we also try to use bare href regardless of its g_path_is_absolute + if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { + inkpb = Inkscape::Pixbuf::create_from_file(fullname); + if (inkpb != nullptr) { + g_free (fullname); + return inkpb; + } + } + g_free (fullname); + } + + /* try filename as absolute */ + if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) { + inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); + if (inkpb != nullptr) { + return inkpb; + } + } + } + } + + /* at last try to load from sp absolute path name */ + filename = absref; + if (filename != nullptr) { + // using absref is outside of SVG rules, so we must at least warn the user + if ( base != nullptr && href != nullptr ) { + g_warning (" did not resolve to a valid image file (base dir is %s), now trying sodipodi:absref=\"%s\"", href, base, absref); + } else { + g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref); + } + + inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); + if (inkpb != nullptr) { + return inkpb; + } + } + /* Nope: We do not find any valid pixmap file :-( */ + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **) brokenimage_xpm); + inkpb = new Inkscape::Pixbuf(pixbuf); + + /* It should be included xpm, so if it still does not does load, */ + /* our libraries are broken */ + g_assert (inkpb != nullptr); + + return inkpb; +} + +/* We assert that realpixbuf is either NULL or identical size to pixbuf */ +static void +sp_image_update_arenaitem (SPImage *image, Inkscape::DrawingImage *ai) +{ + ai->setStyle(SP_OBJECT(image)->style); + ai->setPixbuf(image->pixbuf); + ai->setOrigin(Geom::Point(image->ox, image->oy)); + ai->setScale(image->sx, image->sy); + ai->setClipbox(image->clipbox); +} + +static void sp_image_update_canvas_image(SPImage *image) +{ + SPItem *item = SP_ITEM(image); + for (SPItemView *v = item->display; v != nullptr; v = v->next) { + sp_image_update_arenaitem(image, dynamic_cast(v->arenaitem)); + } +} + +void SPImage::snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const { + /* An image doesn't have any nodes to snap, but still we want to be able snap one image + to another. Therefore we will create some snappoints at the corner, similar to a rect. If + the image is rotated, then the snappoints will rotate with it. Again, just like a rect. + */ + + if (this->clip_ref->getObject()) { + //We are looking at a clipped image: do not return any snappoints, as these might be + //far far away from the visible part from the clipped image + //TODO Do return snappoints, but only when within visual bounding box + } else { + if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_IMG_CORNER)) { + // The image has not been clipped: return its corners, which might be rotated for example + double const x0 = this->x.computed; + double const y0 = this->y.computed; + double const x1 = x0 + this->width.computed; + double const y1 = y0 + this->height.computed; + + Geom::Affine const i2d (this->i2dt_affine ()); + + p.emplace_back(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); + p.emplace_back(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); + p.emplace_back(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); + p.emplace_back(Geom::Point(x1, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); + } + } +} + +/* + * Initially we'll do: + * Transform x, y, set x, y, clear translation + */ + +Geom::Affine SPImage::set_transform(Geom::Affine const &xform) { + /* Calculate position in parent coords. */ + Geom::Point pos( Geom::Point(this->x.computed, this->y.computed) * xform ); + + /* This function takes care of translation and scaling, we return whatever parts we can't + handle. */ + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); + Geom::Point const scale(hypot(ret[0], ret[1]), + hypot(ret[2], ret[3])); + + if ( scale[Geom::X] > MAGIC_EPSILON ) { + ret[0] /= scale[Geom::X]; + ret[1] /= scale[Geom::X]; + } else { + ret[0] = 1.0; + ret[1] = 0.0; + } + + if ( scale[Geom::Y] > MAGIC_EPSILON ) { + ret[2] /= scale[Geom::Y]; + ret[3] /= scale[Geom::Y]; + } else { + ret[2] = 0.0; + ret[3] = 1.0; + } + + this->width = this->width.computed * scale[Geom::X]; + this->height = this->height.computed * scale[Geom::Y]; + + /* Find position in item coords */ + pos = pos * ret.inverse(); + this->x = pos[Geom::X]; + this->y = pos[Geom::Y]; + + return ret; +} + +static void sp_image_set_curve( SPImage *image ) +{ + //create a curve at the image's boundary for snapping + if ((image->height.computed < MAGIC_EPSILON_TOO) || (image->width.computed < MAGIC_EPSILON_TOO) || (image->clip_ref->getObject())) { + if (image->curve) { + image->curve = image->curve->unref(); + } + } else { + Geom::OptRect rect = image->bbox(Geom::identity(), SPItem::VISUAL_BBOX); + SPCurve *c = SPCurve::new_from_rect(*rect, true); + + if (image->curve) { + image->curve = image->curve->unref(); + } + + if (c) { + image->curve = c->ref(); + + c->unref(); + } + } +} + +/** + * Return duplicate of curve (if any exists) or NULL if there is no curve + */ +SPCurve *SPImage::get_curve() const +{ + SPCurve *result = nullptr; + if (curve) { + result = curve->copy(); + } + return result; +} + +void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb) +{ + bool free_data = false; + + // check whether the pixbuf has MIME data + guchar *data = nullptr; + gsize len = 0; + std::string data_mimetype; + + data = const_cast(pb->getMimeData(len, data_mimetype)); + + if (data == nullptr) { + // if there is no supported MIME data, embed as PNG + data_mimetype = "image/png"; + gdk_pixbuf_save_to_buffer(pb->getPixbufRaw(), reinterpret_cast(&data), &len, "png", nullptr, NULL); + free_data = true; + } + + // 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(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); + 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 = nullptr; + gsize len = 0; + GError *error = nullptr; + + if (g_file_get_contents(fn.c_str(), &data, &len, &error)) { + + if (error != nullptr) { + 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(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 SPImage::refresh_if_outdated() +{ + if ( href && pixbuf && pixbuf->modificationTime()) { + // It *might* change + + GStatBuf st; + memset(&st, 0, sizeof(st)); + int val = 0; + if (g_file_test (pixbuf->originalPath().c_str(), G_FILE_TEST_EXISTS)){ + val = g_stat(pixbuf->originalPath().c_str(), &st); + } + if ( !val ) { + // stat call worked. Check time now + if ( st.st_mtime != pixbuf->modificationTime() ) { + requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); + } + } + } +} + +/* + 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 : diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index 021246f21d..88d7daf074 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -48,7 +48,7 @@ namespace Dialog { ObjectProperties::ObjectProperties() : UI::Widget::Panel("/dialogs/object/", SP_VERB_DIALOG_ITEM) - , _blocked (false) + , _blocked(false) , _current_item(nullptr) , _label_id(_("_ID:"), true) , _label_label(_("_Label:"), true) @@ -206,7 +206,7 @@ void ObjectProperties::_init() /* Create the entry box for the SVG DPI */ _spin_dpi.set_digits(2); - _spin_dpi.set_range (1,1200); + _spin_dpi.set_range(1, 1200); grid_top->attach(_spin_dpi, 1, 3, 1, 1); _label_dpi.set_mnemonic_widget(_spin_dpi); @@ -238,7 +238,6 @@ void ObjectProperties::_init() - /* Check boxes */ Gtk::HBox *hb_checkboxes = Gtk::manage(new Gtk::HBox()); contents->pack_start(*hb_checkboxes, FALSE, FALSE, 0); @@ -268,7 +267,7 @@ void ObjectProperties::_init() _cb_lock.signal_toggled().connect(sigc::mem_fun(this, &ObjectProperties::_sensitivityToggled)); /* Preserve aspect ratio */ - _cb_aspect_ratio.set_tooltip_text (_("Check to preserve aspect ratio on images")); + _cb_aspect_ratio.set_tooltip_text(_("Check to preserve aspect ratio on images")); _cb_aspect_ratio.set_hexpand(); _cb_aspect_ratio.set_valign(Gtk::ALIGN_CENTER); grid_cb->attach(_cb_aspect_ratio, 0, 1, 1, 1); @@ -324,7 +323,7 @@ void ObjectProperties::update() return; } _blocked = true; - _cb_aspect_ratio.set_active(item->getAttribute("preserveAspectRatio") == "true"); + _cb_aspect_ratio.set_active(item->getAttribute("preserveAspectRatio") == "true"); _cb_lock.set_active(item->isLocked()); /* Sensitive */ _cb_hide.set_active(item->isExplicitlyHidden()); /* Hidden */ @@ -453,8 +452,7 @@ void ObjectProperties::_labelChanged() if (SP_IS_IMAGE(obj)) { Glib::ustring dpi_value = Glib::ustring::format(_spin_dpi.get_value()); obj->setAttribute("inkscape:svg-dpi", dpi_value); - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, - _("Set image DPI")); + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, _("Set image DPI")); } /* Retrieve the description */ @@ -525,17 +523,17 @@ void ObjectProperties::_aspectRatioToggled() item->setLocked(_cb_aspect_ratio.get_active()); const char *active; - if(_cb_aspect_ratio.get_active()) { + if (_cb_aspect_ratio.get_active()) { active = "true"; - } else { + } + else { active = "none"; } - /* Retrieve the DPI */ + /* Retrieve the DPI */ if (SP_IS_IMAGE(item)) { Glib::ustring dpi_value = Glib::ustring::format(_spin_dpi.get_value()); item->setAttribute("preserveAspectRatio", active); - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, - _("Set preserve ratio")); + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, _("Set preserve ratio")); } _blocked = false; } -- GitLab From 6c2244af9f29fad8858d6fdea4a3aa455c54a462 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 13:44:48 +0200 Subject: [PATCH 4/8] remove vs code --- .vscode/settings.json | 62 ------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 6ce99071c2..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "files.associations": { - "*.ipp": "cpp", - "ratio": "cpp", - "system_error": "cpp", - "istream": "cpp", - "optional": "cpp", - "ostream": "cpp", - "type_traits": "cpp", - "atomic": "cpp", - "chrono": "cpp", - "*.tcc": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "csetjmp": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "strstream": "cpp", - "cinttypes": "cpp", - "condition_variable": "cpp", - "cstdint": "cpp", - "slist": "cpp", - "initializer_list": "cpp", - "iosfwd": "cpp", - "mutex": "cpp", - "thread": "cpp", - "typeindex": "cpp", - "array": "cpp", - "bitset": "cpp", - "complex": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "vector": "cpp", - "exception": "cpp", - "fstream": "cpp", - "functional": "cpp", - "iomanip": "cpp", - "iostream": "cpp", - "limits": "cpp", - "memory": "cpp", - "new": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "string_view": "cpp", - "tuple": "cpp", - "typeinfo": "cpp", - "utility": "cpp", - "valarray": "cpp", - "algorithm": "cpp" - } -} \ No newline at end of file -- GitLab From 74ad76f77ff39e1258ed00d2e50579bf21208676 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 13:46:37 +0200 Subject: [PATCH 5/8] remove unwanted file --- src/object/sp-image.cpp.orig | 913 ----------------------------------- 1 file changed, 913 deletions(-) delete mode 100644 src/object/sp-image.cpp.orig diff --git a/src/object/sp-image.cpp.orig b/src/object/sp-image.cpp.orig deleted file mode 100644 index 5408ec81d7..0000000000 --- a/src/object/sp-image.cpp.orig +++ /dev/null @@ -1,913 +0,0 @@ -/* - * SVG implementation - * - * Authors: - * Lauris Kaplinski - * Edward Flick (EAF) - * Abhishek Sharma - * Jon A. Cruz - * - * Copyright (C) 1999-2005 Authors - * Copyright (C) 2000-2001 Ximian, Inc. - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include -#include <2geom/rect.h> -#include <2geom/transforms.h> -#include - -#include "display/drawing-image.h" -#include "display/cairo-utils.h" -#include "display/curve.h" -//Added for preserveAspectRatio support -- EAF -#include "attributes.h" -#include "print.h" -#include "brokenimage.xpm" -#include "document.h" -#include "sp-image.h" -#include "sp-clippath.h" -#include "xml/quote.h" -#include "preferences.h" -#include "io/sys.h" - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -#include "cms-system.h" -#include "color-profile.h" - -#if HAVE_LIBLCMS2 -# include -#elif HAVE_LIBLCMS1 -# include -#endif // HAVE_LIBLCMS2 - -//#define DEBUG_LCMS -#ifdef DEBUG_LCMS -#define DEBUG_MESSAGE(key, ...)\ -{\ - g_message( __VA_ARGS__ );\ -} -#include -#else -#define DEBUG_MESSAGE(key, ...) -#endif // DEBUG_LCMS -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -/* - * SPImage - */ - -// TODO: give these constants better names: -#define MAGIC_EPSILON 1e-9 -#define MAGIC_EPSILON_TOO 1e-18 -// TODO: also check if it is correct to be using two different epsilon values - -static void sp_image_set_curve(SPImage *image); - -static Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base , char const *svgdpi); -static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai); -static void sp_image_update_canvas_image (SPImage *image); - -#ifdef DEBUG_LCMS -extern guint update_in_progress; -#define DEBUG_MESSAGE_SCISLAC(key, ...) \ -{\ - Inkscape::Preferences *prefs = Inkscape::Preferences::get();\ - bool dump = prefs->getBool("/options/scislac/" #key);\ - bool dumpD = prefs->getBool("/options/scislac/" #key "D");\ - bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2");\ - dumpD &&= ( (update_in_progress == 0) || dumpD2 );\ - if ( dump )\ - {\ - g_message( __VA_ARGS__ );\ -\ - }\ - if ( dumpD )\ - {\ - GtkWidget *dialog = gtk_message_dialog_new(NULL,\ - GTK_DIALOG_DESTROY_WITH_PARENT, \ - GTK_MESSAGE_INFO, \ - GTK_BUTTONS_OK, \ - __VA_ARGS__ \ - );\ - g_signal_connect_swapped(dialog, "response",\ - G_CALLBACK(gtk_widget_destroy), \ - dialog); \ - gtk_widget_show_all( dialog );\ - }\ -} -#else // DEBUG_LCMS -#define DEBUG_MESSAGE_SCISLAC(key, ...) -#endif // DEBUG_LCMS - -SPImage::SPImage() : SPItem(), SPViewBox() { - - this->x.unset(); - this->y.unset(); - this->width.unset(); - this->height.unset(); - this->clipbox = Geom::Rect(); - this->sx = this->sy = 1.0; - this->ox = this->oy = 0.0; - this->dpi = 96.00; - this->prev_width = 0.0; - this->prev_height = 0.0; - this->curve = nullptr; - - this->href = nullptr; -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - this->color_profile = nullptr; -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - this->pixbuf = nullptr; -} - -SPImage::~SPImage() = default; - -void SPImage::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPItem::build(document, repr); - - this->readAttr( "xlink:href" ); - this->readAttr( "x" ); - this->readAttr( "y" ); - this->readAttr( "width" ); - this->readAttr( "height" ); - this->readAttr( "inkscape:svg-dpi" ); - this->readAttr( "preserveAspectRatio" ); - this->readAttr( "color-profile" ); - - /* Register */ - document->addResource("image", this); -} - -void SPImage::release() { - if (this->document) { - // Unregister ourselves - this->document->removeResource("image", this); - } - - if (this->href) { - g_free (this->href); - this->href = nullptr; - } - - delete this->pixbuf; - this->pixbuf = nullptr; - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - if (this->color_profile) { - g_free (this->color_profile); - this->color_profile = nullptr; - } -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - if (this->curve) { - this->curve = this->curve->unref(); - } - - SPItem::release(); -} - -void SPImage::set(unsigned int key, const gchar* value) { - switch (key) { - case SP_ATTR_XLINK_HREF: - g_free (this->href); - this->href = (value) ? g_strdup (value) : nullptr; - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); - break; - - case SP_ATTR_X: - /* ex, em not handled correctly. */ - if (!this->x.read(value)) { - this->x.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_Y: - /* ex, em not handled correctly. */ - if (!this->y.read(value)) { - this->y.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_WIDTH: - /* ex, em not handled correctly. */ - if (!this->width.read(value)) { - this->width.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_HEIGHT: - /* ex, em not handled correctly. */ - if (!this->height.read(value)) { - this->height.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_SVG_DPI: - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); - break; - - case SP_ATTR_PRESERVEASPECTRATIO: - set_preserveAspectRatio( value ); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); - break; - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - case SP_PROP_COLOR_PROFILE: - if ( this->color_profile ) { - g_free (this->color_profile); - } - - this->color_profile = (value) ? g_strdup (value) : nullptr; - - if ( value ) { - DEBUG_MESSAGE( lcmsFour, " color-profile set to '%s'", value ); - } else { - DEBUG_MESSAGE( lcmsFour, " color-profile cleared" ); - } - - // TODO check on this HREF_MODIFIED flag - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); - break; - -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - default: - SPItem::set(key, value); - break; - } - - sp_image_set_curve(this); //creates a curve at the image's boundary for snapping -} - -// BLIP -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -void SPImage::apply_profile(Inkscape::Pixbuf *pixbuf) { - - // TODO: this will prevent using MIME data when exporting. - // Integrate color correction into loading. - pixbuf->ensurePixelFormat(Inkscape::Pixbuf::PF_GDK); - int imagewidth = pixbuf->width(); - int imageheight = pixbuf->height(); - int rowstride = pixbuf->rowstride();; - guchar* px = pixbuf->pixels(); - - if ( px ) { - DEBUG_MESSAGE( lcmsFive, "in 's sp_image_update. About to call colorprofile_get_handle()" ); - - guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN; - cmsHPROFILE prof = Inkscape::CMSSystem::getHandle( this->document, - &profIntent, - this->color_profile ); - if ( prof ) { - cmsProfileClassSignature profileClass = cmsGetDeviceClass( prof ); - if ( profileClass != cmsSigNamedColorClass ) { - int intent = INTENT_PERCEPTUAL; - - switch ( profIntent ) { - case Inkscape::RENDERING_INTENT_RELATIVE_COLORIMETRIC: - intent = INTENT_RELATIVE_COLORIMETRIC; - break; - case Inkscape::RENDERING_INTENT_SATURATION: - intent = INTENT_SATURATION; - break; - case Inkscape::RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: - intent = INTENT_ABSOLUTE_COLORIMETRIC; - break; - case Inkscape::RENDERING_INTENT_PERCEPTUAL: - case Inkscape::RENDERING_INTENT_UNKNOWN: - case Inkscape::RENDERING_INTENT_AUTO: - default: - intent = INTENT_PERCEPTUAL; - } - - cmsHPROFILE destProf = cmsCreate_sRGBProfile(); - cmsHTRANSFORM transf = cmsCreateTransform( prof, - TYPE_RGBA_8, - destProf, - TYPE_RGBA_8, - intent, 0 ); - if ( transf ) { - guchar* currLine = px; - for ( int y = 0; y < imageheight; y++ ) { - // Since the types are the same size, we can do the transformation in-place - cmsDoTransform( transf, currLine, currLine, imagewidth ); - currLine += rowstride; - } - - cmsDeleteTransform( transf ); - } else { - DEBUG_MESSAGE( lcmsSix, "in 's sp_image_update. Unable to create LCMS transform." ); - } - - cmsCloseProfile( destProf ); - } else { - DEBUG_MESSAGE( lcmsSeven, "in 's sp_image_update. Profile type is named color. Can't transform." ); - } - } else { - DEBUG_MESSAGE( lcmsEight, "in 's sp_image_update. No profile found." ); - } - } -} -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -void SPImage::update(SPCtx *ctx, unsigned int flags) { - - SPDocument *doc = this->document; - - SPItem::update(ctx, flags); - if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) { - delete this->pixbuf; - this->pixbuf = nullptr; - if (this->href) { - Inkscape::Pixbuf *pixbuf = nullptr; - const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); - if (!svgdpi) { - svgdpi = "96"; - } - this->dpi = atof(svgdpi); - pixbuf = sp_image_repr_read_image ( - this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), - doc->getBase(), - svgdpi); - - if (pixbuf) { -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - if ( this->color_profile ) apply_profile( pixbuf ); -#endif - this->pixbuf = pixbuf; - } - } - } - - SPItemCtx *ictx = (SPItemCtx *) ctx; - - // Why continue without a pixbuf? So we can display "Missing Image" png. - // Eventually, we should properly support SVG image type (i.e. render it ourselves). - if (this->pixbuf) { - if (!this->x._set) { - this->x.unit = SVGLength::PX; - this->x.computed = 0; - } - - if (!this->y._set) { - this->y.unit = SVGLength::PX; - this->y.computed = 0; - } - - if (!this->width._set) { - this->width.unit = SVGLength::PX; - this->width.computed = this->pixbuf->width(); - } - - if (!this->height._set) { - this->height.unit = SVGLength::PX; - this->height.computed = this->pixbuf->height(); - } - } - - // Calculate x, y, width, height from parent/initial viewport, see sp-root.cpp - this->calcDimsFromParentViewport(ictx); - - // Image creates a new viewport - ictx->viewport= Geom::Rect::from_xywh( this->x.computed, this->y.computed, - this->width.computed, this->height.computed); - - this->clipbox = ictx->viewport; - - this->ox = this->x.computed; - this->oy = this->y.computed; - - if (this->pixbuf) { - - // Viewbox is either from SVG (not supported) or dimensions of pixbuf (PNG, JPG) - this->viewBox = Geom::Rect::from_xywh(0, 0, this->pixbuf->width(), this->pixbuf->height()); - this->viewBox_set = true; - - // SPItemCtx rctx = - get_rctx( ictx ); - - this->ox = c2p[4]; - this->oy = c2p[5]; - this->sx = c2p[0]; - this->sy = c2p[3]; - - } - - - - // TODO: eliminate ox, oy, sx, sy - - sp_image_update_canvas_image ((SPImage *) this); - double proportion_pixbuf = this->pixbuf->height()/(double)this->pixbuf->width(); - double proportion_image = this->height.computed/(double)this->width.computed; - if (this->prev_width && (this->prev_width != this->pixbuf->width() || this->prev_height != this->pixbuf->height())) { - if (std::abs(this->prev_width - this->pixbuf->width()) > std::abs(this->prev_height - this->pixbuf->height())) { - proportion_pixbuf = this->pixbuf->width()/(double)this->pixbuf->height(); - proportion_image = this->width.computed/(double)this->height.computed; - if(proportion_pixbuf != proportion_image) { - double new_height = this->height.computed * proportion_pixbuf; - sp_repr_set_svg_double(this->getRepr(), "width", new_height); - - } - } else { - if(proportion_pixbuf != proportion_image) { - double new_width = this->width.computed * proportion_pixbuf; - sp_repr_set_svg_double(this->getRepr(), "height", new_width); - } - } - } - this->prev_width = this->pixbuf->width(); - this->prev_height = this->pixbuf->height(); -} - -void SPImage::modified(unsigned int flags) { -// SPItem::onModified(flags); - - if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = this->display; v != nullptr; v = v->next) { - Inkscape::DrawingImage *img = dynamic_cast(v->arenaitem); - img->setStyle(this->style); - } - } -} - - -Inkscape::XML::Node *SPImage::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags ) { - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:image"); - } - - repr->setAttribute("xlink:href", this->href); - - /* fixme: Reset attribute if needed (Lauris) */ - if (this->x._set) { - sp_repr_set_svg_double(repr, "x", this->x.computed); - } - - if (this->y._set) { - sp_repr_set_svg_double(repr, "y", this->y.computed); - } - - if (this->width._set) { - sp_repr_set_svg_double(repr, "width", this->width.computed); - } - - if (this->height._set) { - sp_repr_set_svg_double(repr, "height", this->height.computed); - } - repr->setAttribute("inkscape:svg-dpi", this->getRepr()->attribute("inkscape:svg-dpi")); - //XML Tree being used directly here while it shouldn't be... - repr->setAttribute("preserveAspectRatio", this->getRepr()->attribute("preserveAspectRatio")); -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - if (this->color_profile) { - repr->setAttribute("color-profile", this->color_profile); - } -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - SPItem::write(xml_doc, repr, flags); - - return repr; -} - -Geom::OptRect SPImage::bbox(Geom::Affine const &transform, SPItem::BBoxType /*type*/) const { - Geom::OptRect bbox; - - if ((this->width.computed > 0.0) && (this->height.computed > 0.0)) { - bbox = Geom::Rect::from_xywh(this->x.computed, this->y.computed, this->width.computed, this->height.computed); - *bbox *= transform; - } - - return bbox; -} - -void SPImage::print(SPPrintContext *ctx) { - if (this->pixbuf && (this->width.computed > 0.0) && (this->height.computed > 0.0) ) { - Inkscape::Pixbuf *pb = new Inkscape::Pixbuf(*this->pixbuf); - pb->ensurePixelFormat(Inkscape::Pixbuf::PF_GDK); - - guchar *px = pb->pixels(); - int w = pb->width(); - int h = pb->height(); - int rs = pb->rowstride(); - - double vx = this->ox; - double vy = this->oy; - - Geom::Affine t; - Geom::Translate tp(vx, vy); - Geom::Scale s(this->sx, this->sy); - t = s * tp; - ctx->image_R8G8B8A8_N(px, w, h, rs, t, this->style); - delete pb; - } -} - -const char* SPImage::displayName() const { - return _("Image"); -} - -gchar* SPImage::description() const { - char *href_desc; - - if (this->href) { - href_desc = (strncmp(this->href, "data:", 5) == 0) - ? g_strdup(_("embedded")) - : xml_quote_strdup(this->href); - } else { - g_warning("Attempting to call strncmp() with a null pointer."); - href_desc = g_strdup("(null_pointer)"); // we call g_free() on href_desc - } - - char *ret = ( this->pixbuf == nullptr - ? g_strdup_printf(_("[bad reference]: %s"), href_desc) - : g_strdup_printf(_("%d × %d: %s"), - this->pixbuf->width(), - this->pixbuf->height(), - href_desc) ); - - if (this->pixbuf == nullptr && - this->document) - { - Inkscape::Pixbuf * pb = nullptr; - const gchar * svgdpi = this->getRepr()->attribute("inkscape:svg-dpi"); - if (!svgdpi) { - svgdpi = "96"; - } - pb = sp_image_repr_read_image ( - this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), - this->document->getBase(), - svgdpi); - - if (pb) { - ret = g_strdup_printf(_("%d × %d: %s"), - pb->width(), - pb->height(), - href_desc); - delete pb; - } - } - - g_free(href_desc); - return ret; -} - -Inkscape::DrawingItem* SPImage::show(Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) { - Inkscape::DrawingImage *ai = new Inkscape::DrawingImage(drawing); - - sp_image_update_arenaitem(this, ai); - - return ai; -} - -Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absref, gchar const *base, char const *svgdpi) -{ - Inkscape::Pixbuf *inkpb = nullptr; - - gchar const *filename = href; - - if (filename != nullptr) { - if (strncmp (filename,"file:",5) == 0) { - gchar *fullname = g_filename_from_uri(filename, nullptr, nullptr); - if (fullname) { - inkpb = Inkscape::Pixbuf::create_from_file(fullname, svgdpi); - g_free(fullname); - if (inkpb != nullptr) { - return inkpb; - } - } - } else if (strncmp (filename,"data:",5) == 0) { - /* data URI - embedded image */ - filename += 5; - inkpb = Inkscape::Pixbuf::create_from_data_uri(filename, svgdpi); - if (inkpb != nullptr) { - return inkpb; - } - } else { - - if (!g_path_is_absolute (filename)) { - /* try to load from relative pos combined with document base*/ - const gchar *docbase = base; - if (!docbase) { - docbase = "."; - } - gchar *fullname = g_build_filename(docbase, filename, NULL); - - // document base can be wrong (on the temporary doc when importing bitmap from a - // different dir) or unset (when doc is not saved yet), so we check for base+href existence first, - // and if it fails, we also try to use bare href regardless of its g_path_is_absolute - if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { - inkpb = Inkscape::Pixbuf::create_from_file(fullname); - if (inkpb != nullptr) { - g_free (fullname); - return inkpb; - } - } - g_free (fullname); - } - - /* try filename as absolute */ - if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) { - inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); - if (inkpb != nullptr) { - return inkpb; - } - } - } - } - - /* at last try to load from sp absolute path name */ - filename = absref; - if (filename != nullptr) { - // using absref is outside of SVG rules, so we must at least warn the user - if ( base != nullptr && href != nullptr ) { - g_warning (" did not resolve to a valid image file (base dir is %s), now trying sodipodi:absref=\"%s\"", href, base, absref); - } else { - g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref); - } - - inkpb = Inkscape::Pixbuf::create_from_file(filename, svgdpi); - if (inkpb != nullptr) { - return inkpb; - } - } - /* Nope: We do not find any valid pixmap file :-( */ - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **) brokenimage_xpm); - inkpb = new Inkscape::Pixbuf(pixbuf); - - /* It should be included xpm, so if it still does not does load, */ - /* our libraries are broken */ - g_assert (inkpb != nullptr); - - return inkpb; -} - -/* We assert that realpixbuf is either NULL or identical size to pixbuf */ -static void -sp_image_update_arenaitem (SPImage *image, Inkscape::DrawingImage *ai) -{ - ai->setStyle(SP_OBJECT(image)->style); - ai->setPixbuf(image->pixbuf); - ai->setOrigin(Geom::Point(image->ox, image->oy)); - ai->setScale(image->sx, image->sy); - ai->setClipbox(image->clipbox); -} - -static void sp_image_update_canvas_image(SPImage *image) -{ - SPItem *item = SP_ITEM(image); - for (SPItemView *v = item->display; v != nullptr; v = v->next) { - sp_image_update_arenaitem(image, dynamic_cast(v->arenaitem)); - } -} - -void SPImage::snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const { - /* An image doesn't have any nodes to snap, but still we want to be able snap one image - to another. Therefore we will create some snappoints at the corner, similar to a rect. If - the image is rotated, then the snappoints will rotate with it. Again, just like a rect. - */ - - if (this->clip_ref->getObject()) { - //We are looking at a clipped image: do not return any snappoints, as these might be - //far far away from the visible part from the clipped image - //TODO Do return snappoints, but only when within visual bounding box - } else { - if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_IMG_CORNER)) { - // The image has not been clipped: return its corners, which might be rotated for example - double const x0 = this->x.computed; - double const y0 = this->y.computed; - double const x1 = x0 + this->width.computed; - double const y1 = y0 + this->height.computed; - - Geom::Affine const i2d (this->i2dt_affine ()); - - p.emplace_back(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); - p.emplace_back(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); - p.emplace_back(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); - p.emplace_back(Geom::Point(x1, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER); - } - } -} - -/* - * Initially we'll do: - * Transform x, y, set x, y, clear translation - */ - -Geom::Affine SPImage::set_transform(Geom::Affine const &xform) { - /* Calculate position in parent coords. */ - Geom::Point pos( Geom::Point(this->x.computed, this->y.computed) * xform ); - - /* This function takes care of translation and scaling, we return whatever parts we can't - handle. */ - Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); - Geom::Point const scale(hypot(ret[0], ret[1]), - hypot(ret[2], ret[3])); - - if ( scale[Geom::X] > MAGIC_EPSILON ) { - ret[0] /= scale[Geom::X]; - ret[1] /= scale[Geom::X]; - } else { - ret[0] = 1.0; - ret[1] = 0.0; - } - - if ( scale[Geom::Y] > MAGIC_EPSILON ) { - ret[2] /= scale[Geom::Y]; - ret[3] /= scale[Geom::Y]; - } else { - ret[2] = 0.0; - ret[3] = 1.0; - } - - this->width = this->width.computed * scale[Geom::X]; - this->height = this->height.computed * scale[Geom::Y]; - - /* Find position in item coords */ - pos = pos * ret.inverse(); - this->x = pos[Geom::X]; - this->y = pos[Geom::Y]; - - return ret; -} - -static void sp_image_set_curve( SPImage *image ) -{ - //create a curve at the image's boundary for snapping - if ((image->height.computed < MAGIC_EPSILON_TOO) || (image->width.computed < MAGIC_EPSILON_TOO) || (image->clip_ref->getObject())) { - if (image->curve) { - image->curve = image->curve->unref(); - } - } else { - Geom::OptRect rect = image->bbox(Geom::identity(), SPItem::VISUAL_BBOX); - SPCurve *c = SPCurve::new_from_rect(*rect, true); - - if (image->curve) { - image->curve = image->curve->unref(); - } - - if (c) { - image->curve = c->ref(); - - c->unref(); - } - } -} - -/** - * Return duplicate of curve (if any exists) or NULL if there is no curve - */ -SPCurve *SPImage::get_curve() const -{ - SPCurve *result = nullptr; - if (curve) { - result = curve->copy(); - } - return result; -} - -void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb) -{ - bool free_data = false; - - // check whether the pixbuf has MIME data - guchar *data = nullptr; - gsize len = 0; - std::string data_mimetype; - - data = const_cast(pb->getMimeData(len, data_mimetype)); - - if (data == nullptr) { - // if there is no supported MIME data, embed as PNG - data_mimetype = "image/png"; - gdk_pixbuf_save_to_buffer(pb->getPixbufRaw(), reinterpret_cast(&data), &len, "png", nullptr, NULL); - free_data = true; - } - - // 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(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); - 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 = nullptr; - gsize len = 0; - GError *error = nullptr; - - if (g_file_get_contents(fn.c_str(), &data, &len, &error)) { - - if (error != nullptr) { - 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(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 SPImage::refresh_if_outdated() -{ - if ( href && pixbuf && pixbuf->modificationTime()) { - // It *might* change - - GStatBuf st; - memset(&st, 0, sizeof(st)); - int val = 0; - if (g_file_test (pixbuf->originalPath().c_str(), G_FILE_TEST_EXISTS)){ - val = g_stat(pixbuf->originalPath().c_str(), &st); - } - if ( !val ) { - // stat call worked. Check time now - if ( st.st_mtime != pixbuf->modificationTime() ) { - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); - } - } - } -} - -/* - 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 : -- GitLab From 5e617205ca7c76c9a61e400d32044103a8005ea2 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 14:00:26 +0200 Subject: [PATCH 6/8] Fix a open recent bug hadle as impor previously --- src/ui/interface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 5f9a402f11..b19b102217 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -750,6 +750,8 @@ static void sp_recent_open(GtkRecentChooser *recent_menu, gpointer /*user_data*/) { // dealing with the bizarre filename convention in Inkscape for now + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString("/options/openmethod/value", "open"); gchar *uri = gtk_recent_chooser_get_current_uri(GTK_RECENT_CHOOSER(recent_menu)); gchar *local_fn = g_filename_from_uri(uri, nullptr, nullptr); gchar *utf8_fn = g_filename_to_utf8(local_fn, -1, nullptr, nullptr, nullptr); @@ -757,6 +759,7 @@ sp_recent_open(GtkRecentChooser *recent_menu, gpointer /*user_data*/) g_free(utf8_fn); g_free(local_fn); g_free(uri); + prefs->setString("/options/openmethod/value", "done"); } static void -- GitLab From 17429664d66c8ed6c1a75f24c0fb952e8d4799ff Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 14:42:07 +0200 Subject: [PATCH 7/8] Fiz DPI problem update --- src/display/cairo-utils.cpp | 1 - src/object/sp-image.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 02425163d7..7279ac0523 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -354,7 +354,6 @@ Pixbuf *Pixbuf::create_from_file(std::string const &fn, char const *svgdpi) if (val == 0 && stdir.st_mode & S_IFDIR){ return nullptr; } - // we need to load the entire file into memory, // since we'll store it as MIME data gchar *data = nullptr; diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp index e12c7105b8..9c2fe9ac3e 100644 --- a/src/object/sp-image.cpp +++ b/src/object/sp-image.cpp @@ -610,7 +610,7 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre // different dir) or unset (when doc is not saved yet), so we check for base+href existence first, // and if it fails, we also try to use bare href regardless of its g_path_is_absolute if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { - inkpb = Inkscape::Pixbuf::create_from_file(fullname); + inkpb = Inkscape::Pixbuf::create_from_file(fullname, svgdpi); if (inkpb != nullptr) { g_free (fullname); return inkpb; -- GitLab From 4a16ea860c336b5cf6ebb2306e5ce219d10eb46d Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 11 Sep 2018 14:45:20 +0200 Subject: [PATCH 8/8] Fix a bug emeding --- src/extension/internal/svg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index 0931d964a1..d39f5a9603 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -258,7 +258,7 @@ Svg::open (Inkscape::Extension::Input *mod, const gchar *uri) } // convert filename to uri if (embed) { - std::unique_ptr pb(Inkscape::Pixbuf::create_from_file(uri)); + std::unique_ptr pb(Inkscape::Pixbuf::create_from_file(uri, svgdpi.c_str())); if(pb) { sp_embed_svg(image_node, uri); } -- GitLab