sp-use.cpp revision d5ad05ac17abfd7d2eae333a8c1233971e1c1a8f
#define __SP_USE_C__
/*
* SVG <use> implementation
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* bulia byak <buliabyak@users.sf.net>
*
* Copyright (C) 1999-2005 authors
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <cstring>
#include <string>
#include <libnr/nr-matrix-ops.h>
#include <libnr/nr-matrix-fns.h>
#include "display/nr-arena-group.h"
#include "attributes.h"
#include "document.h"
#include "sp-object-repr.h"
#include "sp-flowregion.h"
#include "uri.h"
#include "print.h"
#include "preferences.h"
#include "style.h"
#include "sp-symbol.h"
#include "sp-use.h"
#include "sp-use-reference.h"
/* fixme: */
static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
static void sp_use_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static SPItemClass *parent_class;
//void m_print(gchar *say, Geom::Matrix m)
//{ g_print("%s %g %g %g %g %g %g\n", say, m[0], m[1], m[2], m[3], m[4], m[5]); }
sp_use_get_type(void)
{
if (!use_type) {
sizeof(SPUseClass),
NULL, /* base_init */
NULL, /* base_finalize */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof(SPUse),
16, /* n_preallocs */
NULL, /* value_table */
};
}
return use_type;
}
static void
{
}
static void
{
use->_changed_connection = use->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_use_href_changed), use));
}
static void
{
}
}
static void
{
}
// We don't need to create child here:
// reading xlink:href will attach ref, and that will cause the changed signal to be emitted,
// which will call sp_use_href_changed, and that will take care of the child
}
static void
{
}
}
}
static void
{
switch (key) {
case SP_ATTR_X:
break;
case SP_ATTR_Y:
break;
case SP_ATTR_WIDTH:
break;
case SP_ATTR_HEIGHT:
break;
case SP_ATTR_XLINK_HREF: {
/* No change, do nothing. */
} else {
if (value) {
// First, set the href field, because sp_use_href_changed will need it.
// Now do the attaching, which emits the changed signal.
try {
} catch (Inkscape::BadURIException &e) {
}
} else {
}
}
break;
}
default:
}
break;
}
}
sp_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
}
}
}
return repr;
}
static void
{
* transform );
if (optbbox) {
}
}
}
static void
{
bool translated = false;
translated = true;
}
}
if (translated) {
}
}
static gchar *
{
char *ret;
static unsigned recursion_depth = 0;
if (recursion_depth >= 4) {
/* TRANSLATORS: Used for statusbar description for long <use> chains:
* "Clone of: Clone of: ... in Layer 1". */
return g_strdup(_("..."));
/* We could do better, e.g. chasing the href chain until we reach something other than
* a <use>, and giving its description. */
}
return ret;
} else {
return g_strdup(_("<b>Orphaned clone</b>"));
}
}
static NRArenaItem *
{
if (ac) {
}
}
return ai;
}
static void
{
}
}
}
/**
* Returns the ultimate original of a SPUse (i.e. the first object in the chain of its originals
* which is not an SPUse). If no original is found, NULL is returned (it is the responsibility
* of the caller to make sure that this is handled correctly).
*
* Note that the returned is the clone object, i.e. the child of an SPUse (of the argument one for
* the trivial case) and not the "true original".
*/
SPItem *
{
}
return NULL;
}
/**
* Returns the effective transform that goes from the ultimate original to given SPUse, both ends
* included.
*/
{
//track the ultimate source of a chain of uses
}
//calculate the accummulated transform, starting from the original
// "An additional transformation translate(x,y) is appended to the end (i.e.,
// right-side) of the transform attribute on the generated 'g', where x and y
// represent the values of the x and y attributes on the 'use' element." - http://www.w3.org/TR/SVG11/struct.html#UseElement
t = t * Geom::Translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0);
}
}
}
return t;
}
/**
* Returns the transform that leads to the use from its immediate original.
* Does not inlcude the original's transform if any.
*/
{
}
return t;
}
/**
* Sensing a movement of the original, this function attempts to compensate for it in such a way
* that the clone stays unmoved or moves in parallel (depending on user setting) regardless of the
* clone's transform.
*/
static void
{
// the clone is orphaned; or this is not a real use, but a clone of another use;
// we skip it, otherwise duplicate compensation will occur
if (SP_OBJECT_IS_CLONED(self)) {
return;
}
// never compensate uses which are used in flowtext
return;
}
// user wants no compensation
if (mode == SP_CLONE_COMPENSATION_NONE)
return;
// this is not a simple move, do not try to compensate
if (!(m.isTranslation()))
return;
// restore item->transform field from the repr, in case it was changed by seltrans
// calculate the compensation matrix and the advertized movement matrix
if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
advertized_move = m;
} else if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
} else {
}
// commit the compensation
}
static void
{
}
if (refobj) {
if (ai) {
}
}
}
use->_delete_connection = SP_OBJECT(refobj)->connectDelete(sigc::bind(sigc::ptr_fun(&sp_use_delete_self), use));
use->_transformed_connection = SP_ITEM(refobj)->connectTransformed(sigc::bind(sigc::ptr_fun(&sp_use_move_compensate), use));
}
}
}
static void
{
// always delete uses which are used in flowtext
return;
}
if (mode == SP_CLONE_ORPHANS_UNLINK) {
} else if (mode == SP_CLONE_ORPHANS_DELETE) {
}
}
static void
{
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
}
}
/* Set up child viewport */
}
}
}
}
} else {
}
}
}
/* As last step set additional transform of arena group */
}
}
static void
{
if (flags & SP_OBJECT_MODIFIED_FLAG) {
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
}
}
if (child) {
}
}
}
SPItem *
{
// Track the ultimate source of a chain of uses.
// Calculate the accumulated transform, starting from the original.
for (Inkscape::XML::Node *child = SP_OBJECT_REPR(orig)->firstChild() ; child != NULL; child = child->next()) {
}
} else { // just copy
}
// Add the duplicate repr just after the existing one.
// Retrieve the SPItem of the resulting repr.
// Merge style from the use.
// Hold onto our SPObject and repr for now.
// Remove ourselves, not propagating delete events to avoid a
// chain-reaction with other elements that might reference us.
// Give the copy our old id and let go of our old repr.
// Remove tiled clone attrs.
// Establish the succession and let go of our object.
// Set the accummulated transform.
{
// Advertise ourselves as not moving.
}
return item;
}
SPItem *
{
return ref;
}
static void
sp_use_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs)
{
if (!root)
return;
if (item_class.snappoints) {
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :