initial import
[vuplus_webkit] / 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 #if ENABLE(SVG)
49         , m_hasVirtualLogicalHeight(false)
50 #endif
51         , m_isHorizontal(true)
52         , m_endsWithBreak(false)
53         , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
54         , m_knownToHaveNoOverflow(true)
55         , m_hasEllipsisBoxOrHyphen(false)
56         , m_dirOverride(false)
57         , m_isText(false)
58         , m_determinedIfNextOnLineExists(false)
59         , m_determinedIfPrevOnLineExists(false)
60         , m_nextOnLineExists(false)
61         , m_prevOnLineExists(false)
62         , m_expansion(0)
63 #ifndef NDEBUG
64         , m_hasBadParent(false)
65 #endif
66     {
67     }
68
69     InlineBox(RenderObject* obj, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed,
70               bool dirty, bool extracted, bool isHorizontal, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
71         : m_next(next)
72         , m_prev(prev)
73         , m_parent(parent)
74         , m_renderer(obj)
75         , m_topLeft(topLeft)
76         , m_logicalWidth(logicalWidth)
77         , m_firstLine(firstLine)
78         , m_constructed(constructed)
79         , m_bidiEmbeddingLevel(0)
80         , m_dirty(dirty)
81         , m_extracted(extracted)
82 #if ENABLE(SVG)
83         , m_hasVirtualLogicalHeight(false)
84 #endif
85         , m_isHorizontal(isHorizontal)
86         , m_endsWithBreak(false)
87         , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
88         , m_knownToHaveNoOverflow(true)  
89         , m_hasEllipsisBoxOrHyphen(false)
90         , m_dirOverride(false)
91         , m_isText(false)
92         , m_determinedIfNextOnLineExists(false)
93         , m_determinedIfPrevOnLineExists(false)
94         , m_nextOnLineExists(false)
95         , m_prevOnLineExists(false)
96         , m_expansion(0)
97 #ifndef NDEBUG
98         , m_hasBadParent(false)
99 #endif
100     {
101     }
102
103     virtual ~InlineBox();
104
105     virtual void destroy(RenderArena*);
106
107     virtual void deleteLine(RenderArena*);
108     virtual void extractLine();
109     virtual void attachLine();
110
111     virtual bool isLineBreak() const { return false; }
112
113     virtual void adjustPosition(float dx, float dy);
114     void adjustLineDirectionPosition(float delta)
115     {
116         if (isHorizontal())
117             adjustPosition(delta, 0);
118         else
119             adjustPosition(0, delta);
120     }
121     void adjustBlockDirectionPosition(float delta)
122     {
123         if (isHorizontal())
124             adjustPosition(0, delta);
125         else
126             adjustPosition(delta, 0);
127     }
128
129     virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
130     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
131
132     InlineBox* next() const { return m_next; }
133
134     // Overloaded new operator.
135     void* operator new(size_t, RenderArena*) throw();
136
137     // Overridden to prevent the normal delete from being called.
138     void operator delete(void*, size_t);
139
140 private:
141     // The normal operator new is disallowed.
142     void* operator new(size_t) throw();
143
144 public:
145 #ifndef NDEBUG
146     void showTreeForThis() const;
147     void showLineTreeForThis() const;
148     
149     virtual void showBox(int = 0) const;
150     virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
151     virtual const char* boxName() const;
152 #endif
153
154     bool isText() const { return m_isText; }
155     void setIsText(bool b) { m_isText = b; }
156  
157     virtual bool isInlineFlowBox() const { return false; }
158     virtual bool isInlineTextBox() const { return false; }
159     virtual bool isRootInlineBox() const { return false; }
160 #if ENABLE(SVG)
161     virtual bool isSVGInlineTextBox() const { return false; }
162     virtual bool isSVGInlineFlowBox() const { return false; }
163     virtual bool isSVGRootInlineBox() const { return false; }
164 #endif
165
166     bool hasVirtualLogicalHeight() const { return m_hasVirtualLogicalHeight; }
167     void setHasVirtualLogicalHeight() { m_hasVirtualLogicalHeight = true; }
168     virtual int virtualLogicalHeight() const
169     {
170         ASSERT_NOT_REACHED();
171         return 0;
172     }
173
174     bool isHorizontal() const { return m_isHorizontal; }
175     void setIsHorizontal(bool horizontal) { m_isHorizontal = horizontal; }
176
177     virtual IntRect calculateBoundaries() const
178     {
179         ASSERT_NOT_REACHED();
180         return IntRect();
181     }
182
183     bool isConstructed() { return m_constructed; }
184     virtual void setConstructed() { m_constructed = true; }
185
186     void setExtracted(bool b = true) { m_extracted = b; }
187     
188     void setFirstLineStyleBit(bool f) { m_firstLine = f; }
189     bool isFirstLineStyle() const { return m_firstLine; }
190
191     void remove();
192
193     InlineBox* nextOnLine() const { return m_next; }
194     InlineBox* prevOnLine() const { return m_prev; }
195     void setNextOnLine(InlineBox* next)
196     {
197         ASSERT(m_parent || !next);
198         m_next = next;
199     }
200     void setPrevOnLine(InlineBox* prev)
201     {
202         ASSERT(m_parent || !prev);
203         m_prev = prev;
204     }
205     bool nextOnLineExists() const;
206     bool prevOnLineExists() const;
207
208     virtual bool isLeaf() const { return true; }
209     
210     InlineBox* nextLeafChild() const;
211     InlineBox* prevLeafChild() const;
212         
213     RenderObject* renderer() const { return m_renderer; }
214
215     InlineFlowBox* parent() const
216     {
217         ASSERT(!m_hasBadParent);
218         return m_parent;
219     }
220     void setParent(InlineFlowBox* par) { m_parent = par; }
221
222     const RootInlineBox* root() const;
223     RootInlineBox* root();
224
225     // x() is the left side of the box in the containing block's coordinate system.
226     void setX(float x) { m_topLeft.setX(x); }
227     float x() const { return m_topLeft.x(); }
228     float left() const { return m_topLeft.x(); }
229
230     // y() is the top side of the box in the containing block's coordinate system.
231     void setY(float y) { m_topLeft.setY(y); }
232     float y() const { return m_topLeft.y(); }
233     float top() const { return m_topLeft.y(); }
234
235     const FloatPoint& topLeft() const { return m_topLeft; }
236
237     float width() const { return isHorizontal() ? logicalWidth() : logicalHeight(); }
238     float height() const { return isHorizontal() ? logicalHeight() : logicalWidth(); }
239     FloatSize size() const { return IntSize(width(), height()); }
240     float right() const { return left() + width(); }
241     float bottom() const { return top() + height(); }
242
243     // The logicalLeft position is the left edge of the line box in a horizontal line and the top edge in a vertical line.
244     float logicalLeft() const { return isHorizontal() ? m_topLeft.x() : m_topLeft.y(); }
245     float logicalRight() const { return logicalLeft() + logicalWidth(); }
246     void setLogicalLeft(float left)
247     {
248         if (isHorizontal())
249             setX(left);
250         else
251             setY(left);
252     }
253     int pixelSnappedLogicalLeft() const { return logicalLeft(); }
254     int pixelSnappedLogicalRight() const { return ceilf(logicalRight()); }
255
256     // The logicalTop[ position is the top edge of the line box in a horizontal line and the left edge in a vertical line.
257     LayoutUnit logicalTop() const { return isHorizontal() ? m_topLeft.y() : m_topLeft.x(); }
258     LayoutUnit logicalBottom() const { return logicalTop() + logicalHeight(); }
259     void setLogicalTop(LayoutUnit top)
260     {
261         if (isHorizontal())
262             setY(top);
263         else
264             setX(top);
265     }
266
267     // The logical width is our extent in the line's overall inline direction, i.e., width for horizontal text and height for vertical text.
268     void setLogicalWidth(float w) { m_logicalWidth = w; }
269     float logicalWidth() const { return m_logicalWidth; }
270
271     // The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text.
272     LayoutUnit logicalHeight() const;
273
274     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()); }
275
276     virtual LayoutUnit baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
277     virtual LayoutUnit lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
278     
279     virtual int caretMinOffset() const;
280     virtual int caretMaxOffset() const;
281     virtual unsigned caretMaxRenderedOffset() const;
282
283     unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
284     void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
285     TextDirection direction() const { return m_bidiEmbeddingLevel % 2 ? RTL : LTR; }
286     bool isLeftToRightDirection() const { return direction() == LTR; }
287     int caretLeftmostOffset() const { return isLeftToRightDirection() ? caretMinOffset() : caretMaxOffset(); }
288     int caretRightmostOffset() const { return isLeftToRightDirection() ? caretMaxOffset() : caretMinOffset(); }
289
290     virtual void clearTruncation() { }
291
292     bool isDirty() const { return m_dirty; }
293     void markDirty(bool dirty = true) { m_dirty = dirty; }
294
295     void dirtyLineBoxes();
296     
297     virtual RenderObject::SelectionState selectionState();
298
299     virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
300     // visibleLeftEdge, visibleRightEdge are in the parent's coordinate system.
301     virtual float placeEllipsisBox(bool ltr, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, bool&);
302
303     void setHasBadParent();
304
305     int expansion() const { return m_expansion; }
306     
307     bool visibleToHitTesting() const { return renderer()->style()->visibility() == VISIBLE && renderer()->style()->pointerEvents() != PE_NONE; }
308     
309     EVerticalAlign verticalAlign() const { return renderer()->style(m_firstLine)->verticalAlign(); }
310
311     // Use with caution! The type is not checked!
312     RenderBoxModelObject* boxModelObject() const
313     { 
314         if (!m_renderer->isText())
315             return toRenderBoxModelObject(m_renderer);
316         return 0;
317     }
318
319     FloatPoint locationIncludingFlipping();
320     void flipForWritingMode(FloatRect&);
321     FloatPoint flipForWritingMode(const FloatPoint&);
322     void flipForWritingMode(IntRect&);
323     IntPoint flipForWritingMode(const IntPoint&);
324
325     bool knownToHaveNoOverflow() const { return m_knownToHaveNoOverflow; }
326     void clearKnownToHaveNoOverflow();
327
328 private:
329     InlineBox* m_next; // The next element on the same line as us.
330     InlineBox* m_prev; // The previous element on the same line as us.
331
332     InlineFlowBox* m_parent; // The box that contains us.
333
334 public:
335     RenderObject* m_renderer;
336
337     FloatPoint m_topLeft;
338     float m_logicalWidth;
339     
340     // Some of these bits are actually for subclasses and moved here to compact the structures.
341
342     // for this class
343 protected:
344     bool m_firstLine : 1;
345 private:
346     bool m_constructed : 1;
347     unsigned char m_bidiEmbeddingLevel : 6;
348 protected:
349     bool m_dirty : 1;
350     bool m_extracted : 1;
351     bool m_hasVirtualLogicalHeight : 1;
352
353     bool m_isHorizontal : 1;
354
355     // for RootInlineBox
356     bool m_endsWithBreak : 1;  // Whether the line ends with a <br>.
357     // shared between RootInlineBox and InlineTextBox
358     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).
359     bool m_knownToHaveNoOverflow : 1;
360     bool m_hasEllipsisBoxOrHyphen : 1;
361
362     // for InlineTextBox
363 public:
364     bool m_dirOverride : 1;
365     bool m_isText : 1; // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
366 protected:
367     mutable bool m_determinedIfNextOnLineExists : 1;
368     mutable bool m_determinedIfPrevOnLineExists : 1;
369     mutable bool m_nextOnLineExists : 1;
370     mutable bool m_prevOnLineExists : 1;
371     signed m_expansion : 11; // for justified text
372
373 #ifndef NDEBUG
374 private:
375     bool m_hasBadParent;
376 #endif
377 };
378
379 #ifdef NDEBUG
380 inline InlineBox::~InlineBox()
381 {
382 }
383 #endif
384
385 inline void InlineBox::setHasBadParent()
386 {
387 #ifndef NDEBUG
388     m_hasBadParent = true;
389 #endif
390 }
391
392 } // namespace WebCore
393
394 #ifndef NDEBUG
395 // Outside the WebCore namespace for ease of invocation from gdb.
396 void showTree(const WebCore::InlineBox*);
397 void showLineTree(const WebCore::InlineBox*);
398 #endif
399
400 #endif // InlineBox_h