X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-object.cpp;h=5e011bd046dce8ccde3ecf4f00011dc8d5a9f7a2;hb=2c9c6838241516364d68db0d30520e18f70fc70d;hp=f97007b5140afeea94db994886676cdeb766777b;hpb=420d49b61e68ada5f9029ca1e84d987e8846228f;p=inkscape.git diff --git a/src/sp-object.cpp b/src/sp-object.cpp index f97007b51..5e011bd04 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -13,7 +13,7 @@ */ /** \class SPObject - * + * * SPObject is an abstract base class of all of the document nodes at the * SVG document level. Each SPObject subclass implements a certain SVG * element node type, or is an abstract base class for different node @@ -44,6 +44,10 @@ #include "xml/repr.h" #include "xml/node-fns.h" #include "debug/event-tracker.h" +#include "debug/simple-event.h" +#include "debug/demangle.h" +#include "util/share.h" +#include "util/format.h" #include "algorithms/longest-common-suffix.h" using std::memcpy; @@ -192,6 +196,7 @@ sp_object_init(SPObject *object) object->_collection_policy = SPObject::COLLECT_WITH_PARENT; new (&object->_delete_signal) sigc::signal(); + new (&object->_position_changed_signal) sigc::signal(); object->_successor = NULL; object->_label = NULL; @@ -221,58 +226,39 @@ sp_object_finalize(GObject *object) } spobject->_delete_signal.~signal(); + spobject->_position_changed_signal.~signal(); } namespace { -Inkscape::Util::shared_ptr stringify(SPObject *obj) { - char *temp=g_strdup_printf("%p", obj); - Inkscape::Util::shared_ptr result=Inkscape::Util::share_string(temp); - g_free(temp); - return result; -} +namespace Debug = Inkscape::Debug; +namespace Util = Inkscape::Util; -Inkscape::Util::shared_ptr stringify(unsigned n) { - char *temp=g_strdup_printf("%u", n); - Inkscape::Util::shared_ptr result=Inkscape::Util::share_string(temp); - g_free(temp); - return result; -} +typedef Debug::SimpleEvent BaseRefCountEvent; -class RefEvent : public Inkscape::Debug::Event { +class RefCountEvent : public BaseRefCountEvent { public: - enum Type { REF, UNREF }; + RefCountEvent(SPObject *object, int bias, Util::ptr_shared name) + : BaseRefCountEvent(name) + { + _addProperty("object", Util::format("%p", object)); + _addProperty("class", Debug::demangle(g_type_name(G_TYPE_FROM_INSTANCE(object)))); + _addProperty("new-refcount", Util::format("%d", G_OBJECT(object)->ref_count + bias)); + } +}; - RefEvent(SPObject *object, Type type) - : _object(stringify(object)), _refcount(G_OBJECT(object)->ref_count), - _type(type) +class RefEvent : public RefCountEvent { +public: + RefEvent(SPObject *object) + : RefCountEvent(object, 1, Util::share_static_string("sp-object-ref")) {} +}; - static Category category() { return REFCOUNT; } - - Inkscape::Util::shared_ptr name() const { - if ( _type == REF) { - return Inkscape::Util::share_static_string("sp-object-ref"); - } else { - return Inkscape::Util::share_static_string("sp-object-unref"); - } - } - unsigned propertyCount() const { return 2; } - PropertyPair property(unsigned index) const { - switch (index) { - case 0: - return PropertyPair("object", _object); - case 1: - return PropertyPair("refcount", stringify( _type == REF ? _refcount + 1 : _refcount - 1 )); - default: - return PropertyPair(); - } - } - -private: - Inkscape::Util::shared_ptr _object; - unsigned _refcount; - Type _type; +class UnrefEvent : public RefCountEvent { +public: + UnrefEvent(SPObject *object) + : RefCountEvent(object, -1, Util::share_static_string("sp-object-unref")) + {} }; } @@ -291,11 +277,8 @@ sp_object_ref(SPObject *object, SPObject *owner) g_return_val_if_fail(SP_IS_OBJECT(object), NULL); g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL); - Inkscape::Debug::EventTracker<> tracker; - tracker.set(object, RefEvent::REF); - + Inkscape::Debug::EventTracker tracker(object); g_object_ref(G_OBJECT(object)); - return object; } @@ -314,11 +297,8 @@ sp_object_unref(SPObject *object, SPObject *owner) g_return_val_if_fail(SP_IS_OBJECT(object), NULL); g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL); - Inkscape::Debug::EventTracker<> tracker; - tracker.set(object, RefEvent::UNREF); - + Inkscape::Debug::EventTracker tracker(object); g_object_unref(G_OBJECT(object)); - return NULL; } @@ -327,7 +307,7 @@ sp_object_unref(SPObject *object, SPObject *owner) * * Hrefcount is used for weak references, for example, to * determine whether any graphical element references a certain gradient - * node. + * node. * \param owner Ignored. * \return object, NULL is error * \pre object points to real object @@ -347,7 +327,7 @@ sp_object_href(SPObject *object, gpointer owner) /** * Decrease weak refcount. * - * Hrefcount is used for weak references, for example, to determine whether + * Hrefcount is used for weak references, for example, to determine whether * any graphical element references a certain gradient node. * \param owner Ignored. * \return always NULL @@ -369,7 +349,7 @@ sp_object_hunref(SPObject *object, gpointer owner) /** * Adds increment to _total_hrefcount of object and its parents. */ -void +void SPObject::_updateTotalHRefCount(int increment) { SPObject *topmost_collectable = NULL; for ( SPObject *iter = this ; iter ; iter = SP_OBJECT_PARENT(iter) ) { @@ -391,7 +371,7 @@ SPObject::_updateTotalHRefCount(int increment) { /** * True if object is non-NULL and this is some in/direct parent of object. */ -bool +bool SPObject::isAncestorOf(SPObject const *object) const { g_return_val_if_fail(object != NULL, false); object = SP_OBJECT_PARENT(object); @@ -433,8 +413,8 @@ SPObject const *AncestorSon(SPObject const *obj, SPObject const *ancestor) { /** * Compares height of objects in tree. - * - * Works for different-parent objects, so long as they have a common ancestor. + * + * Works for different-parent objects, so long as they have a common ancestor. * \return \verbatim * 0 positions are equivalent * 1 first object's position is greater than the second @@ -505,33 +485,33 @@ SPObject::defaultLabel() const { } /** Sets the label property for the object */ -void +void SPObject::setLabel(gchar const *label) { SP_OBJECT_REPR(this)->setAttribute("inkscape:label", label, false); } /** Queues the object for orphan collection */ -void +void SPObject::requestOrphanCollection() { g_return_if_fail(document != NULL); document->queueForOrphanCollection(this); /** \todo - * This is a temporary hack added to make fill&stroke rebuild its - * gradient list when the defs are vacuumed. gradient-vector.cpp - * listens to the modified signal on defs, and now we give it that + * This is a temporary hack added to make fill&stroke rebuild its + * gradient list when the defs are vacuumed. gradient-vector.cpp + * listens to the modified signal on defs, and now we give it that * signal. Mental says that this should be made automatic by - * merging SPObjectGroup with SPObject; SPObjectGroup would issue - * this signal automatically. Or maybe just derive SPDefs from + * merging SPObjectGroup with SPObject; SPObjectGroup would issue + * this signal automatically. Or maybe just derive SPDefs from * SPObjectGroup? */ - + this->requestModified(SP_OBJECT_CHILD_MODIFIED_FLAG); } /** Sends the delete signal to all children of this object recursively */ -void +void SPObject::_sendDeleteSignalRecursive() { for (SPObject *child = sp_object_first_child(this); child; child = SP_OBJECT_NEXT(child)) { child->_delete_signal.emit(child); @@ -541,12 +521,12 @@ SPObject::_sendDeleteSignalRecursive() { /** * Deletes the object reference, unparenting it from its parent. - * + * * If the \a propagate parameter is set to true, it emits a delete * signal. If the \a propagate_descendants parameter is true, it * recursively sends the delete signal to children. */ -void +void SPObject::deleteObject(bool propagate, bool propagate_descendants) { sp_object_ref(this, NULL); @@ -606,7 +586,7 @@ sp_object_attach(SPObject *parent, SPObject *object, SPObject *prev) /** * In list of object's siblings, move object behind prev. */ -void +void sp_object_reorder(SPObject *object, SPObject *prev) { g_return_if_fail(object != NULL); g_return_if_fail(SP_IS_OBJECT(object)); @@ -649,7 +629,7 @@ sp_object_reorder(SPObject *object, SPObject *prev) { /** * Remove object from parent's children, release and unref it. */ -void +void sp_object_detach(SPObject *parent, SPObject *object) { g_return_if_fail(parent != NULL); g_return_if_fail(SP_IS_OBJECT(parent)); @@ -657,6 +637,8 @@ sp_object_detach(SPObject *parent, SPObject *object) { g_return_if_fail(SP_IS_OBJECT(object)); g_return_if_fail(object->parent == parent); + sp_object_invoke_release(object); + SPObject *prev=NULL; for ( SPObject *child = parent->children ; child && child != object ; child = child->next ) @@ -677,7 +659,6 @@ sp_object_detach(SPObject *parent, SPObject *object) { object->next = NULL; object->parent = NULL; - sp_object_invoke_release(object); parent->_updateTotalHRefCount(-object->_total_hrefcount); sp_object_unref(object, parent); } @@ -707,7 +688,7 @@ sp_object_get_child_by_repr(SPObject *object, Inkscape::XML::Node *repr) * Callback for child_added event. * Invoked whenever the given mutation event happens in the XML tree. */ -static void +static void sp_object_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref) { GType type = sp_repr_type_lookup(child); @@ -742,14 +723,14 @@ static void sp_object_release(SPObject *object) } /** - * Remove object's child whose node equals repr, release and + * Remove object's child whose node equals repr, release and * unref it. * * Invoked whenever the given mutation event happens in the XML - * tree, BEFORE removal from the XML tree happens, so grouping + * tree, BEFORE removal from the XML tree happens, so grouping * objects can safely release the child data. */ -static void +static void sp_object_remove_child(SPObject *object, Inkscape::XML::Node *child) { debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); @@ -759,7 +740,7 @@ sp_object_remove_child(SPObject *object, Inkscape::XML::Node *child) } /** - * Move object corresponding to child after sibling object corresponding + * Move object corresponding to child after sibling object corresponding * to new_ref. * Invoked whenever the given mutation event happens in the XML tree. * \param old_ref Ignored @@ -771,11 +752,12 @@ static void sp_object_order_changed(SPObject *object, Inkscape::XML::Node *child g_return_if_fail(ochild != NULL); SPObject *prev = new_ref ? sp_object_get_child_by_repr(object, new_ref) : NULL; sp_object_reorder(ochild, prev); + ochild->_position_changed_signal.emit(ochild); } /** * Virtual build callback. - * + * * This has to be invoked immediately after creation of an SPObject. The * frontend method ensures that the new object is properly attached to * the document and repr; implementation then will parse all of the attributes, @@ -867,9 +849,6 @@ sp_object_invoke_release(SPObject *object) g_assert(object != NULL); g_assert(SP_IS_OBJECT(object)); - // we need to remember our parent - // g_assert(!object->parent); - g_assert(!object->next); g_assert(object->document); g_assert(object->repr); @@ -932,7 +911,7 @@ sp_object_repr_child_removed(Inkscape::XML::Node *repr, Inkscape::XML::Node *chi /** * Callback for order_changed node event. - * + * * \todo fixme: */ static void @@ -1181,8 +1160,8 @@ SPObject::updateRepr(Inkscape::XML::Node *repr, unsigned int flags) { /* Modification */ -/** - * Add \a flags to \a object's as dirtiness flags, and +/** + * Add \a flags to \a object's as dirtiness flags, and * recursively add CHILD_MODIFIED flag to * parent and ancestors (as far up as necessary). */ @@ -1233,8 +1212,8 @@ SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) // Merge style if we have good reasons to think that parent style is changed */ /** \todo - * I am not sure whether we should check only propagated - * flag. We are currently assuming that style parsing is + * I am not sure whether we should check only propagated + * flag. We are currently assuming that style parsing is * done immediately. I think this is correct (Lauris). */ if ((flags & SP_OBJECT_STYLE_MODIFIED_FLAG) && (flags & SP_OBJECT_PARENT_MODIFIED_FLAG)) { @@ -1424,33 +1403,33 @@ sp_object_get_unique_id(SPObject *object, gchar const *id) * Returns an object style property. * * \todo - * fixme: Use proper CSS parsing. The current version is buggy - * in a number of situations where key is a substring of the + * fixme: Use proper CSS parsing. The current version is buggy + * in a number of situations where key is a substring of the * style string other than as a property name (including - * where key is a substring of a property name), and is also - * buggy in its handling of inheritance for properties that + * where key is a substring of a property name), and is also + * buggy in its handling of inheritance for properties that * aren't inherited by default. It also doesn't allow for - * the case where the property is specified but with an invalid - * value (in which case I believe the CSS2 error-handling + * the case where the property is specified but with an invalid + * value (in which case I believe the CSS2 error-handling * behaviour applies, viz. behave as if the property hadn't - * been specified). Also, the current code doesn't use CRSelEng - * stuff to take a value from stylesheets. Also, we aren't - * setting any hooks to force an update for changes in any of - * the inputs (i.e., in any of the elements that this function + * been specified). Also, the current code doesn't use CRSelEng + * stuff to take a value from stylesheets. Also, we aren't + * setting any hooks to force an update for changes in any of + * the inputs (i.e., in any of the elements that this function * queries). * * \par - * Given that the default value for a property depends on what - * property it is (e.g., whether to inherit or not), and given - * the above comment about ignoring invalid values, and that the - * repr parent isn't necessarily the right element to inherit - * from (e.g., maybe we need to inherit from the referencing - * element instead), we should probably make the caller + * Given that the default value for a property depends on what + * property it is (e.g., whether to inherit or not), and given + * the above comment about ignoring invalid values, and that the + * repr parent isn't necessarily the right element to inherit + * from (e.g., maybe we need to inherit from the referencing + * element instead), we should probably make the caller * responsible for ascending the repr tree as necessary. */ gchar const * sp_object_get_style_property(SPObject const *object, gchar const *key, gchar const *def) -{ +{ g_return_val_if_fail(object != NULL, NULL); g_return_val_if_fail(SP_IS_OBJECT(object), NULL); g_return_val_if_fail(key != NULL, NULL); @@ -1490,7 +1469,7 @@ sp_object_get_style_property(SPObject const *object, gchar const *key, gchar con /** * Lifts SVG version of all root objects to version. */ -void +void SPObject::_requireSVGVersion(Inkscape::Version version) { for ( SPObject::ParentIterator iter=this ; iter ; ++iter ) { SPObject *object=iter;