Reviewed by John.
[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) const;
128     int positionForOffset(int offset) const;
129     
130     /**
131      * if this text run was rendered @ref _ty pixels below the upper edge
132      * of a view, would the @ref _y -coordinate be inside the vertical range
133      * of this object's representation?
134      */
135     bool checkVerticalPoint(int _y, int _ty, int _h);
136
137     int m_start;
138     unsigned short m_len;
139     
140     int m_truncation; // Where to truncate when text overflow is applied.  We use special constants to
141                       // denote no truncation (the whole run paints) and full truncation (nothing paints at all).
142
143     bool m_reversed : 1;
144     bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
145     int m_toAdd : 14; // for justified text
146
147 private:
148     friend class RenderText;
149 };
150
151 class RenderText : public RenderObject
152 {
153     friend class InlineTextBox;
154
155 public:
156     RenderText(DOM::NodeImpl* node, DOM::DOMStringImpl *_str);
157     virtual ~RenderText();
158
159     virtual bool isTextFragment() const;
160     virtual DOM::DOMStringImpl* originalString() const;
161     
162     virtual const char *renderName() const { return "RenderText"; }
163
164     virtual void setStyle(RenderStyle *style);
165
166     void extractTextBox(InlineTextBox* textBox);
167     void attachTextBox(InlineTextBox* textBox);
168     void removeTextBox(InlineTextBox* textBox);
169     void deleteTextBoxes();
170     virtual void detach();
171     
172     DOM::DOMString data() const { return str; }
173     DOM::DOMStringImpl *string() const { return str; }
174
175     virtual InlineBox* createInlineBox(bool,bool, bool isOnlyRun = false);
176     virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
177     
178     virtual void paint(PaintInfo& i, int tx, int ty) { assert(false); }
179     virtual void layout() { assert(false); }
180
181     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
182                              HitTestAction hitTestAction) { assert(false); return false; }
183
184     virtual void absoluteRects(QValueList<QRect>& rects, int _tx, int _ty);
185
186     virtual VisiblePosition positionForCoordinates(int x, int y);
187
188     unsigned int length() const { return str->l; }
189     QChar *text() const { return str->s; }
190     unsigned int stringLength() const { return str->l; } // non virtual implementation of length()
191     virtual void position(InlineBox* box, int from, int len, bool reverse);
192
193     virtual unsigned int width(unsigned int from, unsigned int len, const Font *f) const;
194     virtual unsigned int width(unsigned int from, unsigned int len, bool firstLine = false) const;
195     virtual int width() const;
196     virtual int height() const;
197
198     // height of the contents (without paddings, margins and borders)
199     virtual short lineHeight( bool firstLine, bool isRootLineBox=false ) const;
200     virtual short baselinePosition( bool firstLine, bool isRootLineBox=false ) const;
201
202     // overrides
203     virtual void calcMinMaxWidth();
204     virtual int minWidth() const { return m_minWidth; }
205     virtual int maxWidth() const { return m_maxWidth; }
206     virtual void trimmedMinMaxWidth(int& beginMinW, bool& beginWS, 
207                                     int& endMinW, bool& endWS,
208                                     bool& hasBreakableChar, bool& hasBreak,
209                                     int& beginMaxW, int& endMaxW,
210                                     int& minW, int& maxW, bool& stripFrontSpaces);
211     
212     bool containsOnlyWhitespace(unsigned int from, unsigned int len) const;
213     
214     // returns the minimum x position of all runs relative to the parent.
215     // defaults to 0.
216     int minXPos() const;
217
218     virtual int xPos() const;
219     virtual int yPos() const;
220
221     virtual const QFont &font();
222     virtual short verticalPositionHint( bool firstLine ) const;
223
224     void setText(DOM::DOMStringImpl *text, bool force=false);
225     void setTextWithOffset(DOM::DOMStringImpl *text, uint offset, uint len, bool force=false);
226
227     virtual bool canBeSelectionLeaf() const { return true; }
228     virtual SelectionState selectionState() const {return m_selectionState;}
229     virtual void setSelectionState(SelectionState s);
230     virtual QRect selectionRect();
231     virtual QRect caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine = 0);
232     void posOfChar(int ch, int &x, int &y);
233
234     virtual int marginLeft() const { return style()->marginLeft().minWidth(0); }
235     virtual int marginRight() const { return style()->marginRight().minWidth(0); }
236
237     virtual QRect getAbsoluteRepaintRect();
238
239     const QFontMetrics &metrics(bool firstLine) const;
240     const Font *htmlFont(bool firstLine) const;
241
242     DOM::TextImpl *element() const
243     { return static_cast<DOM::TextImpl*>(RenderObject::element()); }
244
245     InlineTextBox* firstTextBox() const { return m_firstTextBox; }
246     InlineTextBox* lastTextBox() const { return m_lastTextBox; }
247     
248     virtual InlineBox *inlineBox(long offset, EAffinity affinity = UPSTREAM);
249
250 #if APPLE_CHANGES
251     int widthFromCache(const Font *, int start, int len) const;
252     bool shouldUseMonospaceCache(const Font *) const;
253     void cacheWidths();
254     bool allAscii() const;
255 #endif
256
257     virtual long caretMinOffset() const;
258     virtual long caretMaxOffset() const;
259     virtual unsigned long caretMaxRenderedOffset() const;
260
261     virtual long previousOffset (long current) const;
262     virtual long nextOffset (long current) const;
263     
264 #if APPLE_CHANGES
265 public:
266 #endif
267     InlineTextBox * findNextInlineTextBox( int offset, int &pos ) const;
268
269 protected: // members
270     DOM::DOMStringImpl *str;
271     
272     InlineTextBox* m_firstTextBox;
273     InlineTextBox* m_lastTextBox;
274     
275     int m_minWidth;
276     int m_maxWidth;
277     int m_beginMinWidth;
278     int m_endMinWidth;
279     
280     SelectionState m_selectionState : 3 ;
281     bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
282     bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
283     bool m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre)
284     bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
285     
286     bool m_linesDirty : 1; // This bit indicates that the text run has already dirtied specific
287                            // line boxes, and this hint will enable layoutInlineChildren to avoid
288                            // just dirtying everything when character data is modified (e.g., appended/inserted
289                            // or removed).
290
291     // 22 bits left
292 #if APPLE_CHANGES
293     mutable bool m_allAsciiChecked:1;
294     mutable bool m_allAscii:1;
295     int m_monospaceCharacterWidth;
296 #endif
297 };
298
299 // Used to represent a text substring of an element, e.g., for text runs that are split because of
300 // first letter and that must therefore have different styles (and positions in the render tree).
301 // We cache offsets so that text transformations can be applied in such a way that we can recover
302 // the original unaltered string from our corresponding DOM node.
303 class RenderTextFragment : public RenderText
304 {
305 public:
306     RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
307                        int startOffset, int endOffset);
308     RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str);
309     ~RenderTextFragment();
310     
311     virtual bool isTextFragment() const;
312     
313     uint start() const { return m_start; }
314     uint end() const { return m_end; }
315     
316     DOM::DOMStringImpl* contentString() const { return m_generatedContentStr; }
317     virtual DOM::DOMStringImpl* originalString() const;
318     
319 private:
320     uint m_start;
321     uint m_end;
322     DOM::DOMStringImpl* m_generatedContentStr;
323 };
324 };
325 #endif