diff options
| author | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
|---|---|---|
| committer | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
| commit | 5a4fb2325f60d292b47330f540b26a3279341c90 (patch) | |
| tree | d2aa7967be25450b83e625025366c618101ae49f /src/xml | |
| parent | The Polar Arrange Tab of the Arrange Dialog now hides the parametric (diff) | |
| parent | Remove Snap menu item and improve grid menu item text (diff) | |
| download | inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.tar.gz inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.zip | |
Commit a merge to trunk, with probabal errors
(bzr r11073.1.36)
Diffstat (limited to 'src/xml')
| -rw-r--r-- | src/xml/Makefile_insert | 3 | ||||
| -rw-r--r-- | src/xml/composite-node-observer.cpp | 8 | ||||
| -rw-r--r-- | src/xml/composite-node-observer.h | 2 | ||||
| -rw-r--r-- | src/xml/event-fns.h | 2 | ||||
| -rw-r--r-- | src/xml/event.cpp | 591 | ||||
| -rw-r--r-- | src/xml/helper-observer.cpp | 14 | ||||
| -rw-r--r-- | src/xml/node-fns.cpp | 1 | ||||
| -rw-r--r-- | src/xml/node.h | 16 | ||||
| -rw-r--r-- | src/xml/quote-test.h | 5 | ||||
| -rw-r--r-- | src/xml/quote.cpp | 29 | ||||
| -rw-r--r-- | src/xml/quote.h | 3 | ||||
| -rw-r--r-- | src/xml/rebase-hrefs.h | 2 | ||||
| -rw-r--r-- | src/xml/repr-css.cpp | 60 | ||||
| -rw-r--r-- | src/xml/repr-io.cpp | 140 | ||||
| -rw-r--r-- | src/xml/repr-sorting.cpp | 12 | ||||
| -rw-r--r-- | src/xml/repr-util.cpp | 80 | ||||
| -rw-r--r-- | src/xml/repr.h | 29 | ||||
| -rw-r--r-- | src/xml/simple-node.cpp | 7 |
18 files changed, 546 insertions, 458 deletions
diff --git a/src/xml/Makefile_insert b/src/xml/Makefile_insert index b10f2448b..da55d7f7e 100644 --- a/src/xml/Makefile_insert +++ b/src/xml/Makefile_insert @@ -40,8 +40,7 @@ ink_common_sources += \ xml/subtree.cpp \ xml/subtree.h \ xml/text-node.h \ - xml/invalid-operation-exception.h \ - xml/xml-forward.h + xml/invalid-operation-exception.h # ###################### # ### CxxTest stuff #### diff --git a/src/xml/composite-node-observer.cpp b/src/xml/composite-node-observer.cpp index 36fe469de..7343ab1a8 100644 --- a/src/xml/composite-node-observer.cpp +++ b/src/xml/composite-node-observer.cpp @@ -277,7 +277,13 @@ struct vector_data_matches { bool operator()(NodeObserver const &observer) { VectorNodeObserver const *vo=dynamic_cast<VectorNodeObserver const *>(&observer); - return vo && vo->data == data; + bool OK = false; + if (vo) { + if (vo && vo->data == data) { + OK = true; + } + } + return OK; } }; diff --git a/src/xml/composite-node-observer.h b/src/xml/composite-node-observer.h index 96825d607..3e4b1673a 100644 --- a/src/xml/composite-node-observer.h +++ b/src/xml/composite-node-observer.h @@ -23,7 +23,7 @@ namespace Inkscape { namespace XML { -class NodeEventVector; +struct NodeEventVector; /** * @brief An observer that relays notifications to multiple other observers diff --git a/src/xml/event-fns.h b/src/xml/event-fns.h index 65c65c48c..5e3b43ad8 100644 --- a/src/xml/event-fns.h +++ b/src/xml/event-fns.h @@ -4,7 +4,7 @@ namespace Inkscape { namespace XML { -class Document; +struct Document; class Event; class NodeObserver; diff --git a/src/xml/event.cpp b/src/xml/event.cpp index 23251eac6..9a760ccc5 100644 --- a/src/xml/event.cpp +++ b/src/xml/event.cpp @@ -32,246 +32,247 @@ int Inkscape::XML::Event::_next_serial=0; void sp_repr_begin_transaction (Inkscape::XML::Document *doc) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("begin-transaction"); + EventTracker<SimpleEvent<Event::XML> > tracker("begin-transaction"); - g_assert(doc != NULL); - doc->beginTransaction(); + g_assert(doc != NULL); + doc->beginTransaction(); } void sp_repr_rollback (Inkscape::XML::Document *doc) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("rollback"); + EventTracker<SimpleEvent<Event::XML> > tracker("rollback"); - g_assert(doc != NULL); - doc->rollback(); + g_assert(doc != NULL); + doc->rollback(); } void sp_repr_commit (Inkscape::XML::Document *doc) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("commit"); + EventTracker<SimpleEvent<Event::XML> > tracker("commit"); - g_assert(doc != NULL); - doc->commit(); + g_assert(doc != NULL); + doc->commit(); } Inkscape::XML::Event * sp_repr_commit_undoable (Inkscape::XML::Document *doc) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("commit"); + EventTracker<SimpleEvent<Event::XML> > tracker("commit"); - g_assert(doc != NULL); - return doc->commitUndoable(); + g_assert(doc != NULL); + return doc->commitUndoable(); } namespace { class LogPerformer : public Inkscape::XML::NodeObserver { public: - typedef Inkscape::XML::Node Node; - - static LogPerformer &instance() { - static LogPerformer singleton; - return singleton; - } - - void notifyChildAdded(Node &parent, Node &child, Node *ref) { - parent.addChild(&child, ref); - } - - void notifyChildRemoved(Node &parent, Node &child, Node */*old_ref*/) { - parent.removeChild(&child); - } - - void notifyChildOrderChanged(Node &parent, Node &child, - Node */*old_ref*/, Node *new_ref) - { - parent.changeOrder(&child, new_ref); - } - - void notifyAttributeChanged(Node &node, GQuark name, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) - { - node.setAttribute(g_quark_to_string(name), new_value); - } - - void notifyContentChanged(Node &node, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) - { - node.setContent(new_value); - } + typedef Inkscape::XML::Node Node; + + static LogPerformer &instance() { + static LogPerformer singleton; + return singleton; + } + + void notifyChildAdded(Node &parent, Node &child, Node *ref) { + parent.addChild(&child, ref); + } + + void notifyChildRemoved(Node &parent, Node &child, Node */*old_ref*/) { + parent.removeChild(&child); + } + + void notifyChildOrderChanged(Node &parent, Node &child, + Node */*old_ref*/, Node *new_ref) + { + parent.changeOrder(&child, new_ref); + } + + void notifyAttributeChanged(Node &node, GQuark name, + Inkscape::Util::ptr_shared<char> /*old_value*/, + Inkscape::Util::ptr_shared<char> new_value) + { + node.setAttribute(g_quark_to_string(name), new_value); + } + + void notifyContentChanged(Node &node, + Inkscape::Util::ptr_shared<char> /*old_value*/, + Inkscape::Util::ptr_shared<char> new_value) + { + node.setContent(new_value); + } }; } void Inkscape::XML::undo_log_to_observer( - Inkscape::XML::Event const *log, - Inkscape::XML::NodeObserver &observer + Inkscape::XML::Event const *log, + Inkscape::XML::NodeObserver &observer ) { - for ( Event const *action = log ; action ; action = action->next ) { - action->undoOne(observer); - } + for ( Event const *action = log ; action ; action = action->next ) { + action->undoOne(observer); + } } -void -sp_repr_undo_log (Inkscape::XML::Event *log) +void sp_repr_undo_log (Inkscape::XML::Event *log) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("undo-log"); + EventTracker<SimpleEvent<Event::XML> > tracker("undo-log"); - if (log && log->repr) { - g_assert(!log->repr->document()->inTransaction()); - } + if (log) { + if (log->repr) { + g_assert(!log->repr->document()->inTransaction()); + } + } - Inkscape::XML::undo_log_to_observer(log, LogPerformer::instance()); + Inkscape::XML::undo_log_to_observer(log, LogPerformer::instance()); } void Inkscape::XML::EventAdd::_undoOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildRemoved(*this->repr, *this->child, this->ref); + observer.notifyChildRemoved(*this->repr, *this->child, this->ref); } void Inkscape::XML::EventDel::_undoOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildAdded(*this->repr, *this->child, this->ref); + observer.notifyChildAdded(*this->repr, *this->child, this->ref); } void Inkscape::XML::EventChgAttr::_undoOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyAttributeChanged(*this->repr, this->key, this->newval, this->oldval); + observer.notifyAttributeChanged(*this->repr, this->key, this->newval, this->oldval); } void Inkscape::XML::EventChgContent::_undoOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyContentChanged(*this->repr, this->newval, this->oldval); + observer.notifyContentChanged(*this->repr, this->newval, this->oldval); } void Inkscape::XML::EventChgOrder::_undoOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildOrderChanged(*this->repr, *this->child, this->newref, this->oldref); + observer.notifyChildOrderChanged(*this->repr, *this->child, this->newref, this->oldref); } void Inkscape::XML::replay_log_to_observer( - Inkscape::XML::Event const *log, - Inkscape::XML::NodeObserver &observer + Inkscape::XML::Event const *log, + Inkscape::XML::NodeObserver &observer ) { - List<Inkscape::XML::Event const &> reversed = - reverse_list<Inkscape::XML::Event::ConstIterator>(log, NULL); - for ( ; reversed ; ++reversed ) { - reversed->replayOne(observer); - } + List<Inkscape::XML::Event const &> reversed = + reverse_list<Inkscape::XML::Event::ConstIterator>(log, NULL); + for ( ; reversed ; ++reversed ) { + reversed->replayOne(observer); + } } void sp_repr_replay_log (Inkscape::XML::Event *log) { - using Inkscape::Debug::SimpleEvent; - using Inkscape::Debug::EventTracker; - using Inkscape::Debug::Event; + using Inkscape::Debug::SimpleEvent; + using Inkscape::Debug::EventTracker; + using Inkscape::Debug::Event; - EventTracker<SimpleEvent<Event::XML> > tracker("replay-log"); + EventTracker<SimpleEvent<Event::XML> > tracker("replay-log"); - if (log) { - if (log->repr->document()) { - g_assert(!log->repr->document()->inTransaction()); - } - } + if (log) { + if (log->repr->document()) { + g_assert(!log->repr->document()->inTransaction()); + } + } - Inkscape::XML::replay_log_to_observer(log, LogPerformer::instance()); + Inkscape::XML::replay_log_to_observer(log, LogPerformer::instance()); } void Inkscape::XML::EventAdd::_replayOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildAdded(*this->repr, *this->child, this->ref); + observer.notifyChildAdded(*this->repr, *this->child, this->ref); } void Inkscape::XML::EventDel::_replayOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildRemoved(*this->repr, *this->child, this->ref); + observer.notifyChildRemoved(*this->repr, *this->child, this->ref); } void Inkscape::XML::EventChgAttr::_replayOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyAttributeChanged(*this->repr, this->key, this->oldval, this->newval); + observer.notifyAttributeChanged(*this->repr, this->key, this->oldval, this->newval); } void Inkscape::XML::EventChgContent::_replayOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyContentChanged(*this->repr, this->oldval, this->newval); + observer.notifyContentChanged(*this->repr, this->oldval, this->newval); } void Inkscape::XML::EventChgOrder::_replayOne( - Inkscape::XML::NodeObserver &observer + Inkscape::XML::NodeObserver &observer ) const { - observer.notifyChildOrderChanged(*this->repr, *this->child, this->oldref, this->newref); + observer.notifyChildOrderChanged(*this->repr, *this->child, this->oldref, this->newref); } Inkscape::XML::Event * sp_repr_coalesce_log (Inkscape::XML::Event *a, Inkscape::XML::Event *b) { - Inkscape::XML::Event *action; - Inkscape::XML::Event **prev_ptr; + Inkscape::XML::Event *action; + Inkscape::XML::Event **prev_ptr; - if (!b) return a; - if (!a) return b; + if (!b) return a; + if (!a) return b; - /* find the earliest action in the second log */ - /* (also noting the pointer that references it, so we can - * replace it later) */ - prev_ptr = &b; - for ( action = b ; action->next ; action = action->next ) { - prev_ptr = &action->next; - } + /* find the earliest action in the second log */ + /* (also noting the pointer that references it, so we can + * replace it later) */ + prev_ptr = &b; + for ( action = b ; action->next ; action = action->next ) { + prev_ptr = &action->next; + } - /* add the first log after it */ - action->next = a; + /* add the first log after it */ + action->next = a; - /* optimize the result */ - *prev_ptr = action->optimizeOne(); + /* optimize the result */ + *prev_ptr = action->optimizeOne(); - return b; + return b; } void sp_repr_free_log (Inkscape::XML::Event *log) { - while (log) { - Inkscape::XML::Event *action; - action = log; - log = action->next; - delete action; - } + while (log) { + Inkscape::XML::Event *action; + action = log; + log = action->next; + delete action; + } } namespace { @@ -280,199 +281,211 @@ template <typename T> struct ActionRelations; template <> struct ActionRelations<Inkscape::XML::EventAdd> { - typedef Inkscape::XML::EventDel Opposite; + typedef Inkscape::XML::EventDel Opposite; }; template <> struct ActionRelations<Inkscape::XML::EventDel> { - typedef Inkscape::XML::EventAdd Opposite; + typedef Inkscape::XML::EventAdd Opposite; }; template <typename A> Inkscape::XML::Event *cancel_add_or_remove(A *action) { - typedef typename ActionRelations<A>::Opposite Opposite; - Opposite *opposite=dynamic_cast<Opposite *>(action->next); - - if ( opposite && opposite->repr == action->repr && - opposite->child == action->child && - opposite->ref == action->ref ) - { - Inkscape::XML::Event *remaining=opposite->next; - - delete opposite; - delete action; - - return remaining; - } else { - return action; - } + typedef typename ActionRelations<A>::Opposite Opposite; + Opposite *opposite=dynamic_cast<Opposite *>(action->next); + + bool OK = false; + if (opposite){ + if (opposite->repr == action->repr && + opposite->child == action->child && + opposite->ref == action->ref ) { + OK = true; + } + } + if (OK){ + Inkscape::XML::Event *remaining=opposite->next; + + delete opposite; + delete action; + + return remaining; + } else { + return action; + } } - } Inkscape::XML::Event *Inkscape::XML::EventAdd::_optimizeOne() { - return cancel_add_or_remove(this); + return cancel_add_or_remove(this); } Inkscape::XML::Event *Inkscape::XML::EventDel::_optimizeOne() { - return cancel_add_or_remove(this); + return cancel_add_or_remove(this); } Inkscape::XML::Event *Inkscape::XML::EventChgAttr::_optimizeOne() { - Inkscape::XML::EventChgAttr *chg_attr=dynamic_cast<Inkscape::XML::EventChgAttr *>(this->next); - - /* consecutive chgattrs on the same key can be combined */ - if ( chg_attr && chg_attr->repr == this->repr && - chg_attr->key == this->key ) - { - /* replace our oldval with the prior action's */ - this->oldval = chg_attr->oldval; - - /* discard the prior action */ - this->next = chg_attr->next; - delete chg_attr; - } - - return this; + Inkscape::XML::EventChgAttr *chg_attr=dynamic_cast<Inkscape::XML::EventChgAttr *>(this->next); + + /* consecutive chgattrs on the same key can be combined */ + if ( chg_attr) { + if ( chg_attr->repr == this->repr && + chg_attr->key == this->key ) + { + /* replace our oldval with the prior action's */ + this->oldval = chg_attr->oldval; + + /* discard the prior action */ + this->next = chg_attr->next; + delete chg_attr; + } + } + + return this; } Inkscape::XML::Event *Inkscape::XML::EventChgContent::_optimizeOne() { - Inkscape::XML::EventChgContent *chg_content=dynamic_cast<Inkscape::XML::EventChgContent *>(this->next); + Inkscape::XML::EventChgContent *chg_content=dynamic_cast<Inkscape::XML::EventChgContent *>(this->next); - /* consecutive content changes can be combined */ - if ( chg_content && chg_content->repr == this->repr ) { - /* replace our oldval with the prior action's */ - this->oldval = chg_content->oldval; + /* consecutive content changes can be combined */ + if (chg_content) { + if (chg_content->repr == this->repr ) { + /* replace our oldval with the prior action's */ + this->oldval = chg_content->oldval; - /* get rid of the prior action*/ - this->next = chg_content->next; - delete chg_content; - } + /* get rid of the prior action*/ + this->next = chg_content->next; + delete chg_content; + } + } - return this; + return this; } Inkscape::XML::Event *Inkscape::XML::EventChgOrder::_optimizeOne() { - Inkscape::XML::EventChgOrder *chg_order=dynamic_cast<Inkscape::XML::EventChgOrder *>(this->next); - - /* consecutive chgorders for the same child may be combined or - * canceled out */ - if ( chg_order && chg_order->repr == this->repr && - chg_order->child == this->child ) - { - if ( chg_order->oldref == this->newref ) { - /* cancel them out */ - Inkscape::XML::Event *after=chg_order->next; - - delete chg_order; - delete this; - - return after; - } else { - /* combine them */ - this->oldref = chg_order->oldref; - - /* get rid of the other one */ - this->next = chg_order->next; - delete chg_order; - - return this; - } - } else { - return this; - } + Inkscape::XML::EventChgOrder *chg_order=dynamic_cast<Inkscape::XML::EventChgOrder *>(this->next); + + /* consecutive chgorders for the same child may be combined or + * canceled out */ + bool OK = false; + if (chg_order) { + if (chg_order->repr == this->repr && + chg_order->child == this->child ){ + OK = true; + } + } + if (OK) { + if ( chg_order->oldref == this->newref ) { + /* cancel them out */ + Inkscape::XML::Event *after=chg_order->next; + + delete chg_order; + delete this; + + return after; + } else { + /* combine them */ + this->oldref = chg_order->oldref; + + /* get rid of the other one */ + this->next = chg_order->next; + delete chg_order; + + return this; + } + } else { + return this; + } } namespace { class LogPrinter : public Inkscape::XML::NodeObserver { public: - typedef Inkscape::XML::Node Node; - - static LogPrinter &instance() { - static LogPrinter singleton; - return singleton; - } - - static Glib::ustring node_to_string(Node const &node) { - Glib::ustring result; - char const *type_name=NULL; - switch (node.type()) { - case Inkscape::XML::DOCUMENT_NODE: - type_name = "Document"; - break; - case Inkscape::XML::ELEMENT_NODE: - type_name = "Element"; - break; - case Inkscape::XML::TEXT_NODE: - type_name = "Text"; - break; - case Inkscape::XML::COMMENT_NODE: - type_name = "Comment"; - break; - default: - g_assert_not_reached(); - } - char buffer[40]; - result.append("#<"); - result.append(type_name); - result.append(":"); - snprintf(buffer, 40, "0x%p", &node); - result.append(buffer); - result.append(">"); - - return result; - } - - static Glib::ustring ref_to_string(Node *ref) { - if (ref) { - return node_to_string(*ref); - } else { - return "beginning"; - } - } - - void notifyChildAdded(Node &parent, Node &child, Node *ref) { - g_warning("Event: Added %s to %s after %s", node_to_string(parent).c_str(), node_to_string(child).c_str(), ref_to_string(ref).c_str()); - } - - void notifyChildRemoved(Node &parent, Node &child, Node */*ref*/) { - g_warning("Event: Removed %s from %s", node_to_string(parent).c_str(), node_to_string(child).c_str()); - } - - void notifyChildOrderChanged(Node &parent, Node &child, - Node */*old_ref*/, Node *new_ref) - { - g_warning("Event: Moved %s after %s in %s", node_to_string(child).c_str(), ref_to_string(new_ref).c_str(), node_to_string(parent).c_str()); - } - - void notifyAttributeChanged(Node &node, GQuark name, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) - { - if (new_value) { - g_warning("Event: Set attribute %s to \"%s\" on %s", g_quark_to_string(name), new_value.pointer(), node_to_string(node).c_str()); - } else { - g_warning("Event: Unset attribute %s on %s", g_quark_to_string(name), node_to_string(node).c_str()); - } - } - - void notifyContentChanged(Node &node, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) - { - if (new_value) { - g_warning("Event: Set content of %s to \"%s\"", node_to_string(node).c_str(), new_value.pointer()); - } else { - g_warning("Event: Unset content of %s", node_to_string(node).c_str()); - } - } + typedef Inkscape::XML::Node Node; + + static LogPrinter &instance() { + static LogPrinter singleton; + return singleton; + } + + static Glib::ustring node_to_string(Node const &node) { + Glib::ustring result; + char const *type_name=NULL; + switch (node.type()) { + case Inkscape::XML::DOCUMENT_NODE: + type_name = "Document"; + break; + case Inkscape::XML::ELEMENT_NODE: + type_name = "Element"; + break; + case Inkscape::XML::TEXT_NODE: + type_name = "Text"; + break; + case Inkscape::XML::COMMENT_NODE: + type_name = "Comment"; + break; + default: + g_assert_not_reached(); + } + char buffer[40]; + result.append("#<"); + result.append(type_name); + result.append(":"); + snprintf(buffer, 40, "0x%p", &node); + result.append(buffer); + result.append(">"); + + return result; + } + + static Glib::ustring ref_to_string(Node *ref) { + if (ref) { + return node_to_string(*ref); + } else { + return "beginning"; + } + } + + void notifyChildAdded(Node &parent, Node &child, Node *ref) { + g_warning("Event: Added %s to %s after %s", node_to_string(parent).c_str(), node_to_string(child).c_str(), ref_to_string(ref).c_str()); + } + + void notifyChildRemoved(Node &parent, Node &child, Node */*ref*/) { + g_warning("Event: Removed %s from %s", node_to_string(parent).c_str(), node_to_string(child).c_str()); + } + + void notifyChildOrderChanged(Node &parent, Node &child, + Node */*old_ref*/, Node *new_ref) + { + g_warning("Event: Moved %s after %s in %s", node_to_string(child).c_str(), ref_to_string(new_ref).c_str(), node_to_string(parent).c_str()); + } + + void notifyAttributeChanged(Node &node, GQuark name, + Inkscape::Util::ptr_shared<char> /*old_value*/, + Inkscape::Util::ptr_shared<char> new_value) + { + if (new_value) { + g_warning("Event: Set attribute %s to \"%s\" on %s", g_quark_to_string(name), new_value.pointer(), node_to_string(node).c_str()); + } else { + g_warning("Event: Unset attribute %s on %s", g_quark_to_string(name), node_to_string(node).c_str()); + } + } + + void notifyContentChanged(Node &node, + Inkscape::Util::ptr_shared<char> /*old_value*/, + Inkscape::Util::ptr_shared<char> new_value) + { + if (new_value) { + g_warning("Event: Set content of %s to \"%s\"", node_to_string(node).c_str(), new_value.pointer()); + } else { + g_warning("Event: Unset content of %s", node_to_string(node).c_str()); + } + } }; } -void -sp_repr_debug_print_log(Inkscape::XML::Event const *log) { - Inkscape::XML::replay_log_to_observer(log, LogPrinter::instance()); +void sp_repr_debug_print_log(Inkscape::XML::Event const *log) { + Inkscape::XML::replay_log_to_observer(log, LogPrinter::instance()); } diff --git a/src/xml/helper-observer.cpp b/src/xml/helper-observer.cpp index ce902ba75..c54dd8e74 100644 --- a/src/xml/helper-observer.cpp +++ b/src/xml/helper-observer.cpp @@ -13,10 +13,16 @@ void SignalObserver::set(SPObject* o) { // XML Tree being used direcly in this function in the following code // while it shouldn't be - if(_oldsel && _oldsel->getRepr()) - _oldsel->getRepr()->removeObserver(*this); - if(o && o->getRepr()) - o->getRepr()->addObserver(*this); + if(_oldsel) { + if (_oldsel->getRepr()) { + _oldsel->getRepr()->removeObserver(*this); + } + } + if(o) { + if (o->getRepr()) { + o->getRepr()->addObserver(*this); + } + } _oldsel = o; } diff --git a/src/xml/node-fns.cpp b/src/xml/node-fns.cpp index 20e9fbc38..eb3870978 100644 --- a/src/xml/node-fns.cpp +++ b/src/xml/node-fns.cpp @@ -9,6 +9,7 @@ #include "xml/node-iterators.h" #include "util/find-if-before.h" +#include "node-fns.h" namespace Inkscape { namespace XML { diff --git a/src/xml/node.h b/src/xml/node.h index e83d8a7b7..c1977b0a8 100644 --- a/src/xml/node.h +++ b/src/xml/node.h @@ -19,6 +19,7 @@ #define SEEN_INKSCAPE_XML_NODE_H #include <glibmm/value.h> +#include <glibmm/ustring.h> #include "gc-anchored.h" #include "util/list.h" @@ -194,6 +195,7 @@ public: */ virtual void setContent(gchar const *value)=0; + //@{ /** * @brief Change an attribute of this node * @@ -204,7 +206,19 @@ public: * @param is_interactive Ignored */ virtual void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false)=0; - + + void setAttribute(char const *key, Glib::ustring const &value, bool is_interactive=false) + { + setAttribute(key, value.empty() ? NULL : value.c_str(), is_interactive); + } + + void setAttribute(Glib::ustring const &key, Glib::ustring const &value, bool is_interactive=false) + { + setAttribute( key.empty() ? NULL : key.c_str(), + value.empty() ? NULL : value.c_str(), is_interactive); + } + //@} + /** * @brief Directly set the integer GQuark code for the name of the node * diff --git a/src/xml/quote-test.h b/src/xml/quote-test.h index bd5c1f54c..bc01ec4e9 100644 --- a/src/xml/quote-test.h +++ b/src/xml/quote-test.h @@ -7,10 +7,7 @@ #include <cstring> #include <functional> -/* mental disclaims all responsibility for this evil idea for testing - static functions. The main disadvantages are that we retain any - #define's and `using' directives of the included file. */ -#include "quote.cpp" +#include "quote.h" class XmlQuoteTest : public CxxTest::TestSuite { diff --git a/src/xml/quote.cpp b/src/xml/quote.cpp index 51f9ffb97..02c12dfb0 100644 --- a/src/xml/quote.cpp +++ b/src/xml/quote.cpp @@ -13,22 +13,25 @@ #include <cstring> #include <glib.h> +#include "quote.h" /** \return strlen(xml_quote_strdup(\a val)) (without doing the malloc). * \pre val != NULL */ -static size_t +size_t xml_quoted_strlen(char const *val) { size_t ret = 0; - for (; *val != '\0'; val++) { - switch (*val) { - case '"': ret += sizeof(""") - 1; break; - case '&': ret += sizeof("&") - 1; break; - case '<': ret += sizeof("<") - 1; break; - case '>': ret += sizeof(">") - 1; break; - default: ++ret; break; + if (val != NULL) { + for (; *val != '\0'; val++) { + switch (*val) { + case '"': ret += sizeof(""") - 1; break; + case '&': ret += sizeof("&") - 1; break; + case '<': ret += sizeof("<") - 1; break; + case '>': ret += sizeof(">") - 1; break; + default: ++ret; break; + } } } return ret; @@ -42,11 +45,11 @@ xml_quoted_strlen(char const *val) static void xml_quote(char *dest, char const *src) { -#define COPY_LIT(_lit) do { \ - size_t cpylen = sizeof(_lit "") - 1; \ - memcpy(dest, _lit, cpylen); \ - dest += cpylen; \ - } while(0) +#define COPY_LIT(_lit) do { \ + size_t cpylen = sizeof(_lit "") - 1; \ + memcpy(dest, _lit, cpylen); \ + dest += cpylen; \ + } while(0) for (; *src != '\0'; ++src) { switch (*src) { diff --git a/src/xml/quote.h b/src/xml/quote.h index 597272cd3..8e3bca0eb 100644 --- a/src/xml/quote.h +++ b/src/xml/quote.h @@ -1,6 +1,9 @@ #ifndef SEEN_XML_QUOTE_H #define SEEN_XML_QUOTE_H +#include <stddef.h> + +size_t xml_quoted_strlen(char const *val); char *xml_quote_strdup(char const *src); diff --git a/src/xml/rebase-hrefs.h b/src/xml/rebase-hrefs.h index adb09e52a..5baf96516 100644 --- a/src/xml/rebase-hrefs.h +++ b/src/xml/rebase-hrefs.h @@ -4,7 +4,7 @@ #include <glib.h> #include "util/list.h" #include "xml/attribute-record.h" -struct SPDocument; +class SPDocument; namespace Inkscape { namespace XML { diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp index 19f3f1d6c..24e2db9e1 100644 --- a/src/xml/repr-css.cpp +++ b/src/xml/repr-css.cpp @@ -27,6 +27,7 @@ #include "xml/repr.h" #include "xml/simple-document.h" #include "xml/simple-node.h" +#include "xml/sp-css-attr.h" #include "style.h" #include "libcroco/cr-sel-eng.h" @@ -270,10 +271,9 @@ double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double def /** * Write a style attribute string from a list of properties stored in an SPCSAttr object. */ -gchar *sp_repr_css_write_string(SPCSSAttr *css) +void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str) { - Glib::ustring buffer; - + str.clear(); for ( List<AttributeRecord const> iter = css->attributeList() ; iter ; ++iter ) { @@ -281,28 +281,21 @@ gchar *sp_repr_css_write_string(SPCSSAttr *css) continue; } - buffer.append(g_quark_to_string(iter->key)); - buffer.push_back(':'); + str.append(g_quark_to_string(iter->key)); + str.push_back(':'); if (!strcmp(g_quark_to_string(iter->key), "font-family") || !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) { // we only quote font-family/font-specification, as SPStyle does - gchar *t = g_strdup (iter->value); - g_free (t); - gchar *val_quoted = css2_escape_quote (iter->value); - if (val_quoted) { - buffer.append(val_quoted); - g_free (val_quoted); - } + Glib::ustring val_quoted = css2_escape_quote (iter->value); + str.append(val_quoted); } else { - buffer.append(iter->value); // unquoted + str.append(iter->value); // unquoted } if (rest(iter)) { - buffer.push_back(';'); + str.push_back(';'); } } - - return (buffer.empty() ? NULL : g_strdup (buffer.c_str())); } /** @@ -314,17 +307,16 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr) g_assert(css != NULL); g_assert(attr != NULL); - gchar *value = sp_repr_css_write_string(css); + Glib::ustring value; + sp_repr_css_write_string(css, value); /* * If the new value is different from the old value, this will sometimes send a signal via * CompositeNodeObserver::notiftyAttributeChanged() which results in calling - * SPObject::sp_object_repr_attr_changed and thus updates the object's SPStyle. This update + * SPObject::repr_attr_changed and thus updates the object's SPStyle. This update * results in another call to repr->setAttribute(). */ - repr->setAttribute(attr, value); - - if (value) g_free (value); + repr->setAttribute(attr, value.c_str()); } /** @@ -360,12 +352,32 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con guchar *const str_value_unsigned = cr_term_to_string(decl->value); gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned); gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in "" + Glib::ustring value_unquoted2 = value_unquoted ? value_unquoted : Glib::ustring(); + Glib::ustring units; + + /* + * Problem with parsing of units em and ex, like font-size "1.2em" and "3.4ex" + * stringstream thinks they are in scientific "e" notation and fails + * Must be a better way using std::fixed, precision etc + * + * HACK for now is to strip off em and ex units and add them back at the end + */ + int le = value_unquoted2.length(); + if (le > 2) { + units = value_unquoted2.substr(le-2, 2); + if ((units == "em") || (units == "ex")) { + value_unquoted2 = value_unquoted2.substr(0, le-2); + } + else { + units.clear(); + } + } // libcroco uses %.17f for formatting... leading to trailing zeros or small rounding errors. // CSSOStringStream is used here to write valid CSS (as in sp_style_write_string). This has // the additional benefit of respecting the numerical precission set in the SVG Output // preferences. We assume any numerical part comes first (if not, the whole string is copied). - std::stringstream ss( value_unquoted ); + std::stringstream ss( value_unquoted2 ); double number = 0; std::string characters; std::string temp; @@ -379,6 +391,10 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con Inkscape::CSSOStringStream os; if( number_valid ) os << number; os << characters; + if (!units.empty()) { + os << units; + //g_message("sp_repr_css_merge_from_decl looks like em or ex units %s --> %s", str_value, os.str().c_str()); + } ((Node *) css)->setAttribute(decl->property->stryng->str, os.str().c_str(), false); g_free(value_unquoted); g_free(str_value); diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index b85e58899..0319bb5e3 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -37,6 +37,8 @@ #include "preferences.h" +#include <glibmm/miscutils.h> + using Inkscape::IO::Writer; using Inkscape::Util::List; using Inkscape::Util::cons; @@ -76,11 +78,14 @@ public: XmlSource() : filename(0), encoding(0), - fp(0), + fp(NULL), firstFewLen(0), + LoadEntities(false), + cachedData(), + cachedPos(0), dummy("x"), - instr(0), - gzin(0) + instr(NULL), + gzin(NULL) { for (int k=0;k<4;k++) { @@ -96,7 +101,9 @@ public: } } - int setFile( char const * filename ); + int setFile( char const * filename, bool load_entities ); + + xmlDocPtr readXml(); static int readCb( void * context, char * buffer, int len ); static int closeCb( void * context ); @@ -110,12 +117,15 @@ private: FILE* fp; unsigned char firstFew[4]; int firstFewLen; + bool LoadEntities; // Checks for SYSTEM Entities (requires cached data) + std::string cachedData; + unsigned int cachedPos; Inkscape::URI dummy; Inkscape::IO::UriInputStream* instr; Inkscape::IO::GzipInputStream* gzin; }; -int XmlSource::setFile(char const *filename) +int XmlSource::setFile(char const *filename, bool load_entities=false) { int retVal = -1; @@ -172,14 +182,62 @@ int XmlSource::setFile(char const *filename) retVal = 0; // no error } } + if(load_entities) { + this->cachedData = std::string(""); + this->cachedPos = 0; + + // First get data from file in typical way (cache it all) + char *buffer = new char [4096]; + while(true) { + int len = this->read(buffer, 4096); + if(len <= 0) break; + buffer[len] = 0; + this->cachedData += buffer; + } + delete[] buffer; + + // Check for SYSTEM or PUBLIC entities and remove them from the cache + GMatchInfo *info; + gint start, end; + GRegex *regex = g_regex_new( + "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>", + G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL); + + g_regex_match (regex, this->cachedData.c_str(), G_REGEX_MATCH_NEWLINE_ANY, &info); + + while (g_match_info_matches (info)) { + if (g_match_info_fetch_pos (info, 1, &start, &end)) + this->cachedData.erase(start, end - start); + g_match_info_next (info, NULL); + } + g_match_info_free(info); + g_regex_unref(regex); + } + // Do this after loading cache, so reads don't return cache to fill cache. + this->LoadEntities = load_entities; return retVal; } +xmlDocPtr XmlSource::readXml() +{ + int parse_options = XML_PARSE_HUGE | XML_PARSE_RECOVER; + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false); + if (!allowNetAccess) parse_options |= XML_PARSE_NONET; + + // Allow NOENT only if we're filtering out SYSTEM and PUBLIC entities + if (LoadEntities) parse_options |= XML_PARSE_NOENT; + + return xmlReadIO( readCb, closeCb, this, + filename, getEncoding(), parse_options); +} int XmlSource::readCb( void * context, char * buffer, int len ) { int retVal = -1; + if ( context ) { XmlSource* self = static_cast<XmlSource*>(context); retVal = self->read( buffer, len ); @@ -201,7 +259,15 @@ int XmlSource::read( char *buffer, int len ) int retVal = 0; size_t got = 0; - if ( firstFewLen > 0 ) { + if ( LoadEntities ) { + if (cachedPos >= cachedData.length()) { + return -1; + } else { + retVal = cachedData.copy(buffer, len, cachedPos); + cachedPos += retVal; + return retVal; // Do NOT continue. + } + } else if ( firstFewLen > 0 ) { int some = (len < firstFewLen) ? len : firstFewLen; memcpy( buffer, firstFew, some ); if ( len < firstFewLen ) { @@ -268,7 +334,10 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns) xmlSubstituteEntitiesDefault(1); g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS ), NULL); + if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) { + g_warning("Can't open file: %s (doesn't exist)", filename); + return NULL; + } /* fixme: A file can disappear at any time, including between now and when we actually try to * open it. Get rid of the above test once we're sure that we correctly handle * non-existence. */ @@ -297,16 +366,20 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns) XmlSource src; if ( (src.setFile(filename) == 0) ) { - doc = xmlReadIO( XmlSource::readCb, - XmlSource::closeCb, - &src, - localFilename, - src.getEncoding(), - XML_PARSE_NOENT | XML_PARSE_HUGE); + doc = src.readXml(); + rdoc = sp_repr_do_read( doc, default_ns ); + // For some reason, failed ns loading results in this + // We try a system check version of load with NOENT for adobe + if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) { + xmlFreeDoc( doc ); + src.setFile(filename, true); + doc = src.readXml(); + rdoc = sp_repr_do_read( doc, default_ns ); + } } } - rdoc = sp_repr_do_read( doc, default_ns ); + if ( doc ) { xmlFreeDoc( doc ); } @@ -471,13 +544,19 @@ Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns) gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar */*default_ns*/, GHashTable *prefix_map) { const xmlChar *prefix; - if ( ns && ns->href ) { - prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href), - reinterpret_cast<const char*>(ns->prefix)) ); - void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix)); - void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href)); - g_hash_table_insert( prefix_map, p0, p1 ); - } else { + if (ns){ + if (ns->href ) { + prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href), + reinterpret_cast<const char*>(ns->prefix)) ); + void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix)); + void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href)); + g_hash_table_insert( prefix_map, p0, p1 ); + } + else { + prefix = NULL; + } + } + else { prefix = NULL; } @@ -490,7 +569,6 @@ gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *nam static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, GHashTable *prefix_map) { - Node *repr, *crepr; xmlAttrPtr prop; xmlNodePtr child; gchar c[256]; @@ -530,7 +608,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc } sp_repr_qualified_name (c, 256, node->ns, node->name, default_ns, prefix_map); - repr = xml_doc->createElement(c); + Node *repr = xml_doc->createElement(c); /* TODO remember node->ns->prefix if node->ns != NULL */ for (prop = node->properties; prop != NULL; prop = prop->next) { @@ -547,7 +625,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc child = node->xmlChildrenNode; for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map); + Node *crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map); if (crepr) { repr->appendChild(crepr); Inkscape::GC::release(crepr); @@ -600,10 +678,10 @@ Glib::ustring sp_repr_save_buf(Document *doc) sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI, 0, 0); - outs.close(); - Glib::ustring buf = souts.getString(); + outs.close(); + Glib::ustring buf = souts.getString(); - return buf; + return buf; } @@ -934,15 +1012,15 @@ void sp_repr_write_stream_element( Node * repr, Writer & out, // THIS DOESN'T APPEAR TO DO ANYTHING. Can it be commented out or deleted? { GQuark const href_key = g_quark_from_static_string("xlink:href"); - GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); + //GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); gchar const *xxHref = 0; - gchar const *xxAbsref = 0; + //gchar const *xxAbsref = 0; for ( List<AttributeRecord const> ai(attributes); ai; ++ai ) { if ( ai->key == href_key ) { xxHref = ai->value; - } else if ( ai->key == absref_key ) { - xxAbsref = ai->value; + //} else if ( ai->key == absref_key ) { + //xxAbsref = ai->value; } } diff --git a/src/xml/repr-sorting.cpp b/src/xml/repr-sorting.cpp index 056236d33..09a39acb2 100644 --- a/src/xml/repr-sorting.cpp +++ b/src/xml/repr-sorting.cpp @@ -2,6 +2,7 @@ #include "util/longest-common-suffix.h" #include "xml/repr.h" #include "xml/node-iterators.h" +#include "repr-sorting.h" static bool same_repr(Inkscape::XML::Node const &a, Inkscape::XML::Node const &b) { @@ -13,9 +14,14 @@ Inkscape::XML::Node const *LCA(Inkscape::XML::Node const *a, Inkscape::XML::Node { using Inkscape::Algorithms::longest_common_suffix; Inkscape::XML::Node const *ancestor = longest_common_suffix<Inkscape::XML::NodeConstParentIterator>( - a, b, NULL, &same_repr - ); - if ( ancestor && ancestor->type() != Inkscape::XML::DOCUMENT_NODE ) { + a, b, NULL, &same_repr); + bool OK = false; + if (ancestor) { + if (ancestor->type() != Inkscape::XML::DOCUMENT_NODE) { + OK = true; + } + } + if ( OK ) { return ancestor; } else { return NULL; diff --git a/src/xml/repr-util.cpp b/src/xml/repr-util.cpp index 6899e77ee..12280ea5a 100644 --- a/src/xml/repr-util.cpp +++ b/src/xml/repr-util.cpp @@ -69,71 +69,6 @@ static void sp_xml_ns_register_defaults(); static char *sp_xml_ns_auto_prefix(char const *uri); /*##################### -# UTILITY -#####################*/ - -/** - * Locale-independent double to string conversion - */ -unsigned int sp_xml_dtoa(gchar *buf, double val, unsigned int tprec, unsigned int fprec, unsigned int padf) -{ - double dival, fval, epsilon; - int idigits, ival, i; - i = 0; - if (val < 0.0) { - buf[i++] = '-'; - val = -val; - } - /* Determine number of integral digits */ - if (val >= 1.0) { - idigits = (int) floor(log10(val)); - } else { - idigits = 0; - } - /* Determine the actual number of fractional digits */ - fprec = MAX(fprec, tprec - idigits); - /* Find epsilon */ - epsilon = 0.5 * pow(10.0, - (double) fprec); - /* Round value */ - val += epsilon; - /* Extract integral and fractional parts */ - dival = floor(val); - ival = (int) dival; - fval = val - dival; - /* Write integra */ - if (ival > 0) { - char c[32]; - int j; - j = 0; - while (ival > 0) { - c[32 - (++j)] = '0' + (ival % 10); - ival /= 10; - } - memcpy(buf + i, &c[32 - j], j); - i += j; - tprec -= j; - } else { - buf[i++] = '0'; - tprec -= 1; - } - if ((fprec > 0) && (padf || (fval > epsilon))) { - buf[i++] = '.'; - while ((fprec > 0) && (padf || (fval > epsilon))) { - fval *= 10.0; - dival = floor(fval); - fval -= dival; - buf[i++] = '0' + (int) dival; - fprec -= 1; - } - - } - buf[i] = 0; - return i; -} - - - -/*##################### # MAIN #####################*/ @@ -261,8 +196,13 @@ gchar const *sp_xml_ns_uri_prefix(gchar const *uri, gchar const *suggested) GQuark const prefix_key=g_quark_from_string(suggested); SPXMLNs *found=namespaces; - while ( found && found->prefix != prefix_key ) { - found = found->next; + while (found) { + if (found->prefix != prefix_key) { + found = found->next; + } + else { + break; + } } if (found) { // prefix already used? @@ -492,13 +432,11 @@ unsigned int sp_repr_get_int(Inkscape::XML::Node *repr, gchar const *key, int *v unsigned int sp_repr_get_double(Inkscape::XML::Node *repr, gchar const *key, double *val) { - gchar const *v; - g_return_val_if_fail(repr != NULL, FALSE); g_return_val_if_fail(key != NULL, FALSE); g_return_val_if_fail(val != NULL, FALSE); - v = repr->attribute(key); + gchar const *v = repr->attribute(key); if (v != NULL) { *val = g_ascii_strtod(v, NULL); @@ -584,6 +522,8 @@ unsigned int sp_repr_get_point(Inkscape::XML::Node *repr, gchar const *key, Geom gchar const *v = repr->attribute(key); + g_return_val_if_fail(v != NULL, FALSE); + gchar ** strarray = g_strsplit(v, ",", 2); if (strarray && strarray[0] && strarray[1]) { diff --git a/src/xml/repr.h b/src/xml/repr.h index 86a798e3e..e691eaa7f 100644 --- a/src/xml/repr.h +++ b/src/xml/repr.h @@ -14,16 +14,11 @@ #ifndef SEEN_SP_REPR_H #define SEEN_SP_REPR_H -#include <stdio.h> #include <glib.h> -#include "gc-anchored.h" +#include <glibmm/quark.h> #include "xml/node.h" #include "xml/document.h" -#include "xml/sp-css-attr.h" -#include "io/inkscapestream.h" - -#include <2geom/forward.h> #define SP_SODIPODI_NS_URI "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" #define SP_BROKEN_SODIPODI_NS_URI "http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" @@ -35,6 +30,18 @@ #define SP_OLD_CC_NS_URI "http://web.resource.org/cc/" #define SP_DC_NS_URI "http://purl.org/dc/elements/1.1/" +class SPCSSAttr; + +namespace Inkscape { +namespace IO { +class Writer; +} // namespace IO +} // namespace Inkscape + +namespace Geom { +class Point; +} + /* SPXMLNs */ char const *sp_xml_ns_uri_prefix(gchar const *uri, gchar const *suggested); char const *sp_xml_ns_prefix_uri(gchar const *prefix); @@ -79,7 +86,7 @@ void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name); bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name); double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval); -gchar *sp_repr_css_write_string(SPCSSAttr *css); +void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str); void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key); void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src); void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const gchar *data); @@ -91,9 +98,11 @@ void sp_repr_css_print(SPCSSAttr *css); /* Utility finctions */ /// Remove \a repr from children of its parent node. inline void sp_repr_unparent(Inkscape::XML::Node *repr) { - Inkscape::XML::Node *parent=repr->parent(); - if (parent) { - parent->removeChild(repr); + if (repr) { + Inkscape::XML::Node *parent=repr->parent(); + if (parent) { + parent->removeChild(repr); + } } } diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp index c197d648b..4965f81c8 100644 --- a/src/xml/simple-node.cpp +++ b/src/xml/simple-node.cpp @@ -318,8 +318,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ // Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree. Glib::ustring element = g_quark_to_string(_name); - //g_warning("setAttribute: %s: %s: %s", element.c_str(), name, value); - + // g_message("setAttribute: %s: %s: %s", element.c_str(), name, value); gchar* cleaned_value = g_strdup( value ); // Only check elements in SVG name space and don't block setting attribute to NULL. @@ -347,7 +346,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ // tree (and thus has no parent), default values will not be tested. if( !strcmp( name, "style" ) && (flags >= SP_ATTR_CLEAN_STYLE_WARN) ) { g_free( cleaned_value ); - cleaned_value = sp_attribute_clean_style( this, value, flags ); + cleaned_value = g_strdup( sp_attribute_clean_style( this, value, flags ).c_str() ); // if( g_strcmp0( value, cleaned_value ) ) { // g_warning( "SimpleNode::setAttribute: %s", id.c_str() ); // g_warning( " original: %s", value); @@ -401,9 +400,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ _observers.notifyAttributeChanged(*this, key, old_value, new_value); //g_warning( "setAttribute notified: %s: %s: %s: %s", name, element.c_str(), old_value, new_value ); } - g_free( cleaned_value ); - } void SimpleNode::addChild(Node *generic_child, Node *generic_ref) { |
