diff options
| author | Markus Engel <markus.engel@tum.de> | 2013-03-29 23:52:42 +0000 |
|---|---|---|
| committer | Markus Engel <markus.engel@tum.de> | 2013-03-29 23:52:42 +0000 |
| commit | a168040d5a452544328a1e6ad35aaac351f94d44 (patch) | |
| tree | fae1ba829f543a473da281bd5fa6e4deabbf6912 /src/id-clash.cpp | |
| parent | Removed function pointers from SPObject and subclasses. (diff) | |
| parent | Dutch translation update (diff) | |
| download | inkscape-a168040d5a452544328a1e6ad35aaac351f94d44.tar.gz inkscape-a168040d5a452544328a1e6ad35aaac351f94d44.zip | |
merged from trunk
(bzr r11608.1.56)
Diffstat (limited to 'src/id-clash.cpp')
| -rw-r--r-- | src/id-clash.cpp | 79 |
1 files changed, 63 insertions, 16 deletions
diff --git a/src/id-clash.cpp b/src/id-clash.cpp index 12bb65a26..c8eacfe02 100644 --- a/src/id-clash.cpp +++ b/src/id-clash.cpp @@ -26,6 +26,7 @@ #include "xml/node.h" #include "xml/repr.h" #include "sp-root.h" +#include "sp-gradient.h" typedef enum { REF_HREF, REF_STYLE, REF_URL, REF_CLIPBOARD } ID_REF_TYPE; @@ -35,9 +36,9 @@ struct IdReference { const char *attr; // property or href-like attribute }; -typedef std::map<std::string, std::list<IdReference> > refmap_type; +typedef std::map<Glib::ustring, std::list<IdReference> > refmap_type; -typedef std::pair<SPObject*, std::string> id_changeitem_type; +typedef std::pair<SPObject*, Glib::ustring> id_changeitem_type; typedef std::list<id_changeitem_type> id_changelist_type; const char *href_like_attributes[] = { @@ -79,6 +80,9 @@ const char* clipboard_properties[] = { "fill", "filter", "stroke", + "marker-end", + "marker-mid", + "marker-start" }; #define NUM_CLIPBOARD_PROPERTIES (sizeof(clipboard_properties) / sizeof(*clipboard_properties)) @@ -111,6 +115,7 @@ find_references(SPObject *elem, refmap_type *refmap) g_free(uri); } } + } return; // nothing more to do for inkscape:clipboard elements } @@ -153,6 +158,20 @@ find_references(SPObject *elem, refmap_type *refmap) } } + /* check for url(#...) references in markers */ + const gchar *markers[4] = { "", "marker-start", "marker-mid", "marker-end" }; + for (unsigned i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) { + const gchar *value = style->marker[i].value; + if (value) { + gchar *uri = extract_uri(value); + if (uri && uri[0] == '#') { + IdReference idref = { REF_STYLE, elem, markers[i] }; + (*refmap)[uri+1].push_back(idref); + } + g_free(uri); + } + } + /* check for other url(#...) references */ for (unsigned i = 0; i < NUM_OTHER_URL_PROPERTIES; ++i) { const char *attr = other_url_properties[i]; @@ -241,9 +260,9 @@ fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes) gchar *url = g_strdup_printf("url(#%s)", obj->getId()); sp_repr_css_set_property(style, it->attr, url); g_free(url); - gchar *style_string = sp_repr_css_write_string(style); - it->elem->getRepr()->setAttribute("style", style_string); - g_free(style_string); + Glib::ustring style_string; + sp_repr_css_write_string(style, style_string); + it->elem->getRepr()->setAttribute("style", style_string.c_str()); } else { g_assert(0); // shouldn't happen } @@ -273,14 +292,46 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc) } /* + * Change any references of svg:def from_obj into to_obj + */ +void +change_def_references(SPObject *from_obj, SPObject *to_obj) +{ + refmap_type *refmap = new refmap_type; + SPDocument *current_doc = from_obj->document; + std::string old_id(from_obj->getId()); + + find_references(current_doc->getRoot(), refmap); + + refmap_type::const_iterator pos = refmap->find(old_id); + if (pos != refmap->end()) { + std::list<IdReference>::const_iterator it; + const std::list<IdReference>::const_iterator it_end = pos->second.end(); + for (it = pos->second.begin(); it != it_end; ++it) { + if (it->type == REF_STYLE) { + sp_style_set_property_url(it->elem, it->attr, to_obj, false); + } + } + } + + delete refmap; +} + +/* * Change the id of a SPObject to new_name * If there is an id clash then rename to something similar */ void rename_id(SPObject *elem, Glib::ustring const &new_name) { - gchar *id = g_strdup(new_name.c_str()); + if (new_name.empty()){ + g_message("Invalid Id, will not change."); + return; + } + gchar *id = g_strdup(new_name.c_str()); //id is not empty here as new_name is check to be not empty g_strcanon (id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_'); - if (!*id || !isalnum (*id)) { + Glib::ustring new_name2 = id; //will not fail as id can not be NULL, see length check on new_name + g_free (id); + if (!isalnum (new_name2[0])) { g_message("Invalid Id, will not change."); return; } @@ -291,31 +342,27 @@ void rename_id(SPObject *elem, Glib::ustring const &new_name) find_references(current_doc->getRoot(), refmap); std::string old_id(elem->getId()); - std::string new_id(id); - if (id && current_doc->getObjectById(id)) { + if (current_doc->getObjectById(id)) { // Choose a new ID. // To try to preserve any meaningfulness that the original ID // may have had, the new ID is the old ID followed by a hyphen // and one or more digits. - new_id += '-'; + new_name2 += '-'; for (;;) { - new_id += "0123456789"[std::rand() % 10]; - const char *str = new_id.c_str(); - if (current_doc->getObjectById(str) == NULL) + new_name2 += "0123456789"[std::rand() % 10]; + if (current_doc->getObjectById(new_name2) == NULL) break; } } // Change to the new ID - elem->getRepr()->setAttribute("id", new_id.c_str()); + elem->getRepr()->setAttribute("id", new_name2.c_str()); // Make a note of this change, if we need to fix up refs to it if (refmap->find(old_id) != refmap->end()) { id_changes.push_back(id_changeitem_type(elem, old_id)); } fix_up_refs(refmap, id_changes); - - g_free (id); delete refmap; } |
