Inkscape::XML::Node *box3d_side_convert_to_path(Box3DSide *side) { // TODO: Copy over all important attributes (see sp_selected_item_to_curved_repr() for an example) SPDocument *doc = side->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("d", side->getAttribute("d")); repr->setAttribute("style", side->getAttribute("style")); return repr; }
SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = sp_desktop_document (desktop); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot"); root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create SPItem *ft_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(root_repr)); SPObject *root_object = doc->getObjectByRepr(root_repr); g_assert(SP_IS_FLOWTEXT(root_object)); Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion"); root_repr->appendChild(region_repr); SPObject *region_object = doc->getObjectByRepr(region_repr); g_assert(SP_IS_FLOWREGION(region_object)); Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path region_repr->appendChild(rect_repr); SPRect *rect = SP_RECT(doc->getObjectByRepr(rect_repr)); p0 *= desktop->dt2doc(); p1 *= desktop->dt2doc(); using Geom::X; using Geom::Y; Geom::Coord const x0 = MIN(p0[X], p1[X]); Geom::Coord const y0 = MIN(p0[Y], p1[Y]); Geom::Coord const x1 = MAX(p0[X], p1[X]); Geom::Coord const y1 = MAX(p0[Y], p1[Y]); Geom::Coord const w = x1 - x0; Geom::Coord const h = y1 - y0; rect->setPosition(x0, y0, w, h); rect->updateRepr(); Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); SPObject *para_object = doc->getObjectByRepr(para_repr); g_assert(SP_IS_FLOWPARA(para_object)); Inkscape::XML::Node *text = xml_doc->createTextNode(""); para_repr->appendChild(text); Inkscape::GC::release(root_repr); Inkscape::GC::release(region_repr); Inkscape::GC::release(para_repr); Inkscape::GC::release(rect_repr); ft_item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); return ft_item; }
static void sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *sel) { SPDocument *doc = sp_gradient_vector_selector_get_document (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); if (!doc) return; SPGradient *gr = sp_gradient_vector_selector_get_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = NULL; if (gr) { repr = gr->getRepr()->duplicate(xml_doc); } else { repr = xml_doc->createElement("svg:linearGradient"); Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "0"); stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "1"); stop->setAttribute("style", "stop-color:#fff;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); } doc->getDefs()->getRepr()->addChild(repr, NULL); Glib::ustring old_id = gr->getId(); gr = SP_GRADIENT(doc->getObjectByRepr(repr)); // Rename the new gradients id to be similar to the cloned gradients rename_id(gr, old_id); sp_gradient_vector_selector_set_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors), doc, gr); sel->selectGradientInTree(gr); Inkscape::GC::release(repr); }
SPDocument * GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) { // Determine whether the image should be embedded Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool ask = prefs->getBool("/dialogs/import/ask"); Glib::ustring link = prefs->getString("/dialogs/import/link"); bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); Glib::ustring scale = prefs->getString("/dialogs/import/scale"); // std::cout << "GkdpixbufInput::open: " // << " ask: " << ask // << ", link: " << link // << ", forcexdpi: " << forcexdpi // << ", scale: " << scale << std::endl; // std::cout << " in preferences: " // << " ask: " << !mod->get_param_bool("do_not_ask") // << ", link: " << mod->get_param_optiongroup("link") // << ", mod_dpi: " << mod->get_param_optiongroup("dpi") // << ", scale: " << mod->get_param_optiongroup("scale") << std::endl; if( ask ) { Glib::ustring mod_link = mod->get_param_optiongroup("link"); Glib::ustring mod_dpi = mod->get_param_optiongroup("dpi"); bool mod_forcexdpi = ( mod_dpi.compare( "from_default" ) == 0 ); Glib::ustring mod_scale = mod->get_param_optiongroup("scale"); if( link.compare( mod_link ) != 0 ) { link = mod_link; } prefs->setString("/dialogs/import/link", link ); if( forcexdpi != mod_forcexdpi ) { forcexdpi = mod_forcexdpi; } prefs->setBool("/dialogs/import/forcexdpi", forcexdpi ); if( scale.compare( mod_scale ) != 0 ) { scale = mod_scale; } prefs->setString("/dialogs/import/scale", scale ); prefs->setBool("/dialogs/import/ask", !mod->get_param_bool("do_not_ask") ); } bool embed = ( link.compare( "embed" ) == 0 ); SPDocument *doc = NULL; boost::scoped_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri)); // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage. // Find a way to create the pixbuf only once. if (pb) { doc = SPDocument::createNewDoc(NULL, TRUE, TRUE); bool saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); // no need to undo in this temporary document double width = pb->width(); double height = pb->height(); double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px")); //bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); ImageResolution *ir = 0; double xscale = 1; double yscale = 1; if (!ir && !forcexdpi) { ir = new ImageResolution(uri); } if (ir && ir->ok()) { xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi yscale = 900.0 / floor(10.*ir->y() + .5); } else { xscale = 90.0 / defaultxdpi; yscale = 90.0 / defaultxdpi; } width *= xscale; height *= yscale; delete ir; // deleting NULL is safe // Create image node Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); sp_repr_set_svg_double(image_node, "width", width); sp_repr_set_svg_double(image_node, "height", height); // Added 11 Feb 2014 as we now honor "preserveAspectRatio" and this is // what Inkscaper's expect. image_node->setAttribute("preserveAspectRatio", "none"); if( scale.compare( "auto" ) != 0 ) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "image-rendering", scale.c_str()); sp_repr_css_set(image_node, css, "style"); sp_repr_css_attr_unref( css ); } if (embed) { sp_embed_image(image_node, pb.get()); } else { // convert filename to uri gchar* _uri = g_filename_to_uri(uri, NULL, NULL); if(_uri) { image_node->setAttribute("xlink:href", _uri); g_free(_uri); } else { image_node->setAttribute("xlink:href", uri); } } // Add it to the current layer doc->getRoot()->appendChildRepr(image_node); Inkscape::GC::release(image_node); fit_canvas_to_drawing(doc); // Set viewBox if it doesn't exist if (!doc->getRoot()->viewBox_set) { //std::cout << "Viewbox not set, setting" << std::endl; doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit()))); } // restore undo, as now this document may be shown to the user if a bitmap was opened DocumentUndo::setUndoSensitive(doc, saved); } else { printf("GdkPixbuf loader failed\n"); } return doc; }
/** * 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; }
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(); }
static bool sp_spray_recursive(SPDesktop *desktop, Inkscape::Selection *selection, SPItem *item, Geom::Point p, Geom::Point /*vector*/, gint mode, double radius, double /*force*/, double population, double &scale, double scale_variation, bool /*reverse*/, double mean, double standard_deviation, double ratio, double tilt, double rotation_variation, gint _distrib) { bool did = false; if (SP_IS_BOX3D(item) ) { // convert 3D boxes to ordinary groups before spraying their shapes item = box3d_convert_to_group(SP_BOX3D(item)); selection->add(item); } double _fid = g_random_double_range(0, 1); double angle = g_random_double_range( - rotation_variation / 100.0 * M_PI , rotation_variation / 100.0 * M_PI ); double _scale = g_random_double_range( 1.0 - scale_variation / 100.0, 1.0 + scale_variation / 100.0 ); double dr; double dp; random_position( dr, dp, mean, standard_deviation, _distrib ); dr=dr*radius; if (mode == SPRAY_MODE_COPY) { Geom::OptRect a = item->documentVisualBounds(); if (a) { SPItem *item_copied; if(_fid <= population) { // duplicate SPDocument *doc = item->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); Inkscape::XML::Node *old_repr = item->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); parent->appendChild(copy); SPObject *new_obj = doc->getObjectByRepr(copy); item_copied = (SPItem *) new_obj; //convertion object->item Geom::Point center=item->getCenter(); sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale,_scale)); sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale,scale)); sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); //Move the cursor p Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } } } else if (mode == SPRAY_MODE_SINGLE_PATH) { SPItem *father = NULL; //initial Object SPItem *item_copied = NULL; //Projected Object SPItem *unionResult = NULL; //previous union SPItem *son = NULL; //father copy int i=1; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { SPItem *item1 = (SPItem *) items->data; if (i == 1) { father = item1; } if (i == 2) { unionResult = item1; } i++; } SPDocument *doc = father->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); Inkscape::XML::Node *old_repr = father->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); Geom::OptRect a = father->documentVisualBounds(); if (a) { if (i == 2) { Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc); parent->appendChild(copy1); SPObject *new_obj1 = doc->getObjectByRepr(copy1); son = (SPItem *) new_obj1; // conversion object->item unionResult = son; Inkscape::GC::release(copy1); } if (_fid <= population) { // Rules the population of objects sprayed // duplicates the father Inkscape::XML::Node *copy2 = old_repr->duplicate(xml_doc); parent->appendChild(copy2); SPObject *new_obj2 = doc->getObjectByRepr(copy2); item_copied = (SPItem *) new_obj2; // Move around the cursor Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); Geom::Point center=father->getCenter(); sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale)); sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale)); sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle)); sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); // union and duplication selection->clear(); selection->add(item_copied); selection->add(unionResult); sp_selected_path_union_skip_undo(selection->desktop()); selection->add(father); Inkscape::GC::release(copy2); did = true; } } } else if (mode == SPRAY_MODE_CLONE) { Geom::OptRect a = item->documentVisualBounds(); if (a) { if(_fid <= population) { SPItem *item_copied; SPDocument *doc = item->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); Inkscape::XML::Node *old_repr = item->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); // Creation of the clone Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); // Ad the clone to the list of the father's sons parent->appendChild(clone); // Generates the link between father and son attributes clone->setAttribute("xlink:href", g_strdup_printf("#%s", old_repr->attribute("id")), false); SPObject *clone_object = doc->getObjectByRepr(clone); // conversion object->item item_copied = (SPItem *) clone_object; Geom::Point center = item->getCenter(); sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale)); sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale)); sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle)); Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); Inkscape::GC::release(clone); did = true; } } } return did; }