2008-05-25 Maciej Stachowiak <mjs@apple.com>
[WebKit.git] / WebCore / rendering / RenderContainer.cpp
1 /**
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
6  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
7  * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "RenderContainer.h"
28
29 #include "AXObjectCache.h"
30 #include "Document.h"
31 #include "RenderCounter.h"
32 #include "RenderImageGeneratedContent.h"
33 #include "RenderLayer.h"
34 #include "RenderListItem.h"
35 #include "RenderTable.h"
36 #include "RenderTextFragment.h"
37 #include "RenderView.h"
38 #include "htmlediting.h"
39
40 namespace WebCore {
41
42 RenderContainer::RenderContainer(Node* node)
43     : RenderBox(node)
44     , m_firstChild(0)
45     , m_lastChild(0)
46 {
47 }
48
49 RenderContainer::~RenderContainer()
50 {
51 }
52
53 void RenderContainer::destroy()
54 {
55     destroyLeftoverChildren();
56     RenderBox::destroy();
57 }
58
59 void RenderContainer::destroyLeftoverChildren()
60 {
61     while (m_firstChild) {
62         if (m_firstChild->isListMarker() || (m_firstChild->style()->styleType() == RenderStyle::FIRST_LETTER && !m_firstChild->isText()))
63             m_firstChild->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
64         else {
65         // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
66             if (m_firstChild->element())
67                 m_firstChild->element()->setRenderer(0);
68             m_firstChild->destroy();
69         }
70     }
71 }
72
73 bool RenderContainer::canHaveChildren() const
74 {
75     return true;
76 }
77
78 static void updateListMarkerNumbers(RenderObject* child)
79 {
80     for (RenderObject* r = child; r; r = r->nextSibling())
81         if (r->isListItem())
82             static_cast<RenderListItem*>(r)->updateValue();
83 }
84
85 void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
86 {
87     bool needsTable = false;
88
89     if (newChild->isListItem())
90         updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
91     else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
92         needsTable = !isTable();
93     else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
94         needsTable = !isTable();
95     else if (newChild->isTableSection())
96         needsTable = !isTable();
97     else if (newChild->isTableRow())
98         needsTable = !isTableSection();
99     else if (newChild->isTableCell()) {
100         needsTable = !isTableRow();
101         // I'm not 100% sure this is the best way to fix this, but without this
102         // change we recurse infinitely when trying to render the CSS2 test page:
103         // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
104         // See Radar 2925291.
105         if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
106             needsTable = false;
107     }
108
109     if (needsTable) {
110         RenderTable *table;
111         if(!beforeChild)
112             beforeChild = m_lastChild;
113         if(beforeChild && beforeChild->isAnonymous() && beforeChild->isTable())
114             table = static_cast<RenderTable*>(beforeChild);
115         else {
116             table = new (renderArena()) RenderTable(document() /* is anonymous */);
117             RenderStyle *newStyle = new (renderArena()) RenderStyle;
118             newStyle->inheritFrom(style());
119             newStyle->setDisplay(TABLE);
120             table->setStyle(newStyle);
121             addChild(table, beforeChild);
122         }
123         table->addChild(newChild);
124     } else {
125         // just add it...
126         insertChildNode(newChild, beforeChild);
127     }
128     
129     if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
130         RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
131         if (textToTransform)
132             static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
133     }
134 }
135
136 RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
137 {
138     ASSERT(oldChild->parent() == this);
139
140     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
141     // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
142     // disappears gets repainted properly.
143     if (!documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
144         oldChild->setNeedsLayoutAndPrefWidthsRecalc();
145         oldChild->repaint();
146     }
147         
148     // If we have a line box wrapper, delete it.
149     oldChild->deleteLineBoxWrapper();
150
151     if (!documentBeingDestroyed() && fullRemove) {
152         // if we remove visible child from an invisible parent, we don't know the layer visibility any more
153         RenderLayer* layer = 0;
154         if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
155             layer = enclosingLayer();
156             layer->dirtyVisibleContentStatus();
157         }
158
159          // Keep our layer hierarchy updated.
160         if (oldChild->firstChild() || oldChild->hasLayer()) {
161             if (!layer) layer = enclosingLayer();            
162             oldChild->removeLayers(layer);
163         }
164         
165         // renumber ordered lists
166         if (oldChild->isListItem())
167             updateListMarkerNumbers(oldChild->nextSibling());
168         
169         if (oldChild->isPositioned() && childrenInline())
170             dirtyLinesFromChangedChild(oldChild);
171     }
172     
173     // If oldChild is the start or end of the selection, then clear the selection to
174     // avoid problems of invalid pointers.
175     // FIXME: The SelectionController should be responsible for this when it
176     // is notified of DOM mutations.
177     if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
178         view()->clearSelection();
179
180     // remove the child
181     if (oldChild->previousSibling())
182         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
183     if (oldChild->nextSibling())
184         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
185
186     if (m_firstChild == oldChild)
187         m_firstChild = oldChild->nextSibling();
188     if (m_lastChild == oldChild)
189         m_lastChild = oldChild->previousSibling();
190
191     oldChild->setPreviousSibling(0);
192     oldChild->setNextSibling(0);
193     oldChild->setParent(0);
194
195     if (AXObjectCache::accessibilityEnabled())
196         document()->axObjectCache()->childrenChanged(this);
197
198     return oldChild;
199 }
200
201 void RenderContainer::removeChild(RenderObject* oldChild)
202 {
203     // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
204     // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
205     // layout anyway).
206     oldChild->removeFromObjectLists();
207     
208     removeChildNode(oldChild);
209 }
210
211 RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
212 {
213     if (type == RenderStyle::BEFORE) {
214         RenderObject* first = this;
215         do {
216             // Skip list markers.
217             first = first->firstChild();
218             while (first && first->isListMarker())
219                 first = first->nextSibling();
220         } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
221         if (first && first->style()->styleType() != type)
222             return 0;
223         return first;
224     }
225     if (type == RenderStyle::AFTER) {
226         RenderObject* last = this;
227         do {
228             last = last->lastChild();
229         } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
230         if (last && last->style()->styleType() != type)
231             return 0;
232         return last;
233     }
234
235     ASSERT_NOT_REACHED();
236     return 0;
237 }
238
239 void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
240 {
241     // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
242     if (parent() && parent()->createsAnonymousWrapper())
243         return;
244     updateBeforeAfterContentForContainer(type, this);
245 }
246
247 void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
248 {
249     // In CSS2, before/after pseudo-content cannot nest.  Check this first.
250     if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
251         return;
252     
253     RenderStyle* pseudoElementStyle = styledObject->getPseudoStyle(type);
254     RenderObject* child = beforeAfterContainer(type);
255
256     // Whether or not we currently have generated content attached.
257     bool oldContentPresent = child;
258
259     // Whether or not we now want generated content.  
260     bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
261
262     // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
263     // :after content and not :before content.
264     if (newContentWanted && type == RenderStyle::BEFORE && isInlineContinuation())
265         newContentWanted = false;
266
267     // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
268     // then we don't generate the :after content.
269     if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && continuation())
270         newContentWanted = false;
271     
272     // If we don't want generated content any longer, or if we have generated content, but it's no longer
273     // identical to the new content data we want to build render objects for, then we nuke all
274     // of the old generated content.
275     if (!newContentWanted || (oldContentPresent && !child->style()->contentDataEquivalent(pseudoElementStyle))) {
276         // Nuke the child. 
277         if (child && child->style()->styleType() == type) {
278             oldContentPresent = false;
279             child->destroy();
280             child = (type == RenderStyle::BEFORE) ? m_firstChild : m_lastChild;
281         }
282     }
283
284     // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
285     // have no generated content and can now return.
286     if (!newContentWanted)
287         return;
288
289     if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
290         !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
291         // According to the CSS2 spec (the end of section 12.1), the only allowed
292         // display values for the pseudo style are NONE and INLINE for inline flows.
293         // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
294         // For now we at least relax the restriction to allow all inline types like inline-block
295         // and inline-table.
296         pseudoElementStyle->setDisplay(INLINE);
297
298     if (oldContentPresent) {
299         if (child && child->style()->styleType() == type) {
300             // We have generated content present still.  We want to walk this content and update our
301             // style information with the new pseudo-element style.
302             child->setStyle(pseudoElementStyle);
303
304             // Note that if we ever support additional types of generated content (which should be way off
305             // in the future), this code will need to be patched.
306             for (RenderObject* genChild = child->firstChild(); genChild; genChild = genChild->nextSibling()) {
307                 if (genChild->isText())
308                     // Generated text content is a child whose style also needs to be set to the pseudo-element style.
309                     genChild->setStyle(pseudoElementStyle);
310                 else if (genChild->isImage()) {
311                     // Images get an empty style that inherits from the pseudo.
312                     RenderStyle* style = new (renderArena()) RenderStyle;
313                     style->inheritFrom(pseudoElementStyle);
314                     genChild->setStyle(style);
315                 } else
316                     // Must be a first-letter container. updateFirstLetter() will take care of it.
317                     ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
318             }
319         }
320         return; // We've updated the generated content. That's all we needed to do.
321     }
322     
323     RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? firstChild() : 0;
324
325     // Generated content consists of a single container that houses multiple children (specified
326     // by the content property).  This generated content container gets the pseudo-element style set on it.
327     RenderObject* generatedContentContainer = 0;
328     
329     // Walk our list of generated content and create render objects for each.
330     for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
331         RenderObject* renderer = 0;
332         switch (content->m_type) {
333             case CONTENT_NONE:
334                 break;
335             case CONTENT_TEXT:
336                 renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
337                 renderer->setStyle(pseudoElementStyle);
338                 break;
339             case CONTENT_OBJECT: {
340                 RenderImageGeneratedContent* image = new (renderArena()) RenderImageGeneratedContent(document()); // anonymous object
341                 RenderStyle* style = new (renderArena()) RenderStyle;
342                 style->inheritFrom(pseudoElementStyle);
343                 image->setStyle(style);
344                 if (StyleImage* styleImage = content->m_content.m_image)
345                     image->setStyleImage(styleImage);
346                 renderer = image;
347                 break;
348             }
349             case CONTENT_COUNTER:
350                 renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
351                 renderer->setStyle(pseudoElementStyle);
352                 break;
353         }
354
355         if (renderer) {
356             if (!generatedContentContainer) {
357                 // Make a generated box that might be any display type now that we are able to drill down into children
358                 // to find the original content properly.
359                 generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
360                 generatedContentContainer->setStyle(pseudoElementStyle);
361             }
362             generatedContentContainer->addChild(renderer);
363         }
364     }
365
366     // Add the pseudo after we've installed all our content so that addChild will be able to find the text
367     // inside the inline for e.g., first-letter styling.
368     if (generatedContentContainer)
369         addChild(generatedContentContainer, insertBefore);
370 }
371
372 bool RenderContainer::isAfterContent(RenderObject* child) const
373 {
374     if (!child)
375         return false;
376     if (child->style()->styleType() != RenderStyle::AFTER)
377         return false;
378     // Text nodes don't have their own styles, so ignore the style on a text node.
379     if (child->isText() && !child->isBR())
380         return false;
381     return true;
382 }
383
384 void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
385 {
386     ASSERT(newChild->parent() == 0);
387     ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
388
389     newChild->setParent(this);
390     RenderObject* lChild = m_lastChild;
391
392     if (lChild) {
393         newChild->setPreviousSibling(lChild);
394         lChild->setNextSibling(newChild);
395     } else
396         m_firstChild = newChild;
397
398     m_lastChild = newChild;
399     
400     if (fullAppend) {
401         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
402         // and don't have a layer attached to ourselves.
403         RenderLayer* layer = 0;
404         if (newChild->firstChild() || newChild->hasLayer()) {
405             layer = enclosingLayer();
406             newChild->addLayers(layer, newChild);
407         }
408
409         // if the new child is visible but this object was not, tell the layer it has some visible content
410         // that needs to be drawn and layer visibility optimization can't be used
411         if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
412             if (!layer)
413                 layer = enclosingLayer();
414             if (layer)
415                 layer->setHasVisibleContent(true);
416         }
417         
418         if (!newChild->isFloatingOrPositioned() && childrenInline())
419             dirtyLinesFromChangedChild(newChild);
420     }
421
422     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
423     if (!normalChildNeedsLayout())
424         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
425     
426     if (AXObjectCache::accessibilityEnabled())
427         document()->axObjectCache()->childrenChanged(this);
428 }
429
430 void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
431 {
432     if (!beforeChild) {
433         appendChildNode(child);
434         return;
435     }
436
437     ASSERT(!child->parent());
438     while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
439         beforeChild = beforeChild->parent();
440     ASSERT(beforeChild->parent() == this);
441
442     ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
443
444     if (beforeChild == m_firstChild)
445         m_firstChild = child;
446
447     RenderObject* prev = beforeChild->previousSibling();
448     child->setNextSibling(beforeChild);
449     beforeChild->setPreviousSibling(child);
450     if(prev) prev->setNextSibling(child);
451     child->setPreviousSibling(prev);
452
453     child->setParent(this);
454     
455     if (fullInsert) {
456         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
457         // and don't have a layer attached to ourselves.
458         RenderLayer* layer = 0;
459         if (child->firstChild() || child->hasLayer()) {
460             layer = enclosingLayer();
461             child->addLayers(layer, child);
462         }
463
464         // if the new child is visible but this object was not, tell the layer it has some visible content
465         // that needs to be drawn and layer visibility optimization can't be used
466         if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
467             if (!layer)
468                 layer = enclosingLayer();
469             if (layer)
470                 layer->setHasVisibleContent(true);
471         }
472
473         
474         if (!child->isFloating() && childrenInline())
475             dirtyLinesFromChangedChild(child);
476     }
477
478     child->setNeedsLayoutAndPrefWidthsRecalc();
479     if (!normalChildNeedsLayout())
480         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
481     
482     if (AXObjectCache::accessibilityEnabled())
483         document()->axObjectCache()->childrenChanged(this);
484 }
485
486 void RenderContainer::layout()
487 {
488     ASSERT(needsLayout());
489
490     view()->pushLayoutState(this, IntSize(m_x, m_y));
491
492     RenderObject* child = m_firstChild;
493     while (child) {
494         child->layoutIfNeeded();
495         ASSERT(child->isRenderInline() || !child->needsLayout());
496         child = child->nextSibling();
497     }
498
499     view()->popLayoutState();
500     setNeedsLayout(false);
501 }
502
503 void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
504 {
505     ASSERT(child->isAnonymousBlock());
506     ASSERT(!child->childrenInline());
507     
508     if (child->continuation()) 
509         return;
510     
511     RenderObject* firstAnChild = child->firstChild();
512     RenderObject* lastAnChild = child->lastChild();
513     if (firstAnChild) {
514         RenderObject* o = firstAnChild;
515         while(o) {
516             o->setParent(this);
517             o = o->nextSibling();
518         }
519         firstAnChild->setPreviousSibling(child->previousSibling());
520         lastAnChild->setNextSibling(child->nextSibling());
521         if (child->previousSibling())
522             child->previousSibling()->setNextSibling(firstAnChild);
523         if (child->nextSibling())
524             child->nextSibling()->setPreviousSibling(lastAnChild);
525     } else {
526         if (child->previousSibling())
527             child->previousSibling()->setNextSibling(child->nextSibling());
528         if (child->nextSibling())
529             child->nextSibling()->setPreviousSibling(child->previousSibling());
530     }
531     if (child == m_firstChild)
532         m_firstChild = firstAnChild;
533     if (child == m_lastChild)
534         m_lastChild = lastAnChild;
535     child->setParent(0);
536     child->setPreviousSibling(0);
537     child->setNextSibling(0);
538     if (!child->isText()) {
539         RenderContainer *c = static_cast<RenderContainer*>(child);
540         c->m_firstChild = 0;
541         c->m_next = 0;
542     }
543     child->destroy();
544 }
545
546 VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
547 {
548     // no children...return this render object's element, if there is one, and offset 0
549     if (!m_firstChild)
550         return VisiblePosition(element(), 0, DOWNSTREAM);
551         
552     if (isTable() && element()) {
553         int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
554         int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
555         
556         if (x < 0 || x > right || y < 0 || y > bottom) {
557             if (x <= right / 2)
558                 return VisiblePosition(Position(element(), 0));
559             else
560                 return VisiblePosition(Position(element(), maxDeepOffset(element())));
561         }
562     }
563
564     // Pass off to the closest child.
565     int minDist = INT_MAX;
566     RenderObject* closestRenderer = 0;
567     int newX = x;
568     int newY = y;
569     if (isTableRow()) {
570         newX += xPos();
571         newY += yPos();
572     }
573     for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
574         if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow() 
575             || renderer->style()->visibility() != VISIBLE)
576             continue;
577         
578         int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
579         int bottom = top + renderer->contentHeight();
580         int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
581         int right = left + renderer->contentWidth();
582         
583         if (x <= right && x >= left && y <= top && y >= bottom) {
584             if (renderer->isTableRow())
585                 return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
586             return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
587         }
588
589         // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
590         // and use a different compare depending on which piece (x, y) is in.
591         IntPoint cmp;
592         if (x > right) {
593             if (y < top)
594                 cmp = IntPoint(right, top);
595             else if (y > bottom)
596                 cmp = IntPoint(right, bottom);
597             else
598                 cmp = IntPoint(right, y);
599         } else if (x < left) {
600             if (y < top)
601                 cmp = IntPoint(left, top);
602             else if (y > bottom)
603                 cmp = IntPoint(left, bottom);
604             else
605                 cmp = IntPoint(left, y);
606         } else {
607             if (y < top)
608                 cmp = IntPoint(x, top);
609             else
610                 cmp = IntPoint(x, bottom);
611         }
612         
613         int x1minusx2 = cmp.x() - x;
614         int y1minusy2 = cmp.y() - y;
615         
616         int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
617         if (dist < minDist) {
618             closestRenderer = renderer;
619             minDist = dist;
620         }
621     }
622     
623     if (closestRenderer)
624         return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
625     
626     return VisiblePosition(element(), 0, DOWNSTREAM);
627 }
628
629 void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
630 {
631     if (!m_firstChild && (isInline() || isAnonymousBlock())) {
632         int x, y;
633         absolutePositionForContent(x, y);
634         absoluteRects(rects, x, y);
635         return;
636     }
637
638     if (!m_firstChild)
639         return;
640
641     unsigned offset = start;
642     for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
643         if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
644             int x, y;
645             child->absolutePositionForContent(x, y);
646             child->absoluteRects(rects, x, y);
647         }
648     }
649 }
650
651 #undef DEBUG_LAYOUT
652
653 } // namespace WebCore