diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-08-25 13:32:29 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-08-25 13:32:29 +0000 |
| commit | 6d99fed16aeeb21341e5d28f52534b2a0b94f876 (patch) | |
| tree | 5caf1bbcf66d2c7e04092ef482c00cad63d3d076 /src/ui | |
| parent | [LP:1634022] xcf export - Guides and grids wrongly positionned. Guides and gr... (diff) | |
| download | inkscape-6d99fed16aeeb21341e5d28f52534b2a0b94f876.tar.gz inkscape-6d99fed16aeeb21341e5d28f52534b2a0b94f876.zip | |
Starting with powerpencil
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/tools/freehand-base.cpp | 62 | ||||
| -rw-r--r-- | src/ui/tools/freehand-base.h | 15 | ||||
| -rw-r--r-- | src/ui/tools/pen-tool.cpp | 4 | ||||
| -rw-r--r-- | src/ui/tools/pencil-tool.cpp | 78 | ||||
| -rw-r--r-- | src/ui/tools/pencil-tool.h | 60 |
5 files changed, 177 insertions, 42 deletions
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 76d2df8c5..05afd8058 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -32,6 +32,7 @@ #include "macros.h" #include "message-stack.h" #include "ui/tools/pen-tool.h" +#include "ui/tools/pencil-tool.h" #include "ui/tools/lpe-tool.h" #include "selection-chemistry.h" #include "sp-item-group.h" @@ -41,6 +42,10 @@ // clipboard support #include "ui/clipboard.h" +#define MIN_PRESSURE 0.0 +#define MAX_PRESSURE 1.0 +#define DEFAULT_PRESSURE 1.0 + using Inkscape::DocumentUndo; namespace Inkscape { @@ -89,6 +94,7 @@ FreehandBase::FreehandBase(gchar const *const *cursor_shape) , waiting_LPE_type(Inkscape::LivePathEffect::INVALID_LPE) , red_curve_is_valid(false) , anchor_statusbar(false) + , pressure(DEFAULT_PRESSURE) { } @@ -222,12 +228,56 @@ static void spdc_paste_curve_as_freehand_shape(Geom::PathVector const &newpath, lpe->getRepr()->setAttribute("prop_scale", os.str().c_str()); } -static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points, FreehandBase *dc, SPItem *item) +static void spdc_apply_powerstroke_shape(std::vector<Geom::Point> points, FreehandBase *dc, SPItem *item) { using namespace Inkscape::LivePathEffect; + if (SP_IS_PENCIL_CONTEXT(dc)) { + PencilTool *pt = SP_PENCIL_CONTEXT(dc); + 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; + 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)); + } + } + } + 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); + return; + } + } + 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); // write powerstroke parameters: @@ -321,7 +371,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, } bool simplify = prefs->getInt(tool_name(dc) + "/simplify", 0); if(simplify){ - double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0); + double tol = prefs->getDoubleLimited(tool_name(dc) + "/tolerance", 10.0, 1.0, 100.0); tol = tol/(100.0*(102.0-tol)); std::ostringstream ss; ss << tol; @@ -339,7 +389,13 @@ 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"); diff --git a/src/ui/tools/freehand-base.h b/src/ui/tools/freehand-base.h index a3069aa09..11c5ac124 100644 --- a/src/ui/tools/freehand-base.h +++ b/src/ui/tools/freehand-base.h @@ -44,8 +44,8 @@ namespace Tools { class FreehandBase : public ToolBase { public: - FreehandBase(gchar const *const *cursor_shape); - virtual ~FreehandBase(); + FreehandBase(gchar const *const *cursor_shape); + virtual ~FreehandBase(); Inkscape::Selection *selection; SPCanvasItem *grab; @@ -98,12 +98,15 @@ public: bool red_curve_is_valid; bool anchor_statusbar; + + gdouble pressure; + virtual void set(const Inkscape::Preferences::Entry& val); protected: - virtual void setup(); - virtual void finish(); - virtual void set(const Inkscape::Preferences::Entry& val); - virtual bool root_handler(GdkEvent* event); + + virtual void setup(); + virtual void finish(); + virtual bool root_handler(GdkEvent* event); }; /** diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp index 77cb5b6f8..b3497d006 100644 --- a/src/ui/tools/pen-tool.cpp +++ b/src/ui/tools/pen-tool.cpp @@ -1774,9 +1774,9 @@ void PenTool::_bsplineSpiroBuild() //LivePathEffectObject *lpeobj = static_cast<LivePathEffectObject*> (curve); //Effect *spr = static_cast<Effect*> ( new LPEbspline(lpeobj) ); //spr->doEffect(curve); - if(this->bspline){ + if (this->bspline) { LivePathEffect::sp_bspline_do_effect(curve, 0); - }else{ + } else { LivePathEffect::sp_spiro_do_effect(curve); } diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp index 99b8103c3..23a442b11 100644 --- a/src/ui/tools/pencil-tool.cpp +++ b/src/ui/tools/pencil-tool.cpp @@ -63,6 +63,11 @@ PencilTool::PencilTool() , state(SP_PENCIL_CONTEXT_IDLE) , req_tangent(0, 0) , is_drawing(false) + , previous_pressure(0.0) + , gap_pressure(1.0) + , min_distance(0.2) + , start_clamp(DDC_MIN_PRESSURE) + , end_clamp(DDC_MAX_PRESSURE) , sketch_n(0) { } @@ -79,9 +84,19 @@ void PencilTool::setup() { this->anchor_statusbar = false; } + + PencilTool::~PencilTool() { } +void PencilTool::_extinput(GdkEvent *event) { + if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &this->pressure)) { + this->pressure = CLAMP (this->pressure, start_clamp, end_clamp); + } else { + this->pressure = DDC_DEFAULT_PRESSURE; + } +} + /** Snaps new node relative to the previous node. */ void PencilTool::_endpointSnap(Geom::Point &p, guint const state) { if ((state & GDK_CONTROL_MASK)) { //CTRL enables constrained snapping @@ -110,6 +125,7 @@ bool PencilTool::root_handler(GdkEvent* event) { break; case GDK_MOTION_NOTIFY: + this->_extinput(event); ret = this->_handleMotionNotify(event->motion); break; @@ -138,7 +154,6 @@ bool PencilTool::root_handler(GdkEvent* event) { bool PencilTool::_handleButtonPress(GdkEventButton const &bevent) { bool ret = false; - if ( bevent.button == 1 && !this->space_panning) { Inkscape::Selection *selection = desktop->getSelection(); @@ -165,7 +180,10 @@ 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(); + if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) { + this->state = SP_PENCIL_CONTEXT_FREEHAND; + } switch (this->state) { case SP_PENCIL_CONTEXT_ADDLINE: /* Current segment will be finished with release */ @@ -224,7 +242,7 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) { } bool ret = false; - + if (this->space_panning || (mevent.state & GDK_BUTTON2_MASK) || (mevent.state & GDK_BUTTON3_MASK)) { // allow scrolling return false; @@ -244,9 +262,8 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) { /* Test whether we hit any anchor. */ SPDrawAnchor *anchor = spdc_test_inside(this, Geom::Point(mevent.x, mevent.y)); - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (pencil_within_tolerance) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); if ( Geom::LInfty( Geom::Point(mevent.x,mevent.y) - pencil_drag_origin_w ) < tolerance ) { return false; // Do not drag if we're within tolerance from origin. @@ -261,6 +278,10 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) { switch (this->state) { case SP_PENCIL_CONTEXT_ADDLINE: /* Set red endpoint */ + if (prefs->getInt("/tools/freehand/pencil/freehand-mode", 0) == 3) { + this->state = SP_PENCIL_CONTEXT_FREEHAND; + return true; + } if (anchor) { p = anchor->dp; } else { @@ -294,6 +315,9 @@ 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; @@ -400,6 +424,9 @@ bool PencilTool::_handleButtonRelease(GdkEventButton const &revent) { spdc_concat_colors_and_flush(this, FALSE); this->sa = NULL; this->ea = NULL; + this->ps.clear(); + this->wps.clear(); + this->pps.clear(); if (this->green_anchor) { this->green_anchor = sp_draw_anchor_destroy(this->green_anchor); } @@ -608,7 +635,43 @@ void PencilTool::_addFreehandPoint(Geom::Point const &p, guint /*state*/) { if ( ( p != this->p[ this->npoints - 1 ] ) && in_svg_plane(p) ) { + + this->p[this->npoints++] = p; + this->_fitAndSplit(); + SPCurve *c; + if (sa) { + c = sa->curve; + if (!green_curve->is_empty()) { + c->append_continuous( green_curve, 0.0625); + } + } else { + if (!green_curve->is_empty()) { + c = green_curve; + } else { + c = new SPCurve(); + } + } + if (red_curve_is_valid && !red_curve->is_empty()) { + c->append_continuous(red_curve, 0.0625); + } + 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); + } this->p[this->npoints++] = p; this->_fitAndSplit(); } @@ -690,8 +753,7 @@ void PencilTool::_interpolate() { : Geom::unit_vector(req_vec) ); } } - - this->ps.clear(); + //this->ps = b; } @@ -786,6 +848,8 @@ void PencilTool::_sketchInterpolate() { } this->ps.clear(); + this->pps.clear(); + this->wps.clear(); } void PencilTool::_fitAndSplit() { diff --git a/src/ui/tools/pencil-tool.h b/src/ui/tools/pencil-tool.h index e8d156dbd..b6e9680d2 100644 --- a/src/ui/tools/pencil-tool.h +++ b/src/ui/tools/pencil-tool.h @@ -11,8 +11,12 @@ #include <2geom/d2.h> #include <2geom/sbasis.h> -#define SP_PENCIL_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::PencilTool*>((ToolBase*)obj)) -#define SP_IS_PENCIL_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::PencilTool*>((const ToolBase*)obj) != NULL) + +#define DDC_MIN_PRESSURE 0.0 +#define DDC_MAX_PRESSURE 1.0 +#define DDC_DEFAULT_PRESSURE 1.0 +#define SP_PENCIL_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::PencilTool*>((Inkscape::UI::Tools::ToolBase*)obj)) +#define SP_IS_PENCIL_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::PencilTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) namespace Inkscape { namespace UI { @@ -30,8 +34,8 @@ enum PencilState { */ class PencilTool : public FreehandBase { public: - PencilTool(); - virtual ~PencilTool(); + PencilTool(); + virtual ~PencilTool(); Geom::Point p[16]; gint npoints; @@ -41,35 +45,43 @@ public: bool is_drawing; std::vector<Geom::Point> ps; + std::vector<Geom::Point> pps; + std::vector<double> wps; + double previous_pressure; + double gap_pressure; + double min_distance; + double start_clamp; + double end_clamp; Geom::Piecewise<Geom::D2<Geom::SBasis> > sketch_interpolation; // the current proposal from the sketched paths unsigned sketch_n; // number of sketches done - static const std::string prefsPath; + static const std::string prefsPath; - virtual const std::string& getPrefsPath(); + virtual const std::string& getPrefsPath(); protected: - virtual void setup(); - virtual bool root_handler(GdkEvent* event); + + virtual void setup(); + virtual bool root_handler(GdkEvent* event); private: - bool _handleButtonPress(GdkEventButton const &bevent); - bool _handleMotionNotify(GdkEventMotion const &mevent); - 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); - void _fitAndSplit(); - void _interpolate(); - void _sketchInterpolate(); - - void _cancel(); - void _endpointSnap(Geom::Point &p, guint const state); + bool _handleButtonPress(GdkEventButton const &bevent); + bool _handleMotionNotify(GdkEventMotion const &mevent); + 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); + void _fitAndSplit(); + void _interpolate(); + void _sketchInterpolate(); + void _extinput(GdkEvent *event); + void _cancel(); + void _endpointSnap(Geom::Point &p, guint const state); }; } |
