Krita Source Code Documentation
Loading...
Searching...
No Matches
KoShape.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2006 C. Boemann Rasmussen <cbo@boemann.dk>
3 SPDX-FileCopyrightText: 2006-2010 Thomas Zander <zander@kde.org>
4 SPDX-FileCopyrightText: 2006-2010 Thorsten Zachmann <zachmann@kde.org>
5 SPDX-FileCopyrightText: 2007-2009, 2011 Jan Hambrecht <jaham@gmx.net>
6 SPDX-FileCopyrightText: 2010 Boudewijn Rempt <boud@valdyas.org>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include <limits>
12
13#include "KoShape.h"
14#include "KoShape_p.h"
15#include "KoShapeContainer.h"
16#include "KoShapeLayer.h"
18#include "KoSelection.h"
19#include "KoPointerEvent.h"
20#include "KoInsets.h"
21#include "KoShapeStrokeModel.h"
22#include "KoShapeBackground.h"
23#include "KoColorBackground.h"
24#include "KoHatchBackground.h"
26#include "KoPatternBackground.h"
27#include "KoShapeManager.h"
28#include "KoShapeUserData.h"
32#include "KoViewConverter.h"
33#include "KoShapeStroke.h"
34#include "KoShapeShadow.h"
35#include "KoClipPath.h"
36#include "KoPathShape.h"
37#include "KoFilterEffectStack.h"
38#include <KoSnapData.h>
39
40#include <KoXmlWriter.h>
41#include <KoXmlNS.h>
42#include <KoUnit.h>
43
44#include <QPainter>
45#include <QVariant>
46#include <QPainterPath>
47#include <QList>
48#include <QMap>
49#include <FlakeDebug.h>
50
51#include "kis_assert.h"
52
54
55// KoShape::Private
56
58 : QSharedData()
59 , size(50, 50)
60 , shadow(0)
61 , filterEffectStack(0)
62 , transparency(0.0)
63 , zIndex(0)
64 , runThrough(0)
65 , visible(true)
66 , printable(true)
67 , geometryProtected(false)
68 , keepAspect(false)
69 , selectable(true)
70 , protectContent(false)
71 , textRunAroundSide(KoShape::BiggestRunAroundSide)
72 , textRunAroundDistanceLeft(0.0)
73 , textRunAroundDistanceTop(0.0)
74 , textRunAroundDistanceRight(0.0)
75 , textRunAroundDistanceBottom(0.0)
76 , textRunAroundThreshold(0.0)
77 , textRunAroundContour(KoShape::ContourFull)
78 , paintOrder(defaultPaintOrder())
79 , inheritPaintOrder(true)
80{ }
81
83 : QSharedData()
84 , size(rhs.size)
85 , shapeId(rhs.shapeId)
86 , name(rhs.name)
87 , localMatrix(rhs.localMatrix)
88 , userData(rhs.userData ? rhs.userData->clone() : 0)
89 , stroke(rhs.stroke)
90 , fill(rhs.fill)
93 , shadow(0) // WARNING: not implemented in Krita
94 , clipPath(rhs.clipPath ? rhs.clipPath->clone() : 0)
95 , clipMask(rhs.clipMask ? rhs.clipMask->clone() : 0)
96 , additionalAttributes(rhs.additionalAttributes)
97 , additionalStyleAttributes(rhs.additionalStyleAttributes)
98 , filterEffectStack(0) // WARNING: not implemented in Krita
100 , hyperLink(rhs.hyperLink)
101
102 , zIndex(rhs.zIndex)
104 , visible(rhs.visible)
105 , printable(rhs.visible)
106 , geometryProtected(rhs.geometryProtected)
107 , keepAspect(rhs.keepAspect)
108 , selectable(rhs.selectable)
109 , protectContent(rhs.protectContent)
110
118
121{
122}
123
125{
126 if (shadow && !shadow->deref())
127 delete shadow;
129 delete filterEffectStack;
130}
131
133{
134 if (d->parent)
135 d->parent->model()->childChanged(this, type);
136
137 this->shapeChanged(type);
138
139 Q_FOREACH (KoShape * shape, d->dependees) {
140 shape->shapeChanged(type, this);
141 }
142
143 Q_FOREACH (KoShape::ShapeChangeListener *listener, d->listeners) {
144 listener->notifyShapeChangedImpl(type, this);
145 }
146}
147
149{
150 d->shapeManagers.insert(manager);
151}
152
154{
155 d->shapeManagers.remove(manager);
156}
157
158// ======== KoShape
159
160const qint16 KoShape::maxZIndex = std::numeric_limits<qint16>::max();
161const qint16 KoShape::minZIndex = std::numeric_limits<qint16>::min();
162
164 : d(new Private()),
165 s(new SharedData)
166{
168}
169
171 : d(new Private()),
172 s(rhs.s)
173{
174}
175
177{
179 d->listeners.clear();
188 KIS_SAFE_ASSERT_RECOVER (!d->parent) {
189 d->parent->removeShape(this);
190 }
191
192 KIS_SAFE_ASSERT_RECOVER (d->shapeManagers.isEmpty()) {
193 Q_FOREACH (KoShapeManager *manager, d->shapeManagers) {
194 manager->shapeInterface()->notifyShapeDestructed(this);
195 }
196 d->shapeManagers.clear();
197 }
198}
199
201{
202 KIS_SAFE_ASSERT_RECOVER_NOOP(0 && "not implemented!");
203 qWarning() << shapeId() << "cannot be cloned";
204 return 0;
205}
206
208{
209 KoShape *clonedShape = this->cloneShape();
210
215 KoShape *oldParentShape = this->parent();
216 if (oldParentShape && !oldParentShape->absoluteTransformation().isIdentity()) {
217 clonedShape->applyAbsoluteTransformation(oldParentShape->absoluteTransformation());
218 }
219
220 return clonedShape;
221}
222
223void KoShape::paintStroke(QPainter &painter) const
224{
225 if (stroke()) {
226 stroke()->paint(this, painter);
227 }
228}
229
230void KoShape::paintMarkers(QPainter &painter) const
231{
232 if (stroke()) {
233 stroke()->paintMarkers(this, painter);
234 }
235}
236
237void KoShape::scale(qreal sx, qreal sy)
238{
239 QPointF pos = position();
240 QTransform scaleMatrix;
241 scaleMatrix.translate(pos.x(), pos.y());
242 scaleMatrix.scale(sx, sy);
243 scaleMatrix.translate(-pos.x(), -pos.y());
244 s->localMatrix = s->localMatrix * scaleMatrix;
245
248}
249
250void KoShape::rotate(qreal angle)
251{
252 QPointF center = s->localMatrix.map(QPointF(0.5 * size().width(), 0.5 * size().height()));
253 QTransform rotateMatrix;
254 rotateMatrix.translate(center.x(), center.y());
255 rotateMatrix.rotate(angle);
256 rotateMatrix.translate(-center.x(), -center.y());
257 s->localMatrix = s->localMatrix * rotateMatrix;
258
261}
262
263void KoShape::shear(qreal sx, qreal sy)
264{
265 QPointF pos = position();
266 QTransform shearMatrix;
267 shearMatrix.translate(pos.x(), pos.y());
268 shearMatrix.shear(sx, sy);
269 shearMatrix.translate(-pos.x(), -pos.y());
270 s->localMatrix = s->localMatrix * shearMatrix;
271
274}
275
276void KoShape::setSize(const QSizeF &newSize)
277{
278 QSizeF oldSize(size());
279
280 // always set size, as d->size and size() may vary
281 setSizeImpl(newSize);
282
283 if (oldSize == newSize)
284 return;
285
288}
289
290void KoShape::setSizeImpl(const QSizeF &size) const
291{
292 s->size = size;
293}
294
295void KoShape::setPosition(const QPointF &newPosition)
296{
297 QPointF currentPos = position();
298 if (newPosition == currentPos)
299 return;
300 QTransform translateMatrix;
301 translateMatrix.translate(newPosition.x() - currentPos.x(), newPosition.y() - currentPos.y());
302 s->localMatrix = s->localMatrix * translateMatrix;
303
306}
307
308bool KoShape::hitTest(const QPointF &position) const
309{
310 if (d->parent && d->parent->isClipped(this) && !d->parent->hitTest(position))
311 return false;
312
313 QPointF point = absoluteTransformation().inverted().map(position);
314 QRectF bb = outlineRect();
315
316 if (s->stroke) {
317 KoInsets insets;
318 s->stroke->strokeInsets(this, insets);
319 bb.adjust(-insets.left, -insets.top, insets.right, insets.bottom);
320 }
321 if (bb.contains(point))
322 return true;
323
324 // if there is no shadow we can as well just leave
325 if (! s->shadow)
326 return false;
327
328 // the shadow has an offset to the shape, so we simply
329 // check if the position minus the shadow offset hits the shape
330 point = absoluteTransformation().inverted().map(position - s->shadow->offset());
331
332 return bb.contains(point);
333}
334
336{
337
338 QTransform transform = absoluteTransformation();
339 QRectF bb = outlineRect();
340 if (s->stroke) {
341 KoInsets insets;
342 s->stroke->strokeInsets(this, insets);
343 bb.adjust(-insets.left, -insets.top, insets.right, insets.bottom);
344 }
345 bb = transform.mapRect(bb);
346 if (s->shadow) {
347 KoInsets insets;
348 s->shadow->insets(insets);
349 bb.adjust(-insets.left, -insets.top, insets.right, insets.bottom);
350 }
351 if (s->filterEffectStack) {
352 QRectF clipRect = s->filterEffectStack->clipRectForBoundingRect(outlineRect());
353 bb |= transform.mapRect(clipRect);
354 }
355
356 return bb;
357}
358
360{
361 QRectF boundingRect;
362 Q_FOREACH (KoShape *shape, shapes) {
363 boundingRect |= shape->boundingRect();
364 }
365 return boundingRect;
366}
367
369{
370 return absoluteTransformation().map(outline()).boundingRect();
371}
372
374{
375 QRectF absoluteOutlineRect;
376 Q_FOREACH (KoShape *shape, shapes) {
378 }
379 return absoluteOutlineRect;
380}
381
383{
384 QTransform matrix;
385 // apply parents matrix to inherit any transformations done there.
386 KoShapeContainer * container = d->parent;
387 if (container) {
388 if (container->inheritsTransform(this)) {
389 matrix = container->absoluteTransformation();
390 } else {
391 QSizeF containerSize = container->size();
392 QPointF containerPos = container->absolutePosition() - QPointF(0.5 * containerSize.width(), 0.5 * containerSize.height());
393 matrix.translate(containerPos.x(), containerPos.y());
394 }
395 }
396
397 return s->localMatrix * matrix;
398}
399
400void KoShape::applyAbsoluteTransformation(const QTransform &matrix)
401{
402 QTransform globalMatrix = absoluteTransformation();
403 // the transformation is relative to the global coordinate system
404 // but we want to change the local matrix, so convert the matrix
405 // to be relative to the local coordinate system
406 QTransform transformMatrix = globalMatrix * matrix * globalMatrix.inverted();
407 applyTransformation(transformMatrix);
408}
409
410void KoShape::applyTransformation(const QTransform &matrix)
411{
412 s->localMatrix = matrix * s->localMatrix;
415}
416
417void KoShape::setTransformation(const QTransform &matrix)
418{
419 s->localMatrix = matrix;
422}
423
424QTransform KoShape::transformation() const
425{
426 return s->localMatrix;
427}
428
433
435{
454 if (s1 == s2) return false;
455
456
457 // First sort according to runThrough which is sort of a master level
458 KoShape *parentShapeS1 = s1->parent();
459 KoShape *parentShapeS2 = s2->parent();
460 int runThrough1 = s1->runThrough();
461 int runThrough2 = s2->runThrough();
462 while (parentShapeS1) {
463 if (parentShapeS1->childZOrderPolicy() == KoShape::ChildZParentChild) {
464 runThrough1 = parentShapeS1->runThrough();
465 } else {
466 runThrough1 = runThrough1 + parentShapeS1->runThrough();
467 }
468 parentShapeS1 = parentShapeS1->parent();
469 }
470
471 while (parentShapeS2) {
472 if (parentShapeS2->childZOrderPolicy() == KoShape::ChildZParentChild) {
473 runThrough2 = parentShapeS2->runThrough();
474 } else {
475 runThrough2 = runThrough2 + parentShapeS2->runThrough();
476 }
477 parentShapeS2 = parentShapeS2->parent();
478 }
479
480 if (runThrough1 > runThrough2) {
481 return false;
482 }
483 if (runThrough1 < runThrough2) {
484 return true;
485 }
486
487 // If on the same runThrough level then the zIndex is all that matters.
488 //
489 // We basically walk up through the parents until we find a common base parent
490 // To do that we need two loops where the inner loop walks up through the parents
491 // of s2 every time we step up one parent level on s1
492 //
493 // We don't update the index value until after we have seen that it's not a common base
494 // That way we ensure that two children of a common base are sorted according to their respective
495 // z value
496 bool foundCommonParent = false;
497 int index1 = s1->zIndex();
498 int index2 = s2->zIndex();
499 parentShapeS1 = s1;
500 parentShapeS2 = s2;
501 while (parentShapeS1 && !foundCommonParent) {
502 parentShapeS2 = s2;
503 index2 = parentShapeS2->zIndex();
504 while (parentShapeS2) {
505 if (parentShapeS2 == parentShapeS1) {
506 foundCommonParent = true;
507 break;
508 }
509 if (parentShapeS2->childZOrderPolicy() == KoShape::ChildZParentChild) {
510 index2 = parentShapeS2->zIndex();
511 }
512 parentShapeS2 = parentShapeS2->parent();
513 }
514
515 if (!foundCommonParent) {
516 if (parentShapeS1->childZOrderPolicy() == KoShape::ChildZParentChild) {
517 index1 = parentShapeS1->zIndex();
518 }
519 parentShapeS1 = parentShapeS1->parent();
520 }
521 }
522
523 // If the one shape is a parent/child of the other then sort so.
524 if (s1 == parentShapeS2) {
525 return true;
526 }
527 if (s2 == parentShapeS1) {
528 return false;
529 }
530
531 // If we went that far then the z-Index is used for sorting.
532 return index1 < index2;
533}
534
536{
537
538 if (d->parent == parent) {
539 return;
540 }
541
542 if (d->parent) {
544 d->parent = 0;
545 }
546
547
549
550 if (parent && parent != this) {
551 d->parent = parent;
553 }
554
557}
558
559bool KoShape::inheritsTransformFromAny(const QList<KoShape *> ancestorsInQuestion) const
560{
561 bool result = false;
562
563 KoShape *shape = const_cast<KoShape*>(this);
564 while (shape) {
565 KoShapeContainer *parent = shape->parent();
566 if (parent && !parent->inheritsTransform(shape)) {
567 break;
568 }
569
570 if (ancestorsInQuestion.contains(shape)) {
571 result = true;
572 break;
573 }
574
575 shape = parent;
576 }
577
578 return result;
579}
580
581bool KoShape::hasCommonParent(const KoShape *shape) const
582{
583 const KoShape *thisShape = this;
584 while (thisShape) {
585
586 const KoShape *otherShape = shape;
587 while (otherShape) {
588 if (thisShape == otherShape) {
589 return true;
590 }
591 otherShape = otherShape->parent();
592 }
593
594 thisShape = thisShape->parent();
595 }
596
597 return false;
598}
599
600qint16 KoShape::zIndex() const
601{
602 return s->zIndex;
603}
604
605void KoShape::update() const
606{
607
608 if (!d->shapeManagers.empty()) {
609 const QRectF rect(boundingRect());
610 Q_FOREACH (KoShapeManager * manager, d->shapeManagers) {
611 manager->update(rect, this, true);
612 }
613 }
614}
615
616void KoShape::updateAbsolute(const QRectF &rect) const
617{
618 if (rect.isEmpty() && !rect.isNull()) {
619 return;
620 }
621
622
623 if (!d->shapeManagers.empty() && isVisible()) {
624 Q_FOREACH (KoShapeManager *manager, d->shapeManagers) {
625 manager->update(rect);
626 }
627 }
628}
629
630QPainterPath KoShape::outline() const
631{
632 QPainterPath path;
633 path.addRect(outlineRect());
634 return path;
635}
636
638{
639 const QSizeF s = size();
640 return QRectF(QPointF(0, 0), QSizeF(qMax(s.width(), qreal(0.0001)),
641 qMax(s.height(), qreal(0.0001))));
643
644QPainterPath KoShape::shadowOutline() const
645{
646 if (background()) {
647 return outline();
648 }
649
650 return QPainterPath();
651}
652
654{
655 const QRectF rc = outlineRect();
656
657 QPointF point = rc.topLeft();
658
659 bool valid = false;
660 QPointF anchoredPoint = KoFlake::anchorToPoint(anchor, rc, &valid);
661 if (valid) {
662 point = anchoredPoint;
663 }
664
665 return absoluteTransformation().map(point);
666}
667
668void KoShape::setAbsolutePosition(const QPointF &newPosition, KoFlake::AnchorPosition anchor)
669{
670 QPointF currentAbsPosition = absolutePosition(anchor);
671 QPointF translate = newPosition - currentAbsPosition;
672 QTransform translateMatrix;
673 translateMatrix.translate(translate.x(), translate.y());
674 applyAbsoluteTransformation(translateMatrix);
677}
678
680{
681 s->size = shape->size();
682 s->zIndex = shape->zIndex();
683 s->visible = shape->isVisible(false);
684
685 // Ensure printable is true by default
686 if (!s->visible)
687 s->printable = true;
688 else
689 s->printable = shape->isPrintable();
690
691 s->geometryProtected = shape->isGeometryProtected();
692 s->protectContent = shape->isContentProtected();
693 s->selectable = shape->isSelectable();
694 s->keepAspect = shape->keepAspectRatio();
695 s->localMatrix = shape->s->localMatrix;
696}
697
699{
700 Q_FOREACH (KoShapeManager * manager, d->shapeManagers) {
701 manager->notifyShapeChanged(this);
702 }
703}
704
706{
707 s->userData.reset(userData);
708}
709
711{
712 return s->userData.data();
713}
714
716{
718
719 return !bg || bg->hasTransparency() || s->transparency > 0.0;
720}
721
722void KoShape::setTransparency(qreal transparency)
723{
724 s->transparency = qBound<qreal>(0.0, transparency, 1.0);
725
728}
729
730qreal KoShape::transparency(bool recursive) const
731{
732 if (!recursive || !parent()) {
733 return s->transparency;
734 } else {
735 const qreal parentOpacity = 1.0-parent()->transparency(recursive);
736 const qreal childOpacity = 1.0-s->transparency;
737 return 1.0-(parentOpacity*childOpacity);
738 }
739}
740
742{
743 KoInsets answer;
744 if (s->stroke)
745 s->stroke->strokeInsets(this, answer);
746 return answer;
747}
748
750{
751 KIS_SAFE_ASSERT_RECOVER_RETURN(first != second);
753
754 if (first != Fill) {
755 if (order.at(1) == first) {
756 order[1] = order[0];
757 order[0] = first;
758 } else if (order.at(2) == first) {
759 order[2] = order[0];
760 order[0] = first;
761 }
762 }
763 if (second != first && second != Stroke) {
764 if (order.at(2) == second) {
765 order[2] = order[1];
766 order[1] = second;
767 }
768 }
769 s->inheritPaintOrder = false;
770 s->paintOrder = order;
771}
772
774{
776 if (!s->inheritPaintOrder) {
777 order = s->paintOrder;
778 } else if (parent()) {
779 order = parent()->paintOrder();
780 }
781 return order;
782}
783
789
791{
792 s->inheritPaintOrder = value;
793}
794
796{
797 return s->inheritPaintOrder;
798}
799
800qreal KoShape::rotation() const
801{
802 // try to extract the rotation angle out of the local matrix
803 // if it is a pure rotation matrix
804
805 // check if the matrix has shearing mixed in
806 if (fabs(fabs(s->localMatrix.m12()) - fabs(s->localMatrix.m21())) > 1e-10)
807 return std::numeric_limits<qreal>::quiet_NaN();
808 // check if the matrix has scaling mixed in
809 if (fabs(s->localMatrix.m11() - s->localMatrix.m22()) > 1e-10)
810 return std::numeric_limits<qreal>::quiet_NaN();
811
812 // calculate the angle from the matrix elements
813 qreal angle = atan2(-s->localMatrix.m21(), s->localMatrix.m11()) * 180.0 / M_PI;
814 if (angle < 0.0)
815 angle += 360.0;
816
817 return angle;
818}
819
820QSizeF KoShape::size() const
821{
822 return s->size;
823}
824
825QPointF KoShape::position() const
826{
827 QPointF center = outlineRect().center();
828 return s->localMatrix.map(center) - center;
829}
830
832{
833 return s->textRunAroundSide;
834}
835
837{
838
839 if (side == RunThrough) {
840 if (runThrough == Background) {
841 setRunThrough(-1);
842 } else {
843 setRunThrough(1);
844 }
845 } else {
846 setRunThrough(0);
847 }
848
849 if ( s->textRunAroundSide == side) {
850 return;
851 }
852
853 s->textRunAroundSide = side;
856}
857
859{
860 return s->textRunAroundDistanceTop;
861}
862
864{
865 s->textRunAroundDistanceTop = distance;
866}
867
869{
870 return s->textRunAroundDistanceLeft;
871}
872
874{
875 s->textRunAroundDistanceLeft = distance;
876}
877
879{
880 return s->textRunAroundDistanceRight;
881}
882
884{
885 s->textRunAroundDistanceRight = distance;
886}
887
889{
890 return s->textRunAroundDistanceBottom;
891}
892
894{
895 s->textRunAroundDistanceBottom = distance;
896}
897
899{
900 return s->textRunAroundThreshold;
901}
902
904{
905 s->textRunAroundThreshold = threshold;
906}
907
909{
910 return s->textRunAroundContour;
911}
912
914{
915 s->textRunAroundContour = contour;
916}
917
919{
920 s->inheritBackground = false;
921 s->fill = fill;
924}
925
927{
928
930
931 if (!s->inheritBackground) {
932 bg = s->fill;
933 } else if (parent()) {
934 bg = parent()->background();
935 }
936
937 return bg;
938}
939
941{
942
943 s->inheritBackground = value;
944 if (s->inheritBackground) {
945 s->fill.clear();
946 }
947}
948
950{
951 return s->inheritBackground;
952}
953
954void KoShape::setZIndex(qint16 zIndex)
955{
956 if (s->zIndex == zIndex)
957 return;
958 s->zIndex = zIndex;
960}
961
963{
964 return s->runThrough;
965}
966
967void KoShape::setRunThrough(short int runThrough)
968{
969 s->runThrough = runThrough;
970}
971
973{
974 int _on = (on ? 1 : 0);
975 if (s->visible == _on) return;
976 s->visible = _on;
977}
978
979bool KoShape::isVisible(bool recursive) const
980{
981 if (!recursive)
982 return s->visible;
983
984 if (!s->visible)
985 return false;
986
987 KoShapeContainer * parentShape = parent();
988
989 if (parentShape) {
990 return parentShape->isVisible(true);
991 }
992
993 return true;
994}
995
997{
998 s->printable = on;
999}
1000
1002{
1003 if (s->visible)
1004 return s->printable;
1005 else
1006 return false;
1007}
1008
1009void KoShape::setSelectable(bool selectable)
1010{
1011 s->selectable = selectable;
1012}
1013
1015{
1016 return s->selectable;
1017}
1018
1020{
1021 s->geometryProtected = on;
1022}
1023
1025{
1026 return s->geometryProtected;
1027}
1028
1030{
1031 s->protectContent = protect;
1032}
1033
1035{
1036 return s->protectContent;
1037}
1038
1040{
1041 return d->parent;
1042}
1043
1044void KoShape::setKeepAspectRatio(bool keepAspect)
1045{
1046 s->keepAspect = keepAspect;
1047
1049 notifyChanged();
1050}
1051
1053{
1054 return s->keepAspect;
1055}
1056
1057QString KoShape::shapeId() const
1058{
1059 return s->shapeId;
1060}
1061
1062void KoShape::setShapeId(const QString &id)
1063{
1064 s->shapeId = id;
1065}
1066
1068{
1069
1071
1072 if (!s->inheritStroke) {
1073 stroke = s->stroke;
1074 } else if (parent()) {
1075 stroke = parent()->stroke();
1076 }
1077
1078 return stroke;
1079}
1080
1082{
1083
1084 s->inheritStroke = false;
1085 s->stroke = stroke;
1087 notifyChanged();
1088}
1089
1091{
1092 s->inheritStroke = value;
1093 if (s->inheritStroke) {
1094 s->stroke.clear();
1095 }
1096}
1097
1099{
1100 return s->inheritStroke;
1101}
1102
1104{
1105 if (s->shadow)
1106 s->shadow->deref();
1107 s->shadow = shadow;
1108 if (s->shadow) {
1109 s->shadow->ref();
1110 // TODO update changed area
1111 }
1113 notifyChanged();
1114}
1115
1117{
1118 return s->shadow;
1119}
1120
1122{
1123 s->clipPath.reset(clipPath);
1125 notifyChanged();
1126}
1127
1129{
1130 return s->clipPath.data();
1131}
1132
1134{
1135 s->clipMask.reset(clipMask);
1137 notifyChanged();
1138}
1139
1141{
1142 return s->clipMask.data();
1143}
1144
1145QTransform KoShape::transform() const
1146{
1147 return s->localMatrix;
1148}
1149
1150QString KoShape::name() const
1151{
1152 return s->name;
1153}
1154
1155void KoShape::setName(const QString &name)
1156{
1157 s->name = name;
1158}
1159
1160void KoShape::waitUntilReady(bool asynchronous) const
1161{
1162 Q_UNUSED(asynchronous);
1163}
1164
1165bool KoShape::isShapeEditable(bool recursive) const
1166{
1167 if (!s->visible || s->geometryProtected)
1168 return false;
1169
1170 if (recursive && d->parent) {
1171 return d->parent->isShapeEditable(true);
1172 }
1173
1174 return true;
1175}
1176
1177KisHandlePainterHelper KoShape::createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius, int decorationThickness)
1178{
1179 const QTransform originalPainterTransform = painter->transform();
1180
1181 painter->setTransform(shape->absoluteTransformation() *
1182 converter.documentToView() *
1183 painter->transform());
1184
1185 // move c-tor
1186 return KisHandlePainterHelper(painter, originalPainterTransform, handleRadius, decorationThickness);
1187}
1188
1189KisHandlePainterHelper KoShape::createHandlePainterHelperDocument(QPainter *painter, KoShape *shape, qreal handleRadius, int decorationThickness)
1190{
1191 const QTransform originalPainterTransform = painter->transform();
1192
1193 painter->setTransform(shape->absoluteTransformation() *
1194 painter->transform());
1195
1196 // move c-tor
1197 return KisHandlePainterHelper(painter, originalPainterTransform, handleRadius, decorationThickness);
1198}
1199
1200
1201QPointF KoShape::shapeToDocument(const QPointF &point) const
1202{
1203 return absoluteTransformation().map(point);
1204}
1205
1206QRectF KoShape::shapeToDocument(const QRectF &rect) const
1207{
1208 return absoluteTransformation().mapRect(rect);
1209}
1210
1211QPointF KoShape::documentToShape(const QPointF &point) const
1212{
1213 return absoluteTransformation().inverted().map(point);
1214}
1215
1216QRectF KoShape::documentToShape(const QRectF &rect) const
1217{
1218 return absoluteTransformation().inverted().mapRect(rect);
1219}
1220
1222{
1223 if (! shape)
1224 return false;
1225
1226 // refuse to establish a circular dependency
1227 if (shape->hasDependee(this))
1228 return false;
1229
1230 if (! d->dependees.contains(shape))
1231 d->dependees.append(shape);
1232
1233 return true;
1234}
1235
1237{
1238 int index = d->dependees.indexOf(shape);
1239 if (index >= 0)
1240 d->dependees.removeAt(index);
1241}
1242
1244{
1245 return d->dependees.contains(shape);
1246}
1247
1249{
1250 return d->dependees;
1251}
1252
1254{
1255 Q_UNUSED(type);
1256 Q_UNUSED(shape);
1257}
1258
1260{
1261 return KoSnapData();
1262}
1263
1264void KoShape::setAdditionalAttribute(const QString &name, const QString &value)
1265{
1266 s->additionalAttributes.insert(name, value);
1267}
1268
1269void KoShape::removeAdditionalAttribute(const QString &name)
1270{
1271 s->additionalAttributes.remove(name);
1272}
1273
1274bool KoShape::hasAdditionalAttribute(const QString &name) const
1275{
1276 return s->additionalAttributes.contains(name);
1277}
1278
1279QString KoShape::additionalAttribute(const QString &name) const
1280{
1281 return s->additionalAttributes.value(name);
1282}
1283
1284void KoShape::setAdditionalStyleAttribute(const char *name, const QString &value)
1285{
1286 s->additionalStyleAttributes.insert(name, value);
1287}
1288
1290{
1291 s->additionalStyleAttributes.remove(name);
1292}
1293
1295{
1296 return s->filterEffectStack;
1297}
1298
1300{
1301 if (s->filterEffectStack)
1302 s->filterEffectStack->deref();
1303 s->filterEffectStack = filterEffectStack;
1304 if (s->filterEffectStack) {
1305 s->filterEffectStack->ref();
1306 }
1307 notifyChanged();
1308}
1309
1310QSet<KoShape*> KoShape::toolDelegates() const
1311{
1312 return d->toolDelegates;
1313}
1314
1315void KoShape::setToolDelegates(const QSet<KoShape*> &delegates)
1316{
1317 d->toolDelegates = delegates;
1318}
1319
1320QString KoShape::hyperLink () const
1321{
1322 return s->hyperLink;
1323}
1324
1325void KoShape::setHyperLink(const QString &hyperLink)
1326{
1327 s->hyperLink = hyperLink;
1328}
1329
1331{
1332 Q_FOREACH(KoShape *shape, m_registeredShapes) {
1333 shape->removeShapeChangeListener(this);
1334 }
1335}
1336
1338{
1339 KIS_SAFE_ASSERT_RECOVER_RETURN(!m_registeredShapes.contains(shape));
1340 m_registeredShapes.append(shape);
1341}
1342
1344{
1345 KIS_SAFE_ASSERT_RECOVER_RETURN(m_registeredShapes.contains(shape));
1346 m_registeredShapes.removeAll(shape);
1347}
1348
1350{
1351 KIS_SAFE_ASSERT_RECOVER_RETURN(m_registeredShapes.contains(shape));
1352
1353 notifyShapeChanged(type, shape);
1354
1355 if (type == KoShape::Deleted) {
1356 unregisterShape(shape);
1357 }
1358}
1359
1361{
1362
1363 KIS_SAFE_ASSERT_RECOVER_RETURN(!d->listeners.contains(listener));
1364 listener->registerShape(this);
1365 d->listeners.append(listener);
1366}
1367
1369{
1370
1371 KIS_SAFE_ASSERT_RECOVER_RETURN(d->listeners.contains(listener));
1372 d->listeners.removeAll(listener);
1373 listener->unregisterShape(this);
1374}
1375
1377{
1378 return d->listeners;
1379}
1380
1382{
1383 QList<KoShape *> result;
1384
1385 Q_FOREACH (KoShape *shape, shapes) {
1386 result << shape;
1387
1388 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(shape);
1389 if (container) {
1390 result << linearizeSubtree(container->shapes());
1391 }
1392 }
1393
1394 return result;
1395}
1396
1398{
1399 QList<KoShape*> sortedShapes = shapes;
1400 std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
1401
1402 QList<KoShape *> result;
1403
1404 Q_FOREACH (KoShape *shape, sortedShapes) {
1405 result << shape;
1406
1407 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(shape);
1408 if (container) {
1409 result << linearizeSubtreeSorted(container->shapes());
1410 }
1411 }
1412
1413 return result;
1414}
1415
1416void KoShape::setResolution(qreal /*xRes*/, qreal /*yRes*/)
1417{
1418}
float value(const T *src, size_t ch)
QPointF s1
QPointF s2
qreal distance(const QPointF &p1, const QPointF &p2)
The KisHandlePainterHelper class is a special helper for painting handles around objects....
Clip path used to clip shapes.
QPainterPath clipPath
the compiled clip path in shape coordinates of the clipped shape
This class manages a stack of filter effects.
KoShapeContainer::ShapeInterface shapeInterface
QList< KoShape * > shapes() const
bool inheritsTransform(const KoShape *shape) const
KoShapeManager::ShapeInterface shapeInterface
void update(const QRectF &rect, const KoShape *shape=0, bool selectionHandles=false)
void notifyShapeChanged(KoShape *shape)
virtual ~SharedData()
Definition KoShape.cpp:124
void setToolDelegates(const QSet< KoShape * > &delegates)
Definition KoShape.cpp:1315
virtual void setPaintOrder(PaintOrder first, PaintOrder second)
setPaintOrder set the paint order. As there's only three entries in any given paintorder,...
Definition KoShape.cpp:749
KoShapeUserData * userData() const
Definition KoShape.cpp:710
void setTextRunAroundContour(TextRunAroundContour contour)
Definition KoShape.cpp:913
QScopedPointer< Private > d
Definition KoShape.h:1135
virtual void paintStroke(QPainter &painter) const
paintStroke paints the shape's stroked outline
Definition KoShape.cpp:223
bool isContentProtected() const
Definition KoShape.cpp:1034
virtual QSizeF size() const
Get the size of the shape in pt.
Definition KoShape.cpp:820
void setHyperLink(const QString &hyperLink)
Definition KoShape.cpp:1325
TextRunAroundContour textRunAroundContour() const
Definition KoShape.cpp:908
void setName(const QString &name)
Definition KoShape.cpp:1155
virtual QRectF outlineRect() const
Definition KoShape.cpp:637
bool hasCommonParent(const KoShape *shape) const
Definition KoShape.cpp:581
static const qint16 minZIndex
Definition KoShape.h:507
void setContentProtected(bool protect)
Definition KoShape.cpp:1029
void setTextRunAroundDistanceLeft(qreal distance)
Definition KoShape.cpp:873
void addShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1360
void setInheritBackground(bool value)
setInheritBackground marks a shape as inheriting the background from the parent shape....
Definition KoShape.cpp:940
int runThrough() const
Definition KoShape.cpp:962
void setZIndex(qint16 zIndex)
Definition KoShape.cpp:954
QString shapeId() const
Definition KoShape.cpp:1057
void setTextRunAroundDistanceRight(qreal distance)
Definition KoShape.cpp:883
virtual QPainterPath outline() const
Definition KoShape.cpp:630
KoShapeAnchor * anchor() const
virtual QVector< PaintOrder > paintOrder() const
paintOrder
Definition KoShape.cpp:773
qreal rotation() const
Definition KoShape.cpp:800
KoShape * cloneShapeAndBakeAbsoluteTransform() const
creates a deep copy of the shape/shapes tree and bakes the absolute transform of this into the result...
Definition KoShape.cpp:207
void rotate(qreal angle)
Rotate the shape (relative)
Definition KoShape.cpp:250
virtual KoSnapData snapData() const
Returns additional snap data the shape wants to have snapping to.
Definition KoShape.cpp:1259
void setKeepAspectRatio(bool keepAspect)
Definition KoShape.cpp:1044
void setTextRunAroundDistanceTop(qreal distance)
Definition KoShape.cpp:863
void setTextRunAroundSide(TextRunAroundSide side, RunThroughLevel runThrough=Background)
Definition KoShape.cpp:836
KoShape()
Constructor.
Definition KoShape.cpp:163
bool isSelectable() const
Definition KoShape.cpp:1014
QPointF shapeToDocument(const QPointF &point) const
Transforms point from shape coordinates to document coordinates.
Definition KoShape.cpp:1201
QPointF absolutePosition(KoFlake::AnchorPosition anchor=KoFlake::Center) const
Definition KoShape.cpp:653
void removeShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1368
void setClipMask(KoClipMask *clipMask)
Sets a new clip mask, removing the old one. The mask is owned by the shape.
Definition KoShape.cpp:1133
void setShadow(KoShapeShadow *shadow)
Sets the new shadow, removing the old one.
Definition KoShape.cpp:1103
virtual bool isShapeEditable(bool recursive=true) const
checks recursively if the shape or one of its parents is not visible or locked
Definition KoShape.cpp:1165
void addShapeManager(KoShapeManager *manager)
Definition KoShape.cpp:148
void setTransparency(qreal transparency)
Definition KoShape.cpp:722
static QVector< PaintOrder > defaultPaintOrder()
default paint order as per SVG specification
Definition KoShape.cpp:784
void setFilterEffectStack(KoFilterEffectStack *filterEffectStack)
Sets the new filter effect stack, removing the old one.
Definition KoShape.cpp:1299
QList< KoShape * > dependees() const
Returns list of shapes depending on this shape.
Definition KoShape.cpp:1248
virtual KoShapeStrokeModelSP stroke() const
Definition KoShape.cpp:1067
void applyAbsoluteTransformation(const QTransform &matrix)
Definition KoShape.cpp:400
virtual void setResolution(qreal xRes, qreal yRes)
Definition KoShape.cpp:1416
static bool compareShapeZIndex(KoShape *s1, KoShape *s2)
Definition KoShape.cpp:434
void setSizeImpl(const QSizeF &size) const
Definition KoShape.cpp:290
void setPrintable(bool on)
Definition KoShape.cpp:996
void copySettings(const KoShape *shape)
Definition KoShape.cpp:679
void setTextRunAroundDistanceBottom(qreal distance)
Definition KoShape.cpp:893
void removeAdditionalStyleAttribute(const char *name)
Definition KoShape.cpp:1289
bool isGeometryProtected() const
Definition KoShape.cpp:1024
QString hyperLink() const
Definition KoShape.cpp:1320
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1211
QSet< KoShape * > toolDelegates() const
Definition KoShape.cpp:1310
void shear(qreal sx, qreal sy)
Shear the shape The shape will be sheared using the zero-point which is the top-left corner.
Definition KoShape.cpp:263
QList< ShapeChangeListener * > listeners() const
Definition KoShape.cpp:1376
KoInsets strokeInsets() const
Definition KoShape.cpp:741
virtual QRectF boundingRect() const
Get the bounding box of the shape.
Definition KoShape.cpp:335
KoClipPath * clipPath() const
Returns the currently set clip path or 0 if there is no clip path set.
Definition KoShape.cpp:1128
void setSelectable(bool selectable)
Definition KoShape.cpp:1009
virtual void update() const
Definition KoShape.cpp:605
void applyTransformation(const QTransform &matrix)
Definition KoShape.cpp:410
QRectF absoluteOutlineRect() const
Definition KoShape.cpp:368
virtual void shapeChanged(ChangeType type, KoShape *shape=0)
Definition KoShape.cpp:1253
KoShapeContainer * parent() const
Definition KoShape.cpp:1039
bool inheritStroke() const
inheritStroke shows if the shape inherits the stroke from its parent
Definition KoShape.cpp:1098
void removeShapeManager(KoShapeManager *manager)
Definition KoShape.cpp:153
void shapeChangedPriv(KoShape::ChangeType type)
Definition KoShape.cpp:132
ChildZOrderPolicy
Used by compareShapeZIndex() to order shapes.
Definition KoShape.h:656
@ ChildZDefault
Definition KoShape.h:657
@ ChildZParentChild
normal parent/child ordering
Definition KoShape.h:658
qreal textRunAroundDistanceTop() const
Definition KoShape.cpp:858
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:1081
bool inheritBackground() const
inheritBackground shows if the shape inherits background from its parent
Definition KoShape.cpp:949
static QList< KoShape * > linearizeSubtreeSorted(const QList< KoShape * > &shapes)
Definition KoShape.cpp:1397
void setAdditionalAttribute(const QString &name, const QString &value)
Definition KoShape.cpp:1264
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
virtual void paintMarkers(QPainter &painter) const
paintStroke paints the shape's markers
Definition KoShape.cpp:230
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:417
static KisHandlePainterHelper createHandlePainterHelperDocument(QPainter *painter, KoShape *shape, qreal handleRadius, int decorationThickness)
Definition KoShape.cpp:1189
TextRunAroundContour
The behavior text should do when intersecting this shape.
Definition KoShape.h:131
KoShapeShadow * shadow() const
Returns the currently set shadow or 0 if there is no shadow set.
Definition KoShape.cpp:1116
virtual void setBackground(QSharedPointer< KoShapeBackground > background)
Definition KoShape.cpp:918
void setClipPath(KoClipPath *clipPath)
Sets a new clip path, removing the old one.
Definition KoShape.cpp:1121
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:1177
bool hasAdditionalAttribute(const QString &name) const
Definition KoShape.cpp:1274
KoClipMask * clipMask() const
Returns the currently set clip mask or 0 if there is no clip mask set.
Definition KoShape.cpp:1140
static QList< KoShape * > linearizeSubtree(const QList< KoShape * > &shapes)
Definition KoShape.cpp:1381
RunThroughLevel
Definition KoShape.h:140
@ Background
Definition KoShape.h:141
TextRunAroundSide
The behavior text should do when intersecting this shape.
Definition KoShape.h:120
@ RunThrough
The text will completely ignore the frame and layout as if it was not there.
Definition KoShape.h:127
ChangeType
Used by shapeChanged() to select which change was made.
Definition KoShape.h:95
@ RotationChanged
used after a setRotation()
Definition KoShape.h:97
@ StrokeChanged
the shapes stroke has changed
Definition KoShape.h:105
@ PositionChanged
used after a setPosition()
Definition KoShape.h:96
@ TransparencyChanged
the shapetransparency value has changed
Definition KoShape.h:116
@ Deleted
the shape was deleted
Definition KoShape.h:104
@ ClipPathChanged
the shapes clip path has changed
Definition KoShape.h:114
@ TextRunAroundChanged
used after a setTextRunAroundSide()
Definition KoShape.h:111
@ ShearChanged
used after a shear()
Definition KoShape.h:99
@ ParentChanged
used after a setParent()
Definition KoShape.h:103
@ ClipMaskChanged
the shapes clip path has changed
Definition KoShape.h:115
@ ShadowChanged
the shapes shadow has changed
Definition KoShape.h:107
@ BackgroundChanged
the shapes background has changed
Definition KoShape.h:106
@ ScaleChanged
used after a scale()
Definition KoShape.h:98
@ KeepAspectRatioChange
used after setKeepAspectRatio()
Definition KoShape.h:102
@ SizeChanged
used after a setSize()
Definition KoShape.h:100
@ GenericMatrixChange
used after the matrix was changed without knowing which property explicitly changed
Definition KoShape.h:101
virtual KoShape * cloneShape() const
creates a deep copy of the shape or shape's subtree
Definition KoShape.cpp:200
qreal textRunAroundDistanceRight() const
Definition KoShape.cpp:878
bool isPrintable() const
Definition KoShape.cpp:1001
void scale(qreal sx, qreal sy)
Scale the shape using the zero-point which is the top-left corner.
Definition KoShape.cpp:237
void setUserData(KoShapeUserData *userData)
Definition KoShape.cpp:705
virtual QSharedPointer< KoShapeBackground > background() const
Definition KoShape.cpp:926
virtual ChildZOrderPolicy childZOrderPolicy()
Definition KoShape.cpp:429
QString additionalAttribute(const QString &name) const
Definition KoShape.cpp:1279
virtual bool hasTransparency() const
Definition KoShape.cpp:715
void removeDependee(KoShape *shape)
Definition KoShape.cpp:1236
QTransform transformation() const
Returns the shapes local transformation matrix.
Definition KoShape.cpp:424
KoFilterEffectStack * filterEffectStack() const
Definition KoShape.cpp:1294
bool inheritPaintOrder() const
inheritPaintOrder
Definition KoShape.cpp:795
virtual void setPosition(const QPointF &position)
Set the position of the shape in pt.
Definition KoShape.cpp:295
bool keepAspectRatio() const
Definition KoShape.cpp:1052
virtual void updateAbsolute(const QRectF &rect) const
Definition KoShape.cpp:616
bool inheritsTransformFromAny(const QList< KoShape * > ancestorsInQuestion) const
inheritsTransformFromAny checks if the shape inherits transformation from any of the shapes listed in...
Definition KoShape.cpp:559
qreal textRunAroundDistanceBottom() const
Definition KoShape.cpp:888
void setInheritStroke(bool value)
setInheritStroke marks a shape as inheriting the stroke from the parent shape. NOTE: The currently se...
Definition KoShape.cpp:1090
@ Stroke
Definition KoShape.h:147
@ Markers
Definition KoShape.h:148
void setGeometryProtected(bool on)
Definition KoShape.cpp:1019
virtual void setRunThrough(short int runThrough)
Definition KoShape.cpp:967
QSharedDataPointer< SharedData > s
Definition KoShape.h:1138
void setVisible(bool on)
Definition KoShape.cpp:972
qreal textRunAroundThreshold() const
Definition KoShape.cpp:898
virtual QPainterPath shadowOutline() const
Definition KoShape.cpp:644
void notifyChanged()
Definition KoShape.cpp:698
void setParent(KoShapeContainer *parent)
Definition KoShape.cpp:535
TextRunAroundSide textRunAroundSide() const
Definition KoShape.cpp:831
bool addDependee(KoShape *shape)
Definition KoShape.cpp:1221
virtual bool hitTest(const QPointF &position) const
Check if the shape is hit on position.
Definition KoShape.cpp:308
virtual ~KoShape()
Destructor.
Definition KoShape.cpp:176
void setShapeId(const QString &id)
Definition KoShape.cpp:1062
qint16 zIndex() const
Definition KoShape.cpp:600
void removeAdditionalAttribute(const QString &name)
Definition KoShape.cpp:1269
void setAdditionalStyleAttribute(const char *name, const QString &value)
Definition KoShape.cpp:1284
qreal textRunAroundDistanceLeft() const
Definition KoShape.cpp:868
QTransform transform() const
return the current matrix that contains the rotation/scale/position of this shape
Definition KoShape.cpp:1145
void setInheritPaintOrder(bool value)
setInheritPaintOrder set inherit paint order.
Definition KoShape.cpp:790
QString name() const
Definition KoShape.cpp:1150
bool hasDependee(KoShape *shape) const
Returns if the given shape is dependent on this shape.
Definition KoShape.cpp:1243
void setAbsolutePosition(const QPointF &newPosition, KoFlake::AnchorPosition anchor=KoFlake::Center)
Definition KoShape.cpp:668
static const qint16 maxZIndex
Definition KoShape.h:502
void setTextRunAroundThreshold(qreal threshold)
Definition KoShape.cpp:903
bool isVisible(bool recursive=true) const
Definition KoShape.cpp:979
qreal transparency(bool recursive=false) const
Definition KoShape.cpp:730
virtual void setSize(const QSizeF &size)
Resize the shape.
Definition KoShape.cpp:276
QPointF position() const
Get the position of the shape in pt.
Definition KoShape.cpp:825
virtual void waitUntilReady(bool asynchronous=true) const
Definition KoShape.cpp:1160
virtual QPointF documentToView(const QPointF &documentPoint) const
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define M_PI
Definition kis_global.h:111
AnchorPosition
Definition KoFlake.h:85
KRITAFLAKE_EXPORT QPointF anchorToPoint(AnchorPosition anchor, const QRectF rect, bool *valid=0)
Definition KoFlake.cpp:329
qreal bottom
Bottom inset.
Definition KoInsets.h:50
qreal right
Right inset.
Definition KoInsets.h:52
qreal top
Top inset.
Definition KoInsets.h:49
qreal left
Left inset.
Definition KoInsets.h:51
void notifyShapeDestructed(KoShape *shape)
QList< KoShape * > m_registeredShapes
Definition KoShape.h:1106
void unregisterShape(KoShape *shape)
Definition KoShape.cpp:1343
void registerShape(KoShape *shape)
Definition KoShape.cpp:1337
void notifyShapeChangedImpl(ChangeType type, KoShape *shape)
Definition KoShape.cpp:1349