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

📄 render_object.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
{
    RenderObject* o = parent();
    if (o) {
        o->absolutePosition(xPos, yPos, f);
        if (o->hasOverflowClip())
            o->layer()->subtractScrollOffset(xPos, yPos);
        return true;
    }
    else
    {
        xPos = yPos = 0;
        return false;
    }
}

QRect RenderObject::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
{
   if (extraWidthToEndOfLine)
       *extraWidthToEndOfLine = 0;

    return QRect();
}

int RenderObject::paddingTop() const
{
    int w = 0;
    Length padding = m_style->paddingTop();
    if (padding.isPercent())
        w = containingBlock()->contentWidth();
    w = padding.minWidth(w);
    if ( isTableCell() && padding.isVariable() )
	w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    return w;
}

int RenderObject::paddingBottom() const
{
    int w = 0;
    Length padding = style()->paddingBottom();
    if (padding.isPercent())
        w = containingBlock()->contentWidth();
    w = padding.minWidth(w);
    if ( isTableCell() && padding.isVariable() )
	w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    return w;
}

int RenderObject::paddingLeft() const
{
    int w = 0;
    Length padding = style()->paddingLeft();
    if (padding.isPercent())
        w = containingBlock()->contentWidth();
    w = padding.minWidth(w);
    if ( isTableCell() && padding.isVariable() )
	w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    return w;
}

int RenderObject::paddingRight() const
{
    int w = 0;
    Length padding = style()->paddingRight();
    if (padding.isPercent())
        w = containingBlock()->contentWidth();
    w = padding.minWidth(w);
    if ( isTableCell() && padding.isVariable() )
	w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    return w;
}

RenderCanvas* RenderObject::canvas() const
{
    return static_cast<RenderCanvas*>(document()->renderer());
}

RenderObject *RenderObject::container() const
{
    // This method is extremely similar to containingBlock(), but with a few notable
    // exceptions.
    // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
    // the object is not part of the primary document subtree yet.
    // (2) For normal flow elements, it just returns the parent.
    // (3) For absolute positioned elements, it will return a relative positioned inline.
    // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
    // the layout of the positioned object.  This does mean that calcAbsoluteHorizontal and
    // calcAbsoluteVertical have to use container().
    EPosition pos = m_style->position();
    RenderObject *o = 0;
    if (!isText() && pos == FIXED) {
        // container() can be called on an object that is not in the
        // tree yet.  We don't call canvas() since it will assert if it
        // can't get back to the canvas.  Instead we just walk as high up
        // as we can.  If we're in the tree, we'll get the root.  If we
        // aren't we'll get the root of our little subtree (most likely
        // we'll just return 0).
        o = parent();
        while (o && o->parent()) o = o->parent();
    }
    else if (!isText() && pos == ABSOLUTE) {
        // Same goes here.  We technically just want our containing block, but
        // we may not have one if we're part of an uninstalled subtree.  We'll
        // climb as high as we can though.
        o = parent();
        while (o && o->style()->position() == STATIC && !o->isRoot() && !o->isCanvas())
            o = o->parent();
    }
    else
	o = parent();
    return o;
}

bool RenderObject::isSelectionBorder() const
{
    SelectionState st = selectionState();
    return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
}

#if 0
static void checkFloats(RenderObject* o, RenderObject* f)
{
    if (o->isRenderBlock()) {
        RenderBlock* b = static_cast<RenderBlock*>(o);
        if (b->containsFloat(f))
            assert(false);
    }

    for (RenderObject* c = o->firstChild(); c; c = c->nextSibling())
        checkFloats(c, f);
}
#endif

