File indexing completed on 2024-05-12 15:56:46

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2006-2008 Thorsten Zachmann <zachmann@kde.org>
0003    SPDX-FileCopyrightText: 2006, 2008 C. Boemann <cbo@boemann.dk>
0004    SPDX-FileCopyrightText: 2006-2010 Thomas Zander <zander@kde.org>
0005    SPDX-FileCopyrightText: 2007-2009, 2011 Jan Hambrecht <jaham@gmx.net>
0006 
0007    SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef KOSHAPE_H
0011 #define KOSHAPE_H
0012 
0013 #include "KoFlake.h"
0014 #include "KoFlakeTypes.h"
0015 
0016 #include <QSharedPointer>
0017 #include <QSet>
0018 #include <QMap>
0019 #include <QMetaType>
0020 #include <QSharedDataPointer>
0021 
0022 #include <QDomDocument>
0023 
0024 #include "kritaflake_export.h"
0025 
0026 class QPainter;
0027 class QRectF;
0028 class QPainterPath;
0029 class QTransform;
0030 
0031 class KoShapeContainer;
0032 class KoShapeStrokeModel;
0033 class KoShapeUserData;
0034 class KoViewConverter;
0035 class KoShapeApplicationData;
0036 class KoShapeSavingContext;
0037 class KoShapeLoadingContext;
0038 class KoShapeShadow;
0039 class KoFilterEffectStack;
0040 class KoSnapData;
0041 class KoClipPath;
0042 class KoClipMask;
0043 class KoShapeAnchor;
0044 struct KoInsets;
0045 class KoShapeBackground;
0046 class KisHandlePainterHelper;
0047 class KoShapeManager;
0048 
0049 /**
0050  * Base class for all flake shapes. Shapes extend this class
0051  * to allow themselves to be manipulated. This class just represents
0052  * a graphical shape in the document and can be manipulated by some default
0053  * tools in this library.
0054  *
0055  * Due to the limited responsibility of this class, the extending object
0056  * can have any data backend and is responsible for painting itself.
0057  *
0058  * We strongly suggest that any extending class will use a Model View
0059  * Controller (MVC) design where the View part is all in this class, as well
0060  * as the one that inherits from this one.  This allows the data that rests
0061  * in the model to be reused in different parts of the document. For example
0062  * by having two flake objects that show that same data. Or each showing a section of it.
0063  *
0064  * The KoShape data is completely in postscript-points (pt) (see KoUnit
0065  * for conversion methods to and from points).
0066  * This image will explain the real-world use of the shape and its options.
0067  * <img src="../flake_shape_coords.png" align=center><br>
0068  *  The Rotation center can be returned with absolutePosition()
0069  *
0070  * <p>Flake objects can be created in three ways:
0071  * <ul>
0072  *   <li>a simple new KoDerivedFlake(),
0073  *   <li>through an associated tool,
0074  *   <li>through a factory
0075  * </ul>
0076  *
0077  * <h1>Shape interaction notifications</h1>
0078  * We had several notification methods that allow your shape to be notified of changes in other
0079  * shapes positions or rotation etc.
0080  * <ol><li>The most general is KoShape::shapeChanged().<br>
0081  * a virtual method that you can use to check various changed to your shape made by tools or otherwise.</li>
0082  * <li>for shape hierarchies the parent may receive a notification when a child was modified.
0083  *  This is done though KoShapeContainerModel::childChanged()</li>
0084  * <li>any shape that is at a similar position as another shape there is collision detection.
0085  * You can register your shape to be sensitive to any changes like moving or whatever to
0086  * <b>other</b> shapes that intersect yours.
0087  * Such changes will then be notified to your shape using the method from (1) You should call
0088  * KoShape::setCollisionDetection(bool) to enable this.
0089  * </ol>
0090  */
0091 class KRITAFLAKE_EXPORT KoShape
0092 {
0093 public:
0094     /// Used by shapeChanged() to select which change was made
0095     enum ChangeType {
0096         PositionChanged, ///< used after a setPosition()
0097         RotationChanged, ///< used after a setRotation()
0098         ScaleChanged,   ///< used after a scale()
0099         ShearChanged,   ///< used after a shear()
0100         SizeChanged,    ///< used after a setSize()
0101         GenericMatrixChange,    ///< used after the matrix was changed without knowing which property explicitly changed
0102         KeepAspectRatioChange, ///< used after setKeepAspectRatio()
0103         ParentChanged,   ///< used after a setParent()
0104         Deleted, ///< the shape was deleted
0105         StrokeChanged, ///< the shapes stroke has changed
0106         BackgroundChanged, ///< the shapes background has changed
0107         ShadowChanged, ///< the shapes shadow has changed
0108         BorderChanged, ///< the shapes border has changed
0109         ParameterChanged, ///< the shapes parameter has changed (KoParameterShape only)
0110         ContentChanged, ///< the content of the shape changed e.g. a new image inside a pixmap/text change inside a textshape
0111         TextRunAroundChanged, ///< used after a setTextRunAroundSide()
0112         ChildChanged, ///< a child of a container was changed/removed. This is propagated to all parents
0113         ConnectionPointChanged, ///< a connection point has changed
0114         ClipPathChanged, ///< the shapes clip path has changed
0115         ClipMaskChanged, ///< the shapes clip path has changed
0116         TransparencyChanged ///< the shapetransparency value has changed
0117     };
0118 
0119     /// The behavior text should do when intersecting this shape.
0120     enum TextRunAroundSide {
0121         BiggestRunAroundSide,   ///< Run other text around the side that has the most space
0122         LeftRunAroundSide,      ///< Run other text around the left side of the frame
0123         RightRunAroundSide,     ///< Run other text around the right side of the frame
0124         EnoughRunAroundSide,      ///< Run other text dynamically around both sides of the shape, provided there is sufficient space left
0125         BothRunAroundSide,      ///< Run other text around both sides of the shape
0126         NoRunAround,            ///< The text will be completely avoiding the frame by keeping the horizontal space that this frame occupies blank.
0127         RunThrough              ///< The text will completely ignore the frame and layout as if it was not there
0128     };
0129 
0130     /// The behavior text should do when intersecting this shape.
0131     enum TextRunAroundContour {
0132         ContourBox,     /// Run other text around a bounding rect of the outline
0133         ContourFull,   ///< Run other text around also on the inside
0134         ContourOutside   ///< Run other text around only on the outside
0135     };
0136 
0137     /**
0138      * TODO
0139      */
0140     enum RunThroughLevel {
0141         Background,
0142         Foreground
0143     };
0144 
0145     /**
0146      * @brief Constructor
0147      */
0148     KoShape();
0149 
0150     /**
0151      * @brief Destructor
0152      */
0153     virtual ~KoShape();
0154 
0155     /**
0156      * @brief creates a deep copy of the shape or shape's subtree
0157      * @return a cloned shape
0158      */
0159     virtual KoShape* cloneShape() const;
0160 
0161     /**
0162      * @brief Paint the shape fill
0163      * The class extending this one is responsible for painting itself. \p painter is expected
0164      * to be preconfigured to work in "document" pixels.
0165      *
0166      * @param painter used for painting the shape
0167      */
0168     virtual void paint(QPainter &painter) const = 0;
0169 
0170     /**
0171      * @brief paintStroke paints the shape's stroked outline
0172      * @param painter used for painting the shape
0173      * @see applyConversion()
0174      */
0175     virtual void paintStroke(QPainter &painter) const;
0176 
0177     /**
0178      * @brief Scale the shape using the zero-point which is the top-left corner.
0179      * @see position()
0180      *
0181      * @param sx scale in x direction
0182      * @param sy scale in y direction
0183      */
0184     void scale(qreal sx, qreal sy);
0185 
0186     /**
0187      * @brief Rotate the shape (relative)
0188      *
0189      * The shape will be rotated from the current rotation using the center of the shape using the size()
0190      *
0191      * @param angle change the angle of rotation increasing it with 'angle' degrees
0192      */
0193     void rotate(qreal angle);
0194 
0195     /**
0196      * Return the current rotation in degrees.
0197      * It returns NaN if the shape has a shearing or scaling transformation applied.
0198      */
0199     qreal rotation() const;
0200 
0201     /**
0202      * @brief Shear the shape
0203      * The shape will be sheared using the zero-point which is the top-left corner.
0204      * @see position()
0205      *
0206      * @param sx shear in x direction
0207      * @param sy shear in y direction
0208      */
0209     void shear(qreal sx, qreal sy);
0210 
0211     /**
0212      * @brief Resize the shape
0213      *
0214      * @param size the new size of the shape.  This is different from scaling as
0215      * scaling is a so called secondary operation which is comparable to zooming in
0216      * instead of changing the size of the basic shape.
0217      * Easiest example of this difference is that using this method will not distort the
0218      * size of pattern-fills and strokes.
0219      */
0220     virtual void setSize(const QSizeF &size);
0221 
0222     /**
0223      * @brief Get the size of the shape in pt.
0224      *
0225      * The size is in shape coordinates.
0226      *
0227      * @return the size of the shape as set by setSize()
0228      */
0229     virtual QSizeF size() const;
0230 
0231     /**
0232      * @brief Set the position of the shape in pt
0233      *
0234      * @param position the new position of the shape
0235      */
0236     virtual void setPosition(const QPointF &position);
0237 
0238     /**
0239      * @brief Get the position of the shape in pt
0240      *
0241      * @return the position of the shape
0242      */
0243     QPointF position() const;
0244 
0245     /**
0246      * @brief Check if the shape is hit on position
0247      * @param position the position where the user clicked.
0248      * @return true when it hits.
0249      */
0250     virtual bool hitTest(const QPointF &position) const;
0251 
0252     /**
0253      * @brief Get the bounding box of the shape
0254      *
0255      * This includes the line width and the shadow of the shape
0256      *
0257      * @return the bounding box of the shape
0258      */
0259     virtual QRectF boundingRect() const;
0260 
0261     /**
0262      * Get the united bounding box of a group of shapes. This is a utility
0263      * function used in many places in Krita.
0264      */
0265     static QRectF boundingRect(const QList<KoShape*> &shapes);
0266 
0267     /**
0268      * @return the bounding rect of the outline of the shape measured
0269      *         in absolute coordinate system. Please note that in contrast to
0270      *         boundingRect() this rect doesn't include the stroke and other
0271      *         insets.
0272      */
0273     QRectF absoluteOutlineRect() const;
0274 
0275     /**
0276      * Same as a member function, but applies to a list of shapes and returns a
0277      * united rect.
0278      */
0279     static QRectF absoluteOutlineRect(const QList<KoShape*> &shapes);
0280 
0281     /**
0282      * Return the side text should flow around this shape. This implements the ODF style:wrap
0283      * attribute that specifies how text is displayed around a frame or graphic object.
0284      */
0285     TextRunAroundSide textRunAroundSide() const;
0286 
0287     /**
0288      * Set the side text should flow around this shape.
0289      * @param side the requested side
0290      * @param runThrough run through the foreground or background or...
0291      */
0292     void setTextRunAroundSide(TextRunAroundSide side, RunThroughLevel runThrough = Background);
0293 
0294     /**
0295      * The space between this shape's left edge and text that runs around this shape.
0296      * @return the space around this shape to keep free from text
0297      */
0298     qreal textRunAroundDistanceLeft() const;
0299 
0300     /**
0301      * Set the space between this shape's left edge and the text that run around this shape.
0302      * @param distance the space around this shape to keep free from text
0303      */
0304     void setTextRunAroundDistanceLeft(qreal distance);
0305 
0306     /**
0307      * The space between this shape's top edge and text that runs around this shape.
0308      * @return the space around this shape to keep free from text
0309      */
0310     qreal textRunAroundDistanceTop() const;
0311 
0312     /**
0313      * Set the space between this shape's top edge and the text that run around this shape.
0314      * @param distance the space around this shape to keep free from text
0315      */
0316     void setTextRunAroundDistanceTop(qreal distance);
0317 
0318     /**
0319      * The space between this shape's right edge and text that runs around this shape.
0320      * @return the space around this shape to keep free from text
0321      */
0322     qreal textRunAroundDistanceRight() const;
0323 
0324     /**
0325      * Set the space between this shape's right edge and the text that run around this shape.
0326      * @param distance the space around this shape to keep free from text
0327      */
0328     void setTextRunAroundDistanceRight(qreal distance);
0329 
0330     /**
0331      * The space between this shape's bottom edge and text that runs around this shape.
0332      * @return the space around this shape to keep free from text
0333      */
0334     qreal textRunAroundDistanceBottom() const;
0335 
0336     /**
0337      * Set the space between this shape's bottom edge and the text that run around this shape.
0338      * @param distance the space around this shape to keep free from text
0339      */
0340     void setTextRunAroundDistanceBottom(qreal distance);
0341 
0342     /**
0343      * Return the threshold above which text should flow around this shape.
0344      * The text will not flow around the shape on a side unless the space available on that side
0345      * is above this threshold. Only used when the text run around side is EnoughRunAroundSide.
0346      * @return threshold the threshold
0347      */
0348     qreal textRunAroundThreshold() const;
0349 
0350     /**
0351      * Set the threshold above which text should flow around this shape.
0352      * The text will not flow around the shape on a side unless the space available on that side
0353      * is above this threshold. Only used when the text run around side is EnoughRunAroundSide.
0354      * @param threshold the new threshold
0355      */
0356     void setTextRunAroundThreshold(qreal threshold);
0357 
0358     /**
0359      * Return the how tight text run around is done around this shape.
0360      * @return the contour
0361      */
0362     TextRunAroundContour textRunAroundContour() const;
0363 
0364     /**
0365      * Set how tight text run around is done around this shape.
0366      * @param contour the new contour
0367      */
0368     void setTextRunAroundContour(TextRunAroundContour contour);
0369 
0370     /**
0371      * Set the KoShapeAnchor
0372      */
0373     void setAnchor(KoShapeAnchor *anchor);
0374 
0375     /**
0376      * Return the KoShapeAnchor, or 0
0377      */
0378     KoShapeAnchor *anchor() const;
0379 
0380     /**
0381      * Set the minimum height of the shape.
0382      * Currently it's not respected but only for informational purpose
0383      * @param height the minimum height of the frame.
0384      */
0385     void setMinimumHeight(qreal height);
0386 
0387     /**
0388      * Return the minimum height of the shape.
0389      * @return the minimum height of the shape. Default is 0.0.
0390      */
0391     qreal minimumHeight() const;
0392 
0393 
0394     /**
0395      * Set the background of the shape.
0396      * A shape background can be a plain color, a gradient, a pattern, be fully transparent
0397      * or have a complex fill.
0398      * Setting such a background will allow the shape to be filled and will be able to tell
0399      * if it is transparent or not.
0400      *
0401      * If the shape inherited the background from its parent, its stops inheriting it, that
0402      * is inheritBackground property resets to false.
0403      *
0404      * @param background the new shape background.
0405      */
0406     void setBackground(QSharedPointer<KoShapeBackground> background);
0407 
0408     /**
0409      * return the brush used to paint te background of this shape with.
0410      * A QBrush can have a plain color, be fully transparent or have a complex fill.
0411      * setting such a brush will allow the shape to fill itself using that brush and
0412      * will be able to tell if its transparent or not.
0413      * @return the background-brush
0414      */
0415     QSharedPointer<KoShapeBackground> background() const;
0416 
0417     /**
0418      * @brief setInheritBackground marks a shape as inhiriting the background
0419      * from the parent shape. NOTE: The currently selected background is destroyed.
0420      * @param value true if the shape should inherit the filling background
0421      */
0422     void setInheritBackground(bool value);
0423 
0424     /**
0425      * @brief inheritBackground shows if the shape inherits background from its parent
0426      * @return true if the shape inherits the fill
0427      */
0428     bool inheritBackground() const;
0429 
0430     /**
0431      * Returns true if there is some transparency, false if the shape is fully opaque.
0432      * The default implementation will just return if the background has some transparency,
0433      * you should override it and always return true if your shape is not square.
0434      * @return if the shape is (partly) transparent.
0435      */
0436     virtual bool hasTransparency() const;
0437 
0438     /**
0439      * Sets shape level transparency.
0440      * @param transparency the new shape level transparency
0441      */
0442     void setTransparency(qreal transparency);
0443 
0444     /**
0445      * Returns the shape level transparency.
0446      * @param recursive when true takes the parents transparency into account
0447      */
0448     qreal transparency(bool recursive=false) const;
0449 
0450     /**
0451      * Retrieve the z-coordinate of this shape.
0452      * The zIndex property is used to determine which shape lies on top of other objects.
0453      * An shape with a higher z-order is on top, and can obscure another shape.
0454      * @return the z-index of this shape.
0455      * @see setZIndex()
0456      */
0457     qint16 zIndex() const;
0458 
0459     /**
0460      * Set the z-coordinate of this shape.
0461      * The zIndex property is used to determine which shape lies on top of other objects.
0462      * An shape with a higher z-order is on top, and can obscure, another shape.
0463      * <p>Just like two objects having the same x or y coordinate will make them 'touch',
0464      * so will two objects with the same z-index touch on the z plane.  In layering the
0465      * shape this, however, can cause a little confusion as one always has to be on top.
0466      * The layering if two overlapping objects have the same index is implementation dependent
0467      * and probably depends on the order in which they are added to the shape manager.
0468      * @param zIndex the new z-index;
0469      */
0470     void setZIndex(qint16 zIndex);
0471 
0472     /**
0473      * Maximum value of z-index
0474      */
0475     static const qint16 maxZIndex;
0476 
0477     /**
0478      * Minimum value of z-index
0479      */
0480     static const qint16 minZIndex;
0481 
0482     /**
0483      * Retrieve the run through property of this shape.
0484      * The run through property is used to determine if the shape is behind, inside or before text.
0485      * @return the run through of this shape.
0486      */
0487     int runThrough() const;
0488 
0489     /**
0490      * Set the run through property of this shape.
0491      * The run through property is used to determine if the shape is behind, inside or before text.
0492      * @param runThrough the new run through;
0493      */
0494     virtual void setRunThrough(short int runThrough);
0495 
0496     /**
0497      * Changes the Shape to be visible or invisible.
0498      * Being visible means being painted, as well as being used for
0499      *   things like guidelines or searches.
0500      * @param on when true; set the shape to be visible.
0501      * @see setGeometryProtected(), setContentProtected(), setSelectable()
0502      */
0503     void setVisible(bool on);
0504     /**
0505      * Returns current visibility state of this shape.
0506      * Being visible means being painted, as well as being used for
0507      *   things like guidelines or searches.
0508      * @param recursive when true, checks visibility recursively
0509      * @return current visibility state of this shape.
0510      * @see isGeometryProtected(), isContentProtected(), isSelectable()
0511      */
0512     bool isVisible(bool recursive = true) const;
0513 
0514     /**
0515      * Changes the shape to be printable or not. The default is true.
0516      *
0517      * If a Shape's print flag is true, the shape will be printed. If
0518      * false, the shape will not be printed. If a shape is not visible (@see isVisible),
0519      * it isPrinted will return false, too.
0520      */
0521     void setPrintable(bool on);
0522 
0523     /**
0524      * Returns the current printable state of this shape.
0525      *
0526      * A shape can be visible but not printable, not printable and not visible
0527      * or visible and printable, but not invisible and still printable.
0528      *
0529      * @return current printable state of this shape.
0530      */
0531     bool isPrintable() const;
0532 
0533     /**
0534      * Makes it possible for the user to select this shape.
0535      * This parameter defaults to true.
0536      * @param selectable when true; set the shape to be selectable by the user.
0537      * @see setGeometryProtected(), setContentProtected(), setVisible()
0538      */
0539     void setSelectable(bool selectable);
0540 
0541     /**
0542      * Returns if this shape can be selected by the user.
0543      * @return true only when the object is selectable.
0544      * @see isGeometryProtected(), isContentProtected(), isVisible()
0545      */
0546     bool isSelectable() const;
0547 
0548     /**
0549      * Tells the shape to have its position/rotation and size protected from user-changes.
0550      * The geometry being protected means the user can not change shape or position of the
0551      * shape. This includes any matrix operation such as rotation.
0552      * @param on when true; set the shape to have its geometry protected.
0553      * @see setContentProtected(), setSelectable(), setVisible()
0554      */
0555     void setGeometryProtected(bool on);
0556 
0557     /**
0558      * Returns current geometry protection state of this shape.
0559      * The geometry being protected means the user can not change shape or position of the
0560      * shape. This includes any matrix operation such as rotation.
0561      * @return current geometry protection state of this shape.
0562      * @see isContentProtected(), isSelectable(), isVisible()
0563      */
0564     bool isGeometryProtected() const;
0565 
0566     /**
0567      * Marks the shape to have its content protected against editing.
0568      * Content protection is a hint for tools to disallow the user editing the content.
0569      * @param protect when true set the shapes content to be protected from user modification.
0570      * @see setGeometryProtected(), setSelectable(), setVisible()
0571      */
0572     void setContentProtected(bool protect);
0573 
0574     /**
0575      * Returns current content protection state of this shape.
0576      * Content protection is a hint for tools to disallow the user editing the content.
0577      * @return current content protection state of this shape.
0578      * @see isGeometryProtected(), isSelectable(), isVisible()
0579      */
0580     bool isContentProtected() const;
0581 
0582     /**
0583      * Returns the parent, or 0 if there is no parent.
0584      * @return the parent, or 0 if there is no parent.
0585      */
0586     KoShapeContainer *parent() const;
0587 
0588     /**
0589      * Set the parent of this shape.
0590      * @param parent the new parent of this shape. Can be 0 if the shape has no parent anymore.
0591      */
0592     void setParent(KoShapeContainer *parent);
0593 
0594 
0595     /**
0596      * @brief inheritsTransformFromAny checks if the shape inherits transformation from
0597      *        any of the shapes listed in \p ancestorsInQuestion. The inheritance is checked
0598      *        in recursive way.
0599      * @return true if there is a (transitive) transformation-wise parent found in \p ancestorsInQuestion
0600      */
0601     bool inheritsTransformFromAny(const QList<KoShape*> ancestorsInQuestion) const;
0602 
0603     /**
0604      * @return true if this shape has a common parent with \p shape
0605      */
0606     bool hasCommonParent(const KoShape *shape) const;
0607 
0608     /**
0609      * Request a repaint to be queued.
0610      * The repaint will be of the entire Shape, including its selection handles should this
0611      * shape be selected.
0612      * <p>This method will return immediately and only request a repaint. Successive calls
0613      * will be merged into an appropriate repaint action.
0614      */
0615     virtual void update() const;
0616 
0617     /**
0618      * Request a repaint to be queued.
0619      * The repaint will be restricted to the parameters rectangle, which is expected to be
0620      * in absolute coordinates of the canvas and it is expected to be
0621      * normalized.
0622      * <p>This method will return immediately and only request a repaint. Successive calls
0623      * will be merged into an appropriate repaint action.
0624      * @param rect the rectangle (in pt) to queue for repaint.
0625      */
0626     virtual void updateAbsolute(const QRectF &rect) const;
0627 
0628     /// Used by compareShapeZIndex() to order shapes
0629     enum ChildZOrderPolicy {
0630         ChildZDefault,
0631         ChildZParentChild = ChildZDefault, ///< normal parent/child ordering
0632         ChildZPassThrough ///< children are considered equal to this shape
0633     };
0634 
0635    /**
0636     * Returns if during compareShapeZIndex() how this shape portrays the values
0637     * of its children. The default behaviour is to let this shape's z values take
0638     * the place of its childrens values, so you get a parent/child relationship.
0639     * The children are naturally still ordered relatively to their z values
0640     *
0641     * But for special cases (like Calligra's TextShape) it can be overloaded to return
0642     * ChildZPassThrough which means the children keep their own z values
0643     * @returns the z order policy of this shape
0644     */
0645     virtual ChildZOrderPolicy childZOrderPolicy();
0646 
0647     /**
0648      * This is a method used to sort a list using the STL sorting methods.
0649      * @param s1 the first shape
0650      * @param s2 the second shape
0651      */
0652     static bool compareShapeZIndex(KoShape *s1, KoShape *s2);
0653 
0654     /**
0655      * returns the outline of the shape in the form of a path.
0656      * The outline returned will always be relative to the position() of the shape, so
0657      * moving the shape will not alter the result.  The outline is used to draw the stroke
0658      * on, for example.
0659      * @returns the outline of the shape in the form of a path.
0660      */
0661     virtual QPainterPath outline() const;
0662 
0663     /**
0664      * returns the outline of the shape in the form of a rect.
0665      * The outlineRect returned will always be relative to the position() of the shape, so
0666      * moving the shape will not alter the result.  The outline is used to calculate
0667      * the boundingRect.
0668      * @returns the outline of the shape in the form of a rect.
0669      */
0670     virtual QRectF outlineRect() const;
0671 
0672     /**
0673      * returns the outline of the shape in the form of a path for the use of painting a shadow.
0674      *
0675      * Normally this would be the same as outline() if there is a fill (background) set on the
0676      * shape and empty if not.  However, a shape could reimplement this to return an outline
0677      * even if no fill is defined. A typical example of this would be the picture shape
0678      * which has a picture but almost never a background.
0679      *
0680      * @returns the outline of the shape in the form of a path.
0681      */
0682     virtual QPainterPath shadowOutline() const;
0683 
0684     /**
0685      * Returns the currently set stroke, or 0 if there is no stroke.
0686      * @return the currently set stroke, or 0 if there is no stroke.
0687      */
0688     KoShapeStrokeModelSP stroke() const;
0689 
0690     /**
0691      * Set a new stroke, removing the old one. The stroke inheritance becomes disabled.
0692      * @param stroke the new stroke, or 0 if there should be no stroke.
0693      */
0694     void setStroke(KoShapeStrokeModelSP stroke);
0695 
0696     /**
0697      * @brief setInheritStroke marks a shape as inhiriting the stroke
0698      * from the parent shape. NOTE: The currently selected stroke is destroyed.
0699      * @param value true if the shape should inherit the stroke style
0700      */
0701     void setInheritStroke(bool value);
0702 
0703     /**
0704      * @brief inheritStroke shows if the shape inherits the stroke from its parent
0705      * @return true if the shape inherits the stroke style
0706      */
0707     bool inheritStroke() const;
0708 
0709     /**
0710      * Return the insets of the stroke.
0711      * Convenience method for KoShapeStrokeModel::strokeInsets()
0712      */
0713     KoInsets strokeInsets() const;
0714 
0715     /// Sets the new shadow, removing the old one
0716     void setShadow(KoShapeShadow *shadow);
0717 
0718     /// Returns the currently set shadow or 0 if there is no shadow set
0719     KoShapeShadow *shadow() const;
0720 
0721     /// Sets a new clip path, removing the old one
0722     void setClipPath(KoClipPath *clipPath);
0723 
0724     /// Returns the currently set clip path or 0 if there is no clip path set
0725     KoClipPath * clipPath() const;
0726 
0727     /// Sets a new clip mask, removing the old one. The mask is owned by the shape.
0728     void setClipMask(KoClipMask *clipMask);
0729 
0730     /// Returns the currently set clip mask or 0 if there is no clip mask set
0731     KoClipMask* clipMask() const;
0732 
0733     /**
0734      * Setting the shape to keep its aspect-ratio has the effect that user-scaling will
0735      * keep the width/height ratio intact so as not to distort shapes that rely on that
0736      * ratio.
0737      * @param keepAspect the new value
0738      */
0739     void setKeepAspectRatio(bool keepAspect);
0740 
0741     /**
0742      * Setting the shape to keep its aspect-ratio has the effect that user-scaling will
0743      * keep the width/height ratio intact so as not to distort shapes that rely on that
0744      * ratio.
0745      * @return whether to keep aspect ratio of this shape
0746      */
0747     bool keepAspectRatio() const;
0748 
0749     /**
0750      * Return the position of this shape regardless of rotation/skew/scaling and regardless of
0751      * this shape having a parent (being in a group) or not.<br>
0752      * @param anchor The place on the (unaltered) shape that you want the position of.
0753      * @return the point that is the absolute, centered position of this shape.
0754      */
0755     QPointF absolutePosition(KoFlake::AnchorPosition anchor = KoFlake::Center) const;
0756 
0757     /**
0758      * Move this shape to an absolute position where the end location will be the same
0759      * regardless of the shape's rotation/skew/scaling and regardless of this shape having
0760      * a parent (being in a group) or not.<br>
0761      * The newPosition is going to be the center of the shape.
0762      * This has the convenient effect that: <pre>
0763     shape-&gt;setAbsolutePosition(QPointF(0,0));
0764     shape-&gt;rotate(45);</pre>
0765         Will result in the same visual position of the shape as the opposite:<pre>
0766     shape-&gt;rotate(45);
0767     shape-&gt;setAbsolutePosition(QPointF(0,0));</pre>
0768      * @param newPosition the new absolute center of the shape.
0769      * @param anchor The place on the (unaltered) shape that you set the position of.
0770      */
0771     void setAbsolutePosition(const QPointF &newPosition, KoFlake::AnchorPosition anchor = KoFlake::Center);
0772 
0773     /**
0774      * Set a data object on the shape to be used by an application.
0775      * This is specifically useful when a shape is created in a plugin and that data from that
0776      * shape should be accessible outside the plugin.
0777      * @param userData the new user data, or 0 to delete the current one.
0778      */
0779     void setUserData(KoShapeUserData *userData);
0780     /**
0781      * Return the current userData.
0782      */
0783     KoShapeUserData *userData() const;
0784 
0785     /**
0786      * Return the Id of this shape, identifying the type of shape by the id of the factory.
0787      * @see KoShapeFactoryBase::shapeId()
0788      * @return the id of the shape-type
0789      */
0790     QString shapeId() const;
0791 
0792     /**
0793      * Set the Id of this shape.  A shapeFactory is expected to set the Id at creation
0794      * so applications can find out what kind of shape this is.
0795      * @see KoShapeFactoryBase::shapeId()
0796      * @param id the ID from the factory that created this shape
0797      */
0798     void setShapeId(const QString &id);
0799 
0800     /**
0801      * Create a matrix that describes all the transformations done on this shape.
0802      *
0803      * The absolute transformation is the combined transformation of this shape
0804      * and all its parents and grandparents.
0805      */
0806     QTransform absoluteTransformation() const;
0807 
0808     /**
0809      * Applies a transformation to this shape.
0810      *
0811      * The transformation given is relative to the global coordinate system, i.e. the document.
0812      * This is a convenience function to apply a global transformation to this shape.
0813      * @see applyTransformation
0814      *
0815      * @param matrix the transformation matrix to apply
0816      */
0817     void applyAbsoluteTransformation(const QTransform &matrix);
0818 
0819     /**
0820      * Sets a new transformation matrix describing the local transformations on this shape.
0821      * @param matrix the new transformation matrix
0822      */
0823     void setTransformation(const QTransform &matrix);
0824 
0825     /// Returns the shapes local transformation matrix
0826     QTransform transformation() const;
0827 
0828     /**
0829      * Applies a transformation to this shape.
0830      *
0831      * The transformation given is relative to the shape coordinate system.
0832      *
0833      * @param matrix the transformation matrix to apply
0834      */
0835     void applyTransformation(const QTransform &matrix);
0836 
0837     /**
0838      * Copy all the settings from the parameter shape and apply them to this shape.
0839      * Settings like the position and rotation to visible and locked.  The parent
0840      * is a notable exclusion.
0841      * @param shape the shape to use as original
0842      */
0843     void copySettings(const KoShape *shape);
0844 
0845     /**
0846      * A convenience method that creates a handles helper with applying transformations at
0847      * the same time. Please note that you shouldn't save/restore additionally. All the work
0848      * on restoring original painter's transformations is done by the helper.
0849      */
0850     static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius = 0.0);
0851     static KisHandlePainterHelper createHandlePainterHelperDocument(QPainter *painter, KoShape *shape, qreal handleRadius);
0852 
0853     /**
0854      * @brief Transforms point from shape coordinates to document coordinates
0855      * @param point in shape coordinates
0856      * @return point in document coordinates
0857      */
0858     QPointF shapeToDocument(const QPointF &point) const;
0859 
0860     /**
0861      * @brief Transforms rect from shape coordinates to document coordinates
0862      * @param rect in shape coordinates
0863      * @return rect in document coordinates
0864      */
0865     QRectF shapeToDocument(const QRectF &rect) const;
0866 
0867     /**
0868      * @brief Transforms point from document coordinates to shape coordinates
0869      * @param point in document coordinates
0870      * @return point in shape coordinates
0871      */
0872     QPointF documentToShape(const QPointF &point) const;
0873 
0874     /**
0875      * @brief Transform rect from document coordinates to shape coordinates
0876      * @param rect in document coordinates
0877      * @return rect in shape coordinates
0878      */
0879     QRectF documentToShape(const QRectF &rect) const;
0880 
0881     /**
0882      * Returns the name of the shape.
0883      * @return the shapes name
0884      */
0885     QString name() const;
0886 
0887     /**
0888      * Sets the name of the shape.
0889      * @param name the new shape name
0890      */
0891     void setName(const QString &name);
0892 
0893     /**
0894      * Update the position of the shape in the tree of the KoShapeManager.
0895      */
0896     void notifyChanged();
0897 
0898     /**
0899      * A shape can be in a state that it is doing processing data like loading or text layout.
0900      * In this case it can be shown on screen probably partially but it should really not be printed
0901      * until it is fully done processing.
0902      * Warning! This method can be blocking for a long time
0903      * @param asynchronous If set to true the processing will can take place in a different thread and the
0904      *                     function will not block until the shape is finished.
0905      *                     In case of printing Flake will call this method from a non-main thread and only
0906      *                     start printing it when the in case of printing method returned.
0907      *                     If set to false the processing needs to be done synchronously and will
0908      *                     block until the result is finished.
0909      */
0910     virtual void waitUntilReady(bool asynchronous = true) const;
0911 
0912     /// checks recursively if the shape or one of its parents is not visible or locked
0913     virtual bool isShapeEditable(bool recursive = true) const;
0914 
0915     /**
0916      * Adds a shape which depends on this shape.
0917      * Making a shape dependent on this one means it will get shapeChanged() called
0918      * on each update of this shape.
0919      *
0920      * If this shape already depends on the given shape, establishing the
0921      * dependency is refused to prevent circular dependencies.
0922      *
0923      * @param shape the shape which depends on this shape
0924      * @return true if dependency could be established, otherwise false
0925      * @see removeDependee(), hasDependee()
0926      */
0927     bool addDependee(KoShape *shape);
0928 
0929     /**
0930      * Removes as shape depending on this shape.
0931      * @see addDependee(), hasDependee()
0932      */
0933     void removeDependee(KoShape *shape);
0934 
0935     /// Returns if the given shape is dependent on this shape
0936     bool hasDependee(KoShape *shape) const;
0937 
0938     /// Returns list of shapes depending on this shape
0939     QList<KoShape*> dependees() const;
0940 
0941     /// Returns additional snap data the shape wants to have snapping to
0942     virtual KoSnapData snapData() const;
0943 
0944     /**
0945      * Set additional attribute
0946      *
0947      * This can be used to attach additional attributes to a shape for attributes
0948      * that are application specific like presentation:placeholder
0949      *
0950      * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
0951      * @param value The value of the attribute
0952      */
0953     void setAdditionalAttribute(const QString &name, const QString &value);
0954 
0955     /**
0956      * Remove additional attribute
0957      *
0958      * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
0959      */
0960     void removeAdditionalAttribute(const QString &name);
0961 
0962     /**
0963      * Check if additional attribute is set
0964      *
0965      * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
0966      *
0967      * @return true if there is a attribute with prefix:tag set, false otherwise
0968      */
0969     bool hasAdditionalAttribute(const QString &name) const;
0970 
0971     /**
0972      * Get additional attribute
0973      *
0974      * @param name The name of the attribute in the following form prefix:tag e.g. presentation:placeholder
0975      *
0976      * @return The value of the attribute if it exists or a null string if not found.
0977      */
0978     QString additionalAttribute(const QString &name) const;
0979 
0980     void setAdditionalStyleAttribute(const char *name, const QString &value);
0981 
0982     void removeAdditionalStyleAttribute(const char *name);
0983 
0984     /**
0985      * Returns the filter effect stack of the shape
0986      *
0987      * @return the list of filter effects applied on the shape when rendering.
0988      */
0989     KoFilterEffectStack *filterEffectStack() const;
0990 
0991     /// Sets the new filter effect stack, removing the old one
0992     void setFilterEffectStack(KoFilterEffectStack *filterEffectStack);
0993 
0994     /**
0995      * Return the tool delegates for this shape.
0996      * In Flake a shape being selected will cause the tool manager to make available all tools that
0997      * can edit the selected shapes.  In some cases selecting one shape should allow the tool to
0998      * edit a related shape be available too.  The tool delegates allows this to happen by taking
0999      * all the shapes in the set into account on tool selection.
1000      * Notice that if the set is non-empty 'this' shape is no longer looked at. You can choose
1001      * to add itself to the set too.
1002      */
1003     QSet<KoShape*> toolDelegates() const;
1004 
1005     /**
1006      * Set the tool delegates.
1007      * @param delegates the new delegates.
1008      * @see toolDelegates()
1009      */
1010     void setToolDelegates(const QSet<KoShape*> &delegates);
1011 
1012     /**
1013      * Return the hyperlink for this shape.
1014      */
1015     QString hyperLink () const;
1016 
1017     /**
1018      * Set hyperlink for this shape.
1019      * @param hyperLink name.
1020      */
1021     void setHyperLink(const QString &hyperLink);
1022 
1023 public:
1024 
1025     struct KRITAFLAKE_EXPORT ShapeChangeListener {
1026         virtual ~ShapeChangeListener();
1027         virtual void notifyShapeChanged(ChangeType type, KoShape *shape) = 0;
1028 
1029     private:
1030         friend class KoShape;
1031         void registerShape(KoShape *shape);
1032         void unregisterShape(KoShape *shape);
1033         void notifyShapeChangedImpl(ChangeType type, KoShape *shape);
1034 
1035         QList<KoShape*> m_registeredShapes;
1036     };
1037 
1038     void addShapeChangeListener(ShapeChangeListener *listener);
1039     void removeShapeChangeListener(ShapeChangeListener *listener);
1040 
1041 protected:
1042     QList<ShapeChangeListener *> listeners() const;
1043     void setSizeImpl(const QSizeF &size) const;
1044 
1045 public:
1046     static QList<KoShape*> linearizeSubtree(const QList<KoShape*> &shapes);
1047     static QList<KoShape *> linearizeSubtreeSorted(const QList<KoShape *> &shapes);
1048 protected:
1049     KoShape(const KoShape &rhs);
1050 
1051      /**
1052      * A hook that allows inheriting classes to do something after a KoShape property changed
1053      * This is called whenever the shape, position rotation or scale properties were altered.
1054      * @param type an indicator which type was changed.
1055      * @param shape the shape.
1056      */
1057     virtual void shapeChanged(ChangeType type, KoShape *shape = 0);
1058 
1059     /// return the current matrix that contains the rotation/scale/position of this shape
1060     QTransform transform() const;
1061 
1062 private:
1063     class Private;
1064     QScopedPointer<Private> d;
1065 
1066     class SharedData;
1067     QSharedDataPointer<SharedData> s;
1068 
1069 
1070 protected:
1071     /**
1072      * Notify the shape that a change was done. To be used by inheriting shapes.
1073      * @param type the change type
1074      */
1075     void shapeChangedPriv(KoShape::ChangeType type);
1076 
1077 private:
1078     void addShapeManager(KoShapeManager *manager);
1079     void removeShapeManager(KoShapeManager *manager);
1080     friend class KoShapeManager;
1081 };
1082 
1083 Q_DECLARE_METATYPE(KoShape*)
1084 
1085 #endif