Inkscape
Vector Graphics Editor
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages Concepts
node.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5/* Authors:
6 * Krzysztof Kosiński <tweenk.pl@gmail.com>
7 * Jon A. Cruz <jon@joncruz.org>
8 *
9 * Copyright (C) 2009 Authors
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#ifndef INKSCAPE_UI_TOOL_NODE_H
14#define INKSCAPE_UI_TOOL_NODE_H
15
16#include <cstddef>
17#include <iosfwd>
18#include <list>
19#include <memory>
20#include <optional>
21#include <2geom/point.h>
22#include <boost/noncopyable.hpp>
23
24#include "snap-candidate.h"
26#include "ui/tool/node-types.h"
27
28namespace Inkscape {
29class CanvasItemGroup;
30class CanvasItemCurve;
31
32namespace UI {
33
34class PathManipulator;
35class MultiPathManipulator;
36
37class Node;
38class Handle;
39class NodeList;
40class SubpathList;
41template <typename> class NodeIterator;
42
43std::ostream &operator<<(std::ostream &, NodeType);
44
51
60
61class Handle : public ControlPoint
62{
63public:
64 ~Handle() override;
65
66 inline Geom::Point relativePos() const;
67 inline double length() const;
68 bool isDegenerate() const { return _degenerate; } // True if the handle is retracted, i.e. has zero length.
69
70 void setVisible(bool) override;
71 void move(Geom::Point const &p) override;
72
73 void setPosition(Geom::Point const &p) override;
74 inline void setRelativePos(Geom::Point const &p);
75 void setLength(double len);
76 void retract();
77 void setDirection(Geom::Point const &from, Geom::Point const &to);
78 void setDirection(Geom::Point const &dir);
79 Node *parent() { return _parent; }
80 Handle *other();
81 Handle const *other() const;
82
83 static char const *handle_type_to_localized_string(NodeType type);
84
85protected:
86 Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
87
88 virtual void handle_2button_press();
89 bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, CanvasEvent const &event) override;
90 void dragged(Geom::Point &new_pos, MotionEvent const &event) override;
91 bool grabbed(MotionEvent const &event) override;
92 void ungrabbed(ButtonReleaseEvent const *event) override;
93 bool clicked(ButtonReleaseEvent const &event) override;
94
95 Glib::ustring _getTip(unsigned state) const override;
96 Glib::ustring _getDragTip(MotionEvent const &event) const override;
97 bool _hasDragTips() const override { return true; }
98
99private:
100 inline PathManipulator &_pm();
101 inline PathManipulator &_pm() const;
103 Node *_parent; // the handle's lifetime does not extend beyond that of the parent node,
104 // so a naked pointer is OK and allows setting it during Node's construction
106 bool _degenerate; // True if the handle is retracted, i.e. has zero length. This is used often internally so it makes sense to cache this
107
116 static double _saved_length;
117 static bool _drag_out;
118 friend class Node;
119};
120
121class Node
122 : ListNode
124{
125public:
131 Node(NodeSharedData const &data, Geom::Point const &pos);
132
133 Node(Node const &) = delete;
134
135 void move(Geom::Point const &p) override;
136 void transform(Geom::Affine const &m) override;
137 void fixNeighbors() override;
138 Geom::Rect bounds() const override;
139
140 NodeType type() const { return _type; }
141
150 void setType(NodeType type, bool update_handles = true);
151
152 void showHandles(bool v);
153
154 void updateHandles();
155
160 void pickBestType(); // automatically determine the type from handle positions
161
162 bool isDegenerate() const { return _front.isDegenerate() && _back.isDegenerate(); }
163 bool isEndNode() const;
164 Handle *front() { return &_front; }
165 Handle *back() { return &_back; }
166
172
178
184
190
191 NodeList &nodeList() { return *(static_cast<ListNode*>(this)->ln_list); }
192 NodeList &nodeList() const { return *(static_cast<ListNode const*>(this)->ln_list); }
193
198 void sink();
199
200 static NodeType parse_nodetype(char x);
201 static char const *node_type_to_localized_string(NodeType type);
202
203 // temporarily public
205 bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, CanvasEvent const &event) override;
206
208
209protected:
210 void dragged(Geom::Point &new_pos, MotionEvent const &event) override;
211 bool grabbed(MotionEvent const &event) override;
212 bool clicked(ButtonReleaseEvent const &event) override;
213
214 void _setState(State state) override;
215 Glib::ustring _getTip(unsigned state) const override;
216 Glib::ustring _getDragTip(MotionEvent const &event) const override;
217 bool _hasDragTips() const override { return true; }
218
219private:
220 void _updateAutoHandles();
221
226 void _linearGrow(int dir);
227
228 Node *_next();
229 Node const *_next() const;
230 Node *_prev();
231 Node const *_prev() const;
234 inline PathManipulator &_pm();
235 inline PathManipulator &_pm() const;
236
238 static bool _is_line_segment(Node *first, Node *second);
239
240 // Handles are always present, but are not visible if they coincide with the node
241 // (are degenerate). A segment that has both handles degenerate is always treated
242 // as a line segment
247
248 // This is used by fixNeighbors to repair smooth nodes after all move
249 // operations have been completed. If this is empty, no fixing is needed.
250 std::optional<Geom::Point> _unfixed_pos;
251
252 friend class Handle;
253 friend class NodeList;
254 friend class NodeIterator<Node>;
255 friend class NodeIterator<Node const>;
256};
257
259
284template <typename N>
286 : public boost::bidirectional_iterator_helper<NodeIterator<N>, N, std::ptrdiff_t, N*, N&>
287{
288public:
291 : _node(nullptr)
292 {}
293 // default copy, default assign
294
296 _node = (_node?_node->ln_next:nullptr);
297 return *this;
298 }
300 _node = (_node?_node->ln_prev:nullptr);
301 return *this;
302 }
303 bool operator==(self const &other) const { return _node == other._node; }
304 N &operator*() const { return *static_cast<N*>(_node); }
305 inline operator bool() const; // define after NodeList
307 N *get_pointer() const { return static_cast<N*>(_node); }
309 N *ptr() const { return static_cast<N*>(_node); }
310
311 self next() const {
312 self r(*this);
313 r.advance();
314 return r;
315 }
316 self prev() const {
317 self r(*this);
318 r.retreat();
319 return r;
320 }
323
324private:
326 : _node(const_cast<ListNode*>(n))
327 {}
329 friend class NodeList;
330};
331
333 : ListNode
334 , boost::noncopyable
335{
336public:
337 using size_type = std::size_t;
338 using reference = Node &;
339 using const_reference = Node const &;
340 using pointer = Node *;
341 using const_pointer = Node const *;
345
346 // TODO Lame. Make this private and make SubpathList a factory
355 ~NodeList();
356
357 // iterators
359 iterator end() { return iterator(this); }
361 const_iterator end() const { return const_iterator(this); }
362
363 // size
364 bool empty() const;
365 size_type size() const;
366
367 // extra node-specific methods
368 bool closed() const { return _closed; }
369
374 bool degenerate() const;
375
376 void setClosed(bool c) { _closed = c; }
377 iterator before(double t, double *fracpart = nullptr);
378 iterator before(Geom::PathTime const &pvp);
379 const_iterator before(double t, double *fracpart = nullptr) const {
380 return const_cast<NodeList *>(this)->before(t, fracpart)._node;
381 }
383 return const_cast<NodeList *>(this)->before(pvp)._node;
384 }
385
386 // list operations
387
389 iterator insert(iterator pos, Node *x);
390
391 template <class InputIterator>
392 void insert(iterator pos, InputIterator first, InputIterator last) {
393 for (; first != last; ++first) insert(pos, *first);
394 }
395 void splice(iterator pos, NodeList &list);
396 void splice(iterator pos, NodeList &list, iterator i);
397 void splice(iterator pos, NodeList &list, iterator first, iterator last);
398 void reverse();
399 void shift(int n);
400 void push_front(Node *x) { insert(begin(), x); }
401 void pop_front() { erase(begin()); }
402 void push_back(Node *x) { insert(end(), x); }
403 void pop_back() { erase(--end()); }
404 void clear();
407 NodeList::iterator ret = first;
408 while (first != last) ret = erase(first++);
409 return ret;
410 }
411
412 // member access - undefined results when the list is empty
413 Node &front() { return *static_cast<Node*>(ln_next); }
414 Node &back() { return *static_cast<Node*>(ln_prev); }
415
416 // HACK remove this subpath from its path. This will be removed later.
417 void kill();
418
419 SubpathList const &subpathList() const { return _list; }
421
422 static iterator get_iterator(Node *n) { return iterator(n); }
423 static const_iterator get_iterator(Node const *n) { return const_iterator(n); }
424 static NodeList &get(Node *n);
425 static NodeList &get(iterator const &i);
426
427private:
429 bool _closed = false;
430
431 friend class Node;
432 friend class Handle; // required to access handle and handle line groups
433 friend class NodeIterator<Node>;
434 friend class NodeIterator<Node const>;
435};
436
441class SubpathList : public std::list<std::shared_ptr<NodeList>>
442{
443public:
444 using list_type = std::list<std::shared_ptr<NodeList>>;
445
447
448 PathManipulator const &pm() const { return _path_manipulator; }
450
451private:
454 friend class NodeList;
455 friend class Node;
456 friend class Handle;
457};
458
459// define inline Handle funcs after definition of Node
461 return position() - _parent->position();
462}
463inline void Handle::setRelativePos(Geom::Point const &p) {
465}
466inline double Handle::length() const {
467 return relativePos().length();
468}
470 return _parent->_pm();
471}
473 return _parent->_pm();
474}
476 return nodeList().subpathList().pm();
477}
478
479inline PathManipulator &Node::_pm() const {
480 return nodeList().subpathList().pm();
481}
482
483// definitions for node iterator
484template <typename N>
486 return _node && static_cast<ListNode*>(_node->ln_list) != _node;
487}
488template <typename N>
490 ++(*this);
491 if (G_UNLIKELY(!*this) && _node->ln_list->closed()) ++(*this);
492 return *this;
493}
494template <typename N>
496 --(*this);
497 if (G_UNLIKELY(!*this) && _node->ln_list->closed()) --(*this);
498 return *this;
499}
500
501} // namespace UI
502} // namespace Inkscape
503
504#endif // INKSCAPE_UI_TOOL_NODE_H
505
506/*
507 Local Variables:
508 mode:c++
509 c-file-style:"stroustrup"
510 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
511 indent-tabs-mode:nil
512 fill-column:99
513 End:
514*/
515// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Cartesian point / 2D vector and related operations.
std::unique_ptr< T, CanvasItemUnlinkDeleter > CanvasItemPtr
Smart pointer used to hold CanvasItems, like std::unique_ptr.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Two-dimensional point that doubles as a vector.
Definition point.h:66
Coord length() const
Compute the distance from origin.
Definition point.h:118
Axis aligned, non-empty rectangle.
Definition rect.h:92
Class to store data for points which are snap candidates, either as a source or as a target.
Group of selected control points.
Draggable point, the workhorse of on-canvas editing.
Geom::Point const & position() const
Current position of the control point.
State
Enumeration representing the possible states of the control point, used to determine its appearance.
Geom::Point relativePos() const
Definition node.h:460
bool _hasDragTips() const override
Definition node.h:97
bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, CanvasEvent const &event) override
Definition node.cpp:353
bool clicked(ButtonReleaseEvent const &event) override
Called when the control point is clicked, at mouse button release.
Definition node.cpp:582
void _update_bspline_handles()
Definition node.cpp:195
void setDirection(Geom::Point const &from, Geom::Point const &to)
Definition node.cpp:323
void setRelativePos(Geom::Point const &p)
Definition node.h:463
static double _saved_length
Definition node.h:116
static Geom::Point _saved_dir
Definition node.h:115
Glib::ustring _getDragTip(MotionEvent const &event) const override
Definition node.cpp:732
static Geom::Point _saved_other_pos
Control point of a cubic Bezier curve in a path.
Definition node.h:114
bool isDegenerate() const
Definition node.h:68
virtual void handle_2button_press()
Definition node.cpp:428
bool grabbed(MotionEvent const &event) override
Called when the user moves the point beyond the drag tolerance with the first button held down.
Definition node.cpp:437
void ungrabbed(ButtonReleaseEvent const *event) override
Called when the control point finishes a drag.
Definition node.cpp:557
Handle * other()
Definition node.cpp:603
void dragged(Geom::Point &new_pos, MotionEvent const &event) override
Called while dragging, but before moving the knot to new position.
Definition node.cpp:446
void setVisible(bool) override
Set the visibility of the control point.
Definition node.cpp:188
static bool _drag_out
Definition node.h:117
void setLength(double len)
Definition node.cpp:310
Node * parent()
Definition node.h:79
PathManipulator & _pm()
Definition node.h:469
void setPosition(Geom::Point const &p) override
Relocate the control point without side effects.
Definition node.cpp:292
Glib::ustring _getTip(unsigned state) const override
Definition node.cpp:619
double length() const
Definition node.h:466
static char const * handle_type_to_localized_string(NodeType type)
See also: Node::node_type_to_localized_string(NodeType type)
Definition node.cpp:337
void move(Geom::Point const &p) override
Move the control point to new position with side effects.
Definition node.cpp:206
CanvasItemPtr< CanvasItemCurve > _handle_line
Definition node.h:105
Iterator for editable nodes.
Definition node.h:287
self prev() const
Definition node.h:316
N & operator*() const
Definition node.h:304
NodeIterator(ListNode const *n)
Definition node.h:325
N * get_pointer() const
Get a pointer to the underlying node. Equivalent to &*i.
Definition node.h:307
bool operator==(self const &other) const
Definition node.h:303
self next() const
Definition node.h:311
iterator begin()
Definition node.h:358
const_iterator before(Geom::PathTime const &pvp) const
Definition node.h:382
NodeIterator< value_type > iterator
Definition node.h:343
size_type size() const
Definition node.cpp:1754
static const_iterator get_iterator(Node const *n)
Definition node.h:423
Node const * const_pointer
Definition node.h:341
static NodeList & get(Node *n)
Definition node.cpp:1917
bool closed() const
Definition node.h:368
NodeIterator< value_type const > const_iterator
Definition node.h:344
const_iterator begin() const
Definition node.h:360
iterator erase(iterator first, iterator last)
Definition node.h:406
iterator insert(iterator pos, Node *x)
insert a node before pos.
Definition node.cpp:1785
friend class Node
Definition node.h:431
static iterator get_iterator(Node *n)
Definition node.h:422
void push_front(Node *x)
Definition node.h:400
bool degenerate() const
A subpath is degenerate if it has no segments - either one node in an open path or no nodes in a clos...
Definition node.cpp:1762
const_iterator before(double t, double *fracpart=nullptr) const
Definition node.h:379
std::size_t size_type
Definition node.h:337
SubpathList const & subpathList() const
Definition node.h:419
void shift(int n)
Definition node.cpp:1824
const_iterator end() const
Definition node.h:361
SubpathList & _list
Definition node.h:428
void insert(iterator pos, InputIterator first, InputIterator last)
Definition node.h:392
void splice(iterator pos, NodeList &list)
Definition node.cpp:1796
void push_back(Node *x)
Definition node.h:402
SubpathList & subpathList()
Definition node.h:420
Node const & const_reference
Definition node.h:339
iterator before(double t, double *fracpart=nullptr)
Definition node.cpp:1767
iterator end()
Definition node.h:359
bool empty() const
Definition node.cpp:1749
iterator erase(iterator pos)
Definition node.cpp:1892
void setClosed(bool c)
Definition node.h:376
Node * nodeAwayFrom(Handle *h)
Gets the node in the direction opposite to the given handle.
Definition node.cpp:1598
static NodeType parse_nodetype(char x)
Definition node.cpp:1155
Node * _prev()
Definition node.cpp:784
Node * nodeToward(Handle *h)
Gets the node in the direction of the given handle.
Definition node.cpp:1574
Handle * handleAwayFrom(Node *to)
Gets the handle that goes in the direction opposite to the given adjacent node.
Definition node.cpp:1586
Glib::ustring _getTip(unsigned state) const override
Definition node.cpp:1610
void fixNeighbors() override
Affine transforms keep handle invariants for smooth and symmetric nodes, but smooth nodes at ends of ...
Definition node.cpp:887
Glib::ustring _getDragTip(MotionEvent const &event) const override
Definition node.cpp:1694
void _linearGrow(int dir)
Select or deselect a node in this node's subpath based on its path distance from this node.
Definition node.cpp:1213
void move(Geom::Point const &p) override
Move the control point to new position with side effects.
Definition node.cpp:794
Geom::Rect bounds() const override
Definition node.cpp:872
bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, CanvasEvent const &event) override
Customized event handler to catch scroll events needed for selection grow/shrink.
Definition node.cpp:1171
Handle * front()
Definition node.h:164
Node * _next()
Definition node.cpp:769
bool clicked(ButtonReleaseEvent const &event) override
Called when the control point is clicked, at mouse button release.
Definition node.cpp:1535
void setType(NodeType type, bool update_handles=true)
Sets the node type and optionally restores the invariants associated with the given type.
Definition node.cpp:982
static bool _is_line_segment(Node *first, Node *second)
Determine whether two nodes are joined by a linear segment.
Definition node.cpp:1725
Node(Node const &)=delete
bool isDegenerate() const
Definition node.h:162
std::optional< Geom::Point > _unfixed_pos
Definition node.h:250
bool grabbed(MotionEvent const &event) override
Called when the user moves the point beyond the drag tolerance with the first button held down.
Definition node.cpp:1361
void dragged(Geom::Point &new_pos, MotionEvent const &event) override
Called while dragging, but before moving the knot to new position.
Definition node.cpp:1403
Handle _front
Node handle in the backward direction of the path.
Definition node.h:243
void sink()
Move the node to the bottom of its canvas group.
Definition node.cpp:1150
static char const * node_type_to_localized_string(NodeType type)
See also: Handle::handle_type_to_localized_string(NodeType type)
Definition node.cpp:1709
Handle _back
Node handle in the forward direction of the path.
Definition node.h:244
void pickBestType()
Pick the best type for this node, based on the position of its handles.
Definition node.cpp:1103
Handle * back()
Definition node.h:165
void showHandles(bool v)
Definition node.cpp:963
NodeType _type
Type of node - cusp, smooth...
Definition node.h:245
void _updateAutoHandles()
Definition node.cpp:934
Inkscape::SnapTargetType _snapTargetType() const
Definition node.cpp:1550
void transform(Geom::Affine const &m) override
Apply an arbitrary affine transformation to a control point.
Definition node.cpp:835
PathManipulator & _pm()
Definition node.h:475
bool _hasDragTips() const override
Definition node.h:217
NodeList & nodeList()
Definition node.h:191
NodeType type() const
Definition node.h:140
bool _handles_shown
Definition node.h:246
Handle * handleToward(Node *to)
Gets the handle that faces the given adjacent node.
Definition node.cpp:1562
bool isEndNode() const
Definition node.cpp:1145
void _setState(State state) override
Change the state of the knot.
Definition node.cpp:1341
void updateHandles()
Definition node.cpp:974
NodeList & nodeList() const
Definition node.h:192
Inkscape::SnapCandidatePoint snapCandidatePoint()
Definition node.cpp:1557
Inkscape::SnapSourceType _snapSourceType() const
Definition node.cpp:1543
Manipulator that edits a single path using nodes with handles.
Desktop-bound selectable control object.
List of node lists.
Definition node.h:442
SubpathList(PathManipulator &pm)
Definition node.h:446
std::list< std::shared_ptr< NodeList > > list_type
Definition node.h:444
PathManipulator & _path_manipulator
Definition node.h:453
PathManipulator const & pm() const
Definition node.h:448
PathManipulator & pm()
Definition node.h:449
Base class for Event processors.
Definition tool-base.h:107
To do: update description of desktop.
Definition desktop.h:149
double c[8][4]
std::ostream & operator<<(std::ostream &os, const Bezier &b)
Definition bezier.h:372
NodeType
Types of nodes supported in the node tool.
Definition node-types.h:20
Helper class to stream background task notifications as a series of messages.
SnapSourceType
enumerations of snap source types and snap target types.
Definition snap-enums.h:18
Node types and other small enums.
auto len
Definition safe-printf.h:21
Some utility classes to store various kinds of snap candidates.
size_t N
NodeType
static const Point data[]
Generalized time value in the path.
Definition path.h:139
A mouse button (left/right/middle) is released.
Abstract base class for events.
Movement of the mouse pointer.
ListNode * ln_prev
Definition node.h:48
NodeList * ln_list
Definition node.h:49
ListNode * ln_next
Definition node.h:47
Inkscape::CanvasItemGroup * node_group
Definition node.h:56
Inkscape::CanvasItemGroup * handle_group
Definition node.h:57
Inkscape::CanvasItemGroup * handle_line_group
Definition node.h:58
ControlPointSelection * selection
Definition node.h:55