void RenderObject::removeFromObjectLists()
{
    if (isFloating()) {
        RenderBlock* outermostBlock = containingBlock();
        for (RenderBlock* p = outermostBlock; p && !p->isCanvas(); p = p->containingBlock()) {
            if (p->containsFloat(this))
                outermostBlock = p;
        }

        if (outermostBlock)
            outermostBlock->markAllDescendantsWithFloatsForLayout(this);
#if 0
        // Debugging code for float checking.
        checkFloats(canvas(), this);
#endif
    }

    if (isPositioned()) {
        RenderObject *p;
        for (p = parent(); p; p = p->parent()) {
            if (p->isRenderBlock())
                static_cast<RenderBlock*>(p)->removePositionedObject(this);
        }
    }
}

RenderArena* RenderObject::renderArena() const
{
    DOM::DocumentImpl* doc = document();
    return doc ? doc->renderArena() : 0;
}

void RenderObject::remove()
{
#if APPLE_CHANGES
    // Delete our accessibility object if we have one.
    document()->getAccObjectCache()->detach(this);
#endif

    removeFromObjectLists();

    if (parent())
        //have parent, take care of the tree integrity
        parent()->removeChild(this);
}

void RenderObject::detach()
{
    remove();

    // by default no refcounting
    arenaDelete(document()->renderArena(), this);
}

#if NOKIA_CHANGES
void RenderObject::arenaDelete(RenderArena *arena, void *)
{
    if (m_style->backgroundImage())
        m_style->backgroundImage()->deref(this);
    if (m_style)
        m_style->deref(arena);

    void *savedBase = baseOfRenderObjectBeingDeleted;
    delete this;

    void* base = baseOfRenderObjectBeingDeleted;
    // Recover the size left there for us by operator delete and free the memory.
    arena->free(*(size_t *)base, base);

    baseOfRenderObjectBeingDeleted = savedBase;
}
#else
void RenderObject::arenaDelete(RenderArena *arena, void *base)
{
    if (m_style->backgroundImage())
        m_style->backgroundImage()->deref(this);
    if (m_style)
        m_style->deref(arena);

#ifndef NDEBUG
    void *savedBase = baseOfRenderObjectBeingDeleted;
    baseOfRenderObjectBeingDeleted = base;
#endif
    delete this;
#ifndef NDEBUG
    baseOfRenderObjectBeingDeleted = savedBase;
#endif

    // Recover the size left there for us by operator delete and free the memory.
    arena->free(*(size_t *)base, base);
}
#endif

VisiblePosition RenderObject::positionForCoordinates(int x, int y)
{
    return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
}

bool RenderObject::mouseInside() const
{
    if (!m_mouseInside && continuation())
        return continuation()->mouseInside();
    return m_mouseInside;
}

bool RenderObject::isDragging() const
{
    return m_isDragging;
}

void RenderObject::updateDragState(bool dragOn)
{
    bool valueChanged = (dragOn != m_isDragging);
    m_isDragging = dragOn;
    if (valueChanged && style()->affectedByDragRules())
        element()->setChanged();
    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
        curr->updateDragState(dragOn);
    if (continuation())
        continuation()->updateDragState(dragOn);
}

bool RenderObject::hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
{
    bool inside = false;
    if (hitTestFilter != HitTestSelf) {
        // First test the foreground layer (lines and inlines).
        inside = nodeAtPoint(info, x, y, tx, ty, HitTestForeground);

        // Test floats next.
        if (!inside)
            inside = nodeAtPoint(info, x, y, tx, ty, HitTestFloat);

        // Finally test to see if the mouse is in the background (within a child block's background).
        if (!inside)
            inside = nodeAtPoint(info, x, y, tx, ty, HitTestChildBlockBackgrounds);
    }

    // See if the mouse is inside us but not any of our descendants
    if (hitTestFilter != HitTestDescendants && !inside)
        inside = nodeAtPoint(info, x, y, tx, ty, HitTestBlockBackground);

    return inside;
}

