1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
/** @file
* @brief Path handler in node edit mode
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
*
* This code is in public domain
*/
#ifndef SEEN_SP_NODEPATH_H
#define SEEN_SP_NODEPATH_H
#include "libnr/nr-path-code.h"
#include <glibmm/ustring.h>
#include <gdk/gdkevents.h>
#include <list>
#include <2geom/point.h>
#include <2geom/matrix.h>
#include <boost/optional.hpp>
struct SPCanvasItem;
class SPCurve;
struct SPItem;
class SPObject;
class SPDesktop;
class SPPath;
class SPKnot;
class LivePathEffectObject;
namespace Inkscape {
namespace XML {
class Node;
}
namespace LivePathEffect {
class Effect;
}
}
typedef std::map<Inkscape::LivePathEffect::Effect *, std::vector<SPCanvasItem *> > HelperPathList;
/**
* Radial objects are represented by an angle and a distance from
* 0,0. 0,0 is represented by a == big_num.
*/
class Radial{
public:
/** Radius */
double r;
/** Amplitude */
double a;
Radial() {}
// Radial(Geom::Point const &p); // Convert a point to radial coordinates
Radial(Radial &p) : r(p.r),a(p.a) {}
// operator Geom::Point() const;
/**
* Construct Radial from Geom::Point.
*/
Radial(Geom::Point const &p)
{
r = Geom::L2(p);
if (r > 0) {
a = Geom::atan2 (p);
} else {
a = HUGE_VAL; //undefined
}
}
/**
* Cast Radial to cartesian Geom::Point.
*/
operator Geom::Point() const
{
if (a == HUGE_VAL) {
return Geom::Point(0,0);
} else {
return r*Geom::Point(cos(a), sin(a));
}
}
};
class ShapeEditor;
namespace Inkscape {
namespace NodePath {
/**
* The entire nodepath, containing multiple subpaths
*/
class Path;
/**
* A subpath is a continuous chain of linked nodes
*/
class SubPath;
/**
* One side of a node, i.e. prev or next
*/
class NodeSide;
/**
* A node on a subpath
*/
class Node;
/**
* This is the lowest list item, a simple list of nodes.
*/
class SubPath {
public:
/** The parent of this subpath */
Path * nodepath;
/** Is this path closed (no endpoints) or not?*/
gboolean closed;
/** The nodes in this subpath. */
GList * nodes;
/** The first node of the subpath (does not imply open/closed)*/
Node * first;
/** The last node of the subpath */
Node * last;
};
/**
* What kind of node is this? This is the value for the node->type
* field. NodeType indicates the degree of continuity required for
* the node. I think that the corresponding integer indicates which
* derivate is connected. (Thus 2 means that the node is continuous
* to the second derivative, i.e. has matching endpoints and tangents)
*/
typedef enum {
/** A normal node */
NODE_NONE,
/** This node non-continuously joins two segments.*/
NODE_CUSP,
/** This node continuously joins two segments. */
NODE_SMOOTH,
/** This node has automatic handles. */
NODE_AUTO,
/** This node is symmetric. */
NODE_SYMM
} NodeType;
/**
* A NodeSide is a datarecord which may be on either side (n or p) of a node,
* which describes the segment going to the next node.
*/
class NodeSide{
public:
/** Pointer to the next node, */
Node * other;
/** Position */
Geom::Point pos;
/** Origin (while dragging) in radial notation */
Radial origin_radial;
/** Origin (while dragging) in x/y notation */
Geom::Point origin;
/** Knots are Inkscape's way of providing draggable points. This
* Knot is the point on the curve representing the control point in a
* bezier curve.*/
SPKnot * knot;
/** What kind of rendering? */
SPCanvasItem * line;
};
/**
* A node along a NodePath
*/
class Node {
public:
/** The parent subpath of this node */
SubPath * subpath;
/** Type is selected from NodeType.*/
guint type : 4;
/** Code refers to which ArtCode is used to represent the segment
* (which segment?).*/
guint code : 4;
/** Boolean. Am I currently selected or not? */
guint selected : 1;
/** */
Geom::Point pos;
/** */
Geom::Point origin;
/** Knots are Inkscape's way of providing draggable points. This
* Knot is the point on the curve representing the endpoint.*/
SPKnot * knot;
/** The NodeSide in the 'next' direction */
NodeSide n;
/** The NodeSide in the 'previous' direction */
NodeSide p;
/** The pointer to the nodeside which we are dragging out with Shift */
NodeSide *dragging_out;
/** Boolean. Am I being dragged? */
guint is_dragging : 1;
};
/**
* This is a collection of subpaths which contain nodes
*
* In the following data model. Nodepaths are made up of subpaths which
* are comprised of nodes.
*
* Nodes are linked thus:
* \verbatim
n other
node -----> nodeside ------> node \endverbatim
*/
class Path {
public:
/** Constructor should private, people should create new nodepaths using sp_nodepath_new
* But for some reason I cannot make sp_nodepath_new a friend :-(
*/
Path() {};
/** Destructor */
~Path();
/** Pointer to the current desktop, for reporting purposes */
SPDesktop * desktop;
/** The parent path of this nodepath */
SPObject * object;
/** The parent livepatheffect of this nodepath, if applicable */
SPItem * item;
/** The context which created this nodepath. Important if this nodepath is deleted */
ShapeEditor *shape_editor;
/** The subpaths which comprise this NodePath */
GList * subpaths;
/** A list of nodes which are currently selected */
GList * selected;
/** Transforms (userspace <---> virtual space? someone please describe )
njh: I'd be guessing that these are item <-> desktop transforms.*/
Geom::Matrix i2d, d2i;
/** The DOM node which describes this NodePath */
Inkscape::XML::Node *repr;
gchar *repr_key;
gchar *repr_nodetypes_key;
//STL compliant method to get the selected nodes
void selection(std::list<Node *> &l);
guint numSelected() {return (selected? g_list_length(selected) : 0);}
Geom::Point& singleSelectedCoords() {return (((Node *) selected->data)->pos);}
/// draw a "sketch" of the path by using these variables
SPCanvasItem *helper_path;
SPCurve *curve;
bool show_helperpath;
guint32 helperpath_rgba;
gdouble helperpath_width;
// the helperpaths provided by all LPEs (and their paramaters) of the current item
HelperPathList helper_path_vec;
/// true if we changed repr, to tell this change from an external one such as from undo, simplify, or another desktop
unsigned int local_change;
/// true if we're showing selected nodes' handles
bool show_handles;
/// true if the path cannot contain curves, just straight lines
bool straight_path;
/// active_node points to the node that is currently mouseovered (= NULL if
/// there isn't any); we also consider the node mouseovered if it is covered
/// by one of its handles and the latter is mouseovered
static Node *active_node;
/// Location of mouse pointer when we started dragging, needed for snapping
Geom::Point drag_origin_mouse;
};
} // namespace NodePath
} // namespace Inkscape
enum {
SCULPT_PROFILE_LINEAR,
SCULPT_PROFILE_BELL,
SCULPT_PROFILE_ELLIPTIC
};
// Do function documentation in nodepath.cpp
Inkscape::NodePath::Path * sp_nodepath_new (SPDesktop * desktop, SPObject *object, bool show_handles, const char * repr_key = NULL, SPItem *item = NULL);
void sp_nodepath_deselect (Inkscape::NodePath::Path *nodepath);
void sp_nodepath_select_all (Inkscape::NodePath::Path *nodepath, bool invert);
void sp_nodepath_select_all_from_subpath(Inkscape::NodePath::Path *nodepath, bool invert);
void sp_nodepath_select_next (Inkscape::NodePath::Path *nodepath);
void sp_nodepath_select_prev (Inkscape::NodePath::Path *nodepath);
void sp_nodepath_select_rect (Inkscape::NodePath::Path * nodepath, Geom::Rect const &b, gboolean incremental);
GList *save_nodepath_selection (Inkscape::NodePath::Path *nodepath);
void restore_nodepath_selection (Inkscape::NodePath::Path *nodepath, GList *r);
gboolean nodepath_repr_d_changed (Inkscape::NodePath::Path * np, const char *newd);
gboolean nodepath_repr_typestr_changed (Inkscape::NodePath::Path * np, const char *newtypestr);
gboolean node_key (GdkEvent * event);
void sp_nodepath_update_repr(Inkscape::NodePath::Path *np, const gchar *annotation);
void sp_nodepath_update_statusbar (Inkscape::NodePath::Path *nodepath);
void sp_nodepath_selected_align(Inkscape::NodePath::Path *nodepath, Geom::Dim2 axis);
void sp_nodepath_selected_distribute(Inkscape::NodePath::Path *nodepath, Geom::Dim2 axis);
void sp_nodepath_select_segment_near_point(Inkscape::NodePath::Path *nodepath, Geom::Point p, bool toggle);
void sp_nodepath_add_node_near_point(Inkscape::NodePath::Path *nodepath, Geom::Point p);
void sp_nodepath_curve_drag(Inkscape::NodePath::Path *nodepath, int node, double t, Geom::Point delta);
Inkscape::NodePath::Node * sp_nodepath_get_node_by_index(Inkscape::NodePath::Path *np, int index);
bool sp_node_side_is_line (Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeSide *side);
/* possibly private functions */
void sp_node_selected_add_node (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_break (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_duplicate (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_join (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_join_segment (Inkscape::NodePath::Path *nodepath);
void sp_node_delete_preserve (GList *nodes_to_delete);
void sp_node_selected_delete (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_delete_segment (Inkscape::NodePath::Path *nodepath);
void sp_node_selected_set_type (Inkscape::NodePath::Path *nodepath, Inkscape::NodePath::NodeType type);
void sp_node_selected_set_line_type (Inkscape::NodePath::Path *nodepath, NRPathcode code);
void sp_node_selected_move (Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy);
void sp_node_selected_move_screen (SPDesktop *desktop, Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy);
void sp_node_selected_move_absolute (Inkscape::NodePath::Path *nodepath, Geom::Coord val, Geom::Dim2 axis);
Geom::Rect sp_node_selected_bbox (Inkscape::NodePath::Path *nodepath);
boost::optional<Geom::Coord> sp_node_selected_common_coord (Inkscape::NodePath::Path *nodepath, Geom::Dim2 axis);
void sp_nodepath_show_handles(Inkscape::NodePath::Path *nodepath, bool show);
SPCanvasItem *sp_nodepath_generate_helperpath(SPDesktop *desktop, SPCurve *curve, const Geom::Matrix & i2d, guint32 color);
SPCanvasItem *sp_nodepath_generate_helperpath(SPDesktop *desktop, SPItem *item);
void sp_nodepath_show_helperpath(Inkscape::NodePath::Path *nodepath, bool show);
void sp_nodepath_update_helperpaths(Inkscape::NodePath::Path *np);
void sp_nodepath_make_straight_path(Inkscape::NodePath::Path *np);
void sp_nodepath_selected_nodes_rotate (Inkscape::NodePath::Path * nodepath, gdouble angle, int which, bool screen);
void sp_nodepath_selected_nodes_scale (Inkscape::NodePath::Path * nodepath, gdouble grow, int which);
void sp_nodepath_selected_nodes_scale_screen (Inkscape::NodePath::Path * nodepath, gdouble grow, int which);
void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, Geom::Dim2 axis, boost::optional<Geom::Point> center);
#endif
|