Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
knot-holder-entity.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * KnotHolderEntity definition.
4 *
5 * Authors:
6 * Mitsuru Oka <oka326@parkcity.ne.jp>
7 * Maximilian Albert <maximilian.albert@gmail.com>
8 * Abhishek Sharma
9 *
10 * Copyright (C) 1999-2001 Lauris Kaplinski
11 * Copyright (C) 2000-2001 Ximian, Inc.
12 * Copyright (C) 2001 Mitsuru Oka
13 * Copyright (C) 2004 Monash University
14 * Copyright (C) 2008 Maximilian Albert
15 *
16 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
17 */
18
19#include "knot-holder-entity.h"
20
21#include <glibmm/i18n.h>
22
23#include "desktop.h"
25#include "knot-holder.h"
26#include "live_effects/effect.h"
27#include "object/sp-hatch.h"
28#include "object/sp-item.h"
29#include "object/sp-namedview.h"
30#include "object/sp-pattern.h"
32#include "preferences.h"
33#include "snap.h"
34#include "style.h"
35
38 Glib::ustring const &name,
39 char const *tip, uint32_t color)
40{
41 if (!desktop) {
42 desktop = parent->getDesktop();
43 }
44
45 g_assert(item == parent->getItem());
46 g_assert(desktop && desktop == parent->getDesktop());
47 g_assert(!knot);
48
50 this->item = item; // TODO: remove the item either from here or from knotholder.cpp
51 this->desktop = desktop;
52
53 knot = new SPKnot(desktop, tip, type, name);
54 on_created();
56 knot->show();
57
62}
63
65{
66 if (knot) {
67 // unref should call destroy
69 } else {
70 // FIXME: This shouldn't occur. Perhaps it is caused by LPE PointParams being knotholder entities, too
71 // If so, it will likely be fixed with upcoming refactoring efforts.
72 }
73}
74
76{
77 if (auto const knot_pos = knot_get(); knot_pos.isFinite()) {
78 auto const dp = knot_pos * parent_holder->getEditTransform() * item->i2dt_affine();
79 _moved_connection.block();
81 _moved_connection.unblock();
82 } else {
83 // knot coords are non-finite, hide knot
84 knot->hide();
85 }
86}
87
89{
90 if (state & GDK_SHIFT_MASK) { // Don't snap when shift-key is held
91 return p;
92 }
93
94 auto const i2dt = parent_holder->getEditTransform() * item->i2dt_affine();
95 Geom::Point s = p * i2dt;
96
97 if (!desktop) {
98 std::cerr << "No desktop" << std::endl;
99 return {};
100 } else if (!desktop->getNamedView()) {
101 std::cerr << "No named view" << std::endl;
102 return {};
103 }
104
105 auto &m = desktop->getNamedView()->snap_manager;
106 m.setup(desktop, true, item);
107 m.freeSnapReturnByRef(s, Inkscape::SNAPSOURCE_NODE_HANDLE);
108 m.unSetup();
109
110 return s * i2dt.inverse();
111}
112
114{
115 if (state & GDK_SHIFT_MASK) { // Don't snap when shift-key is held
116 return p;
117 }
118
119 auto const i2d = parent_holder->getEditTransform() * item->i2dt_affine();
120 Geom::Point s = p * i2d;
121
122 auto &m = desktop->getNamedView()->snap_manager;
123 m.setup(desktop, true, item);
124
125 // constrainedSnap() will first project the point p onto the constraint line and then try to snap along that line.
126 // This way the constraint is already enforced, no need to worry about that later on
127 Inkscape::Snapper::SnapConstraint transformed_constraint = Inkscape::Snapper::SnapConstraint(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d);
128 m.constrainedSnapReturnByRef(s, Inkscape::SNAPSOURCE_NODE_HANDLE, transformed_constraint);
129 m.unSetup();
130
131 return s * i2d.inverse();
132}
133
134// LPEs
135
137{
138 if (_effect) {
139 _effect->makeUndoDone(_("Move handle"));
140 }
141}
142
143// Pattern manipulation
144
146{
147 // Setup an initial pattern transformation in the center
148 if (auto rect = item->documentGeometricBounds()) {
149 _cell = offset_to_cell(rect->midpoint());
150 }
151}
152
156Geom::Point PatternKnotHolderEntity::_get_pos(double x, double y, bool transform) const
157{
158 auto pat = _pattern();
159 auto pt = (_cell + Geom::Point(x, y)) * Geom::Point(pat->width(), pat->height());
160 return transform ? pt * pat->getTransform() : pt;
161}
162
164{
165 _cell = offset_to_cell(loc);
166 update_knot();
167 return true;
168}
169
174
176{
177 auto pat = _pattern();
178
179 // 1. Turn the location into the pattern grid coordinate
180 auto scale = Geom::Scale(pat->width(), pat->height());
181 auto d2i = item->i2doc_affine().inverse();
182 auto i2p = pat->getTransform().inverse();
183
184 // Get grid index of nearest pattern repetition.
185 return (loc * d2i * i2p * scale.inverse()).floor();
186}
187
188
193
195{
196 return !_pattern();
197}
198
199// Pattern X/Y knot
200
202{
204 // TODO: Move to constructor when desktop is generally available
205 _quad = make_canvasitem<Inkscape::CanvasItemQuad>(desktop->getCanvasControls());
206 _quad->lower_to_bottom();
207 _quad->set_fill(0x00000000);
208 _quad->set_stroke(0x808080ff);
209 _quad->set_inverted(true);
210 _quad->set_visible(false);
211}
212
214{
216 auto tr = item->i2dt_affine();
217 _quad->set_coords(_get_pos(0, 0) * tr, _get_pos(0, 1) * tr,
218 _get_pos(1, 1) * tr, _get_pos(1, 0) * tr);
219 _quad->set_visible(true);
220}
221
223{
224 return _get_pos(0, 0);
225}
226
228{
229 auto p_snapped = snap_knot_position(p, state);
230
231 if (state & GDK_CONTROL_MASK) {
232 if (std::abs((p - origin).x()) > std::abs((p - origin).y())) {
233 p_snapped.y() = origin.y();
234 } else {
235 p_snapped.x() = origin.x();
236 }
237 }
238
239 if (state) {
240 auto const q = p_snapped - knot_get();
242 }
243
244 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
245}
246
247// Pattern Angle knot
248
250{
251 return _get_pos(1.0, 0);
252}
253
254void PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned state)
255{
256 auto prefs = Inkscape::Preferences::get();
257 int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
258
259 // get the angle from pattern 0,0 to the cursor pos
260 Geom::Point transform_origin = _get_pos(0, 0);
261 double theta = atan2(p - transform_origin);
262 double theta_old = atan2(knot_get() - transform_origin);
263
264 if (state & GDK_CONTROL_MASK) {
265 // Snap theta
266 double snaps_radian = M_PI / snaps;
267 theta = std::round(theta / snaps_radian) * snaps_radian;
268 }
269
270 Geom::Affine rot = Geom::Translate(-transform_origin)
271 * Geom::Rotate(theta - theta_old)
272 * Geom::Translate(transform_origin);
274 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
275}
276
277// Pattern scale knot
278
280{
281 return _get_pos(1.0, 1.0);
282}
283
286{
288 _cached_origin = _get_pos(0, 0);
291
292 if (auto bounding_box = item->documentVisualBounds()) {
293 // Compare the areas of the pattern and the item to find the number of repetitions.
294 double const pattern_area = std::abs(_cached_diagonal[Geom::X] * _cached_diagonal[Geom::Y]);
295 double const item_area = bounding_box->area() * _cached_inverse_linear.descrim2() /
296 (item->i2doc_affine().descrim2() ? 1.0 : 1e-3);
297 _cached_min_scale = std::sqrt(item_area / (pattern_area * MAX_REPETITIONS));
298 } else {
299 _cached_min_scale = 1e-6;
300 }
301}
302
304{
305 using namespace Geom;
306 // FIXME: this snapping should be done together with knowing whether control was pressed.
307 // If GDK_CONTROL_MASK, then constrained snapping should be used.
308 Point p_snapped = snap_knot_position(p, state);
309
310 Point const new_extent = (p_snapped - _cached_origin) * _cached_inverse_linear;
311
312 // 1. Calculate absolute scale factor first
313 double scale_x = std::clamp(new_extent[X] / _cached_diagonal[X], _cached_min_scale, 1e9);
314 double scale_y = std::clamp(new_extent[Y] / _cached_diagonal[Y], _cached_min_scale, 1e9);
315
316 Affine new_transform = (state & GDK_CONTROL_MASK) ? Scale((scale_x + scale_y) * 0.5)
317 : Scale(scale_x, scale_y);
318
319 // 2. Calculate offset to keep pattern origin aligned
320 new_transform *= _cached_transform;
321 auto const new_uncompensated_origin = _get_pos(0, 0, false) * new_transform;
322 new_transform *= Translate(_cached_origin - new_uncompensated_origin);
323
324 item->adjust_pattern(new_transform, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
325 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
326}
327
328// Hatch manipulation
329
331{
332 return !_hatch();
333}
334
339
340static Geom::Point sp_hatch_knot_get(SPHatch const *hatch, double x, double y)
341{
342 return Geom::Point(x, y) * hatch->hatchTransform();
343}
344
349
351{
352 auto hatch = _hatch();
353 return sp_hatch_knot_get(hatch, hatch->pitch(), 0);
354}
355
357{
358 auto hatch = _hatch();
359 auto pitch = hatch->pitch();
360 return sp_hatch_knot_get(hatch, pitch, pitch);
361}
362
364{
365 auto p_snapped = snap_knot_position(p, state);
366
367 if (state & GDK_CONTROL_MASK) {
368 if (std::abs((p - origin).x()) > std::abs((p - origin).y())) {
369 p_snapped.y() = origin.y();
370 } else {
371 p_snapped.x() = origin.x();
372 }
373 }
374
375 if (state) {
376 auto const q = p_snapped - knot_get();
378 }
379
380 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
381}
382
384{
386 int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
387
388 SPHatch *hatch = _hatch();
389
390 // get the angle from hatch 0,0 to the cursor pos
391 auto const transform_origin = sp_hatch_knot_get(hatch, 0, 0);
392 double theta = atan2(p - transform_origin);
393 double theta_old = atan2(knot_get() - transform_origin);
394
395 if (state & GDK_CONTROL_MASK) {
396 // Snap theta
397 double snaps_radian = M_PI / snaps;
398 theta = std::round(theta / snaps_radian) * snaps_radian;
399 }
400
401 Geom::Affine rot =
402 Geom::Translate(-transform_origin) * Geom::Rotate(theta - theta_old) * Geom::Translate(transform_origin);
404 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
405}
406
408{
409 SPHatch *hatch = _hatch();
410
411 // FIXME: this snapping should be done together with knowing whether control was pressed.
412 // If GDK_CONTROL_MASK, then constrained snapping should be used.
413 Geom::Point p_snapped = snap_knot_position(p, state);
414
415 // Get the new scale from the position of the knotholder
416 Geom::Affine transform = hatch->hatchTransform();
417 Geom::Affine transform_inverse = transform.inverse();
418 Geom::Point d = p_snapped * transform_inverse;
419 Geom::Point d_origin = origin * transform_inverse;
420 Geom::Point origin_dt;
421 double hatch_pitch = hatch->pitch();
422 if (state & GDK_CONTROL_MASK) {
423 // if ctrl is pressed: use 1:1 scaling
424 d = d_origin * (d.length() / d_origin.length());
425 }
426
427 Geom::Affine scale = Geom::Translate(-origin_dt) * Geom::Scale(d.x() / hatch_pitch, d.y() / hatch_pitch) *
428 Geom::Translate(origin_dt) * transform;
429
431 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
432}
433
434// Filter manipulation
435
437{
438 // FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
439 Geom::Point p_snapped = snap_knot_position(p, state);
440
441 if (state & GDK_CONTROL_MASK) {
442 if (std::abs((p - origin).x()) > std::abs((p - origin).y())) {
443 p_snapped.y() = origin.y();
444 } else {
445 p_snapped.x() = origin.x();
446 }
447 }
448
449 if (state) {
450 auto filter = item->style ? item->style->getFilter() : nullptr;
451 if (!filter) {
452 return;
453 }
454
455 auto const orig_bbox = item->visualBounds();
456 auto const new_bbox = _topleft ? Geom::Rect(p, orig_bbox->max()) : Geom::Rect(orig_bbox->min(), p);
457
458 if (!filter->width._set) {
459 filter->width.set(SVGLength::PERCENT, 1.2);
460 }
461 if (!filter->height._set) {
462 filter->height.set(SVGLength::PERCENT, 1.2);
463 }
464 if (!filter->x._set) {
465 filter->x.set(SVGLength::PERCENT, -0.1);
466 }
467 if (!filter->y._set) {
468 filter->y.set(SVGLength::PERCENT, -0.1);
469 }
470
471 if (_topleft) {
472 float x_a = filter->width.computed;
473 float y_a = filter->height.computed;
474 filter->height.scale(new_bbox.height() / orig_bbox->height());
475 filter->width.scale(new_bbox.width() / orig_bbox->width());
476 float x_b = filter->width.computed;
477 float y_b = filter->height.computed;
478 filter->x.set(filter->x.unit, filter->x.computed + x_a - x_b);
479 filter->y.set(filter->y.unit, filter->y.computed + y_a - y_b);
480 } else {
481 filter->height.scale(new_bbox.height() / orig_bbox->height());
482 filter->width.scale(new_bbox.width() / orig_bbox->width());
483 }
484 filter->auto_region = false;
485 filter->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
486 }
487
488 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
489}
490
492{
493 auto filter = item->style ? item->style->getFilter() : nullptr;
494 if (!filter) {
496 }
497 auto r = item->visualBounds();
498 return _topleft ? r->min() : r->max();
499}
500
501// Blur manipulation
502
504{
506 // TODO: Move to constructor when desktop is generally available
507
508 _line = make_canvasitem<Inkscape::CanvasItemCurve>(desktop->getCanvasControls());
509 _line->set_z_position(0);
510 _line->set_stroke(0x0033cccc);
511 _line->set_visible(false);
512
513 // This watcher makes sure that adding or removing a blur results in updated knots.
514 _watch_filter = item->style->signal_filter_changed.connect([this] (auto old_obj, auto obj) {
515 update_knot();
516 });
517}
518
520{
521 if (auto blur = _blur()) {
522 knot->show();
523 // This watcher makes sure anything outside that modifies the blur changes the knot.
524 _watch_blur = blur->connectModified([this] (auto item, unsigned flags) {
526 });
527 } else {
528 knot->hide();
529 _watch_blur.disconnect();
530 _line->set_visible(false);
531 }
533}
534
535/* Return the first blur primitive of any applied filter. */
537{
538 if (auto filter = item->style->getFilter()) {
539 for (auto &primitive : filter->children) {
540 if (auto blur = cast<SPGaussianBlur>(&primitive)) {
541 return blur;
542 }
543 }
544 }
545 return nullptr;
546}
547
549{
551 if (box.empty()) {
553 }
554 if (_dir == Geom::Y) {
555 return Geom::Point(box->midpoint()[Geom::X], box->top());
556 }
557 return Geom::Point(box->right(), box->midpoint()[Geom::Y]);
558}
559
561{
562 auto blur = _blur();
563 if (!blur)
564 return Geom::Point(0, 0);
565
566 // First let's find where the gradient is
567 auto tr = item->i2dt_affine();
568 auto dev = blur->get_std_deviation();
569
570 // Blur visibility is 2.4 times the deviation in that direction.
571 double x = dev.getNumber();
572 double y = dev.getOptNumber(true);
573
574 auto p0 = _pos();
575 auto p1 = p0 + Geom::Point(x * 2.4, 0);
576 if (_dir == Geom::Y) {
577 p1 = p0 - Geom::Point(0, y * 2.4);
578 }
579 _line->set_visible(true);
580 _line->set_coords(p0 * tr, p1 * tr);
581
582 return p1;
583}
584
585void BlurKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state)
586{
587 auto blur = _blur();
588 if (!blur)
589 return;
590
591 NumberOptNumber dev = blur->get_std_deviation();
592 auto dp = Geom::Point(dev.getNumber(), dev.getOptNumber(true));
593 auto val = std::max(0.0, (((p - _pos()) * Geom::Scale(1, -1))[_dir]) / 2.4);
594
595 if (state & GDK_CONTROL_MASK) {
596 if (state & GDK_SHIFT_MASK) {
597 dp[!_dir] *= val / dp[_dir];
598 } else {
599 dp[!_dir] = val;
600 }
601 }
602 dp[_dir] = val;
603
604 // When X is set to zero the Opt blur disapears
605 dev.setNumber(std::max(0.001, dp[Geom::X]));
606 dev.setOptNumber(std::max(0.0, dp[Geom::Y]));
607
608 blur->set_deviation(dev);
609}
610
611/*
612 Local Variables:
613 mode:c++
614 c-file-style:"stroustrup"
615 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
616 indent-tabs-mode:nil
617 fill-column:99
618 End:
619*/
620// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
pair< double, double > Point
Definition parser.cpp:7
double scale
Definition aa.cpp:228
Point origin
Definition aa.cpp:227
CanvasItemPtr< Inkscape::CanvasItemCurve > _line
sigc::scoped_connection _watch_blur
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
SPGaussianBlur * _blur() const
Geom::Point _pos() const
sigc::scoped_connection _watch_filter
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
bool _topleft
true for top left point, false for bottom right
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord descrim2() const
Calculate the square of the descriminant.
Definition affine.cpp:424
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
Affine withoutTranslation() const
Definition affine.h:169
Two-dimensional point with integer coordinates.
Definition int-point.h:57
Two-dimensional point that doubles as a vector.
Definition point.h:66
bool isFinite() const
Check whether both coordinates are finite.
Definition point.h:218
Coord length() const
Compute the distance from origin.
Definition point.h:118
constexpr Coord y() const noexcept
Definition point.h:106
constexpr Coord x() const noexcept
Definition point.h:104
Axis aligned, non-empty rectangle.
Definition rect.h:92
Rotation around the origin.
Definition transforms.h:187
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
bool knot_missing() const override
bool _fill
true if the entity tracks fill, false for stroke
void makeUndoDone(Glib::ustring message)
Definition effect.cpp:1521
Preference storage class.
Definition preferences.h:66
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
Geom::Point getDirection() const
Definition snapper.h:95
Geom::Point getPoint() const
Definition snapper.h:90
virtual void on_created()
sigc::scoped_connection _ungrabbed_connection
Geom::Point snap_knot_position(Geom::Point const &p, unsigned state)
sigc::scoped_connection _click_connection
sigc::scoped_connection _moved_connection
void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, Inkscape::CanvasItemCtrlType type=Inkscape::CANVAS_ITEM_CTRL_TYPE_DEFAULT, Glib::ustring const &name="unknown", char const *tip="", uint32_t color=0xffffff00)
KnotHolder * parent_holder
Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, unsigned state)
virtual void update_knot()
virtual Geom::Point knot_get() const =0
sigc::scoped_connection _mousedown_connection
void knot_mousedown_handler(SPKnot *knot, unsigned int state)
Geom::Affine getEditTransform() const
Definition knot-holder.h:73
void knot_moved_handler(SPKnot *knot, Geom::Point const &p, unsigned int state)
void knot_ungrabbed_handler(SPKnot *knot, unsigned int state)
void knot_clicked_handler(SPKnot *knot, unsigned int state)
void knot_ungrabbed(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Inkscape::LivePathEffect::Effect * _effect
float getOptNumber(bool or_num=false) const
float getNumber() const
void setOptNumber(float optnum)
void setNumber(float num)
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
Geom::Point knot_get() const override
void knot_grabbed(Geom::Point const &grab_pos, unsigned state) override
Store pattern geometry info when the scale knot is first grabbed.
static constexpr double MAX_REPETITIONS
Maximum number of pattern repetitons allowed in an item.
CanvasItemPtr< Inkscape::CanvasItemQuad > _quad
Extra visual element to show the pattern editing area.
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned state) override
bool _fill
true if the entity tracks fill, false for stroke
Geom::Point _get_pos(double x, double y, bool transform=true) const
Returns the position based on the pattern's origin, shifted by the percent x/y of its size.
bool knot_missing() const override
Geom::IntPoint offset_to_cell(Geom::Point loc) const
bool set_item_clickpos(Geom::Point loc) override
To do: update description of desktop.
Definition desktop.h:149
Inkscape::CanvasItemGroup * getCanvasControls() const
Definition desktop.h:196
SPNamedView * getNamedView() const
Definition desktop.h:191
Geom::Affine const & hatchTransform() const
Definition sp-hatch.cpp:413
gdouble pitch() const
Definition sp-hatch.cpp:447
Base class for visual SVG elements.
Definition sp-item.h:109
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Definition sp-item.cpp:1821
Geom::OptRect documentVisualBounds() const
Get item's visual bbox in document coordinate system.
Definition sp-item.cpp:1018
Geom::OptRect documentGeometricBounds() const
Get item's geometric bbox in document coordinate system.
Definition sp-item.cpp:1013
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const
Definition sp-item.cpp:915
void adjust_hatch(Geom::Affine const &postmul, bool set=false, PaintServerTransform=TRANSFORM_BOTH)
Definition sp-item.cpp:1403
void adjust_pattern(Geom::Affine const &postmul, bool set=false, PaintServerTransform=TRANSFORM_BOTH)
Definition sp-item.cpp:1380
@ VISUAL_BBOX
Definition sp-item.h:118
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
Definition sp-item.cpp:1816
Geom::OptRect visualBounds(Geom::Affine const &transform=Geom::identity(), bool wfilter=true, bool wclip=true, bool wmask=true) const
Get item's visual bounding box in this item's coordinate system.
Definition sp-item.cpp:925
Desktop-bound visual control object.
Definition knot.h:51
sigc::signal< void(SPKnot *, unsigned int)> ungrabbed_signal
Definition knot.h:97
sigc::signal< void(SPKnot *, Geom::Point const &, unsigned int)> moved_signal
Definition knot.h:98
sigc::signal< void(SPKnot *, unsigned int)> click_signal
Definition knot.h:93
void setPosition(Geom::Point const &p, unsigned int state)
Move knot to new position and emits "moved" signal.
Definition knot.cpp:342
sigc::signal< void(SPKnot *, unsigned int)> mousedown_signal
Definition knot.h:95
static void unref(SPKnot *knot)
Definition knot.cpp:47
void hide()
Hide knot on its canvas.
Definition knot.cpp:327
void show()
Show knot on its canvas.
Definition knot.cpp:322
SnapManager snap_manager
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
Geom::Affine const & getTransform() const
SPPaintServer * getFillPaintServer()
Definition style.h:339
SPFilter * getFilter()
Definition style.h:335
SPPaintServer * getStrokePaintServer()
Definition style.h:343
sigc::signal< void(SPObject *, SPObject *)> signal_filter_changed
Emitted when the filter changes, meaning it starts pointing to a different object.
Definition style.h:333
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.
Definition snap.cpp:663
Editable view implementation.
static char const *const parent
Definition dir-util.cpp:70
SVG Gaussian blur filter effect.
constexpr Coord infinity()
Get a value representing infinity.
Definition coord.h:88
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
SPItem * item
@ SP_KNOT_STATE_NORMAL
Definition knot-enums.h:20
static Geom::Point sp_hatch_knot_get(SPHatch const *hatch, double x, double y)
Various utility functions.
Definition affine.h:22
Affine identity()
Create an identity matrix.
Definition affine.h:210
@ SNAPSOURCE_NODE_HANDLE
Definition snap-enums.h:43
Singleton class to access the preferences file in a convenient way.
SVG <hatch> implementation.
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
@ TRANSFORM_STROKE
Definition sp-item.h:56
@ TRANSFORM_FILL
Definition sp-item.h:56
SVG <pattern> implementation.
SPStyle - a style object for SPItem objects.
SPDesktop * desktop
Glib::ustring name
Definition toolbars.cpp:55