Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: third_party/WebKit/WebCore/rendering/RenderObjectChildList.cpp

Issue 20076: WebKit merge 40500:40539 [WebKit side] (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "RenderObjectChildList.h" 27 #include "RenderObjectChildList.h"
28 #include "RenderObject.h" 28
29 #include "AXObjectCache.h"
30 #include "RenderBlock.h"
31 #include "RenderCounter.h"
32 #include "RenderImageGeneratedContent.h"
33 #include "RenderInline.h"
34 #include "RenderLayer.h"
35 #include "RenderListItem.h"
36 #include "RenderStyle.h"
37 #include "RenderTextFragment.h"
38 #include "RenderView.h"
29 39
30 namespace WebCore { 40 namespace WebCore {
31 41
42 static void updateListMarkerNumbers(RenderObject* child)
43 {
44 for (RenderObject* r = child; r; r = r->nextSibling()) {
45 if (r->isListItem())
46 static_cast<RenderListItem*>(r)->updateValue();
47 }
48 }
49
50
32 void RenderObjectChildList::destroyLeftoverChildren() 51 void RenderObjectChildList::destroyLeftoverChildren()
33 { 52 {
34 while (firstChild()) { 53 while (firstChild()) {
35 if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == RenderStyle::FIRST_LETTER && !firstChild()->isText())) 54 if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == RenderStyle::FIRST_LETTER && !firstChild()->isText()))
36 firstChild()->remove(); // List markers are owned by their enclosin g list and so don't get destroyed by this container. Similarly, first letters ar e destroyed by their remaining text fragment. 55 firstChild()->remove(); // List markers are owned by their enclosin g list and so don't get destroyed by this container. Similarly, first letters ar e destroyed by their remaining text fragment.
37 else { 56 else {
38 // Destroy any anonymous children remaining in the render tree, as w ell as implicit (shadow) DOM elements like those used in the engine-based text f ields. 57 // Destroy any anonymous children remaining in the render tree, as w ell as implicit (shadow) DOM elements like those used in the engine-based text f ields.
39 if (firstChild()->element()) 58 if (firstChild()->element())
40 firstChild()->element()->setRenderer(0); 59 firstChild()->element()->setRenderer(0);
41 firstChild()->destroy(); 60 firstChild()->destroy();
42 } 61 }
43 } 62 }
44 } 63 }
45 64
46 } 65 RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render Object* oldChild, bool fullRemove)
66 {
67 ASSERT(oldChild->parent() == owner);
68
69 // So that we'll get the appropriate dirty bit set (either that a normal flo w child got yanked or
70 // that a positioned child got yanked). We also repaint, so that the area e xposed when the child
71 // disappears gets repainted properly.
72 if (!owner->documentBeingDestroyed() && fullRemove && oldChild->m_everHadLay out) {
73 oldChild->setNeedsLayoutAndPrefWidthsRecalc();
74 oldChild->repaint();
75 }
76
77 // If we have a line box wrapper, delete it.
78 oldChild->deleteLineBoxWrapper();
79
80 if (!owner->documentBeingDestroyed() && fullRemove) {
81 // if we remove visible child from an invisible parent, we don't know th e layer visibility any more
82 RenderLayer* layer = 0;
83 if (owner->style()->visibility() != VISIBLE && oldChild->style()->visibi lity() == VISIBLE && !oldChild->hasLayer()) {
84 layer = owner->enclosingLayer();
85 layer->dirtyVisibleContentStatus();
86 }
87
88 // Keep our layer hierarchy updated.
89 if (oldChild->firstChild() || oldChild->hasLayer()) {
90 if (!layer)
91 layer = owner->enclosingLayer();
92 oldChild->removeLayers(layer);
93 }
94
95 // renumber ordered lists
96 if (oldChild->isListItem())
97 updateListMarkerNumbers(oldChild->nextSibling());
98
99 if (oldChild->isPositioned() && owner->childrenInline())
100 owner->dirtyLinesFromChangedChild(oldChild);
101 }
102
103 // If oldChild is the start or end of the selection, then clear the selectio n to
104 // avoid problems of invalid pointers.
105 // FIXME: The SelectionController should be responsible for this when it
106 // is notified of DOM mutations.
107 if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
108 owner->view()->clearSelection();
109
110 // remove the child
111 if (oldChild->previousSibling())
112 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
113 if (oldChild->nextSibling())
114 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()) ;
115
116 if (firstChild() == oldChild)
117 setFirstChild(oldChild->nextSibling());
118 if (lastChild() == oldChild)
119 setLastChild(oldChild->previousSibling());
120
121 oldChild->setPreviousSibling(0);
122 oldChild->setNextSibling(0);
123 oldChild->setParent(0);
124
125 if (AXObjectCache::accessibilityEnabled())
126 owner->document()->axObjectCache()->childrenChanged(owner);
127
128 return oldChild;
129 }
130
131 void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n ewChild, bool fullAppend)
132 {
133 ASSERT(newChild->parent() == 0);
134 ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->i sTableRow() && !newChild->isTableCell()));
135
136 newChild->setParent(owner);
137 RenderObject* lChild = lastChild();
138
139 if (lChild) {
140 newChild->setPreviousSibling(lChild);
141 lChild->setNextSibling(newChild);
142 } else
143 setFirstChild(newChild);
144
145 setLastChild(newChild);
146
147 if (fullAppend) {
148 // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
149 // and don't have a layer attached to ourselves.
150 RenderLayer* layer = 0;
151 if (newChild->firstChild() || newChild->hasLayer()) {
152 layer = owner->enclosingLayer();
153 newChild->addLayers(layer, newChild);
154 }
155
156 // if the new child is visible but this object was not, tell the layer i t has some visible content
157 // that needs to be drawn and layer visibility optimization can't be use d
158 if (owner->style()->visibility() != VISIBLE && newChild->style()->visibi lity() == VISIBLE && !newChild->hasLayer()) {
159 if (!layer)
160 layer = owner->enclosingLayer();
161 if (layer)
162 layer->setHasVisibleContent(true);
163 }
164
165 if (!newChild->isFloatingOrPositioned() && owner->childrenInline())
166 owner->dirtyLinesFromChangedChild(newChild);
167 }
168
169 newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing blo ck hierarchy.
170 if (!owner->normalChildNeedsLayout())
171 owner->setChildNeedsLayout(true); // We may supply the static position f or an absolute positioned child.
172
173 if (AXObjectCache::accessibilityEnabled())
174 owner->document()->axObjectCache()->childrenChanged(owner);
175 }
176
177 void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c hild, RenderObject* beforeChild, bool fullInsert)
178 {
179 if (!beforeChild) {
180 appendChildNode(owner, child);
181 return;
182 }
183
184 ASSERT(!child->parent());
185 while (beforeChild->parent() != owner && beforeChild->parent()->isAnonymousB lock())
186 beforeChild = beforeChild->parent();
187 ASSERT(beforeChild->parent() == owner);
188
189 ASSERT(!owner->isBlockFlow() || (!child->isTableSection() && !child->isTable Row() && !child->isTableCell()));
190
191 if (beforeChild == firstChild())
192 setFirstChild(child);
193
194 RenderObject* prev = beforeChild->previousSibling();
195 child->setNextSibling(beforeChild);
196 beforeChild->setPreviousSibling(child);
197 if (prev)
198 prev->setNextSibling(child);
199 child->setPreviousSibling(prev);
200
201 child->setParent(owner);
202
203 if (fullInsert) {
204 // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
205 // and don't have a layer attached to ourselves.
206 RenderLayer* layer = 0;
207 if (child->firstChild() || child->hasLayer()) {
208 layer = owner->enclosingLayer();
209 child->addLayers(layer, child);
210 }
211
212 // if the new child is visible but this object was not, tell the layer i t has some visible content
213 // that needs to be drawn and layer visibility optimization can't be use d
214 if (owner->style()->visibility() != VISIBLE && child->style()->visibilit y() == VISIBLE && !child->hasLayer()) {
215 if (!layer)
216 layer = owner->enclosingLayer();
217 if (layer)
218 layer->setHasVisibleContent(true);
219 }
220
221
222 if (!child->isFloating() && owner->childrenInline())
223 owner->dirtyLinesFromChangedChild(child);
224 }
225
226 child->setNeedsLayoutAndPrefWidthsRecalc();
227 if (!owner->normalChildNeedsLayout())
228 owner->setChildNeedsLayout(true); // We may supply the static position f or an absolute positioned child.
229
230 if (AXObjectCache::accessibilityEnabled())
231 owner->document()->axObjectCache()->childrenChanged(owner);
232 }
233
234 static RenderObject* beforeAfterContainer(RenderObject* container, RenderStyle:: PseudoId type)
235 {
236 if (type == RenderStyle::BEFORE) {
237 RenderObject* first = container;
238 do {
239 // Skip list markers.
240 first = first->firstChild();
241 while (first && first->isListMarker())
242 first = first->nextSibling();
243 } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
244 if (first && first->style()->styleType() != type)
245 return 0;
246 return first;
247 }
248 if (type == RenderStyle::AFTER) {
249 RenderObject* last = container;
250 do {
251 last = last->lastChild();
252 } while (last && last->isAnonymous() && last->style()->styleType() == Re nderStyle::NOPSEUDO && !last->isListMarker());
253 if (last && last->style()->styleType() != type)
254 return 0;
255 return last;
256 }
257
258 ASSERT_NOT_REACHED();
259 return 0;
260 }
261
262 static RenderObject* findBeforeAfterParent(RenderObject* object)
263 {
264 // Only table parts need to search for the :before or :after parent
265 if (!(object->isTable() || object->isTableSection() || object->isTableRow()) )
266 return object;
267
268 RenderObject* beforeAfterParent = object;
269 while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterPare nt->isImage()))
270 beforeAfterParent = beforeAfterParent->firstChild();
271 return beforeAfterParent;
272 }
273
274 static void invalidateCountersInContainer(RenderObject* container)
275 {
276 if (!container)
277 return;
278 container = findBeforeAfterParent(container);
279 if (!container)
280 return;
281 for (RenderObject* content = container->firstChild(); content; content = con tent->nextSibling()) {
282 if (content->isCounter())
283 static_cast<RenderCounter*>(content)->invalidate();
284 }
285 }
286
287 void RenderObjectChildList::invalidateCounters(RenderObject* owner)
288 {
289 ASSERT(!owner->documentBeingDestroyed());
290 invalidateCountersInContainer(beforeAfterContainer(owner, RenderStyle::BEFOR E));
291 invalidateCountersInContainer(beforeAfterContainer(owner, RenderStyle::AFTER ));
292 }
293
294 void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Render Style::PseudoId type, RenderObject* styledObject)
295 {
296 // Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
297 ASSERT(owner->document()->usesBeforeAfterRules());
298
299 // In CSS2, before/after pseudo-content cannot nest. Check this first.
300 if (owner->style()->styleType() == RenderStyle::BEFORE || owner->style()->st yleType() == RenderStyle::AFTER)
301 return;
302
303 if (!styledObject)
304 styledObject = owner;
305
306 RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
307 RenderObject* child = beforeAfterContainer(owner, type);
308
309 // Whether or not we currently have generated content attached.
310 bool oldContentPresent = child;
311
312 // Whether or not we now want generated content.
313 bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
314
315 // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
316 // :after content and not :before content.
317 if (newContentWanted && type == RenderStyle::BEFORE && owner->isRenderInline () && toRenderInline(owner)->isInlineContinuation())
318 newContentWanted = false;
319
320 // Similarly, if we're the beginning of a <q>, and there's an inline continu ation for our object,
321 // then we don't generate the :after content.
322 if (newContentWanted && type == RenderStyle::AFTER && owner->isRenderInline( ) && toRenderInline(owner)->continuation())
323 newContentWanted = false;
324
325 // If we don't want generated content any longer, or if we have generated co ntent, but it's no longer
326 // identical to the new content data we want to build render objects for, th en we nuke all
327 // of the old generated content.
328 if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), ps eudoElementStyle) == Node::Detach)) {
329 // Nuke the child.
330 if (child && child->style()->styleType() == type) {
331 oldContentPresent = false;
332 child->destroy();
333 child = (type == RenderStyle::BEFORE) ? owner->virtualChildren()->fi rstChild() : owner->virtualChildren()->lastChild();
334 }
335 }
336
337 // If we have no pseudo-element style or if the pseudo-element style's displ ay type is NONE, then we
338 // have no generated content and can now return.
339 if (!newContentWanted)
340 return;
341
342 if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
343 !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementSty le->position() == FixedPosition))
344 // According to the CSS2 spec (the end of section 12.1), the only allowe d
345 // display values for the pseudo style are NONE and INLINE for inline fl ows.
346 // FIXME: CSS2.1 lifted this restriction, but block display types will c rash.
347 // For now we at least relax the restriction to allow all inline types l ike inline-block
348 // and inline-table.
349 pseudoElementStyle->setDisplay(INLINE);
350
351 if (oldContentPresent) {
352 if (child && child->style()->styleType() == type) {
353 // We have generated content present still. We want to walk this co ntent and update our
354 // style information with the new pseudo-element style.
355 child->setStyle(pseudoElementStyle);
356
357 RenderObject* beforeAfterParent = findBeforeAfterParent(child);
358 if (!beforeAfterParent)
359 return;
360
361 // Note that if we ever support additional types of generated conten t (which should be way off
362 // in the future), this code will need to be patched.
363 for (RenderObject* genChild = beforeAfterParent->firstChild(); genCh ild; genChild = genChild->nextSibling()) {
364 if (genChild->isText())
365 // Generated text content is a child whose style also needs to be set to the pseudo-element style.
366 genChild->setStyle(pseudoElementStyle);
367 else if (genChild->isImage()) {
368 // Images get an empty style that inherits from the pseudo.
369 RefPtr<RenderStyle> style = RenderStyle::create();
370 style->inheritFrom(pseudoElementStyle);
371 genChild->setStyle(style.release());
372 } else
373 // Must be a first-letter container. updateFirstLetter() wil l take care of it.
374 ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_ LETTER);
375 }
376 }
377 return; // We've updated the generated content. That's all we needed to do.
378 }
379
380 RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? owner->virtualC hildren()->firstChild() : 0;
381
382 // Generated content consists of a single container that houses multiple chi ldren (specified
383 // by the content property). This generated content container gets the pseu do-element style set on it.
384 RenderObject* generatedContentContainer = 0;
385
386 // Walk our list of generated content and create render objects for each.
387 for (const ContentData* content = pseudoElementStyle->contentData(); content ; content = content->m_next) {
388 RenderObject* renderer = 0;
389 switch (content->m_type) {
390 case CONTENT_NONE:
391 break;
392 case CONTENT_TEXT:
393 renderer = new (owner->renderArena()) RenderTextFragment(owner-> document() /* anonymous object */, content->m_content.m_text);
394 renderer->setStyle(pseudoElementStyle);
395 break;
396 case CONTENT_OBJECT: {
397 RenderImageGeneratedContent* image = new (owner->renderArena()) RenderImageGeneratedContent(owner->document()); // anonymous object
398 RefPtr<RenderStyle> style = RenderStyle::create();
399 style->inheritFrom(pseudoElementStyle);
400 image->setStyle(style.release());
401 if (StyleImage* styleImage = content->m_content.m_image)
402 image->setStyleImage(styleImage);
403 renderer = image;
404 break;
405 }
406 case CONTENT_COUNTER:
407 renderer = new (owner->renderArena()) RenderCounter(owner->docum ent(), *content->m_content.m_counter);
408 renderer->setStyle(pseudoElementStyle);
409 break;
410 }
411
412 if (renderer) {
413 if (!generatedContentContainer) {
414 // Make a generated box that might be any display type now that we are able to drill down into children
415 // to find the original content properly.
416 generatedContentContainer = RenderObject::createObject(owner->do cument(), pseudoElementStyle);
417 generatedContentContainer->setStyle(pseudoElementStyle);
418 owner->addChild(generatedContentContainer, insertBefore);
419 }
420 generatedContentContainer->addChild(renderer);
421 }
422 }
423 }
424
425 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698