diff --git a/src/attributes.cpp b/src/attributes.cpp index 2588cf8c909505a80c1d7640059611f070bf96be..324f75e5fec5565ecfd8b3ea043f2ceb14f09453 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -54,7 +54,7 @@ static SPStyleProp const props[] = { {SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, "inkscape:highlight-color"}, {SP_ATTR_INKSCAPE_SPRAY_ORIGIN, "inkscape:spray-origin"}, /* SPAnchor */ - {SP_ATTR_XLINK_HREF, "xlink:href"}, + {SP_ATTR_HREF, "href"}, {SP_ATTR_XLINK_TYPE, "xlink:type"}, {SP_ATTR_XLINK_ROLE, "xlink:role"}, {SP_ATTR_XLINK_ARCROLE, "xlink:arcrole"}, @@ -193,7 +193,6 @@ static SPStyleProp const props[] = { /* SPOffset */ {SP_ATTR_SODIPODI_ORIGINAL, "sodipodi:original"}, {SP_ATTR_INKSCAPE_ORIGINAL, "inkscape:original"}, - {SP_ATTR_INKSCAPE_HREF, "inkscape:href"}, {SP_ATTR_INKSCAPE_RADIUS, "inkscape:radius"}, /* SPLine */ {SP_ATTR_X1, "x1"}, diff --git a/src/attributes.h b/src/attributes.h index 198d76187e641adce40e6372d9bedc213b87d2e4..79edde52dcfa4108d1af2f9626fec20be8da5b1f 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -52,7 +52,7 @@ enum SPAttributeEnum : unsigned { SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, SP_ATTR_INKSCAPE_SPRAY_ORIGIN, /* SPAnchor */ - SP_ATTR_XLINK_HREF, + SP_ATTR_HREF, SP_ATTR_XLINK_TYPE, SP_ATTR_XLINK_ROLE, SP_ATTR_XLINK_ARCROLE, @@ -192,7 +192,6 @@ enum SPAttributeEnum : unsigned { /* SPOffset */ SP_ATTR_SODIPODI_ORIGINAL, SP_ATTR_INKSCAPE_ORIGINAL, - SP_ATTR_INKSCAPE_HREF, SP_ATTR_INKSCAPE_RADIUS, /* SPLine */ SP_ATTR_X1, diff --git a/src/extension/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp index 915d3b08f22c3edb9167aea77de70ea6a350711d..a287dd8397f61bfbd458fa22827dc8769b9c486d 100644 --- a/src/extension/internal/bitmap/imagemagick.cpp +++ b/src/extension/internal/bitmap/imagemagick.cpp @@ -80,7 +80,10 @@ ImageMagickDocCache::ImageMagickDocCache(Inkscape::UI::View::View * view) : if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image")) { _nodes[_imageCount] = node; - char const *xlink = node->attribute("xlink:href"); + char const *xlink = node->attribute("href"); + if(!xlink) { + xlink = node->attribute("xlink:href"); + } char const *id = node->attribute("id"); _originals[_imageCount] = xlink; _caches[_imageCount] = (char*)""; diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index bd520455d7e82a459f9e9372932f145ba4c3509f..b663fbe67551ee2d7dea1bedf4a04c0766d6fe58 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -1021,8 +1021,11 @@ void OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node) } if (nodeName == "image" || nodeName == "svg:image") { - Glib::ustring href = getAttribute(node, "xlink:href"); - if (href.size() > 0 && imageTable.count(href) == 0) { + Glib::ustring href = getAttribute(node, "href"); + if (href.empty()) { + href = getAttribute(node, "xlink:href"); + } + if (!href.empty() && imageTable.count(href) == 0) { try { auto uri = Inkscape::URI(href.c_str(), docBaseUri.c_str()); auto mimetype = uri.getMimeType(); @@ -1677,7 +1680,10 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts, Glib::ustring itemTransformString = formatTransform(itemTransform); - Glib::ustring href = getAttribute(node, "xlink:href"); + Glib::ustring href = getAttribute(node, "href"); + if (href.size() == 0) { + href = getAttribute(node, "xlink:href"); + } std::map::iterator iter = imageTable.find(href); if (iter == imageTable.end()) { diff --git a/src/file.cpp b/src/file.cpp index 07f2db33f8c7fa1311cd97af6d30bd92098b1b2a..714ca18f781707f4a5c7dc334aa56af5a50893fa 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -966,7 +966,12 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) // if we are pasting a clone to an already existing object, its // transform is wrong (see ui/clipboard.cpp) - if(obj_copy->attribute("transform-with-parent") && target_document->getObjectById(obj->attribute("xlink:href")+1) ){ + gchar const *href = obj->attribute("href"); + if(!href) { + href = obj->attribute("xlink:href"); + } + + if(obj_copy->attribute("transform-with-parent") && target_document->getObjectById(href+1) ){ obj_copy->setAttribute("transform",obj_copy->attribute("transform-with-parent")); } if(obj_copy->attribute("transform-with-parent")) diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index a7e111a668f12555517c0a419b0acb43b47f771b..e257a931cf5215c93285b293fbcac83592f964fd 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -1507,6 +1507,8 @@ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *lin } else { repr->removeAttribute("xlink:href"); } + // Always remove alternative href attribute + repr->removeAttribute("href"); } diff --git a/src/id-clash.cpp b/src/id-clash.cpp index a7ab3263ef5f6a098a3505732a5c47284ea40185..c62d3a9bc5e4c0ba059914e5faacd44c31763447 100644 --- a/src/id-clash.cpp +++ b/src/id-clash.cpp @@ -43,13 +43,14 @@ typedef std::pair id_changeitem_type; typedef std::list id_changelist_type; const char *href_like_attributes[] = { + "href", + "xlink:href", + "inkscape:href", "inkscape:connection-end", "inkscape:connection-start", - "inkscape:href", "inkscape:path-effect", "inkscape:perspectiveID", "inkscape:tiled-clone-of", - "xlink:href", }; #define NUM_HREF_LIKE_ATTRIBUTES (sizeof(href_like_attributes) / sizeof(*href_like_attributes)) diff --git a/src/io/resource-manager.cpp b/src/io/resource-manager.cpp index e0a3ac95ebe9f9c3cea4fc806af54f2de7c76a6c..d09d6f3e2ca62ed93fb2015951f03e7c0f93db2d 100644 --- a/src/io/resource-manager.cpp +++ b/src/io/resource-manager.cpp @@ -221,7 +221,10 @@ std::vector ResourceManagerImpl::findBrokenLinks( SPDocument *doc for (auto image : images) { Inkscape::XML::Node *ir = image->getRepr(); - gchar const *href = ir->attribute("xlink:href"); + gchar const *href = ir->attribute("href"); + if(!href) { + href = ir->attribute("xlink:href"); + } if ( href && ( uniques.find(href) == uniques.end() ) ) { std::string filename; if (extractFilepath(href, filename)) { @@ -356,7 +359,10 @@ bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) for (auto image : images) { Inkscape::XML::Node *ir = image->getRepr(); - gchar const *href = ir->attribute("xlink:href"); + gchar const *href = ir->attribute("href"); + if(!href) { + href = ir->attribute("xlink:href"); + } if ( href ) { // TODO debug g_message(" consider [%s]", href); @@ -364,6 +370,8 @@ bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) // TODO debug g_message(" Found a replacement"); ir->setAttributeOrRemoveIfEmpty( "xlink:href", mapping[href] ); + // Remove alternative href attribute + ir->removeAttribute("href"); if ( ir->attribute( "sodipodi:absref" ) ) { ir->removeAttribute("sodipodi:absref"); // Remove this attribute } diff --git a/src/object/color-profile.cpp b/src/object/color-profile.cpp index a4776861c3da7b359becc232888a7546c7360275..d828250faa4a0e18744fab6566cfdff28623ac67 100644 --- a/src/object/color-profile.cpp +++ b/src/object/color-profile.cpp @@ -303,7 +303,7 @@ void ColorProfile::build(SPDocument *document, Inkscape::XML::Node *repr) { SPObject::build(document, repr); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->readAttr( "id" ); this->readAttr( "local" ); this->readAttr( "name" ); @@ -321,7 +321,7 @@ void ColorProfile::build(SPDocument *document, Inkscape::XML::Node *repr) { */ void ColorProfile::set(SPAttributeEnum key, gchar const *value) { switch (key) { - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if ( this->href ) { g_free( this->href ); this->href = nullptr; @@ -433,6 +433,8 @@ Inkscape::XML::Node* ColorProfile::write(Inkscape::XML::Document *xml_doc, Inksc if ( (flags & SP_OBJECT_WRITE_ALL) || this->href ) { repr->setAttribute( "xlink:href", this->href ); + // Remove alternative href attribute + repr->removeAttribute("href"); } if ( (flags & SP_OBJECT_WRITE_ALL) || this->local ) { diff --git a/src/object/filters/image.cpp b/src/object/filters/image.cpp index ea88d81c8d72c71c2a7d86b92d7a3fed0a1aaa74..6c777bd8257dfc8e2e5f8403384ad8924e3a4c26 100644 --- a/src/object/filters/image.cpp +++ b/src/object/filters/image.cpp @@ -57,8 +57,8 @@ void SPFeImage::build(SPDocument *document, Inkscape::XML::Node *repr) /*LOAD ATTRIBUTES FROM REPR HERE*/ - this->readAttr( "preserveAspectRatio" ); - this->readAttr( "xlink:href" ); + this->readAttr("preserveAspectRatio"); + this->readAttr("href", "xlink:href"); } /** @@ -100,7 +100,7 @@ static void sp_feImage_href_modified(SPObject* /*old_elem*/, SPObject* new_elem, void SPFeImage::set(SPAttributeEnum key, gchar const *value) { switch(key) { /*DEAL WITH SETTING ATTRIBUTES HERE*/ - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (this->href) { g_free(this->href); } diff --git a/src/object/sp-anchor.cpp b/src/object/sp-anchor.cpp index 544e2d3e95b565d38fb2c40214c59a7a204297f9..c26b5f29c9f0ca65780ad33da57e6b6bbe350e24 100644 --- a/src/object/sp-anchor.cpp +++ b/src/object/sp-anchor.cpp @@ -35,13 +35,13 @@ SPAnchor::~SPAnchor() = default; void SPAnchor::build(SPDocument *document, Inkscape::XML::Node *repr) { SPGroup::build(document, repr); + this->readAttr("href", "xlink:href"); this->readAttr( "xlink:type" ); this->readAttr( "xlink:role" ); this->readAttr( "xlink:arcrole" ); this->readAttr( "xlink:title" ); this->readAttr( "xlink:show" ); this->readAttr( "xlink:actuate" ); - this->readAttr( "xlink:href" ); this->readAttr( "target" ); } @@ -68,7 +68,7 @@ void SPAnchor::release() { void SPAnchor::set(SPAttributeEnum key, const gchar* value) { switch (key) { - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: g_free(this->href); this->href = g_strdup(value); this->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -119,6 +119,8 @@ Inkscape::XML::Node* SPAnchor::write(Inkscape::XML::Document *xml_doc, Inkscape: } repr->setAttribute("xlink:href", this->href); + // Remove alternative href attribute + repr->removeAttribute("href"); if (this->type) repr->setAttribute("xlink:type", this->type); if (this->title) repr->setAttribute("xlink:title", this->title); diff --git a/src/object/sp-filter.cpp b/src/object/sp-filter.cpp index 4c434b9dafdc96d3a23868721ec53183cd90ee14..d5184deb8f308faffb298ea0a76f4c653188f6e9 100644 --- a/src/object/sp-filter.cpp +++ b/src/object/sp-filter.cpp @@ -71,7 +71,7 @@ void SPFilter::build(SPDocument *document, Inkscape::XML::Node *repr) { this->readAttr( "width" ); this->readAttr( "height" ); this->readAttr( "filterRes" ); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->_refcount = 0; SPObject::build(document, repr); @@ -165,7 +165,7 @@ void SPFilter::set(SPAttributeEnum key, gchar const *value) { this->filterRes.set(value); this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (value) { try { this->href->attach(Inkscape::URI(value)); @@ -317,6 +317,8 @@ Inkscape::XML::Node* SPFilter::write(Inkscape::XML::Document *doc, Inkscape::XML if (this->href->getURI()) { auto uri_string = this->href->getURI()->str(); repr->setAttributeOrRemoveIfEmpty("xlink:href", uri_string); + // Remove alternative href attribute + repr->removeAttribute("href"); } SPObject::write(doc, repr, flags); diff --git a/src/object/sp-gradient.cpp b/src/object/sp-gradient.cpp index 031aa22569dc6d117a1c1bd839fd642123736d2b..df7c04feaa899ab52579e406fd75c12353c0d895 100644 --- a/src/object/sp-gradient.cpp +++ b/src/object/sp-gradient.cpp @@ -293,7 +293,7 @@ void SPGradient::build(SPDocument *document, Inkscape::XML::Node *repr) this->readAttr( "gradientUnits" ); this->readAttr( "gradientTransform" ); this->readAttr( "spreadMethod" ); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->readAttr( "osb:paint" ); // Register ourselves @@ -387,7 +387,7 @@ void SPGradient::set(SPAttributeEnum key, gchar const *value) this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (value) { try { this->ref->attach(Inkscape::URI(value)); @@ -632,6 +632,8 @@ Inkscape::XML::Node *SPGradient::write(Inkscape::XML::Document *xml_doc, Inkscap if (this->ref->getURI()) { auto uri_string = this->ref->getURI()->str(); repr->setAttributeOrRemoveIfEmpty("xlink:href", uri_string); + // Make sure alternative attribute is not already set. + repr->removeAttribute("href"); } if ((flags & SP_OBJECT_WRITE_ALL) || this->units_set) { diff --git a/src/object/sp-hatch.cpp b/src/object/sp-hatch.cpp index ef9bae6ca016a5468715e13be1f96e719cf0e921..19177130f2ba275a40da9213b524d57341d5ded2 100644 --- a/src/object/sp-hatch.cpp +++ b/src/object/sp-hatch.cpp @@ -77,8 +77,8 @@ void SPHatch::build(SPDocument* doc, Inkscape::XML::Node* repr) readAttr("y"); readAttr("pitch"); readAttr("rotate"); - readAttr("xlink:href"); - readAttr( "style" ); + readAttr("href", "xlink:href"); + readAttr("style"); // Register ourselves doc->addResource("hatch", this); @@ -199,7 +199,7 @@ void SPHatch::set(SPAttributeEnum key, const gchar* value) requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (value && href == value) { // Href unchanged, do nothing. } else { @@ -515,6 +515,8 @@ SPHatch *SPHatch::clone_if_necessary(SPItem *item, const gchar *property) repr->setAttribute("inkscape:collect", "always"); Glib::ustring parent_ref = Glib::ustring::compose("#%1", getRepr()->attribute("id")); repr->setAttribute("xlink:href", parent_ref); + // Make sure alternative href attribute is removed + repr->removeAttribute("href"); defsrepr->addChild(repr, nullptr); const gchar *child_id = repr->attribute("id"); diff --git a/src/object/sp-image.cpp b/src/object/sp-image.cpp index cec0c1299eb4e6a0d3a146347946e77845526bb8..b9a308b42d32f99dde4f1bc3eba7d404f55b1ec4 100644 --- a/src/object/sp-image.cpp +++ b/src/object/sp-image.cpp @@ -131,7 +131,7 @@ SPImage::~SPImage() = default; void SPImage::build(SPDocument *document, Inkscape::XML::Node *repr) { SPItem::build(document, repr); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->readAttr( "x" ); this->readAttr( "y" ); this->readAttr( "width" ); @@ -174,7 +174,7 @@ void SPImage::release() { void SPImage::set(SPAttributeEnum key, const gchar* value) { switch (key) { - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: g_free (this->href); this->href = (value) ? g_strdup (value) : nullptr; this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG); @@ -339,8 +339,11 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { svgdpi = atof(this->getRepr()->attribute("inkscape:svg-dpi")); } this->dpi = svgdpi; - pixbuf = sp_image_repr_read_image(this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), doc->getDocumentBase(), svgdpi); + gchar const *href = this->getAttribute("href"); + if(!href) { + href = this->getAttribute("xlink:href"); + } + pixbuf = sp_image_repr_read_image(href, this->getAttribute("sodipodi:absref"), doc->getDocumentBase(), svgdpi); if (pixbuf) { #if defined(HAVE_LIBLCMS2) @@ -456,6 +459,8 @@ Inkscape::XML::Node *SPImage::write(Inkscape::XML::Document *xml_doc, Inkscape:: } repr->setAttribute("xlink:href", this->href); + // Remove alternative href attribute + repr->removeAttribute("href"); /* fixme: Reset attribute if needed (Lauris) */ if (this->x._set) { @@ -551,8 +556,11 @@ gchar* SPImage::description() const { if (this->getRepr()->attribute("inkscape:svg-dpi")) { svgdpi = atof(this->getRepr()->attribute("inkscape:svg-dpi")); } - pb = sp_image_repr_read_image(this->getRepr()->attribute("xlink:href"), - this->getRepr()->attribute("sodipodi:absref"), this->document->getDocumentBase(), svgdpi); + gchar const *href = this->getAttribute("href"); + if(!href) { + href = this->getAttribute("xlink:href"); + } + pb = sp_image_repr_read_image(href, this->getAttribute("sodipodi:absref"), this->document->getDocumentBase(), svgdpi); if (pb) { ret = g_strdup_printf(_("%d × %d: %s"), @@ -814,6 +822,8 @@ void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb) // 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); + // Remove alternative href attribute + image_node->removeAttribute("href"); g_free(buffer); if (free_data) g_free(data); @@ -867,6 +877,8 @@ void sp_embed_svg(Inkscape::XML::Node *image_node, std::string const &fn) // 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); + // Remove alternative href attribute + image_node->removeAttribute("href"); g_free(buffer); g_free(data); diff --git a/src/object/sp-object.cpp b/src/object/sp-object.cpp index e1e9c80599e7b156d3743967b22362b80b2b114e..3fe4db3e9dd6848f77ced6facc2ae25337700c54 100644 --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -1008,19 +1008,24 @@ void SPObject::setKeyValue(SPAttributeEnum key, gchar const *value) this->set(key, value); } -void SPObject::readAttr(gchar const *key) +void SPObject::readAttr(gchar const *key, char const *fallback) { - //g_assert(object != NULL); - //g_assert(SP_IS_OBJECT(object)); g_assert(key != nullptr); - - //XML Tree being used here. - g_assert(this->getRepr() != nullptr); - auto keyid = sp_attribute_lookup(key); + if (keyid != SP_ATTR_INVALID) { - /* Retrieve the 'key' attribute from the object's XML representation */ - gchar const *value = getRepr()->attribute(key); + + //XML Tree being used here. + auto repr = this->getRepr(); + g_assert(repr != nullptr); + + // Retrieve the 'key' attribute from the object's XML representation + gchar const *value = repr->attribute(key); + + // Use a fallback key, but apply it to the same attribute name + if(!value && fallback) { + value = repr->attribute(fallback); + } setKeyValue(keyid, value); } diff --git a/src/object/sp-object.h b/src/object/sp-object.h index 100583ba22856bfb97232f7db3f2cdbdfe64a47d..15b96199e723c99ddda06c0d54428bb3b4f4760a 100644 --- a/src/object/sp-object.h +++ b/src/object/sp-object.h @@ -721,8 +721,12 @@ public: /** * Read value of key attribute from XML node into object. + * + * @param key The name of the attribute being read. Is converted to an SPAttributeEnum + * @param fallback The key to use if the main key isn't available, does not need + * to exist in SPAttributeEnum. */ - void readAttr(char const *key); + void readAttr(char const *key, char const *fallback = nullptr); char const *getTagName(SPException *ex) const; diff --git a/src/object/sp-offset.cpp b/src/object/sp-offset.cpp index bcb24e8debfe9e4d1bb8f2a95606678fff20e702..a5f04c10247c4743573359c39d8f212bd8dd74d2 100644 --- a/src/object/sp-offset.cpp +++ b/src/object/sp-offset.cpp @@ -134,9 +134,7 @@ void SPOffset::build(SPDocument *document, Inkscape::XML::Node *repr) { this->readAttr( "inkscape:original" ); } - if (this->getRepr()->attribute("xlink:href")) { - this->readAttr( "xlink:href" ); - } else { + if (this->getRepr()->attribute("inkscape:href")) { gchar const *oldA = this->getRepr()->attribute("inkscape:href"); if (oldA) { @@ -154,9 +152,9 @@ void SPOffset::build(SPDocument *document, Inkscape::XML::Node *repr) { this->removeAttribute("inkscape:href"); } - - this->readAttr( "xlink:href" ); } + + this->readAttr("href", "xlink:href"); } Inkscape::XML::Node* SPOffset::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { @@ -267,8 +265,7 @@ void SPOffset::set(SPAttributeEnum key, const gchar* value) { } break; - case SP_ATTR_INKSCAPE_HREF: - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if ( value == nullptr ) { sp_offset_quit_listening(this); if ( this->sourceHref ) { diff --git a/src/object/sp-pattern.cpp b/src/object/sp-pattern.cpp index 5017ca434fd64d39cc966ee0a9ca1b0931450ec2..fe9af904cbdea69a5720dffea5f7138bb4d31616 100644 --- a/src/object/sp-pattern.cpp +++ b/src/object/sp-pattern.cpp @@ -75,7 +75,7 @@ void SPPattern::build(SPDocument *doc, Inkscape::XML::Node *repr) this->readAttr("height"); this->readAttr("viewBox"); this->readAttr("preserveAspectRatio"); - this->readAttr("xlink:href"); + this->readAttr("href", "xlink:href"); this->readAttr("style"); /* Register ourselves */ @@ -183,7 +183,7 @@ void SPPattern::set(SPAttributeEnum key, const gchar *value) this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (value && this->href == value) { /* Href unchanged, do nothing. */ } @@ -329,6 +329,8 @@ SPPattern *SPPattern::_chain() const repr->setAttribute("inkscape:collect", "always"); Glib::ustring parent_ref = Glib::ustring::compose("#%1", getRepr()->attribute("id")); repr->setAttribute("xlink:href", parent_ref); + // Remove alternative href attribute + repr->removeAttribute("href"); defsrepr->addChild(repr, nullptr); SPObject *child = document->getObjectByRepr(repr); diff --git a/src/object/sp-script.cpp b/src/object/sp-script.cpp index d965421cbbdaa92f553c396b88ff4dadeb679e4f..3dad6332ae88a9a6ef8e3e8e55ecdcd89fb087c6 100644 --- a/src/object/sp-script.cpp +++ b/src/object/sp-script.cpp @@ -25,7 +25,7 @@ void SPScript::build(SPDocument* doc, Inkscape::XML::Node* repr) { SPObject::build(doc, repr); //Read values of key attributes from XML nodes into object. - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); doc->addResource("script", this); } @@ -55,7 +55,7 @@ void SPScript::modified(unsigned int /*flags*/) { void SPScript::set(SPAttributeEnum key, const gchar* value) { switch (key) { - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: if (this->xlinkhref) { g_free(this->xlinkhref); } diff --git a/src/object/sp-tag-use.cpp b/src/object/sp-tag-use.cpp index 40c5599e702117a61ad18425ad9a802db7d92176..c821df79f52828ffe508dd922bef2f32a3c2a26e 100644 --- a/src/object/sp-tag-use.cpp +++ b/src/object/sp-tag-use.cpp @@ -58,7 +58,7 @@ void SPTagUse::build(SPDocument *document, Inkscape::XML::Node *repr) { SPObject::build(document, repr); - readAttr( "xlink:href" ); + readAttr("href", "xlink:href"); // We don't need to create child here: // reading xlink:href will attach ref, and that will cause the changed signal to be emitted, @@ -89,7 +89,8 @@ SPTagUse::set(SPAttributeEnum key, gchar const *value) { switch (key) { - case SP_ATTR_XLINK_HREF: { + case SP_ATTR_HREF: + { if ( value && href && ( strcmp(value, href) == 0 ) ) { /* No change, do nothing. */ } else { @@ -112,7 +113,6 @@ SPTagUse::set(SPAttributeEnum key, gchar const *value) } break; } - default: SPObject::set(key, value); break; @@ -131,6 +131,8 @@ SPTagUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, gui if (ref->getURI()) { auto uri_string = ref->getURI()->str(); repr->setAttributeOrRemoveIfEmpty("xlink:href", uri_string); + // Remove alternative href attribute + repr->removeAttribute("href"); } return repr; diff --git a/src/object/sp-tref.cpp b/src/object/sp-tref.cpp index a99f8686f99d4fe2512e3829929d845b5966db60..636eb2429ad335bd398646dd7b1e4947f01c9bc2 100644 --- a/src/object/sp-tref.cpp +++ b/src/object/sp-tref.cpp @@ -64,7 +64,7 @@ SPTRef::~SPTRef() { void SPTRef::build(SPDocument *document, Inkscape::XML::Node *repr) { SPItem::build(document, repr); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->readAttr( "x" ); this->readAttr( "y" ); this->readAttr( "dx" ); @@ -92,7 +92,7 @@ void SPTRef::set(SPAttributeEnum key, const gchar* value) { if (this->attributes.readSingleAttribute(key, value, style, &viewport)) { // x, y, dx, dy, rotate this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - } else if (key == SP_ATTR_XLINK_HREF) { // xlink:href + } else if (key == SP_ATTR_HREF) { // xlink:href or href if ( !value ) { // No value g_free(this->href); @@ -178,6 +178,8 @@ Inkscape::XML::Node* SPTRef::write(Inkscape::XML::Document *xml_doc, Inkscape::X auto uri_string = uri.c_str(); debug("uri_string=%s", uri_string); repr->setAttribute("xlink:href", uri_string); + // Make sure alternative attribute is removed + repr->removeAttribute("href"); } SPItem::write(xml_doc, repr, flags); diff --git a/src/object/sp-tspan.cpp b/src/object/sp-tspan.cpp index bfa52c57b61b9ae33df8a5c56031990b3579e25a..8c8cccb3f5443aa09894617cfe222dada6c644ba 100644 --- a/src/object/sp-tspan.cpp +++ b/src/object/sp-tspan.cpp @@ -264,7 +264,7 @@ void SPTextPath::build(SPDocument *doc, Inkscape::XML::Node *repr) { this->readAttr( "rotate" ); this->readAttr( "startOffset" ); this->readAttr( "side" ); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); this->readAttr( "style"); @@ -289,7 +289,7 @@ void SPTextPath::set(SPAttributeEnum key, const gchar* value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } else { switch (key) { - case SP_ATTR_XLINK_HREF: + case SP_ATTR_HREF: this->sourcePath->link((char*)value); break; case SP_ATTR_SIDE: @@ -427,6 +427,8 @@ Inkscape::XML::Node* SPTextPath::write(Inkscape::XML::Document *xml_doc, Inkscap if ( this->sourcePath->sourceHref ) { repr->setAttribute("xlink:href", this->sourcePath->sourceHref); + // Remove alternative href attribute + repr->removeAttribute("href"); } if ( flags & SP_OBJECT_WRITE_BUILD ) { diff --git a/src/object/sp-use.cpp b/src/object/sp-use.cpp index f1cf6d04704d87e630470ea8e73fd02e648e2ebd..c45f06e58d3537d23be3df3c5262e490d9744506 100644 --- a/src/object/sp-use.cpp +++ b/src/object/sp-use.cpp @@ -82,7 +82,7 @@ void SPUse::build(SPDocument *document, Inkscape::XML::Node *repr) { this->readAttr( "y" ); this->readAttr( "width" ); this->readAttr( "height" ); - this->readAttr( "xlink:href" ); + this->readAttr("href", "xlink:href"); // We don't need to create child here: // reading xlink:href will attach ref, and that will cause the changed signal to be emitted, @@ -129,7 +129,7 @@ void SPUse::set(SPAttributeEnum key, const gchar* value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: { + case SP_ATTR_HREF: { if ( value && this->href && ( strcmp(value, this->href) == 0 ) ) { /* No change, do nothing. */ } else { @@ -175,6 +175,8 @@ Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XM if (this->ref->getURI()) { auto uri_string = this->ref->getURI()->str(); repr->setAttributeOrRemoveIfEmpty("xlink:href", uri_string); + // Remove alternative href attribute + repr->removeAttribute("href"); } SPShape *shape = dynamic_cast(child); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 85e29eda8ec75efb98cc96c93371cd36471cba39..c83fa0c76f8e0dc6ca65b6c8a98105d64de308c0 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -548,6 +548,8 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) // std::cout << id << " old, its ori: " << orig->getId() << "; will relink:" << new_ids[i] << " to " << new_ids[j] << "\n"; SPObject *new_clone = doc->getObjectById(new_ids[i]); new_clone->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); + // Remove alternative href attribute + new_clone->removeAttribute("href"); new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } @@ -555,7 +557,10 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) gchar *source_href = offset->sourceHref; for (guint j = 0; j < old_ids.size(); j++) { if (source_href && source_href[0]=='#' && !strcmp(source_href+1, old_ids[j])) { - doc->getObjectById(new_ids[i])->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); + auto obj = doc->getObjectById(new_ids[i]); + obj->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); + // Remove alternative href attribute + obj->removeAttribute("href"); } } } else if (text) { @@ -564,7 +569,10 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) const gchar *source_href = sp_textpath_get_path_item(textpath)->getId(); for (guint j = 0; j < old_ids.size(); j++) { if (!strcmp(source_href, old_ids[j])) { - doc->getObjectById(new_ids[i])->firstChild()->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); + auto obj = doc->getObjectById(new_ids[i])->firstChild(); + obj->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); + // Remove alternative href attribute + obj->removeAttribute("href"); } } } else if (path) { @@ -2682,6 +2690,8 @@ void ObjectSet::relink() if (dynamic_cast(item)) { item->setAttribute("xlink:href", newref); + // Remove alternative href attribute + item->removeAttribute("href"); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); relinked = true; } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 54a16886faded787d5d34619354706e512652b4b..d05cc2fe810167821981ad6269783817d1aee30e 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -342,6 +342,8 @@ void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* Inkscape::XML::Node *use = _doc->createElement("svg:use"); use->setAttribute("xlink:href", id ); + // Remove alternative href attribute + use->removeAttribute("href"); // Set a default style in rather than so it can be changed. use->setAttribute("style", style ); if (!Geom::are_near(scale_units, 1.0, Geom::EPSILON)) { diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 85965743f4ceeb666dc14d8b2849b94c2f5d92e7..e6184fd8f0a24d57a49fae4c4e28ef51c20db860 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -685,8 +685,12 @@ void ContextMenu::AnchorLinkRemove() void ContextMenu::MakeImageMenu () { Gtk::MenuItem* mi; - Inkscape::XML::Node *ir = _object->getRepr(); - const gchar *href = ir->attribute("xlink:href"); + const gchar *href = _object->getAttribute("href"); + if(!href) { + href = _object->getAttribute("xlink:href"); + } + + bool not_href = !href || strncmp(href, "data:", 5) == 0; /* Image properties */ mi = Gtk::manage(new Gtk::MenuItem(_("Image _Properties..."), true)); @@ -699,7 +703,7 @@ void ContextMenu::MakeImageMenu () mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageEdit)); mi->show(); insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { + if ( not_href ) { mi->set_sensitive( FALSE ); } @@ -718,7 +722,7 @@ void ContextMenu::MakeImageMenu () mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageEmbed)); mi->show(); insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { + if ( not_href ) { mi->set_sensitive( FALSE ); } } @@ -729,7 +733,7 @@ void ContextMenu::MakeImageMenu () mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageExtract)); mi->show(); insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) != 0)) ) { + if ( not_href ) { mi->set_sensitive( FALSE ); } } @@ -798,8 +802,10 @@ void ContextMenu::ImageEdit() auto itemlist= _desktop->selection->items(); for(auto i=itemlist.begin();i!=itemlist.end();++i){ - Inkscape::XML::Node *ir = (*i)->getRepr(); - const gchar *href = ir->attribute("xlink:href"); + const gchar *href = (*i)->getAttribute("href"); + if(!href) { + href = (*i)->getAttribute("xlink:href"); + } if (strncmp (href,"file:",5) == 0) { // URI to filename conversion diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index 74d75439c331247b63a7d2d5f37772aa9f298c7b..8a1f85178444a15c6f5efd1f545acb6c2b69ef0d 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -1854,12 +1854,16 @@ bool CloneTiler::is_a_clone_of(SPObject *tile, SPObject *obj) Inkscape::XML::Node *obj_repr = obj->getRepr(); id_href = g_strdup_printf("#%s", obj_repr->attribute("id")); } + + const gchar *href = tile->getAttribute("href"); + if(!href) { + href = tile->getAttribute("xlink:href"); + } if (dynamic_cast(tile) && - tile->getRepr()->attribute("xlink:href") && - (!id_href || !strcmp(id_href, tile->getRepr()->attribute("xlink:href"))) && - tile->getRepr()->attribute("inkscape:tiled-clone-of") && - (!id_href || !strcmp(id_href, tile->getRepr()->attribute("inkscape:tiled-clone-of")))) + href && (!id_href || !strcmp(id_href, href)) && + tile->getAttribute("inkscape:tiled-clone-of") && + (!id_href || !strcmp(id_href, tile->getAttribute("inkscape:tiled-clone-of")))) { result = true; } else { diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index a1575fee92a16398d076f944a47b4399134bb937..0efc4185d9ea64a5c6bd60501c96e59939183624 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -2842,7 +2842,7 @@ void FilterEffectsDialog::init_settings_widgets() _settings->add_dualspinscale(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1); _settings->type(NR_FILTER_IMAGE); - _settings->add_fileorelement(SP_ATTR_XLINK_HREF, _("Source of Image:")); + _settings->add_fileorelement(SP_ATTR_HREF, _("Source of Image:")); _image_x = _settings->add_entry(SP_ATTR_X,_("X"),_("X")); _image_x->signal_attr_changed().connect(sigc::mem_fun(*this, &FilterEffectsDialog::image_x_changed)); //This commented because we want the default empty value of X or Y and couldent get it from SpinButton diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp index 44bcf7f138527b667ca14d120d3a8f0bf894f7f4..5ec8dbbe610544eb8754fe2e06cb59734d2aed84 100644 --- a/src/ui/dialog/object-attributes.cpp +++ b/src/ui/dialog/object-attributes.cpp @@ -35,6 +35,7 @@ struct SPAttrDesc { }; static const SPAttrDesc anchor_desc[] = { + { N_("Href:"), "href"}, { N_("Href:"), "xlink:href"}, { N_("Target:"), "target"}, { N_("Type:"), "xlink:type"}, @@ -53,6 +54,7 @@ static const SPAttrDesc anchor_desc[] = { }; static const SPAttrDesc image_desc[] = { + { N_("URL:"), "href"}, { N_("URL:"), "xlink:href"}, { N_("X:"), "x"}, { N_("Y:"), "y"}, @@ -121,8 +123,11 @@ void ObjectAttributes::widget_setup () // else if (type == SP_TYPE_IMAGE) else if (SP_IS_IMAGE(item)) { - Inkscape::XML::Node *ir = obj->getRepr(); - const gchar *href = ir->attribute("xlink:href"); + + const gchar *href = obj->getAttribute("href"); + if(!href) { + href = obj->getAttribute("xlink:href"); + } if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { desc = image_nohref_desc; diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 9dc867bb4cd3219e19ab84e82187a08ac6ff4798..f36403ea8e515f87444a03b374317740e41a1ae9 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -992,7 +992,11 @@ gchar const* SymbolsDialog::styleFromUse( gchar const* id, SPDocument* document) std::vector l = useInDoc( document ); for( auto use:l ) { if ( use ) { - gchar const *href = use->getRepr()->attribute("xlink:href"); + // Support SVG2 style href but continue xlink support + const gchar *href = use->getAttribute("href"); + if (!href) { + href = use->getAttribute("xlink:href"); + } if( href ) { Glib::ustring href2(href); Glib::ustring id2(id); diff --git a/src/xml/rebase-hrefs.cpp b/src/xml/rebase-hrefs.cpp index b6f7e5505e15596cf3244396ec5bd3078beb7c98..1cc14cf23d48464ae6e2341fbdc43d88ad658677 100644 --- a/src/xml/rebase-hrefs.cpp +++ b/src/xml/rebase-hrefs.cpp @@ -70,7 +70,8 @@ Inkscape::XML::rebase_href_attrs(gchar const *const old_abs_base, return attributes; } - GQuark const href_key = g_quark_from_static_string("xlink:href"); + GQuark const href_key = g_quark_from_static_string("href"); + GQuark const xlink_href_key = g_quark_from_static_string("xlink:href"); GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); /* First search attributes for xlink:href and sodipodi:absref, putting the rest in ret. @@ -82,7 +83,7 @@ Inkscape::XML::rebase_href_attrs(gchar const *const old_abs_base, List ret; { for (List ai(attributes); ai; ++ai) { - if (ai->key == href_key) { + if (ai->key == href_key || ai->key == xlink_href_key) { old_href = ai->value; if (!href_needs_rebasing(static_cast(old_href))) { return attributes; @@ -167,7 +168,10 @@ void Inkscape::XML::rebase_hrefs(SPDocument *const doc, gchar const *const new_b for (auto image : images) { Inkscape::XML::Node *ir = image->getRepr(); - auto href_cstr = ir->attribute("xlink:href"); + auto href_cstr = ir->attribute("href"); + if (!href_cstr) { + href_cstr = ir->attribute("xlink:href"); + } if (!href_cstr) { continue; } @@ -208,6 +212,8 @@ void Inkscape::XML::rebase_hrefs(SPDocument *const doc, gchar const *const new_b href_str = Inkscape::uri_to_iri(href_str.c_str()); ir->setAttribute("xlink:href", href_str); + // Remove alternative href attribute + ir->removeAttribute("href"); } doc->setDocumentBase(new_base); diff --git a/testfiles/src/attributes-test.cpp b/testfiles/src/attributes-test.cpp index 01462e1593de50ee2692af6e9be8339818aef68f..d71e12b000ac38434b92e9413fdfab1abe20459b 100644 --- a/testfiles/src/attributes-test.cpp +++ b/testfiles/src/attributes-test.cpp @@ -359,10 +359,11 @@ std::vector getKnownAttrs() AttributeInfo("x-height", true), AttributeInfo("x1", true), AttributeInfo("x2", true), + AttributeInfo("href", true), + // AttributeInfo("xlink:href", true), AttributeInfo("xChannelSelector", true), AttributeInfo("xlink:actuate", true), AttributeInfo("xlink:arcrole", true), - AttributeInfo("xlink:href", true), AttributeInfo("xlink:role", true), AttributeInfo("xlink:show", true), AttributeInfo("xlink:title", true), @@ -411,7 +412,7 @@ std::vector getKnownAttrs() AttributeInfo("inkscape:flatsided", true), AttributeInfo("inkscape:groupmode", true), AttributeInfo("inkscape:highlight-color", true), - AttributeInfo("inkscape:href", true), + // AttributeInfo("inkscape:href", true), AttributeInfo("inkscape:label", true), AttributeInfo("inkscape:layoutOptions", true), AttributeInfo("inkscape:lockguides", true),