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

Unified Diff: third_party/WebKit/WebCore/rendering/RenderContainer.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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/WebCore/rendering/RenderContainer.cpp
===================================================================
--- third_party/WebKit/WebCore/rendering/RenderContainer.cpp (revision 9118)
+++ third_party/WebKit/WebCore/rendering/RenderContainer.cpp (working copy)
@@ -96,7 +96,7 @@
table->addChild(newChild);
} else {
// just add it...
- insertChildNode(newChild, beforeChild);
+ children()->insertChildNode(this, newChild, beforeChild);
}
if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
@@ -106,481 +106,15 @@
}
}
-RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
-{
- ASSERT(oldChild->parent() == this);
-
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if (!documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
- oldChild->setNeedsLayoutAndPrefWidthsRecalc();
- oldChild->repaint();
- }
-
- // If we have a line box wrapper, delete it.
- oldChild->deleteLineBoxWrapper();
-
- if (!documentBeingDestroyed() && fullRemove) {
- // if we remove visible child from an invisible parent, we don't know the layer visibility any more
- RenderLayer* layer = 0;
- if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
- layer = enclosingLayer();
- layer->dirtyVisibleContentStatus();
- }
-
- // Keep our layer hierarchy updated.
- if (oldChild->firstChild() || oldChild->hasLayer()) {
- if (!layer) layer = enclosingLayer();
- oldChild->removeLayers(layer);
- }
-
- // renumber ordered lists
- if (oldChild->isListItem())
- updateListMarkerNumbers(oldChild->nextSibling());
-
- if (oldChild->isPositioned() && childrenInline())
- dirtyLinesFromChangedChild(oldChild);
- }
-
- // If oldChild is the start or end of the selection, then clear the selection to
- // avoid problems of invalid pointers.
- // FIXME: The SelectionController should be responsible for this when it
- // is notified of DOM mutations.
- if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
- view()->clearSelection();
-
- // remove the child
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (children()->firstChild() == oldChild)
- children()->setFirstChild(oldChild->nextSibling());
- if (children()->lastChild() == oldChild)
- children()->setLastChild(oldChild->previousSibling());
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-
- return oldChild;
-}
-
void RenderContainer::removeChild(RenderObject* oldChild)
{
// We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
// cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
// layout anyway).
oldChild->removeFromObjectLists();
-
- removeChildNode(oldChild);
+ m_children.removeChildNode(this, oldChild);
}
-RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
-{
- if (type == RenderStyle::BEFORE) {
- RenderObject* first = this;
- do {
- // Skip list markers.
- first = first->firstChild();
- while (first && first->isListMarker())
- first = first->nextSibling();
- } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
- if (first && first->style()->styleType() != type)
- return 0;
- return first;
- }
- if (type == RenderStyle::AFTER) {
- RenderObject* last = this;
- do {
- last = last->lastChild();
- } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
- if (last && last->style()->styleType() != type)
- return 0;
- return last;
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
-{
- // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
- if (parent() && parent()->createsAnonymousWrapper())
- return;
- updateBeforeAfterContentForContainer(type, this);
-}
-
-static RenderObject* findBeforeAfterParent(RenderObject* object)
-{
- // Only table parts need to search for the :before or :after parent
- if (!(object->isTable() || object->isTableSection() || object->isTableRow()))
- return object;
-
- RenderObject* beforeAfterParent = object;
- while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
- beforeAfterParent = beforeAfterParent->firstChild();
- return beforeAfterParent;
-}
-
-void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
-{
- // Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
- ASSERT(document()->usesBeforeAfterRules());
-
- // In CSS2, before/after pseudo-content cannot nest. Check this first.
- if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
- return;
-
- RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
- RenderObject* child = beforeAfterContainer(type);
-
- // Whether or not we currently have generated content attached.
- bool oldContentPresent = child;
-
- // Whether or not we now want generated content.
- bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
-
- // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
- // :after content and not :before content.
- if (newContentWanted && type == RenderStyle::BEFORE && isRenderInline() && toRenderInline(this)->isInlineContinuation())
- newContentWanted = false;
-
- // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
- // then we don't generate the :after content.
- if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && toRenderInline(this)->continuation())
- newContentWanted = false;
-
- // If we don't want generated content any longer, or if we have generated content, but it's no longer
- // identical to the new content data we want to build render objects for, then we nuke all
- // of the old generated content.
- if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
- // Nuke the child.
- if (child && child->style()->styleType() == type) {
- oldContentPresent = false;
- child->destroy();
- child = (type == RenderStyle::BEFORE) ? children()->firstChild() : children()->lastChild();
- }
- }
-
- // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
- // have no generated content and can now return.
- if (!newContentWanted)
- return;
-
- if (isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
- !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
- // According to the CSS2 spec (the end of section 12.1), the only allowed
- // display values for the pseudo style are NONE and INLINE for inline flows.
- // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
- // For now we at least relax the restriction to allow all inline types like inline-block
- // and inline-table.
- pseudoElementStyle->setDisplay(INLINE);
-
- if (oldContentPresent) {
- if (child && child->style()->styleType() == type) {
- // We have generated content present still. We want to walk this content and update our
- // style information with the new pseudo-element style.
- child->setStyle(pseudoElementStyle);
-
- RenderObject* beforeAfterParent = findBeforeAfterParent(child);
- if (!beforeAfterParent)
- return;
-
- // Note that if we ever support additional types of generated content (which should be way off
- // in the future), this code will need to be patched.
- for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
- if (genChild->isText())
- // Generated text content is a child whose style also needs to be set to the pseudo-element style.
- genChild->setStyle(pseudoElementStyle);
- else if (genChild->isImage()) {
- // Images get an empty style that inherits from the pseudo.
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- genChild->setStyle(style.release());
- } else
- // Must be a first-letter container. updateFirstLetter() will take care of it.
- ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
- }
- }
- return; // We've updated the generated content. That's all we needed to do.
- }
-
- RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? children()->firstChild() : 0;
-
- // Generated content consists of a single container that houses multiple children (specified
- // by the content property). This generated content container gets the pseudo-element style set on it.
- RenderObject* generatedContentContainer = 0;
-
- // Walk our list of generated content and create render objects for each.
- for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
- RenderObject* renderer = 0;
- switch (content->m_type) {
- case CONTENT_NONE:
- break;
- case CONTENT_TEXT:
- renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
- renderer->setStyle(pseudoElementStyle);
- break;
- case CONTENT_OBJECT: {
- RenderImageGeneratedContent* image = new (renderArena()) RenderImageGeneratedContent(document()); // anonymous object
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- image->setStyle(style.release());
- if (StyleImage* styleImage = content->m_content.m_image)
- image->setStyleImage(styleImage);
- renderer = image;
- break;
- }
- case CONTENT_COUNTER:
- renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
- renderer->setStyle(pseudoElementStyle);
- break;
- }
-
- if (renderer) {
- if (!generatedContentContainer) {
- // Make a generated box that might be any display type now that we are able to drill down into children
- // to find the original content properly.
- generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
- generatedContentContainer->setStyle(pseudoElementStyle);
- addChild(generatedContentContainer, insertBefore);
- }
- generatedContentContainer->addChild(renderer);
- }
- }
-}
-
-bool RenderContainer::isAfterContent(RenderObject* child) const
-{
- if (!child)
- return false;
- if (child->style()->styleType() != RenderStyle::AFTER)
- return false;
- // Text nodes don't have their own styles, so ignore the style on a text node.
- if (child->isText() && !child->isBR())
- return false;
- return true;
-}
-
-static void invalidateCountersInContainer(RenderObject* container)
-{
- if (!container)
- return;
- container = findBeforeAfterParent(container);
- if (!container)
- return;
- for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
- if (content->isCounter())
- static_cast<RenderCounter*>(content)->invalidate();
- }
-}
-
-void RenderContainer::invalidateCounters()
-{
- if (documentBeingDestroyed())
- return;
-
- invalidateCountersInContainer(beforeAfterContainer(RenderStyle::BEFORE));
- invalidateCountersInContainer(beforeAfterContainer(RenderStyle::AFTER));
-}
-
-void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
-{
- ASSERT(newChild->parent() == 0);
- ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
-
- newChild->setParent(this);
- RenderObject* lChild = children()->lastChild();
-
- if (lChild) {
- newChild->setPreviousSibling(lChild);
- lChild->setNextSibling(newChild);
- } else
- children()->setFirstChild(newChild);
-
- children()->setLastChild(newChild);
-
- if (fullAppend) {
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- RenderLayer* layer = 0;
- if (newChild->firstChild() || newChild->hasLayer()) {
- layer = enclosingLayer();
- newChild->addLayers(layer, newChild);
- }
-
- // if the new child is visible but this object was not, tell the layer it has some visible content
- // that needs to be drawn and layer visibility optimization can't be used
- if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
- if (!layer)
- layer = enclosingLayer();
- if (layer)
- layer->setHasVisibleContent(true);
- }
-
- if (!newChild->isFloatingOrPositioned() && childrenInline())
- dirtyLinesFromChangedChild(newChild);
- }
-
- newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
-void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
-{
- if (!beforeChild) {
- appendChildNode(child);
- return;
- }
-
- ASSERT(!child->parent());
- while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
- beforeChild = beforeChild->parent();
- ASSERT(beforeChild->parent() == this);
-
- ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
-
- if (beforeChild == children()->firstChild())
- children()->setFirstChild(child);
-
- RenderObject* prev = beforeChild->previousSibling();
- child->setNextSibling(beforeChild);
- beforeChild->setPreviousSibling(child);
- if(prev) prev->setNextSibling(child);
- child->setPreviousSibling(prev);
-
- child->setParent(this);
-
- if (fullInsert) {
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- RenderLayer* layer = 0;
- if (child->firstChild() || child->hasLayer()) {
- layer = enclosingLayer();
- child->addLayers(layer, child);
- }
-
- // if the new child is visible but this object was not, tell the layer it has some visible content
- // that needs to be drawn and layer visibility optimization can't be used
- if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
- if (!layer)
- layer = enclosingLayer();
- if (layer)
- layer->setHasVisibleContent(true);
- }
-
-
- if (!child->isFloating() && childrenInline())
- dirtyLinesFromChangedChild(child);
- }
-
- child->setNeedsLayoutAndPrefWidthsRecalc();
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
-VisiblePosition RenderContainer::positionForCoordinates(int xPos, int yPos)
-{
- // no children...return this render object's element, if there is one, and offset 0
- if (!children()->firstChild())
- return VisiblePosition(element(), 0, DOWNSTREAM);
-
- if (isTable() && element()) {
- int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
- int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
-
- if (xPos < 0 || xPos > right || yPos < 0 || yPos > bottom) {
- if (xPos <= right / 2)
- return VisiblePosition(Position(element(), 0));
- else
- return VisiblePosition(Position(element(), maxDeepOffset(element())));
- }
- }
-
- // Pass off to the closest child.
- int minDist = INT_MAX;
- RenderBox* closestRenderer = 0;
- int newX = xPos;
- int newY = yPos;
- if (isTableRow()) {
- newX += x();
- newY += y();
- }
- for (RenderObject* renderObject = children()->firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
- if (!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow()
- || renderObject->style()->visibility() != VISIBLE)
- continue;
-
- if (!renderObject->isBox())
- continue;
-
- RenderBox* renderer = toRenderBox(renderObject);
-
- int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->y());
- int bottom = top + renderer->contentHeight();
- int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->x());
- int right = left + renderer->contentWidth();
-
- if (xPos <= right && xPos >= left && yPos <= top && yPos >= bottom) {
- if (renderer->isTableRow())
- return renderer->positionForCoordinates(xPos + newX - renderer->x(), yPos + newY - renderer->y());
- return renderer->positionForCoordinates(xPos - renderer->x(), yPos - renderer->y());
- }
-
- // Find the distance from (x, y) to the box. Split the space around the box into 8 pieces
- // and use a different compare depending on which piece (x, y) is in.
- IntPoint cmp;
- if (xPos > right) {
- if (yPos < top)
- cmp = IntPoint(right, top);
- else if (yPos > bottom)
- cmp = IntPoint(right, bottom);
- else
- cmp = IntPoint(right, yPos);
- } else if (xPos < left) {
- if (yPos < top)
- cmp = IntPoint(left, top);
- else if (yPos > bottom)
- cmp = IntPoint(left, bottom);
- else
- cmp = IntPoint(left, yPos);
- } else {
- if (yPos < top)
- cmp = IntPoint(xPos, top);
- else
- cmp = IntPoint(xPos, bottom);
- }
-
- int x1minusx2 = cmp.x() - xPos;
- int y1minusy2 = cmp.y() - yPos;
-
- int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
- if (dist < minDist) {
- closestRenderer = renderer;
- minDist = dist;
- }
- }
-
- if (closestRenderer)
- return closestRenderer->positionForCoordinates(newX - closestRenderer->x(), newY - closestRenderer->y());
-
- return VisiblePosition(element(), 0, DOWNSTREAM);
-}
-
void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
{
if (!children()->firstChild() && (isInline() || isAnonymousBlock())) {
« no previous file with comments | « third_party/WebKit/WebCore/rendering/RenderContainer.h ('k') | third_party/WebKit/WebCore/rendering/RenderCounter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698