2e833615d8cbeb5fdc93412cb3e301c835496013
[WebKit-https.git] / WebCore / khtml / rendering / render_text.h
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * (C) 1999 Lars Knoll (knoll@kde.org)
5  * (C) 2000 Dirk Mueller (mueller@kde.org)
6  * Copyright (C) 2004 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 #ifndef RENDERTEXT_H
25 #define RENDERTEXT_H
26
27 #include "dom/dom_string.h"
28 #include "xml/dom_stringimpl.h"
29 #include "xml/dom_textimpl.h"
30 #include "rendering/render_object.h"
31 #include "rendering/render_flow.h"
32
33 #include <qptrvector.h>
34 #include <assert.h>
35 #include "KWQKHTMLPart.h"
36
37 class QPainter;
38 class QFontMetrics;
39
40 namespace DOM {
41     class Position;
42     class DocumentMarker;
43 };
44
45 // Define a constant for soft hyphen's unicode value.
46 #define SOFT_HYPHEN 173
47
48 const int cNoTruncation = -1;
49 const int cFullTruncation = -2;
50
51 namespace khtml
52 {
53     class RenderText;
54     class RenderStyle;
55
56 class InlineTextBox : public InlineRunBox
57 {
58 public:
59     InlineTextBox(RenderObject* obj)
60     :InlineRunBox(obj)
61     {
62         m_start = 0;
63         m_len = 0;
64         m_reversed = false;
65         m_treatAsText = true;
66         m_toAdd = 0;
67         m_truncation = cNoTruncation;
68     }
69     
70     InlineTextBox* nextTextBox() const { return static_cast<InlineTextBox*>(nextLineBox()); }
71     InlineTextBox* prevTextBox() const { return static_cast<InlineTextBox*>(prevLineBox()); }
72     
73     uint start() const { return m_start; }
74     uint end() const { return m_len ? m_start+m_len-1 : m_start; }
75     uint len() const { return m_len; }
76
77     void offsetRun(int d) { m_start += d; }
78
79     void detach(RenderArena* arena);
80     
81     QRect selectionRect(int absx, int absy, int startPos, int endPos);
82     bool isSelected(int startPos, int endPos) const;
83     void selectionStartEnd(int& sPos, int& ePos);
84     
85     virtual void paint(RenderObject::PaintInfo& i, int tx, int ty);
86     virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
87
88     RenderText* textObject();
89     
90     virtual void deleteLine(RenderArena* arena);
91     virtual void extractLine();
92     virtual void attachLine();
93
94     virtual RenderObject::SelectionState selectionState();
95
96     virtual void clearTruncation() { m_truncation = cNoTruncation; }
97     virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
98
99     // Overloaded new operator.  Derived classes must override operator new
100     // in order to allocate out of the RenderArena.
101     void* operator new(size_t sz, RenderArena* renderArena) throw();    
102
103     // Overridden to prevent the normal delete from being called.
104     void operator delete(void* ptr, size_t sz);
105         
106 private:
107     // The normal operator new is disallowed.
108     void* operator new(size_t sz) throw();
109
110 public:
111     void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
112     int spaceAdd() { return m_toAdd; }
113
114     virtual bool isInlineTextBox() { return true; }    
115     virtual bool isText() const { return m_treatAsText; }
116     void setIsText(bool b) { m_treatAsText = b; }
117     
118     void paintDecoration(QPainter* p, int _tx, int _ty, int decoration);
119     void paintSelection(QPainter* p, int tx, int ty, RenderStyle* style, const Font* font);
120     void paintMarkedTextBackground(QPainter* p, int tx, int ty, RenderStyle* style, const Font* font, int startPos, int endPos);
121     void paintMarker(QPainter* p, int _tx, int _ty, DOM::DocumentMarker marker);
122     void paintMarkedTextUnderline(QPainter *pt, int _tx, int _ty, KWQKHTMLPart::MarkedTextUnderline underline);
123     virtual long caretMinOffset() const;
124     virtual long caretMaxOffset() const;
125     virtual unsigned long caretMaxRenderedOffset() const;
126     
127     int offsetForPosition(int _x, bool includePartialGlyphs = true);
128     
129     /**
130      * if this text run was rendered @ref _ty pixels below the upper edge
131      * of a view, would the @ref _y -coordinate be inside the vertical range
132      * of this object's representation?
133      */
134     bool checkVerticalPoint(int _y, int _ty, int _h);
135
136     int m_start;
137     unsigned short m_len;
138     
139     int m_truncation; // Where to truncate when text overflow is applied.  We use special constants to
140                       // denote no truncation (the whole run paints) and full truncation (nothing paints at all).
141
142     bool m_reversed : 1;
143     bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
144     int m_toAdd : 14; // for justified text
145
146 private:
147     friend class RenderText;
148 };
149
150 class RenderText : public RenderObject
151 {
152     friend class InlineTextBox;
153
154 public:
155     RenderText(DOM::NodeImpl* node, DOM::DOMStringImpl *_str);
156     virtual ~RenderText();
157
158     virtual bool isTextFragment() const;
159     virtual DOM::DOMStringImpl* originalString() const;
160     
161     virtual const char *renderName() const { return "RenderText"; }
162
163     virtual void setStyle(RenderStyle *style);
164
165     void extractTextBox(InlineTextBox* textBox);
166     void attachTextBox(InlineTextBox* textBox);
167     void removeTextBox(InlineTextBox* textBox);
168     void deleteTextBoxes();
169     virtual void detach();
170     
171     DOM::DOMString data() const { return str; }
172     DOM::DOMStringImpl *string() const { return str; }
173
174     virtual InlineBox* createInlineBox(bool,bool, bool isOnlyRun = false);
175     virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
176     
177     virtual void paint(PaintInfo& i, int tx, int ty) { assert(false); }
178     virtual void layout() { assert(false); }
179
180     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
181                              HitTestAction hitTestAction) { assert(false); return false; }
182
183     virtual void absoluteRects(QValueList<QRect>& rects, int _tx, int _ty);
184
185     virtual VisiblePosition positionForCoordinates(int x, int y);
186
187     unsigned int length() const { return str->l; }
188     QChar *text() const { return str->s; }
189     unsigned int stringLength() const { return str->l; } // non virtual implementation of length()
190     virtual void position(InlineBox* box, int from, int len, bool reverse);
191
192     virtual unsigned int width(unsigned int from, unsigned int len, const Font *f) const;
193     virtual unsigned int width(unsigned int from, unsigned int len, bool firstLine = false) const;
194     virtual int width() const;
195     virtual int height() const;
196
197     // height of the contents (without paddings, margins and borders)
198     virtual short lineHeight( bool firstLine, bool isRootLineBox=false ) const;
199     virtual short baselinePosition( bool firstLine, bool isRootLineBox=false ) const;
200
201     // overrides
202     virtual void calcMinMaxWidth();
203     virtual int minWidth() const { return m_minWidth; }
204     virtual int maxWidth() const { return m_maxWidth; }
205     virtual void trimmedMinMaxWidth(int& beginMinW, bool& beginWS, 
206                                     int& endMinW, bool& endWS,
207                                     bool& hasBreakableChar, bool& hasBreak,
208                                     int& beginMaxW, int& endMaxW,
209                                     int& minW, int& maxW, bool& stripFrontSpaces);
210     
211     bool containsOnlyWhitespace(unsigned int from, unsigned int len) const;
212     
213     // returns the minimum x position of all runs relative to the parent.
214     // defaults to 0.
215     int minXPos() const;
216
217     virtual int xPos() const;
218     virtual int yPos() const;
219
220     virtual const QFont &font();
221     virtual short verticalPositionHint( bool firstLine ) const;
222
223     void setText(DOM::DOMStringImpl *text, bool force=false);
224     void setTextWithOffset(DOM::DOMStringImpl *text, uint offset, uint len, bool force=false);
225
226     virtual bool canBeSelectionLeaf() const { return true; }
227     virtual SelectionState selectionState() const {return m_selectionState;}
228     virtual void setSelectionState(SelectionState s);
229     virtual QRect selectionRect();
230     virtual QRect caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine = 0);
231     void posOfChar(int ch, int &x, int &y);
232
233     virtual int marginLeft() const { return style()->marginLeft().minWidth(0); }
234     virtual int marginRight() const { return style()->marginRight().minWidth(0); }
235
236     virtual QRect getAbsoluteRepaintRect();
237
238     const QFontMetrics &metrics(bool firstLine) const;
239     const Font *htmlFont(bool firstLine) const;
240
241     DOM::TextImpl *element() const
242     { return static_cast<DOM::TextImpl*>(RenderObject::element()); }
243
244     InlineTextBox* firstTextBox() const { return m_firstTextBox; }
245     InlineTextBox* lastTextBox() const { return m_lastTextBox; }
246     
247     virtual InlineBox *inlineBox(long offset, EAffinity affinity = UPSTREAM);
248
249 #if APPLE_CHANGES
250     int widthFromCache(const Font *, int start, int len) const;
251     bool shouldUseMonospaceCache(const Font *) const;
252     void cacheWidths();
253     bool allAscii() const;
254 #endif
255
256     virtual long caretMinOffset() const;
257     virtual long caretMaxOffset() const;
258     virtual unsigned long caretMaxRenderedOffset() const;
259
260     virtual long previousOffset (long current) const;
261     virtual long nextOffset (long current) const;
262     
263 #if APPLE_CHANGES
264 public:
265 #endif
266     InlineTextBox * findNextInlineTextBox( int offset, int &pos ) const;
267
268 protected: // members
269     DOM::DOMStringImpl *str;
270     
271     InlineTextBox* m_firstTextBox;
272     InlineTextBox* m_lastTextBox;
273     
274     int m_minWidth;
275     int m_maxWidth;
276     int m_beginMinWidth;
277     int m_endMinWidth;
278     
279     SelectionState m_selectionState : 3 ;
280     bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
281     bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
282     bool m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre)
283     bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
284     
285     bool m_linesDirty : 1; // This bit indicates that the text run has already dirtied specific
286                            // line boxes, and this hint will enable layoutInlineChildren to avoid
287                            // just dirtying everything when character data is modified (e.g., appended/inserted
288                            // or removed).
289
290     // 22 bits left
291 #if APPLE_CHANGES
292     mutable bool m_allAsciiChecked:1;
293     mutable bool m_allAscii:1;
294     int m_monospaceCharacterWidth;
295 #endif
296 };
297
298 // Used to represent a text substring of an element, e.g., for text runs that are split because of
299 // first letter and that must therefore have different styles (and positions in the render tree).
300 // We cache offsets so that text transformations can be applied in such a way that we can recover
301 // the original unaltered string from our corresponding DOM node.
302 class RenderTextFragment : public RenderText
303 {
304 public:
305     RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
306                        int startOffset, int endOffset);
307     RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str);
308     ~RenderTextFragment();
309     
310     virtual bool isTextFragment() const;
311     
312     uint start() const { return m_start; }
313     uint end() const { return m_end; }
314     
315     DOM::DOMStringImpl* contentString() const { return m_generatedContentStr; }
316     virtual DOM::DOMStringImpl* originalString() const;
317     
318 private:
319     uint m_start;
320     uint m_end;
321     DOM::DOMStringImpl* m_generatedContentStr;
322 };
323 };
324 #endif