OSDN Git Service

Merge WebKit at r78450: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / rendering / RenderObjectChildList.cpp
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "RenderObjectChildList.h"
29
30 #include "AXObjectCache.h"
31 #include "ContentData.h"
32 #include "RenderBlock.h"
33 #include "RenderCounter.h"
34 #include "RenderImage.h"
35 #include "RenderImageResourceStyleImage.h"
36 #include "RenderInline.h"
37 #include "RenderLayer.h"
38 #include "RenderListItem.h"
39 #include "RenderStyle.h"
40 #include "RenderTextFragment.h"
41 #include "RenderView.h"
42
43 namespace WebCore {
44
45 void RenderObjectChildList::destroyLeftoverChildren()
46 {
47     while (firstChild()) {
48         if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText()))
49             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.
50         else if (firstChild()->isRunIn() && firstChild()->node()) {
51             firstChild()->node()->setRenderer(0);
52             firstChild()->node()->setNeedsStyleRecalc();
53             firstChild()->destroy();
54         } else {
55             // 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.
56             if (firstChild()->node())
57                 firstChild()->node()->setRenderer(0);
58             firstChild()->destroy();
59         }
60     }
61 }
62
63 RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool fullRemove)
64 {
65     ASSERT(oldChild->parent() == owner);
66
67     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
68     // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
69     // disappears gets repainted properly.
70     if (!owner->documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
71         oldChild->setNeedsLayoutAndPrefWidthsRecalc();
72         if (oldChild->isBody())
73             owner->view()->repaint();
74         else
75             oldChild->repaint();
76     }
77
78     // If we have a line box wrapper, delete it.
79     if (oldChild->isBox())
80         toRenderBox(oldChild)->deleteLineBoxWrapper();
81
82     if (!owner->documentBeingDestroyed() && fullRemove) {
83         // if we remove visible child from an invisible parent, we don't know the layer visibility any more
84         RenderLayer* layer = 0;
85         if (owner->style()->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
86             layer = owner->enclosingLayer();
87             layer->dirtyVisibleContentStatus();
88         }
89
90          // Keep our layer hierarchy updated.
91         if (oldChild->firstChild() || oldChild->hasLayer()) {
92             if (!layer)
93                 layer = owner->enclosingLayer();
94             oldChild->removeLayers(layer);
95         }
96
97         if (oldChild->isListItem())
98             toRenderListItem(oldChild)->updateListMarkerNumbers();
99
100         if (oldChild->isPositioned() && owner->childrenInline())
101             owner->dirtyLinesFromChangedChild(oldChild);
102
103 #if ENABLE(SVG)
104         // Update cached boundaries in SVG renderers, if a child is removed.
105         owner->setNeedsBoundariesUpdate();
106 #endif
107     }
108     
109     // If oldChild is the start or end of the selection, then clear the selection to
110     // avoid problems of invalid pointers.
111     // FIXME: The SelectionController should be responsible for this when it
112     // is notified of DOM mutations.
113     if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
114         owner->view()->clearSelection();
115
116     // remove the child
117     if (oldChild->previousSibling())
118         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
119     if (oldChild->nextSibling())
120         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
121
122     if (firstChild() == oldChild)
123         setFirstChild(oldChild->nextSibling());
124     if (lastChild() == oldChild)
125         setLastChild(oldChild->previousSibling());
126
127     oldChild->setPreviousSibling(0);
128     oldChild->setNextSibling(0);
129     oldChild->setParent(0);
130
131     if (oldChild->m_hasCounterNodeMap)
132         RenderCounter::destroyCounterNodes(oldChild);
133
134     if (AXObjectCache::accessibilityEnabled())
135         owner->document()->axObjectCache()->childrenChanged(owner);
136
137     return oldChild;
138 }
139
140 void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* newChild, bool fullAppend)
141 {
142     ASSERT(newChild->parent() == 0);
143     ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
144
145     newChild->setParent(owner);
146     RenderObject* lChild = lastChild();
147
148     if (lChild) {
149         newChild->setPreviousSibling(lChild);
150         lChild->setNextSibling(newChild);
151     } else
152         setFirstChild(newChild);
153
154     setLastChild(newChild);
155     
156     if (fullAppend) {
157         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
158         // and don't have a layer attached to ourselves.
159         RenderLayer* layer = 0;
160         if (newChild->firstChild() || newChild->hasLayer()) {
161             layer = owner->enclosingLayer();
162             newChild->addLayers(layer, newChild);
163         }
164
165         // if the new child is visible but this object was not, tell the layer it has some visible content
166         // that needs to be drawn and layer visibility optimization can't be used
167         if (owner->style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
168             if (!layer)
169                 layer = owner->enclosingLayer();
170             if (layer)
171                 layer->setHasVisibleContent(true);
172         }
173
174         if (newChild->isListItem())
175             toRenderListItem(newChild)->updateListMarkerNumbers();
176
177         if (!newChild->isFloatingOrPositioned() && owner->childrenInline())
178             owner->dirtyLinesFromChangedChild(newChild);
179     }
180
181     RenderCounter::rendererSubtreeAttached(newChild);
182     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
183     if (!owner->normalChildNeedsLayout())
184         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
185     
186     if (AXObjectCache::accessibilityEnabled())
187         owner->document()->axObjectCache()->childrenChanged(owner);
188 }
189
190 void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* beforeChild, bool fullInsert)
191 {
192     if (!beforeChild) {
193         appendChildNode(owner, child, fullInsert);
194         return;
195     }
196
197     ASSERT(!child->parent());
198     while (beforeChild->parent() != owner && beforeChild->parent()->isAnonymousBlock())
199         beforeChild = beforeChild->parent();
200     ASSERT(beforeChild->parent() == owner);
201
202     ASSERT(!owner->isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
203
204     if (beforeChild == firstChild())
205         setFirstChild(child);
206
207     RenderObject* prev = beforeChild->previousSibling();
208     child->setNextSibling(beforeChild);
209     beforeChild->setPreviousSibling(child);
210     if (prev)
211         prev->setNextSibling(child);
212     child->setPreviousSibling(prev);
213
214     child->setParent(owner);
215     
216     if (fullInsert) {
217         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
218         // and don't have a layer attached to ourselves.
219         RenderLayer* layer = 0;
220         if (child->firstChild() || child->hasLayer()) {
221             layer = owner->enclosingLayer();
222             child->addLayers(layer, child);
223         }
224
225         // if the new child is visible but this object was not, tell the layer it has some visible content
226         // that needs to be drawn and layer visibility optimization can't be used
227         if (owner->style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
228             if (!layer)
229                 layer = owner->enclosingLayer();
230             if (layer)
231                 layer->setHasVisibleContent(true);
232         }
233
234         if (child->isListItem())
235             toRenderListItem(child)->updateListMarkerNumbers();
236
237         if (!child->isFloating() && owner->childrenInline())
238             owner->dirtyLinesFromChangedChild(child);
239     }
240
241     RenderCounter::rendererSubtreeAttached(child);
242     child->setNeedsLayoutAndPrefWidthsRecalc();
243     if (!owner->normalChildNeedsLayout())
244         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
245     
246     if (AXObjectCache::accessibilityEnabled())
247         owner->document()->axObjectCache()->childrenChanged(owner);
248 }
249
250 static RenderObject* findBeforeAfterParent(RenderObject* object)
251 {
252     // Only table parts need to search for the :before or :after parent
253     if (!(object->isTable() || object->isTableSection() || object->isTableRow()))
254         return object;
255
256     RenderObject* beforeAfterParent = object;
257     while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
258         beforeAfterParent = beforeAfterParent->firstChild();
259     return beforeAfterParent;
260 }
261
262 static void invalidateCountersInContainer(RenderObject* container, const AtomicString& identifier)
263 {
264     if (!container)
265         return;
266     container = findBeforeAfterParent(container);
267     if (!container)
268         return;
269     // Sometimes the counter is attached directly on the container.
270     if (container->isCounter()) {
271         toRenderCounter(container)->invalidate(identifier);
272         return;
273     }
274     for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
275         if (content->isCounter())
276             toRenderCounter(content)->invalidate(identifier);
277     }
278 }
279
280 void RenderObjectChildList::invalidateCounters(const RenderObject* owner, const AtomicString& identifier)
281 {
282     ASSERT(!owner->documentBeingDestroyed());
283     invalidateCountersInContainer(beforePseudoElementRenderer(owner), identifier);
284     invalidateCountersInContainer(afterPseudoElementRenderer(owner), identifier);
285 }
286
287 RenderObject* RenderObjectChildList::beforePseudoElementRenderer(const RenderObject* owner) const
288 {
289     // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent.
290     // Therefore we should skip these generated run-ins when checking our immediate children.
291     // If we don't find our :before child immediately, then we should check if we own a
292     // generated inline run-in in the next level of children.
293     RenderObject* first = const_cast<RenderObject*>(owner);
294     do {
295         // Skip list markers and generated run-ins
296         first = first->firstChild();
297         while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn() && first->isAnonymous())))
298             first = first->nextSibling();
299     } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO);
300
301     if (!first)
302         return 0;
303
304     if (first->style()->styleType() == BEFORE)
305         return first;
306
307     // Check for a possible generated run-in, using run-in positioning rules.
308     // Skip inlines and floating / positioned blocks, and place as the first child.
309     first = owner->firstChild();
310     if (!first->isRenderBlock())
311         return 0;
312     while (first && first->isFloatingOrPositioned())
313         first = first->nextSibling();
314     if (first) {
315         first = first->firstChild();
316         // We still need to skip any list markers that could exist before the run-in.
317         while (first && first->isListMarker())
318             first = first->nextSibling();
319         if (first && first->style()->styleType() == BEFORE && first->isRenderInline() && first->isRunIn() && first->isAnonymous())
320             return first;
321     }
322     return 0;
323 }
324
325 RenderObject* RenderObjectChildList::afterPseudoElementRenderer(const RenderObject* owner) const
326 {
327     RenderObject* last = const_cast<RenderObject*>(owner);
328     do {
329         last = last->lastChild();
330     } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker());
331     if (last && last->style()->styleType() != AFTER)
332         return 0;
333     return last;
334 }
335
336 void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
337 {
338     // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
339     ASSERT(owner->document()->usesBeforeAfterRules());
340
341     // In CSS2, before/after pseudo-content cannot nest.  Check this first.
342     if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
343         return;
344     
345     if (!styledObject)
346         styledObject = owner;
347
348     RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
349     RenderObject* child;
350     switch (type) {
351     case BEFORE:
352         child = beforePseudoElementRenderer(owner);
353         break;
354     case AFTER:
355         child = afterPseudoElementRenderer(owner);
356         break;
357     default:
358         ASSERT_NOT_REACHED();
359         return;
360     }
361
362     // Whether or not we currently have generated content attached.
363     bool oldContentPresent = child;
364
365     // Whether or not we now want generated content.
366     bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
367
368     // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
369     // :after content and not :before content.
370     if (newContentWanted && type == BEFORE && owner->isElementContinuation())
371         newContentWanted = false;
372
373     // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
374     // then we don't generate the :after content.
375     if (newContentWanted && type == AFTER && owner->virtualContinuation())
376         newContentWanted = false;
377     
378     // If we don't want generated content any longer, or if we have generated content, but it's no longer
379     // identical to the new content data we want to build render objects for, then we nuke all
380     // of the old generated content.
381     if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
382         // Nuke the child. 
383         if (child->style()->styleType() == type) {
384             oldContentPresent = false;
385             child->destroy();
386             child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
387         }
388     }
389
390     // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
391     // have no generated content and can now return.
392     if (!newContentWanted)
393         return;
394
395     if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
396         !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
397         // According to the CSS2 spec (the end of section 12.1), the only allowed
398         // display values for the pseudo style are NONE and INLINE for inline flows.
399         // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
400         // For now we at least relax the restriction to allow all inline types like inline-block
401         // and inline-table.
402         pseudoElementStyle->setDisplay(INLINE);
403
404     if (oldContentPresent) {
405         if (child && child->style()->styleType() == type) {
406             // We have generated content present still.  We want to walk this content and update our
407             // style information with the new pseudo-element style.
408             child->setStyle(pseudoElementStyle);
409
410             RenderObject* beforeAfterParent = findBeforeAfterParent(child);
411             if (!beforeAfterParent)
412                 return;
413
414             // Note that if we ever support additional types of generated content (which should be way off
415             // in the future), this code will need to be patched.
416             for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
417                 if (genChild->isText())
418                     // Generated text content is a child whose style also needs to be set to the pseudo-element style.
419                     genChild->setStyle(pseudoElementStyle);
420                 else if (genChild->isImage()) {
421                     // Images get an empty style that inherits from the pseudo.
422                     RefPtr<RenderStyle> style = RenderStyle::create();
423                     style->inheritFrom(pseudoElementStyle);
424                     genChild->setStyle(style.release());
425                 } else {
426                     // RenderListItem may insert a list marker here. We do not need to care about this case.
427                     // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
428                     ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
429                 }
430             }
431         }
432         return; // We've updated the generated content. That's all we needed to do.
433     }
434     
435     RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;
436
437     // Generated content consists of a single container that houses multiple children (specified
438     // by the content property).  This generated content container gets the pseudo-element style set on it.
439     RenderObject* generatedContentContainer = 0;
440     
441     // Walk our list of generated content and create render objects for each.
442     for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
443         RenderObject* renderer = 0;
444         switch (content->type()) {
445             case CONTENT_NONE:
446                 break;
447             case CONTENT_TEXT:
448                 renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, content->text());
449                 renderer->setStyle(pseudoElementStyle);
450                 break;
451             case CONTENT_OBJECT: {
452                 RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object
453                 RefPtr<RenderStyle> style = RenderStyle::create();
454                 style->inheritFrom(pseudoElementStyle);
455                 image->setStyle(style.release());
456                 if (StyleImage* styleImage = content->image())
457                     image->setImageResource(RenderImageResourceStyleImage::create(styleImage));
458                 else
459                     image->setImageResource(RenderImageResource::create());
460                 renderer = image;
461                 break;
462             }
463             case CONTENT_COUNTER:
464                 renderer = new (owner->renderArena()) RenderCounter(owner->document(), *content->counter());
465                 renderer->setStyle(pseudoElementStyle);
466                 break;
467         }
468
469         if (renderer) {
470             if (!generatedContentContainer) {
471                 // Make a generated box that might be any display type now that we are able to drill down into children
472                 // to find the original content properly.
473                 generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
474                 ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
475                 generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
476                 generatedContentContainer->setStyle(pseudoElementStyle);
477                 owner->addChild(generatedContentContainer, insertBefore);
478             }
479             if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
480                 generatedContentContainer->addChild(renderer);
481             else
482                 renderer->destroy();
483         }
484     }
485 }
486
487 } // namespace WebCore