1 /* This file is part of the KDE project 2 * Copyright (C) 2007-2008,2011 Jan Hambrecht <jaham@gmx.net> 3 * Copyright (C) 2008 Rob Buis <buis@kde.org> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef ARTISTICTEXTSHAPE_H 22 #define ARTISTICTEXTSHAPE_H 23 24 #include "ArtisticTextRange.h" 25 #include <KoShape.h> 26 #include <KoPostscriptPaintDevice.h> 27 #include <SvgShape.h> 28 #include <QFont> 29 #include <QPainterPath> 30 #include <QVector> 31 32 class QPainter; 33 class KoPathShape; 34 class ArtisticTextLoadingContext; 35 class SvgGraphicsContext; 36 37 #define ArtisticTextShapeID "ArtisticText" 38 39 /// Character position within text shape (range index, range character index) 40 typedef QPair<int, int> CharIndex; 41 42 class ArtisticTextShape : public KoShape, public SvgShape 43 { 44 public: 45 enum TextAnchor { AnchorStart, AnchorMiddle, AnchorEnd }; 46 47 enum LayoutMode { 48 Straight, ///< baseline is a straight line 49 OnPath, ///< baseline is a QPainterPath 50 OnPathShape ///< baseline is the outline of a path shape 51 }; 52 53 ArtisticTextShape(); 54 ~ArtisticTextShape() override; 55 56 /// reimplemented 57 void paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintContext) override; 58 /// reimplemented 59 void saveOdf(KoShapeSavingContext & context) const override; 60 /// reimplemented 61 bool loadOdf( const KoXmlElement & element, KoShapeLoadingContext &context ) override; 62 /// reimplemented 63 QSizeF size() const override; 64 /// reimplemented 65 void setSize( const QSizeF &size ) override; 66 /// reimplemented 67 QPainterPath outline() const override; 68 /// reimplemented from SvgShape 69 bool saveSvg(SvgSavingContext &context) override; 70 /// reimplemented from SvgShape 71 bool loadSvg(const KoXmlElement &element, SvgLoadingContext &context) override; 72 73 /// Sets the plain text to display 74 void setPlainText(const QString &newText); 75 76 /// Returns the plain text content 77 QString plainText() const; 78 79 /// Returns formatted text 80 QList<ArtisticTextRange> text() const; 81 82 /// Returns if text shape is empty, i.e. no text 83 bool isEmpty() const; 84 85 /// Clears the text shape 86 void clear(); 87 88 /** 89 * Sets the font used for drawing 90 * Note that it is expected that the font has its point size set 91 * in postscript points. 92 */ 93 void setFont(const QFont &font); 94 95 /** 96 * Sets the font for the specified range of characters 97 * @param charIndex the index of the first character of the range 98 * @param charCount the number of characters of the range 99 * @param font the new font to set 100 */ 101 void setFont(int charIndex, int charCount, const QFont &font); 102 103 /** 104 * Returns the font at the specified character position 105 * If the text shape is empty it will return the default font. 106 * If the character index is smaller than zero it will return the font 107 * of the first character. If the character index is greater than the 108 * last character index it will return the font of the last character. 109 */ 110 QFont fontAt(int charIndex) const; 111 112 /// Returns the default font 113 QFont defaultFont() const; 114 115 /// Attaches this text shape to the given path shape 116 bool putOnPath(KoPathShape *path); 117 118 /// Puts the text on the given path, the path is expected to be in document coordinates 119 bool putOnPath(const QPainterPath &path); 120 121 /// Detaches this text shape from an already attached path shape 122 void removeFromPath(); 123 124 /// Returns if shape is attached to a path shape 125 bool isOnPath() const; 126 127 /// Sets the offset for for text on path 128 void setStartOffset(qreal offset); 129 130 /// Returns the start offset for text on path 131 qreal startOffset() const; 132 133 /** 134 * Returns the y-offset from the top-left corner to the baseline. 135 * This is usable for being able to exactly position the texts baseline. 136 * Note: The value makes only sense for text not attached to a path. 137 */ 138 qreal baselineOffset() const; 139 140 /// Sets the text anchor 141 void setTextAnchor(TextAnchor anchor); 142 143 /// Returns the actual text anchor 144 TextAnchor textAnchor() const; 145 146 /// Returns the current layout mode 147 LayoutMode layout() const; 148 149 /// Returns the baseline path 150 QPainterPath baseline() const; 151 152 /// Returns a pointer to the shape used as baseline 153 KoPathShape * baselineShape() const; 154 155 /// Removes a range of text starting from the given character 156 QList<ArtisticTextRange> removeText(int charIndex, int charCount); 157 158 /// Copies a range of text starting from the given character 159 QList<ArtisticTextRange> copyText(int charIndex, int charCount); 160 161 /// Adds a range of text at the given index 162 void insertText(int charIndex, const QString &plainText); 163 164 /// Adds range of text at the given index 165 void insertText(int charIndex, const ArtisticTextRange &textRange); 166 167 /// Adds ranges of text at the given index 168 void insertText(int charIndex, const QList<ArtisticTextRange> &textRanges); 169 170 /// Appends plain text to the last text range 171 void appendText(const QString &plainText); 172 173 /// Appends a single formatted range of text 174 void appendText(const ArtisticTextRange &text); 175 176 /// Replaces a range of text with the specified text range 177 bool replaceText(int charIndex, int charCount, const ArtisticTextRange &textRange); 178 179 /// Replaces a range of text with the specified text ranges 180 bool replaceText(int charIndex, int charCount, const QList<ArtisticTextRange> &textRanges); 181 182 /// Gets the angle of the char with the given index 183 qreal charAngleAt(int charIndex) const; 184 185 /// Gets the position of the char with the given index in shape coordinates 186 QPointF charPositionAt(int charIndex) const; 187 188 /// Gets the extents of the char with the given index 189 QRectF charExtentsAt(int charIndex) const; 190 191 /// Returns index of range and index within range of specified character 192 CharIndex indexOfChar(int charIndex) const; 193 194 /// reimplemented from KoShape 195 void shapeChanged(ChangeType type, KoShape * shape) override; 196 197 private: 198 void updateSizeAndPosition( bool global = false ); 199 bool pathHasChanged() const; 200 void createOutline(); 201 202 void beginTextUpdate(); 203 void finishTextUpdate(); 204 205 /// Calculates abstract character positions in baseline coordinates 206 QVector<QPointF> calculateAbstractCharacterPositions(); 207 208 /// Returns the bounding box for an empty text shape 209 QRectF nullBoundBox() const; 210 211 /// Saves svg font 212 void saveSvgFont(const QFont &font, SvgSavingContext &context); 213 /// Saves svg text range 214 void saveSvgTextRange(const ArtisticTextRange &range, SvgSavingContext &context, bool saveFont, qreal baselineOffset); 215 /// Parse nested text ranges 216 void parseTextRanges(const KoXmlElement &element, SvgLoadingContext &context, ArtisticTextLoadingContext &textContext); 217 /// Creates text range 218 ArtisticTextRange createTextRange(const QString &text, ArtisticTextLoadingContext &context, SvgGraphicsContext *gc); 219 220 QList<ArtisticTextRange> m_ranges; 221 KoPostscriptPaintDevice m_paintDevice; 222 KoPathShape * m_path; ///< the path shape we are attached to 223 qreal m_startOffset; ///< the offset from the attached path start point 224 QPointF m_outlineOrigin; ///< the top-left corner of the non-normalized text outline 225 QPainterPath m_outline; ///< the actual text outline 226 QPainterPath m_baseline; ///< the baseline path the text is put on 227 TextAnchor m_textAnchor; ///< the actual text anchor 228 QVector<qreal> m_charOffsets; ///< char positions [0..1] on baseline path 229 QVector<QPointF> m_charPositions; ///< char positions in shape coordinates 230 int m_textUpdateCounter; 231 QFont m_defaultFont; 232 bool m_drawBoundaryLines; 233 }; 234 235 #endif // ARTISTICTEXTSHAPE_H 236