Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
canvas-item-curve.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/*
7 * Author:
8 * Tavmjong Bah
9 *
10 * Copyright (C) 2020 Tavmjong Bah
11 *
12 * Rewrite of SPCtrlLine and SPCtrlCurve
13 *
14 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15 */
16
17#include <2geom/bezier-curve.h>
18
19#include "canvas-item-curve.h"
20
21#include "display/cairo-utils.h"
22#include "helper/geom.h"
23#include "ui/widget/canvas.h"
24
25namespace Inkscape {
26
31 : CanvasItem(group)
32{
33 _name = "CanvasItemCurve:Null";
34}
35
40 : CanvasItem(group)
41 , _curve(std::make_unique<Geom::LineSegment>(p0, p1))
42{
43 _name = "CanvasItemCurve:Line";
44}
45
50 Geom::Point const &p0, Geom::Point const &p1,
51 Geom::Point const &p2, Geom::Point const &p3)
52 : CanvasItem(group)
53 , _curve(std::make_unique<Geom::CubicBezier>(p0, p1, p2, p3))
54{
55 _name = "CanvasItemCurve:CubicBezier";
56}
57
62{
63 defer([=, this] {
64 _name = "CanvasItemCurve:Line";
65 _curve = std::make_unique<Geom::LineSegment>(p0, p1);
67 });
68}
69
73void CanvasItemCurve::set_coords(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3)
74{
75 defer([=, this] {
76 _name = "CanvasItemCurve:CubicBezier";
77 _curve = std::make_unique<Geom::CubicBezier>(p0, p1, p2, p3);
79 });
80}
81
86{
87 defer([=, this] {
88 if (_width == width) return;
89 _width = width;
91 });
92}
93
98{
99 defer([=, this] {
100 if (bg_alpha == alpha) return;
101 bg_alpha = alpha;
103 });
104}
105
110{
111 double d = Geom::infinity();
112 if (_curve) {
114 curve *= affine(); // Document to canvas.
115 Geom::Point n = curve.pointAt(curve.nearestTime(p));
116 d = Geom::distance(p, n);
117 }
118 return d;
119}
120
124bool CanvasItemCurve::contains(Geom::Point const &p, double tolerance)
125{
126 return closest_distance_to(p) <= tolerance;
127}
128
133{
134 // Queue redraw of old area (erase previous content).
135 request_redraw(); // This is actually never useful as curves are always deleted
136 // and recreated when a node is moved! But keep it in case we change that.
137
138 if (!_curve || _curve->isDegenerate()) {
139 _bounds = {};
140 return; // No curve! Can happen - see node.h.
141 }
142
143 // Tradeoff between updating a larger area (typically twice for Beziers?) vs computation time for bounds.
144 _bounds = expandedBy(_curve->boundsExact() * affine(), 2); // Room for stroke.
145
146 // Queue redraw of new area
148}
149
154{
155 assert(_curve); // Not called if _curve is null, since _bounds would be null.
156
157 // Todo: Transform, rather than copy.
159 curve *= affine(); // Document to canvas.
160 curve *= Geom::Translate(-buf.rect.min()); // Canvas to screen.
161
162 buf.cr->save();
163
164 buf.cr->begin_new_path();
165
166 if (curve.size() == 2) {
167 // Line
168 buf.cr->move_to(curve[0].x(), curve[0].y());
169 buf.cr->line_to(curve[1].x(), curve[1].y());
170 } else {
171 // Curve
172 buf.cr->move_to(curve[0].x(), curve[0].y());
173 buf.cr->curve_to(curve[1].x(), curve[1].y(), curve[2].x(), curve[2].y(), curve[3].x(), curve[3].y());
174 }
175
176 buf.cr->set_source_rgba(1.0, 1.0, 1.0, bg_alpha);
177 buf.cr->set_line_width(background_width);
178 buf.cr->stroke_preserve();
179
181 buf.cr->set_line_width(_width);
182 buf.cr->stroke();
183
184 // Uncomment to show bounds
185 // Geom::Rect bounds = _bounds;
186 // bounds.expandBy(-1);
187 // bounds -= buf.rect.min();
188 // buf.cr->set_source_rgba(1.0, 0.0, 0.0, 1.0);
189 // buf.cr->rectangle(bounds.min().x(), bounds.min().y(), bounds.width(), bounds.height());
190 // buf.cr->stroke();
191
192 buf.cr->restore();
193}
194
195} // namespace Inkscape
196
197/*
198 Local Variables:
199 mode:c++
200 c-file-style:"stroustrup"
201 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
202 indent-tabs-mode:nil
203 fill-column:99
204 End:
205*/
206// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Bezier curve.
void ink_cairo_set_source_color(Cairo::RefPtr< Cairo::Context > &ctx, Colors::Color const &color, bool to_srgb)
Set the source color of the Cairo context.
Cairo integration helpers.
Inkscape canvas widget.
Two-dimensional Bezier curve of arbitrary order.
Two-dimensional point that doubles as a vector.
Definition point.h:66
Translation by a vector.
Definition transforms.h:115
std::unique_ptr< Geom::BezierCurve > _curve
double closest_distance_to(Geom::Point const &p) const
Returns distance between point in canvas units and nearest point on curve.
void set_width(int width)
Set stroke width.
void _update(bool propagate) override
Update and redraw control curve.
void set_coords(Geom::Point const &p0, Geom::Point const &p1)
Set a linear control curve.
void _render(Inkscape::CanvasItemBuffer &buf) const override
Render curve to screen via Cairo.
bool contains(Geom::Point const &p, double tolerance=0) override
Returns true if point p (in canvas units) is within tolerance (canvas units) distance of curve.
CanvasItemCurve(CanvasItemGroup *group)
Create an null control curve.
void set_bg_alpha(float alpha)
Set background stroke alpha.
Geom::OptRect _bounds
Geom::Affine const & affine() const
constexpr Coord infinity()
Get a value representing infinity.
Definition coord.h:88
Specific geometry functions for Inkscape, not provided my lib2geom.
auto expandedBy(Geom::IntRect rect, int amount)
Definition geom.h:67
Various utility functions.
Definition affine.h:22
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
Helper class to stream background task notifications as a series of messages.
STL namespace.
int buf
Class used when rendering canvas items.
Definition curve.h:24
double width