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