90baabadda22e05abc924bbde93494b44f7eeb3b
[WebKit-https.git] / WebCore / rendering / RenderFlow.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23 #include "RenderFlow.h"
24
25 #include "Document.h"
26 #include "GraphicsContext.h"
27 #include "HTMLNames.h"
28 #include "InlineTextBox.h"
29 #include "RenderArena.h"
30 #include "RenderInline.h"
31 #include "RenderLayer.h"
32 #include "RenderView.h"
33
34 using namespace std;
35
36 namespace WebCore {
37
38 using namespace HTMLNames;
39
40 #ifndef NDEBUG
41
42 RenderFlow::~RenderFlow()
43 {
44     ASSERT(!m_firstLineBox);
45     ASSERT(!m_lastLineBox);
46 }
47
48 #endif
49
50 RenderFlow* RenderFlow::createAnonymousFlow(Document* doc, RenderStyle* style)
51 {
52     RenderFlow* result;
53     if (style->display() == INLINE)
54         result = new (doc->renderArena()) RenderInline(doc);
55     else
56         result = new (doc->renderArena()) RenderBlock(doc);
57     result->setStyle(style);
58     return result;
59 }
60
61 RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
62 {
63     if (beforeChild && beforeChild->parent() == this)
64         return this;
65
66     RenderFlow* curr = continuation();
67     RenderFlow* nextToLast = this;
68     RenderFlow* last = this;
69     while (curr) {
70         if (beforeChild && beforeChild->parent() == curr) {
71             if (curr->firstChild() == beforeChild)
72                 return last;
73             return curr;
74         }
75
76         nextToLast = last;
77         last = curr;
78         curr = curr->continuation();
79     }
80
81     if (!beforeChild && !last->firstChild())
82         return nextToLast;
83     return last;
84 }
85
86 void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
87 {
88     RenderFlow* flow = continuationBefore(beforeChild);
89     ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() ||
90                 beforeChild->parent()->isRenderInline());
91     RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) : 
92                                     (flow->continuation() ? flow->continuation() : flow);
93
94     if (newChild->isFloatingOrPositioned())
95         return beforeChildParent->addChildToFlow(newChild, beforeChild);
96
97     // A continuation always consists of two potential candidates: an inline or an anonymous
98     // block box holding block children.
99     bool childInline = newChild->isInline();
100     bool bcpInline = beforeChildParent->isInline();
101     bool flowInline = flow->isInline();
102
103     if (flow == beforeChildParent)
104         return flow->addChildToFlow(newChild, beforeChild);
105     else {
106         // The goal here is to match up if we can, so that we can coalesce and create the
107         // minimal # of continuations needed for the inline.
108         if (childInline == bcpInline)
109             return beforeChildParent->addChildToFlow(newChild, beforeChild);
110         else if (flowInline == childInline)
111             return flow->addChildToFlow(newChild, 0); // Just treat like an append.
112         else
113             return beforeChildParent->addChildToFlow(newChild, beforeChild);
114     }
115 }
116
117 void RenderFlow::addChild(RenderObject* newChild, RenderObject* beforeChild)
118 {
119     if (continuation())
120         return addChildWithContinuation(newChild, beforeChild);
121     return addChildToFlow(newChild, beforeChild);
122 }
123
124 void RenderFlow::extractLineBox(InlineFlowBox* box)
125 {
126     checkConsistency();
127
128     m_lastLineBox = box->prevFlowBox();
129     if (box == m_firstLineBox)
130         m_firstLineBox = 0;
131     if (box->prevLineBox())
132         box->prevLineBox()->setNextLineBox(0);
133     box->setPreviousLineBox(0);
134     for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
135         curr->setExtracted();
136
137     checkConsistency();
138 }
139
140 void RenderFlow::attachLineBox(InlineFlowBox* box)
141 {
142     checkConsistency();
143
144     if (m_lastLineBox) {
145         m_lastLineBox->setNextLineBox(box);
146         box->setPreviousLineBox(m_lastLineBox);
147     } else
148         m_firstLineBox = box;
149     InlineFlowBox* last = box;
150     for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
151         curr->setExtracted(false);
152         last = curr;
153     }
154     m_lastLineBox = last;
155
156     checkConsistency();
157 }
158
159 void RenderFlow::removeLineBox(InlineFlowBox* box)
160 {
161     checkConsistency();
162
163     if (box == m_firstLineBox)
164         m_firstLineBox = box->nextFlowBox();
165     if (box == m_lastLineBox)
166         m_lastLineBox = box->prevFlowBox();
167     if (box->nextLineBox())
168         box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
169     if (box->prevLineBox())
170         box->prevLineBox()->setNextLineBox(box->nextLineBox());
171
172     checkConsistency();
173 }
174
175 void RenderFlow::deleteLineBoxes()
176 {
177     if (m_firstLineBox) {
178         RenderArena* arena = renderArena();
179         InlineRunBox* next;
180         for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) {
181             next = curr->nextLineBox();
182             curr->destroy(arena);
183         }
184         m_firstLineBox = 0;
185         m_lastLineBox = 0;
186     }
187 }
188
189 void RenderFlow::destroy()
190 {
191     // Detach our continuation first.
192     if (m_continuation)
193         m_continuation->destroy();
194     m_continuation = 0;
195
196     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
197     // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.
198     RenderContainer::destroyLeftoverChildren();
199
200     if (!documentBeingDestroyed()) {
201         if (m_firstLineBox) {
202             // We can't wait for RenderContainer::destroy to clear the selection,
203             // because by then we will have nuked the line boxes.
204             // FIXME: The SelectionController should be responsible for this when it
205             // is notified of DOM mutations.
206             if (isSelectionBorder())
207                 view()->clearSelection();
208
209             // If line boxes are contained inside a root, that means we're an inline.
210             // In that case, we need to remove all the line boxes so that the parent
211             // lines aren't pointing to deleted children. If the first line box does
212             // not have a parent that means they are either already disconnected or
213             // root lines that can just be destroyed without disconnecting.
214             if (m_firstLineBox->parent()) {
215                 for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox())
216                     box->remove();
217             }
218
219             // If we are an anonymous block, then our line boxes might have children
220             // that will outlast this block. In the non-anonymous block case those
221             // children will be destroyed by the time we return from this function.
222             if (isAnonymousBlock()) {
223                 for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) {
224                     while (InlineBox* childBox = box->firstChild())
225                         childBox->remove();
226                 }
227             }
228         } else if (isInline() && parent())
229             parent()->dirtyLinesFromChangedChild(this);
230     }
231
232     deleteLineBoxes();
233
234     RenderContainer::destroy();
235 }
236
237 void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
238 {
239     if (!parent() || (selfNeedsLayout() && !isInlineFlow()) || isTable())
240         return;
241
242     // If we have no first line box, then just bail early.
243     if (!firstLineBox()) {
244         // For an empty inline, go ahead and propagate the check up to our parent, unless the parent
245         // is already dirty.
246         if (isInline() && !parent()->selfNeedsLayout())
247             parent()->dirtyLinesFromChangedChild(this);
248         return;
249     }
250
251     // Try to figure out which line box we belong in.  First try to find a previous
252     // line box by examining our siblings.  If we didn't find a line box, then use our 
253     // parent's first line box.
254     RootInlineBox* box = 0;
255     RenderObject* curr = 0;
256     for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
257         if (curr->isFloatingOrPositioned())
258             continue;
259
260         if (curr->isReplaced()) {
261             InlineBox* wrapper = curr->inlineBoxWrapper();
262             if (wrapper)
263                 box = wrapper->root();
264         } else if (curr->isText()) {
265             InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
266             if (textBox)
267                 box = textBox->root();
268         } else if (curr->isInlineFlow()) {
269             InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
270             if (runBox)
271                 box = runBox->root();
272         }
273
274         if (box)
275             break;
276     }
277     if (!box)
278         box = firstLineBox()->root();
279
280     // If we found a line box, then dirty it.
281     if (box) {
282         RootInlineBox* adjacentBox;
283         box->markDirty();
284
285         // dirty the adjacent lines that might be affected
286         // NOTE: we dirty the previous line because RootInlineBox objects cache
287         // the address of the first object on the next line after a BR, which we may be
288         // invalidating here.  For more info, see how RenderBlock::layoutInlineChildren
289         // calls setLineBreakInfo with the result of findNextLineBreak.  findNextLineBreak,
290         // despite the name, actually returns the first RenderObject after the BR.
291         // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
292         adjacentBox = box->prevRootBox();
293         if (adjacentBox)
294             adjacentBox->markDirty();
295         if (child->isBR() || (curr && curr->isBR())) {
296             adjacentBox = box->nextRootBox();
297             if (adjacentBox)
298                 adjacentBox->markDirty();
299         }
300     }
301 }
302
303 short RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
304 {
305     if (firstLine) {
306         RenderStyle* s = style(firstLine);
307         Length lh = s->lineHeight();
308         if (lh.isNegative()) {
309             if (s == style()) {
310                 if (m_lineHeight == -1)
311                     m_lineHeight = RenderObject::lineHeight(false);
312                 return m_lineHeight;
313             }
314             return s->font().lineSpacing();
315         }
316         if (lh.isPercent())
317             return lh.calcMinValue(s->fontSize());
318         return lh.value();
319     }
320
321     if (m_lineHeight == -1)
322         m_lineHeight = RenderObject::lineHeight(false);
323     return m_lineHeight;
324 }
325
326 void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
327 {
328     if (!isRootLineBox && isReplaced())
329         return RenderContainer::dirtyLineBoxes(fullLayout, isRootLineBox);
330
331     if (fullLayout)
332         deleteLineBoxes();
333     else {
334         for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
335             curr->dirtyLineBoxes();
336     }
337 }
338
339 InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
340 {
341     checkConsistency();
342
343     if (!isRootLineBox &&
344         (isReplaced() || makePlaceHolderBox))                     // Inline tables and inline blocks
345         return RenderContainer::createInlineBox(false, isRootLineBox);  // (or positioned element placeholders).
346
347     InlineFlowBox* flowBox = 0;
348     if (isInlineFlow())
349         flowBox = new (renderArena()) InlineFlowBox(this);
350     else
351         flowBox = new (renderArena()) RootInlineBox(this);
352
353     if (!m_firstLineBox)
354         m_firstLineBox = m_lastLineBox = flowBox;
355     else {
356         m_lastLineBox->setNextLineBox(flowBox);
357         flowBox->setPreviousLineBox(m_lastLineBox);
358         m_lastLineBox = flowBox;
359     }
360
361     checkConsistency();
362
363     return flowBox;
364 }
365
366 void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int ty)
367 {
368     // Only paint during the foreground/selection phases.
369     if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline 
370         && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines)
371         return;
372
373     bool inlineFlow = isInlineFlow();
374     if (inlineFlow)
375         ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
376
377     // If we have no lines then we have no work to do.
378     if (!firstLineBox())
379         return;
380
381     // We can check the first box and last box and avoid painting if we don't
382     // intersect.  This is a quick short-circuit that we can take to avoid walking any lines.
383     // FIXME: This check is flawed in the following extremely obscure way:
384     // if some line in the middle has a huge overflow, it might actually extend below the last line.
385     int yPos = firstLineBox()->root()->topOverflow() - maximalOutlineSize(paintInfo.phase);
386     int h = maximalOutlineSize(paintInfo.phase) + lastLineBox()->root()->bottomOverflow() - yPos;
387     yPos += ty;
388     if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
389         return;
390
391     PaintInfo info(paintInfo);
392     RenderFlowSequencedSet outlineObjects;
393     info.outlineObjects = &outlineObjects;
394
395     // See if our root lines intersect with the dirty rect.  If so, then we paint
396     // them.  Note that boxes can easily overlap, so we can't make any assumptions
397     // based off positions of our first line box or our last line box.
398     RenderView* v = view();
399     bool usePrintRect = !v->printRect().isEmpty();
400     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
401         if (usePrintRect) {
402             // FIXME: This is a feeble effort to avoid splitting a line across two pages.
403             // It is utterly inadequate, and this should not be done at paint time at all.
404             // The whole way objects break across pages needs to be redone.
405             // Try to avoid splitting a line vertically, but only if it's less than the height
406             // of the entire page.
407             if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= v->printRect().height()) {
408                 if (ty + curr->root()->bottomOverflow() > v->printRect().bottom()) {
409                     if (ty + curr->root()->topOverflow() < v->truncatedAt())
410                         v->setBestTruncatedAt(ty + curr->root()->topOverflow(), this);
411                     // If we were able to truncate, don't paint.
412                     if (ty + curr->root()->topOverflow() >= v->truncatedAt())
413                         break;
414                 }
415             }
416         }
417
418         int top = min(curr->root()->topOverflow(), curr->root()->selectionTop()) - maximalOutlineSize(info.phase);
419         int bottom = curr->root()->bottomOverflow() + maximalOutlineSize(info.phase);
420         h = bottom - top;
421         yPos = ty + top;
422         if (yPos < info.rect.bottom() && yPos + h > info.rect.y())
423             curr->paint(info, tx, ty);
424     }
425
426     if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
427         RenderFlowSequencedSet::iterator end = info.outlineObjects->end();
428         for (RenderFlowSequencedSet::iterator it = info.outlineObjects->begin(); it != end; ++it) {
429             RenderFlow* flow = *it;
430             flow->paintOutline(info.context, tx, ty);
431         }
432         info.outlineObjects->clear();
433     }
434 }
435
436 bool RenderFlow::hitTestLines(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
437 {
438     if (hitTestAction != HitTestForeground)
439         return false;
440
441     bool inlineFlow = isInlineFlow();
442     if (inlineFlow)
443         ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
444
445     // If we have no lines then we have no work to do.
446     if (!firstLineBox())
447         return false;
448
449     // We can check the first box and last box and avoid hit testing if we don't
450     // contain the point.  This is a quick short-circuit that we can take to avoid walking any lines.
451     // FIXME: This check is flawed in the following extremely obscure way:
452     // if some line in the middle has a huge overflow, it might actually extend below the last line.
453     if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
454         return false;
455
456     // See if our root lines contain the point.  If so, then we hit test
457     // them further.  Note that boxes can easily overlap, so we can't make any assumptions
458     // based off positions of our first line box or our last line box.
459     for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
460         if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
461             bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
462             if (inside) {
463                 updateHitTestResult(result, IntPoint(x - tx, y - ty));
464                 return true;
465             }
466         }
467     }
468     
469     return false;
470 }
471
472 IntRect RenderFlow::absoluteClippedOverflowRect()
473 {
474     if (isInlineFlow()) {
475         // Only compacts and run-ins are allowed in here during layout.
476         ASSERT(!view() || !view()->layoutState() || isCompact() || isRunIn());
477
478         if (!firstLineBox() && !continuation())
479             return IntRect();
480
481         // Find our leftmost position.
482         int left = 0;
483         int top = firstLineBox() ? firstLineBox()->yPos() : 0;
484         for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
485             if (curr == firstLineBox() || curr->xPos() < left)
486                 left = curr->xPos();
487         }
488
489         // Now invalidate a rectangle.
490         int ow = style() ? style()->outlineSize() : 0;
491         if (isCompact())
492             left -= m_x;
493         
494         // We need to add in the relative position offsets of any inlines (including us) up to our
495         // containing block.
496         RenderBlock* cb = containingBlock();
497         for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb; 
498              inlineFlow = inlineFlow->parent()) {
499              if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
500                 inlineFlow->layer()->relativePositionOffset(left, top);
501         }
502
503         IntRect r(-ow + left, -ow + top, width() + ow * 2, height() + ow * 2);
504         if (cb->hasColumns())
505             cb->adjustRectForColumns(r);
506
507         if (cb->hasOverflowClip()) {
508             // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
509             // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
510             // anyway if its size does change.
511             int x = r.x();
512             int y = r.y();
513             IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
514             cb->layer()->subtractScrollOffset(x, y); // For overflow:auto/scroll/hidden.
515             IntRect repaintRect(x, y, r.width(), r.height());
516             r = intersection(repaintRect, boxRect);
517         }
518         cb->computeAbsoluteRepaintRect(r);
519
520         if (ow) {
521             for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
522                 if (!curr->isText()) {
523                     IntRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
524                     r.unite(childRect);
525                 }
526             }
527
528             if (continuation() && !continuation()->isInline()) {
529                 IntRect contRect = continuation()->getAbsoluteRepaintRectWithOutline(ow);
530                 r.unite(contRect);
531             }
532         }
533
534         return r;
535     }
536
537     return RenderContainer::absoluteClippedOverflowRect();
538 }
539
540 int RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
541 {
542     ASSERT(!isInlineFlow());
543     if (!includeOverflowInterior && hasOverflowClip())
544         return includeSelf && m_width > 0 ? overflowHeight(false) : 0;
545
546     int bottom = includeSelf && m_width > 0 ? m_height : 0;
547     if (!hasColumns()) {
548         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
549         // For now, we have to descend into all the children, since we may have a huge abs div inside
550         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
551         // the abs div.
552         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
553             if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
554                 bottom = max(bottom, c->yPos() + c->lowestPosition(false));
555         }
556     }
557
558     if (includeSelf && isRelPositioned())
559         bottom += relativePositionOffsetY();         
560
561     return bottom;
562 }
563
564 int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
565 {
566     ASSERT(!isInlineFlow());
567     if (!includeOverflowInterior && hasOverflowClip())
568         return includeSelf && m_height > 0 ? overflowWidth(false) : 0;
569
570     int right = includeSelf && m_height > 0 ? m_width : 0;
571     if (!hasColumns()) {
572         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
573         // For now, we have to descend into all the children, since we may have a huge abs div inside
574         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
575         // the abs div.
576         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
577             if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
578                 right = max(right, c->xPos() + c->rightmostPosition(false));
579         }
580     }
581
582     if (includeSelf && isRelPositioned())
583         right += relativePositionOffsetX();
584
585     return right;
586 }
587
588 int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
589 {
590     ASSERT(!isInlineFlow());
591     if (!includeOverflowInterior && hasOverflowClip())
592         return includeSelf && m_height > 0 ? overflowLeft(false) : m_width;
593
594     int left = includeSelf && m_height > 0 ? 0 : m_width;
595     if (!hasColumns()) {
596         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
597         // For now, we have to descend into all the children, since we may have a huge abs div inside
598         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
599         // the abs div.
600         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
601             if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
602                 left = min(left, c->xPos() + c->leftmostPosition(false));
603         }
604     }
605
606     if (includeSelf && isRelPositioned())
607         left += relativePositionOffsetX(); 
608
609     return left;
610 }
611
612 IntRect RenderFlow::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
613 {
614     // Do the normal calculation in most cases.
615     if (firstChild() || style()->display() == INLINE)
616         return RenderContainer::caretRect(offset, affinity, extraWidthToEndOfLine);
617
618     // This is a special case:
619     // The element is not an inline element, and it's empty. So we have to
620     // calculate a fake position to indicate where objects are to be inserted.
621     
622     // FIXME: This does not take into account either :first-line or :first-letter
623     // However, as soon as some content is entered, the line boxes will be
624     // constructed and this kludge is not called any more. So only the caret size
625     // of an empty :first-line'd block is wrong. I think we can live with that.
626     RenderStyle* currentStyle = firstLineStyle();
627     int height = lineHeight(true);
628     const int caretWidth = 1;
629
630     enum CaretAlignment { alignLeft, alignRight, alignCenter };
631
632     CaretAlignment alignment = alignLeft;
633
634     switch (currentStyle->textAlign()) {
635         case TAAUTO:
636         case JUSTIFY:
637             if (currentStyle->direction() == RTL)
638                 alignment = alignRight;
639             break;
640         case LEFT:
641         case WEBKIT_LEFT:
642             break;
643         case CENTER:
644         case WEBKIT_CENTER:
645             alignment = alignCenter;
646             break;
647         case RIGHT:
648         case WEBKIT_RIGHT:
649             alignment = alignRight;
650             break;
651     }
652
653     int x = borderLeft() + paddingLeft();
654     int w = width();
655
656     switch (alignment) {
657         case alignLeft:
658             break;
659         case alignCenter:
660             x = (x + w - (borderRight() + paddingRight())) / 2;
661             break;
662         case alignRight:
663             x = w - (borderRight() + paddingRight());
664             break;
665     }
666
667     if (extraWidthToEndOfLine) {
668         if (isRenderBlock()) {
669             *extraWidthToEndOfLine = w - (x + caretWidth);
670         } else {
671             // FIXME: This code looks wrong.
672             // myRight and containerRight are set up, but then clobbered.
673             // So *extraWidthToEndOfLine will always be 0 here.
674
675             int myRight = x + caretWidth;
676             int ignore;
677             absolutePositionForContent(myRight, ignore);
678
679             int containerRight = containingBlock()->xPos() + containingBlockWidth();
680             absolutePositionForContent(containerRight, ignore);
681
682             *extraWidthToEndOfLine = containerRight - myRight;
683         }
684     }
685
686     int absx, absy;
687     absolutePositionForContent(absx, absy);
688     x += absx;
689     int y = absy + paddingTop() + borderTop();
690
691     return IntRect(x, y, caretWidth, height);
692 }
693
694 void RenderFlow::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
695 {
696     if (isRenderBlock()) {
697         // Continuations should include their margins in the outline rect.
698         if (continuation()) {
699             bool nextInlineHasLineBox = continuation()->firstLineBox();
700             bool prevInlineHasLineBox = static_cast<RenderFlow*>(continuation()->element()->renderer())->firstLineBox();
701             int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0;
702             int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0;
703             graphicsContext->addFocusRingRect(IntRect(tx, ty - topMargin, 
704                                                       width(), height() + topMargin + bottomMargin));
705         } else
706             graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
707     }
708
709     if (!hasOverflowClip() && !hasControlClip()) {
710         for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
711             graphicsContext->addFocusRingRect(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
712
713         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
714             if (!curr->isText() && !curr->isListMarker()) {
715                 int x = 0;
716                 int y = 0;
717                 if (curr->layer()) 
718                     curr->absolutePosition(x, y);
719                 else {
720                     x = tx + curr->xPos();
721                     y = ty + curr->yPos();
722                 }
723                 curr->addFocusRingRects(graphicsContext, x, y);
724             }
725     }
726
727     if (continuation()) {
728         if (isInline())
729             continuation()->addFocusRingRects(graphicsContext, 
730                                               tx - containingBlock()->xPos() + continuation()->xPos(),
731                                               ty - containingBlock()->yPos() + continuation()->yPos());
732         else
733             continuation()->addFocusRingRects(graphicsContext, 
734                                               tx - xPos() + continuation()->containingBlock()->xPos(),
735                                               ty - yPos() + continuation()->containingBlock()->yPos());
736     }
737 }
738
739 void RenderFlow::paintOutline(GraphicsContext* graphicsContext, int tx, int ty)
740 {
741     if (!hasOutline())
742         return;
743     
744     if (style()->outlineStyleIsAuto() || hasOutlineAnnotation()) {
745         int ow = style()->outlineWidth();
746         Color oc = style()->outlineColor();
747         if (!oc.isValid())
748             oc = style()->color();
749
750         graphicsContext->initFocusRing(ow, style()->outlineOffset());
751         addFocusRingRects(graphicsContext, tx, ty);
752         if (style()->outlineStyleIsAuto())
753             graphicsContext->drawFocusRing(oc);
754         else
755             addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
756         graphicsContext->clearFocusRing();
757     }
758
759     if (style()->outlineStyleIsAuto() || style()->outlineStyle() <= BHIDDEN)
760         return;
761
762     Vector<IntRect*> rects;
763
764     rects.append(new IntRect);
765     for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
766         rects.append(new IntRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
767
768     rects.append(new IntRect);
769
770     for (unsigned i = 1; i < rects.size() - 1; i++)
771         paintOutlineForLine(graphicsContext, tx, ty, *rects.at(i - 1), *rects.at(i), *rects.at(i + 1));
772     deleteAllValues(rects);
773 }
774
775 void RenderFlow::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, int ty,
776                                      const IntRect& lastline, const IntRect& thisline, const IntRect& nextline)
777 {
778     int ow = style()->outlineWidth();
779     EBorderStyle os = style()->outlineStyle();
780     Color oc = style()->outlineColor();
781     if (!oc.isValid())
782         oc = style()->color();
783
784     int offset = style()->outlineOffset();
785
786     int t = ty + thisline.y() - offset;
787     int l = tx + thisline.x() - offset;
788     int b = ty + thisline.bottom() + offset;
789     int r = tx + thisline.right() + offset;
790     
791     // left edge
792     drawBorder(graphicsContext,
793                l - ow,
794                t - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : 0),
795                l,
796                b + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : 0),
797                BSLeft,
798                oc, style()->color(), os,
799                (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : -ow),
800                (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : -ow));
801     
802     // right edge
803     drawBorder(graphicsContext,
804                r,
805                t - (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : 0),
806                r + ow,
807                b + (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : 0),
808                BSRight,
809                oc, style()->color(), os,
810                (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : -ow),
811                (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : -ow));
812     // upper edge
813     if (thisline.x() < lastline.x())
814         drawBorder(graphicsContext,
815                    l - ow,
816                    t - ow,
817                    min(r+ow, (lastline.isEmpty() ? 1000000 : tx + lastline.x())),
818                    t ,
819                    BSTop, oc, style()->color(), os,
820                    ow,
821                    (!lastline.isEmpty() && tx + lastline.x() + 1 < r + ow) ? -ow : ow);
822     
823     if (lastline.right() < thisline.right())
824         drawBorder(graphicsContext,
825                    max(lastline.isEmpty() ? -1000000 : tx + lastline.right(), l - ow),
826                    t - ow,
827                    r + ow,
828                    t ,
829                    BSTop, oc, style()->color(), os,
830                    (!lastline.isEmpty() && l - ow < tx + lastline.right()) ? -ow : ow,
831                    ow);
832     
833     // lower edge
834     if (thisline.x() < nextline.x())
835         drawBorder(graphicsContext,
836                    l - ow,
837                    b,
838                    min(r + ow, !nextline.isEmpty() ? tx + nextline.x() + 1 : 1000000),
839                    b + ow,
840                    BSBottom, oc, style()->color(), os,
841                    ow,
842                    (!nextline.isEmpty() && tx + nextline.x() + 1 < r + ow) ? -ow : ow);
843     
844     if (nextline.right() < thisline.right())
845         drawBorder(graphicsContext,
846                    max(!nextline.isEmpty() ? tx + nextline.right() : -1000000, l - ow),
847                    b,
848                    r + ow,
849                    b + ow,
850                    BSBottom, oc, style()->color(), os,
851                    (!nextline.isEmpty() && l - ow < tx + nextline.right()) ? -ow : ow,
852                    ow);
853 }
854
855 #ifndef NDEBUG
856
857 void RenderFlow::checkConsistency() const
858 {
859     const InlineFlowBox* prev = 0;
860     for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) {
861         ASSERT(child->object() == this);
862         ASSERT(child->prevFlowBox() == prev);
863         prev = child;
864     }
865     ASSERT(prev == m_lastLineBox);
866 }
867
868 #endif
869
870 } // namespace WebCore