Krita Source Code Documentation
Loading...
Searching...
No Matches
EnhancedPathShapeFactory.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2007 Jan Hambrecht <jaham@gmx.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
9
10#include <KoShapeStroke.h>
11#include <KoProperties.h>
12#include <KoXmlNS.h>
13#include <KoColorBackground.h>
15
16#include <KoIcon.h>
17
18#include <klocalizedstring.h>
19#include "kis_pointer_utils.h"
20
21#include <QString>
22
23#include <math.h>
24
26 : KoShapeFactoryBase(EnhancedPathShapeId, i18n("An enhanced path shape"))
27{
28 setToolTip(i18n("An enhanced path"));
29 setIconName(koIconNameCStr("krita_draw_path"));
32
33// addCross();
34// addArrow();
35// addCallout();
36// addSmiley();
37// addCircularArrow();
38// addGearhead();
39}
40
42{
43 EnhancedPathShape *shape = new EnhancedPathShape(QRect(0, 0, 100, 100));
44 shape->setStroke(toQShared(new KoShapeStroke(1.0)));
46
47 shape->addModifiers("35");
48
49 shape->addFormula("Right", "width - $0");
50 shape->addFormula("Bottom", "height - $0");
51 shape->addFormula("Half", "min(0.5 * height, 0.5 * width)");
52
53 shape->addCommand("M $0 0");
54 shape->addCommand("L ?Right 0 ?Right $0 width $0 width ?Bottom ?Right ?Bottom");
55 shape->addCommand("L ?Right height $0 height $0 ?Bottom 0 ?Bottom 0 $0 $0 $0");
56 shape->addCommand("Z");
57
58 ComplexType handle;
59 handle["draw:handle-position"] = "$0 0";
60 handle["draw:handle-range-x-minimum"] = '0';
61 handle["draw:handle-range-x-maximum"] = "?Half";
62 shape->addHandle(handle);
63 shape->setSize(QSize(100, 100));
64
65 return shape;
66}
67
69{
70 QVariant viewboxData;
71 const QRect viewBox = (params->property(QLatin1String("viewBox"), viewboxData)) ?
72 viewboxData.toRect() :
73 QRect(0, 0, 100, 100);
74
75 EnhancedPathShape *shape = new EnhancedPathShape(viewBox);
76
78 shape->setStroke(toQShared(new KoShapeStroke(1.0)));
79 shape->addModifiers(params->stringProperty("modifiers"));
80
81 ListType handles = params->property("handles").toList();
82 foreach (const QVariant &v, handles) {
83 shape->addHandle(v.toMap());
84 }
85
86 ComplexType formulae = params->property("formulae").toMap();
87 ComplexType::const_iterator formula = formulae.constBegin();
88 ComplexType::const_iterator lastFormula = formulae.constEnd();
89 for (; formula != lastFormula; ++formula) {
90 shape->addFormula(formula.key(), formula.value().toString());
91 }
92
93 QStringList commands = params->property("commands").toStringList();
94 foreach (const QString &cmd, commands) {
95 shape->addCommand(cmd);
96 }
97
98 QVariant color;
99 if (params->property("background", color)) {
100 shape->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(color.value<QColor>())));
101 }
102 QSizeF size = shape->size();
103 if (size.width() > size.height()) {
104 shape->setSize(QSizeF(100, 100 * size.height() / size.width()));
105 } else {
106 shape->setSize(QSizeF(100 * size.width() / size.height(), 100));
107 }
108
109 return shape;
110}
111
113 const QString &modifiers, const QStringList &commands,
114 const ListType &handles, const ComplexType &formulae) const
115{
116 KoProperties *props = new KoProperties();
117 props->setProperty("modifiers", modifiers);
118 props->setProperty("commands", commands);
119 props->setProperty("handles", handles);
120 props->setProperty("formulae", formulae);
121 props->setProperty("background", QVariant::fromValue<QColor>(QColor(Qt::red)));
122
123 return props;
124}
125
127{
128 QString modifiers("35");
129
130 QStringList commands;
131 commands.append("M $0 0");
132 commands.append("L ?Right 0 ?Right $0 width $0 width ?Bottom ?Right ?Bottom");
133 commands.append("L ?Right height $0 height $0 ?Bottom 0 ?Bottom 0 $0 $0 $0");
134 commands.append("Z");
135
136 ListType handles;
137 ComplexType handle;
138 handle["draw:handle-position"] = "$0 0";
139 handle["draw:handle-range-x-minimum"] = '0';
140 handle["draw:handle-range-x-maximum"] = "?Half";
141 handles.append(QVariant(handle));
142
143 ComplexType formulae;
144 formulae["Right"] = "width - $0";
145 formulae["Bottom"] = "height - $0";
146 formulae["Half"] = "min(0.5 * height, 0.5 * width)";
147
149 t.id = KoPathShapeId;
150 t.templateId = "cross";
151 t.name = i18n("Cross");
152 t.family = "funny";
153 t.toolTip = i18n("A cross");
154 t.iconName = koIconName("cross-shape");
155 t.properties = dataToProperties(modifiers, commands, handles, formulae);
156
157 addTemplate(t);
158}
159
161{
162 {
163 // arrow right
164 QString modifiers("60 35");
165
166 QStringList commands;
167 commands.append("M $0 $1");
168 commands.append("L $0 0 width ?HalfHeight $0 height $0 ?LowerCorner 0 ?LowerCorner 0 $1");
169 commands.append("Z");
170
171 ListType handles;
172 ComplexType handle;
173 handle["draw:handle-position"] = "$0 $1";
174 handle["draw:handle-range-x-minimum"] = '0';
175 handle["draw:handle-range-x-maximum"] = "width";
176 handle["draw:handle-range-y-minimum"] = '0';
177 handle["draw:handle-range-y-maximum"] = "?HalfHeight";
178 handles.append(QVariant(handle));
179
180 ComplexType formulae;
181 formulae["HalfHeight"] = "0.5 * height";
182 formulae["LowerCorner"] = "height - $1";
183
185 t.id = KoPathShapeId;
186 t.templateId = "arrow_right";
187 t.name = i18n("Arrow");
188 t.family = "arrow";
189 t.toolTip = i18n("An arrow");
190 t.iconName = koIconName("draw-arrow-forward");
191 t.properties = dataToProperties(modifiers, commands, handles, formulae);
192
193 addTemplate(t);
194 }
195
196 {
197 // arrow left
198 QString modifiers("40 35");
199
200 QStringList commands;
201 commands.append("M $0 $1");
202 commands.append("L $0 0 0 ?HalfHeight $0 height $0 ?LowerCorner width ?LowerCorner width $1");
203 commands.append("Z");
204
205 ListType handles;
206 ComplexType handle;
207 handle["draw:handle-position"] = "$0 $1";
208 handle["draw:handle-range-x-minimum"] = '0';
209 handle["draw:handle-range-x-maximum"] = "width";
210 handle["draw:handle-range-y-minimum"] = '0';
211 handle["draw:handle-range-y-maximum"] = "?HalfHeight";
212 handles.append(QVariant(handle));
213
214 ComplexType formulae;
215 formulae["HalfHeight"] = "0.5 * height";
216 formulae["LowerCorner"] = "height - $1";
217
219 t.id = KoPathShapeId;
220 t.templateId = "arrow_left";
221 t.name = i18n("Arrow");
222 t.family = "arrow";
223 t.toolTip = i18n("An arrow");
224 t.iconName = koIconName("draw-arrow-back");
225 t.properties = dataToProperties(modifiers, commands, handles, formulae);
226
227 addTemplate(t);
228 }
229
230 {
231 // arrow top
232 QString modifiers("35 40");
233
234 QStringList commands;
235 commands.append("M $0 $1");
236 commands.append("L 0 $1 ?HalfWidth 0 width $1 ?RightCorner $1 ?RightCorner height $0 height");
237 commands.append("Z");
238
239 ListType handles;
240 ComplexType handle;
241 handle["draw:handle-position"] = "$0 $1";
242 handle["draw:handle-range-x-minimum"] = '0';
243 handle["draw:handle-range-x-maximum"] = "?HalfWidth";
244 handle["draw:handle-range-y-minimum"] = '0';
245 handle["draw:handle-range-y-maximum"] = "height";
246 handles.append(QVariant(handle));
247
248 ComplexType formulae;
249 formulae["HalfWidth"] = "0.5 * width";
250 formulae["RightCorner"] = "width - $0";
251
253 t.id = KoPathShapeId;
254 t.templateId = "arrow_top";
255 t.name = i18n("Arrow");
256 t.family = "arrow";
257 t.toolTip = i18n("An arrow");
258 t.iconName = koIconName("draw-arrow-up");
259 t.properties = dataToProperties(modifiers, commands, handles, formulae);
260
261 addTemplate(t);
262 }
263
264 {
265 // arrow bottom
266 QString modifiers("35 60");
267
268 QStringList commands;
269 commands.append("M $0 $1");
270 commands.append("L 0 $1 ?HalfWidth height width $1 ?RightCorner $1 ?RightCorner 0 $0 0");
271 commands.append("Z");
272
273 ListType handles;
274 ComplexType handle;
275 handle["draw:handle-position"] = "$0 $1";
276 handle["draw:handle-range-x-minimum"] = '0';
277 handle["draw:handle-range-x-maximum"] = "?HalfWidth";
278 handle["draw:handle-range-y-minimum"] = '0';
279 handle["draw:handle-range-y-maximum"] = "height";
280 handles.append(QVariant(handle));
281
282 ComplexType formulae;
283 formulae["HalfWidth"] = "0.5 * width";
284 formulae["RightCorner"] = "width - $0";
285
287 t.id = KoPathShapeId;
288 t.templateId = "arrow_bottom";
289 t.name = i18n("Arrow");
290 t.family = "arrow";
291 t.toolTip = i18n("An arrow");
292 t.iconName = koIconName("draw-arrow-down");
293 t.properties = dataToProperties(modifiers, commands, handles, formulae);
294
295 addTemplate(t);
296 }
297}
298
300{
301 QString modifiers("4250 45000");
302
303 QStringList commands;
304 commands.append("M 3590 0");
305 commands.append("X 0 3590");
306 commands.append("L ?f2 ?f3 0 8970 0 12630 ?f4 ?f5 0 18010");
307 commands.append("Y 3590 21600");
308 commands.append("L ?f6 ?f7 8970 21600 12630 21600 ?f8 ?f9 18010 21600");
309 commands.append("X 21600 18010");
310 commands.append("L ?f10 ?f11 21600 12630 21600 8970 ?f12 ?f13 21600 3590");
311 commands.append("Y 18010 0");
312 commands.append("L ?f14 ?f15 12630 0 8970 0 ?f16 ?f17");
313 commands.append("Z");
314 commands.append("N");
315
316 ComplexType formulae;
317 formulae["f0"] = "$0 -10800";
318 formulae["f1"] = "$1 -10800";
319 formulae["f2"] = "if(?f18 ,$0 ,0)";
320 formulae["f3"] = "if(?f18 ,$1 ,6280)";
321 formulae["f4"] = "if(?f23 ,$0 ,0)";
322 formulae["f5"] = "if(?f23 ,$1 ,15320)";
323 formulae["f6"] = "if(?f26 ,$0 ,6280)";
324 formulae["f7"] = "if(?f26 ,$1 ,21600)";
325 formulae["f8"] = "if(?f29 ,$0 ,15320)";
326 formulae["f9"] = "if(?f29 ,$1 ,21600)";
327 formulae["f10"] = "if(?f32 ,$0 ,21600)";
328 formulae["f11"] = "if(?f32 ,$1 ,15320)";
329 formulae["f12"] = "if(?f34 ,$0 ,21600)";
330 formulae["f13"] = "if(?f34 ,$1 ,6280)";
331 formulae["f14"] = "if(?f36 ,$0 ,15320)";
332 formulae["f15"] = "if(?f36 ,$1 ,0)";
333 formulae["f16"] = "if(?f38 ,$0 ,6280)";
334 formulae["f17"] = "if(?f38 ,$1 ,0)";
335 formulae["f18"] = "if($0 ,-1,?f19)";
336 formulae["f19"] = "if(?f1 ,-1,?f22)";
337 formulae["f20"] = "abs(?f0)";
338 formulae["f21"] = "abs(?f1)";
339 formulae["f22"] = "?f20 -?f21";
340 formulae["f23"] = "if($0 ,-1,?f24)";
341 formulae["f24"] = "if(?f1 ,?f22 ,-1)";
342 formulae["f25"] = "$1 -21600";
343 formulae["f26"] = "if(?f25 ,?f27 ,-1)";
344 formulae["f27"] = "if(?f0 ,-1,?f28)";
345 formulae["f28"] = "?f21 -?f20";
346 formulae["f29"] = "if(?f25 ,?f30 ,-1)";
347 formulae["f30"] = "if(?f0 ,?f28 ,-1)";
348 formulae["f31"] = "$0 -21600";
349 formulae["f32"] = "if(?f31 ,?f33 ,-1)";
350 formulae["f33"] = "if(?f1 ,?f22 ,-1)";
351 formulae["f34"] = "if(?f31 ,?f35 ,-1)";
352 formulae["f35"] = "if(?f1 ,-1,?f22)";
353 formulae["f36"] = "if($1 ,-1,?f37)";
354 formulae["f37"] = "if(?f0 ,?f28 ,-1)";
355 formulae["f38"] = "if($1 ,-1,?f39)";
356 formulae["f39"] = "if(?f0 ,-1,?f28)";
357 formulae["f40"] = "$0";
358 formulae["f41"] = "$1";
359
360 ListType handles;
361 ComplexType handle;
362 handle["draw:handle-position"] = "$0 $1";
363 handles.append(QVariant(handle));
364
366 t.id = KoPathShapeId;
367 t.templateId = "callout";
368 t.name = i18n("Callout");
369 t.family = "funny";
370 t.toolTip = i18n("A callout");
371 t.iconName = koIconName("callout-shape");
372 KoProperties *properties = dataToProperties(modifiers, commands, handles, formulae);
373 properties->setProperty(QLatin1String("viewBox"), QRect(0, 0, 21600, 21600));
374 t.properties = properties;
375
376 addTemplate(t);
377}
378
380{
381 QString modifiers("17520");
382
383 QStringList commands;
384 commands.append("U 10800 10800 10800 10800 0 23592960");
385 commands.append("Z");
386 commands.append("N");
387 commands.append("U 7305 7515 1165 1165 0 23592960");
388 commands.append("Z");
389 commands.append("N");
390 commands.append("U 14295 7515 1165 1165 0 23592960");
391 commands.append("Z");
392 commands.append("N");
393 commands.append("M 4870 ?f1");
394 commands.append("C 8680 ?f2 12920 ?f2 16730 ?f1");
395 commands.append("Z");
396 commands.append("F");
397 commands.append("N");
398
399 ComplexType formulae;
400 formulae["f0"] = "$0 -15510";
401 formulae["f1"] = "17520-?f0";
402 formulae["f2"] = "15510+?f0";
403
404 ListType handles;
405 ComplexType handle;
406 handle["draw:handle-position"] = "10800 $0";
407 handle["draw:handle-range-y-minimum"] = "15510";
408 handle["draw:handle-range-y-maximum"] = "17520";
409 handles.append(QVariant(handle));
410
412 t.id = KoPathShapeId;
413 t.templateId = "smiley";
414 t.name = i18n("Smiley");
415 t.family = "funny";
416 t.toolTip = i18n("Smiley");
417 t.iconName = koIconName("smiley-shape");
418 KoProperties *properties = dataToProperties(modifiers, commands, handles, formulae);
419 properties->setProperty(QLatin1String("viewBox"), QRect(0, 0, 21600, 21600));
420 t.properties = properties;
421
422 addTemplate(t);
423}
424
426{
427 QString modifiers("180 0 5500");
428
429 QStringList commands;
430 commands.append("B ?f3 ?f3 ?f20 ?f20 ?f19 ?f18 ?f17 ?f16");
431 commands.append("W 0 0 21600 21600 ?f9 ?f8 ?f11 ?f10");
432 commands.append("L ?f24 ?f23 ?f36 ?f35 ?f29 ?f28");
433 commands.append("Z");
434 commands.append("N");
435
436 ComplexType formulae;
437
438 formulae["f0"] = "$0";
439 formulae["f1"] = "$1";
440 formulae["f2"] = "$2";
441 formulae["f3"] = "10800+$2";
442 formulae["f4"] = "10800*sin($0 *(pi/180))";
443 formulae["f5"] = "10800*cos($0 *(pi/180))";
444 formulae["f6"] = "10800*sin($1 *(pi/180))";
445 formulae["f7"] = "10800*cos($1 *(pi/180))";
446 formulae["f8"] = "?f4 +10800";
447 formulae["f9"] = "?f5 +10800";
448 formulae["f10"] = "?f6 +10800";
449 formulae["f11"] = "?f7 +10800";
450 formulae["f12"] = "?f3 *sin($0 *(pi/180))";
451 formulae["f13"] = "?f3 *cos($0 *(pi/180))";
452 formulae["f14"] = "?f3 *sin($1 *(pi/180))";
453 formulae["f15"] = "?f3 *cos($1 *(pi/180))";
454 formulae["f16"] = "?f12 +10800";
455 formulae["f17"] = "?f13 +10800";
456 formulae["f18"] = "?f14 +10800";
457 formulae["f19"] = "?f15 +10800";
458 formulae["f20"] = "21600-?f3";
459 formulae["f21"] = "13500*sin($1 *(pi/180))";
460 formulae["f22"] = "13500*cos($1 *(pi/180))";
461 formulae["f23"] = "?f21 +10800";
462 formulae["f24"] = "?f22 +10800";
463 formulae["f25"] = "$2 -2700";
464 formulae["f26"] = "?f25 *sin($1 *(pi/180))";
465 formulae["f27"] = "?f25 *cos($1 *(pi/180))";
466 formulae["f28"] = "?f26 +10800";
467 formulae["f29"] = "?f27 +10800";
468 formulae["f30"] = "($1+45)*pi/180";
469 formulae["f31"] = "sqrt(((?f29-?f24)*(?f29-?f24))+((?f28-?f23)*(?f28-?f23)))";
470 formulae["f32"] = "sqrt(2)/2*?f31";
471 formulae["f33"] = "?f32*sin(?f30)";
472 formulae["f34"] = "?f32*cos(?f30)";
473 formulae["f35"] = "?f28+?f33";
474 formulae["f36"] = "?f29+?f34";
475
476 ListType handles;
477 ComplexType handle;
478 handle["draw:handle-position"] = "$0 10800";
479 handle["draw:handle-polar"] = "10800 10800";
480 handle["draw:handle-radius-range-minimum"] = "10800";
481 handle["draw:handle-radius-range-maximum"] = "10800";
482 handles.append(QVariant(handle));
483
484 handle.clear();
485 handle["draw:handle-position"] = "$1 $2";
486 handle["draw:handle-polar"] = "10800 10800";
487 handle["draw:handle-radius-range-minimum"] = '0';
488 handle["draw:handle-radius-range-maximum"] = "10800";
489 handles.append(QVariant(handle));
490
492 t.id = KoPathShapeId;
493 t.templateId = "circulararrow";
494 t.name = i18n("Circular Arrow");
495 t.family = "arrow";
496 t.toolTip = i18n("A circular-arrow");
497 t.iconName = koIconName("circular-arrow-shape");
498 KoProperties *properties = dataToProperties(modifiers, commands, handles, formulae);
499 properties->setProperty(QLatin1String("viewBox"), QRect(0, 0, 21600, 21600));
500 t.properties = properties;
501 addTemplate(t);
502}
503
505{
506 QStringList commands;
507 commands.append("M 20 70");
508 commands.append("L 20 100 30 100 30 50 30 70 40 70 40 40 0 40 0 70 10 70 10 50 10 100 20 100");
509 commands.append("Z");
510 commands.append("N");
511
512 uint toothCount = 10;
513 qreal toothAngle = 360.0 / qreal(toothCount);
514 //kDebug() <<"toothAngle =" << toothAngle;
515 qreal outerRadius = 0.5 * 25.0;
516 qreal innerRadius = 0.5 * 17.0;
517 QPointF center(20, 25);
518 qreal radian = (270.0 - 0.35 * toothAngle) * M_PI / 180.0;
519 commands.append(QString("M %1 %2").arg(center.x() + innerRadius * cos(radian)).arg(center.y() + innerRadius * sin(radian)));
520 QString cmd("L");
521 for (uint i = 0; i < toothCount; ++i) {
522 radian += 0.15 * toothAngle * M_PI / 180.0;
523 cmd += QString(" %1 %2").arg(center.x() + outerRadius * cos(radian)).arg(center.y() + outerRadius * sin(radian));
524 radian += 0.35 * toothAngle * M_PI / 180.0;
525 cmd += QString(" %1 %2").arg(center.x() + outerRadius * cos(radian)).arg(center.y() + outerRadius * sin(radian));
526 radian += 0.15 * toothAngle * M_PI / 180.0;
527 cmd += QString(" %1 %2").arg(center.x() + innerRadius * cos(radian)).arg(center.y() + innerRadius * sin(radian));
528 radian += 0.35 * toothAngle * M_PI / 180.0;
529 cmd += QString(" %1 %2").arg(center.x() + innerRadius * cos(radian)).arg(center.y() + innerRadius * sin(radian));
530 }
531 //kDebug() <<"gear command =" << cmd;
532 commands.append(cmd);
533 commands.append("Z");
534 commands.append("N");
535
537 t.id = KoPathShapeId;
538 t.templateId = "gearhead";
539 t.name = i18n("Gearhead");
540 t.family = "funny";
541 t.toolTip = i18n("A gearhead");
542 t.iconName = koIconName("gearhead-shape");
543 KoProperties *properties = dataToProperties(QString(), commands, ListType(), ComplexType());
544 properties->setProperty("background", QVariant::fromValue<QColor>(QColor(Qt::blue)));
545 properties->setProperty(QLatin1String("viewBox"), QRect(0, 0, 40, 90));
546 t.properties = properties;
547 addTemplate(t);
548}
549
550bool EnhancedPathShapeFactory::supports(const QDomElement &e, KoShapeLoadingContext &context) const
551{
552 Q_UNUSED(context);
553 return (e.localName() == "custom-shape" && e.namespaceURI() == KoXmlNS::draw);
554}
#define EnhancedPathShapeId
qreal v
QList< QString > QStringList
unsigned int uint
#define KoPathShapeId
Definition KoPathShape.h:20
KoShape * createDefaultShape(KoDocumentResourceManager *documentResources=0) const override
bool supports(const QDomElement &e, KoShapeLoadingContext &context) const override
KoShape * createShape(const KoProperties *params, KoDocumentResourceManager *documentResources=0) const override
QMap< QString, QVariant > ComplexType
KoProperties * dataToProperties(const QString &modifiers, const QStringList &commands, const ListType &handles, const ComplexType &formulae) const
void addCommand(const QString &command)
Add command for instance "M 0 0".
void addHandle(const QMap< QString, QVariant > &handle)
Add a single handle with format: x y minX maxX minY maxY.
void setSize(const QSizeF &newSize) override
Resize the shape.
void addFormula(const QString &name, const QString &formula)
Add formula with given name and textual representation.
void addModifiers(const QString &modifiers)
Add modifiers with format: modifier0 modifier1 modifier2 ...
A simple solid color shape background.
QSizeF size() const override
reimplemented
void setProperty(const QString &name, const QVariant &value)
QString stringProperty(const QString &name, const QString &defaultValue=QString()) const
bool property(const QString &name, QVariant &value) const
void addTemplate(const KoShapeTemplate &params)
void setToolTip(const QString &tooltip)
void setLoadingPriority(int priority)
void setIconName(const char *iconName)
void setXmlElementNames(const QString &nameSpace, const QStringList &elementNames)
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:1081
virtual void setBackground(QSharedPointer< KoShapeBackground > background)
Definition KoShape.cpp:918
void setShapeId(const QString &id)
Definition KoShape.cpp:1062
static const QString draw
Definition KoXmlNS.h:27
#define M_PI
Definition kis_global.h:111
#define koIconNameCStr(name)
Definition kis_icon.h:28
#define koIconName(name)
Definition kis_icon.h:27
QSharedPointer< T > toQShared(T *ptr)
QString iconName
Icon name.
QString family
The family of the shape (possible values are: "funny","arrow")
QString id
The id of the shape.
QString toolTip
The tooltip text for the template.
QString name
The name to be shown for this template.
const KoProperties * properties
QString templateId
The id of this particular template - only has to be unique with the shape.