tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebCore / rendering / InlineBox.h
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifndef InlineBox_h
22 #define InlineBox_h
23
24 #include "RenderBoxModelObject.h"
25 #include "TextDirection.h"
26
27 namespace WebCore {
28
29 class HitTestRequest;
30 class HitTestResult;
31 class RootInlineBox;
32
33 // InlineBox represents a rectangle that occurs on a line.  It corresponds to
34 // some RenderObject (i.e., it represents a portion of that RenderObject).
35 class InlineBox {
36 public:
37     InlineBox(RenderObject* obj)
38         : m_next(0)
39         , m_prev(0)
40         , m_parent(0)
41         , m_renderer(obj)
42         , m_logicalWidth(0)
43         , m_firstLine(false)
44         , m_constructed(false)
45         , m_bidiEmbeddingLevel(0)
46         , m_dirty(false)
47         , m_extracted(false)
48         , m_hasVirtualLogicalHeight(false)
49         , m_isHorizontal(true)
50         , m_endsWithBreak(false)
51         , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
52         , m_knownToHaveNoOverflow(true)
53         , m_hasEllipsisBoxOrHyphen(false)
54         , m_dirOverride(false)
55         , m_isText(false)
56         , m_determinedIfNextOnLineExists(false)
57         , m_nextOnLineExists(false)
58         , m_expansion(0)
59 #ifndef NDEBUG
60         , m_hasBadParent(false)
61 #endif
62     {
63     }
64
65     InlineBox(RenderObject* obj, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed,
66               bool dirty, bool extracted, bool isHorizontal, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
67         : m_next(next)
68         , m_prev(prev)
69         , m_parent(parent)
70         , m_renderer(obj)
71         , m_topLeft(topLeft)
72         , m_logicalWidth(logicalWidth)
73         , m_firstLine(firstLine)
74         , m_constructed(constructed)
75         , m_bidiEmbeddingLevel(0)
76         , m_dirty(dirty)
77         , m_extracted(extracted)
78         , m_hasVirtualLogicalHeight(false)
79         , m_isHorizontal(isHorizontal)
80         , m_endsWithBreak(false)
81         , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
82         , m_knownToHaveNoOverflow(true)  
83         , m_hasEllipsisBoxOrHyphen(false)
84         , m_dirOverride(false)
85         , m_isText(false)
86         , m_determinedIfNextOnLineExists(false)
87         , m_nextOnLineExists(false)
88         , m_expansion(0)
89 #ifndef NDEBUG
90         , m_hasBadParent(false)
91 #endif
92     {
93     }
94
95     virtual ~InlineBox();
96
97     virtual void destroy(RenderArena*);
98
99     virtual void deleteLine(RenderArena*);
100     virtual void extractLine();
101     virtual void attachLine();
102
103     virtual bool isLineBreak() const { return false; }
104
105     virtual void adjustPosition(float dx, float dy);
106     void adjustLineDirectionPosition(float delta)
107     {
108         if (isHorizontal())
109             adjustPosition(delta, 0);
110         else
111             adjustPosition(0, delta);
112     }
113     void adjustBlockDirectionPosition(float delta)
114     {
115         if (isHorizontal())
116             adjustPosition(0, delta);
117         else
118             adjustPosition(delta, 0);
119     }
120
121     virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
122     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
123
124     InlineBox* next() const { return m_next; }
125
126     // Overloaded new operator.
127     void* operator new(size_t, RenderArena*) throw();
128
129     // Overridden to prevent the normal delete from being called.
130     void operator delete(void*, size_t);
131
132 private:
133     // The normal operator new is disallowed.
134     void* operator new(size_t) throw();
135
136 public:
137 #ifndef NDEBUG
138     void showTreeForThis() const;
139     void showLineTreeForThis() const;
140     
141     virtual void showBox(int = 0) const;
142     virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
143     virtual const char* boxName() const;
144 #endif
145
146     bool isText() const { return m_isText; }
147     void setIsText(bool b) { m_isText = b; }
148  
149     virtual bool isInlineFlowBox() const { return false; }
150     virtual bool isInlineTextBox() const { return false; }
151     virtual bool isRootInlineBox() const { return false; }
152 #if ENABLE(SVG)
153     virtual bool isSVGInlineTextBox() const { return false; }
154     virtual bool isSVGInlineFlowBox() const { return false; }
155     virtual bool isSVGRootInlineBox() const { return false; }
156 #endif
157
158     bool hasVirtualLogicalHeight() const { return m_hasVirtualLogicalHeight; }
159     void setHasVirtualLogicalHeight() { m_hasVirtualLogicalHeight = true; }
160     virtual float virtualLogicalHeight() const
161     {
162         ASSERT_NOT_REACHED();
163         return 0;
164     }
165
166     bool isHorizontal() const { return m_isHorizontal; }
167     void setIsHorizontal(bool horizontal) { m_isHorizontal = horizontal; }
168
169     virtual FloatRect calculateBoundaries() const
170     {
171         ASSERT_NOT_REACHED();
172         return FloatRect();
173     }
174
175     bool isConstructed() { return m_constructed; }
176     virtual void setConstructed() { m_constructed = true; }
177
178     void setExtracted(bool b = true) { m_extracted = b; }
179     
180     void setFirstLineStyleBit(bool f) { m_firstLine = f; }
181     bool isFirstLineStyle() const { return m_firstLine; }
182
183     void remove();
184
185     InlineBox* nextOnLine() const { return m_next; }
186     InlineBox* prevOnLine() const { return m_prev; }
187     void setNextOnLine(InlineBox* next)
188     {
189         ASSERT(m_parent || !next);
190         m_next = next;
191     }
192     void setPrevOnLine(InlineBox* prev)
193     {
194         ASSERT(m_parent || !prev);
195         m_prev = prev;
196     }
197     bool nextOnLineExists() const;
198
199     virtual bool isLeaf() const { return true; }
200     
201     InlineBox* nextLeafChild() const;
202     InlineBox* prevLeafChild() const;
203         
204     RenderObject* renderer() const { return m_renderer; }
205
206     InlineFlowBox* parent() const
207     {
208         ASSERT(!m_hasBadParent);
209         return m_parent;
210     }
211     void setParent(InlineFlowBox* par) { m_parent = par; }
212
213     const RootInlineBox* root() const;
214     RootInlineBox* root();
215
216     // x() is the left side of the box in the containing block's coordinate system.
217     void setX(float x) { m_topLeft.setX(x); }
218     float x() const { return m_topLeft.x(); }
219     float left() const { return m_topLeft.x(); }
220
221     // y() is the top side of the box in the containing block's coordinate system.
222     void setY(float y) { m_topLeft.setY(y); }
223     float y() const { return m_topLeft.y(); }
224     float top() const { return m_topLeft.y(); }
225
226     const FloatPoint& topLeft() const { return m_topLeft; }
227
228     float width() const { return isHorizontal() ? logicalWidth() : logicalHeight(); }
229     float height() const { return isHorizontal() ? logicalHeight() : logicalWidth(); }
230     FloatSize size() const { return IntSize(width(), height()); }
231     float right() const { return left() + width(); }
232     float bottom() const { return top() + height(); }
233
234     // The logicalLeft position is the left edge of the line box in a horizontal line and the top edge in a vertical line.
235     float logicalLeft() const { return isHorizontal() ? m_topLeft.x() : m_topLeft.y(); }
236     float logicalRight() const { return logicalLeft() + logicalWidth(); }
237     void setLogicalLeft(float left)
238     {
239         if (isHorizontal())
240             setX(left);
241         else
242             setY(left);
243     }
244     int pixelSnappedLogicalLeft() const { return logicalLeft(); }
245     int pixelSnappedLogicalRight() const { return ceilf(logicalRight()); }
246     int pixelSnappedLogicalTop() const { return logicalTop(); }
247     int pixelSnappedLogicalBottom() const { return ceilf(logicalBottom()); }
248
249     // The logicalTop[ position is the top edge of the line box in a horizontal line and the left edge in a vertical line.
250     float logicalTop() const { return isHorizontal() ? m_topLeft.y() : m_topLeft.x(); }
251     float logicalBottom() const { return logicalTop() + logicalHeight(); }
252     void setLogicalTop(float top)
253     {
254         if (isHorizontal())
255             setY(top);
256         else
257             setX(top);
258     }
259
260     // The logical width is our extent in the line's overall inline direction, i.e., width for horizontal text and height for vertical text.
261     void setLogicalWidth(float w) { m_logicalWidth = w; }
262     float logicalWidth() const { return m_logicalWidth; }
263
264     // The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text.
265     float logicalHeight() const;
266
267     FloatRect logicalFrameRect() const { return isHorizontal() ? FloatRect(m_topLeft.x(), m_topLeft.y(), m_logicalWidth, logicalHeight()) : FloatRect(m_topLeft.y(), m_topLeft.x(), m_logicalWidth, logicalHeight()); }
268
269     virtual LayoutUnit baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
270     virtual LayoutUnit lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
271     
272     virtual int caretMinOffset() const;
273     virtual int caretMaxOffset() const;
274
275     unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
276     void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
277     TextDirection direction() const { return m_bidiEmbeddingLevel % 2 ? RTL : LTR; }
278     bool isLeftToRightDirection() const { return direction() == LTR; }
279     int caretLeftmostOffset() const { return isLeftToRightDirection() ? caretMinOffset() : caretMaxOffset(); }
280     int caretRightmostOffset() const { return isLeftToRightDirection() ? caretMaxOffset() : caretMinOffset(); }
281
282     virtual void clearTruncation() { }
283
284     bool isDirty() const { return m_dirty; }
285     void markDirty(bool dirty = true) { m_dirty = dirty; }
286
287     void dirtyLineBoxes();
288     
289     virtual RenderObject::SelectionState selectionState();
290
291     virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
292     // visibleLeftEdge, visibleRightEdge are in the parent's coordinate system.
293     virtual float placeEllipsisBox(bool ltr, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, bool&);
294
295     void setHasBadParent();
296
297     int expansion() const { return m_expansion; }
298     
299     bool visibleToHitTesting() const { return renderer()->style()->visibility() == VISIBLE && renderer()->style()->pointerEvents() != PE_NONE; }
300     
301     EVerticalAlign verticalAlign() const { return renderer()->style(m_firstLine)->verticalAlign(); }
302
303     // Use with caution! The type is not checked!
304     RenderBoxModelObject* boxModelObject() const
305     { 
306         if (!m_renderer->isText())
307             return toRenderBoxModelObject(m_renderer);
308         return 0;
309     }
310
311     FloatPoint locationIncludingFlipping();
312     void flipForWritingMode(FloatRect&);
313     FloatPoint flipForWritingMode(const FloatPoint&);
314     void flipForWritingMode(IntRect&);
315     IntPoint flipForWritingMode(const IntPoint&);
316
317     bool knownToHaveNoOverflow() const { return m_knownToHaveNoOverflow; }
318     void clearKnownToHaveNoOverflow();
319
320 private:
321     InlineBox* m_next; // The next element on the same line as us.
322     InlineBox* m_prev; // The previous element on the same line as us.
323
324     InlineFlowBox* m_parent; // The box that contains us.
325
326 public:
327     RenderObject* m_renderer;
328
329     FloatPoint m_topLeft;
330     float m_logicalWidth;
331     
332     // Some of these bits are actually for subclasses and moved here to compact the structures.
333
334     // for this class
335 protected:
336     bool m_firstLine : 1;
337 private:
338     bool m_constructed : 1;
339     unsigned char m_bidiEmbeddingLevel : 6;
340 protected:
341     bool m_dirty : 1;
342     bool m_extracted : 1;
343     bool m_hasVirtualLogicalHeight : 1;
344
345     bool m_isHorizontal : 1;
346
347     // for RootInlineBox
348     bool m_endsWithBreak : 1;  // Whether the line ends with a <br>.
349     // shared between RootInlineBox and InlineTextBox
350     bool m_hasSelectedChildrenOrCanHaveLeadingExpansion : 1; // Whether we have any children selected (this bit will also be set if the <br> that terminates our line is selected).
351     bool m_knownToHaveNoOverflow : 1;
352     bool m_hasEllipsisBoxOrHyphen : 1;
353
354     // for InlineTextBox
355 public:
356     bool m_dirOverride : 1;
357     bool m_isText : 1; // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
358 protected:
359     mutable bool m_determinedIfNextOnLineExists : 1;
360     mutable bool m_nextOnLineExists : 1;
361     signed m_expansion : 11; // for justified text
362
363 #ifndef NDEBUG
364 private:
365     bool m_hasBadParent;
366 #endif
367 };
368
369 #ifdef NDEBUG
370 inline InlineBox::~InlineBox()
371 {
372 }
373 #endif
374
375 inline void InlineBox::setHasBadParent()
376 {
377 #ifndef NDEBUG
378     m_hasBadParent = true;
379 #endif
380 }
381
382 } // namespace WebCore
383
384 #ifndef NDEBUG
385 // Outside the WebCore namespace for ease of invocation from gdb.
386 void showTree(const WebCore::InlineBox*);
387 void showLineTree(const WebCore::InlineBox*);
388 #endif
389
390 #endif // InlineBox_h