⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_object.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    return !document()->view()->needsFullRepaint() && !layer();
}

void RenderObject::repaintObjectsBeforeLayout()
{
    if (!needsLayout() || isText())
        return;

    bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
    if (selfNeedsLayout()) {
        repaint();
        if (blockWithInlineChildren)
            return;
    }

    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
        if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
            current->repaintObjectsBeforeLayout();
    }
}

QRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
{
    QRect r(getAbsoluteRepaintRect());
    r.setRect(r.x()-ow, r.y()-ow, r.width()+ow*2, r.height()+ow*2);

    if (continuation() && !isInline())
        r.setRect(r.x(), r.y()-collapsedMarginTop(), r.width(), r.height()+collapsedMarginTop()+collapsedMarginBottom());

    if (isInlineFlow()) {
        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
            if (!curr->isText()) {
                QRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
                r = r.unite(childRect);
            }
        }
    }

    return r;
}

QRect RenderObject::getAbsoluteRepaintRect()
{
    if (parent())
        return parent()->getAbsoluteRepaintRect();
    return QRect();
}

void RenderObject::getAbsoluteRepaintRectIncludingFloats(QRect& bounds, QRect& fullBounds)
{
    bounds = fullBounds = getAbsoluteRepaintRect();
}

void RenderObject::computeAbsoluteRepaintRect(QRect& r, bool f)
{
    if (parent())
        return parent()->computeAbsoluteRepaintRect(r, f);
}

void RenderObject::dirtyLinesFromChangedChild(RenderObject* child, bool adding)
{
}

#ifndef NDEBUG

QString RenderObject::information() const
{
    QString str;
    QTextStream ts( &str, IO_WriteOnly );
    ts << renderName()
	<< "(" << (style() ? style()->refCount() : 0) << ")"
       << ": " << (void*)this << "  ";
    if (isInline()) ts << "il ";
    if (childrenInline()) ts << "ci ";
    if (isFloating()) ts << "fl ";
    if (isAnonymous()) ts << "an ";
    if (isRelPositioned()) ts << "rp ";
    if (isPositioned()) ts << "ps ";
    if (needsLayout()) ts << "nl ";
    if (m_recalcMinMax) ts << "rmm ";
    if (mouseInside()) ts << "mi ";
    if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
    if (element() && element()->active()) ts << "act ";
    if (element() && element()->hasAnchor()) ts << "anchor ";
    if (element() && element()->focused()) ts << "focus ";
    if (element()) ts << " <" <<  getTagName(element()->id()).string() << ">";
    ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
	<< (isTableCell() ?
	    ( QString::fromLatin1(" [r=") +
	      QString::number( static_cast<const RenderTableCell *>(this)->row() ) +
	      QString::fromLatin1(" c=") +
	      QString::number( static_cast<const RenderTableCell *>(this)->col() ) +
	      QString::fromLatin1(" rs=") +
	      QString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
	      QString::fromLatin1(" cs=") +
	      QString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
	      QString::fromLatin1("]") ) : QString::null );
	return str;
}

void RenderObject::printTree(int indent) const
{
    QString ind;
    ind.fill(' ', indent);

    kdDebug() << ind << information() << endl;

    RenderObject *child = firstChild();
    while( child != 0 )
    {
        child->printTree(indent+2);
        child = child->nextSibling();
    }
}

void RenderObject::dump(QTextStream *stream, QString ind) const
{
    if (isAnonymous()) { *stream << " anonymous"; }
    if (isFloating()) { *stream << " floating"; }
    if (isPositioned()) { *stream << " positioned"; }
    if (isRelPositioned()) { *stream << " relPositioned"; }
    if (isText()) { *stream << " text"; }
    if (isInline()) { *stream << " inline"; }
    if (isReplaced()) { *stream << " replaced"; }
    if (shouldPaintBackgroundOrBorder()) { *stream << " paintBackground"; }
    if (needsLayout()) { *stream << " needsLayout"; }
    if (minMaxKnown()) { *stream << " minMaxKnown"; }
    *stream << endl;

    RenderObject *child = firstChild();
    while( child != 0 )
    {
	*stream << ind << child->renderName() << ": ";
	child->dump(stream,ind+"  ");
	child = child->nextSibling();
    }
}
#endif

