void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer)
{
    ASSERT(!newChild->parent());
    ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));

    while (beforeChild && beforeChild->parent() && beforeChild->parent() != owner)
        beforeChild = beforeChild->parent();

    // This should never happen, but if it does prevent render tree corruption
    // where child->parent() ends up being owner but child->nextSibling()->parent()
    // is not owner.
    if (beforeChild && beforeChild->parent() != owner) {
        ASSERT_NOT_REACHED();
        return;
    }

    newChild->setParent(owner);

    if (firstChild() == beforeChild)
        setFirstChild(newChild);

    if (beforeChild) {
        RenderObject* previousSibling = beforeChild->previousSibling();
        if (previousSibling)
            previousSibling->setNextSibling(newChild);
        newChild->setPreviousSibling(previousSibling);
        newChild->setNextSibling(beforeChild);
        beforeChild->setPreviousSibling(newChild);
    } else {
        if (lastChild())
            lastChild()->setNextSibling(newChild);
        newChild->setPreviousSibling(lastChild());
        setLastChild(newChild);
    }

    if (!owner->documentBeingDestroyed() && notifyRenderer)
        newChild->insertedIntoTree();

    if (!owner->documentBeingDestroyed()) {
        RenderCounter::rendererSubtreeAttached(newChild);
    }
    
    newChild->setNeedsLayoutAndPrefWidthsRecalc();
    if (!owner->normalChildNeedsLayout())
        owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.

    if (AXObjectCache* cache = owner->document()->axObjectCache())
        cache->childrenChanged(owner);
}
static Node* pseudoAwareLastChild(const Node& node) {
  if (node.isElementNode()) {
    const Element& currentElement = toElement(node);
    Node* last = currentElement.pseudoElement(PseudoIdAfter);
    if (last)
      return last;

    last = lastChild(currentElement);
    if (!last)
      last = currentElement.pseudoElement(PseudoIdBefore);
    return last;
  }

  return lastChild(node);
}
示例#3
0
void ShadowRoot::recalcStyle(StyleRecalcChange change)
{
    // ShadowRoot doesn't support custom callbacks.
    ASSERT(!hasCustomStyleCallbacks());

    StyleResolverParentScope parentScope(*this);

    if (styleChangeType() >= SubtreeStyleChange)
        change = Force;

    if (change < Force && hasRareData() && childNeedsStyleRecalc())
        checkForChildrenAdjacentRuleChanges();

    // There's no style to update so just calling recalcStyle means we're updated.
    clearNeedsStyleRecalc();

    // FIXME: This doesn't handle :hover + div properly like Element::recalcStyle does.
    Text* lastTextNode = 0;
    for (Node* child = lastChild(); child; child = child->previousSibling()) {
        if (child->isTextNode()) {
            toText(child)->recalcTextStyle(change, lastTextNode);
            lastTextNode = toText(child);
        } else if (child->isElementNode()) {
            if (child->shouldCallRecalcStyle(change))
                toElement(child)->recalcStyle(change, lastTextNode);
            if (child->renderer())
                lastTextNode = 0;
        }
    }

    clearChildNeedsStyleRecalc();
}
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
    IntPoint pointInContainer(_x, _y);
    IntSize containerToParentOffset(_tx, _ty);

    IntPoint pointInParent = pointInContainer - containerToParentOffset;
    IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox();

    // Note: For now, we're ignoring hits to border and padding for <svg>
    IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox();
    if (!contentBoxRect().contains(pointInContentBox))
        return false;

    IntPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);

    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
            // FIXME: CSS/HTML assumes the local point is relative to the border box, right?
            updateHitTestResult(result, pointInBorderBox);
            return true;
        }
    }

    // Spec: Only graphical elements can be targeted by the mouse, so we don't check self here.
    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
    return false;
}
bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    // Give RenderSVGViewportContainer a chance to apply its viewport clip
    if (!pointIsInsideViewportClip(pointInParent))
        return false;

    FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);

    if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
        return false;
                
    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
            updateHitTestResult(result, roundedLayoutPoint(localPoint));
            return true;
        }
    }

    // Accessibility wants to return SVG containers, if appropriate.
    if (request.type() & HitTestRequest::AccessibilityHitTest && m_objectBoundingBox.contains(localPoint)) {
        updateHitTestResult(result, roundedLayoutPoint(localPoint));
        return true;
    }
    
    // Spec: Only graphical elements can be targeted by the mouse, period.
    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
    return false;
}
示例#6
0
void Element::recalcChildStyle(StyleRecalcChange change)
{
    ASSERT(document().inStyleRecalc());
    ASSERT(change >= Inherit || childNeedsStyleRecalc());
    ASSERT(!needsStyleRecalc());

    if (change > Inherit || childNeedsStyleRecalc()) {

        // This loop is deliberately backwards because we use insertBefore in the rendering tree, and want to avoid
        // a potentially n^2 loop to find the insertion point while resolving style. Having us start from the last
        // child and work our way back means in the common case, we'll find the insertion point in O(1) time.
        // See crbug.com/288225
        StyleResolver& styleResolver = document().styleResolver();
        for (Node* child = lastChild(); child; child = child->previousSibling()) {
            if (child->isTextNode()) {
                toText(child)->recalcTextStyle(change);
            } else if (child->isElementNode()) {
                Element* element = toElement(child);
                if (element->shouldCallRecalcStyle(change))
                    element->recalcStyle(change);
                else if (element->supportsStyleSharing())
                    styleResolver.addToStyleSharingList(*element);
            }
        }
    }
}
示例#7
0
bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    // Give RenderSVGViewportContainer a chance to apply its viewport clip
    if (!pointIsInsideViewportClip(pointInParent))
        return false;

    FloatPoint localPoint;
    if (!SVGRenderSupport::transformToUserSpaceAndCheckClipping(this, localToParentTransform(), pointInParent, localPoint))
        return false;

    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
            updateHitTestResult(result, roundedLayoutPoint(localPoint));
            return true;
        }
    }

    // pointer-events=boundingBox makes it possible for containers to be direct targets
    if (style()->pointerEvents() == PE_BOUNDINGBOX) {
        ASSERT(isObjectBoundingBoxValid());
        if (objectBoundingBox().contains(localPoint)) {
            updateHitTestResult(result, roundedLayoutPoint(localPoint));
            return true;
        }
    }
    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
    return false;
}
示例#8
0
void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* newChild, bool notifyRenderer)
{
    ASSERT(newChild->parent() == 0);
    ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));

    newChild->setParent(owner);
    RenderObject* lChild = lastChild();

    if (lChild) {
        newChild->setPreviousSibling(lChild);
        lChild->setNextSibling(newChild);
    } else
        setFirstChild(newChild);

    setLastChild(newChild);
    
    if (!owner->documentBeingDestroyed() && notifyRenderer)
        newChild->insertedIntoTree();

    if (!owner->documentBeingDestroyed()) {
        RenderCounter::rendererSubtreeAttached(newChild);
    }
    newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
    if (!owner->normalChildNeedsLayout())
        owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
    
    if (AXObjectCache::accessibilityEnabled())
        owner->document()->axObjectCache()->childrenChanged(owner);
}
示例#9
0
bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
    if (!viewport().isEmpty()
        && style()->overflowX() == OHIDDEN
        && style()->overflowY() == OHIDDEN) {
        int tx = _tx + m_x;
        int ty = _ty + m_y;

        // Check if we need to do anything at all.
        IntRect overflowBox = overflowRect(false);
        overflowBox.move(tx, ty);
        AffineTransform ctm = RenderContainer::absoluteTransform();
        ctm.translate(viewport().x(), viewport().y());
        double localX, localY;
        ctm.inverse().map(_x + _tx, _y + _ty, &localX, &localY);
        if (!overflowBox.contains((int)localX, (int)localY))
            return false;
    }

    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction)) {
            updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
            return true;
        }
    }
    
    // Spec: Only graphical elements can be targeted by the mouse, period.
    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
    return false;
}
示例#10
0
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const IntPoint& pointInContainer, const IntPoint& accumulatedOffset, HitTestAction hitTestAction)
{
    IntPoint pointInParent = pointInContainer - toSize(accumulatedOffset);
    IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox();

    // Note: For now, we're ignoring hits to border and padding for <svg>
    IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox();
    if (!contentBoxRect().contains(pointInContentBox))
        return false;

    IntPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);

    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
            // FIXME: CSS/HTML assumes the local point is relative to the border box, right?
            updateHitTestResult(result, pointInBorderBox);
            // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet.
            result.addNodeToRectBasedTestResult(child->node(), pointInContainer);
            return true;
        }
    }

    // If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit.
    if (hitTestAction == HitTestBlockBackground && style()->pointerEvents() != PE_NONE) {
        // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase,
        // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need
        // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able 
        // to detect these hits anymore.
        updateHitTestResult(result, roundedIntPoint(localPoint));
        return true;
    }

    return false;
}
示例#11
0
文件: node.cpp 项目: KDE/quanta
Node *Node::lastChildNE()
{
  Node *n = lastChild();
  while(n && n->tag->type == Tag::Empty)
    n = n->prev;
  return n;
}
示例#12
0
RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer)
{
    ASSERT(oldChild->parent() == owner);

    if (oldChild->isFloatingOrOutOfFlowPositioned())
        toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();

    // 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).
    if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
        // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
        if (oldChild->hasLayer())
            oldChild->repaint();
    }

    // If we have a line box wrapper, delete it.
    if (oldChild->isBox())
        toRenderBox(oldChild)->deleteLineBoxWrapper();

    // If oldChild is the start or end of the selection, then clear the selection to
    // avoid problems of invalid pointers.
    // FIXME: The FrameSelection should be responsible for this when it
    // is notified of DOM mutations.
    if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
        owner->view()->clearSelection();

    if (!owner->documentBeingDestroyed() && notifyRenderer)
        oldChild->willBeRemovedFromTree();

    // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
    // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
    // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.

    if (oldChild->previousSibling())
        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    if (oldChild->nextSibling())
        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());

    if (firstChild() == oldChild)
        setFirstChild(oldChild->nextSibling());
    if (lastChild() == oldChild)
        setLastChild(oldChild->previousSibling());

    oldChild->setPreviousSibling(0);
    oldChild->setNextSibling(0);
    oldChild->setParent(0);

    // rendererRemovedFromTree walks the whole subtree. We can improve performance
    // by skipping this step when destroying the entire tree.
    if (!owner->documentBeingDestroyed()) {
        RenderCounter::rendererRemovedFromTree(oldChild);
    }

    if (AXObjectCache::accessibilityEnabled())
        owner->document()->axObjectCache()->childrenChanged(owner);

    return oldChild;
}
示例#13
0
Frame* FrameTree::deepLastChild() const
{
    Frame* result = &m_thisFrame;
    for (Frame* last = lastChild(); last; last = last->tree().lastChild())
        result = last;

    return result;
}
示例#14
0
RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer)
{
    ASSERT(oldChild->parent() == owner);

    if (oldChild->isFloatingOrOutOfFlowPositioned())
        toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();

    // 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 (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
        if (oldChild->isBody())
            owner->view()->repaint();
        else
            oldChild->repaint();
    }

    // If we have a line box wrapper, delete it.
    if (oldChild->isBox())
        toRenderBox(oldChild)->deleteLineBoxWrapper();

    if (!owner->documentBeingDestroyed() && notifyRenderer)
        oldChild->willBeRemovedFromTree();
    
    // If oldChild is the start or end of the selection, then clear the selection to
    // avoid problems of invalid pointers.
    // FIXME: The FrameSelection should be responsible for this when it
    // is notified of DOM mutations.
    if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
        owner->view()->clearSelection();

    // remove the child
    if (oldChild->previousSibling())
        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    if (oldChild->nextSibling())
        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());

    if (firstChild() == oldChild)
        setFirstChild(oldChild->nextSibling());
    if (lastChild() == oldChild)
        setLastChild(oldChild->previousSibling());

    oldChild->setPreviousSibling(0);
    oldChild->setNextSibling(0);
    oldChild->setParent(0);

    // rendererRemovedFromTree walks the whole subtree. We can improve performance
    // by skipping this step when destroying the entire tree.
    if (!owner->documentBeingDestroyed()) {
        RenderCounter::rendererRemovedFromTree(oldChild);
    }

    if (AXObjectCache::accessibilityEnabled())
        owner->document()->axObjectCache()->childrenChanged(owner);

    return oldChild;
}
示例#15
0
void CounterNode::remove ()
{
    if (m_parent) m_parent->removeChild(this);
    else {
        Q_ASSERT(isReset());
        Q_ASSERT(!firstChild());
        Q_ASSERT(!lastChild());
    }
}
Node* FlatTreeTraversal::lastWithin(const Node& node)
{
    assertPrecondition(node);
    Node* descendant = traverseLastChild(node);
    for (Node* child = descendant; child; child = lastChild(*child))
        descendant = child;
    assertPostcondition(descendant);
    return descendant;
}
void QSequentialAnimationGroupJob::restart()
{
    // restarting the group by making the first/last animation the current one
    if (m_direction == Forward) {
        m_previousLoop = 0;
        if (m_currentAnimation == firstChild())
            activateCurrentAnimation();
        else
            setCurrentAnimation(firstChild());
    }
    else { // direction == Backward
        m_previousLoop = m_loopCount - 1;
        if (m_currentAnimation == lastChild())
            activateCurrentAnimation();
        else
            setCurrentAnimation(lastChild());
    }
}
示例#18
0
void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* newChild, bool fullAppend)
{
    ASSERT(newChild->parent() == 0);
    ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));

    newChild->setParent(owner);
    RenderObject* lChild = lastChild();

    if (lChild) {
        newChild->setPreviousSibling(lChild);
        lChild->setNextSibling(newChild);
    } else
        setFirstChild(newChild);

    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 = owner->enclosingLayer();
            newChild->addLayers(layer);
        }

        // 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 (owner->style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
            if (!layer)
                layer = owner->enclosingLayer();
            if (layer)
                layer->setHasVisibleContent(true);
        }

        if (newChild->isListItem())
            toRenderListItem(newChild)->updateListMarkerNumbers();

        if (!newChild->isFloating() && owner->childrenInline())
            owner->dirtyLinesFromChangedChild(newChild);

        if (newChild->isRenderRegion())
            toRenderRegion(newChild)->attachRegion();

        if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
            containerFlowThread->addFlowChild(newChild);
    }

    RenderCounter::rendererSubtreeAttached(newChild);
    RenderQuote::rendererSubtreeAttached(newChild);
    newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
    if (!owner->normalChildNeedsLayout())
        owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
    
    if (AXObjectCache::accessibilityEnabled())
        owner->document()->axObjectCache()->childrenChanged(owner);
}
示例#19
0
LayoutTextFragment* LayoutQuote::findFragmentChild() const
{
    // We walk from the end of the child list because, if we've had a first-letter
    // LayoutObject inserted then the remaining text will be at the end.
    while (LayoutObject* child = lastChild()) {
        if (child->isText() && toLayoutText(child)->isTextFragment())
            return toLayoutTextFragment(child);
    }

    return nullptr;
}
RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer)
{
    ASSERT(oldChild->parent() == owner);

    if (oldChild->isFloatingOrOutOfFlowPositioned())
        toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();

    {
        // FIXME: We should not be allowing paint invalidation during layout. crbug.com/336250
        AllowPaintInvalidationScope scoper(owner->frameView());

        // 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 issue paint invalidations, so that the area exposed when the child
        // disappears gets paint invalidated properly.
        if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
            oldChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
            oldChild->invalidatePaintForWholeRenderer();
        }
    }

    // If we have a line box wrapper, delete it.
    if (oldChild->isBox())
        toRenderBox(oldChild)->deleteLineBoxWrapper();

    // If oldChild is the start or end of the selection, then clear the selection to
    // avoid problems of invalid pointers.
    // FIXME: The FrameSelection should be responsible for this when it
    // is notified of DOM mutations.
    if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
        owner->view()->clearSelection();

    if (!owner->documentBeingDestroyed() && notifyRenderer)
        oldChild->willBeRemovedFromTree();

    // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
    // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
    // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.

    if (oldChild->previousSibling())
        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    if (oldChild->nextSibling())
        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());

    if (firstChild() == oldChild)
        setFirstChild(oldChild->nextSibling());
    if (lastChild() == oldChild)
        setLastChild(oldChild->previousSibling());

    oldChild->setPreviousSibling(0);
    oldChild->setNextSibling(0);
    oldChild->setParent(0);

    return oldChild;
}
示例#21
0
文件: Node.cpp 项目: jlsandell/cjango
void Node::append(Node* node)
{
    assert(!node->parent());
    assert(!node->previousSibling());
    assert(!node->nextSibling());
    node->setParent(this);

    if (!firstChild()) {
        assert(!lastChild());
        setFirstChild(node);
        setLastChild(node);
    } else {
        assert(lastChild());
        Node* lastChild = this->lastChild();
        assert(!lastChild->nextSibling());
        lastChild->setNextSibling(node);
        node->setPreviousSibling(lastChild);
        setLastChild(node);
    }
}
示例#22
0
FbTextElement FbTextElement::operator[](const QString &name)
{
    FbTextElement child = firstChild();
    while (!child.isNull()) {
        if (child.tagName().toLower() == name) return child;
        child = child.nextSibling();
    }
    QString html = QString("<%1></%1>").arg(name);
    appendInside(html);
    return lastChild();
}
void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer)
{
    ASSERT(!newChild->parent());

    while (beforeChild && beforeChild->parent() && beforeChild->parent() != owner)
        beforeChild = beforeChild->parent();

    // This should never happen, but if it does prevent render tree corruption
    // where child->parent() ends up being owner but child->nextSibling()->parent()
    // is not owner.
    if (beforeChild && beforeChild->parent() != owner) {
        ASSERT_NOT_REACHED();
        return;
    }

    newChild->setParent(owner);

    if (firstChild() == beforeChild)
        setFirstChild(newChild);

    if (beforeChild) {
        RenderObject* previousSibling = beforeChild->previousSibling();
        if (previousSibling)
            previousSibling->setNextSibling(newChild);
        newChild->setPreviousSibling(previousSibling);
        newChild->setNextSibling(beforeChild);
        beforeChild->setPreviousSibling(newChild);
    } else {
        if (lastChild())
            lastChild()->setNextSibling(newChild);
        newChild->setPreviousSibling(lastChild());
        setLastChild(newChild);
    }

    if (!owner->documentBeingDestroyed() && notifyRenderer)
        newChild->insertedIntoTree();

    newChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
    if (!owner->normalChildNeedsLayout())
        owner->setChildNeedsLayout(); // We may supply the static position for an absolute positioned child.
}
示例#24
0
Node* previous(const Node* node, const Node* stayWithin)
{
    if (node == stayWithin)
        return 0;

    if (Node* previousNode = previousSibling(node)) {
        while (Node* previousLastChild = lastChild(previousNode))
            previousNode = previousLastChild;
        return previousNode;
    }
    return parent(node);
}
bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        if (child->nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction)) {
            updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
            return true;
        }
    }

    // Spec: Only graphical elements can be targeted by the mouse, period.
    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
    return false;
}
void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
{
    // Make sure we don't append things after :after-generated content if we have it.
    if (!beforeChild && isAfterContent(lastChild()))
        beforeChild = lastChild();

    if (!newChild->isInline() && !newChild->isFloatingOrPositioned()) {
        // We are placing a block inside an inline. We have to perform a split of this
        // inline into continuations.  This involves creating an anonymous block box to hold
        // |newChild|.  We then make that block box a continuation of this inline.  We take all of
        // the children after |beforeChild| and put them in a clone of this object.
        RefPtr<RenderStyle> newStyle = RenderStyle::create();
        newStyle->inheritFrom(style());
        newStyle->setDisplay(BLOCK);

        RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
        newBox->setStyle(newStyle.release());
        RenderFlow* oldContinuation = continuation();
        setContinuation(newBox);

        // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
        // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
        // content gets properly destroyed.
        bool isLastChild = (beforeChild == lastChild());
        if (document()->usesBeforeAfterRules())
            updateBeforeAfterContent(RenderStyle::AFTER);
        if (isLastChild && beforeChild != lastChild())
            beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
                             // point to be 0.  It's just a straight append now.

        splitFlow(beforeChild, newBox, newChild, oldContinuation);
        return;
    }

    RenderContainer::addChild(newChild, beforeChild);

    newChild->setNeedsLayoutAndPrefWidthsRecalc();
}
static Node* pseudoAwarePreviousSibling(const Node& node) {
  Node* previousNode = previousSibling(node);
  Node* parentNode = parent(node);

  if (parentNode && parentNode->isElementNode() && !previousNode) {
    if (node.isAfterPseudoElement()) {
      if (Node* child = lastChild(*parentNode))
        return child;
    }
    if (!node.isBeforePseudoElement())
      return toElement(parentNode)->pseudoElement(PseudoIdBefore);
  }
  return previousNode;
}
示例#28
0
void Playlist::appendTracks( const QList<Track*> tracks )
{
    // a week attempt to speed up the setItemWidget time issue
    setUpdatesEnabled(false);
    bool doSort = isSortingEnabled();
    setSortingEnabled(false);
    hide();

    appendTracks( tracks,(PlaylistItem*)lastChild());

    setSortingEnabled(doSort);
    setUpdatesEnabled(true);
    show();
}
示例#29
0
void RenderQuote::updateText()
{
    String text = computeText();
    if (m_text == text)
        return;
    m_text = text;
    // Start from the end of the child list because, if we've had a first-letter
    // renderer inserted then the remaining text will be at the end.
    if (auto* fragment = fragmentChild(lastChild())) {
        fragment->setContentString(m_text);
        return;
    }
    addChild(new RenderTextFragment(document(), m_text));
}
void QSequentialAnimationGroupJob::rewindForwards(const AnimationIndex &newAnimationIndex)
{
    if (m_previousLoop > m_currentLoop) {
        // we need to fast rewind to the beginning
        for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->previousSibling()) {
            RETURN_IF_DELETED(setCurrentAnimation(anim, true));
            RETURN_IF_DELETED(anim->setCurrentTime(0));
        }
        // this will make sure the current animation is reset to the end
        if (lastChild() && !lastChild()->previousSibling()) {   //count == 1
            // we need to force activation because setCurrentAnimation will have no effect
            RETURN_IF_DELETED(activateCurrentAnimation());
        } else {
            RETURN_IF_DELETED(setCurrentAnimation(lastChild(), true));
        }
    }

    // and now we need to fast rewind from the current position to
    for (QAbstractAnimationJob *anim = m_currentAnimation; anim && anim != newAnimationIndex.animation; anim = anim->previousSibling()) {
        RETURN_IF_DELETED(setCurrentAnimation(anim, true));
        RETURN_IF_DELETED(anim->setCurrentTime(0));
    }
    // setting the new current animation will happen later
}