sp-object.cpp revision 87223513f0edf4dcd1727917ded980e3ac4fd4ae
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * SPObject implementation.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Authors:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Lauris Kaplinski <lauris@kaplinski.com>
843e19887f64dde75055cf8842fc4db2171eff45johnlev * bulia byak <buliabyak@users.sf.net>
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Stephen Silver <sasilver@users.sourceforge.net>
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Jon A. Cruz <jon@joncruz.org>
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Abhishek Sharma
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (C) 1999-2008 authors
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (C) 2001-2002 Ximian, Inc.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Released under GNU GPL, read the file 'COPYING' for more information
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <cstring>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <string>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "helper/sp-marshal.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "xml/node-event-vector.h"
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee#include "attributes.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "attribute-rel-util.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "color-profile.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "document.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "preferences.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "style.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "sp-factory.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "sp-paint-server.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "sp-root.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "sp-style-elem.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "sp-script.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "streq.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "strneq.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "xml/repr.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "xml/node-fns.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "debug/event-tracker.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "debug/simple-event.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "debug/demangle.h"
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include "util/share.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "util/format.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "util/longest-common-suffix.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevusing std::memcpy;
843e19887f64dde75055cf8842fc4db2171eff45johnlevusing std::strchr;
843e19887f64dde75055cf8842fc4db2171eff45johnlevusing std::strcmp;
843e19887f64dde75055cf8842fc4db2171eff45johnlevusing std::strlen;
843e19887f64dde75055cf8842fc4db2171eff45johnlevusing std::strstr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define noSP_OBJECT_DEBUG_CASCADE
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define noSP_OBJECT_DEBUG
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#ifdef SP_OBJECT_DEBUG
843e19887f64dde75055cf8842fc4db2171eff45johnlev# define debug(f, a...) { g_print("%s(%d) %s:", \
843e19887f64dde75055cf8842fc4db2171eff45johnlev __FILE__,__LINE__,__FUNCTION__); \
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_print(f, ## a); \
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_print("\n"); \
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev#else
843e19887f64dde75055cf8842fc4db2171eff45johnlev# define debug(f, a...) /* */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevnamespace {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* createObject() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return new SPObject();
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bool gridRegistered = SPFactory::instance().registerObject("inkscape:grid", createObject);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabguint update_in_progress = 0; // guard against update-during-update
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevInkscape::XML::NodeEventVector object_event_vector = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject::repr_child_added,
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject::repr_child_removed,
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject::repr_attr_changed,
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject::repr_content_changed,
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject::repr_order_changed
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev// A friend class used to set internal members on SPObject so as to not expose settors in SPObject's public API
843e19887f64dde75055cf8842fc4db2171eff45johnlevclass SPObjectImpl
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabpublic:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
5d2eda970e48f8985448151c73e699614ce9f357John Levon/**
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Null's the id member of an SPObject without attempting to free prior contents.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
5d2eda970e48f8985448151c73e699614ce9f357John Levon static void setIdNull( SPObject* obj ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (obj) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab obj->id = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/**
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Sets the id member of an object, freeing any prior content.
5d2eda970e48f8985448151c73e699614ce9f357John Levon */
843e19887f64dde75055cf8842fc4db2171eff45johnlev static void setId( SPObject* obj, gchar const* id ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (obj && (id != obj->id) ) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (obj->id) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_free(obj->id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev obj->id = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (id) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev obj->id = g_strdup(id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic gchar *sp_object_get_unique_id(SPObject *object,
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar const *defid);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject::SPObject()
843e19887f64dde75055cf8842fc4db2171eff45johnlev : cloned(0), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0),
843e19887f64dde75055cf8842fc4db2171eff45johnlev document(NULL), parent(NULL), children(NULL), _last_child(NULL),
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab next(NULL), id(NULL), repr(NULL), refCount(1),
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _successor(NULL), _collection_policy(SPObject::COLLECT_WITH_PARENT),
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _label(NULL), _default_label(NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab debug("id=%x, typename=%s",this, g_type_name_from_instance((GTypeInstance*)object));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //used XML Tree here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->getRepr(); // TODO check why this call is made
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPObjectImpl::setIdNull(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // FIXME: now we create style for all objects, but per SVG, only the following can have style attribute:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // vg, g, defs, desc, title, symbol, use, image, switch, path, rect, circle, ellipse, line, polyline,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // polygon, text, tspan, tref, textPath, altGlyph, glyphRef, marker, linearGradient, radialGradient,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // stop, pattern, clipPath, mask, filter, feImage, a, font, glyph, missing-glyph, foreignObject
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->style = sp_style_new_from_object(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabSPObject::~SPObject() {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_free(this->_label);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_free(this->_default_label);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->_label = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->_default_label = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (this->_successor) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_object_unref(this->_successor, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->_successor = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev// CPPIFY: make pure virtual
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::read_content() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev //throw;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::update(SPCtx* ctx, unsigned int flags) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev //throw;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::modified(unsigned int flags) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //throw;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabnamespace {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabnamespace Debug = Inkscape::Debug;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabnamespace Util = Inkscape::Util;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabtypedef Debug::SimpleEvent<Debug::Event::REFCOUNT> BaseRefCountEvent;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevclass RefCountEvent : public BaseRefCountEvent {
843e19887f64dde75055cf8842fc4db2171eff45johnlevpublic:
843e19887f64dde75055cf8842fc4db2171eff45johnlev RefCountEvent(SPObject *object, int bias, Util::ptr_shared<char> name)
5d2eda970e48f8985448151c73e699614ce9f357John Levon : BaseRefCountEvent(name)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _addProperty("object", Util::format("%p", object));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _addProperty("class", Debug::demangle(g_type_name(G_TYPE_FROM_INSTANCE(object))));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _addProperty("new-refcount", Util::format("%d", G_OBJECT(object)->ref_count + bias));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab};
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabclass RefEvent : public RefCountEvent {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabpublic:
843e19887f64dde75055cf8842fc4db2171eff45johnlev RefEvent(SPObject *object)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab : RefCountEvent(object, 1, Util::share_static_string("sp-object-ref"))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {}
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabclass UnrefEvent : public RefCountEvent {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeepublic:
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee UnrefEvent(SPObject *object)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee : RefCountEvent(object, -1, Util::share_static_string("sp-object-unref"))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {}
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar const* SPObject::getId() const {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return id;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevInkscape::XML::Node * SPObject::getRepr() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return repr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevInkscape::XML::Node const* SPObject::getRepr() const{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return repr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *sp_object_ref(SPObject *object, SPObject *owner)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(object != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::Debug::EventTracker<RefEvent> tracker(object);
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_object_ref(G_OBJECT(object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->refCount++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return object;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabSPObject *sp_object_unref(SPObject *object, SPObject *owner)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(object != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::Debug::EventTracker<UnrefEvent> tracker(object);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //g_object_unref(G_OBJECT(object));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab object->refCount--;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (object->refCount < 0) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab delete object;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *sp_object_href(SPObject *object, gpointer /*owner*/)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(object != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->hrefcount++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->_updateTotalHRefCount(1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return object;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *sp_object_hunref(SPObject *object, gpointer /*owner*/)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(object != NULL, NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(object->hrefcount > 0, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab object->hrefcount--;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab object->_updateTotalHRefCount(-1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::_updateTotalHRefCount(int increment) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *topmost_collectable = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for ( SPObject *iter = this ; iter ; iter = iter->parent ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab iter->_total_hrefcount += increment;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ( iter->_total_hrefcount < iter->hrefcount ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_critical("HRefs overcounted");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ( iter->_total_hrefcount == 0 &&
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab iter->_collection_policy != COLLECT_WITH_PARENT )
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab topmost_collectable = iter;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (topmost_collectable) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab topmost_collectable->requestOrphanCollection();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabbool SPObject::isAncestorOf(SPObject const *object) const {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(object != NULL, false);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab object = object->parent;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while (object) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ( object == this ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return true;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab object = object->parent;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return false;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabnamespace {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabbool same_objects(SPObject const &a, SPObject const &b) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return &a == &b;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabSPObject const *SPObject::nearestCommonAncestor(SPObject const *object) const {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_val_if_fail(object != NULL, NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab using Inkscape::Algorithms::longest_common_suffix;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return longest_common_suffix<SPObject::ConstParentIterator>(this, object, NULL, &same_objects);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee}
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeestatic SPObject const *AncestorSon(SPObject const *obj, SPObject const *ancestor) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee SPObject const *result = 0;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if ( obj && ancestor ) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (obj->parent == ancestor) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee result = obj;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee } else {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee result = AncestorSon(obj->parent, ancestor);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return result;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee}
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeeint sp_object_compare_position(SPObject const *first, SPObject const *second)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int result = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (first != second) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPObject const *ancestor = first->nearestCommonAncestor(second);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // Need a common ancestor to be able to compare
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ( ancestor ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // we have an object and its ancestor (should not happen when sorting selection)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (ancestor == first) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab result = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else if (ancestor == second) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab result = -1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPObject const *to_first = AncestorSon(first, ancestor);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPObject const *to_second = AncestorSon(second, ancestor);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(to_second->parent == to_first->parent);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev result = sp_repr_compare_position(to_first->getRepr(), to_second->getRepr());
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return result;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *SPObject::appendChildRepr(Inkscape::XML::Node *repr) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( !cloned ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev getRepr()->appendChild(repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return document->getObjectByRepr(repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_critical("Attempt to append repr as child of cloned object");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::setCSS(SPCSSAttr *css, gchar const *attr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->getRepr() != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_repr_css_set(this->getRepr(), css, attr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::changeCSS(SPCSSAttr *css, gchar const *attr)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->getRepr() != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_repr_css_change(this->getRepr(), css, attr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevGSList *SPObject::childList(bool add_ref, Action) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev GSList *l = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for ( SPObject *child = firstChild() ; child; child = child->getNext() ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (add_ref) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_ref (child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab l = g_slist_prepend (l, child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return l;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar const *SPObject::label() const {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return _label;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabgchar const *SPObject::defaultLabel() const {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (_label) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return _label;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!_default_label) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (getId()) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev _default_label = g_strdup_printf("#%s", getId());
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _default_label = g_strdup_printf("<%s>", getRepr()->name());
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return _default_label;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::setLabel(gchar const *label)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
843e19887f64dde75055cf8842fc4db2171eff45johnlev getRepr()->setAttribute("inkscape:label", label, false);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::requestOrphanCollection() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(document != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::Preferences *prefs = Inkscape::Preferences::get();
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // do not remove style or script elements (Bug #276244)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (SP_IS_STYLE_ELEM(this)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev // leave it
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (SP_IS_SCRIPT(this)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev // leave it
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else if ((! prefs->getBool("/options/cleanupswatches/value", false)) && SP_IS_PAINT_SERVER(this) && static_cast<SPPaintServer*>(this)->isSwatch() ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // leave it
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else if (IS_COLORPROFILE(this)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // leave it
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab document->queueForOrphanCollection(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /** \todo
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * This is a temporary hack added to make fill&stroke rebuild its
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * gradient list when the defs are vacuumed. gradient-vector.cpp
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * listens to the modified signal on defs, and now we give it that
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * signal. Mental says that this should be made automatic by
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * merging SPObjectGroup with SPObject; SPObjectGroup would issue
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * this signal automatically. Or maybe just derive SPDefs from
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * SPObjectGroup?
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->requestModified(SP_OBJECT_CHILD_MODIFIED_FLAG);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::_sendDeleteSignalRecursive() {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (SPObject *child = firstChild(); child; child = child->getNext()) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab child->_delete_signal.emit(child);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab child->_sendDeleteSignalRecursive();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::deleteObject(bool propagate, bool propagate_descendants)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_object_ref(this, NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (propagate) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _delete_signal.emit(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (propagate_descendants) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->_sendDeleteSignalRecursive();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab Inkscape::XML::Node *repr = getRepr();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (repr && repr->parent()) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_repr_unparent(repr);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (_successor) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _successor->deleteObject(propagate, propagate_descendants);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_object_unref(this, NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::attach(SPObject *object, SPObject *prev)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //g_return_if_fail(parent != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //g_return_if_fail(SP_IS_OBJECT(parent));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(object != NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(SP_IS_OBJECT(object));
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(!prev || SP_IS_OBJECT(prev));
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(!prev || prev->parent == this);
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(!object->parent);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon sp_object_ref(object, this);
5d2eda970e48f8985448151c73e699614ce9f357John Levon object->parent = this;
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->_updateTotalHRefCount(object->_total_hrefcount);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (prev) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon next = prev->next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon prev->next = object;
5d2eda970e48f8985448151c73e699614ce9f357John Levon } else {
5d2eda970e48f8985448151c73e699614ce9f357John Levon next = this->children;
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->children = object;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon object->next = next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!next) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->_last_child = object;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!object->xml_space.set)
5d2eda970e48f8985448151c73e699614ce9f357John Levon object->xml_space.value = this->xml_space.value;
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levonvoid SPObject::reorder(SPObject *prev)
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
5d2eda970e48f8985448151c73e699614ce9f357John Levon //g_return_if_fail(object != NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon //g_return_if_fail(SP_IS_OBJECT(object));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee g_return_if_fail(this->parent != NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(this != prev);
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(!prev || SP_IS_OBJECT(prev));
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_return_if_fail(!prev || prev->parent == this->parent);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *const parent=this->parent;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *old_prev=NULL;
5d2eda970e48f8985448151c73e699614ce9f357John Levon for ( SPObject *child = parent->children ; child && child != this ;
5d2eda970e48f8985448151c73e699614ce9f357John Levon child = child->next )
5d2eda970e48f8985448151c73e699614ce9f357John Levon {
5d2eda970e48f8985448151c73e699614ce9f357John Levon old_prev = child;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *next=this->next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (old_prev) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee old_prev->next = next;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee } else {
5d2eda970e48f8985448151c73e699614ce9f357John Levon parent->children = next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!next) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon parent->_last_child = old_prev;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (prev) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon next = prev->next;
843e19887f64dde75055cf8842fc4db2171eff45johnlev prev->next = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev next = parent->children;
843e19887f64dde75055cf8842fc4db2171eff45johnlev parent->children = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->next = next;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!next) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev parent->_last_child = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::detach(SPObject *object)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_return_if_fail(parent != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_return_if_fail(SP_IS_OBJECT(parent));
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(object != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(SP_IS_OBJECT(object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(object->parent == this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->releaseReferences();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *prev=NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for ( SPObject *child = this->children ; child && child != object ;
843e19887f64dde75055cf8842fc4db2171eff45johnlev child = child->next )
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
843e19887f64dde75055cf8842fc4db2171eff45johnlev prev = child;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *next=object->next;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (prev) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon prev->next = next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon } else {
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->children = next;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!next) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->_last_child = prev;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->next = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->parent = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->_updateTotalHRefCount(-object->_total_hrefcount);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_unref(object, this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *SPObject::get_child_by_repr(Inkscape::XML::Node *repr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(repr != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *result = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( _last_child && (_last_child->getRepr() == repr) ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev result = _last_child; // optimization for common scenario
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev for ( SPObject *child = children ; child ; child = child->next ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( child->getRepr() == repr ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev result = child;
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return result;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev try {
843e19887f64dde75055cf8842fc4db2171eff45johnlev const std::string typeString = NodeTraits::get_type_string(*child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* ochild = SPFactory::instance().createObject(typeString);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *prev = ref ? object->get_child_by_repr(ref) : NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->attach(ochild, prev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_unref(ochild, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ochild->invoke_build(object->document, child, object->cloned);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } catch (const FactoryExceptions::TypeNotRegistered& e) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev std::string node = e.what();
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev // special cases
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (node.empty()) return; // comments, usually
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (node == "rdf:RDF") return; // no SP node yet
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (node == "inkscape:clipboard") return; // SP node not necessary
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_warning("TypeNotRegistered exception: %s", e.what());
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::release() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (object->children) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->detach(object->children);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::remove_child(Inkscape::XML::Node* child) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *ochild = object->get_child_by_repr(child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail (ochild != NULL || !strcmp("comment", child->name())); // comments have no objects
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ochild) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->detach(ochild);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * old_ref, Inkscape::XML::Node *new_ref) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *ochild = object->get_child_by_repr(child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(ochild != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *prev = new_ref ? object->get_child_by_repr(new_ref) : NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev ochild->reorder(prev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ochild->_position_changed_signal.emit(ochild);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Nothing specific here */
843e19887f64dde75055cf8842fc4db2171eff45johnlev debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->readAttr("xml:space");
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->readAttr("inkscape:label");
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->readAttr("inkscape:collect");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (Inkscape::XML::Node *rchild = repr->firstChild() ; rchild != NULL; rchild = rchild->next()) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev try {
843e19887f64dde75055cf8842fc4db2171eff45johnlev const std::string typeString = NodeTraits::get_type_string(*rchild);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev // special cases
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (typeString.empty()) continue; // comments, usually
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (typeString == "rdf:RDF") continue; // no SP node yet
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (typeString == "inkscape:clipboard") continue; // SP node not necessary
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* child = SPFactory::instance().createObject(typeString);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->attach(child, object->lastChild());
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_unref(child, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev child->invoke_build(document, rchild, object->cloned);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } catch (const FactoryExceptions::TypeNotRegistered& e) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_warning("TypeNotRegistered exception: %s", e.what());
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, unsigned int cloned)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab debug("id=%x, typename=%s", this, g_type_name_from_instance((GTypeInstance*)this));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //g_assert(object != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //g_assert(SP_IS_OBJECT(object));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(document != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(repr != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(this->document == NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(this->repr == NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(this->getId() == NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Bookkeeping */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document = document;
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->repr = repr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!cloned) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::GC::anchor(repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->cloned = cloned;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( !cloned ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document->bindObjectToRepr(this->repr, this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (Inkscape::XML::id_permitted(this->repr)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* If we are not cloned, and not seeking, force unique id */
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar const *id = this->repr->attribute("id");
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!document->isSeeking()) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar *realid = sp_object_get_unique_id(this, id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(realid != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document->bindObjectToId(realid, this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObjectImpl::setId(this, realid);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(realid);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Redefine ID, if required */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((id == NULL) || (strcmp(id, this->getId()) != 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->repr->setAttribute("id", this->getId());
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (id) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev // bind if id, but no conflict -- otherwise, we can expect
843e19887f64dde75055cf8842fc4db2171eff45johnlev // a subsequent setting of the id attribute
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!this->document->getObjectById(id)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document->bindObjectToId(id, this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObjectImpl::setId(this, id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->getId() == NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Invoke derived methods, if any */
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->build(document, repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Signalling (should be connected AFTER processing derived methods */
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_repr_add_listener(repr, &object_event_vector, this);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint SPObject::getIntAttribute(char const *key, int def)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_repr_get_int(getRepr(),key,&def);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return def;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevunsigned SPObject::getPosition(){
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return repr->position();
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levonvoid SPObject::appendChild(Inkscape::XML::Node *child) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->repr);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->appendChild(child);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::addChild(Inkscape::XML::Node *child, Inkscape::XML::Node * prev)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->addChild(child,prev);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levonvoid SPObject::releaseReferences() {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->document);
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_assert(this->repr);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon sp_repr_remove_listener_by_data(this->repr, this);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->_release_signal.emit(this);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->release();
5d2eda970e48f8985448151c73e699614ce9f357John Levon
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* all hrefs should be released by the "release" handlers */
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->hrefcount == 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!cloned) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (this->id) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document->bindObjectToId(this->id, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(this->id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->id = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(this->_default_label);
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->_default_label = NULL;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->document->bindObjectToRepr(this->repr, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::GC::release(this->repr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(!this->id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (this->style) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->style = sp_style_unref(this->style);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon this->document = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->repr = NULL;
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject *SPObject::getPrev()
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *prev = 0;
5d2eda970e48f8985448151c73e699614ce9f357John Levon for ( SPObject *obj = parent->firstChild(); obj && !prev; obj = obj->getNext() ) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (obj->getNext() == this) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon prev = obj;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon return prev;
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levonvoid SPObject::repr_child_added(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data)
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *object = SP_OBJECT(data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->child_added(child, ref);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::repr_child_removed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node * /*ref*/, gpointer data)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *object = SP_OBJECT(data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->remove_child(child);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::repr_order_changed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *object = SP_OBJECT(data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->order_changed(child, old, newer);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::set(unsigned int key, gchar const* value) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(key != SP_ATTR_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (key) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_ATTR_ID:
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev //XML Tree being used here.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( !object->cloned && object->getRepr()->type() == Inkscape::XML::ELEMENT_NODE ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPDocument *document=object->document;
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *conflict=NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar const *new_id = value;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (new_id) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev conflict = document->getObjectById((char const *)new_id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( conflict && conflict != object ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!document->isSeeking()) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_ref(conflict, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev // give the conflicting object a new ID
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar *new_conflict_id = sp_object_get_unique_id(conflict, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev conflict->getRepr()->setAttribute("id", new_conflict_id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(new_conflict_id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_object_unref(conflict, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev new_id = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (object->getId()) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev document->bindObjectToId(object->getId(), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObjectImpl::setId(object, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (new_id) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObjectImpl::setId(object, new_id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev document->bindObjectToId(object->getId(), object);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(object->_default_label);
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->_default_label = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_ATTR_INKSCAPE_LABEL:
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(object->_label);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (value) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->_label = g_strdup(value);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->_label = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(object->_default_label);
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->_default_label = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_ATTR_INKSCAPE_COLLECT:
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( value && !strcmp(value, "always") ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->setCollectionPolicy(SPObject::ALWAYS_COLLECT);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->setCollectionPolicy(SPObject::COLLECT_WITH_PARENT);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_ATTR_XML_SPACE:
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (value && !strcmp(value, "preserve")) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->xml_space.value = SP_XML_SPACE_PRESERVE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->xml_space.set = TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (value && !strcmp(value, "default")) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->xml_space.value = SP_XML_SPACE_DEFAULT;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->xml_space.set = TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (object->parent) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *parent;
843e19887f64dde75055cf8842fc4db2171eff45johnlev parent = object->parent;
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->xml_space.value = parent->xml_space.value;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_ATTR_STYLE:
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_style_read_from_object(object->style, object);
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::setKeyValue(unsigned int key, gchar const *value)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_assert(object != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_assert(SP_IS_OBJECT(object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev this->set(key, value);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::readAttr(gchar const *key)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_assert(object != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_assert(SP_IS_OBJECT(object));
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(key != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev //XML Tree being used here.
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_assert(this->getRepr() != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int keyid = sp_attribute_lookup(key);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (keyid != SP_ATTR_INVALID) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Retrieve the 'key' attribute from the object's XML representation */
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar const *value = getRepr()->attribute(key);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev setKeyValue(keyid, value);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::repr_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *key, gchar const * /*oldval*/, gchar const * /*newval*/, bool is_interactive, gpointer data)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *object = SP_OBJECT(data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->readAttr(key);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev // manual changes to extension attributes require the normal
843e19887f64dde75055cf8842fc4db2171eff45johnlev // attributes, which depend on them, to be updated immediately
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (is_interactive) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->updateRepr(0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid SPObject::repr_content_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*oldcontent*/, gchar const * /*newcontent*/, gpointer data)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *object = SP_OBJECT(data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->read_content();
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/**
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Return string representation of space value.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic gchar const *sp_xml_get_space_string(unsigned int space)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (space) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_XML_SPACE_DEFAULT:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return "default";
843e19887f64dde75055cf8842fc4db2171eff45johnlev case SP_XML_SPACE_PRESERVE:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return "preserve";
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevInkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject* object = this;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!repr && (flags & SP_OBJECT_WRITE_BUILD)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr = object->getRepr()->duplicate(doc);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!( flags & SP_OBJECT_WRITE_EXT )) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("inkscape:collect", NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("id", object->getId());
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (object->xml_space.set) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev char const *xml_space;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xml_space = sp_xml_get_space_string(object->xml_space.value);
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("xml:space", xml_space);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( flags & SP_OBJECT_WRITE_EXT &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev object->collectionPolicy() == SPObject::ALWAYS_COLLECT )
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("inkscape:collect", "always");
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("inkscape:collect", NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPStyle const *const obj_style = object->style;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (obj_style) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar *s = sp_style_write_string(obj_style, SP_STYLE_FLAG_IFSET);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev // Check for valid attributes. This may be time consuming.
843e19887f64dde75055cf8842fc4db2171eff45johnlev // It is useful, though, for debugging Inkscape code.
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::Preferences *prefs = Inkscape::Preferences::get();
843e19887f64dde75055cf8842fc4db2171eff45johnlev if( prefs->getBool("/options/svgoutput/check_on_editing") ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int flags = sp_attribute_clean_get_prefs();
843e19887f64dde75055cf8842fc4db2171eff45johnlev Glib::ustring s_cleaned = sp_attribute_clean_style( repr, s, flags );
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free( s );
843e19887f64dde75055cf8842fc4db2171eff45johnlev s = (s_cleaned.empty() ? NULL : g_strdup (s_cleaned.c_str()));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if( s == NULL || strcmp(s,"") == 0 ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("style", NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev repr->setAttribute("style", s);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_free(s);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /** \todo I'm not sure what to do in this case. Bug #1165868
843e19887f64dde75055cf8842fc4db2171eff45johnlev * suggests that it can arise, but the submitter doesn't know
843e19887f64dde75055cf8842fc4db2171eff45johnlev * how to do so reliably. The main two options are either
843e19887f64dde75055cf8842fc4db2171eff45johnlev * leave repr's style attribute unchanged, or explicitly clear it.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Must also consider what to do with property attributes for
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the element; see below.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev char const *style_str = repr->attribute("style");
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!style_str) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev style_str = "NULL";
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_warning("Item's style is NULL; repr style attribute is %s", style_str);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /** \note We treat object->style as authoritative. Its effects have
843e19887f64dde75055cf8842fc4db2171eff45johnlev * been written to the style attribute above; any properties that are
843e19887f64dde75055cf8842fc4db2171eff45johnlev * unset we take to be deliberately unset (e.g. so that clones can
843e19887f64dde75055cf8842fc4db2171eff45johnlev * override the property).
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Note that the below has an undesirable consequence of changing the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * appearance on renderers that lack CSS support (e.g. SVG tiny);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * possibly we should write property attributes instead of a style
843e19887f64dde75055cf8842fc4db2171eff45johnlev * attribute.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev sp_style_unset_property_attrs (object);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return repr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevInkscape::XML::Node * SPObject::updateRepr(unsigned int flags)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( !cloned ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::XML::Node *repr = getRepr();
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (repr) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return updateRepr(repr->document(), repr, flags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_critical("Attempt to update non-existent repr");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee } else {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /* cloned objects have no repr */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabInkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(doc != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (cloned) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* cloned objects have no repr */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!(flags & SP_OBJECT_WRITE_BUILD) && !repr) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab repr = getRepr();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return this->write(doc, repr, flags);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/* Modification */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::requestDisplayUpdate(unsigned int flags)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail( this->document != NULL );
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (update_in_progress) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee g_print("WARNING: Requested update while update in progress, counter = %d\n", update_in_progress);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee }
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* requestModified must be used only to set one of SP_OBJECT_MODIFIED_FLAG or
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * SP_OBJECT_CHILD_MODIFIED_FLAG */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(!(flags & SP_OBJECT_PARENT_MODIFIED_FLAG));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail((flags & SP_OBJECT_MODIFIED_FLAG) || (flags & SP_OBJECT_CHILD_MODIFIED_FLAG));
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG)));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee bool already_propagated = (!(this->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee this->uflags |= flags;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /* If requestModified has already been called on this object or one of its children, then we
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * don't need to set CHILD_MODIFIED on our ancestors because it's already been done.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (already_propagated) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (parent) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab parent->requestDisplayUpdate(SP_OBJECT_CHILD_MODIFIED_FLAG);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab document->requestModified();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::updateDisplay(SPCtx *ctx, unsigned int flags)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab update_in_progress ++;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#ifdef SP_OBJECT_DEBUG_CASCADE
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_print("Update %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *) this), getId(), flags, this->uflags, this->mflags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#endif
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* Get this flags */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab flags |= this->uflags;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* Copy flags to modified cascade for later processing */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->mflags |= this->uflags;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* We have to clear flags here to allow rescheduling update */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->uflags = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // Merge style if we have good reasons to think that parent style is changed */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /** \todo
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * I am not sure whether we should check only propagated
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * flag. We are currently assuming that style parsing is
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * done immediately. I think this is correct (Lauris).
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((flags & SP_OBJECT_STYLE_MODIFIED_FLAG) && (flags & SP_OBJECT_PARENT_MODIFIED_FLAG)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (this->style && this->parent) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_style_merge_from_parent(this->style, this->parent->style);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab try
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->update(ctx, flags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev catch(...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /** \todo
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in case of catching an exception we need to inform the user somehow that the document is corrupted
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * maybe by implementing an document flag documentOk
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or by a modal error dialog
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_warning("SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) : throw in ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->update(this, ctx, flags);");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab update_in_progress --;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::requestModified(unsigned int flags)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail( this->document != NULL );
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* requestModified must be used only to set one of SP_OBJECT_MODIFIED_FLAG or
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * SP_OBJECT_CHILD_MODIFIED_FLAG */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(!(flags & SP_OBJECT_PARENT_MODIFIED_FLAG));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail((flags & SP_OBJECT_MODIFIED_FLAG) || (flags & SP_OBJECT_CHILD_MODIFIED_FLAG));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG)));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bool already_propagated = (!(this->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->mflags |= flags;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* If requestModified has already been called on this object or one of its children, then we
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * don't need to set CHILD_MODIFIED on our ancestors because it's already been done.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (already_propagated) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (parent) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab parent->requestModified(SP_OBJECT_CHILD_MODIFIED_FLAG);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab document->requestModified();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::emitModified(unsigned int flags)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* only the MODIFIED_CASCADE flag is legal here */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#ifdef SP_OBJECT_DEBUG_CASCADE
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee g_print("Modified %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *) this), getId(), flags, this->uflags, this->mflags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#endif
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab flags |= this->mflags;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* We have to clear mflags beforehand, as signal handlers may
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * make changes and therefore queue new modification notifications
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * themselves. */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->mflags = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_object_ref(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab this->modified(flags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab _modified_signal.emit(this, flags);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sp_object_unref(this);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabgchar const *SPObject::getTagName(SPException *ex) const
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(repr != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* If exception is not clear, return */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!SP_EXCEPTION_IS_OK(ex)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /// \todo fixme: Exception if object is NULL? */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //XML Tree being used here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return getRepr()->name();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabgchar const *SPObject::getAttribute(gchar const *key, SPException *ex) const
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
5d2eda970e48f8985448151c73e699614ce9f357John Levon g_assert(this->repr != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* If exception is not clear, return */
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!SP_EXCEPTION_IS_OK(ex)) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon return NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /// \todo fixme: Exception if object is NULL? */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //XML Tree being used here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (gchar const *) getRepr()->attribute(key);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::setAttribute(gchar const *key, gchar const *value, SPException *ex)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(this->repr != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* If exception is not clear, return */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_return_if_fail(SP_EXCEPTION_IS_OK(ex));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /// \todo fixme: Exception if object is NULL? */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //XML Tree being used here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab getRepr()->setAttribute(key, value, false);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeevoid SPObject::removeAttribute(gchar const *key, SPException *ex)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* If exception is not clear, return */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee g_return_if_fail(SP_EXCEPTION_IS_OK(ex));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /// \todo fixme: Exception if object is NULL? */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee //XML Tree being used here.
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee getRepr()->setAttribute(key, NULL, false);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee}
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeebool SPObject::storeAsDouble( gchar const *key, double *val ) const
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee{
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee g_assert(this->getRepr()!= NULL);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee return sp_repr_get_double(((Inkscape::XML::Node *)(this->getRepr())),key,val);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee}
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee/** Helper */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybeestatic gchar*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabsp_object_get_unique_id(SPObject *object,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab gchar const *id)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab static unsigned long count = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(SP_IS_OBJECT(object));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab count++;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //XML Tree being used here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab gchar const *name = object->getRepr()->name();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_assert(name != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab gchar const *local = strchr(name, ':');
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (local) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev name = local + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (id != NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (object->document->getObjectById(id) == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return g_strdup(id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon size_t const name_len = strlen(name);
5d2eda970e48f8985448151c73e699614ce9f357John Levon size_t const buflen = name_len + (sizeof(count) * 10 / 4) + 1;
5d2eda970e48f8985448151c73e699614ce9f357John Levon gchar *const buf = (gchar *) g_malloc(buflen);
5d2eda970e48f8985448151c73e699614ce9f357John Levon memcpy(buf, name, name_len);
5d2eda970e48f8985448151c73e699614ce9f357John Levon gchar *const count_buf = buf + name_len;
5d2eda970e48f8985448151c73e699614ce9f357John Levon size_t const count_buflen = buflen - name_len;
5d2eda970e48f8985448151c73e699614ce9f357John Levon do {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab ++count;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_snprintf(count_buf, count_buflen, "%lu", count);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } while ( object->document->getObjectById(buf) != NULL );
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return buf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab// Style
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar const * SPObject::getStyleProperty(gchar const *key, gchar const *def) const
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_return_val_if_fail(object != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev //g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_return_val_if_fail(key != NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev //XML Tree being used here.
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar const *style = getRepr()->attribute("style");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (style) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t const len = strlen(key);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char const *p;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while ( (p = strstr(style, key))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab != NULL )
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab p += len;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while ((*p <= ' ') && *p) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab p++;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (*p++ != ':') {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while ((*p <= ' ') && *p) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev p++;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t const inherit_len = sizeof("inherit") - 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (*p
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab && !(strneq(p, "inherit", inherit_len)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab && (p[inherit_len] == '\0'
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab || p[inherit_len] == ';'
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab || g_ascii_isspace(p[inherit_len])))) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon return p;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab //XML Tree being used here.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab gchar const *val = getRepr()->attribute(key);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (val && !streq(val, "inherit")) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return val;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (this->parent) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (this->parent)->getStyleProperty(key, def);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon return def;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabvoid SPObject::_requireSVGVersion(Inkscape::Version version) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for ( SPObject::ParentIterator iter=this ; iter ; ++iter ) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon SPObject *object = iter;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (SP_IS_ROOT(object)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPRoot *root = SP_ROOT(object);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ( root->version.svg < version ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab root->version.svg = version;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab// Titles and descriptions
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/* Note:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab Titles and descriptions are stored in 'title' and 'desc' child elements
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (see section 5.4 of the SVG 1.0 and 1.1 specifications). The spec allows
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab an element to have more than one 'title' child element, but strongly
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab recommends against this and requires using the first one if a choice must
843e19887f64dde75055cf8842fc4db2171eff45johnlev be made. The same applies to 'desc' elements. Therefore, these functions
843e19887f64dde75055cf8842fc4db2171eff45johnlev ignore all but the first 'title' child element and first 'desc' child
843e19887f64dde75055cf8842fc4db2171eff45johnlev element, except when deleting a title or description.
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon This will change in SVG 2, where multiple 'title' and 'desc' elements will
5d2eda970e48f8985448151c73e699614ce9f357John Levon be allowed with different localized strings.
5d2eda970e48f8985448151c73e699614ce9f357John Levon*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar * SPObject::title() const
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return getTitleOrDesc("svg:title");
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevbool SPObject::setTitle(gchar const *title, bool verbatim)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return setTitleOrDesc(title, "svg:title", verbatim);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar * SPObject::desc() const
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return getTitleOrDesc("svg:desc");
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevbool SPObject::setDesc(gchar const *desc, bool verbatim)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return setTitleOrDesc(desc, "svg:desc", verbatim);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevgchar * SPObject::getTitleOrDesc(gchar const *svg_tagname) const
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee{
843e19887f64dde75055cf8842fc4db2171eff45johnlev gchar *result = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *elem = findFirstChild(svg_tagname);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ( elem ) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev result = g_string_free(elem->textualContent(), FALSE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return result;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevbool SPObject::setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool verbatim)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!verbatim) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // If the new title/description is just whitespace,
843e19887f64dde75055cf8842fc4db2171eff45johnlev // treat it as though it were NULL.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (value) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev bool just_whitespace = true;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (const gchar *cp = value; *cp; ++cp) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!std::strchr("\r\n \t", *cp)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev just_whitespace = false;
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (just_whitespace) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev value = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev // Don't stomp on mark-up if there is no real change.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (value) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab gchar *current_value = getTitleOrDesc(svg_tagname);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (current_value) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bool different = std::strcmp(current_value, value);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab g_free(current_value);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!different) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return false;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab SPObject *elem = findFirstChild(svg_tagname);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (value == NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (elem == NULL) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee return false;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // delete the title/description(s)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while (elem) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab elem->deleteObject();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab elem = findFirstChild(svg_tagname);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return true;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab Inkscape::XML::Document *xml_doc = document->getReprDoc();
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (elem == NULL) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee // create a new 'title' or 'desc' element, putting it at the
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee // beginning (in accordance with the spec's recommendations)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee Inkscape::XML::Node *xml_elem = xml_doc->createElement(svg_tagname);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee repr->addChild(xml_elem, NULL);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee elem = document->getObjectByRepr(xml_elem);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee Inkscape::GC::release(xml_elem);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee }
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab // remove the current content of the 'text' or 'desc' element
843e19887f64dde75055cf8842fc4db2171eff45johnlev SPObject *child;
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (NULL != (child = elem->firstChild())) child->deleteObject();
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev // add the new content
843e19887f64dde75055cf8842fc4db2171eff45johnlev elem->appendChildRepr(xml_doc->createTextNode(value));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return true;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevSPObject * SPObject::findFirstChild(gchar const *tagname) const
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (SPObject *child = children; child; child = child->next)
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (child->repr->type() == Inkscape::XML::ELEMENT_NODE &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev !strcmp(child->repr->name(), tagname)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return child;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevGString * SPObject::textualContent() const
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
843e19887f64dde75055cf8842fc4db2171eff45johnlev GString* text = g_string_new("");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (const SPObject *child = firstChild(); child; child = child->next)
843e19887f64dde75055cf8842fc4db2171eff45johnlev {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Inkscape::XML::NodeType child_type = child->repr->type();
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (child_type == Inkscape::XML::ELEMENT_NODE) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev GString * new_text = child->textualContent();
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_string_append(text, new_text->str);
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_string_free(new_text, TRUE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev else if (child_type == Inkscape::XML::TEXT_NODE) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev g_string_append(text, child->repr->content());
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return text;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev Local Variables:
843e19887f64dde75055cf8842fc4db2171eff45johnlev mode:c++
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab c-file-style:"stroustrup"
843e19887f64dde75055cf8842fc4db2171eff45johnlev c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
843e19887f64dde75055cf8842fc4db2171eff45johnlev indent-tabs-mode:nil
843e19887f64dde75055cf8842fc4db2171eff45johnlev fill-column:99
843e19887f64dde75055cf8842fc4db2171eff45johnlev End:
843e19887f64dde75055cf8842fc4db2171eff45johnlev*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee