0bf70d3834060b96116c8224dd244e706b60ead7
[WebKit-https.git] / WebCore / rendering / RenderBlock.h
1 /*
2  * This file is part of the render object implementation for KHTML.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  * Copyright (C) 2003, 2004, 2005, 2006 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 RenderBlock_h
25 #define RenderBlock_h
26
27 #include "DeprecatedPtrList.h"
28 #include "GapRects.h"
29 #include "RenderFlow.h"
30 #include "RootInlineBox.h"
31
32 namespace WebCore {
33
34 class Position;
35
36 enum CaretType { CursorCaret, DragCaret };
37
38 class RenderBlock : public RenderFlow {
39 public:
40     typedef Vector<UChar, 1024> CharacterBuffer;
41     static void bidiReorderCharacters(Document*, RenderStyle*, CharacterBuffer&);
42
43     RenderBlock(Node*);
44     virtual ~RenderBlock();
45
46     virtual const char* renderName() const;
47
48     // These two functions are overridden for inline-block.
49     virtual short lineHeight(bool firstLine, bool isRootLineBox = false) const;
50     virtual short baselinePosition(bool firstLine, bool isRootLineBox = false) const;
51
52     virtual bool isRenderBlock() const { return true; }
53     virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
54     virtual bool isInlineFlow() const { return isInline() && !isReplaced(); }
55     virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
56
57     virtual bool childrenInline() const { return m_childrenInline; }
58     virtual void setChildrenInline(bool b) { m_childrenInline = b; }
59     void makeChildrenNonInline(RenderObject* insertionPoint = 0);
60     void deleteLineBoxTree();
61
62     // The height (and width) of a block when you include overflow spillage out of the bottom
63     // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
64     // it would have an overflow height of borderTop() + paddingTop() + 100px.
65     virtual int overflowHeight(bool includeInterior = true) const;
66     virtual int overflowWidth(bool includeInterior = true) const;
67     virtual int overflowLeft(bool includeInterior = true) const;
68     virtual int overflowTop(bool includeInterior = true) const;
69     virtual IntRect overflowRect(bool includeInterior = true) const;
70     virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
71     virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
72
73     void addVisualOverflow(const IntRect&);
74
75     virtual bool isSelfCollapsingBlock() const;
76     virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
77     virtual bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
78
79     virtual int maxTopMargin(bool positive) const { return positive ? maxTopPosMargin() : maxTopNegMargin(); }
80     virtual int maxBottomMargin(bool positive) const { return positive ? maxBottomPosMargin() : maxBottomNegMargin(); }
81
82     int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); }
83     int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); }
84     int maxBottomPosMargin() const { return m_maxMargin ? m_maxMargin->m_bottomPos : MaxMargin::bottomPosDefault(this); }
85     int maxBottomNegMargin() const { return m_maxMargin ? m_maxMargin->m_bottomNeg : MaxMargin::bottomNegDefault(this); }
86     void setMaxTopMargins(int pos, int neg);
87     void setMaxBottomMargins(int pos, int neg);
88     
89     void initMaxMarginValues()
90     {
91         if (m_maxMargin) {
92             m_maxMargin->m_topPos = MaxMargin::topPosDefault(this);
93             m_maxMargin->m_topNeg = MaxMargin::topNegDefault(this);
94             m_maxMargin->m_bottomPos = MaxMargin::bottomPosDefault(this);
95             m_maxMargin->m_bottomNeg = MaxMargin::bottomNegDefault(this);
96         }
97     }
98
99     virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
100     virtual void removeChild(RenderObject*);
101
102     virtual void repaintOverhangingFloats(bool paintAllDescendants);
103
104     virtual void setStyle(RenderStyle*);
105
106     virtual void layout();
107     virtual void layoutBlock(bool relayoutChildren);
108     void layoutBlockChildren(bool relayoutChildren);
109     void layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom);
110
111     void layoutPositionedObjects(bool relayoutChildren);
112     void insertPositionedObject(RenderObject*);
113     void removePositionedObject(RenderObject*);
114     virtual void removePositionedObjects(RenderBlock*);
115
116     virtual void positionListMarker() { }
117
118     virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
119
120     // Called to lay out the legend for a fieldset.
121     virtual RenderObject* layoutLegend(bool relayoutChildren) { return 0; };
122
123     // the implementation of the following functions is in bidi.cpp
124     void bidiReorderLine(const BidiIterator& start, const BidiIterator& end, BidiState& bidi);
125     RootInlineBox* determineStartPosition(bool fullLayout, BidiIterator& start, BidiState& bidi);
126     RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart,
127                                         BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext,
128                                         int& yPos);
129     bool matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,
130                         const BidiIterator& endLineStart, const BidiStatus& endLineStatus, BidiContext* endLineContext,
131                         RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
132     int skipWhitespace(BidiIterator&, BidiState&);
133     BidiIterator findNextLineBreak(BidiIterator& start, BidiState& info);
134     RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end);
135     InlineFlowBox* createLineBoxes(RenderObject*);
136     void computeHorizontalPositionsForLine(RootInlineBox*, BidiState&);
137     void computeVerticalPositionsForLine(RootInlineBox*);
138     void checkLinesForOverflow();
139     void deleteEllipsisLineBoxes();
140     void checkLinesForTextOverflow();
141     // end bidi.cpp functions
142
143     virtual void paint(PaintInfo&, int tx, int ty);
144     virtual void paintObject(PaintInfo&, int tx, int ty);
145     void paintFloats(PaintInfo&, int tx, int ty, bool paintSelection = false);
146     void paintContents(PaintInfo&, int tx, int ty);
147     void paintColumns(PaintInfo&, int tx, int ty, bool paintFloats = false);
148     void paintChildren(PaintInfo&, int tx, int ty);
149     void paintEllipsisBoxes(PaintInfo&, int tx, int ty);
150     void paintSelection(PaintInfo&, int tx, int ty);
151     void paintCaret(PaintInfo&, CaretType);
152     
153     void insertFloatingObject(RenderObject*);
154     void removeFloatingObject(RenderObject*);
155
156     // called from lineWidth, to position the floats added in the last line.
157     void positionNewFloats();
158     void clearFloats();
159     int getClearDelta(RenderObject* child);
160     virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
161     void markPositionedObjectsForLayout();
162
163     // FIXME: containsFloats() should not return true if the floating objects list
164     // is empty. However, layoutInlineChildren() relies on the current behavior.
165     // http://bugs.webkit.org/show_bug.cgi?id=7395#c3
166     virtual bool containsFloats() { return m_floatingObjects; }
167     virtual bool containsFloat(RenderObject*);
168
169     virtual bool avoidsFloats() const;
170
171     virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > m_height; }
172     void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
173     void addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset);
174
175     int nearestFloatBottom(int height) const;
176     int floatBottom() const;
177     inline int leftBottom();
178     inline int rightBottom();
179     IntRect floatRect() const;
180
181     virtual int lineWidth(int y) const;
182     virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
183     virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
184     virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
185
186     int rightOffset() const;
187     int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
188     int rightOffset(int y) const { return rightRelOffset(y, rightOffset(), true); }
189
190     int leftOffset() const;
191     int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
192     int leftOffset(int y) const { return leftRelOffset(y, leftOffset(), true); }
193
194     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
195     virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
196     virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
197
198     virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
199
200     virtual VisiblePosition positionForCoordinates(int x, int y);
201     
202     // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
203     virtual int availableWidth() const;
204     
205     virtual void calcPrefWidths();
206     void calcInlinePrefWidths();
207     void calcBlockPrefWidths();
208
209     virtual int getBaselineOfFirstLineBox() const;
210     virtual int getBaselineOfLastLineBox() const;
211
212     RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
213     RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
214
215     // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
216     // children.
217     virtual RenderBlock* firstLineBlock() const;
218     virtual void updateFirstLetter();
219
220     bool inRootBlockContext() const;
221
222     void setHasMarkupTruncation(bool b = true) { m_hasMarkupTruncation = b; }
223     bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
224
225     virtual bool hasSelectedChildren() const { return m_selectionState != SelectionNone; }
226     virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
227     virtual void setSelectionState(SelectionState s);
228
229     struct BlockSelectionInfo {
230         RenderBlock* m_block;
231         GapRects m_rects;
232         SelectionState m_state;
233
234         BlockSelectionInfo()
235             : m_block(0)
236             , m_state(SelectionNone)
237         {
238         }
239
240         BlockSelectionInfo(RenderBlock* b)
241             : m_block(b)
242             , m_rects(b->needsLayout() ? GapRects() : b->selectionGapRects())
243             , m_state(b->selectionState())
244         { 
245         }
246
247         RenderBlock* block() const { return m_block; }
248         GapRects rects() const { return m_rects; }
249         SelectionState state() const { return m_state; }
250     };
251
252     virtual IntRect selectionRect(bool) { return selectionGapRects(); }
253     GapRects selectionGapRects();
254     virtual bool shouldPaintSelectionGaps() const;
255     bool isSelectionRoot() const;
256     GapRects fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
257                                int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* = 0);
258     GapRects fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
259                                      int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
260     GapRects fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
261                                     int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
262     IntRect fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
263                                      int blockX, int blockY, const PaintInfo*);
264     IntRect fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, 
265                                  int blockX, int blockY, int tx, int ty, const PaintInfo*);
266     IntRect fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
267                                   int blockX, int blockY, int tx, int ty, const PaintInfo*);
268     IntRect fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo*);
269
270     void getHorizontalSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
271     int leftSelectionOffset(RenderBlock* rootBlock, int y);
272     int rightSelectionOffset(RenderBlock* rootBlock, int y);
273
274 #ifndef NDEBUG
275     virtual void dump(TextStream*, DeprecatedString ind = "") const;
276 #endif
277
278     // Helper methods for computing line counts and heights for line counts.
279     RootInlineBox* lineAtIndex(int);
280     int lineCount();
281     int heightForLineCount(int);
282     void clearTruncation();
283
284     int desiredColumnWidth() const;
285     unsigned desiredColumnCount() const;
286     Vector<IntRect>* columnRects() const;
287     void setDesiredColumnCountAndWidth(int count, int width);
288     
289     void adjustRectForColumns(IntRect&) const;
290
291     void addContinuationWithOutline(RenderFlow*);
292     void paintContinuationOutlines(PaintInfo&, int tx, int ty);
293
294 private:
295     void adjustPointToColumnContents(IntPoint&) const;
296     void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust
297
298 protected:
299     void newLine();
300     virtual bool hasLineIfEmpty() const;
301     bool layoutOnlyPositionedObjects();
302
303 private:
304     Position positionForBox(InlineBox*, bool start = true) const;
305     Position positionForRenderer(RenderObject*, bool start = true) const;
306
307     int columnGap() const;
308     void calcColumnWidth();
309     int layoutColumns(int endOfContent = -1);
310
311 protected:
312     struct FloatingObject {
313         enum Type {
314             FloatLeft,
315             FloatRight
316         };
317
318         FloatingObject(Type type)
319             : node(0)
320             , startY(0)
321             , endY(0)
322             , left(0)
323             , width(0)
324             , m_type(type)
325             , noPaint(false)
326         {
327         }
328
329         Type type() { return static_cast<Type>(m_type); }
330
331         RenderObject* node;
332         int startY;
333         int endY;
334         int left;
335         int width;
336         unsigned m_type : 1; // Type (left or right aligned)
337         bool noPaint : 1;
338     };
339
340     // The following helper functions and structs are used by layoutBlockChildren.
341     class CompactInfo {
342         // A compact child that needs to be collapsed into the margin of the following block.
343         RenderObject* m_compact;
344
345         // The block with the open margin that the compact child is going to place itself within.
346         RenderObject* m_block;
347
348     public:
349         RenderObject* compact() const { return m_compact; }
350         RenderObject* block() const { return m_block; }
351         bool matches(RenderObject* child) const { return m_compact && m_block == child; }
352
353         void clear() { set(0, 0); }
354         void set(RenderObject* c, RenderObject* b) { m_compact = c; m_block = b; }
355
356         CompactInfo() { clear(); }
357     };
358
359     class MarginInfo {
360         // Collapsing flags for whether we can collapse our margins with our children's margins.
361         bool m_canCollapseWithChildren : 1;
362         bool m_canCollapseTopWithChildren : 1;
363         bool m_canCollapseBottomWithChildren : 1;
364
365         // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
366         // margins in our container.  Table cells and the body are the common examples. We
367         // also have a custom style property for Safari RSS to deal with TypePad blog articles.
368         bool m_quirkContainer : 1;
369
370         // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.  
371         // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
372         // always be collapsing with one another.  This variable can remain set to true through multiple iterations 
373         // as long as we keep encountering self-collapsing blocks.
374         bool m_atTopOfBlock : 1;
375
376         // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
377         bool m_atBottomOfBlock : 1;
378
379         // If our last normal flow child was a self-collapsing block that cleared a float,
380         // we track it in this variable.
381         bool m_selfCollapsingBlockClearedFloat : 1;
382
383         // These variables are used to detect quirky margins that we need to collapse away (in table cells
384         // and in the body element).
385         bool m_topQuirk : 1;
386         bool m_bottomQuirk : 1;
387         bool m_determinedTopQuirk : 1;
388
389         // These flags track the previous maximal positive and negative margins.
390         int m_posMargin;
391         int m_negMargin;
392
393     public:
394         MarginInfo(RenderBlock* b, int top, int bottom);
395
396         void setAtTopOfBlock(bool b) { m_atTopOfBlock = b; }
397         void setAtBottomOfBlock(bool b) { m_atBottomOfBlock = b; }
398         void clearMargin() { m_posMargin = m_negMargin = 0; }
399         void setSelfCollapsingBlockClearedFloat(bool b) { m_selfCollapsingBlockClearedFloat = b; }
400         void setTopQuirk(bool b) { m_topQuirk = b; }
401         void setBottomQuirk(bool b) { m_bottomQuirk = b; }
402         void setDeterminedTopQuirk(bool b) { m_determinedTopQuirk = b; }
403         void setPosMargin(int p) { m_posMargin = p; }
404         void setNegMargin(int n) { m_negMargin = n; }
405         void setPosMarginIfLarger(int p) { if (p > m_posMargin) m_posMargin = p; }
406         void setNegMarginIfLarger(int n) { if (n > m_negMargin) m_negMargin = n; }
407
408         void setMargin(int p, int n) { m_posMargin = p; m_negMargin = n; }
409
410         bool atTopOfBlock() const { return m_atTopOfBlock; }
411         bool canCollapseWithTop() const { return m_atTopOfBlock && m_canCollapseTopWithChildren; }
412         bool canCollapseWithBottom() const { return m_atBottomOfBlock && m_canCollapseBottomWithChildren; }
413         bool canCollapseTopWithChildren() const { return m_canCollapseTopWithChildren; }
414         bool canCollapseBottomWithChildren() const { return m_canCollapseBottomWithChildren; }
415         bool selfCollapsingBlockClearedFloat() const { return m_selfCollapsingBlockClearedFloat; }
416         bool quirkContainer() const { return m_quirkContainer; }
417         bool determinedTopQuirk() const { return m_determinedTopQuirk; }
418         bool topQuirk() const { return m_topQuirk; }
419         bool bottomQuirk() const { return m_bottomQuirk; }
420         int posMargin() const { return m_posMargin; }
421         int negMargin() const { return m_negMargin; }
422         int margin() const { return m_posMargin - m_negMargin; }
423     };
424
425     void adjustPositionedBlock(RenderObject* child, const MarginInfo&);
426     void adjustFloatingBlock(const MarginInfo&);
427     RenderObject* handleSpecialChild(RenderObject* child, const MarginInfo&, CompactInfo&, bool& handled);
428     RenderObject* handleFloatingChild(RenderObject* child, const MarginInfo&, bool& handled);
429     RenderObject* handlePositionedChild(RenderObject* child, const MarginInfo&, bool& handled);
430     RenderObject* handleCompactChild(RenderObject* child, CompactInfo&, bool& handled);
431     RenderObject* handleRunInChild(RenderObject* child, bool& handled);
432     void collapseMargins(RenderObject* child, MarginInfo&, int yPosEstimate);
433     void clearFloatsIfNeeded(RenderObject* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin);
434     void insertCompactIfNeeded(RenderObject* child, CompactInfo&);
435     int estimateVerticalPosition(RenderObject* child, const MarginInfo&);
436     void determineHorizontalPosition(RenderObject* child);
437     void handleBottomOfBlock(int top, int bottom, MarginInfo&);
438     void setCollapsedBottomMargin(const MarginInfo&);
439     // End helper functions and structs used by layoutBlockChildren.
440
441 private:
442     DeprecatedPtrList<FloatingObject>* m_floatingObjects;
443     DeprecatedPtrList<RenderObject>* m_positionedObjects;
444          
445      // Allocated only when some of these fields have non-default values
446      struct MaxMargin {
447          MaxMargin(const RenderBlock* o) 
448              : m_topPos(topPosDefault(o))
449              , m_topNeg(topNegDefault(o))
450              , m_bottomPos(bottomPosDefault(o))
451              , m_bottomNeg(bottomNegDefault(o))
452              { 
453              }
454          static int topPosDefault(const RenderBlock* o) { return o->marginTop() > 0 ? o->marginTop() : 0; }
455          static int topNegDefault(const RenderBlock* o) { return o->marginTop() < 0 ? -o->marginTop() : 0; }
456          static int bottomPosDefault(const RenderBlock* o) { return o->marginBottom() > 0 ? o->marginBottom() : 0; }
457          static int bottomNegDefault(const RenderBlock* o) { return o->marginBottom() < 0 ? -o->marginBottom() : 0; }
458          
459          int m_topPos;
460          int m_topNeg;
461          int m_bottomPos;
462          int m_bottomNeg;
463      };
464
465     MaxMargin* m_maxMargin;
466
467 protected:
468     // How much content overflows out of our block vertically or horizontally.
469     int m_overflowHeight;
470     int m_overflowWidth;
471     int m_overflowLeft;
472     int m_overflowTop;
473 };
474
475 } // namespace WebCore
476
477 #endif // RenderBlock_h