File indexing completed on 2024-06-23 04:19:02
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #ifndef kpTextSelection_H 0030 #define kpTextSelection_H 0031 0032 0033 #include "layers/selections/kpAbstractSelection.h" 0034 #include "imagelib/kpImage.h" 0035 #include "layers/selections/text/kpTextStyle.h" 0036 #include "layers/selections/text/kpPreeditText.h" 0037 0038 // 0039 // A rectangular text box containing lines of text, rendered in a given text 0040 // style. 0041 // 0042 // A text selection with an empty list of text lines is just a text box 0043 // border and contains no content. 0044 // 0045 // The minimal text selection that is considered to contain content consists 0046 // of a single empty text line. 0047 // 0048 // The rendered elements are as follows: 0049 // 0050 // ############### 0051 // # # 0052 // # * *---------- Text Border 0053 // # | # 0054 // #####|######### 0055 // | 0056 // | 0057 // Text Area 0058 // (text lines are rendered on top of here; the parts of the lines 0059 // that don't fit here are not rendered) 0060 // 0061 // The text style determines how the text box is drawn. 0062 // 0063 // The foreground color determines the color of the text. Transparent 0064 // foreground text means that the text box is see-through for the pixels 0065 // of the text, exposing the document pixels below. It does not mean 0066 // that the transparent color is drawn onto the document. In other 0067 // words, we are "painting" transparent pixels -- not "setting" them. 0068 // 0069 // If the background color is opaque, the text is drawn on top of a 0070 // filled-in rectangle and the rectangle completely overwrites any 0071 // document pixels below. 0072 // 0073 // Consistent with the behavior of a transparent foreground color, a 0074 // transparent background color does not mean that a transparent-colored 0075 // rectangle is drawn onto the document. Instead, it means that the 0076 // text box background is see-through so that text is drawn directly on 0077 // top of the document pixels. No rectangle is drawn in this case. 0078 // 0079 // A text box with transparent foreground and background colors is 0080 // completely invisible since both the text and background are see-through. 0081 // 0082 // A rendered text cursor is controlled separately by kpViewManager, as 0083 // cursors are only a view concept so do not belong in this document-based 0084 // class. 0085 // 0086 // Marshalling, for copying text selections to the clipboard, is not 0087 // currently supported. This is because generally, users are only interested 0088 // in the text itself, not the border nor formatting. 0089 // 0090 class kpTextSelection : public kpAbstractSelection 0091 { 0092 Q_OBJECT 0093 0094 // 0095 // Initialization 0096 // 0097 0098 public: 0099 explicit kpTextSelection (const QRect &rect = QRect (), 0100 const kpTextStyle &textStyle = kpTextStyle ()); 0101 kpTextSelection (const QRect &rect, const QList <QString> &textLines, 0102 const kpTextStyle &textStyle); 0103 kpTextSelection (const kpTextSelection &rhs); 0104 0105 kpTextSelection &operator= (const kpTextSelection &rhs); 0106 0107 kpTextSelection *clone () const override; 0108 0109 // Returns a copy of the text selection but with new dimensions 0110 // <newWidth> x <newHeight>. 0111 kpTextSelection *resized (int newWidth, int newHeight) const; 0112 0113 ~kpTextSelection () override; 0114 0115 0116 // 0117 // Marshalling 0118 // 0119 0120 public: 0121 int serialID () const override; 0122 0123 bool readFromStream (QDataStream &stream) override; 0124 0125 void writeToStream (QDataStream &stream) const override; 0126 0127 0128 // 0129 // General Queries 0130 // 0131 0132 public: 0133 QString name () const override; 0134 0135 kpCommandSize::SizeType size () const override; 0136 0137 public: 0138 bool isRectangular () const override; 0139 0140 0141 // 0142 // Position & Dimensions 0143 // 0144 0145 public: 0146 // Returns the absolute minimum size that a textbox must be if it is of 0147 // the given <textStyle>. 0148 // 0149 // This leaves enough room for the border on all 4 sides and also a 0150 // text area big enough to fit a character in an extremely small font. 0151 static int MinimumWidthForTextStyle (const kpTextStyle &textStyle); 0152 static int MinimumHeightForTextStyle (const kpTextStyle &textStyle); 0153 static QSize MinimumSizeForTextStyle (const kpTextStyle &textStyle); 0154 0155 // REFACTOR: Enforce in kpTextSelection, not just in kpToolSelection & 0156 // when pasting (in kpMainWindow). 0157 // 0158 // Otherwise, if enforcement fails, e.g. textAreaRect() will 0159 // not work. 0160 int minimumWidth () const override; 0161 int minimumHeight () const override; 0162 0163 public: 0164 // Returns the suggested minimum size that a textbox should be if it is of 0165 // the given <textStyle>. 0166 // 0167 // This leaves enough room for the border on all 4 sides and also for 0168 // a small line of the text in the given text style. 0169 static int PreferredMinimumWidthForTextStyle (const kpTextStyle &textStyle); 0170 static int PreferredMinimumHeightForTextStyle (const kpTextStyle &textStyle); 0171 static QSize PreferredMinimumSizeForTextStyle (const kpTextStyle &textStyle); 0172 0173 public: 0174 // Returns the size of the text border. Constant. 0175 static int TextBorderSize (); 0176 0177 // Returns the rectangle that text lines are drawn on top of. 0178 // This will be a sub-rectangle of boundingRect() and is therefore, 0179 // in document coordinates like everything else in this class. 0180 QRect textAreaRect () const; 0181 0182 public: 0183 QPolygon calculatePoints () const override; 0184 0185 0186 // 0187 // Point Testing 0188 // 0189 0190 public: 0191 bool contains (const QPoint &point) const override; 0192 0193 public: 0194 bool pointIsInTextBorderArea (const QPoint &point) const; 0195 bool pointIsInTextArea (const QPoint &point) const; 0196 0197 0198 // 0199 // Content 0200 // 0201 0202 public: 0203 // (see class header comment) 0204 bool hasContent () const override; 0205 0206 void deleteContent () override; 0207 0208 public: 0209 QList <QString> textLines () const; 0210 void setTextLines (const QList <QString> &textLines); 0211 0212 static QString textForTextLines (const QList <QString> &textLines); 0213 // Returns textLines() as one long newline-separated string. 0214 // If the last text line is not empty, there is no trailing newline. 0215 QString text () const; 0216 0217 0218 // 0219 // Text Style 0220 // 0221 0222 public: 0223 kpTextStyle textStyle () const; 0224 void setTextStyle (const kpTextStyle &textStyle); 0225 0226 0227 // 0228 // Preedit Text 0229 // 0230 0231 public: 0232 kpPreeditText preeditText () const; 0233 void setPreeditText (const kpPreeditText &preeditText); 0234 0235 // 0236 // Cursor 0237 // 0238 // A text cursor position is the row and column of a character in 0239 // textLines(), that it is to the left of. As a result, a column value 0240 // of 1 character past the last character of a text line is allowed. 0241 // 0242 0243 public: 0244 // If the given point is in the text area, it returns the closest 0245 // row/column (in textLines()) for the point. 0246 // 0247 // If the given point is not in the text area, it returns -1. 0248 int closestTextRowForPoint (const QPoint &point) const; 0249 int closestTextColForPoint (const QPoint &point) const; 0250 0251 // Given a valid row and column in textLines(), returns the top-left 0252 // point of where the text cursor should be rendered. 0253 // TODO: Code is not symmetric to closestTest{Row,Col}ForPoint() 0254 // [look at the Y/row value calculations] 0255 // 0256 // If the row and column is not inside textLines(), it returns 0257 // KP_INVALID_POINT. 0258 QPoint pointForTextRowCol (int row, int col) const; 0259 0260 0261 // 0262 // Rendering 0263 // 0264 0265 private: 0266 void drawPreeditString(QPainter &painter, int &x, int y, const kpPreeditText &preeditText) const; 0267 0268 public: 0269 void paint(QImage *destPixmap, const QRect &docRect) const override; 0270 0271 void paintBorder(QImage *destPixmap, const QRect &docRect, 0272 bool selectionFinished) const override; 0273 0274 public: 0275 // Returns an image that contains the painted text (without a border). 0276 // 0277 // If the text box has a see-through background, the image will be given 0278 // an arbitrarily neutral background (currently, the transparent color). 0279 // As a result, the returned image will be an approximation since text 0280 // boxes are normally rendered -- and antialiased with -- a different 0281 // background, namely the document image. Therefore, it is invalid to 0282 // stamp the returned image onto the document image and expect it to look 0283 // like stamping this text selection onto the document image (the latter 0284 // is achieved via kpDocument::selectionPushOntoDocument(), antialiases 0285 // and is more correct). 0286 kpImage approximateImage () const; 0287 0288 0289 private: 0290 struct kpTextSelectionPrivate * const d; 0291 }; 0292 0293 0294 #endif // kpTextSelection_H