sp-object.cpp revision dac38e300279674677dd6c3c68cc0890b580b97e
2N/A * SPObject implementation. 2N/A * Lauris Kaplinski <lauris@kaplinski.com> 2N/A * bulia byak <buliabyak@users.sf.net> 2N/A * Stephen Silver <sasilver@users.sourceforge.net> 2N/A * Copyright (C) 1999-2008 authors 2N/A * Copyright (C) 2001-2002 Ximian, Inc. 2N/A * Released under GNU GPL, read the file 'COPYING' for more information 2N/A * SPObject is an abstract base class of all of the document nodes at the 2N/A * SVG document level. Each SPObject subclass implements a certain SVG 2N/A * element node type, or is an abstract base class for different node 2N/A * types. The SPObject layer is bound to the SPRepr layer, closely 2N/A * following the SPRepr mutations via callbacks. During creation, 2N/A * SPObject parses and interprets all textual attributes and CSS style 2N/A * strings of the SPRepr, and later updates the internal state whenever 2N/A * it receives a signal about a change. The opposite is not true - there 2N/A * are methods manipulating SPObjects directly and such changes do not 2N/A * propagate to the SPRepr layer. This is important for implementation of 2N/A * the undo stack, animations and other features. 2N/A * SPObjects are bound to the higher-level container SPDocument, which 2N/A * provides document level functionality such as the undo stack, 2N/A/* Real handlers of repr signals */ 2N/A * Registers the SPObject class with Gdk and returns its type number. 2N/A * Initializes the SPObject vtable. 2N/A * Callback to initialize the SPObject object. // FIXME: now we create style for all objects, but per SVG, only the following can have style attribute: // vg, g, defs, desc, title, symbol, use, image, switch, path, rect, circle, ellipse, line, polyline, // polygon, text, tspan, tref, textPath, altGlyph, glyphRef, marker, linearGradient, radialGradient, // stop, pattern, clipPath, mask, filter, feImage, a, font, glyph, missing-glyph, foreignObject * Callback to destroy all members and connections of object and itself. * Increase reference count of object, with possible debugging. * \param owner If non-NULL, make debug log entry. * \return object, NULL is error. * \pre object points to real object * Decrease reference count of object, with possible debugging and * \param owner If non-NULL, make debug log entry. * \pre object points to real object * Increase weak refcount. * Hrefcount is used for weak references, for example, to * determine whether any graphical element references a certain gradient * \return object, NULL is error * \pre object points to real object * Decrease weak refcount. * Hrefcount is used for weak references, for example, to determine whether * any graphical element references a certain gradient node. * \pre object points to real object and hrefcount>0 * Adds increment to _total_hrefcount of object and its parents. * True if object is non-NULL and this is some in/direct parent of object. * Returns youngest object being parent to this and object. * Compares height of objects in tree. * Works for different-parent objects, so long as they have a common ancestor. * 0 positions are equivalent * 1 first object's position is greater than the second * -1 first object's position is less than the second \endverbatim if (
ancestor ==
NULL)
return 0;
// cannot compare, no common ancestor! // we have an object and its ancestor (should not happen when sorting selection) * Append repr as child of this object. * \pre this is not a cloned object g_critical(
"Attempt to append repr as child of cloned object");
* Retrieves the children as a GSList object, optionally ref'ing the children * in the process, if add_ref is specified. /** Gets the label property for the object or a default if no label /** Returns a default label property for the object. */ /** Sets the label property for the object */ /** Queues the object for orphan collection */ * This is a temporary hack added to make fill&stroke rebuild its * listens to the modified signal on defs, and now we give it that * signal. Mental says that this should be made automatic by * merging SPObjectGroup with SPObject; SPObjectGroup would issue * this signal automatically. Or maybe just derive SPDefs from /** Sends the delete signal to all children of this object recursively */ * Deletes the object reference, unparenting it from its parent. * If the \a propagate parameter is set to true, it emits a delete * signal. If the \a propagate_descendants parameter is true, it * recursively sends the delete signal to children. * Put object into object tree, under parent, and behind prev; * also update object's XML space. * In list of object's siblings, move object behind prev. * Remove object from parent's children, release and unref it. * Return object's child whose node pointer equals repr. * Callback for child_added event. * Invoked whenever the given mutation event happens in the XML tree. * Removes, releases and unrefs all children of object. * This is the opposite of build. It has to be invoked as soon as the * object is removed from the tree, even if it is still alive according * to reference count. The frontend unregisters the object from the * document and releases the SPRepr bindings; implementations should free * state data and release all child objects. Invoking release on * SPRoot destroys the whole document tree. * Remove object's child whose node equals repr, release and * Invoked whenever the given mutation event happens in the XML * tree, BEFORE removal from the XML tree happens, so grouping * objects can safely release the child data. * Move object corresponding to child after sibling object corresponding * Invoked whenever the given mutation event happens in the XML tree. * Virtual build callback. * This has to be invoked immediately after creation of an SPObject. The * frontend method ensures that the new object is properly attached to * the document and repr; implementation then will parse all of the attributes, * generate the children objects and so on. Invoking build on the SPRoot * object results in creation of the whole document tree (this is, what * SPDocument does after the creation of the XML tree). * \see sp_object_release() /* Nothing specific here */ /* If we are not cloned, and not seeking, force unique id */ /* Redefine ID, if required */ // bind if id, but no conflict -- otherwise, we can expect // a subsequent setting of the id attribute /* Invoke derived methods, if any */ /* Signalling (should be connected AFTER processing derived methods */ /* all hrefs should be released by the "release" handlers */ * Callback for child_added node event. * Callback for remove_child node event. * Callback for order_changed node event. * Callback for set event. // give the conflicting object a new ID * Call virtual set() function of object. * Read value of key attribute from XML node into object. /* Retrieve the 'key' attribute from the object's XML representation */ * Callback for attr_changed node event. // manual changes to extension attributes require the normal // attributes, which depend on them, to be updated immediately * Callback for content_changed node event. * Return string representation of space value. * Callback for write event. /** \todo I'm not sure what to do in this case. Bug #1165868 * suggests that it can arise, but the submitter doesn't know * how to do so reliably. The main two options are either * leave repr's style attribute unchanged, or explicitly clear it. * Must also consider what to do with property attributes for * the element; see below. /** \note We treat object->style as authoritative. Its effects have * been written to the style attribute above; any properties that are * unset we take to be deliberately unset (e.g. so that clones can * override the property). * Note that the below has an undesirable consequence of changing the * appearance on renderers that lack CSS support (e.g. SVG tiny); * possibly we should write property attributes instead of a style * Update this object's XML node with flags value. g_critical(
"Attempt to update non-existent repr");
/* cloned objects have no repr */ /** Used both to create reprs in the original document, and to create * reprs in another document (e.g. a temporary document used when /* cloned objects have no repr */ /// \todo FIXME: else probably error (Lauris) */ * Add \a flags to \a object's as dirtiness flags, and * recursively add CHILD_MODIFIED flag to * parent and ancestors (as far up as necessary). /* requestModified must be used only to set one of SP_OBJECT_MODIFIED_FLAG or * SP_OBJECT_CHILD_MODIFIED_FLAG */ /* If requestModified has already been called on this object or one of its children, then we * don't need to set CHILD_MODIFIED on our ancestors because it's already been done. /* Copy flags to modified cascade for later processing */ /* We have to clear flags here to allow rescheduling update */ // Merge style if we have good reasons to think that parent style is changed */ * I am not sure whether we should check only propagated * flag. We are currently assuming that style parsing is * done immediately. I think this is correct (Lauris). * in case of catching an exception we need to inform the user somehow that the document is corrupted * maybe by implementing an document flag documentOk * or by a modal error dialog g_warning(
"SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) : throw in ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->update(this, ctx, flags);");
* Request modified always bubbles *up* the tree, as opposed to * request display update, which trickles down and relies on the * flags set during this pass... /* requestModified must be used only to set one of SP_OBJECT_MODIFIED_FLAG or * SP_OBJECT_CHILD_MODIFIED_FLAG */ /* If requestModified has already been called on this object or one of its children, then we * don't need to set CHILD_MODIFIED on our ancestors because it's already been done. * Emits the MODIFIED signal with the object's flags. * The object's mflags are the original set aside during the update pass for * later delivery here. Once emitModified() is called, those flags don't * need to be stored any longer. /* only the MODIFIED_CASCADE flag is legal here */ /* We have to clear mflags beforehand, as signal handlers may * make changes and therefore queue new modification notifications /* If exception is not clear, return */ /// \todo fixme: Exception if object is NULL? */ /* If exception is not clear, return */ /// \todo fixme: Exception if object is NULL? */ /* If exception is not clear, return */ /// \todo fixme: Exception if object is NULL? */ /* If exception is not clear, return */ /// \todo fixme: Exception if object is NULL? */ static unsigned long count = 0;
* Returns an object style property. * fixme: Use proper CSS parsing. The current version is buggy * in a number of situations where key is a substring of the * style string other than as a property name (including * where key is a substring of a property name), and is also * buggy in its handling of inheritance for properties that * aren't inherited by default. It also doesn't allow for * the case where the property is specified but with an invalid * value (in which case I believe the CSS2 error-handling * behaviour applies, viz. behave as if the property hadn't * been specified). Also, the current code doesn't use CRSelEng * stuff to take a value from stylesheets. Also, we aren't * setting any hooks to force an update for changes in any of * the inputs (i.e., in any of the elements that this function * Given that the default value for a property depends on what * property it is (e.g., whether to inherit or not), and given * the above comment about ignoring invalid values, and that the * repr parent isn't necessarily the right element to inherit * from (e.g., maybe we need to inherit from the referencing * <use> element instead), we should probably make the caller * responsible for ascending the repr tree as necessary. while ((*p <=
' ') && *p) p++;
while ((*p <=
' ') && *p) p++;
* Lifts SVG version of all root objects to version. * Return sodipodi version of first root ancestor or (0,0). * Returns previous object in sibling list or NULL. /* Titles and descriptions */ Titles and descriptions are stored in 'title' and 'desc' child elements (see section 5.4 of the SVG 1.0 and 1.1 specifications). The spec allows an element to have more than one 'title' child element, but strongly recommends against this and requires using the first one if a choice must be made. The same applies to 'desc' elements. Therefore, these functions ignore all but the first 'title' child element and first 'desc' child element, except when deleting a title or description. * Returns the title of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. * Sets the title of this object * A NULL first argument is interpreted as meaning that the existing title * (if any) should be deleted. * The second argument is optional - see setTitleOrDesc() below for details. * Returns the description of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. * Sets the description of this object. * A NULL first argument is interpreted as meaning that the existing * description (if any) should be deleted. * The second argument is optional - see setTitleOrDesc() below for details. * Returns the title or description of this object, or NULL if there is none. * The SVG spec allows 'title' and 'desc' elements to contain text marked up * using elements from other namespaces. Therefore, this function cannot * in general just return a pointer to an existing string - it must instead * construct a string containing the title or description without the mark-up. * Consequently, the return value is a newly allocated string (or NULL), and * must be freed (using g_free()) by the caller. * Sets or deletes the title or description of this object. * A NULL 'value' argument causes the title or description to be deleted. * If verbatim==true, then the title or description is set to exactly the * specified value. If verbatim==false then two exceptions are made: * (2) If the specified value is the same as the current value except for * mark-up, then the current value is left unchanged. * This is usually the desired behaviour, so 'verbatim' defaults to false for * setTitle() and setDesc(). * and usually false otherwise. // treat it as though it were NULL. // Don't stomp on mark-up if there is no real change. // create a new 'title' or 'desc' element, putting it at the // beginning (in accordance with the spec's recommendations) // remove the current content of the 'text' or 'desc' element * Find the first child of this object with a given tag name, * and return it. Returns NULL if there is no matching child. * Return the full textual content of an element (typically all the * content except the tags). * Must not be used on anything except elements. c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :