File indexing completed on 2025-01-12 12:28:11
0001 /* 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 1999-2003 Lars Knoll <knoll@kde.org> 0005 * Copyright (C) 2000-2003 Dirk Mueller <mueller@kde.org> 0006 * Copyright (C) 2003, 2006 Apple Computer, Inc. 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this library; see the file COPYING.LIB. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 * 0023 */ 0024 #ifndef RENDERTEXT_H 0025 #define RENDERTEXT_H 0026 0027 #include "dom/dom_string.h" 0028 #include "xml/dom_stringimpl.h" 0029 #include "xml/dom_textimpl.h" 0030 #include "rendering/render_object.h" 0031 #include "rendering/render_line.h" 0032 0033 #include <QMutableVectorIterator> 0034 #include <assert.h> 0035 0036 class QPainter; 0037 class QFontMetrics; 0038 0039 // Define a constant for soft hyphen's unicode value. 0040 #define SOFT_HYPHEN 173 0041 0042 const int cNoTruncation = -1; 0043 const int cFullTruncation = -2; 0044 0045 namespace khtml 0046 { 0047 class RenderText; 0048 class RenderStyle; 0049 0050 class InlineTextBox : public InlineRunBox 0051 { 0052 public: 0053 InlineTextBox(RenderObject *obj) 0054 : InlineRunBox(obj), 0055 // ### necessary as some codepaths (<br>) do *not* initialize these (LS) 0056 m_start(0), m_len(0), m_truncation(cNoTruncation), m_reversed(false), m_toAdd(0) 0057 { 0058 } 0059 0060 uint start() const 0061 { 0062 return m_start; 0063 } 0064 uint end() const 0065 { 0066 return m_len ? m_start + m_len - 1 : m_start; 0067 } 0068 uint len() const 0069 { 0070 return m_len; 0071 } 0072 0073 void detach(RenderArena *renderArena, bool noRemove = false) override; 0074 0075 InlineTextBox *nextTextBox() const 0076 { 0077 return static_cast<InlineTextBox *>(nextLineBox()); 0078 } 0079 InlineTextBox *prevTextBox() const 0080 { 0081 return static_cast<InlineTextBox *>(prevLineBox()); 0082 } 0083 0084 void clearTruncation() override 0085 { 0086 m_truncation = cNoTruncation; 0087 } 0088 int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool &foundBox) override; 0089 0090 // Overloaded new operator. Derived classes must override operator new 0091 // in order to allocate out of the RenderArena. 0092 void *operator new(size_t sz, RenderArena *renderArena) throw(); 0093 0094 // Overridden to prevent the normal delete from being called. 0095 void operator delete(void *ptr, size_t sz); 0096 0097 private: 0098 // The normal operator new is disallowed. 0099 void *operator new(size_t sz) throw(); 0100 0101 public: 0102 void setSpaceAdd(int add) 0103 { 0104 m_width -= m_toAdd; 0105 m_toAdd = add; 0106 m_width += m_toAdd; 0107 } 0108 int spaceAdd() 0109 { 0110 return m_toAdd; 0111 } 0112 0113 bool isInlineTextBox() const override 0114 { 0115 return true; 0116 } 0117 0118 void paint(RenderObject::PaintInfo &i, int tx, int ty) override; 0119 void paintDecoration(QPainter *pt, const Font *f, int _tx, int _ty, int decoration); 0120 void paintShadow(QPainter *pt, const Font *f, int _tx, int _ty, const ShadowData *shadow); 0121 void paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle *style, int tx, int ty, int startPos, int endPos, int deco); 0122 0123 void selectionStartEnd(int &sPos, int &ePos); 0124 RenderObject::SelectionState selectionState(); 0125 0126 // Return before, after (offset set to max), or inside the text, at @p offset 0127 FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, int &offset); 0128 0129 bool checkVerticalPoint(int _y, int _ty, int _h, int height) 0130 { 0131 if ((_ty + m_y > _y + _h) || (_ty + m_y + m_baseline + height < _y)) { 0132 return false; 0133 } return true; 0134 } 0135 0136 /** 0137 * determines the offset into the DOMString of the character the given 0138 * coordinate points to. 0139 * The returned offset is never out of range. 0140 * @param _x given coordinate (relative to containing block) 0141 * @param ax returns exact coordinate the offset corresponds to 0142 * (relative to containing block) 0143 * @return the offset (relative to the RenderText object, not to this run) 0144 */ 0145 int offsetForPoint(int _x, int &ax) const; 0146 0147 /** 0148 * calculates the with of the specified chunk in this text box. 0149 * @param pos zero-based position within the text box up to which 0150 * the width is to be determined 0151 * @return the width in pixels 0152 */ 0153 int widthFromStart(int pos) const; 0154 0155 long caretMinOffset() const override; 0156 long caretMaxOffset() const override; 0157 unsigned long caretMaxRenderedOffset() const override; 0158 0159 /** returns the associated render text 0160 */ 0161 const RenderText *renderText() const; 0162 RenderText *renderText(); 0163 0164 void extractLine() override; 0165 void deleteLine(RenderArena *arena) override; 0166 void attachLine() override; 0167 0168 int m_start; 0169 unsigned short m_len; 0170 0171 int m_truncation; // Where to truncate when text overflow is applied. 0172 // We use special constants to denote no truncation (the whole run paints) 0173 // and full truncation (nothing paints at all). 0174 0175 bool m_reversed : 1; 0176 unsigned m_toAdd : 14; // for justified text 0177 private: 0178 friend class RenderText; 0179 }; 0180 0181 class RenderText : public RenderObject 0182 { 0183 friend class InlineTextBox; 0184 0185 public: 0186 RenderText(DOM::NodeImpl *node, DOM::DOMStringImpl *_str); 0187 virtual ~RenderText(); 0188 0189 virtual bool isTextFragment() const; 0190 virtual DOM::DOMStringImpl *originalString() const; 0191 0192 const char *renderName() const override 0193 { 0194 return "RenderText"; 0195 } 0196 0197 void setStyle(RenderStyle *style) override; 0198 0199 void detach() override; 0200 0201 void deleteInlineBoxes(RenderArena *arena = nullptr) override; 0202 void dirtyInlineBoxes(bool fullLayout, bool) override; 0203 void removeInlineBox(InlineBox *_box) override; 0204 0205 DOM::DOMString data() const 0206 { 0207 return str; 0208 } 0209 DOM::DOMStringImpl *string() const 0210 { 0211 return str; 0212 } 0213 0214 InlineBox *createInlineBox(bool, bool) override; 0215 0216 void layout() override 0217 { 0218 assert(false); 0219 } 0220 0221 bool nodeAtPoint(NodeInfo &info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inBox) override; 0222 0223 RenderPosition positionForCoordinates(int _x, int _y) override; 0224 0225 // Return before, after (offset set to max), or inside the text, at @p offset 0226 virtual FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, 0227 DOM::NodeImpl *&node, int &offset, 0228 SelPointState &); 0229 0230 unsigned int length() const override 0231 { 0232 if (str) { 0233 return str->l; 0234 } else { 0235 return 0; 0236 } 0237 } 0238 QChar *text() const 0239 { 0240 if (str) { 0241 return str->s; 0242 } else { 0243 return nullptr; 0244 } 0245 } 0246 unsigned int stringLength() const 0247 { 0248 return str->l; // non virtual implementation of length() 0249 } 0250 void position(InlineBox *box, int from, int len, bool reverse) override; 0251 0252 virtual unsigned int width(unsigned int from, unsigned int len, const Font *f) const; 0253 virtual unsigned int width(unsigned int from, unsigned int len, bool firstLine = false) const; 0254 short width() const override; 0255 int height() const override; 0256 0257 // height of the contents (without paddings, margins and borders) 0258 short lineHeight(bool firstLine) const override; 0259 short baselinePosition(bool firstLine) const override; 0260 0261 // overrides 0262 void calcMinMaxWidth() override; 0263 short minWidth() const override 0264 { 0265 return m_minWidth; 0266 } 0267 int maxWidth() const override 0268 { 0269 return m_maxWidth; 0270 } 0271 0272 void trimmedMinMaxWidth(int &beginMinW, bool &beginWS, 0273 int &endMinW, bool &endWS, 0274 bool &hasBreakableChar, bool &hasBreak, 0275 int &beginMaxW, int &endMaxW, 0276 int &minW, int &maxW, bool &stripFrontSpaces); 0277 0278 bool containsOnlyWhitespace(unsigned int from, unsigned int len) const; 0279 0280 ushort startMin() const 0281 { 0282 return m_startMin; 0283 } 0284 ushort endMin() const 0285 { 0286 return m_endMin; 0287 } 0288 0289 // returns the minimum x position of all runs relative to the parent. 0290 // defaults to 0. 0291 int minXPos() const; 0292 0293 int inlineXPos() const override; 0294 int inlineYPos() const override; 0295 0296 bool hasReturn() const 0297 { 0298 return m_hasReturn; 0299 } 0300 0301 virtual const QFont &font(); 0302 short verticalPositionHint(bool firstLine) const override; 0303 0304 bool isFixedWidthFont() const; 0305 0306 void setText(DOM::DOMStringImpl *text, bool force = false); 0307 0308 SelectionState selectionState() const override 0309 { 0310 return KDE_CAST_BF_ENUM(SelectionState, m_selectionState); 0311 } 0312 void setSelectionState(SelectionState s) override 0313 { 0314 m_selectionState = s; 0315 } 0316 void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height) const override; 0317 bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool f = false) const override; 0318 bool posOfChar(int ch, int &x, int &y) const; 0319 bool isPointInsideSelection(int x, int y, const DOM::Selection &) const override; 0320 0321 short marginLeft() const override 0322 { 0323 return style()->marginLeft().minWidth(0); 0324 } 0325 short marginRight() const override 0326 { 0327 return style()->marginRight().minWidth(0); 0328 } 0329 0330 void repaint(Priority p = NormalPriority) override; 0331 0332 InlineTextBox *firstTextBox() const 0333 { 0334 return m_firstTextBox; 0335 } 0336 InlineTextBox *lastTextBox() const 0337 { 0338 return m_lastTextBox; 0339 } 0340 0341 QList< QRectF > getClientRects() override; 0342 0343 bool hasBreakableChar() const 0344 { 0345 return m_hasBreakableChar; 0346 } 0347 bool isSimpleText() const 0348 { 0349 return m_isSimpleText; 0350 } 0351 const QFontMetrics &metrics(bool firstLine) const; 0352 const Font *htmlFont(bool firstLine) const; 0353 0354 DOM::TextImpl *element() const 0355 { 0356 return static_cast<DOM::TextImpl *>(RenderObject::element()); 0357 } 0358 0359 InlineBox *inlineBox(long offset) override; 0360 0361 void removeTextBox(InlineTextBox *box); 0362 void attachTextBox(InlineTextBox *box); 0363 void extractTextBox(InlineTextBox *box); 0364 0365 #ifdef ENABLE_DUMP 0366 void dump(QTextStream &stream, const QString &ind) const override; 0367 #endif 0368 0369 long caretMinOffset() const override; 0370 long caretMaxOffset() const override; 0371 unsigned long caretMaxRenderedOffset() const override; 0372 0373 /** Find the text box that includes the character at @p offset 0374 * and return pos, which is the position of the char in the run. 0375 * @param offset zero-based offset into DOM string 0376 * @param pos returns relative position within text box 0377 * @param checkFirstLetter passing @p true will also regard :first-letter 0378 * boxes, if available. 0379 * @return the text box, or 0 if no match has been found 0380 */ 0381 const InlineTextBox *findInlineTextBox(int offset, int &pos, 0382 bool checkFirstLetter = false) const; 0383 0384 // helper methods to convert Position from rendered text into DOM position 0385 // (takes into account space collapsing) 0386 unsigned convertToDOMPosition(unsigned position) const; 0387 unsigned convertToRenderedPosition(unsigned position) const; 0388 protected: 0389 virtual void setTextInternal(DOM::DOMStringImpl *text); 0390 0391 // members 0392 InlineTextBox *m_firstTextBox; 0393 InlineTextBox *m_lastTextBox; 0394 0395 DOM::DOMStringImpl *str; // 0396 0397 short m_lineHeight; 0398 short m_minWidth; 0399 int m_maxWidth; 0400 short m_beginMinWidth; 0401 short m_endMinWidth; 0402 0403 KDE_BF_ENUM(SelectionState) m_selectionState : 3; 0404 bool m_hasReturn : 1; 0405 bool m_hasBreakableChar : 1; 0406 bool m_hasBreak : 1; 0407 bool m_hasBeginWS : 1; 0408 bool m_hasEndWS : 1; 0409 bool m_isSimpleText : 1; 0410 0411 ushort m_startMin : 8; 0412 ushort m_endMin : 8; 0413 }; 0414 0415 inline const RenderText *InlineTextBox::renderText() const 0416 { 0417 return static_cast<RenderText *>(object()); 0418 } 0419 0420 inline RenderText *InlineTextBox::renderText() 0421 { 0422 return static_cast<RenderText *>(object()); 0423 } 0424 0425 // Used to represent a text substring of an element, e.g., for text runs that are split because of 0426 // first letter and that must therefore have different styles (and positions in the render tree). 0427 // We cache offsets so that text transformations can be applied in such a way that we can recover 0428 // the original unaltered string from our corresponding DOM node. 0429 class RenderTextFragment : public RenderText 0430 { 0431 public: 0432 RenderTextFragment(DOM::NodeImpl *_node, DOM::DOMStringImpl *_str, 0433 int startOffset, int endOffset); 0434 RenderTextFragment(DOM::NodeImpl *_node, DOM::DOMStringImpl *_str); 0435 ~RenderTextFragment(); 0436 0437 bool isTextFragment() const override; 0438 const char *renderName() const override 0439 { 0440 return "RenderTextFragment"; 0441 } 0442 0443 uint start() const 0444 { 0445 return m_start; 0446 } 0447 uint end() const 0448 { 0449 return m_end; 0450 } 0451 0452 DOM::DOMStringImpl *contentString() const 0453 { 0454 return m_generatedContentStr; 0455 } 0456 DOM::DOMStringImpl *originalString() const override; 0457 0458 RenderObject *firstLetter() const 0459 { 0460 return m_firstLetter; 0461 } 0462 void setFirstLetter(RenderObject *firstLetter) 0463 { 0464 m_firstLetter = firstLetter; 0465 } 0466 0467 // overrides 0468 void detach() override; 0469 private: 0470 void setTextInternal(DOM::DOMStringImpl *text) override; 0471 0472 uint m_start; 0473 uint m_end; 0474 DOM::DOMStringImpl *m_generatedContentStr; 0475 RenderObject *m_firstLetter; 0476 }; 0477 } // end namespace 0478 #endif