=== modified file 'src/splivarot.cpp' --- src/splivarot.cpp 2016-02-13 01:41:52 +0000 +++ src/splivarot.cpp 2016-03-13 12:45:08 +0000 @@ -849,7 +849,8 @@ static void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine marker_transform, Geom::Scale stroke_scale, Geom::Affine transform, - Inkscape::XML::Node *g_repr, Inkscape::XML::Document *xml_doc, SPDocument * doc ) + Inkscape::XML::Node *g_repr, Inkscape::XML::Document *xml_doc, SPDocument * doc, + SPDesktop *desktop) { SPMarker* marker = SP_MARKER (marker_object); SPItem* marker_item = sp_item_first_item_child(marker_object); @@ -869,8 +870,11 @@ if (marker_item->getRepr()) { Inkscape::XML::Node *m_repr = marker_item->getRepr()->duplicate(xml_doc); g_repr->appendChild(m_repr); + //There is a special group to markers whith this reverse the order in clussion + m_repr->setPosition(0); SPItem *marker_item = (SPItem *) doc->getObjectByRepr(m_repr); marker_item->doWriteTransform(m_repr, tr); + sp_item_path_outline(marker_item, desktop); } } @@ -1144,74 +1148,86 @@ return ret_pathv; } -void -sp_selected_path_outline(SPDesktop *desktop) +bool +sp_item_path_outline(SPItem *item, SPDesktop *desktop) { + bool did = false; Inkscape::Selection *selection = desktop->getSelection(); - - if (selection->isEmpty()) { - desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select stroked path(s) to convert stroke to path.")); - return; - } - - bool did = false; - std::vector il(selection->itemList()); - for (std::vector::const_iterator l = il.begin(); l != il.end(); l++){ - SPItem *item = *l; - - if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item)) - continue; - - SPCurve *curve = NULL; - if (SP_IS_SHAPE(item)) { - curve = SP_SHAPE(item)->getCurve(); - if (curve == NULL) - continue; - } - if (SP_IS_TEXT(item)) { - curve = SP_TEXT(item)->getNormalizedBpath(); - if (curve == NULL) - continue; - } - - g_assert(curve != NULL); - - if (curve->get_pathvector().empty()) { - continue; - } - - // pas de stroke pas de chocolat - if (!item->style || item->style->stroke.noneSet) { - curve->unref(); - continue; - } - - // remember old stroke style, to be set on fill - SPStyle *i_style = item->style; - SPCSSAttr *ncss = 0; - { - ncss = sp_css_attr_from_style(i_style, SP_STYLE_FLAG_ALWAYS); - gchar const *s_val = sp_repr_css_property(ncss, "stroke", NULL); - gchar const *s_opac = sp_repr_css_property(ncss, "stroke-opacity", NULL); - - sp_repr_css_set_property(ncss, "stroke", "none"); - sp_repr_css_set_property(ncss, "stroke-opacity", "1.0"); - sp_repr_css_set_property(ncss, "fill", s_val); - if ( s_opac ) { - sp_repr_css_set_property(ncss, "fill-opacity", s_opac); - } else { - sp_repr_css_set_property(ncss, "fill-opacity", "1.0"); - } - sp_repr_css_unset_property(ncss, "marker-start"); - sp_repr_css_unset_property(ncss, "marker-mid"); - sp_repr_css_unset_property(ncss, "marker-end"); - } - - Geom::Affine const transform(item->transform); - float const scale = transform.descrim(); - gchar const *mask = item->getRepr()->attribute("mask"); - gchar const *clip_path = item->getRepr()->attribute("clip-path"); - + if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item)) + return did; + + SPCurve *curve = NULL; + if (SP_IS_SHAPE(item)) { + curve = SP_SHAPE(item)->getCurve(); + if (curve == NULL) + return did; + } + if (SP_IS_TEXT(item)) { + curve = SP_TEXT(item)->getNormalizedBpath(); + if (curve == NULL) + return did; + } + + g_assert(curve != NULL); + + if (curve->get_pathvector().empty()) { + return did; + } + + // pas de stroke pas de chocolat + if (!item->style) { + curve->unref(); + return did; + } + + // remember old stroke style, to be set on fill + SPStyle *i_style = item->style; + //Stroke - and markers + SPCSSAttr *ncss = 0; + { + ncss = sp_css_attr_from_style(i_style, SP_STYLE_FLAG_ALWAYS); + gchar const *s_val = sp_repr_css_property(ncss, "stroke", NULL); + gchar const *s_opac = sp_repr_css_property(ncss, "stroke-opacity", NULL); + + sp_repr_css_set_property(ncss, "stroke", "none"); + sp_repr_css_set_property(ncss, "stroke-opacity", "1.0"); + sp_repr_css_set_property(ncss, "fill", s_val); + if ( s_opac ) { + sp_repr_css_set_property(ncss, "fill-opacity", s_opac); + } else { + sp_repr_css_set_property(ncss, "fill-opacity", "1.0"); + } + sp_repr_css_unset_property(ncss, "marker-start"); + sp_repr_css_unset_property(ncss, "marker-mid"); + sp_repr_css_unset_property(ncss, "marker-end"); + } + //fill + SPCSSAttr *ncsf = 0; + { + ncsf = sp_css_attr_from_style(i_style, SP_STYLE_FLAG_ALWAYS); + sp_repr_css_set_property(ncsf, "stroke", "none"); + sp_repr_css_set_property(ncsf, "stroke-opacity", "1.0"); + sp_repr_css_unset_property(ncsf, "marker-start"); + sp_repr_css_unset_property(ncsf, "marker-mid"); + sp_repr_css_unset_property(ncsf, "marker-end"); + } + + Geom::Affine const transform(item->transform); + float const scale = transform.descrim(); + gchar const *mask = item->getRepr()->attribute("mask"); + gchar const *clip_path = item->getRepr()->attribute("clip-path"); + + Path *orig = new Path; + Path *res = new Path; + SPCurve *curvetemp = curve_for_item(item); + if (curvetemp == NULL) { + curve->unref(); + return did; + } + // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly. + Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curvetemp->get_pathvector() ); + curvetemp->unref(); + if ( !item->style->stroke.noneSet ) { float o_width, o_miter; JoinType o_join; ButtType o_butt; @@ -1252,19 +1268,8 @@ o_miter = i_style->stroke_miterlimit.value * o_width; } - SPCurve *curvetemp = curve_for_item(item); - if (curvetemp == NULL) { - curve->unref(); - continue; - } - // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly. - Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curvetemp->get_pathvector() ); - curvetemp->unref(); - Path *orig = new Path; orig->LoadPathVector(pathv); - - Path *res = new Path; res->SetBackData(false); if (!i_style->stroke_dasharray.values.empty()) { @@ -1318,75 +1323,99 @@ // ca a merdĀŽ, ou bien le resultat est vide delete res; delete orig; - continue; + return did; } - - did = true; - - // remember the position of the item - gint pos = item->getRepr()->position(); - // remember parent - Inkscape::XML::Node *parent = item->getRepr()->parent(); - // remember id - char const *id = item->getRepr()->attribute("id"); - // remember title - gchar *title = item->title(); - // remember description - gchar *desc = item->desc(); - - if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether - + } + // remember the position of the item + gint pos = item->getRepr()->position(); + // remember parent + Inkscape::XML::Node *parent = item->getRepr()->parent(); + // remember id + char const *id = item->getRepr()->attribute("id"); + // remember title + gchar *title = item->title(); + // remember description + gchar *desc = item->desc(); + + if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether + + //The stroke + Inkscape::XML::Node *stroke = NULL; + if( !item->style->stroke.noneSet ){ SPDocument * doc = desktop->getDocument(); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); + stroke = xml_doc->createElement("svg:path"); // restore old style, but set old stroke style on fill - sp_repr_css_change(repr, ncss, "style"); + sp_repr_css_change(stroke, ncss, "style"); sp_repr_css_attr_unref(ncss); gchar *str = orig->svg_dump_path(); - repr->setAttribute("d", str); + stroke->setAttribute("d", str); g_free(str); if (mask) - repr->setAttribute("mask", mask); + stroke->setAttribute("mask", mask); if (clip_path) - repr->setAttribute("clip-path", clip_path); - - if (SP_IS_SHAPE(item) && SP_SHAPE(item)->hasMarkers ()) { - - Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g"); - - // add the group to the parent - parent->appendChild(g_repr); - // move to the saved position - g_repr->setPosition(pos > 0 ? pos : 0); - - g_repr->appendChild(repr); - // restore title, description, id, transform - repr->setAttribute("id", id); - SPItem *newitem = (SPItem *) doc->getObjectByRepr(repr); - newitem->doWriteTransform(repr, transform); - if (title) { - newitem->setTitle(title); - } - if (desc) { - newitem->setDesc(desc); - } - - SPShape *shape = SP_SHAPE(item); - - Geom::PathVector const & pathv = curve->get_pathvector(); - + stroke->setAttribute("clip-path", clip_path); + } + + if (SP_IS_SHAPE(item)) { + SPDocument * doc = desktop->getDocument(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g"); + + // add the group to the parent + parent->appendChild(g_repr); + // move to the saved position + g_repr->setPosition(pos > 0 ? pos : 0); + + //The fill + + Inkscape::XML::Node *fill = NULL; + gchar const *f_val = sp_repr_css_property(ncsf, "fill", NULL); + if (f_val) { + fill = xml_doc->createElement("svg:path"); + sp_repr_css_change(fill, ncsf, "style"); + + sp_repr_css_attr_unref(ncsf); + + gchar *str = sp_svg_write_path( pathv ); + fill->setAttribute("d", str); + g_free(str); + + if (mask) + fill->setAttribute("mask", mask); + if (clip_path) + fill->setAttribute("clip-path", clip_path); + } + // restore title, description, id, transform + g_repr->setAttribute("id", id); + SPItem *newitem = (SPItem *) doc->getObjectByRepr(g_repr); + newitem->doWriteTransform(g_repr, transform); + if (title) { + newitem->setTitle(title); + } + if (desc) { + newitem->setDesc(desc); + } + + SPShape *shape = SP_SHAPE(item); + + Geom::PathVector const & pathv = curve->get_pathvector(); + Inkscape::XML::Node *markers = NULL; + if(SP_SHAPE(item)->hasMarkers ()) { + markers = xml_doc->createElement("svg:g"); + g_repr->appendChild(markers); + markers->setPosition(pos > 0 ? pos : 0); // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( SPObject *marker_obj = shape->_marker[i] ) { Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); sp_selected_path_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, - g_repr, xml_doc, doc ); + markers, xml_doc, doc, desktop ); } } // MID marker @@ -1401,7 +1430,7 @@ Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front())); sp_selected_path_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, - g_repr, xml_doc, doc ); + markers, xml_doc, doc, desktop ); } // MID position if (path_it->size_default() > 1) { @@ -1414,9 +1443,9 @@ * there should be a midpoint marker between last segment and closing straight line segment */ Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); - sp_selected_path_outline_add_marker(midmarker_obj, m, - Geom::Scale(i_style->stroke_width.computed), transform, - g_repr, xml_doc, doc); + sp_selected_path_outline_add_marker( midmarker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + markers, xml_doc, doc, desktop ); ++curve_it1; ++curve_it2; @@ -1428,7 +1457,7 @@ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); sp_selected_path_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, - g_repr, xml_doc, doc ); + markers, xml_doc, doc, desktop ); } } } @@ -1447,61 +1476,157 @@ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); sp_selected_path_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, - g_repr, xml_doc, doc ); - } - } - //bug lp:1290573 : completely destroy the old object first - curve->unref(); + markers, xml_doc, doc, desktop ); + } + } + if (mask) + markers->setAttribute("mask", mask); + if (clip_path) + markers->setAttribute("clip-path", clip_path); + } + gchar const *paint_order = sp_repr_css_property(ncss, "paint-order", NULL); + SPIPaintOrder temp; + temp.read( paint_order ); + if (temp.layer[0] != SP_CSS_PAINT_ORDER_NORMAL) { + + if (temp.layer[0] == SP_CSS_PAINT_ORDER_FILL) { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_STROKE) { + if ( fill ) { + g_repr->appendChild(fill); + } + if ( stroke ) { + g_repr->appendChild(stroke); + } + if ( markers ) { + markers->setPosition(2); + } + } else { + if ( fill ) { + g_repr->appendChild(fill); + } + if ( markers ) { + markers->setPosition(1); + } + if ( stroke ) { + g_repr->appendChild(stroke); + } + } + } else if (temp.layer[0] == SP_CSS_PAINT_ORDER_STROKE) { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_FILL) { + if ( stroke ) { + g_repr->appendChild(stroke); + } + if ( fill ) { + g_repr->appendChild(fill); + } + if ( markers ) { + markers->setPosition(2); + } + } else { + if ( stroke ) { + g_repr->appendChild(stroke); + } + if ( markers ) { + markers->setPosition(1); + } + if ( fill ) { + g_repr->appendChild(fill); + } + } + } else { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_STROKE) { + if ( markers ) { + markers->setPosition(0); + } + if ( stroke ) { + g_repr->appendChild(stroke); + } + if ( fill ) { + g_repr->appendChild(fill); + } + } else { + if ( markers ) { + markers->setPosition(0); + } + if ( fill ) { + g_repr->appendChild(fill); + } + if ( stroke ) { + g_repr->appendChild(stroke); + } + } + } + + } else { + if ( fill ) { + g_repr->appendChild(fill); + } + if ( stroke ) { + g_repr->appendChild(stroke); + } + if ( markers ) { + markers->setPosition(2); + } + } + if( fill || stroke || markers ) { + did = true; + } + if (!fill && !markers) { + g_repr = stroke; + } + if (!fill && !stroke) { + g_repr = markers; + } + if (!markers && !stroke) { + g_repr = fill; + } + + //bug lp:1290573 : completely destroy the old object first + curve->unref(); + //Check for recursive markers to path + if( selection->includes(item) ){ selection->remove(item); item->deleteObject(false); - selection->add(g_repr); - - Inkscape::GC::release(g_repr); - - } else - { - //lp:1290573 - curve->unref(); - selection->remove(item); + } else { item->deleteObject(false); - - // add the new repr to the parent - parent->appendChild(repr); - - // move to the saved position - repr->setPosition(pos > 0 ? pos : 0); - - // restore title, description, id, transform - repr->setAttribute("id", id); - - SPItem *newitem = (SPItem *) desktop->getDocument()->getObjectByRepr(repr); - newitem->doWriteTransform(repr, transform); - if (title) { - newitem->setTitle(title); - } - if (desc) { - newitem->setDesc(desc); - } - - selection->add(repr); - } - - Inkscape::GC::release(repr); - - } - if (title) { - g_free(title); - title = 0; - } - if (desc) { - g_free(desc); - desc = 0; - } - - delete res; - delete orig; + Inkscape::GC::release(g_repr); + + } + } + + if (title) { + g_free(title); + title = 0; + } + if (desc) { + g_free(desc); + desc = 0; + } + + delete res; + delete orig; + + + return did; +} + +void +sp_selected_path_outline(SPDesktop *desktop) +{ + Inkscape::Selection *selection = desktop->getSelection(); + + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select stroked path(s) to convert stroke to path.")); + return; + } + + bool did = false; + std::vector il(selection->itemList()); + for (std::vector::const_iterator l = il.begin(); l != il.end(); l++){ + SPItem *item = *l; + did = sp_item_path_outline(item, desktop); } if (did) { === modified file 'src/splivarot.h' --- src/splivarot.h 2016-02-13 01:41:52 +0000 +++ src/splivarot.h 2016-03-13 09:55:55 +0000 @@ -53,6 +53,7 @@ // outline of a curve // uses the stroke-width +bool sp_item_path_outline (SPItem *item, SPDesktop *desktop); void sp_selected_path_outline (SPDesktop *desktop); Geom::PathVector* item_outline(SPItem const *item, bool bbox_only = false);