summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2017-08-27 10:55:26 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2017-08-27 10:55:26 +0000
commitbbde5dbeeb06611e99f9fa7f73dafe3bf70df01c (patch)
tree8f2aba648ca0b2ae7519903c2270d56039e4a6a9
parentStarting with powerpencil (diff)
downloadinkscape-bbde5dbeeb06611e99f9fa7f73dafe3bf70df01c.tar.gz
inkscape-bbde5dbeeb06611e99f9fa7f73dafe3bf70df01c.zip
Working on preview over powerpencil
-rw-r--r--share/ui/select-toolbar.ui3
-rw-r--r--src/live_effects/lpe-powerstroke.cpp31
-rw-r--r--src/live_effects/lpe-powerstroke.h3
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp4
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.h3
-rw-r--r--src/ui/tools/freehand-base.cpp65
-rw-r--r--src/ui/tools/pencil-tool.cpp215
-rw-r--r--src/ui/tools/pencil-tool.h8
-rw-r--r--src/widgets/pencil-toolbar.cpp71
9 files changed, 321 insertions, 82 deletions
diff --git a/share/ui/select-toolbar.ui b/share/ui/select-toolbar.ui
index d1fc779e8..4d28628ad 100644
--- a/share/ui/select-toolbar.ui
+++ b/share/ui/select-toolbar.ui
@@ -208,6 +208,9 @@
<toolbar name='PencilToolbar'>
<toolitem action='FreehandModeActionPencil' />
<separator />
+ <toolitem action='MinPressureAction' />
+ <toolitem action='MaxPressureAction' />
+ <separator />
<toolitem action='FlattenSpiroBsplinePencil' />
<separator />
<toolitem action='PencilToleranceAction' />
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 05ce3b7bd..ae2ce1e65 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -167,6 +167,7 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true),
interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER),
interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2),
+ scale_width(_("Width scale:"), _("Width scale all points"), "scale_width", &wr, this, 1.0),
start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT),
linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_EXTRP_MITER_ARC),
miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.),
@@ -186,14 +187,22 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
registerParameter(&start_linecap_type);
registerParameter(&linejoin_type);
registerParameter(&miter_limit);
+ registerParameter(&scale_width);
registerParameter(&end_linecap_type);
+ scale_width.param_set_range(0.0, Geom::infinity());
+ scale_width.param_set_increments(1, 1);
+ scale_width.param_set_digits(4);
}
LPEPowerStroke::~LPEPowerStroke()
{
}
-
+void
+LPEPowerStroke::doBeforeEffect(SPLPEItem const *lpeItem)
+{
+ offset_points.set_scale_width(scale_width);
+}
void
LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
{
@@ -247,6 +256,7 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
points.push_back( Geom::Point(size - 0.2,width) );
}
}
+ offset_points.set_scale_width(scale_width);
offset_points.param_set_and_write_new_value(points);
} else {
if (!SP_IS_SHAPE(lpeitem)) {
@@ -559,7 +569,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = pathv[0].toPwSb();
Piecewise<D2<SBasis> > der = derivative(pwd2_in);
Piecewise<D2<SBasis> > n = unitVector(der,0.0001);
- if (!n.size()) {
+ if (!n.size() || !pwd2_in.size() || !n.size()) {
return path_in;
}
n = rot90(n);
@@ -568,10 +578,15 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
LineCapType end_linecap = static_cast<LineCapType>(end_linecap_type.get_value());
LineCapType start_linecap = static_cast<LineCapType>(start_linecap_type.get_value());
- std::vector<Geom::Point> ts = offset_points.data();
- if (ts.empty()) {
+ std::vector<Geom::Point> ts_no_scale = offset_points.data();
+ if (ts_no_scale.empty()) {
return path_out;
}
+ std::vector<Geom::Point> ts;
+ for (std::vector<Geom::Point>::iterator tsp = ts_no_scale.begin(); tsp != ts_no_scale.end(); ++tsp) {
+ Geom::Point p = Geom::Point((*tsp)[Geom::X], (*tsp)[Geom::Y] * scale_width);
+ ts.push_back(p);
+ }
if (sort_points) {
sort(ts.begin(), ts.end(), compare_offsets);
}
@@ -625,10 +640,16 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
LineJoinType jointype = static_cast<LineJoinType>(linejoin_type.get_value());
+ if (!x.size() || !y.size()) {
+ return path_in;
+ }
Piecewise<D2<SBasis> > pwd2_out_1 = compose(pwd2_in,x);
Piecewise<D2<SBasis> > pwd2_out_2 = y*compose(n,x);
+ if (!pwd2_out_1.size() || !pwd2_out_2.size()) {
+ return path_in;
+ }
Piecewise<D2<SBasis> > pwd2_out = pwd2_out_1 + pwd2_out_2;
- Piecewise<D2<SBasis> > mirrorpath = reverse(compose(pwd2_in,x) - y*compose(n,x));
+ Piecewise<D2<SBasis> > mirrorpath = reverse( pwd2_out_1 - pwd2_out_2);
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/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h
index 135d39274..4a0eda75a 100644
--- a/src/live_effects/lpe-powerstroke.h
+++ b/src/live_effects/lpe-powerstroke.h
@@ -27,7 +27,7 @@ public:
virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
-
+ virtual void doBeforeEffect(SPLPEItem const *lpeItem);
virtual void doOnApply(SPLPEItem const* lpeitem);
virtual void doOnRemove(SPLPEItem const* lpeitem);
@@ -40,6 +40,7 @@ private:
BoolParam sort_points;
EnumParam<unsigned> interpolator_type;
ScalarParam interpolator_beta;
+ ScalarParam scale_width;
EnumParam<unsigned> start_linecap_type;
EnumParam<unsigned> linejoin_type;
ScalarParam miter_limit;
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index 25639b406..bc06e42ca 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -163,7 +163,7 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom:
Geom::Point const s = snap_knot_position(p, state);
double t = nearest_time(s, pwd2);
double offset = dot(s - pwd2.valueAt(t), n.valueAt(t));
- _pparam->_vector.at(_index) = Geom::Point(t, offset);
+ _pparam->_vector.at(_index) = Geom::Point(t, offset/_pparam->_scale_width);
if (_pparam->_vector.size() == 1 ) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble("/live_effect/power_stroke/width", offset);
@@ -188,7 +188,7 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() const
g_warning("Broken powerstroke point at %f, I won't try to add that", offset_point[X]);
return Geom::Point(infinity(), infinity());
}
- Point canvas_point = pwd2.valueAt(offset_point[X]) + offset_point[Y] * n.valueAt(offset_point[X]);
+ Point canvas_point = pwd2.valueAt(offset_point[X]) + (offset_point[Y] * _pparam->_scale_width) * n.valueAt(offset_point[X]);
return canvas_point;
}
diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h
index a34163ca1..621d3b969 100644
--- a/src/live_effects/parameter/powerstrokepointarray.h
+++ b/src/live_effects/parameter/powerstrokepointarray.h
@@ -35,6 +35,7 @@ public:
void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
+
float median_width();
virtual bool providesKnotHolderEntities() const { return true; }
@@ -46,6 +47,8 @@ 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 set_scale_width(double scale_width){_scale_width = scale_width;};
+ double _scale_width;
friend class PowerStrokePointArrayParamKnotHolderEntity;
private:
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 05afd8058..fba3c8397 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -237,40 +237,36 @@ static void spdc_apply_powerstroke_shape(std::vector<Geom::Point> points, Freeha
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 3) {
SPShape *sp_shape = dynamic_cast<SPShape *>(item);
- Geom::PathVector pathvector;
if (sp_shape) {
- pathvector = sp_shape->getCurve()->get_pathvector();
- size_t counter = 0;
+ SPCurve * c = sp_shape->getCurve();
+ if (!c) {
+ return;
+ }
auto wps = pt->wps.begin();
- double previous_pos = 0.0;
for (auto pps = pt->pps.begin(); pps != pt->pps.end(); ++pps,++wps) {
- counter++;
- Geom::Affine transformCoordinate = item->i2dt_affine();
- Geom::Point position = *pps;
- position *= transformCoordinate.inverse();
- double pos = Geom::nearest_time(position, paths_to_pw(pathvector));
- double width = *wps;
- if(pos > 1e6) {
- pos = 0;;
- }
- if(pos > pathvector[0].size() ) {
- pos = pathvector[0].size();
- }
- if ((pos - previous_pos) < pt->min_distance ||
- (counter == pt->wps.size() || (pos - previous_pos) < 0.1) )
- {
- continue;
- }
- previous_pos = pos;
- if (!Geom::are_near(width, 0.0, 0.1) ) {
- points.push_back(Geom::Point(pos,width));
- }
+ pt->addPowerStrokePoint(c, *pps, *wps);
+ }
+ }
+ if(pt->points.empty()){
+ //if use mouse give a line
+ 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;
+ pt->points.push_back(Geom::Point(0,pressure_computed));
}
Effect::createAndApply(POWERSTROKE, dc->desktop->doc(), item);
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
- static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);
+ static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(pt->points);
+ pt->points.clear();
return;
}
}
@@ -389,13 +385,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
if (sp_shape) {
curve = sp_shape->getCurve();
}
- if (SP_IS_PENCIL_CONTEXT(dc)) {
- if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 3) {
- std::vector<Geom::Point> points;
- spdc_apply_powerstroke_shape(points, dc, item);
- shape = NONE;
- }
- }
+
bool shape_applied = false;
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
const char *cstroke = sp_repr_css_property(css_item, "stroke", "none");
@@ -407,6 +397,15 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
if (!swidth) {
swidth = swidth/2;
}
+ if (SP_IS_PENCIL_CONTEXT(dc)) {
+ if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 3) {
+ std::vector<Geom::Point> points;
+ spdc_apply_powerstroke_shape(points, dc, item);
+ shape = NONE;
+ //To allow retain color
+ shape_applied = true;
+ }
+ }
#define SHAPE_LENGTH 10
#define SHAPE_HEIGHT 10
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index 23a442b11..9b411297f 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -20,6 +20,7 @@
#include "ui/tools/pencil-tool.h"
#include "desktop.h"
+#include "inkscape.h"
#include "selection.h"
#include "selection-chemistry.h"
@@ -35,9 +36,14 @@
#include <glibmm/i18n.h>
#include "context-fns.h"
#include "sp-namedview.h"
+#include "xml/node.h"
+#include "xml/sp-css-attr.h"
+#include "svg/svg.h"
+#include "display/curve.h"
#include "desktop-style.h"
#include "display/sp-canvas.h"
#include "display/curve.h"
+#include "live_effects/lpe-powerstroke.h"
#include "ui/tool/event-utils.h"
namespace Inkscape {
@@ -64,8 +70,9 @@ PencilTool::PencilTool()
, req_tangent(0, 0)
, is_drawing(false)
, previous_pressure(0.0)
+ , previous_point(Geom::Point(0,0))
+ , start(false)
, gap_pressure(1.0)
- , min_distance(0.2)
, start_clamp(DDC_MIN_PRESSURE)
, end_clamp(DDC_MAX_PRESSURE)
, sketch_n(0)
@@ -315,9 +322,6 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) {
// - We cannot do this in the button press handler because at that point we don't know yet
// wheter we're going into freehand mode or not
this->ps.push_back(this->p[0]);
- this->pps.push_back(this->p[0]);
- double pressure_computed = pow(this->pressure,3);
- this->wps.push_back(pressure_computed);
}
this->_addFreehandPoint(p, mevent.state);
ret = true;
@@ -421,12 +425,16 @@ 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;
this->ps.clear();
this->wps.clear();
this->pps.clear();
+ previous_pressure = 0.0;
+ previous_point = Geom::Point(0,0);
if (this->green_anchor) {
this->green_anchor = sp_draw_anchor_destroy(this->green_anchor);
}
@@ -628,52 +636,184 @@ void PencilTool::_finishEndpoint() {
}
}
-void PencilTool::_addFreehandPoint(Geom::Point const &p, guint /*state*/) {
- g_assert( this->npoints > 0 );
- g_return_if_fail(unsigned(this->npoints) < G_N_ELEMENTS(this->p));
+void
+sp_powerstroke_preview(SPObject *elemref, Geom::PathVector pathvector, const char * item_id, std::vector<Geom::Point> points)
+{
+ using namespace Inkscape::LivePathEffect;
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ if (!document) {
+ return;
+ }
+ Geom::Affine transformCoordinate = SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->i2dt_affine();
+ Geom::Coord scale = transformCoordinate.expansionX();
+ Inkscape::XML::Document *xml_doc = document->getReprDoc();
+ Inkscape::XML::Node *preview = NULL;
+ if (elemref) {
+ Effect* lpe = SP_LPE_ITEM(elemref)->getCurrentLPE();
+ if (points.size() != static_cast<LPEPowerStroke*>(lpe)->offset_points.data().size()) {
+ static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);
+ }
+ gchar * pvector_str = sp_svg_write_path(pathvector);
+ elemref->setAttribute("inkscape:original-d" , pvector_str);
+ g_free(pvector_str);
+ } else {
+ preview = xml_doc->createElement("svg:path");
+ preview->setAttribute("id", item_id);
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property (css, "fill","none");
+ sp_repr_css_set_property (css, "stroke","#DEDEDE");
+ sp_repr_css_set_property (css, "opacity","0.9");
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ preview->setAttribute("style", css_str.c_str());
+ gchar * pvector_str = sp_svg_write_path(pathvector);
+ preview->setAttribute("d" , pvector_str);
+ g_free(pvector_str);
+ elemref = SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->appendChildRepr(preview);
+ Inkscape::GC::release(preview);
+ Effect::createAndApply(POWERSTROKE, SP_ACTIVE_DESKTOP->doc(), SP_ITEM(elemref));
+ Effect* lpe = SP_LPE_ITEM(elemref)->getCurrentLPE();
+ static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);
+ }
+}
- if ( ( p != this->p[ this->npoints - 1 ] )
- && in_svg_plane(p) )
- {
-
- this->p[this->npoints++] = p;
- this->_fitAndSplit();
- SPCurve *c;
+void
+PencilTool::addPowerStrokePoint(SPCurve * c, Geom::Point p, double pressure_data)
+{
+ bool live = false;
+ SPCurve * curve;
+ if(!c) {
+ SPCurve * previous_red = red_curve->copy();
+ SPCurve * previous_green = green_curve->copy();
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ //Simplify a bit the base curve to avoid artifacts
+ //double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0);
+ //prefs->setDouble("/tools/freehand/pencil/tolerance", 30.0);
+ _interpolate();
+ //prefs->setDouble("/tools/freehand/pencil/tolerance", tol);
+ live = true;
if (sa) {
- c = sa->curve;
+ curve = sa->curve;
if (!green_curve->is_empty()) {
- c->append_continuous( green_curve, 0.0625);
+ curve->append_continuous( green_curve, 0.0625);
+ if (!red_curve->is_empty()) {
+ curve->append_continuous( red_curve, 0.0625);
+ }
}
} else {
if (!green_curve->is_empty()) {
- c = green_curve;
+ curve = green_curve->copy();
+ if (!red_curve->is_empty()) {
+ curve->append_continuous( red_curve, 0.0625);
+ }
} else {
- c = new SPCurve();
+ curve = NULL;
}
}
- if (red_curve_is_valid && !red_curve->is_empty()) {
- c->append_continuous(red_curve, 0.0625);
+ red_curve = previous_red->copy();
+ green_curve = previous_green->copy();
+ previous_red->unref();
+ previous_green->unref();
+ } else {
+ curve = c->copy();
+ }
+ SPObject *elemref = NULL;
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ if (!document) {
+ return;
+ }
+ const char * item_id = "___pencil_preview_powerstroke___";
+ if ((elemref = document->getObjectById(item_id))) {
+ if (!live && 2==3) {
+ LivePathEffectObject * lpeobj = SP_LPE_ITEM(elemref)->getCurrentLPE()->getLPEObj();
+ SP_OBJECT(lpeobj)->deleteObject();
+ lpeobj = NULL;
+ elemref->deleteObject();
+ elemref = NULL;
}
- Geom::PathVector pathvector = c->get_pathvector();
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- double pressure = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3 ? this->pressure :1;
- this->ps.push_back(p);
- double pressure_computed = pow(this->pressure, 3) * 25;
-// std::cout << previous_pressure <<"previous_pressure\n";
-// std::cout << pressure_computed <<"pressure_computed\n";
-// std::cout << std::abs(previous_pressure - pressure_computed) <<"std::abs(previous_pressure - pressure_computed)\n";
-// std::cout << gap_pressure <<"gap_pressure\n";
-// std::cout << Geom::distance(this->pps[this->pps.size()-1], p) << "distance\n";
-
- if (previous_pressure == 0.0 ||
- std::abs(previous_pressure - pressure_computed) > gap_pressure )
- {
- previous_pressure = pressure_computed;
- this->pps.push_back(p);
- this->wps.push_back(pressure_computed);
+ }
+ if (!curve) {
+ return;
+ }
+ Geom::Affine transformCoordinate = SP_ITEM(SP_ACTIVE_DESKTOP->currentLayer())->i2dt_affine();
+ Geom::Coord scale = transformCoordinate.expansionX();
+ double zoom = SP_EVENT_CONTEXT(this)->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;
+ }
+ //Maybe the 12 POW can be moved to a preferences 12 give a good results of sensibility on my tablet
+ //But maybe is a tweakable value. less number = less sensibility
+ //8 give an aceptable max witht to powerstoke
+ double pressure_base = pow(pressure_data, 12);
+ double pressure_shirnked = (pressure_base * (max - min)) + min;
+ double pressure_factor = pressure_base/pressure_shirnked;
+ double pressure_computed = (pressure_shirnked * 8.0 * scale) / zoom;
+ bool force = false;
+ bool buttonrelease = false;
+ if (pressure_computed < 0.05 && previous_pressure != 0.0 ) {
+ pressure_computed = previous_pressure;
+ force = true;
+ buttonrelease = true;
+// } else if (std::abs(previous_pressure - pressure_computed) > 4 && previous_pressure != 0.0) {
+// pressure_computed = previous_pressure;
+// force = true;
+ }
+ if (previous_pressure == 0.0 && pressure_computed != 0.0) {
+ start = true;
+ }
+ double tol = 135.0 / zoom;
+ Geom::PathVector pathvector = curve->get_pathvector();
+ pathvector *= transformCoordinate.inverse();
+ if (start || force || std::abs(previous_pressure - pressure_computed) > gap_pressure / (zoom * pressure_factor)) {
+ previous_pressure = pressure_computed;
+ double pos = pathvector[0].size();
+ if (live) {
+ p = pathvector[0].finalPoint();
+ } else {
+ pos = Geom::nearest_time(p, paths_to_pw(pathvector));
+ }
+ //This magic number get an acurate result maybe is better move to preferences and optionaly add GUI
+
+ //Force star and end in start and end path position
+ if(pos > 1e6 || start) {
+ pos = 0.0;
+ } else if (buttonrelease) {
+ pos = pathvector[0].size();
+ } else if (pos > 0.0 && Geom::distance(p, previous_point) < tol ) {
+ sp_powerstroke_preview(elemref, pathvector, item_id, points);
+ return;
+ }
+ start = false;
+ previous_point = p;
+ this->points.push_back(Geom::Point(pos, pressure_computed));
+ if (live) {
+ pps.push_back(p);
+ wps.push_back(pressure_data);
}
+ }
+ if (live) {
+ sp_powerstroke_preview(elemref, pathvector, item_id, points);
+ }
+}
+
+void PencilTool::_addFreehandPoint(Geom::Point const &p, guint /*state*/) {
+ g_assert( this->npoints > 0 );
+ g_return_if_fail(unsigned(this->npoints) < G_N_ELEMENTS(this->p));
+
+ if ( ( p != this->p[ this->npoints - 1 ] )
+ && in_svg_plane(p) )
+ {
+
this->p[this->npoints++] = p;
this->_fitAndSplit();
+ this->ps.push_back(p);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) {
+ this->addPowerStrokePoint(NULL, p, this->pressure);
+ }
}
}
@@ -849,6 +989,7 @@ void PencilTool::_sketchInterpolate() {
this->ps.clear();
this->pps.clear();
+ this->points.clear();
this->wps.clear();
}
diff --git a/src/ui/tools/pencil-tool.h b/src/ui/tools/pencil-tool.h
index b6e9680d2..607d10c4a 100644
--- a/src/ui/tools/pencil-tool.h
+++ b/src/ui/tools/pencil-tool.h
@@ -46,13 +46,15 @@ public:
std::vector<Geom::Point> ps;
std::vector<Geom::Point> pps;
+ std::vector<Geom::Point> points;
std::vector<double> wps;
double previous_pressure;
+ Geom::Point previous_point;
+ bool start;
double gap_pressure;
- double min_distance;
double start_clamp;
double end_clamp;
-
+ void addPowerStrokePoint(SPCurve * c, Geom::Point p, double pressure_data);
Geom::Piecewise<Geom::D2<Geom::SBasis> > sketch_interpolation; // the current proposal from the sketched paths
unsigned sketch_n; // number of sketches done
@@ -71,8 +73,8 @@ private:
bool _handleButtonRelease(GdkEventButton const &revent);
bool _handleKeyPress(GdkEventKey const &event);
bool _handleKeyRelease(GdkEventKey const &event);
-
void _setStartpoint(Geom::Point const &p);
+
void _setEndpoint(Geom::Point const &p);
void _finishEndpoint();
void _addFreehandPoint(Geom::Point const &p, guint state);
diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp
index d3c7f5a79..f33a33ecd 100644
--- a/src/widgets/pencil-toolbar.cpp
+++ b/src/widgets/pencil-toolbar.cpp
@@ -83,6 +83,16 @@ static void freehand_mode_changed(EgeSelectOneAction* act, GObject* tbl)
if (SP_IS_PEN_CONTEXT(desktop->event_context)) {
Inkscape::UI::Tools::PenTool *pc = SP_PEN_CONTEXT(desktop->event_context);
pc->setPolylineMode();
+ } else {
+ if (mode == 3) {
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "shape_action") ), false );
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "minpressure") ), true );
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "maxpressure") ), true );
+ } else {
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "shape_action") ), true );
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "minpressure") ), false );
+ gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "maxpressure") ), false );
+ }
}
if (mode == 1 || mode == 2) {
gtk_action_set_visible( GTK_ACTION( g_object_get_data(tbl, "flatten_spiro_bspline") ), true );
@@ -241,6 +251,11 @@ static void freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GOb
g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(freehand_change_shape), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
g_object_set_data( holder, "shape_action", act1 );
+ if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) {
+ gtk_action_set_visible( GTK_ACTION(act1), false );
+ } else {
+ gtk_action_set_visible( GTK_ACTION(act1), true );
+ }
}
}
@@ -351,6 +366,26 @@ static void sp_simplify_flatten(GtkWidget * /*widget*/, GObject *obj)
}
}
+static void sp_minpressure_value_changed(GtkAdjustment *adj, GObject *tbl)
+{
+ // quit if run by the attr_changed listener
+ if (g_object_get_data( tbl, "freeze" )) {
+ return;
+ }
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/freehand/pencil/minpressure", gtk_adjustment_get_value(adj));
+}
+
+static void sp_maxpressure_value_changed(GtkAdjustment *adj, GObject *tbl)
+{
+ // quit if run by the attr_changed listener
+ if (g_object_get_data( tbl, "freeze" )) {
+ return;
+ }
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/freehand/pencil/maxpressure", gtk_adjustment_get_value(adj));
+}
+
static void sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
{
// quit if run by the attr_changed listener
@@ -445,7 +480,41 @@ void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
sp_add_freehand_mode_toggle(mainActions, holder, true);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
EgeAdjustmentAction* eact = 0;
-
+ /* min pressure */
+ {
+ eact = create_adjustment_action( "MinPressureAction",
+ _("Min presure"), _("Min:"), _("Min percent of pressure"),
+ "/tools/freehand/pencil/minpressure", 0,
+ GTK_WIDGET(desktop->canvas), holder, FALSE, NULL,
+ 0, 100, 1, 0,
+ 0, 0, 0,
+ sp_minpressure_value_changed, NULL, 0 ,0);
+
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ g_object_set_data( holder, "minpressure", eact );
+ if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) {
+ gtk_action_set_visible( GTK_ACTION(eact), true );
+ } else {
+ gtk_action_set_visible( GTK_ACTION(eact), false );
+ }
+ }
+ /* max pressure */
+ {
+ eact = create_adjustment_action( "MaxPressureAction",
+ _("Max presure"), _("Max:"), _("Max percent of pressure"),
+ "/tools/freehand/pencil/maxpressure", 100,
+ GTK_WIDGET(desktop->canvas), holder, FALSE, NULL,
+ 0, 100, 1, 0,
+ 0, 0, 0,
+ sp_maxpressure_value_changed, NULL, 0 ,0);
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ g_object_set_data( holder, "maxpressure", eact );
+ if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) {
+ gtk_action_set_visible( GTK_ACTION(eact), true );
+ } else {
+ gtk_action_set_visible( GTK_ACTION(eact), false );
+ }
+ }
/* Tolerance */
{
gchar const* labels[] = {_("(many nodes, rough)"), _("(default)"), 0, 0, 0, 0, _("(few nodes, smooth)")};