void SPDocument::queueForOrphanCollection(SPObject *object) { g_return_if_fail(object != NULL); g_return_if_fail(SP_OBJECT_DOCUMENT(object) == this); sp_object_ref(object, NULL); _collection_queue = g_slist_prepend(_collection_queue, object); }
void SPClipPath::modified(unsigned int flags) { if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = NULL; for (SPObject *child = this->firstChild(); child; child = child->getNext()) { sp_object_ref(child); l = g_slist_prepend(l, child); } l = g_slist_reverse(l); while (l) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } sp_object_unref(child); } }
void ObjectHierarchy::setBottom(SPObject *object) { if (object == NULL) { printf("assertion object != NULL failed\n"); return; } if ( bottom() == object ) { return; } if (!top()) { _addBottom(object); } else if (bottom()->isAncestorOf(object)) { _addBottom(bottom(), object); } else if ( top() == object ) { _trimBelow(top()); } else if (top()->isAncestorOf(object)) { if (object->isAncestorOf(bottom())) { _trimBelow(object); } else { // object is a sibling or cousin of bottom() SPObject *saved_top=top(); sp_object_ref(saved_top, NULL); _clear(); _addBottom(saved_top); _addBottom(saved_top, object); sp_object_unref(saved_top, NULL); } } else { _clear(); _addBottom(object); } _changed_signal.emit(top(), bottom()); }
void SPUse::modified(unsigned int flags) { // std::cout << "SPUse::modified: " << (getId()?getId():"null") << std::endl; if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); this->context_style = this->style; g->setStyle(this->style, this->context_style); } } if (child) { sp_object_ref(child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } sp_object_unref(child); } }
ObjectHierarchy::Record ObjectHierarchy::_attach(SPObject *object) { sp_object_ref(object, NULL); sigc::connection connection = object->connectRelease( sigc::mem_fun(*this, &ObjectHierarchy::_trim_for_release) ); return Record(object, connection); }
void NRStyle::Paint::set(SPPaintServer *ps) { clear(); if (ps) { type = PAINT_SERVER; server = ps; sp_object_ref(server, NULL); } }
void sp_sel_trans_grab (SPSelTrans * seltrans, NRPointF *p, gdouble x, gdouble y, gboolean show_handles) { SPSelection *selection; const GSList *l; int n; selection = SP_DT_SELECTION (seltrans->desktop); g_return_if_fail (!seltrans->grabbed); seltrans->grabbed = TRUE; seltrans->show_handles = show_handles; sp_sel_trans_update_volatile_state (seltrans); seltrans->changed = FALSE; if (seltrans->empty) return; l = sp_selection_item_list (selection); seltrans->nitems = g_slist_length ((GSList *) l); seltrans->items = nr_new (SPItem *, seltrans->nitems); seltrans->transforms = nr_new (NRMatrixF, seltrans->nitems); n = 0; while (l) { seltrans->items[n] = (SPItem *) sp_object_ref (SP_OBJECT (l->data), NULL); sp_item_i2d_affine (seltrans->items[n], &seltrans->transforms[n]); l = l->next; n += 1; } nr_matrix_d_set_identity (&seltrans->current); seltrans->point.x = p->x; seltrans->point.y = p->y; seltrans->spp_length = sp_selection_snappoints (selection, seltrans->spp, SP_SELTRANS_SPP_SIZE); seltrans->opposit.x = seltrans->box.x0 + (1 - x) * fabs (seltrans->box.x1 - seltrans->box.x0); seltrans->opposit.y = seltrans->box.y0 + (1 - y) * fabs (seltrans->box.y1 - seltrans->box.y0); if ((x != -1) && (y != -1)) { sp_canvas_item_show (seltrans->norm); sp_canvas_item_show (seltrans->grip); } if (seltrans->show == SP_SELTRANS_SHOW_OUTLINE) { sp_canvas_item_show (seltrans->l1); sp_canvas_item_show (seltrans->l2); sp_canvas_item_show (seltrans->l3); sp_canvas_item_show (seltrans->l4); } sp_sel_trans_update_handles (seltrans); g_return_if_fail(seltrans->stamp_cache == NULL); }
void ObjectHierarchy::_trimBelow(SPObject *limit) { while ( !_hierarchy.empty() && _hierarchy.front().object != limit ) { SPObject *object=_hierarchy.front().object; sp_object_ref(object, NULL); _detach(_hierarchy.front()); _hierarchy.pop_front(); _removed_signal.emit(object); sp_object_unref(object, NULL); } }
void ObjectHierarchy::_trim_for_release(SPObject *object) { this->_trimBelow(object); assert(!this->_hierarchy.empty()); assert(this->_hierarchy.front().object == object); sp_object_ref(object, NULL); this->_detach(this->_hierarchy.front()); this->_hierarchy.pop_front(); this->_removed_signal.emit(object); sp_object_unref(object, NULL); this->_changed_signal.emit(this->top(), this->bottom()); }
/** * Callback for modified event. */ void SPGradient::modified(guint flags) { if (flags & SP_OBJECT_CHILD_MODIFIED_FLAG) { // CPPIFY // This comparison has never worked (i. e. always evaluated to false), // the right value would have been SP_TYPE_MESH //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { // if (!SP_IS_MESH(this)) { // this->invalidateVector(); // } else { // this->invalidateArray(); // } this->invalidateVector(); } if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { // CPPIFY // see above //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { // if (!SP_IS_MESH(this)) { // this->ensureVector(); // } else { // this->ensureArray(); // } this->ensureVector(); } if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; flags &= SP_OBJECT_MODIFIED_CASCADE; // FIXME: climb up the ladder of hrefs GSList *l = NULL; for (SPObject *child = this->firstChild() ; child; child = child->getNext() ) { sp_object_ref(child); l = g_slist_prepend(l, child); } l = g_slist_reverse(l); while (l) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } sp_object_unref(child); } }
void Selection::_emitChanged(bool persist_selection_context/* = false */) { if (persist_selection_context) { if (NULL == _selection_context) { _selection_context = _layers->currentLayer(); sp_object_ref(_selection_context, NULL); _context_release_connection = _selection_context->connectRelease(sigc::mem_fun(*this, &Selection::_releaseContext)); } } else { _releaseContext(_selection_context); } INKSCAPE.selection_changed(this); _changed_signal.emit(this); }
void SPTRef::modified(unsigned int flags) { if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; SPObject *child = this->stringChild; if (child) { sp_object_ref(child); if (flags || (child->mflags & SP_OBJECT_MODIFIED_FLAG)) { child->emitModified(flags); } sp_object_unref(child); } }
void SPClipPath::update(SPCtx* ctx, unsigned int flags) { if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = NULL; for ( SPObject *child = this->firstChild(); child; child = child->getNext()) { sp_object_ref(child); l = g_slist_prepend(l, child); } l = g_slist_reverse(l); while (l) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->updateDisplay(ctx, flags); } sp_object_unref(child); } for (SPClipPathView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); if (this->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX && v->bbox) { Geom::Affine t = Geom::Scale(v->bbox->dimensions()); t.setTranslation(v->bbox->min()); g->setChildTransform(t); } else { g->setChildTransform(Geom::identity()); } } }
static gint sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event) { gint ret = FALSE; SPDesktop *desktop = event_context->desktop; SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); Inkscape::SelTrans *seltrans = sc->_seltrans; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); // make sure we still have valid objects to move around if (sc->item && SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))==NULL) { sp_select_context_abort(event_context); } switch (event->type) { case GDK_BUTTON_PRESS: if (event->button.button == 1 && !event_context->space_panning) { /* Left mousebutton */ // save drag origin xp = (gint) event->button.x; yp = (gint) event->button.y; within_tolerance = true; // remember what modifiers were on before button press sc->button_press_shift = (event->button.state & GDK_SHIFT_MASK) ? true : false; sc->button_press_ctrl = (event->button.state & GDK_CONTROL_MASK) ? true : false; sc->button_press_alt = (event->button.state & GDK_MOD1_MASK) ? true : false; if (event->button.state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) { // if shift or ctrl was pressed, do not move objects; // pass the event to root handler which will perform rubberband, shift-click, ctrl-click, ctrl-drag } else { sc->dragging = TRUE; sc->moved = FALSE; desktop->setCursor(SP_SELECT_D_CURSOR); desktop->canvas->force_full_redraw_after_interruptions(5); // remember the clicked item in sc->item: if (sc->item) { sp_object_unref(sc->item, NULL); sc->item = NULL; } sc->item = sp_event_context_find_item (desktop, Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, FALSE); sp_object_ref(sc->item, NULL); rb_escaped = drag_escaped = 0; if (sc->grabbed) { sp_canvas_item_ungrab(sc->grabbed, event->button.time); sc->grabbed = NULL; } sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->drawing), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time); sc->grabbed = SP_CANVAS_ITEM(desktop->drawing); desktop->canvas->force_full_redraw_after_interruptions(5); ret = TRUE; } } else if (event->button.button == 3) { // right click; do not eat it so that right-click menu can appear, but cancel dragging & rubberband sp_select_context_abort(event_context); } break; case GDK_ENTER_NOTIFY: { if (!desktop->isWaitingCursor() && !sc->dragging) { desktop->setCursor(SP_SELECT_CURSOR); } break; } case GDK_LEAVE_NOTIFY: if (!desktop->isWaitingCursor() && !sc->dragging) desktop->setCursor(event_context->cursor_shape); break; case GDK_KEY_PRESS: if (get_group0_keyval (&event->key) == GDK_space) { if (sc->dragging && sc->grabbed) { /* stamping mode: show content mode moving */ seltrans->stamp(); ret = TRUE; } } break; default: break; } if (!ret) { if (((SPEventContextClass *) parent_class)->item_handler) ret = ((SPEventContextClass *) parent_class)->item_handler(event_context, item, event); } return ret; }
void SPUse::update(SPCtx *ctx, unsigned flags) { SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } childflags &= SP_OBJECT_MODIFIED_CASCADE; /* Set up child viewport */ if (this->x.unit == SVGLength::PERCENT) { this->x.computed = this->x.value * ictx->viewport.width(); } if (this->y.unit == SVGLength::PERCENT) { this->y.computed = this->y.value * ictx->viewport.height(); } if (this->width.unit == SVGLength::PERCENT) { this->width.computed = this->width.value * ictx->viewport.width(); } if (this->height.unit == SVGLength::PERCENT) { this->height.computed = this->height.value * ictx->viewport.height(); } cctx.viewport = Geom::Rect::from_xywh(0, 0, this->width.computed, this->height.computed); cctx.i2vp = Geom::identity(); childflags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; if (this->child) { sp_object_ref(this->child); if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem const &chi = *SP_ITEM(this->child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; this->child->updateDisplay((SPCtx *)&cctx, childflags); } sp_object_unref(this->child); } SPItem::update(ctx, flags); if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); g->setStyle(this->style); } } /* As last step set additional transform of arena group */ for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); Geom::Affine t(Geom::Translate(this->x.computed, this->y.computed)); g->setChildTransform(t); } }
void SPUse::update(SPCtx *ctx, unsigned flags) { // std::cout << "SPUse::update: " << (getId()?getId():"null") << std::endl; SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } childflags &= SP_OBJECT_MODIFIED_CASCADE; /* Set up child viewport */ if (this->x.unit == SVGLength::PERCENT) { this->x.computed = this->x.value * ictx->viewport.width(); } if (this->y.unit == SVGLength::PERCENT) { this->y.computed = this->y.value * ictx->viewport.height(); } if (this->width.unit == SVGLength::PERCENT) { this->width.computed = this->width.value * ictx->viewport.width(); } if (this->height.unit == SVGLength::PERCENT) { this->height.computed = this->height.value * ictx->viewport.height(); } childflags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; if (this->child) { sp_object_ref(this->child); // viewport is only changed if referencing a symbol or svg element if( SP_IS_SYMBOL(this->child) || SP_IS_ROOT(this->child) ) { cctx.viewport = Geom::Rect::from_xywh(0, 0, this->width.computed, this->height.computed); cctx.i2vp = Geom::identity(); } if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem const *chi = dynamic_cast<SPItem const *>(child); g_assert(chi != NULL); cctx.i2doc = chi->transform * ictx->i2doc; cctx.i2vp = chi->transform * ictx->i2vp; this->child->updateDisplay((SPCtx *)&cctx, childflags); } sp_object_unref(this->child); } SPItem::update(ctx, flags); if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); this->context_style = this->style; g->setStyle(this->style, this->context_style); } } /* As last step set additional transform of arena group */ for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); Geom::Affine t(Geom::Translate(this->x.computed, this->y.computed)); g->setChildTransform(t); } }
/** * This function will create a new tspan element with the same attributes as * the tref had and add the same text as a child. The tref is replaced in the * tree with the new tspan. * The code is based partially on sp_use_unlink */ SPObject * sp_tref_convert_to_tspan(SPObject *obj) { SPObject * new_tspan = NULL; //////////////////// // BASE CASE //////////////////// if (SP_IS_TREF(obj)) { SPTRef *tref = SP_TREF(obj); if (tref && tref->stringChild) { Inkscape::XML::Node *tref_repr = tref->getRepr(); Inkscape::XML::Node *tref_parent = tref_repr->parent(); SPDocument *document = tref->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *new_tspan_repr = xml_doc->createElement("svg:tspan"); // Add the new tspan element just after the current tref tref_parent->addChild(new_tspan_repr, tref_repr); Inkscape::GC::release(new_tspan_repr); new_tspan = document->getObjectByRepr(new_tspan_repr); // Create a new string child for the tspan Inkscape::XML::Node *new_string_repr = tref->stringChild->getRepr()->duplicate(xml_doc); new_tspan_repr->addChild(new_string_repr, NULL); //SPObject * new_string_child = document->getObjectByRepr(new_string_repr); // Merge style from the tref SPStyle *new_tspan_sty = new_tspan->style; SPStyle const *tref_sty = tref->style; sp_style_merge_from_dying_parent(new_tspan_sty, tref_sty); sp_style_merge_from_parent(new_tspan_sty, new_tspan->parent->style); new_tspan->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(tref, NULL); Inkscape::GC::anchor(tref_repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. tref->deleteObject(false); // Give the copy our old id and let go of our old repr. new_tspan_repr->setAttribute("id", tref_repr->attribute("id")); Inkscape::GC::release(tref_repr); // Establish the succession and let go of our object. tref->setSuccessor(new_tspan); sp_object_unref(tref, NULL); } } //////////////////// // RECURSIVE CASE //////////////////// else { GSList *l = NULL; for (SPObject *child = obj->firstChild() ; child != NULL ; child = child->getNext() ) { sp_object_ref(child, obj); l = g_slist_prepend (l, child); } l = g_slist_reverse (l); while (l) { SPObject *child = reinterpret_cast<SPObject *>(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); // Note that there may be more than one conversion happening here, so if it's not a // tref being passed into this function, the returned value can't be specifically known new_tspan = sp_tref_convert_to_tspan(child); sp_object_unref(child, obj); } } return new_tspan; }
SPItem *SPUse::unlink() { Inkscape::XML::Node *repr = this->getRepr(); if (!repr) { return NULL; } Inkscape::XML::Node *parent = repr->parent(); SPDocument *document = this->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); // Track the ultimate source of a chain of uses. SPItem *orig = this->root(); if (!orig) { return NULL; } // Calculate the accumulated transform, starting from the original. Geom::Affine t = this->get_root_transform(); Inkscape::XML::Node *copy = NULL; if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) { Inkscape::XML::Node *newchild = child->duplicate(xml_doc); copy->appendChild(newchild); } } else { // just copy copy = orig->getRepr()->duplicate(xml_doc); } // Add the duplicate repr just after the existing one. parent->addChild(copy, repr); // Retrieve the SPItem of the resulting repr. SPObject *unlinked = document->getObjectByRepr(copy); // Merge style from the use. unlinked->style->merge( this->style ); unlinked->style->cascade( unlinked->parent->style ); unlinked->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(this, NULL); Inkscape::GC::anchor(repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. this->deleteObject(false); // Give the copy our old id and let go of our old repr. copy->setAttribute("id", repr->attribute("id")); Inkscape::GC::release(repr); // Remove tiled clone attrs. copy->setAttribute("inkscape:tiled-clone-of", NULL); copy->setAttribute("inkscape:tile-w", NULL); copy->setAttribute("inkscape:tile-h", NULL); copy->setAttribute("inkscape:tile-cx", NULL); copy->setAttribute("inkscape:tile-cy", NULL); // Establish the succession and let go of our object. this->setSuccessor(unlinked); sp_object_unref(this, NULL); SPItem *item = dynamic_cast<SPItem *>(unlinked); g_assert(item != NULL); // Set the accummulated transform. { Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. item->doWriteTransform(item->getRepr(), t, &nomove); } return item; }