diff options
| author | Jabiertxof <jtx@jtx> | 2017-05-29 00:11:53 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx> | 2017-05-29 00:11:53 +0000 |
| commit | 802385842d5a2fbe8def45b72ce433260720c954 (patch) | |
| tree | 12d3247409e5e3fb5f6858fdef7c0e0b72dad570 /src | |
| parent | Order LPE parameters (diff) | |
| download | inkscape-802385842d5a2fbe8def45b72ce433260720c954.tar.gz inkscape-802385842d5a2fbe8def45b72ce433260720c954.zip | |
Initial release
(bzr r15704)
Diffstat (limited to 'src')
26 files changed, 587 insertions, 183 deletions
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index c2f434f50..e1e5cab4c 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -36,6 +36,7 @@ set(live_effects_SRC lpe-perp_bisector.cpp lpe-perspective-envelope.cpp lpe-perspective_path.cpp + lpe-powerclip.cpp lpe-powerstroke.cpp lpe-recursiveskeleton.cpp lpe-rough-hatches.cpp @@ -121,6 +122,7 @@ set(live_effects_SRC lpe-perspective-envelope.h lpe-perspective_path.h lpe-powerstroke-interpolators.h + lpe-powerclip.h lpe-powerstroke.h lpe-recursiveskeleton.h lpe-rough-hatches.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index a6920c1fb..700564334 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -49,6 +49,7 @@ enum EffectType { BOUNDING_BOX, MEASURE_LINE, FILLET_CHAMFER, + POWERCLIP, DOEFFECTSTACK_TEST, ANGLE_BISECTOR, CIRCLE_WITH_RADIUS, diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index a4b44b1a9..50976188a 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -47,6 +47,7 @@ #include "live_effects/lpe-perp_bisector.h" #include "live_effects/lpe-perspective-envelope.h" #include "live_effects/lpe-perspective_path.h" +#include "live_effects/lpe-powerclip.h" #include "live_effects/lpe-powerstroke.h" #include "live_effects/lpe-recursiveskeleton.h" #include "live_effects/lpe-roughen.h" @@ -124,6 +125,7 @@ const Util::EnumData<EffectType> LPETypeData[] = { /* 9.93 */ {MEASURE_LINE, N_("Measure Line"), "measure_line"}, {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet_chamfer"}, + {POWERCLIP, N_("Power clip"), "powerclip"}, #ifdef LPE_ENABLE_TEST_EFFECTS {DOEFFECTSTACK_TEST, N_("doEffect stack test"), "doeffectstacktest"}, {ANGLE_BISECTOR, N_("Angle bisector"), "angle_bisector"}, @@ -302,6 +304,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case FILLET_CHAMFER: neweffect = static_cast<Effect*> ( new LPEFilletChamfer(lpeobj) ); break; + case POWERCLIP: + neweffect = static_cast<Effect*> ( new LPEPowerClip(lpeobj) ); + break; case ROUGHEN: neweffect = static_cast<Effect*> ( new LPERoughen(lpeobj) ); break; @@ -355,7 +360,8 @@ Effect::Effect(LivePathEffectObject *lpeobject) oncanvasedit_it(0), is_visible(_("Is visible?"), _("If unchecked, the effect remains applied to the object but is temporarily disabled on canvas"), "is_visible", &wr, this, true), show_orig_path(false), - erase_extra_objects(true), + keep_paths(false), + is_load(true), lpeobj(lpeobject), concatenate_before_pwd2(false), sp_lpe_item(NULL), @@ -511,6 +517,7 @@ Effect::doBeforeEffect (SPLPEItem const*/*lpeitem*/) void Effect::doAfterEffect (SPLPEItem const* /*lpeitem*/) { + is_load = false; } void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/) diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 60ee8d98f..e353eba23 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -132,7 +132,8 @@ public: void editNextParamOncanvas(SPItem * item, SPDesktop * desktop); bool apply_to_clippath_and_mask; - bool erase_extra_objects; // set this to false allow retain extra generated objects, see measure line LPE + bool keep_paths; // set this to false allow retain extra generated objects, see measure line LPE + bool is_load; bool upd_params; BoolParam is_visible; SPCurve * sp_curve; diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index dbd67beda..721a4ecab 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -44,12 +44,12 @@ LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject) weight.param_set_range(NO_POWER, 100.0); weight.param_set_increments(0.1, 0.1); weight.param_set_digits(4); - weight.param_overwrite_widget(true); + weight.param_set_undo(false); steps.param_set_range(1, 10); steps.param_set_increments(1, 1); steps.param_set_digits(0); - steps.param_overwrite_widget(true); + steps.param_set_undo(false); helper_size.param_set_range(0.0, 999.0); helper_size.param_set_increments(1, 1); diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index ff24b46da..b29b5e493 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -96,6 +96,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : previous_num_copies = num_copies; previous_origin = Geom::Point(0,0); previous_start_point = Geom::Point(0,0); + starting_point.param_widget_is_visible(false); reset = false; } @@ -108,6 +109,7 @@ void LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem) { if (split_items) { + is_load = false; SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; @@ -319,14 +321,12 @@ Gtk::Widget * LPECopyRotate::newWidget() Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); Glib::ustring *tip = param->param_getTooltip(); if (widg) { - if (param->param_key != "starting_point") { - vbox->pack_start(*widg, true, true, 2); - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } + vbox->pack_start(*widg, true, true, 2); + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); } } } @@ -722,8 +722,8 @@ LPECopyRotate::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) void LPECopyRotate::doOnRemove (SPLPEItem const* /*lpeitem*/) { - //unset "erase_extra_objects" hook on sp-lpe-item.cpp - if (!erase_extra_objects) { + //set "keep paths" hook on sp-lpe-item.cpp + if (keep_paths) { processObjects(LPE_TO_OBJECTS); return; } diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index 08ceab3c3..11298bcbe 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -38,7 +38,7 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) method(_("Method:"), _("Methods to calculate the fillet or chamfer"), "method", FMConverter, &wr, this, FM_AUTO), mode(_("Mode:"), _("Mode, fillet or chamfer"), - "mode", &wr, this, "F"), + "mode", &wr, this, "F", true), radius(_("Radius (unit or %):"), _("Radius, in unit or %"), "radius", &wr, this, 0.0), chamfer_steps(_("Chamfer steps:"), _("Chamfer steps"), "chamfer_steps", @@ -80,7 +80,7 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) radius.param_set_range(0.0, Geom::infinity()); radius.param_set_increments(1, 1); radius.param_set_digits(4); - radius.param_overwrite_widget(true); + radius.param_set_undo(false); chamfer_steps.param_set_range(1, 999); chamfer_steps.param_set_increments(1, 1); chamfer_steps.param_set_digits(0); diff --git a/src/live_effects/lpe-measure-line.cpp b/src/live_effects/lpe-measure-line.cpp index f7892cbe7..99828aef8 100644 --- a/src/live_effects/lpe-measure-line.cpp +++ b/src/live_effects/lpe-measure-line.cpp @@ -141,6 +141,7 @@ LPEMeasureLine::LPEMeasureLine(LivePathEffectObject *lpeobject) : helpline_overlap.param_set_digits(2); start_stored = Geom::Point(0,0); end_stored = Geom::Point(0,0); + id_origin.param_widget_is_visible(false); } LPEMeasureLine::~LPEMeasureLine() {} @@ -674,8 +675,8 @@ LPEMeasureLine::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) void LPEMeasureLine::doOnRemove (SPLPEItem const* /*lpeitem*/) { - //unset "erase_extra_objects" hook on sp-lpe-item.cpp - if (!erase_extra_objects) { + //set "keep paths" hook on sp-lpe-item.cpp + if (keep_paths) { processObjects(LPE_TO_OBJECTS); items.clear(); return; @@ -700,24 +701,22 @@ Gtk::Widget *LPEMeasureLine::newWidget() while (it != param_vector.end()) { if ((*it)->widget_is_visible) { Parameter *param = *it; - if (param->param_key != "id_origin") { - Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); - Glib::ustring *tip = param->param_getTooltip(); - if (widg) { - if (param->param_key != "dimline_format" && - param->param_key != "helperlines_format" && - param->param_key != "arrows_format" && - param->param_key != "anotation_format") { - vbox->pack_start(*widg, true, true, 2); - } else { - vbox_expander->pack_start(*widg, true, true, 2); - } - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } + Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); + Glib::ustring *tip = param->param_getTooltip(); + if (widg) { + if (param->param_key != "dimline_format" && + param->param_key != "helperlines_format" && + param->param_key != "arrows_format" && + param->param_key != "anotation_format") { + vbox->pack_start(*widg, true, true, 2); + } else { + vbox_expander->pack_start(*widg, true, true, 2); + } + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); } } } diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index bd3dedc86..3fcc4ae3d 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -78,6 +78,8 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : split_gap.param_set_digits(5); apply_to_clippath_and_mask = true; previous_center = Geom::Point(0,0); + id_origin.param_widget_is_visible(false); + center_point.param_widget_is_visible(false); } LPEMirrorSymmetry::~LPEMirrorSymmetry() @@ -87,6 +89,7 @@ LPEMirrorSymmetry::~LPEMirrorSymmetry() void LPEMirrorSymmetry::doAfterEffect (SPLPEItem const* lpeitem) { + is_load = false; SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; @@ -304,42 +307,6 @@ LPEMirrorSymmetry::toMirror(Geom::Affine transform) } } -Gtk::Widget * -LPEMirrorSymmetry::newWidget() -{ - // use manage here, because after deletion of Effect object, others might - // still be pointing to this widget. - Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); - vbox->set_border_width(5); - vbox->set_homogeneous(false); - vbox->set_spacing(2); - - std::vector<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter * param = *it; - if (param->param_key == "id_origin" || param->param_key == "center_point") { - ++it; - continue; - } - Gtk::Widget * widg = param->param_newWidget(); - Glib::ustring * tip = param->param_getTooltip(); - if (widg) { - vbox->pack_start(*widg, true, true, 2); - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; - } - return dynamic_cast<Gtk::Widget *>(vbox); -} - //TODO: Migrate the tree next function to effect.cpp/h to avoid duplication void LPEMirrorSymmetry::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) @@ -350,8 +317,8 @@ LPEMirrorSymmetry::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) void LPEMirrorSymmetry::doOnRemove (SPLPEItem const* /*lpeitem*/) { - //unset "erase_extra_objects" hook on sp-lpe-item.cpp - if (!erase_extra_objects) { + //set "keep paths" hook on sp-lpe-item.cpp + if (keep_paths) { processObjects(LPE_TO_OBJECTS); return; } diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index 07bb3d4fc..e98c83f2b 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -46,7 +46,6 @@ public: virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); - virtual Gtk::Widget * newWidget(); void toMirror(Geom::Affine transform); // void cloneAttrbutes(Inkscape::XML::Node * origin, Inkscape::XML::Node * dest, const char * first_attribute, ...); void cloneD(SPObject *orig, SPObject *dest, bool live, bool root); diff --git a/src/live_effects/lpe-powerclip.cpp b/src/live_effects/lpe-powerclip.cpp new file mode 100644 index 000000000..a3a827ec4 --- /dev/null +++ b/src/live_effects/lpe-powerclip.cpp @@ -0,0 +1,297 @@ +/* + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#include "live_effects/lpe-powerclip.h" +#include <2geom/path-intersection.h> +#include <2geom/intersection-graph.h> +#include "display/drawing-item.h" +#include "display/curve.h" +#include "helper/geom.h" +#include "sp-clippath.h" +#include "sp-path.h" +#include "sp-shape.h" +#include "sp-item-group.h" +#include "ui/tools-switch.h" +#include "path-chemistry.h" + +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + +namespace Inkscape { +namespace LivePathEffect { + +LPEPowerClip::LPEPowerClip(LivePathEffectObject *lpeobject) + : Effect(lpeobject), + hide_clip(_("Hide clip"), _("Hide clip"), "hide_clip", &wr, this, false), + inverse(_("Inverse clip"), _("Inverse clip"), "inverse", &wr, this, false), + flatten(_("Flatten clip"), _("Flatten clip"), "flatten", &wr, this, false), + fillrule(_("Set/unset evenodd fill rule"), _("Set/unset evenodd fill rule (this is overwriting your current value)."), "fillrule", &wr, this, false), + convert_shapes(_("Convert clip shapes to paths"), _("Convert clip shapes to paths (this is overwriting your current value)."), "convert_shapes", &wr, this, false), + //tooltip empty to no show in default param set + is_inverse("Store the last inverse apply", "", "is_inverse", &wr, this, "false", false) +{ + registerParameter(&hide_clip); + registerParameter(&inverse); + registerParameter(&flatten); + registerParameter(&fillrule); + registerParameter(&convert_shapes); + registerParameter(&is_inverse); + is_clip = false; + previous_fillrule = fillrule; +} + +LPEPowerClip::~LPEPowerClip() {} + +void +LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ + original_bbox(lpeitem); + const Glib::ustring uri = (Glib::ustring)sp_lpe_item->getRepr()->attribute("clip-path"); + SPClipPath *clip_path = SP_ITEM(lpeitem)->clip_ref->getObject(); + SPItem * item = SP_ITEM(lpeitem); + if(hide_clip) { + SPItemView *v; + for (v = item->display; v != NULL; v = v->next) { + clip_path->hide(v->arenaitem->key()); + } + Geom::OptRect bbox = item->geometricBounds(); + clip_path->setBBox(v->arenaitem->key(), bbox); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + } else if (!hide_clip) { + Geom::OptRect bbox = item->geometricBounds(); + for (SPItemView *v = item->display; v != NULL; v = v->next) { + if (!v->arenaitem->key()) { + v->arenaitem->setKey(SPItem::display_key_new(3)); + } + Inkscape::DrawingItem *ai = clip_path->show( + v->arenaitem->drawing(), + v->arenaitem->key()); + v->arenaitem->setClip(ai); + clip_path->setBBox(v->arenaitem->key(), bbox); + clip_path->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + } + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + } + Geom::Point topleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.max() + 5); + Geom::Point topright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.max() + 5); + Geom::Point bottomright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.min() - 5); + Geom::Point bottomleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.min() - 5); + clip_box.clear(); + clip_box.start(topleft); + clip_box.appendNew<Geom::LineSegment>(topright); + clip_box.appendNew<Geom::LineSegment>(bottomright); + clip_box.appendNew<Geom::LineSegment>(bottomleft); + clip_box.close(); + //clip_path *= sp_lpe_item->i2dt_affine(); + if(clip_path) { + is_clip = true; + std::vector<SPObject*> clip_path_list = clip_path->childList(true); + for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { + SPObject * clip_data = *iter; + if (SP_IS_SHAPE(clip_data) && !SP_IS_PATH(clip_data) && convert_shapes) { + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + const char * id = clip_data->getId(); + Inkscape::XML::Node *clip_path_node = sp_selected_item_to_curved_repr(SP_ITEM(clip_data), 0); + clip_data->updateRepr(xml_doc, clip_path_node, SP_OBJECT_WRITE_ALL); + clip_data->getRepr()->setAttribute("id", id); + clip_path->emitModified(SP_OBJECT_MODIFIED_CASCADE); + std::cout << "toshapes\n"; + } + if( inverse && isVisible()) { + addInverse(SP_ITEM(clip_data)); + } else if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + removeInverse(SP_ITEM(clip_data)); + } + } + } else { + is_clip = false; + } +} + +void +LPEPowerClip::addInverse (SPItem * clip_data){ + if (SP_IS_GROUP(clip_data)) { + std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_data)); + for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPItem *subitem = *iter; + addInverse(subitem); + } + } else if (SP_IS_PATH(clip_data)) { + setFillRule(clip_data); + SPCurve * c = NULL; + c = SP_SHAPE(clip_data)->getCurve(); + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + c_pv.pop_back(); + } + //TODO: this can be not correct but no better way + bool dir_a = Geom::path_direction(c_pv[0]); + bool dir_b = Geom::path_direction(clip_box); + if (dir_a == dir_b) { + clip_box = clip_box.reversed(); + } + c_pv.push_back(clip_box); + c->set_pathvector(c_pv); + SP_SHAPE(clip_data)->setCurve(c, TRUE); + c->unref(); + is_inverse.param_setValue((Glib::ustring)"true", true); +// SPDesktop *desktop = SP_ACTIVE_DESKTOP; +// if (desktop) { +// if (tools_isactive(desktop, TOOLS_NODES)) { +// Inkscape::Selection * sel = SP_ACTIVE_DESKTOP->getSelection(); +// SPItem * item = sel->singleItem(); +// if (item != NULL) { +// sel->remove(item); +// sel->add(item); +// } +// } +// } + } + } +} + +void +LPEPowerClip::removeInverse (SPItem * clip_data){ + if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + if (SP_IS_GROUP(clip_data)) { + std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_data)); + for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPItem *subitem = *iter; + removeInverse(subitem); + } + } else if (SP_IS_PATH(clip_data)) { + setFillRule(clip_data); + SPCurve * c = NULL; + c = SP_SHAPE(clip_data)->getCurve(); + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + c_pv.pop_back(); + c->set_pathvector(c_pv); + SP_SHAPE(clip_data)->setCurve(c, TRUE); + c->unref(); + is_inverse.param_setValue((Glib::ustring)"false", true); +// SPDesktop *desktop = SP_ACTIVE_DESKTOP; +// if (desktop) { +// if (tools_isactive(desktop, TOOLS_NODES)) { +// Inkscape::Selection * sel = SP_ACTIVE_DESKTOP->getSelection(); +// SPItem * item = sel->singleItem(); +// if (item != NULL) { +// sel->remove(item); +// sel->add(item); +// } +// } +// } + } + } + } +} + +void +LPEPowerClip::doOnRemove (SPLPEItem const* /*lpeitem*/) +{ + SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); + if(!keep_paths) { + if(clip_path) { + is_clip = true; + std::vector<SPObject*> clip_path_list = clip_path->childList(true); + for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { + SPObject * clip_data = *iter; + if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + removeInverse(SP_ITEM(clip_data)); + is_inverse.param_setValue((Glib::ustring)"false"); + } + } + } + } else { + if (flatten && clip_path) { + clip_path->deleteObject(); + sp_lpe_item->getRepr()->setAttribute("clip-path", NULL); + } + } +} + +Geom::PathVector +LPEPowerClip::doEffect_path(Geom::PathVector const & path_in){ + Geom::PathVector path_out = pathv_to_linear_and_cubic_beziers(path_in); + if (flatten && is_clip && isVisible()) { + SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); + if(clip_path) { + std::vector<SPObject*> clip_path_list = clip_path->childList(true); + for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { + SPObject * clip_data = *iter; + flattenClip(SP_ITEM(clip_data), path_out); + } + } + } + return path_out; +} + +void +LPEPowerClip::flattenClip(SPItem * clip_data, Geom::PathVector &path_in) +{ + if (SP_IS_GROUP(clip_data)) { + std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_data)); + for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPItem *subitem = *iter; + flattenClip(subitem, path_in); + } + } else if (SP_IS_PATH(clip_data)) { + if (!SP_IS_PATH(clip_data) && convert_shapes) { + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + const char * id = clip_data->getId(); + Inkscape::XML::Node *clip_path_node = sp_selected_item_to_curved_repr(clip_data, 0); + clip_data->updateRepr(xml_doc, clip_path_node, SP_OBJECT_WRITE_ALL); + clip_data->getRepr()->setAttribute("id", id); + } + SPCurve * c = NULL; + c = SP_SHAPE(clip_data)->getCurve(); + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(c_pv, path_in); + if (pig && !c_pv.empty() && !path_in.empty()) { + path_in = pig->getIntersection(); + } + c->unref(); + } + } +} + +void +LPEPowerClip::setFillRule(SPItem * clip_data) +{ + if (previous_fillrule != fillrule) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css, clip_data->getRepr()->attribute("style")); + if (fillrule) { + sp_repr_css_set_property (css, "fill-rule", "evenodd"); + } else { + sp_repr_css_set_property (css, "fill-rule", "nonzero"); + } + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + clip_data->getRepr()->setAttribute("style", css_str.c_str()); + previous_fillrule = fillrule; + } +} + +}; //namespace LivePathEffect +}; /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/lpe-powerclip.h b/src/live_effects/lpe-powerclip.h new file mode 100644 index 000000000..8ff8111e8 --- /dev/null +++ b/src/live_effects/lpe-powerclip.h @@ -0,0 +1,47 @@ +#ifndef INKSCAPE_LPE_POWERCLIP_H +#define INKSCAPE_LPE_POWERCLIP_H + +/* + * Inkscape::LPEPowerClip + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/hidden.h" +#include "live_effects/parameter/path.h" +#include "live_effects/lpegroupbbox.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEPowerClip : public Effect, GroupBBoxEffect { +public: + LPEPowerClip(LivePathEffectObject *lpeobject); + virtual ~LPEPowerClip(); + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); + //virtual void doOnVisibilityToggled(SPLPEItem const* lpeitem); + virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); + void addInverse (SPItem * clip_data); + void removeInverse (SPItem * clip_data); + void flattenClip(SPItem * clip_data, Geom::PathVector &path_in); + void setFillRule(SPItem * clip_data); +protected: + //virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); + +private: + BoolParam hide_clip; + BoolParam inverse; + BoolParam flatten; + BoolParam fillrule; + BoolParam convert_shapes; + HiddenParam is_inverse; + Geom::Path clip_box; + bool is_clip; + bool previous_fillrule; +}; + +} //namespace LivePathEffect +} //namespace Inkscape +#endif diff --git a/src/live_effects/lpe-transform_2pts.cpp b/src/live_effects/lpe-transform_2pts.cpp index f4d233d56..ab05b880c 100644 --- a/src/live_effects/lpe-transform_2pts.cpp +++ b/src/live_effects/lpe-transform_2pts.cpp @@ -64,9 +64,9 @@ LPETransform2Pts::LPETransform2Pts(LivePathEffectObject *lpeobject) : registerParameter(&lock_angle); first_knot.param_make_integer(true); - first_knot.param_overwrite_widget(true); + first_knot.param_set_undo(false); last_knot.param_make_integer(true); - last_knot.param_overwrite_widget(true); + last_knot.param_set_undo(false); helper_size.param_set_range(0, 999); helper_size.param_set_increments(1, 1); helper_size.param_set_digits(0); diff --git a/src/live_effects/parameter/bool.cpp b/src/live_effects/parameter/bool.cpp index 3184bfa80..954947cf4 100644 --- a/src/live_effects/parameter/bool.cpp +++ b/src/live_effects/parameter/bool.cpp @@ -21,8 +21,8 @@ namespace LivePathEffect { BoolParam::BoolParam( const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, - Effect* effect, bool default_value , bool no_widget) - : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value), hide_widget(no_widget) + Effect* effect, bool default_value) + : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value) { } @@ -65,7 +65,7 @@ BoolParam::param_getSVGValue() const Gtk::Widget * BoolParam::param_newWidget() { - if(!hide_widget){ + if(widget_is_visible){ Inkscape::UI::Widget::RegisteredCheckButton * checkwdg = Gtk::manage( new Inkscape::UI::Widget::RegisteredCheckButton( param_label, param_tooltip, diff --git a/src/live_effects/parameter/bool.h b/src/live_effects/parameter/bool.h index 39f328eaa..417752050 100644 --- a/src/live_effects/parameter/bool.h +++ b/src/live_effects/parameter/bool.h @@ -25,8 +25,7 @@ public: const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, Effect* effect, - bool default_value = false, - bool no_widget = false); + bool default_value = false); virtual ~BoolParam(); virtual Gtk::Widget * param_newWidget(); @@ -47,7 +46,6 @@ private: bool value; bool defvalue; - bool hide_widget; }; diff --git a/src/live_effects/parameter/hidden.cpp b/src/live_effects/parameter/hidden.cpp index 2f218847a..e8c55ebd3 100644 --- a/src/live_effects/parameter/hidden.cpp +++ b/src/live_effects/parameter/hidden.cpp @@ -22,11 +22,12 @@ namespace LivePathEffect { HiddenParam::HiddenParam( const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, - Effect* effect, const Glib::ustring default_value ) + Effect* effect, const Glib::ustring default_value, bool is_visible) : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value) { + param_widget_is_visible(is_visible); } void @@ -65,9 +66,12 @@ HiddenParam::param_newWidget() } void -HiddenParam::param_setValue(const Glib::ustring newvalue) +HiddenParam::param_setValue(const Glib::ustring newvalue, bool write) { value = newvalue; + if (write) { + param_write_to_repr(value.c_str()); + } } } /* namespace LivePathEffect */ diff --git a/src/live_effects/parameter/hidden.h b/src/live_effects/parameter/hidden.h index d565272b6..c3fba5575 100644 --- a/src/live_effects/parameter/hidden.h +++ b/src/live_effects/parameter/hidden.h @@ -29,7 +29,8 @@ public: const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, Effect* effect, - const Glib::ustring default_value = ""); + const Glib::ustring default_value = "", + bool widget_is_visible = false); virtual ~HiddenParam() {} virtual Gtk::Widget * param_newWidget(); @@ -37,7 +38,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; - void param_setValue(Glib::ustring newvalue); + void param_setValue(Glib::ustring newvalue, bool write = false); virtual void param_set_default(); virtual void param_update_default(const gchar * default_value); diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp index 45f46a0a7..2f73488aa 100644 --- a/src/live_effects/parameter/parameter.cpp +++ b/src/live_effects/parameter/parameter.cpp @@ -55,7 +55,7 @@ void Parameter::write_to_SVG(void) */ ScalarParam::ScalarParam( const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, - Effect* effect, gdouble default_value, bool no_widget) + Effect* effect, gdouble default_value) : Parameter(label, tip, key, wr, effect), value(default_value), min(-SCALARPARAM_G_MAXDOUBLE), @@ -66,8 +66,7 @@ ScalarParam::ScalarParam( const Glib::ustring& label, const Glib::ustring& tip, inc_step(0.1), inc_page(1), add_slider(false), - overwrite_widget(false), - hide_widget(no_widget) + _set_undo(true) { } @@ -164,15 +163,15 @@ ScalarParam::param_make_integer(bool yes) } void -ScalarParam::param_overwrite_widget(bool overwrite_widget) +ScalarParam::param_set_undo(bool set_undo) { - this->overwrite_widget = overwrite_widget; + _set_undo = set_undo; } Gtk::Widget * ScalarParam::param_newWidget() { - if(!hide_widget){ + if(widget_is_visible){ Inkscape::UI::Widget::RegisteredScalar *rsu = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalar( param_label, param_tooltip, param_key, *param_wr, param_effect->getRepr(), param_effect->getSPDoc() ) ); @@ -184,7 +183,7 @@ ScalarParam::param_newWidget() if (add_slider) { rsu->addSlider(); } - if(!overwrite_widget){ + if(_set_undo){ rsu->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change scalar parameter")); } return dynamic_cast<Gtk::Widget *> (rsu); diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h index ee1d2d547..7ab7e30dd 100644 --- a/src/live_effects/parameter/parameter.h +++ b/src/live_effects/parameter/parameter.h @@ -57,6 +57,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue) = 0; // returns true if new value is valid / accepted. virtual gchar * param_getSVGValue() const = 0; + virtual void param_widget_is_visible(bool is_visible) {widget_is_visible = is_visible;} void write_to_SVG(); virtual void param_set_default() = 0; @@ -103,8 +104,7 @@ public: const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, Effect* effect, - gdouble default_value = 1.0, - bool no_widget = false); + gdouble default_value = 1.0); virtual ~ScalarParam(); virtual bool param_readSVGValue(const gchar * strvalue); @@ -121,7 +121,7 @@ public: void addSlider(bool add_slider_widget) { add_slider = add_slider_widget; }; double param_get_max() { return max; }; double param_get_min() { return min; }; - void param_overwrite_widget(bool overwrite_widget); + void param_set_undo(bool set_undo); virtual Gtk::Widget * param_newWidget(); inline operator gdouble() const { return value; }; @@ -136,8 +136,7 @@ protected: double inc_step; double inc_page; bool add_slider; - bool overwrite_widget; - bool hide_widget; + bool _set_undo; private: ScalarParam(const ScalarParam&); diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index 6e90c9279..54f5d93e8 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -69,7 +69,10 @@ PathParam::PathParam( const Glib::ustring& label, const Glib::ustring& tip, defvalue = g_strdup(default_value); param_readSVGValue(defvalue); oncanvas_editable = true; - + _edit_button = true; + _copy_button = true; + _paste_button = true; + _link_button = true; ref_changed_connection = ref.changedSignal().connect(sigc::mem_fun(*this, &PathParam::ref_changed)); } @@ -167,6 +170,15 @@ PathParam::param_getSVGValue() const } } +void +PathParam::set_buttons(bool edit_button, bool copy_button, bool paste_button, bool link_button) +{ + _edit_button = edit_button; + _copy_button = copy_button; + _paste_button = paste_button; + _link_button = link_button; +} + Gtk::Widget * PathParam::param_newWidget() { @@ -175,47 +187,55 @@ PathParam::param_newWidget() Gtk::Label* pLabel = Gtk::manage(new Gtk::Label(param_label)); static_cast<Gtk::HBox*>(_widget)->pack_start(*pLabel, true, true); pLabel->set_tooltip_text(param_tooltip); - - Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("tool-node-editor"), Inkscape::ICON_SIZE_BUTTON) ); - Gtk::Button * pButton = Gtk::manage(new Gtk::Button()); - pButton->set_relief(Gtk::RELIEF_NONE); - pIcon->show(); - pButton->add(*pIcon); - pButton->show(); - pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_edit_button_click)); - static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); - pButton->set_tooltip_text(_("Edit on-canvas")); - - pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-copy"), Inkscape::ICON_SIZE_BUTTON) ); - pButton = Gtk::manage(new Gtk::Button()); - pButton->set_relief(Gtk::RELIEF_NONE); - pIcon->show(); - pButton->add(*pIcon); - pButton->show(); - pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_copy_button_click)); - static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); - pButton->set_tooltip_text(_("Copy path")); - - pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-paste"), Inkscape::ICON_SIZE_BUTTON) ); - pButton = Gtk::manage(new Gtk::Button()); - pButton->set_relief(Gtk::RELIEF_NONE); - pIcon->show(); - pButton->add(*pIcon); - pButton->show(); - pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_paste_button_click)); - static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); - pButton->set_tooltip_text(_("Paste path")); - - pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-clone"), Inkscape::ICON_SIZE_BUTTON) ); - pButton = Gtk::manage(new Gtk::Button()); - pButton->set_relief(Gtk::RELIEF_NONE); - pIcon->show(); - pButton->add(*pIcon); - pButton->show(); - pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_link_button_click)); - static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); - pButton->set_tooltip_text(_("Link to path on clipboard")); - + Gtk::Widget * pIcon = NULL; + Gtk::Button * pButton = NULL; + if (_edit_button) { + pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("tool-node-editor"), Inkscape::ICON_SIZE_BUTTON) ); + pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_edit_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Edit on-canvas")); + } + + if (_copy_button) { + pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-copy"), Inkscape::ICON_SIZE_BUTTON) ); + pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_copy_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Copy path")); + } + + if (_paste_button) { + pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-paste"), Inkscape::ICON_SIZE_BUTTON) ); + pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_paste_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Paste path")); + } + if (_link_button) { + pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-clone"), Inkscape::ICON_SIZE_BUTTON) ); + pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_link_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Link to path on clipboard")); + } + static_cast<Gtk::HBox*>(_widget)->show_all_children(); return dynamic_cast<Gtk::Widget *> (_widget); diff --git a/src/live_effects/parameter/path.h b/src/live_effects/parameter/path.h index 5381a6b36..ff5e4f1b8 100644 --- a/src/live_effects/parameter/path.h +++ b/src/live_effects/parameter/path.h @@ -44,7 +44,7 @@ public: void param_set_and_write_default(); void set_new_value (Geom::PathVector const &newpath, bool write_to_svg); void set_new_value (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &newpath, bool write_to_svg); - + void set_buttons(bool edit_button, bool copy_button, bool paste_button, bool link_button); virtual void param_editOncanvas(SPItem * item, SPDesktop * dt); virtual void param_setup_nodepath(Inkscape::NodePath::Path *np); virtual void addCanvasIndicators(SPLPEItem const* lpeitem, std::vector<Geom::PathVector> &hp_vec); @@ -91,6 +91,10 @@ protected: gchar * defvalue; private: + bool _edit_button; + bool _copy_button; + bool _paste_button; + bool _link_button; PathParam(const PathParam&); PathParam& operator=(const PathParam&); }; diff --git a/src/live_effects/parameter/satellitesarray.cpp b/src/live_effects/parameter/satellitesarray.cpp index 7626317a1..ce4da243e 100644 --- a/src/live_effects/parameter/satellitesarray.cpp +++ b/src/live_effects/parameter/satellitesarray.cpp @@ -37,6 +37,7 @@ SatellitesArrayParam::SatellitesArrayParam(const Glib::ustring &label, _current_zoom = 0; _effectType = FILLET_CHAMFER; _last_pathvector_satellites = NULL; + param_widget_is_visible(false); } diff --git a/src/live_effects/parameter/satellitesarray.h b/src/live_effects/parameter/satellitesarray.h index 5ae372ac2..300a7a9dd 100644 --- a/src/live_effects/parameter/satellitesarray.h +++ b/src/live_effects/parameter/satellitesarray.h @@ -57,6 +57,7 @@ public: void setEffectType(EffectType et); void setPathVectorSatellites(PathVectorSatellites *pathVectorSatellites, bool write = true); void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + bool widget_is_visible; friend class FilletChamferKnotHolderEntity; friend class LPEFilletChamfer; diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index efb1f4353..228263be4 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -50,7 +50,7 @@ static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable); static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem); static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem); -static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem); +static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths); typedef std::list<std::string> HRefList; static std::string patheffectlist_svg_string(PathEffectList const & list); @@ -129,16 +129,15 @@ void SPLPEItem::set(unsigned int key, gchar const* value) { if (!value) { LivePathEffectObject *lpeobj = (*it)->lpeobject; Inkscape::LivePathEffect::Effect * lpe = lpeobj->get_lpe(); - if (dynamic_cast<Inkscape::LivePathEffect::LPEMirrorSymmetry *>(lpe) || - dynamic_cast<Inkscape::LivePathEffect::LPEMeasureLine *>(lpe) || - dynamic_cast<Inkscape::LivePathEffect::LPECopyRotate *>(lpe) ) - { + if (lpe) { lpe->doOnRemove(this); } + ++it; + } else { + (*it)->unlink(); + delete *it; + it = this->path_effect_list->erase(it); } - (*it)->unlink(); - delete *it; - it = this->path_effect_list->erase(it); } // Parse the contents of "value" to rebuild the path effect reference list @@ -215,11 +214,52 @@ Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape /** * returns true when LPE was successful. */ +bool SPLPEItem::hasPathEffectOnClipOrMask() const +{ + bool has_clipormask_lpe = false; + if (this->hasPathEffect() && this->pathEffectsEnabled()) { + for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (!lpeobj) { + return false; + } + Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe(); + if (!lpe) { + return false; + } + if (lpe->isVisible()) { + if (lpe->acceptsNumClicks() > 0 && !lpe->isReady()) { + return false; + } + if (lpe->apply_to_clippath_and_mask) { + has_clipormask_lpe = true; + } + } + } + } + return has_clipormask_lpe; +} + +bool SPLPEItem::hasPathEffectOnClipOrMaskRecursive() const +{ + if (parent && SP_IS_LPE_ITEM(parent)) { + return hasPathEffectOnClipOrMask() || SP_LPE_ITEM(parent)->hasPathEffectOnClipOrMaskRecursive(); + } + else { + return hasPathEffectOnClipOrMask(); + } +} + +/** + * returns true when LPE was successful. + */ bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) { if (!curve) { return false; } + bool has_clipormask_lpe = false; if (this->hasPathEffect() && this->pathEffectsEnabled()) { for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it) { @@ -245,6 +285,9 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip // yet, we don't alter the path return false; } + if (lpe->apply_to_clippath_and_mask) { + has_clipormask_lpe = true; + } if (!is_clip_or_mask || (is_clip_or_mask && lpe->apply_to_clippath_and_mask)) { // Groups have their doBeforeEffect called elsewhere if (current) { @@ -272,7 +315,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip } } } - if(!SP_IS_GROUP(this) && !is_clip_or_mask){ + if(!SP_IS_GROUP(this) && !is_clip_or_mask && has_clipormask_lpe){ this->apply_to_clippath(this); this->apply_to_mask(this); } @@ -363,48 +406,49 @@ sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem) } static void -sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem) +sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths) { g_return_if_fail(lpeitem != NULL); - if (SP_IS_GROUP(lpeitem)) { - if (!lpeitem->hasPathEffectRecursive()) { + if (!lpeitem->hasPathEffectOnClipOrMaskRecursive()) { SPMask * mask = lpeitem->mask_ref->getObject(); if(mask) { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths); } SPClipPath * clip_path = lpeitem->clip_ref->getObject(); if(clip_path) { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild())); + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths); } } std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPObject *subitem = *iter; if (SP_IS_LPE_ITEM(subitem)) { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(subitem)); + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(subitem), keep_paths); } } - } - else if (SP_IS_PATH(lpeitem)) { + } else if (SP_IS_PATH(lpeitem)) { Inkscape::XML::Node *repr = lpeitem->getRepr(); - if (!lpeitem->hasPathEffectRecursive() && repr->attribute("inkscape:original-d")) { - SPMask * mask = lpeitem->mask_ref->getObject(); - if(mask) - { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); - } - SPClipPath * clip_path = lpeitem->clip_ref->getObject(); - if(clip_path) - { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild())); + SPMask * mask = lpeitem->mask_ref->getObject(); + if(mask) { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths); + } + SPClipPath * clip_path = lpeitem->clip_ref->getObject(); + if(clip_path) { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths); + } + mask = dynamic_cast<SPMask *>(lpeitem->parent); + clip_path = dynamic_cast<SPClipPath *>(lpeitem->parent); + if ((!lpeitem->hasPathEffectRecursive() && repr->attribute("inkscape:original-d")) || + ((mask || clip_path) && !lpeitem->hasPathEffectOnClipOrMaskRecursive() && repr->attribute("inkscape:original-d"))) + { + if (!keep_paths) { + repr->setAttribute("d", repr->attribute("inkscape:original-d")); } - repr->setAttribute("d", repr->attribute("inkscape:original-d")); repr->setAttribute("inkscape:original-d", NULL); - } - else { + } else { sp_lpe_item_update_patheffect(lpeitem, true, true); } } @@ -458,7 +502,16 @@ void SPLPEItem::addPathEffect(std::string value, bool reset) // Apply the path effect sp_lpe_item_update_patheffect(this, true, true); - + SPMask * mask = mask_ref->getObject(); + if(mask && !hasPathEffectOnClipOrMaskRecursive()) + { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), false); + } + SPClipPath * clip_path = clip_ref->getObject(); + if(clip_path && !hasPathEffectOnClipOrMaskRecursive()) + { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), false); + } //fix bug 1219324 if (SP_ACTIVE_DESKTOP ) { Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; @@ -499,9 +552,8 @@ void SPLPEItem::removeCurrentPathEffect(bool keep_paths) if( SP_IS_GENERICELLIPSE(this)) { SP_GENERICELLIPSE(this)->write( this->getRepr()->document(), this->getRepr(), SP_OBJECT_WRITE_EXT ); } - - sp_lpe_item_cleanup_original_path_recursive(this); } + sp_lpe_item_cleanup_original_path_recursive(this, keep_paths); } /** @@ -519,7 +571,7 @@ void SPLPEItem::removeAllPathEffects(bool keep_paths) LivePathEffectObject *lpeobj = (*it)->lpeobject; if (lpeobj) { Inkscape::LivePathEffect::Effect * lpe = lpeobj->get_lpe(); - lpe->erase_extra_objects = false; + lpe->keep_paths = true; } } } @@ -531,9 +583,8 @@ void SPLPEItem::removeAllPathEffects(bool keep_paths) if (SP_IS_GENERICELLIPSE(this)) { SP_GENERICELLIPSE(this)->write(this->getRepr()->document(), this->getRepr(), SP_OBJECT_WRITE_EXT); } - - sp_lpe_item_cleanup_original_path_recursive(this); } + sp_lpe_item_cleanup_original_path_recursive(this, keep_paths); } void SPLPEItem::downCurrentPathEffect() @@ -554,7 +605,7 @@ void SPLPEItem::downCurrentPathEffect() this->getRepr()->setAttribute("inkscape:path-effect", patheffectlist_svg_string(new_list)); - sp_lpe_item_cleanup_original_path_recursive(this); + sp_lpe_item_cleanup_original_path_recursive(this, false); } void SPLPEItem::upCurrentPathEffect() @@ -573,7 +624,7 @@ void SPLPEItem::upCurrentPathEffect() this->getRepr()->setAttribute("inkscape:path-effect", patheffectlist_svg_string(new_list)); - sp_lpe_item_cleanup_original_path_recursive(this); + sp_lpe_item_cleanup_original_path_recursive(this, false); } /** used for shapes so they can see if they should also disable shape calculation and read from d= */ @@ -645,6 +696,7 @@ bool SPLPEItem::hasPathEffectRecursive() const return hasPathEffect(); } } + void SPLPEItem::apply_to_clippath(SPItem *item) { @@ -800,7 +852,7 @@ void SPLPEItem::remove_child(Inkscape::XML::Node * child) { SPObject *ochild = this->get_child_by_repr(child); if ( ochild && SP_IS_LPE_ITEM(ochild) ) { - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(ochild)); + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(ochild), false); } } diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index 0f198c49c..d5d4e118b 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -70,6 +70,8 @@ public: virtual void update_patheffect(bool write); + bool hasPathEffectOnClipOrMask() const; + bool hasPathEffectOnClipOrMaskRecursive() const; bool performPathEffect(SPCurve *curve, SPShape *current = NULL, bool is_clip_or_mask = false); bool pathEffectsEnabled() const; diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index 0c948c91c..5daedcd02 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -368,7 +368,10 @@ void gather_items(NodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Shape } //XML Tree being used directly here while it shouldn't be. - if (SP_IS_PATH(obj) && obj->getRepr()->attribute("inkscape:original-d") != NULL) { + if (SP_IS_PATH(obj) && + obj->getRepr()->attribute("inkscape:original-d") != NULL && + !SP_LPE_ITEM(obj)->hasPathEffectOfType(LivePathEffect::POWERCLIP)) + { ShapeRecord r; r.item = static_cast<SPItem*>(obj); r.edit_transform = Geom::identity(); // TODO wrong? @@ -383,7 +386,7 @@ void gather_items(NodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Shape ShapeRecord r; r.item = item; // TODO add support for objectBoundingBox - r.edit_transform = base ? base->i2doc_affine() : Geom::identity(); + r.edit_transform = base || role == SHAPE_ROLE_CLIPPING_PATH ? base->i2doc_affine() : Geom::identity(); r.role = role; if (s.insert(r).second) { |
