Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-hatch-path.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/*
7 * Author:
8 * Tomasz Boczkowski <penginsbacon@gmail.com>
9 * Jon A. Cruz <jon@joncruz.org>
10 *
11 * Copyright (C) 2014 Tomasz Boczkowski
12 *
13 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
14 */
15
16#include <string>
17#include <2geom/path.h>
18
19#include "style.h"
20#include "svg/svg.h"
21#include "display/curve.h"
22#include "display/drawing.h"
24#include "helper/geom.h"
25#include "attributes.h"
26#include "sp-item.h"
27#include "sp-hatch-path.h"
29
30SPHatchPath::SPHatchPath() = default;
31
33
44
46{
47 views.clear();
49}
50
51void SPHatchPath::set(SPAttr key, gchar const *value)
52{
53 switch (key) {
54 case SPAttr::D:
55 if (value) {
58 _curve.emplace(std::move(pv));
59 } else {
60 _curve.reset();
61 }
62
63 requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
64 break;
65
66 case SPAttr::OFFSET:
67 offset.readOrUnset(value);
68 requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
69 break;
70
71 default:
73 style->clear(key);
74 requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
75 } else {
76 SPObject::set(key, value);
77 }
78 break;
79 }
80}
81
82void SPHatchPath::update(SPCtx *ctx, unsigned int flags)
83{
84 if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
85 flags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B;
86 }
87
88 if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
90 //TODO: Check specification
91
92 SPItemCtx *ictx = static_cast<SPItemCtx *>(ctx);
93 double const aw = (ictx) ? 1.0 / ictx->i2vp.descrim() : 1.0;
94 style->stroke_width.computed = style->stroke_width.value * aw;
95
96 for (auto &v : views) {
97 v.drawingitem->setStyle(style);
98 }
99 }
100 }
101
102 if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
103 for (auto &v : views) {
104 _updateView(v);
105 }
106 }
107}
108
110{
111 return !_curve || _repeatLength() > 0;
112}
113
115{
116 views.emplace_back(make_drawingitem<Inkscape::DrawingShape>(drawing), extents, key);
117 auto &v = views.back();
118 auto s = v.drawingitem.get();
119
120 _updateView(v);
121
122 return s;
123}
124
125void SPHatchPath::hide(unsigned int key)
126{
127 auto it = std::find_if(views.begin(), views.end(), [=] (auto &v) {
128 return v.key == key;
129 });
130
131 if (it != views.end()) {
132 views.erase(it);
133 return;
134 }
135
136 g_assert_not_reached();
137}
138
139void SPHatchPath::setStripExtents(unsigned int key, Geom::OptInterval const &extents)
140{
141 for (auto &v : views) {
142 if (v.key == key) {
143 v.extents = extents;
144 break;
145 }
146 }
147}
148
150{
151 Geom::OptRect bbox;
153
155 if (!_curve) {
158 test_curve.moveto(Geom::Point(0, 1));
159 bbox = bounds_exact_transformed(test_curve.get_pathvector(), transform);
160 } else {
161 bbox = bounds_exact_transformed(_curve->get_pathvector(), transform);
162 }
163
164 double stroke_width = style->stroke_width.computed;
165 result.setMin(bbox->left() - stroke_width / 2);
166 result.setMax(bbox->right() + stroke_width / 2);
167 return result;
168}
169
171{
172 for (auto const &v : views) {
173 if (v.key == key) {
174 return _calculateRenderCurve(v);
175 }
176 }
177 g_assert_not_reached();
178 return SPCurve{};
179}
180
182{
183 gdouble val = 0;
184
185 if (_curve && _curve->last_point()) {
186 val = _curve->last_point()->y();
187 }
188
189 return val;
190}
191
193{
194 auto calculated_curve = _calculateRenderCurve(view);
195
196 Geom::Affine offset_transform = Geom::Translate(offset.computed, 0);
197 view.drawingitem->setTransform(offset_transform);
198 style->fill.setNone();
199 view.drawingitem->setStyle(style);
200 view.drawingitem->setPath(std::make_shared<SPCurve>(std::move(calculated_curve)));
201}
202
204{
205 SPCurve calculated_curve;
206
207 if (!view.extents) {
208 return calculated_curve;
209 }
210
211 if (!_curve) {
212 calculated_curve.moveto(0, view.extents->min());
213 calculated_curve.lineto(0, view.extents->max());
214 //TODO: if hatch has a dasharray defined, adjust line ends
215 } else {
216 gdouble repeatLength = _repeatLength();
217 if (repeatLength > 0) {
218 gdouble initial_y = floor(view.extents->min() / repeatLength) * repeatLength;
219 int segment_cnt = ceil((view.extents->extent()) / repeatLength) + 1;
220
221 auto segment = *_curve;
222 segment.transform(Geom::Translate(0, initial_y));
223
224 Geom::Affine step_transform = Geom::Translate(0, repeatLength);
225 for (int i = 0; i < segment_cnt; ++i) {
226 if (_continuous) {
227 calculated_curve.append_continuous(segment);
228 } else {
229 calculated_curve.append(segment);
230 }
231 segment.transform(step_transform);
232 }
233 }
234 }
235 return calculated_curve;
236}
237
238void SPHatchPath::_readHatchPathVector(char const *str, Geom::PathVector &pathv, bool &continous_join)
239{
240 if (!str) {
241 return;
242 }
243
244 pathv = sp_svg_read_pathv(str);
245
246 if (!pathv.empty()) {
247 continous_join = false;
248 } else {
249 Glib::ustring str2 = Glib::ustring::compose("M0,0 %1", str);
250 pathv = sp_svg_read_pathv(str2.c_str());
251 if (pathv.empty()) {
252 return;
253 }
254
255 gdouble last_point_x = pathv.back().finalPoint().x();
257 stream << last_point_x;
258 Glib::ustring str3 = Glib::ustring::compose("M%1,0 %2", stream.str(), str);
259 Geom::PathVector pathv3 = sp_svg_read_pathv(str3.c_str());
260
261 //Path can be composed of relative commands only. In this case final point
262 //coordinates would depend on first point position. If this happens, fall
263 //back to using 0,0 as first path point
264 if (pathv3.back().finalPoint().y() == pathv.back().finalPoint().y()) {
265 pathv = pathv3;
266 }
267 continous_join = true;
268 }
269}
270
272 : drawingitem(std::move(drawingitem))
273 , extents(extents)
274 , key(key) {}
275
276/*
277 Local Variables:
278 mode:c++
279 c-file-style:"stroustrup"
280 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
281 indent-tabs-mode:nil
282 fill-column:99
283 End:
284 */
285// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Path - a sequence of contiguous curves.
bool SP_ATTRIBUTE_IS_CSS(SPAttr k)
True iff k is a property in SVG, i.e.
Lookup dictionary for attributes/properties.
SPAttr
Definition attributes.h:27
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord descrim() const
Calculate the descriminant.
Definition affine.cpp:434
Range of real numbers that is never empty.
Definition interval.h:59
Range of real numbers that can be empty.
Definition interval.h:199
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Sequence of subpaths.
Definition pathvector.h:122
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Point finalPoint() const
Get the last point in the path.
Definition path.h:709
Two-dimensional point that doubles as a vector.
Definition point.h:66
constexpr Coord y() const noexcept
Definition point.h:106
constexpr Coord x() const noexcept
Definition point.h:104
Translation by a vector.
Definition transforms.h:115
A thin wrapper around std::ostringstream, but writing floating point numbers in the format required b...
SVG drawing item for display.
Interface for refcounted XML nodes.
Definition node.h:80
Wrapper around a Geom::PathVector object.
Definition curve.h:26
void append(Geom::PathVector const &, bool use_lineto=false)
Definition curve.cpp:434
void moveto(Geom::Point const &p)
Perform a moveto to a point, thus starting a new subpath.
Definition curve.cpp:138
void lineto(Geom::Point const &p)
Adds a line to the current subpath.
Definition curve.cpp:149
std::optional< Geom::Point > last_point() const
Return last point of last subpath or nothing when the curve is empty.
Definition curve.cpp:399
bool append_continuous(SPCurve const &c1, double tolerance=0.0625)
Append c1 to this with possible fusing of close endpoints.
Definition curve.cpp:468
Typed SVG document implementation.
Definition document.h:103
void release() override
std::optional< SPCurve > _curve
void set(SPAttr key, const gchar *value) override
SPCurve calculateRenderCurve(unsigned key) const
SVGLength offset
void _readHatchPathVector(char const *str, Geom::PathVector &pathv, bool &continous_join)
SPCurve _calculateRenderCurve(View const &view) const
void build(SPDocument *doc, Inkscape::XML::Node *repr) override
Inkscape::DrawingItem * show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptInterval extents)
gdouble _repeatLength() const
void setStripExtents(unsigned int key, Geom::OptInterval const &extents)
void update(SPCtx *ctx, unsigned int flags) override
void hide(unsigned int key)
void _updateView(View &view)
std::vector< View > views
Geom::Interval bounds() const
~SPHatchPath() override
bool isValid() const
Inkscape::XML::Node * repr
Definition sp-object.h:193
virtual void set(SPAttr key, const char *value)
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
virtual void release()
void readAttr(char const *key)
Read value of key attribute from XML node into object.
virtual void build(SPDocument *doc, Inkscape::XML::Node *repr)
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
void clear()
Definition style.cpp:505
T< SPAttr::FILL, SPIPaint > fill
fill
Definition style.h:240
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
Definition style.h:249
void readOrUnset(char const *str, Unit u=NONE, float v=0, float c=0)
float computed
Definition svg-length.h:50
TODO: insert short description here.
Css & result
std::unique_ptr< T, UnlinkDeleter > DrawingItemPtr
Smart pointer used by the Object Tree to hold items in the Display Tree, like std::unique_ptr.
Group belonging to an SVG drawing element.
SVG drawing for display.
Geom::OptRect bounds_exact_transformed(Geom::PathVector const &pv, Geom::Affine const &t)
Definition geom.cpp:153
Specific geometry functions for Inkscape, not provided my lib2geom.
auto floor(Geom::Rect const &rect)
Definition geom.h:130
STL namespace.
static cairo_user_data_key_t key
SVG <hatchPath> implementation.
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
int test_curve(void)
Definition spiro.cpp:1085
Unused.
Definition sp-object.h:94
DrawingItemPtr< Inkscape::DrawingShape > drawingitem
View(DrawingItemPtr< Inkscape::DrawingShape > drawingitem, Geom::OptInterval const &extents, unsigned key)
Geom::OptInterval extents
Contains transformations to document/viewport and the viewport size.
Definition sp-item.h:92
Geom::Affine i2vp
Item to viewport transformation.
Definition sp-item.h:100
@ SP_CSS_UNIT_PERCENT
SPStyle - a style object for SPItem objects.
Geom::PathVector sp_svg_read_pathv(char const *str)
Definition svg-path.cpp:37