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.,                                        *
24 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.              *
25 ****************************************************************************/
26 
27 #include "subdivide.h"
28 #include "scribuscore.h"
29 #include "scribusdoc.h"
30 #include "appmodes.h"
31 #include "selection.h"
32 
subdivide_getPluginAPIVersion()33 int subdivide_getPluginAPIVersion()
34 {
35 	return PLUGIN_API_VERSION;
36 }
37 
subdivide_getPlugin()38 ScPlugin* subdivide_getPlugin()
39 {
40 	SubdividePlugin* plug = new SubdividePlugin();
41 	Q_CHECK_PTR(plug);
42 	return plug;
43 }
44 
subdivide_freePlugin(ScPlugin * plugin)45 void subdivide_freePlugin(ScPlugin* plugin)
46 {
47 	SubdividePlugin* plug = qobject_cast<SubdividePlugin*>(plugin);
48 	Q_ASSERT(plug);
49 	delete plug;
50 }
51 
SubdividePlugin()52 SubdividePlugin::SubdividePlugin()
53 {
54 	// Set action info in languageChange, so we only have to do
55 	// it in one place.
56 	languageChange();
57 }
58 
~SubdividePlugin()59 SubdividePlugin::~SubdividePlugin() {};
60 
languageChange()61 void SubdividePlugin::languageChange()
62 {
63 	// Note that we leave the unused members unset. They'll be initialised
64 	// with their default ctors during construction.
65 	// Action name
66 	m_actionInfo.name = "Subdivide";
67 	// Action text for menu, including accel
68 	m_actionInfo.text = tr("Subdivide Path");
69 	m_actionInfo.helpText = tr("Subdivide a path by inserting new Nodes.");
70 	// Menu
71 	m_actionInfo.menu = "ItemPathOps";
72 	m_actionInfo.parentMenu = "Item";
73 	m_actionInfo.subMenuName = tr("Path Tools");
74 	m_actionInfo.enabledOnStartup = false;
75 	m_actionInfo.notSuitableFor.append(PageItem::Line);
76 	m_actionInfo.notSuitableFor.append(PageItem::Symbol);
77 	m_actionInfo.forAppMode.append(modeEditClip);
78 	m_actionInfo.needsNumObjects = 1;
79 }
80 
fullTrName() const81 QString SubdividePlugin::fullTrName() const
82 {
83 	return QObject::tr("Subdivide");
84 }
85 
getAboutData() const86 const ScActionPlugin::AboutData* SubdividePlugin::getAboutData() const
87 {
88 	AboutData* about = new AboutData;
89 	Q_CHECK_PTR(about);
90 	about->authors = QString::fromUtf8("Franz Schmid <Franz.Schmid@altmuehlnet.de>");
91 	about->shortDescription = tr("Subdivide");
92 	about->description = tr("Subdivide selected Path");
93 	// about->version
94 	// about->releaseDate
95 	// about->copyright
96 	about->license = "GPL";
97 	return about;
98 }
99 
deleteAboutData(const AboutData * about) const100 void SubdividePlugin::deleteAboutData(const AboutData* about) const
101 {
102 	Q_ASSERT(about);
103 	delete about;
104 }
105 
run(ScribusDoc * doc,const QString &)106 bool SubdividePlugin::run(ScribusDoc* doc, const QString&)
107 {
108 	ScribusDoc* currDoc = doc;
109 	if (currDoc == nullptr)
110 		currDoc = ScCore->primaryMainWindow()->doc;
111 	double nearT = 0.5;
112 	uint docSelectionCount = currDoc->m_Selection->count();
113 	if (docSelectionCount != 0)
114 	{
115 		for (uint aa = 0; aa < docSelectionCount; ++aa)
116 		{
117 			FPointArray points;
118 			PageItem *currItem = currDoc->m_Selection->itemAt(aa);
119 			if (currDoc->nodeEdit.isContourLine())
120 			{
121 				uint psize = currItem->ContourLine.size();
122 				for (uint a = 0; a < psize-3; a += 4)
123 				{
124 					if (currItem->ContourLine.isMarker(a))
125 					{
126 						points.setMarker();
127 						continue;
128 					}
129 					FPoint base = currItem->ContourLine.point(a);
130 					FPoint c1 = currItem->ContourLine.point(a+1);
131 					FPoint base2 =  currItem->ContourLine.point(a+2);
132 					FPoint c2 = currItem->ContourLine.point(a+3);
133 					FPoint cn1 = (1.0 - nearT) * base + nearT * c1;
134 					FPoint cn2 = (1.0 - nearT) * cn1 + nearT * ((1.0 - nearT) * c1 + nearT * c2);
135 					FPoint cn3 = (1.0 - nearT) * ((1.0 - nearT) * c1 + nearT * c2) + nearT * ((1.0 - nearT) * c2 + nearT * base2);
136 					FPoint cn4 = (1.0 - nearT) * c2 + nearT * base2;
137 					FPoint bp1 = (1.0 - nearT) * cn2 + nearT * cn3;
138 					if ((base == c1) && (base2 == c2))
139 					{
140 						points.addPoint(base);
141 						points.addPoint(c1);
142 						points.addPoint(bp1);
143 						points.addPoint(bp1);
144 						points.addPoint(bp1);
145 						points.addPoint(bp1);
146 						points.addPoint(base2);
147 						points.addPoint(c2);
148 					}
149 					else
150 					{
151 						points.addPoint(base);
152 						points.addPoint(cn1);
153 						points.addPoint(bp1);
154 						points.addPoint(cn2);
155 						points.addPoint(bp1);
156 						points.addPoint(cn3);
157 						points.addPoint(base2);
158 						points.addPoint(cn4);
159 					}
160 				}
161 				currItem->ContourLine = points;
162 			}
163 			else
164 			{
165 				uint psize = currItem->PoLine.size();
166 				for (uint a = 0; a < psize-3; a += 4)
167 				{
168 					if (currItem->PoLine.isMarker(a))
169 					{
170 						points.setMarker();
171 						continue;
172 					}
173 					FPoint base = currItem->PoLine.point(a);
174 					FPoint c1 = currItem->PoLine.point(a+1);
175 					FPoint base2 =  currItem->PoLine.point(a+2);
176 					FPoint c2 = currItem->PoLine.point(a+3);
177 					FPoint cn1 = (1.0 - nearT) * base + nearT * c1;
178 					FPoint cn2 = (1.0 - nearT) * cn1 + nearT * ((1.0 - nearT) * c1 + nearT * c2);
179 					FPoint cn3 = (1.0 - nearT) * ((1.0 - nearT) * c1 + nearT * c2) + nearT * ((1.0 - nearT) * c2 + nearT * base2);
180 					FPoint cn4 = (1.0 - nearT) * c2 + nearT * base2;
181 					FPoint bp1 = (1.0 - nearT) * cn2 + nearT * cn3;
182 					if ((base == c1) && (base2 == c2))
183 					{
184 						points.addPoint(base);
185 						points.addPoint(c1);
186 						points.addPoint(bp1);
187 						points.addPoint(bp1);
188 						points.addPoint(bp1);
189 						points.addPoint(bp1);
190 						points.addPoint(base2);
191 						points.addPoint(c2);
192 					}
193 					else
194 					{
195 						points.addPoint(base);
196 						points.addPoint(cn1);
197 						points.addPoint(bp1);
198 						points.addPoint(cn2);
199 						points.addPoint(bp1);
200 						points.addPoint(cn3);
201 						points.addPoint(base2);
202 						points.addPoint(cn4);
203 					}
204 				}
205 				currItem->PoLine = points;
206 				currItem->ClipEdited = true;
207 				currItem->FrameType = 3;
208 				currDoc->adjustItemSize(currItem);
209 				currItem->OldB2 = currItem->width();
210 				currItem->OldH2 = currItem->height();
211 				currItem->updateClip();
212 			}
213 		}
214 		currDoc->regionsChanged()->update(QRectF());
215 		currDoc->changed();
216 	}
217 	return true;
218 }
219