static NodeImpl *selectStartNode(const RenderObject *object)
{
    DOM::NodeImpl *node = 0;
    bool forcedOn = false;

    for (const RenderObject *curr = object; curr; curr = curr->parent()) {
        if (curr->style()->userSelect() == SELECT_TEXT)
	    forcedOn = true;
        if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
            return 0;

	if (!node)
	    node = curr->element();
    }

    // somewhere up the render tree there must be an element!
    assert(node);

    return node;
}

bool RenderObject::canSelect() const
{
    return selectStartNode(this) != 0;
}

bool RenderObject::shouldSelect() const
{
    NodeImpl *node = selectStartNode(this);
    if (!node)
        return false;
    return node->dispatchHTMLEvent(DOM::EventImpl::SELECTSTART_EVENT, true, true);
}

QColor RenderObject::selectionColor(QPainter *p) const
{
    QColor color;
    if (style()->userSelect() != SELECT_NONE) {
        RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
        if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
            color = pseudoStyle->backgroundColor();
        else
            color = p->selectedTextBackgroundColor();
    }

    return color;
}

DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
{
    if (!dhtmlOK && !uaOK)
        return 0;

    const RenderObject* curr = this;
    while (curr) {
        DOM::NodeImpl *elt = curr->element();
        if (elt && elt->nodeType() == Node::TEXT_NODE) {
            // Since there's no way for the author to address the -khtml-user-drag style for a text node,
            // we use our own judgement.
            if (uaOK && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y)) {
                dhtmlWillDrag = false;
                return curr->node();
            } else if (curr->shouldSelect()) {
                // In this case we have a click in the unselected portion of text.  If this text is
                // selectable, we want to start the selection process instead of looking for a parent
                // to try to drag.
                return 0;
            }
        } else {
            EUserDrag dragMode = curr->style()->userDrag();
            if (dhtmlOK && dragMode == DRAG_ELEMENT) {
                dhtmlWillDrag = true;
                return curr->node();
            } else if (uaOK && dragMode == DRAG_AUTO
                       && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y))
            {
                dhtmlWillDrag = false;
                return curr->node();
            }
        }
        curr = curr->parent();
    }
    return 0;
}

void RenderObject::selectionStartEnd(int& spos, int& epos)
{
    canvas()->selectionStartEnd(spos, epos);
}

RenderBlock* RenderObject::createAnonymousBlock()
{
    RenderStyle *newStyle = new (renderArena()) RenderStyle();
    newStyle->inheritFrom(m_style);
    newStyle->setDisplay(BLOCK);

    RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
    newBox->setStyle(newStyle);
    return newBox;
}

void RenderObject::handleDynamicFloatPositionChange()
{
    // We have gone from not affecting the inline status of the parent flow to suddenly
    // having an impact.  See if there is a mismatch between the parent flow's
    // childrenInline() state and our state.
    setInline(style()->isDisplayInlineType());
    if (isInline() != parent()->childrenInline()) {
        if (!isInline()) {
            if (parent()->isRenderInline()) {
                // We have to split the parent flow.
                RenderInline* parentInline = static_cast<RenderInline*>(parent());
                RenderBlock* newBox = parentInline->createAnonymousBlock();

                RenderFlow* oldContinuation = parent()->continuation();
                parentInline->setContinuation(newBox);

                RenderObject* beforeChild = nextSibling();
                parent()->removeChildNode(this);
                parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
            }
            else if (parent()->isRenderBlock())
                static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
        }
        else {
            // An anonymous block must be made to wrap this inline.
            RenderBlock* box = createAnonymousBlock();
            parent()->insertChildNode(box, this);
            box->appendChildNode(parent()->removeChildNode(this));
        }
    }
}

