1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3 * Path utilities.
4 *//*
5 * Authors:
6 * see git history
7 * Created by fred on Fri Dec 05 2003.
8 * tweaked endlessly by bulia byak <buliabyak@users.sf.net>
9 *
10 * Copyright (C) 2018 Authors
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14 #ifdef HAVE_CONFIG_H
15 #endif
16
17 #include <vector>
18
19 #include "path-util.h"
20
21 #include "text-editing.h"
22
23 #include "livarot/Path.h"
24 #include "livarot/Shape.h"
25
26 #include "object/sp-flowtext.h"
27 #include "object/sp-image.h"
28 #include "object/sp-marker.h"
29 #include "object/sp-path.h"
30 #include "object/sp-text.h"
31
32 #include "display/curve.h"
33
34 // derived from Path_for_item
35 Path *
Path_for_pathvector(Geom::PathVector const & epathv)36 Path_for_pathvector(Geom::PathVector const &epathv)
37 {
38 /*std::cout << "converting to Livarot path" << std::endl;
39
40 Geom::SVGPathWriter wr;
41 wr.feed(epathv);
42 std::cout << wr.str() << std::endl;*/
43
44 Path *dest = new Path;
45 dest->LoadPathVector(epathv);
46 return dest;
47 }
48
49 Path *
Path_for_item(SPItem * item,bool doTransformation,bool transformFull)50 Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
51 {
52 std::unique_ptr<SPCurve> curve = curve_for_item(item);
53
54 if (curve == nullptr)
55 return nullptr;
56
57 Geom::PathVector *pathv =
58 pathvector_for_curve(item, curve.get(), doTransformation, transformFull, Geom::identity(), Geom::identity());
59
60 /*std::cout << "converting to Livarot path" << std::endl;
61
62 Geom::SVGPathWriter wr;
63 if (pathv) {
64 wr.feed(*pathv);
65 }
66 std::cout << wr.str() << std::endl;*/
67
68 Path *dest = new Path;
69 dest->LoadPathVector(*pathv);
70 delete pathv;
71
72 /*gchar *str = dest->svg_dump_path();
73 std::cout << "After conversion:\n" << str << std::endl;
74 g_free(str);*/
75
76 return dest;
77 }
78
79 /**
80 * Obtains an item's Path before the LPE stack has been applied.
81 */
82 Path *
Path_for_item_before_LPE(SPItem * item,bool doTransformation,bool transformFull)83 Path_for_item_before_LPE(SPItem *item, bool doTransformation, bool transformFull)
84 {
85 std::unique_ptr<SPCurve> curve = curve_for_item_before_LPE(item);
86
87 if (curve == nullptr)
88 return nullptr;
89
90 Geom::PathVector *pathv =
91 pathvector_for_curve(item, curve.get(), doTransformation, transformFull, Geom::identity(), Geom::identity());
92
93 Path *dest = new Path;
94 dest->LoadPathVector(*pathv);
95 delete pathv;
96
97 return dest;
98 }
99
100 /*
101 * NOTE: Returns empty pathvector if curve == NULL
102 * TODO: see if calling this method can be optimized. All the pathvector copying might be slow.
103 */
104 Geom::PathVector*
pathvector_for_curve(SPItem * item,SPCurve * curve,bool doTransformation,bool transformFull,Geom::Affine extraPreAffine,Geom::Affine extraPostAffine)105 pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Affine extraPreAffine, Geom::Affine extraPostAffine)
106 {
107 if (curve == nullptr)
108 return nullptr;
109
110 Geom::PathVector *dest = new Geom::PathVector;
111 *dest = curve->get_pathvector(); // Make a copy; must be freed by the caller!
112
113 if (doTransformation) {
114 if (transformFull) {
115 *dest *= extraPreAffine * item->i2doc_affine() * extraPostAffine;
116 } else {
117 *dest *= extraPreAffine * (Geom::Affine)item->transform * extraPostAffine;
118 }
119 } else {
120 *dest *= extraPreAffine * extraPostAffine;
121 }
122
123 return dest;
124 }
125
126 /**
127 * Obtains an item's curve. For SPPath, it is the path *before* LPE. For SPShapes other than path, it is the path *after* LPE.
128 * So the result is somewhat ill-defined, and probably this method should not be used... See curve_for_item_before_LPE.
129 */
curve_for_item(SPItem * item)130 std::unique_ptr<SPCurve> curve_for_item(SPItem *item)
131 {
132 if (!item)
133 return nullptr;
134
135 std::unique_ptr<SPCurve> curve;
136
137 if (auto path = dynamic_cast<SPPath const *>(item)) {
138 curve = SPCurve::copy(path->curveForEdit());
139 } else if (auto shape = dynamic_cast<SPShape const *>(item)) {
140 curve = SPCurve::copy(shape->curve());
141 } else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
142 curve = te_get_layout(item)->convertToCurves();
143 } else if (auto image = dynamic_cast<SPImage const *>(item)) {
144 curve = image->get_curve();
145 }
146
147 return curve;
148 }
149
150 /**
151 * Obtains an item's curve *before* LPE.
152 */
curve_for_item_before_LPE(SPItem * item)153 std::unique_ptr<SPCurve> curve_for_item_before_LPE(SPItem *item)
154 {
155 if (!item)
156 return nullptr;
157
158 std::unique_ptr<SPCurve> curve;
159
160 if (auto shape = dynamic_cast<SPShape const *>(item)) {
161 curve = SPCurve::copy(shape->curveForEdit());
162 } else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
163 curve = te_get_layout(item)->convertToCurves();
164 } else if (auto image = dynamic_cast<SPImage const *>(item)) {
165 curve = image->get_curve();
166 }
167
168 return curve;
169 }
170
get_nearest_position_on_Path(Path * path,Geom::Point p,unsigned seg)171 std::optional<Path::cut_position> get_nearest_position_on_Path(Path *path, Geom::Point p, unsigned seg)
172 {
173 //get nearest position on path
174 Path::cut_position pos = path->PointToCurvilignPosition(p, seg);
175 return pos;
176 }
177
get_point_on_Path(Path * path,int piece,double t)178 Geom::Point get_point_on_Path(Path *path, int piece, double t)
179 {
180 Geom::Point p;
181 path->PointAt(piece, t, p);
182 return p;
183 }
184
185
186 /*
187 Local Variables:
188 mode:c++
189 c-file-style:"stroustrup"
190 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
191 indent-tabs-mode:nil
192 fill-column:99
193 End:
194 */
195 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
196