File indexing completed on 2024-05-12 16:33:19
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2007-2008,2011 Jan Hambrecht <jaham@gmx.net> 0003 * Copyright (C) 2008 Rob Buis <buis@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #ifndef ARTISTICTEXTSHAPE_H 0022 #define ARTISTICTEXTSHAPE_H 0023 0024 #include "ArtisticTextRange.h" 0025 #include <KoShape.h> 0026 #include <KoPostscriptPaintDevice.h> 0027 #include <SvgShape.h> 0028 #include <QFont> 0029 #include <QPainterPath> 0030 #include <QVector> 0031 0032 class QPainter; 0033 class KoPathShape; 0034 class ArtisticTextLoadingContext; 0035 class SvgGraphicsContext; 0036 0037 #define ArtisticTextShapeID "ArtisticText" 0038 0039 /// Character position within text shape (range index, range character index) 0040 typedef QPair<int, int> CharIndex; 0041 0042 class ArtisticTextShape : public KoShape, public SvgShape 0043 { 0044 public: 0045 enum TextAnchor { AnchorStart, AnchorMiddle, AnchorEnd }; 0046 0047 enum LayoutMode { 0048 Straight, ///< baseline is a straight line 0049 OnPath, ///< baseline is a QPainterPath 0050 OnPathShape ///< baseline is the outline of a path shape 0051 }; 0052 0053 ArtisticTextShape(); 0054 ~ArtisticTextShape() override; 0055 0056 /// reimplemented 0057 void paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintContext) override; 0058 /// reimplemented 0059 void saveOdf(KoShapeSavingContext & context) const override; 0060 /// reimplemented 0061 bool loadOdf( const KoXmlElement & element, KoShapeLoadingContext &context ) override; 0062 /// reimplemented 0063 QSizeF size() const override; 0064 /// reimplemented 0065 void setSize( const QSizeF &size ) override; 0066 /// reimplemented 0067 QPainterPath outline() const override; 0068 /// reimplemented from SvgShape 0069 bool saveSvg(SvgSavingContext &context) override; 0070 /// reimplemented from SvgShape 0071 bool loadSvg(const KoXmlElement &element, SvgLoadingContext &context) override; 0072 0073 /// Sets the plain text to display 0074 void setPlainText(const QString &newText); 0075 0076 /// Returns the plain text content 0077 QString plainText() const; 0078 0079 /// Returns formatted text 0080 QList<ArtisticTextRange> text() const; 0081 0082 /// Returns if text shape is empty, i.e. no text 0083 bool isEmpty() const; 0084 0085 /// Clears the text shape 0086 void clear(); 0087 0088 /** 0089 * Sets the font used for drawing 0090 * Note that it is expected that the font has its point size set 0091 * in postscript points. 0092 */ 0093 void setFont(const QFont &font); 0094 0095 /** 0096 * Sets the font for the specified range of characters 0097 * @param charIndex the index of the first character of the range 0098 * @param charCount the number of characters of the range 0099 * @param font the new font to set 0100 */ 0101 void setFont(int charIndex, int charCount, const QFont &font); 0102 0103 /** 0104 * Returns the font at the specified character position 0105 * If the text shape is empty it will return the default font. 0106 * If the character index is smaller than zero it will return the font 0107 * of the first character. If the character index is greater than the 0108 * last character index it will return the font of the last character. 0109 */ 0110 QFont fontAt(int charIndex) const; 0111 0112 /// Returns the default font 0113 QFont defaultFont() const; 0114 0115 /// Attaches this text shape to the given path shape 0116 bool putOnPath(KoPathShape *path); 0117 0118 /// Puts the text on the given path, the path is expected to be in document coordinates 0119 bool putOnPath(const QPainterPath &path); 0120 0121 /// Detaches this text shape from an already attached path shape 0122 void removeFromPath(); 0123 0124 /// Returns if shape is attached to a path shape 0125 bool isOnPath() const; 0126 0127 /// Sets the offset for for text on path 0128 void setStartOffset(qreal offset); 0129 0130 /// Returns the start offset for text on path 0131 qreal startOffset() const; 0132 0133 /** 0134 * Returns the y-offset from the top-left corner to the baseline. 0135 * This is usable for being able to exactly position the texts baseline. 0136 * Note: The value makes only sense for text not attached to a path. 0137 */ 0138 qreal baselineOffset() const; 0139 0140 /// Sets the text anchor 0141 void setTextAnchor(TextAnchor anchor); 0142 0143 /// Returns the actual text anchor 0144 TextAnchor textAnchor() const; 0145 0146 /// Returns the current layout mode 0147 LayoutMode layout() const; 0148 0149 /// Returns the baseline path 0150 QPainterPath baseline() const; 0151 0152 /// Returns a pointer to the shape used as baseline 0153 KoPathShape * baselineShape() const; 0154 0155 /// Removes a range of text starting from the given character 0156 QList<ArtisticTextRange> removeText(int charIndex, int charCount); 0157 0158 /// Copies a range of text starting from the given character 0159 QList<ArtisticTextRange> copyText(int charIndex, int charCount); 0160 0161 /// Adds a range of text at the given index 0162 void insertText(int charIndex, const QString &plainText); 0163 0164 /// Adds range of text at the given index 0165 void insertText(int charIndex, const ArtisticTextRange &textRange); 0166 0167 /// Adds ranges of text at the given index 0168 void insertText(int charIndex, const QList<ArtisticTextRange> &textRanges); 0169 0170 /// Appends plain text to the last text range 0171 void appendText(const QString &plainText); 0172 0173 /// Appends a single formatted range of text 0174 void appendText(const ArtisticTextRange &text); 0175 0176 /// Replaces a range of text with the specified text range 0177 bool replaceText(int charIndex, int charCount, const ArtisticTextRange &textRange); 0178 0179 /// Replaces a range of text with the specified text ranges 0180 bool replaceText(int charIndex, int charCount, const QList<ArtisticTextRange> &textRanges); 0181 0182 /// Gets the angle of the char with the given index 0183 qreal charAngleAt(int charIndex) const; 0184 0185 /// Gets the position of the char with the given index in shape coordinates 0186 QPointF charPositionAt(int charIndex) const; 0187 0188 /// Gets the extents of the char with the given index 0189 QRectF charExtentsAt(int charIndex) const; 0190 0191 /// Returns index of range and index within range of specified character 0192 CharIndex indexOfChar(int charIndex) const; 0193 0194 /// reimplemented from KoShape 0195 void shapeChanged(ChangeType type, KoShape * shape) override; 0196 0197 private: 0198 void updateSizeAndPosition( bool global = false ); 0199 bool pathHasChanged() const; 0200 void createOutline(); 0201 0202 void beginTextUpdate(); 0203 void finishTextUpdate(); 0204 0205 /// Calculates abstract character positions in baseline coordinates 0206 QVector<QPointF> calculateAbstractCharacterPositions(); 0207 0208 /// Returns the bounding box for an empty text shape 0209 QRectF nullBoundBox() const; 0210 0211 /// Saves svg font 0212 void saveSvgFont(const QFont &font, SvgSavingContext &context); 0213 /// Saves svg text range 0214 void saveSvgTextRange(const ArtisticTextRange &range, SvgSavingContext &context, bool saveFont, qreal baselineOffset); 0215 /// Parse nested text ranges 0216 void parseTextRanges(const KoXmlElement &element, SvgLoadingContext &context, ArtisticTextLoadingContext &textContext); 0217 /// Creates text range 0218 ArtisticTextRange createTextRange(const QString &text, ArtisticTextLoadingContext &context, SvgGraphicsContext *gc); 0219 0220 QList<ArtisticTextRange> m_ranges; 0221 KoPostscriptPaintDevice m_paintDevice; 0222 KoPathShape * m_path; ///< the path shape we are attached to 0223 qreal m_startOffset; ///< the offset from the attached path start point 0224 QPointF m_outlineOrigin; ///< the top-left corner of the non-normalized text outline 0225 QPainterPath m_outline; ///< the actual text outline 0226 QPainterPath m_baseline; ///< the baseline path the text is put on 0227 TextAnchor m_textAnchor; ///< the actual text anchor 0228 QVector<qreal> m_charOffsets; ///< char positions [0..1] on baseline path 0229 QVector<QPointF> m_charPositions; ///< char positions in shape coordinates 0230 int m_textUpdateCounter; 0231 QFont m_defaultFont; 0232 bool m_drawBoundaryLines; 0233 }; 0234 0235 #endif // ARTISTICTEXTSHAPE_H