25#include <gdk/gdkkeysyms.h>
26#include <glibmm/i18n.h>
68#define DDC_MIN_PRESSURE 0.0
69#define DDC_MAX_PRESSURE 1.0
70#define DDC_DEFAULT_PRESSURE 1.0
83 if (prefs->
getBool(
"/tools/freehand/pencil/selcue")) {
105 if ((state & GDK_CONTROL_MASK)) {
110 if (!(state & GDK_SHIFT_MASK)) {
186 if (event.
modifiers & GDK_CONTROL_MASK) {
188 if (!(event.
modifiers & GDK_SHIFT_MASK)) {
213 }
else if (!(event.
modifiers & GDK_SHIFT_MASK)) {
248 if ((event.
modifiers & GDK_BUTTON2_MASK)) {
260 if ( ( event.
modifiers & GDK_BUTTON1_MASK ) && this->_is_drawing) {
325 _wps.emplace_back(0, 0);
339 }
else if (!anchor) {
396 if (is<SPLPEItem>(
item)) {
397 Effect* lpe = cast<SPLPEItem>(
item)->getCurrentLPE();
455 gint shapetype = prefs->
getInt(
"/tools/freehand/pencil/shape", 0);
456 gint simplify = prefs->
getInt(
"/tools/freehand/pencil/simplify", 0);
457 gint
mode = prefs->
getInt(
"/tools/freehand/pencil/freehand-mode", 0);
458 prefs->
setInt(
"/tools/freehand/pencil/shape", 0);
459 prefs->
setInt(
"/tools/freehand/pencil/simplify", 0);
460 prefs->
setInt(
"/tools/freehand/pencil/freehand-mode", 0);
462 prefs->
setInt(
"/tools/freehand/pencil/freehand-mode",
mode);
463 prefs->
setInt(
"/tools/freehand/pencil/simplify", simplify);
464 prefs->
setInt(
"/tools/freehand/pencil/shape", shapetype);
516 case GDK_KEY_KP_Down:
616 g_return_if_fail( this->
_npoints > 0 );
645 this->red_curve.first_point() == this->red_curve.second_point())
659static inline double square(
double const x) {
return x * x; }
672 double tol = prefs->
getDoubleLimited(
"/tools/freehand/pencil/base-simplify", 25.0, 0.0, 100.0) * 0.4;
674 int n_points = this->
ps.size();
676 int max_segs = 4 * n_points;
677 std::vector<Geom::Point> b(max_segs);
682 curvepressure.
moveto(b[0]);
683 for (
int c = 0;
c < n_segs;
c++) {
684 curvepressure.
curveto(b[4 *
c + 1], b[4 *
c + 2], b[4 *
c + 3]);
698 auto powerpreview = cast<SPShape>(
currentLayer()->appendChildRepr(pp));
699 auto lpeitem = powerpreview;
704 tol = prefs->
getDoubleLimited(
"/tools/freehand/pencil/tolerance", 10.0, 0.0, 100.0) + 30;
706 tol = tol / (130.0 * (132.0 - tol));
709 Effect::createAndApply(SIMPLIFY, document, lpeitem);
710 Effect *lpe = lpeitem->getCurrentLPE();
715 Glib::ustring pref_path =
"/live_effects/simplify/smooth_angles";
720 pref_path =
"/live_effects/simplify/helper_size";
725 pref_path =
"/live_effects/simplify/step";
736 SPCurve const *curvepressure = powerpreview->curve();
744 Glib::ustring pref_path_pp =
"/live_effects/powerstroke/powerpencil";
745 prefs->
setBool(pref_path_pp,
true);
746 Effect::createAndApply(POWERSTROKE, document, lpeitem);
747 Effect *lpe = lpeitem->getCurrentLPE();
751 Glib::ustring pref_path =
"/live_effects/powerstroke/interpolator_type";
756 pref_path =
"/live_effects/powerstroke/linejoin_type";
761 pref_path =
"/live_effects/powerstroke/interpolator_beta";
766 gint cap = prefs->
getInt(
"/live_effects/powerstroke/powerpencilcap", 2);
767 pspreview->
getRepr()->
setAttribute(
"start_linecap_type", LineCapTypeConverter.get_key(cap));
774 pp->
setAttribute(
"style",
"fill:#888888;opacity:1;fill-rule:nonzero;stroke:none;");
776 prefs->
setBool(pref_path_pp,
false);
802 this->
ps.push_back(p);
806 double min = prefs->
getIntLimited(
"/tools/freehand/pencil/minpressure", 0, 0, 100) / 100.0;
807 double max = prefs->
getIntLimited(
"/tools/freehand/pencil/maxpressure", 30, 0, 100) / 100.0;
812 double const pressure_shrunk = std::lerp(min, max,
pressure);
813 double pressure_computed = std::abs(pressure_shrunk * dezoomify_factor);
818 if (pressure_computed) {
825 if (!pressure_path.
empty() && !previous_presure.
empty()) {
839 size_t ps_size = this->
ps.size();
840 if ( ps_size <= 1 ) {
846 gint path_size = path.
size();
847 std::vector<Geom::Point> tmp_points;
849 bool increase =
false;
852 double limit = 6 * dezoomify_factor;
855 double min = std::min(this->
_wps.back()[
Geom::X] / 10, limit);
856 double original_lenght = this->
_wps.back()[
Geom::X];
859 for (
auto wps : this->
_wps) {
864 if (!original_lenght || wps[
Geom::X] > max) {
870 if (previous[
Geom::Y] < (max10 + min10) / 2.0) {
871 if (increase && tmp_points.size() > 1) {
872 tmp_points.pop_back();
875 tmp_points.push_back(wps);
878 if (!increase && tmp_points.size() > 1) {
879 tmp_points.pop_back();
882 tmp_points.push_back(wps);
890 double prev_pressure = 0;
891 for (
auto point : tmp_points) {
892 point[
Geom::X] /= (double)original_lenght;
894 if (std::abs(point[
Geom::Y] - prev_pressure) > point[
Geom::Y] / 10.0) {
895 this->
points.push_back(point);
896 prev_pressure = point[
Geom::Y];
901 double average_pressure = std::accumulate(
_wps.begin(),
_wps.end(), 0.0,
902 [](
double const &sum_so_far,
Geom::Point const &point) ->
double {
903 return sum_so_far + point[Geom::Y];
904 }) / (double)
_wps.size();
906 2.0 * average_pressure );
911 size_t ps_size = this->
ps.size();
912 if ( ps_size <= 1 ) {
918 double tol = prefs->
getDoubleLimited(
"/tools/freehand/pencil/tolerance", 10.0, 0.0, 100.0) * 0.4;
919 bool simplify = prefs->
getInt(
"/tools/freehand/pencil/simplify", 0);
921 double tol2 = prefs->
getDoubleLimited(
"/tools/freehand/pencil/base-simplify", 25.0, 0.0, 100.0) * 0.4;
922 tol = std::min(tol,tol2);
932 int n_points = this->
ps.size();
935 int max_segs = 4 * n_points;
937 std::vector<Geom::Point> b(max_segs);
943 guint
mode = prefs->
getInt(
"/tools/freehand/pencil/freehand-mode", 0);
944 for (
int c = 0;
c < n_segs;
c++) {
947 Geom::Point point_at1 = b[4 *
c + 0] + (1./3) * (b[4 *
c + 3] - b[4 *
c + 0]);
948 Geom::Point point_at2 = b[4 *
c + 3] + (1./3) * (b[4 *
c + 0] - b[4 *
c + 3]);
949 this->
green_curve->curveto(point_at1,point_at2,b[4*
c+3]);
952 this->
green_curve->curveto(b[4 *
c + 1], b[4 *
c + 2], b[4 *
c + 3]);
954 std::optional<Geom::Point> finalp = this->
green_curve->last_point();
957 this->
green_curve->curveto(*finalp, b[4 *
c + 3], b[4 *
c + 3]);
959 this->
green_curve->curveto(b[4 *
c + 1], b[4 *
c + 3], b[4 *
c + 3]);
974 g_assert( last_seg );
979 delete last_seg_reverse;
990 if ( this->
ps.size() <= 1 ) {
995 double tol = prefs->
getDoubleLimited(
"/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
996 bool simplify = prefs->
getInt(
"/tools/freehand/pencil/simplify", 0);
998 double tol2 = prefs->
getDoubleLimited(
"/tools/freehand/pencil/base-simplify", 25.0, 1.0, 100.0) * 0.4;
999 tol = std::min(tol,tol2);
1003 bool average_all_sketches = prefs->
getBool(
"/tools/freehand/pencil/average_all_sketches",
true);
1010 int n_points = this->
ps.size();
1013 int max_segs = 4 * n_points;
1015 std::vector<Geom::Point> b(max_segs);
1022 for (
int c = 0;
c < n_segs;
c++) {
1031 if (average_all_sketches) {
1066 g_assert( last_seg );
1071 delete last_seg_reverse;
1086 double const tolerance_sq = 0;
1106 guint
mode = prefs->
getInt(
"/tools/freehand/pencil/freehand-mode", 0);
1108 Geom::Point point_at1 = b[0] + (1./3)*(b[3] - b[0]);
1109 Geom::Point point_at2 = b[3] + (1./3)*(b[0] - b[3]);
1126 g_assert( last_seg );
1131 delete last_seg_reverse;
1143 auto other = prefs->
getColor(
"/tools/nodes/highlight_color",
"#ff0000ff");
1145 if(other == highlight) {
TODO: insert short description here.
double distance(Shape const *s, Geom::Point const &p)
Bezier fitting algorithms.
Coord descrim() const
Calculate the descriminant.
Bezier curve with compile-time specified order.
Set of all points at a fixed distance from the center.
D2< SBasis > toSBasis() const
Abstract continuous curve on a plane defined on [0,1].
virtual Point finalPoint() const =0
Retrieve the end of the curve.
virtual Curve * reverse() const
Create a reversed version of this curve.
virtual Point unitTangentAt(Coord t, unsigned n=3) const
Compute a vector tangent to the curve.
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
bool empty() const
Check whether path is empty.
Piecewise< D2< SBasis > > toPwSb() const
size_type size() const
Natural size of the path.
void appendNew(Args &&... args)
Append a new curve to the path.
Function defined as discrete pieces.
void push(const T &s, double to)
Convenience/implementation hiding function to add segment/cut pairs.
Two-dimensional point that doubles as a vector.
uint32_t toRGBA(double opacity=1.0) const
Return an sRGB conversion of the color in RGBA int32 format.
void remove_snaptarget(bool only_if_presnap=false)
RAII-style mechanism for creating a temporary undo-insensitive context.
SPGroup * currentLayer() const
Returns current top layer.
void param_set_and_write_new_value(std::vector< StorageType > const &new_vector)
Inkscape::XML::Node * getRepr()
PowerStrokePointArrayParam offset_points
MessageId flash(MessageType type, char const *message)
Temporarily pushes a message onto the stack.
void clear()
Unselects all selected objects.
SPItem * singleItem()
Returns a single selected item.
bool isValidDouble() const
Check if the preference value can be interpreted as a floating point value.
bool isValidString() const
Check if the preference value is a valid String.
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
Colors::Color getColor(Glib::ustring const &pref_path, std::string const &def="black")
Entry const getEntry(Glib::ustring const &pref_path)
Retrieve a preference entry without specifying its type.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
int getIntLimited(Glib::ustring const &pref_path, int def=0, int min=INT_MIN, int max=INT_MAX)
Retrieve a limited integer.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
double getDoubleLimited(Glib::ustring const &pref_path, double def=0.0, double min=DBL_MIN, double max=DBL_MAX, Glib::ustring const &unit="")
Retrieve a limited floating point value.
The set of selected SPObjects for a given document and layer model.
void add(XML::Node *repr)
Add an XML node's SPObject to the set of selected objects.
Class to store data for points which are snap candidates, either as a source or as a target.
Interface for refcounted XML nodes.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Path and its polyline approximation.
void LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation)
Load a lib2geom Geom::PathVector in this path object.
Geom::PathVector MakePathVector() const
Create a lib2geom Geom::PathVector from this Path object.
void Simplify(double treshhold)
Simplify the path.
Wrapper around a Geom::PathVector object.
Geom::Curve const * last_segment() const
Return last pathsegment (possibly the closing path segment) of the last path in PathVector or NULL.
void moveto(Geom::Point const &p)
Perform a moveto to a point, thus starting a new subpath.
bool is_unset() const
True if paths are in curve.
void transform(Geom::Affine const &m)
Transform all paths in curve by matrix.
void reset()
Set curve to empty curve.
Geom::PathVector const & get_pathvector() const
void lineto(Geom::Point const &p)
Adds a line to the current subpath.
bool is_empty() const
True if no paths are in curve.
void curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2)
Adds a bezier segment to the current subpath.
To do: update description of desktop.
double current_zoom() const
SPDocument * getDocument() const
Inkscape::CanvasItemGroup * getCanvasSketch() const
Inkscape::MessageStack * messageStack() const
Inkscape::Display::SnapIndicator * getSnapIndicator() const
SPNamedView * getNamedView() const
Inkscape::Selection * getSelection() const
Inkscape::LayerManager & layerManager()
Geom::Affine const & w2d() const
Transformation from window to desktop coordinates (zoom/rotate).
Typed SVG document implementation.
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Geom::Scale getDocumentScale(bool computed=true) const
Returns document scale as defined by width/height (in pixels) and viewBox (real world to user-units).
std::shared_ptr< SPCurve > curve
Inkscape::Colors::Color highlight_color() const override
Generate a highlight colour if one isn't set and return it.
Base class for visual SVG elements.
Class to coordinate snapping operations.
void setup(SPDesktop const *desktop, bool snapindicator=true, SPObject const *item_to_ignore=nullptr, std::vector< Inkscape::SnapCandidatePoint > *unselected_nodes=nullptr)
Convenience shortcut when there is only one item to ignore.
void preSnap(Inkscape::SnapCandidatePoint const &p, bool to_path_only=false)
Editable view implementation.
The nodes at the ends of the path in the pen/pencil tools.
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
constexpr Coord infinity()
Get a value representing infinity.
double Coord
Floating point type used to store coordinates.
Interpolators for lists of points.
PowerStroke LPE effect, see lpe-powerstroke.cpp.
Interface for locally managing a current status message.
Raw stack of active status messages.
int bezier_fit_cubic_full(Point bezier[], int split_points[], Point const data[], int len, Point const &tHat1, Point const &tHat2, double error, unsigned max_beziers)
Fit a multi-segment Bezier curve to a set of digitized points, without possible weedout of identical ...
Angle distance(Angle const &a, Angle const &b)
bool is_zero(Point const &p)
int bezier_fit_cubic_r(Point bezier[], Point const data[], int len, double error, unsigned max_beziers)
Fit a multi-segment Bezier curve to a set of digitized points, with possible weedout of identical poi...
PathVector path_from_piecewise(Piecewise< D2< SBasis > > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
Point unit_vector(Point const &a)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Coord LInfty(Point const &p)
static R & release(R &r)
Decrements the reference count of a anchored object.
void inspect_event(E &&event, Fs... funcs)
Perform pattern-matching on a CanvasEvent.
bool state_held_only_shift(unsigned state)
bool have_viable_layer(SPDesktop *desktop, MessageContext *message)
Check to see if the current layer is both unhidden and unlocked.
bool state_held_only_ctrl(unsigned state)
Geom::PathVector sp_pathvector_boolop(Geom::PathVector const &pathva, Geom::PathVector const &pathvb, BooleanOp bop, FillRule fra, FillRule frb)
Perform a boolean operation on two pathvectors.
Conversion between SBasis and Bezier basis polynomials.
Provides a class that shows a temporary indicator on the canvas of where the snap was,...
SPCSSAttr - interface for CSS Attributes.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable)
Base class for live path effect items.
Abstract base class for events.
unsigned modifiers
The modifiers mask immediately before the event.
Movement of the mouse pointer.
Geom::Point pos
Location of the cursor.
Interface for XML documents.
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
parse SVG path specifications
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)