void RenderObject::setStyle(RenderStyle *style)
{
    if (m_style == style)
        return;

    bool affectsParentBlock = false;
    RenderStyle::Diff d = RenderStyle::Equal;
    if (m_style) {
        // If our z-index changes value or our visibility changes,
        // we need to dirty our stacking context's z-order list.
        if (style) {
#if APPLE_CHANGES
            if (m_style->visibility() != style->visibility() ||
                m_style->zIndex() != style->zIndex() ||
                m_style->hasAutoZIndex() != style->hasAutoZIndex())
                document()->setDashboardRegionsDirty(true);
#endif

            if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
                 m_style->zIndex() != style->zIndex() ||
                 m_style->visibility() != style->visibility()) && layer()) {
                layer()->stackingContext()->dirtyZOrderLists();
                if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
                    m_style->visibility() != style->visibility())
                    layer()->dirtyZOrderLists();
            }
        }

        d = m_style->diff(style);

        // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
        if (d == RenderStyle::RepaintLayer && !layer())
            d = RenderStyle::Repaint;

        // The background of the root element or the body element could propagate up to
        // the canvas.  Just dirty the entire canvas when our style changes substantially.
        if (d >= RenderStyle::Repaint && element() &&
            (element()->id() == ID_HTML || element()->id() == ID_BODY))
            canvas()->repaint();
        else if (m_parent && !isText()) {
            // Do a repaint with the old style first, e.g., for example if we go from
            // having an outline to not having an outline.
            if (d == RenderStyle::RepaintLayer) {
                layer()->repaintIncludingDescendants();
                if (!(m_style->clip() == style->clip()))
                    layer()->clearClipRects();
            }
            else if (d == RenderStyle::Repaint)
                repaint();
        }

        // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
        // end up being destroyed.
        if (d == RenderStyle::Layout && layer() &&
            (m_style->position() != style->position() ||
             m_style->zIndex() != style->zIndex() ||
             m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
             !(m_style->clip() == style->clip()) ||
             m_style->hasClip() != style->hasClip() ||
             m_style->opacity() != style->opacity()))
            layer()->repaintIncludingDescendants();

        // When a layout hint happens and an object's position style changes, we have to do a layout
        // to dirty the render tree using the old position value now.
        if (d == RenderStyle::Layout && m_parent && m_style->position() != style->position())
            setNeedsLayoutAndMinMaxRecalc();

        if (isFloating() && (m_style->floating() != style->floating()))
            // For changes in float styles, we need to conceivably remove ourselves
            // from the floating objects list.
            removeFromObjectLists();
        else if (isPositioned() && (style->position() != ABSOLUTE && style->position() != FIXED))
            // For changes in positioning styles, we need to conceivably remove ourselves
            // from the positioned objects list.
            removeFromObjectLists();

        affectsParentBlock = m_style && isFloatingOrPositioned() &&
            (!style->isFloating() && style->position() != ABSOLUTE && style->position() != FIXED)
            && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());

        // reset style flags
        m_floating = false;
        m_positioned = false;
        m_relPositioned = false;
        m_paintBackground = false;
        m_hasOverflowClip = false;
    }

    RenderStyle *oldStyle = m_style;
    m_style = style;

    updateBackgroundImages(oldStyle);

    if (m_style)
        m_style->ref();

    if (oldStyle)
        oldStyle->deref(renderArena());

    setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground());

    if (affectsParentBlock)
        handleDynamicFloatPositionChange();

    // No need to ever schedule repaints from a style change of a text run, since
    // we already did this for the parent of the text run.
    if (d == RenderStyle::Layout && m_parent)
        setNeedsLayoutAndMinMaxRecalc();
    else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
        // Do a repaint with the new style now, e.g., for example if we go from
        // not having an outline to having an outline.
        repaint();
}

void RenderObject::setStyleInternal(RenderStyle* st)
{
    if (m_style == st)
        return;
    if (m_style)
        m_style->deref(renderArena());
    m_style = st;
    if (m_style)
        m_style->ref();
}

void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
{
    // FIXME: This will be slow when a large number of images is used.  Fix by using a dict.
    const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
    const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
    for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
        if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
            currOld->backgroundImage()->deref(this);
    }
    for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
        if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
            currNew->backgroundImage()->ref(this);
    }
}

QRect RenderObject::viewRect() const
{
    return canvas()->viewRect();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -