void SPObject::deleteObject(bool propagate, bool propagate_descendants) { sp_object_ref(this, NULL); if (propagate) { _delete_signal.emit(this); } if (propagate_descendants) { this->_sendDeleteSignalRecursive(); } Inkscape::XML::Node *repr = getRepr(); if (repr && repr->parent()) { sp_repr_unparent(repr); } if (_successor) { _successor->deleteObject(propagate, propagate_descendants); } sp_object_unref(this, NULL); }
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; }
static void spdc_flush_white(FreehandBase *dc, SPCurve *gc) { SPCurve *c; if (dc->white_curves) { g_assert(dc->white_item); c = SPCurve::concat(dc->white_curves); g_slist_free(dc->white_curves); dc->white_curves = NULL; if (gc) { c->append(gc, FALSE); } } else if (gc) { c = gc; c->ref(); } else { return; } // Now we have to go back to item coordinates at last c->transform( dc->white_item ? (dc->white_item)->dt2i_affine() : dc->desktop->dt2doc() ); SPDesktop *desktop = dc->desktop; SPDocument *doc = desktop->getDocument(); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); if ( c && !c->is_empty() ) { // We actually have something to write bool has_lpe = false; Inkscape::XML::Node *repr; if (dc->white_item) { repr = dc->white_item->getRepr(); has_lpe = SP_LPE_ITEM(dc->white_item)->hasPathEffectRecursive(); } else { repr = xml_doc->createElement("svg:path"); // Set style sp_desktop_apply_style_tool(desktop, repr, tool_name(dc).data(), false); } gchar *str = sp_svg_write_path( c->get_pathvector() ); g_assert( str != NULL ); if (has_lpe) repr->setAttribute("inkscape:original-d", str); else repr->setAttribute("d", str); g_free(str); if (!dc->white_item) { // Attach repr SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); spdc_check_for_and_apply_waiting_LPE(dc, item, c); if(previous_shape_type != BEND_CLIPBOARD){ dc->selection->set(repr); } Inkscape::GC::release(repr); item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); item->updateRepr(); item->doWriteTransform(item->getRepr(), item->transform, NULL, true); if(previous_shape_type == BEND_CLIPBOARD){ repr->parent()->removeChild(repr); } } DocumentUndo::done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL, _("Draw path")); // When quickly drawing several subpaths with Shift, the next subpath may be finished and // flushed before the selection_modified signal is fired by the previous change, which // results in the tool losing all of the selected path's curve except that last subpath. To // fix this, we force the selection_modified callback now, to make sure the tool's curve is // in sync immediately. spdc_selection_modified(desktop->getSelection(), 0, dc); } c->unref(); // Flush pending updates doc->ensureUpToDate(); }
void Tracer::traceThread() { //## Remember. NEVER leave this method without setting //## engine back to NULL //## Prepare our kill flag. We will watch this later to //## see if the main thread wants us to stop keepGoing = true; SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { g_warning("Trace: No active desktop\n"); return; } Inkscape::MessageStack *msgStack = desktop->getMessageStack(); Inkscape::Selection *selection = desktop->getSelection(); if (!SP_ACTIVE_DOCUMENT) { char *msg = _("Trace: No active document"); msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); engine = NULL; return; } SPDocument *doc = SP_ACTIVE_DOCUMENT; doc->ensureUpToDate(); SPImage *img = getSelectedSPImage(); if (!img) { engine = NULL; return; } GdkPixbuf *trace_pb = gdk_pixbuf_copy(img->pixbuf->getPixbufRaw(false)); if (img->pixbuf->pixelFormat() == Inkscape::Pixbuf::PF_CAIRO) { convert_pixels_argb32_to_pixbuf( gdk_pixbuf_get_pixels(trace_pb), gdk_pixbuf_get_width(trace_pb), gdk_pixbuf_get_height(trace_pb), gdk_pixbuf_get_rowstride(trace_pb)); } Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(trace_pb, false); pixbuf = sioxProcessImage(img, pixbuf); if (!pixbuf) { char *msg = _("Trace: Image has no bitmap data"); msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); engine = NULL; return; } msgStack->flash(Inkscape::NORMAL_MESSAGE, _("Trace: Starting trace...")); desktop->updateCanvasNow(); std::vector<TracingEngineResult> results = engine->trace(pixbuf); //printf("nrPaths:%d\n", results.size()); int nrPaths = results.size(); //### Check if we should stop if (!keepGoing || nrPaths<1) { engine = NULL; return; } //### Get pointers to the <image> and its parent //XML Tree being used directly here while it shouldn't be. Inkscape::XML::Node *imgRepr = SP_OBJECT(img)->getRepr(); Inkscape::XML::Node *par = imgRepr->parent(); //### Get some information for the new transform() double x = 0.0; double y = 0.0; double width = 0.0; double height = 0.0; double dval = 0.0; if (sp_repr_get_double(imgRepr, "x", &dval)) x = dval; if (sp_repr_get_double(imgRepr, "y", &dval)) y = dval; if (sp_repr_get_double(imgRepr, "width", &dval)) width = dval; if (sp_repr_get_double(imgRepr, "height", &dval)) height = dval; double iwidth = (double)pixbuf->get_width(); double iheight = (double)pixbuf->get_height(); double iwscale = width / iwidth; double ihscale = height / iheight; Geom::Translate trans(x, y); Geom::Scale scal(iwscale, ihscale); //# Convolve scale, translation, and the original transform Geom::Affine tf(scal * trans); tf *= img->transform; //#OK. Now let's start making new nodes Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *groupRepr = NULL; //# if more than 1, make a <g>roup of <path>s if (nrPaths > 1) { groupRepr = xml_doc->createElement("svg:g"); par->addChild(groupRepr, imgRepr); } long totalNodeCount = 0L; for (unsigned int i=0 ; i<results.size() ; i++) { TracingEngineResult result = results[i]; totalNodeCount += result.getNodeCount(); Inkscape::XML::Node *pathRepr = xml_doc->createElement("svg:path"); pathRepr->setAttribute("style", result.getStyle().c_str()); pathRepr->setAttribute("d", result.getPathData().c_str()); if (nrPaths > 1) groupRepr->addChild(pathRepr, NULL); else par->addChild(pathRepr, imgRepr); //### Apply the transform from the image to the new shape SPObject *reprobj = doc->getObjectByRepr(pathRepr); if (reprobj) { SPItem *newItem = SP_ITEM(reprobj); newItem->doWriteTransform(pathRepr, tf, NULL); } if (nrPaths == 1) { selection->clear(); selection->add(pathRepr); } Inkscape::GC::release(pathRepr); } // If we have a group, then focus on, then forget it if (nrPaths > 1) { selection->clear(); selection->add(groupRepr); Inkscape::GC::release(groupRepr); } //## inform the document, so we can undo DocumentUndo::done(doc, SP_VERB_SELECTION_TRACE, _("Trace bitmap")); engine = NULL; char *msg = g_strdup_printf(_("Trace: Done. %ld nodes created"), totalNodeCount); msgStack->flash(Inkscape::NORMAL_MESSAGE, msg); g_free(msg); }