File indexing completed on 2024-06-23 04:27:03

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2007, 2010, 2011 Jan Hambrecht <jaham@gmx.net>
0003  * SPDX-FileCopyrightText: 2010 Carlos Licea <carlos@kdab.com>
0004  * SPDX-FileCopyrightText: 2010 Nokia Corporation and /or its subsidiary(-ies).
0005  *   Contact: Suresh Chande suresh.chande@nokia.com
0006  *
0007  * SPDX-License-Identifier: LGPL-2.0-or-later
0008  */
0009 
0010 #ifndef KOENHANCEDPATHSHAPE_H
0011 #define KOENHANCEDPATHSHAPE_H
0012 
0013 #include <KoParameterShape.h>
0014 #include <QList>
0015 #include <QMap>
0016 #include <QRectF>
0017 #include <QStringList>
0018 
0019 #define EnhancedPathShapeId "EnhancedPathShape"
0020 
0021 class EnhancedPathCommand;
0022 class EnhancedPathHandle;
0023 class EnhancedPathFormula;
0024 class EnhancedPathParameter;
0025 class KoShapeSavingContext;
0026 class KoShapeLoadingContext;
0027 
0028 /**
0029  * An enhanced shape is a custom shape which can be defined
0030  * by enhanced geometry data.
0031  * The data consists of a list of commands like moveto,
0032  * lineto, curveto, etc. which are used to create the outline
0033  * of the shape. The coordinates or parameters of the commands
0034  * can be constant values, named variables (identifiers),
0035  * modifiers, functions or formulae.
0036 */
0037 class EnhancedPathShape : public KoParameterShape
0038 {
0039 public:
0040     EnhancedPathShape(const QRect &viewBox);
0041     ~EnhancedPathShape() override;
0042 
0043     KoShape* cloneShape() const override;
0044 
0045     /**
0046      * Evaluates the given reference to a identifier, modifier or formula.
0047      * @param reference the reference to evaluate
0048      * @return the result of the evaluation
0049      */
0050     qreal evaluateReference(const QString &reference);
0051 
0052     /**
0053      * Evaluates the given constant or reference to a identifier, modifier
0054      * or formula.
0055      * @param val the value to evaluate
0056      * @return the result of the evaluation
0057      */
0058     qreal evaluateConstantOrReference(const QString &val);
0059 
0060     /**
0061      * Attempts to modify a given reference.
0062      *
0063      * Only modifiers can me modified, others silently ignore the attempt.
0064      *
0065      * @param reference the reference to modify
0066      * @param value the new value
0067      */
0068     void modifyReference(const QString &reference, qreal value);
0069 
0070     // from KoShape
0071     void setSize(const QSizeF &newSize) override;
0072     // from KoParameterShape
0073     QPointF normalize() override;
0074 
0075     /// Add formula with given name and textual representation
0076     void addFormula(const QString &name, const QString &formula);
0077 
0078     /// Add a single handle with format: x y minX maxX minY maxY
0079     void addHandle(const QMap<QString, QVariant> &handle);
0080 
0081     /// Add modifiers with format: modifier0 modifier1 modifier2 ...
0082     void addModifiers(const QString &modifiers);
0083 
0084     /// Add command for instance "M 0 0"
0085     void addCommand(const QString &command);
0086 
0087     /// Returns the viewbox of the enhanced path shape
0088     QRect viewBox() const;
0089 
0090     /// Converts from shape coordinates to viewbox coordinates
0091     QPointF shapeToViewbox(const QPointF &point) const;
0092 
0093     /// Sets if the shape is to be mirrored horizontally before applying any other transformations
0094     //NOTE: in the standard nothing is mentioned about the priorities of the transformations"
0095     //it's assumed like this because of the behavior shown in OOo
0096     void setMirrorHorizontally(bool mirrorHorizontally);
0097 
0098     /// Sets if the shape is to be mirrored vertically before applying any other transformations
0099     //NOTE: in the standard nothing is mentioned about the priorities of the transformations"
0100     //it's assumed like this because of the behavior shown in OOo
0101     void setMirrorVertically(bool mirrorVertically);
0102 
0103     // Sets member variable representing draw:path-stretchpoint-x attribute
0104     void setPathStretchPointX(qreal pathStretchPointX);
0105 
0106     // Sets member variable representing draw:path-stretchpoint-y attribute
0107     void setPathStretchPointY(qreal pathStretchPointY);
0108 
0109     /// Returns parameter from given textual representation
0110     EnhancedPathParameter *parameter(const QString &text);
0111 
0112 protected:
0113     //from KoShape
0114     void shapeChanged(ChangeType type, KoShape *shape = 0) override;
0115     // from KoParameterShape
0116     void moveHandleAction(int handleId, const QPointF &point, Qt::KeyboardModifiers modifiers = Qt::NoModifier) override;
0117     // from KoParameterShape
0118     void updatePath(const QSizeF &size) override;
0119 
0120 private:
0121     EnhancedPathShape(const EnhancedPathShape &rhs);
0122 
0123     void evaluateHandles();
0124     void reset();
0125 
0126     /// parses the enhanced path data
0127     void parsePathData(const QString &data);
0128 
0129     /// Adds a new command
0130     void addCommand(const QString &command, bool triggerUpdate);
0131 
0132     /// Updates the size and position of an optionally existing text-on-shape text area
0133     void updateTextArea();
0134 
0135     /// Enables caching results
0136     void enableResultCache(bool enable);
0137 
0138     // This function checks if draw:path-stretchpoint-x or draw:path-stretchpoint-y attributes are set.
0139     // If the attributes are set the path shape coordinates (m_subpaths) are changed so that the form
0140     // of the shape is preserved after stretching. It is needed for example in round-rectangles, to
0141     // have the corners round after stretching. Without it the corners would be elliptical.
0142     // Returns true if any points were actually changed, otherwise false.
0143     bool useStretchPoints(const QSizeF &size, qreal &scale);
0144 
0145     typedef QMap<QString, EnhancedPathFormula *> FormulaStore;
0146     typedef QList<qreal> ModifierStore;
0147     typedef QMap<QString, EnhancedPathParameter *> ParameterStore;
0148 
0149     QRect m_viewBox;     ///< the viewbox rectangle
0150     QRectF m_viewBound;   ///< the bounding box of the path in viewbox coordinates
0151     QTransform m_viewMatrix; ///< matrix to convert from viewbox coordinates to shape coordinates
0152     QTransform m_mirrorMatrix; ///< matrix to used for mirroring
0153     QPointF m_viewBoxOffset;
0154     QStringList m_textArea;
0155     QList<EnhancedPathCommand *> m_commands; ///< the commands creating the outline
0156     QList<EnhancedPathHandle *> m_enhancedHandles; ///< the handles for modifying the shape
0157     FormulaStore m_formulae;     ///< the formulae
0158     ModifierStore m_modifiers;   ///< the modifier values
0159     ParameterStore m_parameters; ///< the shared parameters
0160     bool m_mirrorVertically; ///<whether or not the shape is to be mirrored vertically before transforming it
0161     bool m_mirrorHorizontally; ///<whether or not the shape is to be mirrored horizontally before transforming it
0162     qreal m_pathStretchPointX; ///< draw:path-stretchpoint-x attribute
0163     qreal m_pathStretchPointY; ///< draw:path-stretchpoint-y attribute
0164     QHash<QString, qreal> m_resultCache; ///< cache for intermediate results used when evaluating path
0165     bool m_cacheResults; ///< indicates if result cache is enabled
0166 };
0167 
0168 #endif // KOENHANCEDPATHSHAPE_H