gchar * sp_svg_write_path(Geom::Path const &p) { Inkscape::SVG::PathString str; sp_svg_write_path(str, p); return g_strdup(str.c_str()); }
Inkscape::XML::Node* SPStar::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:path"); } if (flags & SP_OBJECT_WRITE_EXT) { repr->setAttribute("sodipodi:type", "star"); sp_repr_set_int (repr, "sodipodi:sides", this->sides); sp_repr_set_svg_double(repr, "sodipodi:cx", this->center[Geom::X]); sp_repr_set_svg_double(repr, "sodipodi:cy", this->center[Geom::Y]); sp_repr_set_svg_double(repr, "sodipodi:r1", this->r[0]); sp_repr_set_svg_double(repr, "sodipodi:r2", this->r[1]); sp_repr_set_svg_double(repr, "sodipodi:arg1", this->arg[0]); sp_repr_set_svg_double(repr, "sodipodi:arg2", this->arg[1]); sp_repr_set_boolean (repr, "inkscape:flatsided", this->flatsided); sp_repr_set_svg_double(repr, "inkscape:rounded", this->rounded); sp_repr_set_svg_double(repr, "inkscape:randomized", this->randomized); } this->set_shape(); char *d = sp_svg_write_path (this->_curve->get_pathvector()); repr->setAttribute("d", d); g_free(d); // CPPIFY: see header file SPShape::write(xml_doc, repr, flags); return repr; }
Inkscape::XML::Node* Box3DSide::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { // this is where we end up when saving as plain SVG (also in other circumstances?) // thus we don' set "sodipodi:type" so that the box is only saved as an ordinary svg:path repr = xml_doc->createElement("svg:path"); } if (flags & SP_OBJECT_WRITE_EXT) { sp_repr_set_int(repr, "inkscape:box3dsidetype", this->dir1 ^ this->dir2 ^ this->front_or_rear); } this->set_shape(); /* Duplicate the path */ SPCurve const *curve = this->_curve; //Nulls might be possible if this called iteratively if ( !curve ) { return NULL; } char *d = sp_svg_write_path ( curve->get_pathvector() ); repr->setAttribute("d", d); g_free (d); SPPolygon::write(xml_doc, repr, flags); return repr; }
static SPRepr * sp_spiral_write (SPObject *object, SPRepr *repr, guint flags) { SPSpiral *spiral; char *d; spiral = SP_SPIRAL (object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = sp_repr_new ("path"); } if (flags & SP_OBJECT_WRITE_EXT) { /* Fixme: we may replace these attributes by * sodipodi:spiral="cx cy exp revo rad arg t0" */ sp_repr_set_attr (repr, "sodipodi:type", "spiral"); sp_repr_set_double_attribute (repr, "sodipodi:cx", spiral->cx); sp_repr_set_double_attribute (repr, "sodipodi:cy", spiral->cy); sp_repr_set_double_attribute (repr, "sodipodi:expansion", spiral->exp); sp_repr_set_double_attribute (repr, "sodipodi:revolution", spiral->revo); sp_repr_set_double_attribute (repr, "sodipodi:radius", spiral->rad); sp_repr_set_double_attribute (repr, "sodipodi:argument", spiral->arg); sp_repr_set_double_attribute (repr, "sodipodi:t0", spiral->t0); } d = sp_svg_write_path (((SPShape *) spiral)->curve->bpath); sp_repr_set_attr (repr, "d", d); g_free (d); if (((SPObjectClass *) (parent_class))->write) ((SPObjectClass *) (parent_class))->write (object, repr, flags | SP_SHAPE_WRITE_PATH); return repr; }
gchar * sp_svg_write_path(Geom::PathVector const &p) { Inkscape::SVG::PathString str; for(Geom::PathVector::const_iterator pit = p.begin(); pit != p.end(); ++pit) { sp_svg_write_path(str, *pit); } return g_strdup(str.c_str()); }
void sp_selected_path_reverse(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList *items = (GSList *) selection->itemList(); if (!items) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to reverse.")); return; } // set "busy" cursor desktop->setWaitingCursor(); bool did = false; desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Reversing paths...")); for (GSList *i = items; i != NULL; i = i->next) { if (!SP_IS_PATH(i->data)) continue; did = true; SPPath *path = SP_PATH(i->data); SPCurve *rcurve = sp_path_get_curve_reference(path)->create_reverse(); gchar *str = sp_svg_write_path(rcurve->get_pathvector()); if ( sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(path)) ) { SP_OBJECT_REPR(path)->setAttribute("inkscape:original-d", str); } else { SP_OBJECT_REPR(path)->setAttribute("d", str); } g_free(str); rcurve->unref(); // reverse nodetypes order (Bug #179866) gchar *nodetypes = g_strdup(SP_OBJECT_REPR(path)->attribute("sodipodi:nodetypes")); if ( nodetypes ) { SP_OBJECT_REPR(path)->setAttribute("sodipodi:nodetypes", g_strreverse(nodetypes)); g_free(nodetypes); } } desktop->clearWaitingCursor(); if (did) { sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_REVERSE, _("Reverse path")); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No paths</b> to reverse in the selection.")); } }
void SPLPEItem::apply_to_clippath(SPItem *item) { SPClipPath *clipPath = item->clip_ref->getObject(); if(clipPath) { SPObject * clip_data = clipPath->firstChild(); SPCurve * clip_curve = NULL; if (SP_IS_PATH(clip_data)) { clip_curve = SP_PATH(clip_data)->get_original_curve(); } else if(SP_IS_SHAPE(clip_data)) { clip_curve = SP_SHAPE(clip_data)->getCurve(); } else if(SP_IS_GROUP(clip_data)) { apply_to_clip_or_mask_group(SP_ITEM(clip_data), item); return; } if(clip_curve) { bool success = false; if(SP_IS_GROUP(this)){ clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this))); success = this->performPathEffect(clip_curve); clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse()); } else { success = this->performPathEffect(clip_curve); } Inkscape::XML::Node *reprClip = clip_data->getRepr(); if (success) { gchar *str = sp_svg_write_path(clip_curve->get_pathvector()); reprClip->setAttribute("d", str); g_free(str); } else { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = reprClip->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } clip_curve->unref(); } } if(SP_IS_GROUP(item)){ GSList const *item_list = sp_item_group_item_list(SP_GROUP(item)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); apply_to_clippath(SP_ITEM(subitem)); } } }
/** * * Writes the path object into a Inkscape::XML::Node */ static Inkscape::XML::Node * sp_path_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPShape *shape = (SPShape *) object; if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:path"); } #ifdef PATH_VERBOSE g_message("sp_path_write writes 'd' attribute"); #endif if ( shape->_curve != NULL ) { gchar *str = sp_svg_write_path(shape->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } if (flags & SP_OBJECT_WRITE_EXT) { if ( shape->_curve_before_lpe != NULL ) { gchar *str = sp_svg_write_path(shape->_curve_before_lpe->get_pathvector()); repr->setAttribute("inkscape:original-d", str); g_free(str); } else { repr->setAttribute("inkscape:original-d", NULL); } } SP_PATH(shape)->connEndPair.writeRepr(repr); if (((SPObjectClass *)(parent_class))->write) { ((SPObjectClass *)(parent_class))->write(object, xml_doc, repr, flags); } return repr; }
void SPStar::update_patheffect(bool write) { this->set_shape(); if (write) { Inkscape::XML::Node *repr = this->getRepr(); if ( this->_curve != NULL ) { gchar *str = sp_svg_write_path(this->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } } this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); }
/* * set_elliptical_path_attribute: * * Convert center to endpoint parameterization and set it to repr. * * See SVG 1.0 Specification W3C Recommendation * ``F.6 Ellptical arc implementation notes'' for more detail. */ bool SPGenericEllipse::set_elliptical_path_attribute(Inkscape::XML::Node *repr) { // Make sure our pathvector is up to date. this->set_shape(); if (this->getCurve() != NULL) { gchar* d = sp_svg_write_path(this->getCurve()->get_pathvector()); repr->setAttribute("d", d); g_free(d); } else { repr->setAttribute("d", NULL); } return true; }
static void sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) { SPShape * const shape = (SPShape *) lpeitem; Inkscape::XML::Node *repr = shape->getRepr(); #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect"); #endif if (shape->_curve_before_lpe && sp_lpe_item_has_path_effect_recursive(lpeitem)) { SPCurve *curve = shape->_curve_before_lpe->copy(); /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe. * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ shape->setCurveInsync(curve, TRUE); bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve); if (success && write) { // could also do shape->getRepr()->updateRepr(); but only the d attribute needs updating. #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect writes 'd' attribute"); #endif if ( shape->_curve != NULL ) { gchar *str = sp_svg_write_path(shape->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } } else if (!success) { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = repr->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { shape->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); curve->unref(); } }
/** * Writes the given transform into the repr for the given item. */ static void sp_path_write_transform (SPItem *item, SPRepr *repr, NRMatrixF *transform) { SPPath *path; SPShape *shape; NRBPath dpath, spath; double ex; gchar *svgpath; SPStyle *style; path = (SPPath *) item; shape = (SPShape *) item; /* Calculate the DF */ ex = NR_MATRIX_DF_EXPANSION (transform); /* Take the path for the shape, write it as an svgpath, and add it to the repr */ spath.path = shape->curve->bpath; nr_path_duplicate_transform (&dpath, &spath, transform); svgpath = sp_svg_write_path (dpath.path); sp_repr_set_attr (repr, "d", svgpath); g_free (svgpath); nr_free (dpath.path); /* Wrte the style info into the repr */ style = SP_OBJECT_STYLE (item); if (style->stroke.type != SP_PAINT_TYPE_NONE) { if (!NR_DF_TEST_CLOSE (ex, 1.0, NR_EPSILON_D)) { gchar *str; /* Scale changed, so we have to adjust stroke width */ style->stroke_width.computed *= ex; if (style->stroke_dash.n_dash != 0) { int i; for (i = 0; i < style->stroke_dash.n_dash; i++) style->stroke_dash.dash[i] *= ex; style->stroke_dash.offset *= ex; } str = sp_style_write_difference (style, SP_OBJECT_STYLE (SP_OBJECT_PARENT (item))); sp_repr_set_attr (repr, "style", str); g_free (str); } } sp_repr_set_attr (repr, "transform", NULL); }
/** * * Writes the path object into a SPRepr */ static SPRepr * sp_path_write (SPObject *object, SPRepr *repr, guint flags) { SPShape *shape; ArtBpath *abp; gchar *str; shape = (SPShape *) object; if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = sp_repr_new ("path"); } abp = sp_curve_first_bpath (shape->curve); str = sp_svg_write_path (abp); sp_repr_set_attr (repr, "d", str); g_free (str); if (((SPObjectClass *) (parent_class))->write) { ((SPObjectClass *) (parent_class))->write (object, repr, flags); } return repr; }
static void spdc_flush_white (SPDrawContext *dc, SPCurve *gc) { SPCurve *c; if (dc->white_curves) { g_assert (dc->white_item); c = sp_curve_concat (dc->white_curves); g_slist_free (dc->white_curves); dc->white_curves = NULL; if (gc) { sp_curve_append (c, gc, FALSE); } } else if (gc) { c = gc; sp_curve_ref (c); } else { return; } /* Now we have to go back to item coordinates at last */ if (dc->white_item) { NRMatrixD d2itemd; sp_item_dt2i_affine_d (dc->white_item, SP_EVENT_CONTEXT_DESKTOP (dc), &d2itemd); c = sp_curve_transform (c, NR_MATRIX_D_TO_DOUBLE (&d2itemd)); } else { gdouble d2item[6]; sp_desktop_dt2root_affine (SP_EVENT_CONTEXT_DESKTOP (dc), (NRMatrixD *) d2item); c = sp_curve_transform (c, d2item); } if (c && !sp_curve_empty (c)) { SPDesktop *dt; SPDocument *doc; SPRepr *repr; gchar *str; /* We actually have something to write */ dt = SP_EVENT_CONTEXT_DESKTOP (dc); doc = SP_DT_DOCUMENT (dt); if (dc->white_item) { repr = SP_OBJECT_REPR (dc->white_item); } else { SPRepr *style; repr = sp_repr_new ("path"); /* fixme: Pen and pencil need separate style (Lauris) */ style = inkscape_get_repr (INKSCAPE, "tools.freehand"); if (style) { SPCSSAttr *css; css = sp_repr_css_attr_inherited (style, "style"); sp_repr_css_set (repr, css, "style"); sp_repr_css_attr_unref (css); } } str = sp_svg_write_path (SP_CURVE_BPATH (c)); g_assert (str != NULL); sp_repr_set_attr (repr, "d", str); g_free (str); if (!dc->white_item) { /* Attach repr */ sp_document_add_repr (SP_DT_DOCUMENT (dt), repr); sp_selection_set_repr (dc->selection, repr); sp_repr_unref (repr); } sp_document_done (doc); } sp_curve_unref (c); /* Flush pending updates */ sp_document_ensure_up_to_date (SP_DT_DOCUMENT (SP_EVENT_CONTEXT_DESKTOP (dc))); }
Inkscape::XML::Node * sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) { if (!item) return NULL; Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { // Special treatment for text: convert each glyph to separate path, then group the paths Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g"); g_repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform")); /* Mask */ gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask"); if ( mask_str ) g_repr->setAttribute("mask", mask_str); /* Clip path */ gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path"); if ( clip_path_str ) g_repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ g_repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false); g_repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false); /* Whole text's style */ gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item), SP_OBJECT_STYLE(SP_OBJECT_PARENT(item))); g_repr->setAttribute("style", style_str); g_free(style_str); Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); do { Inkscape::Text::Layout::iterator iter_next = iter; iter_next.nextGlyph(); // iter_next is one glyph ahead from iter if (iter == iter_next) break; /* This glyph's style */ SPObject const *pos_obj = 0; void *rawptr = 0; te_get_layout(item)->getSourceOfCharacter(iter, &rawptr); if (!rawptr || !SP_IS_OBJECT(rawptr)) // no source for glyph, abort break; pos_obj = SP_OBJECT(rawptr); while (SP_IS_STRING(pos_obj) && SP_OBJECT_PARENT(pos_obj)) { pos_obj = SP_OBJECT_PARENT(pos_obj); // SPStrings don't have style } gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(pos_obj), SP_OBJECT_STYLE(SP_OBJECT_PARENT(pos_obj))); // get path from iter to iter_next: SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next); iter = iter_next; // shift to next glyph if (!curve) { // error converting this glyph g_free (style_str); continue; } if (curve->is_empty()) { // whitespace glyph? curve->unref(); g_free (style_str); continue; } Inkscape::XML::Node *p_repr = xml_doc->createElement("svg:path"); gchar *def_str = sp_svg_write_path(curve->get_pathvector()); p_repr->setAttribute("d", def_str); g_free(def_str); curve->unref(); p_repr->setAttribute("style", style_str); g_free(style_str); g_repr->appendChild(p_repr); Inkscape::GC::release(p_repr); if (iter == te_get_layout(item)->end()) break; } while (true); return g_repr; } SPCurve *curve = NULL; if (SP_IS_SHAPE(item)) { curve = sp_shape_get_curve(SP_SHAPE(item)); } if (!curve) return NULL; // Prevent empty paths from being added to the document // otherwise we end up with zomby markup in the SVG file if(curve->is_empty()) { curve->unref(); return NULL; } Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); /* Transformation */ repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform")); /* Style */ gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item), SP_OBJECT_STYLE(SP_OBJECT_PARENT(item))); repr->setAttribute("style", style_str); g_free(style_str); /* Mask */ gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask"); if ( mask_str ) repr->setAttribute("mask", mask_str); /* Clip path */ gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path"); if ( clip_path_str ) repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false); repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false); /* Definition */ gchar *def_str = sp_svg_write_path(curve->get_pathvector()); repr->setAttribute("d", def_str); g_free(def_str); curve->unref(); return repr; }
void sp_selected_path_combine(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *doc = sp_desktop_document(desktop); if (g_slist_length((GSList *) selection->itemList()) < 1) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to combine.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Combining paths...")); // set "busy" cursor desktop->setWaitingCursor(); GSList *items = g_slist_copy((GSList *) selection->itemList()); items = sp_degroup_list (items); // descend into any groups in selection GSList *to_paths = NULL; for (GSList *i = items; i != NULL; i = i->next) { SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item) && !SP_IS_GROUP(item)) to_paths = g_slist_prepend(to_paths, item); } GSList *converted = NULL; bool did = sp_item_list_to_curves(to_paths, &items, &converted); g_slist_free(to_paths); for (GSList *i = converted; i != NULL; i = i->next) items = g_slist_prepend(items, doc->getObjectByRepr((Inkscape::XML::Node*)(i->data))); items = sp_degroup_list (items); // converting to path may have added more groups, descend again items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position); items = g_slist_reverse(items); // remember the position, id, transform and style of the topmost path, they will be assigned to the combined one gint position = 0; char const *id = NULL; char const *transform = NULL; gchar *style = NULL; gchar *path_effect = NULL; SPCurve* curve = 0; SPItem *first = NULL; Inkscape::XML::Node *parent = NULL; if (did) { selection->clear(); } for (GSList *i = items; i != NULL; i = i->next) { // going from top to bottom SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item)) continue; if (!did) { selection->clear(); did = true; } SPCurve *c = sp_path_get_curve_for_edit(SP_PATH(item)); if (first == NULL) { // this is the topmost path first = item; parent = SP_OBJECT_REPR(first)->parent(); position = SP_OBJECT_REPR(first)->position(); id = SP_OBJECT_REPR(first)->attribute("id"); transform = SP_OBJECT_REPR(first)->attribute("transform"); // FIXME: merge styles of combined objects instead of using the first one's style style = g_strdup(SP_OBJECT_REPR(first)->attribute("style")); path_effect = g_strdup(SP_OBJECT_REPR(first)->attribute("inkscape:path-effect")); //c->transform(item->transform); curve = c; } else { c->transform(item->getRelativeTransform(SP_OBJECT(first))); curve->append(c, false); c->unref(); } // unless this is the topmost object, if (item != first) { // reduce position only if the same parent if (SP_OBJECT_REPR(item)->parent() == parent) position--; // delete the object for real, so that its clones can take appropriate action SP_OBJECT(item)->deleteObject(); } } g_slist_free(items); if (did) { SP_OBJECT(first)->deleteObject(false); // delete the topmost. Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc()); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); // restore id, transform, path effect, and style repr->setAttribute("id", id); if (transform) repr->setAttribute("transform", transform); repr->setAttribute("style", style); g_free(style); repr->setAttribute("inkscape:path-effect", path_effect); g_free(path_effect); // set path data corresponding to new curve gchar *dstring = sp_svg_write_path(curve->get_pathvector()); curve->unref(); if (path_effect) repr->setAttribute("inkscape:original-d", dstring); else repr->setAttribute("d", dstring); g_free(dstring); // add the new group to the parent of the topmost parent->appendChild(repr); // move to the position of the topmost, reduced by the number of deleted items repr->setPosition(position > 0 ? position : 0); sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_COMBINE, _("Combine")); selection->set(repr); Inkscape::GC::release(repr); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to combine in the selection.")); } desktop->clearWaitingCursor(); }
void sp_selected_path_break_apart(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); if (selection->isEmpty()) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to break apart.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Breaking apart paths...")); // set "busy" cursor desktop->setWaitingCursor(); bool did = false; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { SPItem *item = (SPItem *) items->data; if (!SP_IS_PATH(item)) continue; SPPath *path = SP_PATH(item); SPCurve *curve = sp_path_get_curve_for_edit(SP_PATH(path)); if (curve == NULL) continue; did = true; Inkscape::XML::Node *parent = SP_OBJECT_REPR(item)->parent(); gint pos = SP_OBJECT_REPR(item)->position(); char const *id = SP_OBJECT_REPR(item)->attribute("id"); gchar *style = g_strdup(SP_OBJECT(item)->repr->attribute("style")); gchar *path_effect = g_strdup(SP_OBJECT(item)->repr->attribute("inkscape:path-effect")); Geom::PathVector apv = curve->get_pathvector() * SP_ITEM(path)->transform; curve->unref(); // it's going to resurrect as one of the pieces, so we delete without advertisement SP_OBJECT(item)->deleteObject(false); curve = new SPCurve(apv); g_assert(curve != NULL); GSList *list = curve->split(); curve->unref(); GSList *reprs = NULL; for (GSList *l = list; l != NULL; l = l->next) { curve = (SPCurve *) l->data; Inkscape::XML::Node *repr = parent->document()->createElement("svg:path"); repr->setAttribute("style", style); repr->setAttribute("inkscape:path-effect", path_effect); gchar *str = sp_svg_write_path(curve->get_pathvector()); if (path_effect) repr->setAttribute("inkscape:original-d", str); else repr->setAttribute("d", str); g_free(str); // add the new repr to the parent parent->appendChild(repr); // move to the saved position repr->setPosition(pos > 0 ? pos : 0); // if it's the first one, restore id if (l == list) repr->setAttribute("id", id); reprs = g_slist_prepend (reprs, repr); Inkscape::GC::release(repr); } selection->setReprList(reprs); g_slist_free(reprs); g_slist_free(list); g_free(style); g_free(path_effect); } desktop->clearWaitingCursor(); if (did) { sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_BREAK_APART, _("Break apart")); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to break apart in the selection.")); } }