diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-11-19 22:54:21 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-11-19 22:54:21 +0000 |
| commit | d91112f7116f50489bd93047f6e7bc0985512c68 (patch) | |
| tree | 29919bec74826788890efdeabea204255a683c4d /src | |
| parent | Working on fix smooth draw (diff) | |
| download | inkscape-d91112f7116f50489bd93047f6e7bc0985512c68.tar.gz inkscape-d91112f7116f50489bd93047f6e7bc0985512c68.zip | |
Working on coontinuing paths
Diffstat (limited to 'src')
| -rw-r--r-- | src/live_effects/lpe-powerstroke.cpp | 2 | ||||
| -rw-r--r-- | src/live_effects/parameter/powerstrokepointarray.cpp | 16 | ||||
| -rw-r--r-- | src/live_effects/parameter/powerstrokepointarray.h | 2 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 15 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.h | 1 | ||||
| -rw-r--r-- | src/ui/tools/freehand-base.cpp | 24 | ||||
| -rw-r--r-- | src/ui/tools/pencil-tool.cpp | 294 | ||||
| -rw-r--r-- | src/ui/tools/pencil-tool.h | 10 |
8 files changed, 173 insertions, 191 deletions
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 7c060a965..e9943af4c 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -645,7 +645,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) } LineJoinType jointype = static_cast<LineJoinType>(linejoin_type.get_value()); - Piecewise<D2<SBasis> > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise<D2<SBasis> > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); Piecewise<D2<SBasis> > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); Geom::Path fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 7e2da4cfd..289498498 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -90,18 +90,28 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi } /** call this method to recalculate the controlpoints when path is reversed.*/ -void -PowerStrokePointArrayParam::reverse_controlpoints() +std::vector<Geom::Point> +PowerStrokePointArrayParam::reverse_controlpoints(bool write) { + std::vector<Geom::Point> controlpoints; if (!last_pwd2.empty()) { Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in_reverse = reverse(last_pwd2); for (unsigned int i = 0; i < _vector.size(); ++i) { Geom::Point control_pos = last_pwd2.valueAt(_vector[i][Geom::X]); double new_pos = Geom::nearest_time(control_pos, pwd2_in_reverse); + controlpoints.push_back(Geom::Point(new_pos,_vector[i][Geom::Y])); _vector[i][Geom::X] = new_pos; } - write_to_SVG(); + if (write) { + write_to_SVG(); + _vector.clear(); + _vector = controlpoints; + controlpoints.clear(); + write_to_SVG(); + return _vector; + } } + return controlpoints; } float PowerStrokePointArrayParam::median_width() diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index b8e63e5f7..a1d4db3ca 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -47,7 +47,7 @@ public: Geom::Piecewise<Geom::D2<Geom::SBasis> > const & get_pwd2_normal() const { return last_pwd2_normal; } void recalculate_controlpoints_for_new_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in); - void reverse_controlpoints(); + std::vector<Geom::Point> reverse_controlpoints(bool write); void set_scale_width(double scale_width){_scale_width = scale_width;}; double _scale_width; friend class PowerStrokePointArrayParamKnotHolderEntity; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 93168a727..ef69fdade 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -204,22 +204,12 @@ void InkscapePreferences::AddBaseSimplifySpinbutton(DialogPage &p, Glib::ustring false ); } - -void InkscapePreferences::AddPowerStrokeKnotDistanceFactor(DialogPage &p, Glib::ustring const &prefs_path, double def_value) -{ - PrefSpinButton* sb = Gtk::manage( new PrefSpinButton); - sb->init ( prefs_path + "/knots-distance", 0.1, 9999.0, 1.0, 10.0, def_value, false, false); - p.add_line( false, _("Minimum knot distance factor:"), *sb, _("on tablet usage"), - _("This unitless value affects the density of LPE knots. A small value allows you to draw squiggly lines, while a higher value creates smoother lines with less width differences."), - false ); -} - void InkscapePreferences::AddPowerStrokeGapPressureFactor(DialogPage &p, Glib::ustring const &prefs_path, gint def_value) { PrefSpinButton* sb = Gtk::manage( new PrefSpinButton); sb->init ( prefs_path + "/gap-pressure", 1, 100, 1, 10, def_value, true, false); - p.add_line( false, _("Minimun pressure % diference needed to create knot:"), *sb, _("on tablet usage"), - _("Minimun percent difference in pressure that is required to create a new PowerStroke knot."), + p.add_line( false, _("Pressure diference on knots:"), *sb, _("%"), + _("Pressure diference percent that is required to create a new PowerStroke knot."), false ); } @@ -442,7 +432,6 @@ void InkscapePreferences::initPageTools() this->AddDotSizeSpinbutton(_page_pencil, "/tools/freehand/pencil", 3.0); this->AddBaseSimplifySpinbutton(_page_pencil, "/tools/freehand/pencil", 25.0); _page_pencil.add_group_header( _("Pressure sensitivity settings")); - this->AddPowerStrokeKnotDistanceFactor(_page_pencil, "/tools/freehand/pencil", 135.0); this->AddPowerStrokeGapPressureFactor(_page_pencil, "/tools/freehand/pencil", 10); _page_pencil.add_group_header( _("Sketch mode")); diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index bd9168913..0f78a49a4 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -500,7 +500,6 @@ protected: static void AddFirstAndLastCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value); static void AddDotSizeSpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value); static void AddBaseSimplifySpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value); - static void AddPowerStrokeKnotDistanceFactor(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value); static void AddPowerStrokeGapPressureFactor(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, gint def_value); static void AddNewObjectsStyle(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL); diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index ae91f1f8b..0d539b0f3 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -242,24 +242,24 @@ static void spdc_apply_powerstroke_shape(std::vector<Geom::Point> points, Freeha } pt->addPowerStrokePencil(c); } - double zoom = SP_EVENT_CONTEXT(dc)->desktop->current_zoom() * 5.0; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - double min = prefs->getIntLimited("/tools/freehand/pencil/minpressure", 0, 1, 100) / 100.0; - double max = prefs->getIntLimited("/tools/freehand/pencil/maxpressure", 100, 1, 100) / 100.0; - if (min > max){ - min = max; - } - Geom::Affine transformCoordinate = SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->i2dt_affine(); - Geom::Coord scale = transformCoordinate.expansionX(); - double pressure_shirnked = (1.0 * (max - min)) + min; - double pressure_computed = (pressure_shirnked * 8.0 * scale) / zoom; if(pt->points.empty()){ - pt->points.push_back(Geom::Point(0, pressure_computed)); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); + const char *stroke_width = sp_repr_css_property(css_item, "stroke-width", "0"); + double swidth; + sp_svg_number_read_d(stroke_width, &swidth); + swidth = prefs->getDouble("/live_effect/power_stroke/width", swidth/2); + if (!swidth) { + swidth = swidth/2; + } + pt->points.push_back(Geom::Point(0, swidth)); } Effect::createAndApply(POWERSTROKE, dc->desktop->doc(), item); Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE(); lpe->getRepr()->setAttribute("sort_points", "true"); lpe->getRepr()->setAttribute("interpolator_type", "CentripetalCatmullRom"); + lpe->getRepr()->setAttribute("interpolator_beta", "0.2"); + lpe->getRepr()->setAttribute("miter_limit", "4"); lpe->getRepr()->setAttribute("linejoin_type", "round"); static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(pt->points); pt->points.clear(); diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp index c2c3d571f..478ba61f6 100644 --- a/src/ui/tools/pencil-tool.cpp +++ b/src/ui/tools/pencil-tool.cpp @@ -74,7 +74,7 @@ PencilTool::PencilTool() , sketch_n(0) , _powerpreviewtail(NULL) , _powerpreview(NULL) - , _second_chance_preview(false) + , _previewok(true) { } @@ -97,16 +97,10 @@ PencilTool::~PencilTool() { void PencilTool::_extinput(GdkEvent *event) { if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &this->pressure)) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/tools/freehand/pencil/pressure", true)) { - this->pressure = CLAMP (this->pressure, DDC_MIN_PRESSURE, DDC_MAX_PRESSURE); - input_has_pressure = true; - } else { - this->pressure = DDC_DEFAULT_PRESSURE; - input_has_pressure = false; - } + this->pressure = CLAMP (this->pressure, DDC_MIN_PRESSURE, DDC_MAX_PRESSURE); } else { this->pressure = DDC_DEFAULT_PRESSURE; + //If no pressure device ignore pressure button input_has_pressure = false; } } @@ -192,6 +186,8 @@ bool PencilTool::_handleButtonPress(GdkEventButton const &bevent) { pencil_drag_origin_w = Geom::Point(bevent.x,bevent.y); pencil_within_tolerance = true; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + input_has_pressure = prefs->getBool("/tools/freehand/pencil/pressure", true); if (input_has_pressure) { this->state = SP_PENCIL_CONTEXT_FREEHAND; } @@ -225,7 +221,9 @@ bool PencilTool::_handleButtonPress(GdkEventButton const &bevent) { // anchor, which is handled by the sibling branch above) selection->clear(); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path")); - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); + if (!input_has_pressure) { + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); + } } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path")); m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); @@ -271,7 +269,7 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) { Geom::Point p = desktop->w2d(Geom::Point(mevent.x, mevent.y)); /* Test whether we hit any anchor. */ - SPDrawAnchor *anchor = spdc_test_inside(this, Geom::Point(mevent.x, mevent.y)); + SPDrawAnchor *anchor = spdc_test_inside(this, Geom::Point(mevent.x,mevent.y)); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (pencil_within_tolerance) { gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); @@ -428,6 +426,8 @@ bool PencilTool::_handleButtonRelease(GdkEventButton const &revent) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Finishing freehand")); this->_interpolate(); + //Remove here because points are recalculated once finish. This is because we want live preview. + this->points.clear(); spdc_concat_colors_and_flush(this, FALSE); this->sa = NULL; this->ea = NULL; @@ -636,7 +636,7 @@ void PencilTool::_finishEndpoint() { } void -PencilTool::_powerStrokePreview(Geom::Path path, std::vector<Geom::Point> points, bool write) +PencilTool::_powerStrokePreview(Geom::Path const path, std::vector<Geom::Point> points, bool write) { using namespace Inkscape::LivePathEffect; SPDocument * document = SP_ACTIVE_DOCUMENT; @@ -644,62 +644,15 @@ PencilTool::_powerStrokePreview(Geom::Path path, std::vector<Geom::Point> points return; } Inkscape::XML::Document *xml_doc = document->getReprDoc(); - if (_powerpreview) { - SPLPEItem * lpeitem = dynamic_cast<SPLPEItem *>(_powerpreview); - if (!lpeitem) { - return; - } - Effect* lpe = lpeitem->getCurrentLPE(); - lpeitem->path_effects_enabled = 0; - lpe->getRepr()->setAttribute("interpolator_type" , "CentripetalCatmullRom"); - lpe->getRepr()->setAttribute("linejoin_type", "round"); - lpe->getRepr()->setAttribute("end_linecap_type", end_linecap_type); - gchar * path_str = sp_svg_write_path(path); - _powerpreview->setAttribute("inkscape:original-d" , path_str); - g_free(path_str); - lpeitem->path_effects_enabled = 1; - LPEPowerStroke * ps = static_cast<LPEPowerStroke*>(lpe); - if (ps) { - ps->offset_points.param_set_and_write_new_value(points); - } - if (write) { - lpe->getRepr()->setAttribute("end_linecap_type", "round"); - SPCurve * curve = SP_SHAPE(_powerpreview)->getCurve(); - //SPCurve * curve_before = SP_SHAPE(_powerpreview)->getCurveBeforeLPE(); - if (!_powerpreviewtail) { - Inkscape::XML::Node *tail = NULL; - tail = xml_doc->createElement("svg:path"); - tail->setAttribute("sodipodi:insensitive", "true"); - _powerpreviewtail = SP_ITEM(SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->appendChildRepr(tail)); - SPCSSAttr *css = sp_css_attr_from_object(_powerpreview, SP_STYLE_FLAG_ALWAYS); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - tail->setAttribute("style", css_str.c_str()); - Inkscape::GC::release(tail); - } - // if (curve != curve_before) { - SP_SHAPE(_powerpreviewtail)->setCurve(curve, true); - //second_chance_preview = false; -// } else if (!_second_chance_preview) { -// Try to reload if the process go bad -// _second_chance_preview = true; -// points_parsed--; -// addPowerStrokePencil(NULL); -// } else { -// _second_chance_preview = false; - //} - curve->unref(); - //curve_before->unref(); - } - } else { + SPCurve * curve = new SPCurve(); + Geom::PathVector const pathv(path); + if (!_powerpreview) { Inkscape::XML::Node *body = NULL; body = xml_doc->createElement("svg:path"); body->setAttribute("sodipodi:insensitive", "true"); sp_desktop_apply_style_tool(desktop, body, Glib::ustring("/tools/freehand/pencil").data(), false); - _powerpreview = SP_ITEM(SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->appendChildRepr(body)); - gchar * path_str = sp_svg_write_path(path); - body->setAttribute("d" , path_str); - g_free(path_str); + _powerpreview = SP_SHAPE(SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->appendChildRepr(body)); + _powerpreview->setCurve(curve, true); Inkscape::GC::release(body); SPCSSAttr *css = sp_css_attr_from_object(_powerpreview, SP_STYLE_FLAG_ALWAYS); const gchar * stroke = sp_repr_css_property(css, "stroke", "none"); @@ -715,14 +668,56 @@ PencilTool::_powerStrokePreview(Geom::Path path, std::vector<Geom::Point> points Glib::ustring css_str; sp_repr_css_write_string(css,css_str); body->setAttribute("style", css_str.c_str()); - Effect::createAndApply(POWERSTROKE, SP_ACTIVE_DESKTOP->doc(), _powerpreview); - Effect* lpe = SP_LPE_ITEM(_powerpreview)->getCurrentLPE(); - LPEPowerStroke* ps = static_cast<LPEPowerStroke*>(lpe); - if (ps) { - ps->offset_points.param_set_and_write_new_value(points); + gchar * pvector_str = sp_svg_write_path(pathv); + _powerpreview->setAttribute("d" , pvector_str); + g_free(pvector_str); + SPLPEItem * lpeitem = dynamic_cast<SPLPEItem *>(_powerpreview); + if (!lpeitem) { + return; } - end_linecap_type = body->attribute("end_linecap_type"); - } + Effect::createAndApply(POWERSTROKE, SP_ACTIVE_DESKTOP->doc(), SP_ITEM(_powerpreview)); + Effect* lpe = lpeitem->getCurrentLPE(); + lpe->getRepr()->setAttribute("sort_points", "true"); + lpe->getRepr()->setAttribute("interpolator_type", "CentripetalCatmullRom"); + lpe->getRepr()->setAttribute("interpolator_beta", "0.2"); + lpe->getRepr()->setAttribute("miter_limit", "4"); + lpe->getRepr()->setAttribute("linejoin_type", "round"); + end_linecap_type = lpe->getRepr()->attribute("end_linecap_type"); + } + SPLPEItem * lpeitem = dynamic_cast<SPLPEItem *>(_powerpreview); + if (!lpeitem) { + return; + } + Effect* lpe = lpeitem->getCurrentLPE(); + lpe->getRepr()->setAttribute("end_linecap_type", end_linecap_type); + static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points); + gchar * pvector_str = sp_svg_write_path(pathv); + _powerpreview->setAttribute("inkscape:original-d" , pvector_str); + g_free(pvector_str); + if (write) { + lpe->getRepr()->setAttribute("end_linecap_type", "round"); + curve = _powerpreview->getCurve(); + _powerpreview->setAttribute("inkscape:original-d", ""); + _powerpreview->setAttribute("d", ""); + if (!_powerpreviewtail) { + Inkscape::XML::Node *tail = NULL; + tail = xml_doc->createElement("svg:path"); + tail->setAttribute("sodipodi:insensitive", "true"); + _powerpreviewtail = SP_SHAPE(SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->appendChildRepr(tail)); + SPCSSAttr *css = sp_css_attr_from_object(_powerpreview, SP_STYLE_FLAG_ALWAYS); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + tail->setAttribute("style", css_str.c_str()); + Inkscape::GC::release(tail); + } + if (!curve->is_empty()) { + _powerpreviewtail->setCurve(curve, true); + _previewok = true; + } else {//if (!_second_chance_preview) { + _previewok = false; + } + } + curve->unref(); } void @@ -751,6 +746,13 @@ PencilTool::addPowerStrokePencil(SPCurve * c) using namespace Inkscape::LivePathEffect; this->points.clear(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0); + double gap_pressure = prefs->getIntLimited("/tools/freehand/pencil/gap-pressure",10, 1, 100)/100.0; + double min = prefs->getIntLimited("/tools/freehand/pencil/minpressure", 0, 1, 100) / 100.0; + double max = prefs->getIntLimited("/tools/freehand/pencil/maxpressure", 100, 1, 100) / 100.0; + if (min > max){ + min = max; + } bool live = false; SPCurve * curve; if(!c) { @@ -758,26 +760,38 @@ PencilTool::addPowerStrokePencil(SPCurve * c) //Simplify a bit the base curve to avoid artifacts SPCurve * previous_red = red_curve->copy(); SPCurve * previous_green = green_curve->copy(); - double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0); prefs->setDouble("/tools/freehand/pencil/tolerance", 18.0); _interpolate(); prefs->setDouble("/tools/freehand/pencil/tolerance", tol); if (sa) { curve = sa->curve; + if(prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 1 || + prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 2) + { + curve = overwrite_curve; + } if (sa->start) { - curve = curve->create_reverse(); + SPCurve *ret = curve->create_reverse(); + curve->unref(); + curve = ret->copy(); + ret->unref(); } Effect* lpe = SP_LPE_ITEM(white_item)->getCurrentLPE(); LPEPowerStroke* ps = static_cast<LPEPowerStroke*>(lpe); if (ps) { if (sa->start) { - ps->offset_points.reverse_controlpoints(); + this->points = ps->offset_points.reverse_controlpoints(false); + } else { + this->points = ps->offset_points.data(); } - this->points = ps->offset_points.data(); } - if (!green_curve->is_empty()) { - curve->append_continuous( green_curve, 0.0625); + if (curve->is_empty()) { + curve = green_curve->copy(); + } else { + green_curve->move_endpoints(curve->first_path()->finalPoint(), *green_curve->last_point()); + curve->append_continuous( green_curve, 0.0625); + } if (!red_curve->is_empty()) { curve->append_continuous( red_curve, 0.0625); } @@ -808,95 +822,63 @@ PencilTool::addPowerStrokePencil(SPCurve * c) return; } Geom::Affine transformCoordinate = SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->i2dt_affine(); - Geom::Coord scale = transformCoordinate.expansionX(); Geom::PathVector pathvector = curve->get_pathvector(); + Geom::Path const path = pathvector[0]; curve->unref(); - //pathvector *= transformCoordinate.inverse(); - double min = prefs->getIntLimited("/tools/freehand/pencil/minpressure", 0, 1, 100) / 100.0; - double max = prefs->getIntLimited("/tools/freehand/pencil/maxpressure", 100, 1, 100) / 100.0; - if (min > max){ - min = max; - } - double gap_pressure = prefs->getIntLimited("/tools/freehand/pencil/gap-pressure",10, 1, 100)/100.0; - //TODO: shrunk pressure sensitive over 0.5, less means release pen input. Need to check in more hardware - //gap_pressure = (gap_pressure * 0.5) + 0.5; - double knots_distance = prefs->getDoubleLimited("/tools/freehand/pencil/knots-distance",135.0, 0.1, 9999.0); double previous_pressure = 0.0; - double previous_pressure_computed = 0.0; - double dezoomify_factor = 0.05 * 1000/SP_EVENT_CONTEXT(this)->desktop->current_zoom();//\/100 we want 100% = 1; - double tol = knots_distance * dezoomify_factor/100.0; - Geom::Point previous_point = Geom::Point(0,0); - bool start = true; - auto pressure = this->wps.begin(); - bool buttonrelease = false; - bool lastsegmentpressure = 0.0; double pressure_computed = 0.0; + double dezoomify_factor = 0.05 * 1000/SP_EVENT_CONTEXT(this)->desktop->current_zoom();//\/100 we want 100% = 1; + bool start = true; + auto pressure = this->wps.begin(); size_t counter = 0; for (auto point = this->ps.begin(); point != this->ps.end(); ++point, ++pressure) { -// //TODO: shrunk pressure sensitive over 0.5, less means release pen input. Need to check in more hardware -// if (this->wps[this->wps.size()-1] < 0.01) { -// // break; -// } counter++; - //remove start/end pressure gap - if (counter < 4 || this->ps.size()-4 < counter) { - continue; + //remove end pressure gap + if (this->ps.size() > 2 && this->ps.size()-2 < counter) { + break; } - double pressure_shrunk = (*pressure * (max - min)) + min; - //We need half width for power stroke + //We need half width for power stroke pressure_computed = pressure_shrunk * dezoomify_factor/2.0; - std::cout << *pressure << "pressure" << std::endl; - std::cout << pressure_computed << "pressure_computed" << std::endl; - if (start) { - start = false; - previous_point = *point; - previous_pressure = *pressure; - previous_pressure_computed = pressure_computed; - this->points.push_back(Geom::Point(0.0, pressure_computed)); - } else if (std::abs(previous_pressure - *pressure) > gap_pressure/100.0 ) { - Geom::Point position = *point; - if (!live) { - position *= transformCoordinate.inverse(); - } - double pos = Geom::nearest_time(position, pathvector[0]); - std::cout << tol << "tol" << std::endl; - if (pos > 1e6 || Geom::distance(*point, previous_point) < tol) - { - std::cout << Geom::distance(*point, previous_point) << "Geom::distance(*point, previous_point)" << std::endl; - continue; + //remove start pressure gap + if (counter < 3) { + if (start) { + start = false; + this->points.push_back(Geom::Point(0, pressure_computed)); + } else { + this->points[this->points.size()-1] = Geom::Point(0, pressure_computed); } -// if (pathvector[0].size()-1 < pos) { -// this->points.push_back(Geom::Point(pos, previous_pressure_computed)); -// break; -// } - previous_point = *point; - previous_pressure = *pressure; - previous_pressure_computed = pressure_computed; + previous_pressure = pressure_shrunk; + continue; + } + Geom::Point position = *point; + if (!live) { + position *= transformCoordinate.inverse(); + } + double pos = Geom::nearest_time(position, path); + if (pos < 1e6 && std::abs(previous_pressure - pressure_shrunk) > gap_pressure) { + previous_pressure = pressure_shrunk; this->points.push_back(Geom::Point(pos, pressure_computed)); } } if (live && this->points.size() > 0) { bool write = false; - if (points_parsed != this->points.size()) { + if (points_parsed != this->points.size() || !_previewok) { points_parsed = this->points.size(); write = true; } - std::vector<Geom::Point> pointsend; - Geom::Path out = pathvector[0]; - if (this->points.size() == 1) { - _powerStrokePreview(out * transformCoordinate.inverse(), pointsend, false); - } else if (write) { - _powerStrokePreview(out * transformCoordinate.inverse(), this->points, write); + if (write) { + _powerStrokePreview(path * transformCoordinate.inverse(), this->points, write); } else { - Geom::Point start = this->points[this->points.size()-2]; - Geom::Point end = this->points[this->points.size()-1]; - out = out.portion(start[Geom::X], out.size()); - pointsend.push_back(Geom::Point(0, start[Geom::Y])); - pointsend.push_back(Geom::Point(out.size(), end[Geom::Y])); - _powerStrokePreview(out * transformCoordinate.inverse(), pointsend, write); + Geom::Point start = this->points[this->points.size()-1]; + if (start[Geom::X] < path.size()) { + std::vector<Geom::Point> pointsend; + Geom::Path const pathtail = path.portion(start[Geom::X], path.size()); + pointsend.push_back(Geom::Point(0, start[Geom::Y])); + _powerStrokePreview(pathtail * transformCoordinate.inverse(), pointsend, write); + pointsend.clear(); + } } - pointsend.clear(); } } @@ -944,14 +926,15 @@ void PencilTool::_interpolate() { if (tol < 18.0 * 0.4) { tol = 18.0 * 0.4; } - size_t i = this->ps.size(); -// while (i > 3 && -// (this->wps[i-1] < 0.5 || Geom::distance(this->ps[i-1], this->ps[i-2]) < Geom::distance(this->ps[i-2], this->ps[i-3])/2.0)) -// { -// this->ps.pop_back(); -// this->wps.pop_back(); -// i--; -// } + //Smooth last 2 segments + if (this->ps.size() > 2) { + Geom::Point last_point = this->ps[this->ps.size()-1]; + Geom::Point prev_point = middle_point(last_point,this->ps[this->ps.size()-3]); + this->ps.pop_back(); + this->ps.pop_back(); + this->ps.push_back(prev_point); + this->ps.push_back(last_point); + } } double tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2); @@ -979,13 +962,14 @@ void PencilTool::_interpolate() { guint mode = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0); for (int c = 0; c < n_segs; c++) { // if we are in BSpline we modify the trace to create adhoc nodes - if(mode == 2){ + if (mode == 2) { Geom::Point point_at1 = b[4 * c + 0] + (1./3) * (b[4 * c + 3] - b[4 * c + 0]); point_at1 = Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP); Geom::Point point_at2 = b[4 * c + 3] + (1./3) * (b[4 * c + 0] - b[4 * c + 3]); point_at2 = Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP); this->green_curve->curveto(point_at1,point_at2,b[4*c+3]); - }else{ + } else { + //force retracted handle at end if power stroke if (c == n_segs - 1 && input_has_pressure) { this->green_curve->curveto(b[4 * c + 1], b[4 * c + 3], b[4 * c + 3]); } else { diff --git a/src/ui/tools/pencil-tool.h b/src/ui/tools/pencil-tool.h index 3e1332501..ce38f5deb 100644 --- a/src/ui/tools/pencil-tool.h +++ b/src/ui/tools/pencil-tool.h @@ -6,7 +6,7 @@ */ #include "ui/tools/freehand-base.h" - +#include "sp-shape.h" #include <2geom/piecewise.h> #include <2geom/d2.h> #include <2geom/sbasis.h> @@ -70,10 +70,10 @@ private: bool _handleKeyPress(GdkEventKey const &event); bool _handleKeyRelease(GdkEventKey const &event); void _setStartpoint(Geom::Point const &p); - void _powerStrokePreview(Geom::Path path, std::vector<Geom::Point> points, bool write); - SPItem *_powerpreview; - SPItem *_powerpreviewtail; - bool _second_chance_preview; + void _powerStrokePreview(Geom::Path const path, std::vector<Geom::Point> points, bool write); + SPShape *_powerpreview; + SPShape *_powerpreviewtail; + bool _previewok; gchar const * end_linecap_type; void _setEndpoint(Geom::Point const &p); void _finishEndpoint(); |
