Rev 18114 | Rev 19067 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
11006 | fschmid | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
7 | /*************************************************************************** |
||
8 | * Copyright (C) 2007 by Franz Schmid * |
||
9 | * franz.schmid@altmuehlnet.de * |
||
10 | * * |
||
11 | * This program is free software; you can redistribute it and/or modify * |
||
12 | * it under the terms of the GNU General Public License as published by * |
||
13 | * the Free Software Foundation; either version 2 of the License, or * |
||
14 | * (at your option) any later version. * |
||
15 | * * |
||
16 | * This program is distributed in the hope that it will be useful, * |
||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
||
19 | * GNU General Public License for more details. * |
||
20 | * * |
||
21 | * You should have received a copy of the GNU General Public License * |
||
22 | * along with this program; if not, write to the * |
||
23 | * Free Software Foundation, Inc., * |
||
18122 | mrdocs | 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
11006 | fschmid | 25 | ****************************************************************************/ |
26 | |||
17539 | jghali | 27 | #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) |
14170 | jghali | 28 | #define _USE_MATH_DEFINES |
29 | #endif |
||
30 | #include <cmath> |
||
11006 | fschmid | 31 | #include "pathstroker.h" |
12920 | fschmid | 32 | #include "pageitem_polygon.h" |
33 | #include "commonstrings.h" |
||
11006 | fschmid | 34 | #include "scribuscore.h" |
13805 | jghali | 35 | #include "scribusdoc.h" |
11027 | fschmid | 36 | #include "scribusstructs.h" |
13805 | jghali | 37 | #include "selection.h" |
11006 | fschmid | 38 | #include "util.h" |
39 | #include <QPainterPathStroker> |
||
40 | |||
41 | int pathstroker_getPluginAPIVersion() |
||
42 | { |
||
43 | return PLUGIN_API_VERSION; |
||
44 | } |
||
45 | |||
46 | ScPlugin* pathstroker_getPlugin() |
||
47 | { |
||
48 | PathStrokerPlugin* plug = new PathStrokerPlugin(); |
||
49 | Q_CHECK_PTR(plug); |
||
50 | return plug; |
||
51 | } |
||
52 | |||
53 | void pathstroker_freePlugin(ScPlugin* plugin) |
||
54 | { |
||
55 | PathStrokerPlugin* plug = dynamic_cast<PathStrokerPlugin*>(plugin); |
||
56 | Q_ASSERT(plug); |
||
57 | delete plug; |
||
58 | } |
||
59 | |||
60 | PathStrokerPlugin::PathStrokerPlugin() : ScActionPlugin() |
||
61 | { |
||
62 | // Set action info in languageChange, so we only have to do |
||
63 | // it in one place. |
||
64 | languageChange(); |
||
65 | } |
||
66 | |||
67 | PathStrokerPlugin::~PathStrokerPlugin() {}; |
||
68 | |||
69 | void PathStrokerPlugin::languageChange() |
||
70 | { |
||
71 | // Note that we leave the unused members unset. They'll be initialised |
||
72 | // with their default ctors during construction. |
||
73 | // Action name |
||
74 | m_actionInfo.name = "PathStroker"; |
||
75 | // Action text for menu, including accel |
||
76 | m_actionInfo.text = tr("Create Path from Stroke"); |
||
77 | // Menu |
||
11037 | fschmid | 78 | m_actionInfo.menu = "ItemPathOps"; |
11050 | fschmid | 79 | m_actionInfo.parentMenu = "Item"; |
80 | m_actionInfo.subMenuName = tr("Path Tools"); |
||
12566 | cbradney | 81 | m_actionInfo.enabledOnStartup = false; |
11006 | fschmid | 82 | m_actionInfo.notSuitableFor.append(PageItem::Line); |
83 | m_actionInfo.notSuitableFor.append(PageItem::TextFrame); |
||
84 | m_actionInfo.notSuitableFor.append(PageItem::ImageFrame); |
||
85 | m_actionInfo.notSuitableFor.append(PageItem::PathText); |
||
86 | m_actionInfo.notSuitableFor.append(PageItem::LatexFrame); |
||
15060 | fschmid | 87 | m_actionInfo.notSuitableFor.append(PageItem::Symbol); |
16191 | fschmid | 88 | m_actionInfo.notSuitableFor.append(PageItem::RegularPolygon); |
16215 | fschmid | 89 | m_actionInfo.notSuitableFor.append(PageItem::Arc); |
16311 | fschmid | 90 | m_actionInfo.notSuitableFor.append(PageItem::Spiral); |
11027 | fschmid | 91 | m_actionInfo.forAppMode.append(modeNormal); |
11006 | fschmid | 92 | m_actionInfo.needsNumObjects = 1; |
93 | } |
||
94 | |||
95 | const QString PathStrokerPlugin::fullTrName() const |
||
96 | { |
||
11024 | fschmid | 97 | return QObject::tr("PathStroker"); |
11006 | fschmid | 98 | } |
99 | |||
100 | const ScActionPlugin::AboutData* PathStrokerPlugin::getAboutData() const |
||
101 | { |
||
102 | AboutData* about = new AboutData; |
||
103 | Q_CHECK_PTR(about); |
||
104 | about->authors = QString::fromUtf8("Franz Schmid <Franz.Schmid@altmuehlnet.de>"); |
||
105 | about->shortDescription = tr("Create Path from Stroke"); |
||
11018 | fschmid | 106 | about->description = tr("Converts the stroke of a Path to a filled Path."); |
11006 | fschmid | 107 | // about->version |
108 | // about->releaseDate |
||
109 | // about->copyright |
||
110 | about->license = "GPL"; |
||
111 | return about; |
||
112 | } |
||
113 | |||
114 | void PathStrokerPlugin::deleteAboutData(const AboutData* about) const |
||
115 | { |
||
116 | Q_ASSERT(about); |
||
117 | delete about; |
||
118 | } |
||
119 | |||
120 | bool PathStrokerPlugin::run(ScribusDoc* doc, QString) |
||
121 | { |
||
122 | ScribusDoc* currDoc = doc; |
||
123 | if (currDoc == 0) |
||
124 | currDoc = ScCore->primaryMainWindow()->doc; |
||
125 | if (currDoc->m_Selection->count() > 0) |
||
126 | { |
||
12055 | jghali | 127 | QVector<double> m_array; |
11006 | fschmid | 128 | PageItem *currItem = currDoc->m_Selection->itemAt(0); |
129 | FPointArray path = currItem->PoLine; |
||
11018 | fschmid | 130 | QPainterPath pp; |
131 | if (currItem->itemType() == PageItem::PolyLine) |
||
132 | pp = path.toQPainterPath(false); |
||
133 | else |
||
134 | pp = path.toQPainterPath(true); |
||
12920 | fschmid | 135 | if (currItem->NamedLStyle.isEmpty()) |
11006 | fschmid | 136 | { |
12920 | fschmid | 137 | QPainterPathStroker stroke; |
138 | stroke.setCapStyle(currItem->lineEnd()); |
||
139 | stroke.setJoinStyle(currItem->lineJoin()); |
||
140 | if (currItem->lineStyle() == Qt::SolidLine) |
||
141 | stroke.setDashPattern(currItem->lineStyle()); |
||
142 | else |
||
11006 | fschmid | 143 | { |
12920 | fschmid | 144 | getDashArray(currItem->lineStyle(), 1, m_array); |
145 | stroke.setDashPattern(m_array); |
||
146 | } |
||
147 | stroke.setWidth(currItem->lineWidth()); |
||
16350 | fschmid | 148 | QPainterPath result = stroke.createStroke(pp).simplified(); |
12920 | fschmid | 149 | if (currItem->startArrowIndex() != 0) |
150 | { |
||
151 | FPoint Start = currItem->PoLine.point(0); |
||
18114 | jghali | 152 | for (int xx = 1; xx < currItem->PoLine.size(); xx += 2) |
11006 | fschmid | 153 | { |
12920 | fschmid | 154 | FPoint Vector = currItem->PoLine.point(xx); |
155 | if ((Start.x() != Vector.x()) || (Start.y() != Vector.y())) |
||
156 | { |
||
157 | double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI); |
||
13951 | fschmid | 158 | QTransform arrowTrans; |
14969 | cbradney | 159 | FPointArray arrow = currDoc->arrowStyles().at(currItem->startArrowIndex()-1).points.copy(); |
12920 | fschmid | 160 | arrowTrans.translate(Start.x(), Start.y()); |
161 | arrowTrans.rotate(r); |
||
15345 | fschmid | 162 | arrowTrans.scale(currItem->startArrowScale() / 100.0, currItem->startArrowScale() / 100.0); |
12920 | fschmid | 163 | arrowTrans.scale(currItem->lineWidth(), currItem->lineWidth()); |
164 | arrow.map(arrowTrans); |
||
165 | result.addPath(arrow.toQPainterPath(true)); |
||
166 | break; |
||
167 | } |
||
11006 | fschmid | 168 | } |
169 | } |
||
12920 | fschmid | 170 | if (currItem->endArrowIndex() != 0) |
171 | { |
||
172 | FPoint End = currItem->PoLine.point(currItem->PoLine.size()-2); |
||
173 | for (uint xx = currItem->PoLine.size()-1; xx > 0; xx -= 2) |
||
174 | { |
||
175 | FPoint Vector = currItem->PoLine.point(xx); |
||
176 | if ((End.x() != Vector.x()) || (End.y() != Vector.y())) |
||
177 | { |
||
178 | double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI); |
||
13951 | fschmid | 179 | QTransform arrowTrans; |
14969 | cbradney | 180 | FPointArray arrow = currDoc->arrowStyles().at(currItem->endArrowIndex()-1).points.copy(); |
12920 | fschmid | 181 | arrowTrans.translate(End.x(), End.y()); |
182 | arrowTrans.rotate(r); |
||
15345 | fschmid | 183 | arrowTrans.scale(currItem->endArrowScale() / 100.0, currItem->endArrowScale() / 100.0); |
12920 | fschmid | 184 | arrowTrans.scale(currItem->lineWidth(), currItem->lineWidth()); |
185 | arrow.map(arrowTrans); |
||
186 | result.addPath(arrow.toQPainterPath(true)); |
||
187 | break; |
||
188 | } |
||
189 | } |
||
190 | } |
||
191 | currDoc->m_Selection->clear(); |
||
192 | PageItem* newItem = currDoc->convertItemTo(currItem, PageItem::Polygon); |
||
193 | newItem->setLineWidth(0); |
||
194 | newItem->setLineStyle(Qt::SolidLine); |
||
195 | newItem->setFillColor(newItem->lineColor()); |
||
196 | newItem->setFillShade(newItem->lineShade()); |
||
197 | newItem->setFillTransparency(newItem->lineTransparency()); |
||
198 | newItem->setFillBlendmode(newItem->lineBlendmode()); |
||
199 | FPointArray points; |
||
200 | points.fromQPainterPath(result); |
||
201 | newItem->PoLine = points; |
||
202 | newItem->ClipEdited = true; |
||
203 | newItem->FrameType = 3; |
||
204 | currDoc->AdjustItemSize(newItem); |
||
205 | newItem->OldB2 = newItem->width(); |
||
206 | newItem->OldH2 = newItem->height(); |
||
207 | newItem->updateClip(); |
||
208 | newItem->ContourLine = newItem->PoLine.copy(); |
||
16338 | fschmid | 209 | newItem->setFillEvenOdd(false); |
12920 | fschmid | 210 | currDoc->m_Selection->addItem(newItem); |
11006 | fschmid | 211 | } |
12920 | fschmid | 212 | else |
11006 | fschmid | 213 | { |
12920 | fschmid | 214 | currDoc->m_Selection->clear(); |
215 | multiLine ml = currDoc->MLineStyles[currItem->NamedLStyle]; |
||
216 | bool first = true; |
||
217 | for (int it = ml.size()-1; it > -1; it--) |
||
11006 | fschmid | 218 | { |
12920 | fschmid | 219 | if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0)) |
11006 | fschmid | 220 | { |
12920 | fschmid | 221 | QPainterPathStroker stroke; |
222 | stroke.setCapStyle(static_cast<Qt::PenCapStyle>(ml[it].LineEnd)); |
||
223 | stroke.setJoinStyle(static_cast<Qt::PenJoinStyle>(ml[it].LineJoin)); |
||
224 | if (static_cast<Qt::PenStyle>(ml[it].Dash) == Qt::SolidLine) |
||
225 | stroke.setDashPattern(static_cast<Qt::PenStyle>(ml[it].Dash)); |
||
226 | else |
||
227 | { |
||
228 | getDashArray(static_cast<Qt::PenStyle>(ml[it].Dash), 1, m_array); |
||
229 | stroke.setDashPattern(m_array); |
||
230 | } |
||
231 | stroke.setWidth(ml[it].Width); |
||
13842 | fschmid | 232 | QPainterPath result = stroke.createStroke(pp).simplified(); |
12920 | fschmid | 233 | PageItem* newItem; |
234 | if (first) |
||
235 | { |
||
236 | newItem = currDoc->convertItemTo(currItem, PageItem::Polygon); |
||
237 | } |
||
238 | else |
||
239 | { |
||
240 | newItem = new PageItem_Polygon(*currItem); |
||
12921 | fschmid | 241 | newItem->convertTo(PageItem::Polygon); |
12920 | fschmid | 242 | currDoc->Items->append(newItem); |
243 | } |
||
244 | first = false; |
||
245 | newItem->setLineStyle(Qt::SolidLine); |
||
246 | newItem->setFillColor(ml[it].Color); |
||
247 | newItem->setFillShade(ml[it].Shade); |
||
248 | newItem->setFillTransparency(newItem->lineTransparency()); |
||
249 | newItem->setFillBlendmode(newItem->lineBlendmode()); |
||
250 | newItem->setLineColor(CommonStrings::None); |
||
251 | newItem->setCustomLineStyle(""); |
||
252 | FPointArray points; |
||
253 | points.fromQPainterPath(result); |
||
254 | newItem->PoLine = points; |
||
255 | newItem->ClipEdited = true; |
||
256 | newItem->FrameType = 3; |
||
257 | currDoc->AdjustItemSize(newItem); |
||
258 | newItem->OldB2 = newItem->width(); |
||
259 | newItem->OldH2 = newItem->height(); |
||
260 | newItem->updateClip(); |
||
261 | newItem->ContourLine = newItem->PoLine.copy(); |
||
16338 | fschmid | 262 | newItem->setFillEvenOdd(false); |
12920 | fschmid | 263 | currDoc->m_Selection->addItem(newItem); |
11006 | fschmid | 264 | } |
265 | } |
||
12920 | fschmid | 266 | if (currItem->startArrowIndex() != 0) |
267 | { |
||
268 | FPoint Start = currItem->PoLine.point(0); |
||
18114 | jghali | 269 | for (int xx = 1; xx < currItem->PoLine.size(); xx += 2) |
12920 | fschmid | 270 | { |
271 | FPoint Vector = currItem->PoLine.point(xx); |
||
272 | if ((Start.x() != Vector.x()) || (Start.y() != Vector.y())) |
||
273 | { |
||
274 | double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI); |
||
13951 | fschmid | 275 | QTransform arrowTrans; |
14969 | cbradney | 276 | FPointArray arrow = currDoc->arrowStyles().at(currItem->startArrowIndex()-1).points.copy(); |
12920 | fschmid | 277 | arrowTrans.translate(Start.x(), Start.y()); |
278 | arrowTrans.rotate(r); |
||
15345 | fschmid | 279 | arrowTrans.scale(currItem->startArrowScale() / 100.0, currItem->startArrowScale() / 100.0); |
12920 | fschmid | 280 | arrowTrans.scale(currItem->lineWidth(), currItem->lineWidth()); |
281 | arrow.map(arrowTrans); |
||
282 | PageItem* newItem = new PageItem_Polygon(*currItem); |
||
283 | currDoc->Items->append(newItem); |
||
284 | newItem->setLineWidth(0); |
||
285 | newItem->setLineStyle(Qt::SolidLine); |
||
286 | newItem->setCustomLineStyle(""); |
||
287 | newItem->setFillColor(newItem->lineColor()); |
||
288 | newItem->setFillShade(newItem->lineShade()); |
||
289 | newItem->setFillTransparency(newItem->lineTransparency()); |
||
290 | newItem->setFillBlendmode(newItem->lineBlendmode()); |
||
291 | newItem->PoLine = arrow; |
||
292 | newItem->ClipEdited = true; |
||
293 | newItem->FrameType = 3; |
||
294 | currDoc->AdjustItemSize(newItem); |
||
295 | newItem->OldB2 = newItem->width(); |
||
296 | newItem->OldH2 = newItem->height(); |
||
297 | newItem->updateClip(); |
||
298 | newItem->ContourLine = newItem->PoLine.copy(); |
||
12921 | fschmid | 299 | newItem->setFillEvenOdd(true); |
12920 | fschmid | 300 | currDoc->m_Selection->addItem(newItem); |
301 | break; |
||
302 | } |
||
303 | } |
||
304 | } |
||
305 | if (currItem->endArrowIndex() != 0) |
||
306 | { |
||
307 | FPoint End = currItem->PoLine.point(currItem->PoLine.size()-2); |
||
308 | for (uint xx = currItem->PoLine.size()-1; xx > 0; xx -= 2) |
||
309 | { |
||
310 | FPoint Vector = currItem->PoLine.point(xx); |
||
311 | if ((End.x() != Vector.x()) || (End.y() != Vector.y())) |
||
312 | { |
||
313 | double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI); |
||
13951 | fschmid | 314 | QTransform arrowTrans; |
14969 | cbradney | 315 | FPointArray arrow = currDoc->arrowStyles().at(currItem->endArrowIndex()-1).points.copy(); |
12920 | fschmid | 316 | arrowTrans.translate(End.x(), End.y()); |
317 | arrowTrans.rotate(r); |
||
15345 | fschmid | 318 | arrowTrans.scale(currItem->endArrowScale() / 100.0, currItem->endArrowScale() / 100.0); |
12920 | fschmid | 319 | arrowTrans.scale(currItem->lineWidth(), currItem->lineWidth()); |
320 | arrow.map(arrowTrans); |
||
321 | PageItem* newItem = new PageItem_Polygon(*currItem); |
||
322 | currDoc->Items->append(newItem); |
||
323 | newItem->setLineWidth(0); |
||
324 | newItem->setLineStyle(Qt::SolidLine); |
||
325 | newItem->setCustomLineStyle(""); |
||
326 | newItem->setFillColor(newItem->lineColor()); |
||
327 | newItem->setFillShade(newItem->lineShade()); |
||
328 | newItem->setFillTransparency(newItem->lineTransparency()); |
||
329 | newItem->setFillBlendmode(newItem->lineBlendmode()); |
||
330 | newItem->PoLine = arrow; |
||
331 | newItem->ClipEdited = true; |
||
332 | newItem->FrameType = 3; |
||
333 | currDoc->AdjustItemSize(newItem); |
||
334 | newItem->OldB2 = newItem->width(); |
||
335 | newItem->OldH2 = newItem->height(); |
||
336 | newItem->updateClip(); |
||
337 | newItem->ContourLine = newItem->PoLine.copy(); |
||
12921 | fschmid | 338 | newItem->setFillEvenOdd(true); |
12920 | fschmid | 339 | currDoc->m_Selection->addItem(newItem); |
340 | break; |
||
341 | } |
||
342 | } |
||
343 | } |
||
344 | if (currDoc->m_Selection->count() > 1) |
||
345 | currDoc->itemSelection_GroupObjects(false, false); |
||
12921 | fschmid | 346 | currDoc->m_Selection->itemAt(0)->emitAllToGUI(); |
11006 | fschmid | 347 | } |
348 | currDoc->changed(); |
||
349 | } |
||
350 | return true; |
||
351 | } |