void RenderObject::setInnerNode(NodeInfo& info)
{
    if (!info.innerNode() && !isInline() && continuation()) {
        // We are in the margins of block elements that are part of a continuation.  In
        // this case we're actually still inside the enclosing inline element that was
        // split.  Go ahead and set our inner node accordingly.
        info.setInnerNode(continuation()->element());
        if (!info.innerNonSharedNode())
            info.setInnerNonSharedNode(continuation()->element());
    }

    if (!info.innerNode() && element())
        info.setInnerNode(element());

    if(!info.innerNonSharedNode() && element())
        info.setInnerNonSharedNode(element());
}

bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
                               HitTestAction hitTestAction)
{
    return false;
}

short RenderObject::verticalPositionHint( bool firstLine ) const
{
    short vpos = m_verticalPosition;
    if ( m_verticalPosition == PositionUndefined || firstLine ) {
	vpos = getVerticalPosition( firstLine );
	if ( !firstLine )
	    m_verticalPosition = vpos;
    }
    return vpos;

}

short RenderObject::getVerticalPosition( bool firstLine ) const
{
    if (!isInline())
        return 0;

    // This method determines the vertical position for inline elements.
    int vpos = 0;
    EVerticalAlign va = style()->verticalAlign();
    if ( va == TOP ) {
        vpos = PositionTop;
    } else if ( va == BOTTOM ) {
        vpos = PositionBottom;
    } else if ( va == LENGTH ) {
        vpos = -style()->verticalAlignLength().width( lineHeight( firstLine ) );
    } else  {
        bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
        vpos = checkParent ? parent()->verticalPositionHint( firstLine ) : 0;
        // don't allow elements nested inside text-top to have a different valignment.
        if ( va == BASELINE )
            return vpos;

        const QFont &f = parent()->font( firstLine );
        int fontsize = f.pixelSize();

        if (va == SUB)
            vpos += fontsize/5 + 1;
        else if (va == SUPER)
            vpos -= fontsize/3 + 1;
        else if (va == TEXT_TOP)
            vpos += baselinePosition( firstLine ) - QFontMetrics(f).ascent();
        else if (va == MIDDLE)
            vpos += - (int)(QFontMetrics(f).xHeight()/2) - lineHeight( firstLine )/2 + baselinePosition( firstLine );
        else if (va == TEXT_BOTTOM) {
            vpos += QFontMetrics(f).descent();
            if (!isReplaced())
                vpos -= fontMetrics(firstLine).descent();
        } else if ( va == BASELINE_MIDDLE )
            vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
    }

    return vpos;
}

short RenderObject::lineHeight( bool firstLine, bool ) const
{
    RenderStyle* s = style(firstLine);

    Length lh = s->lineHeight();
#ifdef NOKIA_CHANGES
    lh.value = lh.value * 100 / canvas()->view()->scalingFactor();
#endif
    // its "unset", choose nice default
    if (lh.value < 0)
        return s->fontMetrics().lineSpacing();

    if (lh.isPercent())
        return lh.minWidth(s->font().pixelSize());

    // its fixed
    return lh.value;
}

short RenderObject::baselinePosition( bool firstLine, bool isRootLineBox ) const
{
    const QFontMetrics &fm = fontMetrics( firstLine );
    return fm.ascent() + ( lineHeight( firstLine, isRootLineBox ) - fm.height() ) / 2;
}

void RenderObject::invalidateVerticalPositions()
{
    m_verticalPosition = PositionUndefined;
    RenderObject *child = firstChild();
    while( child ) {
	child->invalidateVerticalPositions();
	child = child->nextSibling();
    }
}

void RenderObject::recalcMinMaxWidths()
{
    KHTMLAssert( m_recalcMinMax );

#ifdef DEBUG_LAYOUT
    kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
#endif

    if (m_recalcMinMax)
        updateFirstLetter();

    RenderObject *child = firstChild();
    while( child ) {
        // gcc sucks. if anybody knows a trick to get rid of the
        // warning without adding an extra (unneeded) initialisation,
        // go ahead
	int cmin = 0;
	int cmax = 0;
	bool test = false;
	if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
	    cmin = child->m

⌨️ 快捷键说明

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