summaryrefslogtreecommitdiffstats
path: root/src/sp-object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp-object.cpp')
-rw-r--r--src/sp-object.cpp187
1 files changed, 77 insertions, 110 deletions
diff --git a/src/sp-object.cpp b/src/sp-object.cpp
index 9cb386026..0cd7b371e 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -7,8 +7,9 @@
* Stephen Silver <sasilver@users.sourceforge.net>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
+ * Adrian Boguszewski
*
- * Copyright (C) 1999-2008 authors
+ * Copyright (C) 1999-2016 authors
* Copyright (C) 2001-2002 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
@@ -16,6 +17,7 @@
#include <cstring>
#include <string>
+#include <boost/range/adaptor/transformed.hpp>
#include "helper/sp-marshal.h"
#include "xml/node-event-vector.h"
@@ -114,8 +116,7 @@ static gchar *sp_object_get_unique_id(SPObject *object,
*/
SPObject::SPObject()
: cloned(0), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0),
- document(NULL), parent(NULL), children(NULL), _last_child(NULL),
- next(NULL), id(NULL), repr(NULL), refCount(1),hrefList(std::list<SPObject*>()),
+ document(NULL), parent(NULL), id(NULL), repr(NULL), refCount(1), hrefList(std::list<SPObject*>()),
_successor(NULL), _collection_policy(SPObject::COLLECT_WITH_PARENT),
_label(NULL), _default_label(NULL)
{
@@ -148,6 +149,9 @@ SPObject::~SPObject() {
sp_object_unref(this->_successor, NULL);
this->_successor = NULL;
}
+ if (parent) {
+ parent->children.erase(parent->children.iterator_to(*this));
+ }
if( style == NULL ) {
// style pointer could be NULL if unreffed too many times.
@@ -396,13 +400,12 @@ void SPObject::changeCSS(SPCSSAttr *css, gchar const *attr)
}
std::vector<SPObject*> SPObject::childList(bool add_ref, Action) {
- std::vector<SPObject*> l;
- for ( SPObject *child = firstChild() ; child; child = child->getNext() ) {
+ std::vector<SPObject*> l;
+ for (auto& child: children) {
if (add_ref) {
- sp_object_ref (child);
+ sp_object_ref(&child);
}
-
- l.push_back(child);
+ l.push_back(&child);
}
return l;
@@ -465,9 +468,9 @@ void SPObject::requestOrphanCollection() {
}
void SPObject::_sendDeleteSignalRecursive() {
- for (SPObject *child = firstChild(); child; child = child->getNext()) {
- child->_delete_signal.emit(child);
- child->_sendDeleteSignalRecursive();
+ for (auto& child: children) {
+ child._delete_signal.emit(&child);
+ child._sendDeleteSignalRecursive();
}
}
@@ -495,12 +498,12 @@ void SPObject::deleteObject(bool propagate, bool propagate_descendants)
void SPObject::cropToObject(SPObject *except)
{
std::vector<SPObject*> toDelete;
- for ( SPObject *child = this->firstChild(); child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
- if (child->isAncestorOf(except)) {
- child->cropToObject(except);
- } else if(child != except) {
- toDelete.push_back(child);
+ for (auto& child: children) {
+ if (SP_IS_ITEM(&child)) {
+ if (child.isAncestorOf(except)) {
+ child.cropToObject(except);
+ } else if(&child != except) {
+ toDelete.push_back(&child);
}
}
}
@@ -523,60 +526,29 @@ void SPObject::attach(SPObject *object, SPObject *prev)
object->parent = this;
this->_updateTotalHRefCount(object->_total_hrefcount);
- SPObject *next;
- if (prev) {
- next = prev->next;
- prev->next = object;
- } else {
- next = this->children;
- this->children = object;
- }
- object->next = next;
- if (!next) {
- this->_last_child = object;
+ auto it = children.begin();
+ if (prev != nullptr) {
+ it = ++children.iterator_to(*prev);
}
+ children.insert(it, *object);
+
if (!object->xml_space.set)
object->xml_space.value = this->xml_space.value;
}
-void SPObject::reorder(SPObject *prev)
-{
- //g_return_if_fail(object != NULL);
- //g_return_if_fail(SP_IS_OBJECT(object));
- g_return_if_fail(this->parent != NULL);
- g_return_if_fail(this != prev);
- g_return_if_fail(!prev || SP_IS_OBJECT(prev));
- g_return_if_fail(!prev || prev->parent == this->parent);
-
- SPObject *const parent=this->parent;
+void SPObject::reorder(SPObject* obj, SPObject* prev) {
+ g_return_if_fail(obj != nullptr);
+ g_return_if_fail(obj->parent);
+ g_return_if_fail(obj->parent == this);
+ g_return_if_fail(obj != prev);
+ g_return_if_fail(!prev || prev->parent == obj->parent);
- SPObject *old_prev=NULL;
- for ( SPObject *child = parent->children ; child && child != this ;
- child = child->next )
- {
- old_prev = child;
+ auto it = children.begin();
+ if (prev != nullptr) {
+ it = ++children.iterator_to(*prev);
}
- SPObject *next=this->next;
- if (old_prev) {
- old_prev->next = next;
- } else {
- parent->children = next;
- }
- if (!next) {
- parent->_last_child = old_prev;
- }
- if (prev) {
- next = prev->next;
- prev->next = this;
- } else {
- next = parent->children;
- parent->children = this;
- }
- this->next = next;
- if (!next) {
- parent->_last_child = this;
- }
+ children.splice(it, children, children.iterator_to(*obj));
}
void SPObject::detach(SPObject *object)
@@ -587,26 +559,9 @@ void SPObject::detach(SPObject *object)
g_return_if_fail(SP_IS_OBJECT(object));
g_return_if_fail(object->parent == this);
+ children.erase(children.iterator_to(*object));
object->releaseReferences();
- SPObject *prev=NULL;
- for ( SPObject *child = this->children ; child && child != object ;
- child = child->next )
- {
- prev = child;
- }
-
- SPObject *next=object->next;
- if (prev) {
- prev->next = next;
- } else {
- this->children = next;
- }
- if (!next) {
- this->_last_child = prev;
- }
-
- object->next = NULL;
object->parent = NULL;
this->_updateTotalHRefCount(-object->_total_hrefcount);
@@ -616,14 +571,14 @@ void SPObject::detach(SPObject *object)
SPObject *SPObject::get_child_by_repr(Inkscape::XML::Node *repr)
{
g_return_val_if_fail(repr != NULL, NULL);
- SPObject *result = 0;
+ SPObject *result = nullptr;
- if ( _last_child && (_last_child->getRepr() == repr) ) {
- result = _last_child; // optimization for common scenario
+ if (children.size() > 0 && children.back().getRepr() == repr) {
+ result = &children.back(); // optimization for common scenario
} else {
- for ( SPObject *child = children ; child ; child = child->next ) {
- if ( child->getRepr() == repr ) {
- result = child;
+ for (auto& child: children) {
+ if (child.getRepr() == repr) {
+ result = &child;
break;
}
}
@@ -654,10 +609,12 @@ void SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
void SPObject::release() {
SPObject* object = this;
-
debug("id=%p, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object));
- while (object->children) {
- object->detach(object->children);
+ auto tmp = children | boost::adaptors::transformed([](SPObject& obj){return &obj;});
+ std::vector<SPObject *> toRelease(tmp.begin(), tmp.end());
+
+ for (auto& p: toRelease) {
+ object->detach(p);
}
}
@@ -678,7 +635,7 @@ void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * /
SPObject *ochild = object->get_child_by_repr(child);
g_return_if_fail(ochild != NULL);
SPObject *prev = new_ref ? object->get_child_by_repr(new_ref) : NULL;
- ochild->reorder(prev);
+ object->reorder(ochild, prev);
ochild->_position_changed_signal.emit(ochild);
}
@@ -840,15 +797,22 @@ void SPObject::releaseReferences() {
SPObject *SPObject::getPrev()
{
- SPObject *prev = 0;
- for ( SPObject *obj = parent->firstChild(); obj && !prev; obj = obj->getNext() ) {
- if (obj->getNext() == this) {
- prev = obj;
- }
+ SPObject *prev = nullptr;
+ if (parent && !parent->children.empty() && &parent->children.front() != this) {
+ prev = &*(--parent->children.iterator_to(*this));
}
return prev;
}
+SPObject* SPObject::getNext()
+{
+ SPObject *next = nullptr;
+ if (parent && !parent->children.empty() && &parent->children.back() != this) {
+ next = &*(++parent->children.iterator_to(*this));
+ }
+ return next;
+}
+
void SPObject::repr_child_added(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data)
{
SPObject *object = SP_OBJECT(data);
@@ -1512,8 +1476,11 @@ bool SPObject::setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool
}
else {
// remove the current content of the 'text' or 'desc' element
- SPObject *child;
- while (NULL != (child = elem->firstChild())) child->deleteObject();
+ auto tmp = elem->children | boost::adaptors::transformed([](SPObject& obj) { return &obj; });
+ std::vector<SPObject*> vec(tmp.begin(), tmp.end());
+ for (auto &child: vec) {
+ child->deleteObject();
+ }
}
// add the new content
@@ -1521,33 +1488,33 @@ bool SPObject::setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool
return true;
}
-SPObject * SPObject::findFirstChild(gchar const *tagname) const
+SPObject* SPObject::findFirstChild(gchar const *tagname) const
{
- for (SPObject *child = children; child; child = child->next)
+ for (auto& child: const_cast<SPObject*>(this)->children)
{
- if (child->repr->type() == Inkscape::XML::ELEMENT_NODE &&
- !strcmp(child->repr->name(), tagname)) {
- return child;
+ if (child.repr->type() == Inkscape::XML::ELEMENT_NODE &&
+ !strcmp(child.repr->name(), tagname)) {
+ return &child;
}
}
- return NULL;
+ return nullptr;
}
char* SPObject::textualContent() const
{
GString* text = g_string_new("");
- for (const SPObject *child = firstChild(); child; child = child->next)
+ for (auto& child: children)
{
- Inkscape::XML::NodeType child_type = child->repr->type();
+ Inkscape::XML::NodeType child_type = child.repr->type();
if (child_type == Inkscape::XML::ELEMENT_NODE) {
- char* new_string = child->textualContent();
+ char* new_string = child.textualContent();
g_string_append(text, new_string);
g_free(new_string);
}
else if (child_type == Inkscape::XML::TEXT_NODE) {
- g_string_append(text, child->repr->content());
+ g_string_append(text, child.repr->content());
}
}
return g_string_free(text, FALSE);
@@ -1564,8 +1531,8 @@ void SPObject::recursivePrintTree( unsigned level )
std::cout << " ";
}
std::cout << (getId()?getId():"No object id") << std::endl;
- for (SPObject *child = children; child; child = child->next) {
- child->recursivePrintTree( level+1 );
+ for (auto& child: children) {
+ child.recursivePrintTree(level + 1);
}
}