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

📄 render_block.cpp

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

	BoxInfo* sel = new BoxInfo;
	sel->renderObject = this;
	sel->absoluteXPos = deltaX;
	sel->absoluteYPos = deltaY;
	sel->width = m_width;
	sel->height = m_height;
	sel->area = 0;
	boxInfoList.append(sel);

	for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
        if(!child->isFloating() && !child->layer())
			child->getRenderersInRect(boxInfoList, deltaX, deltaY,rect);
	}

    //handle floats
	if (!m_floatingObjects)
	    return;

	FloatingObject* r;
	QPtrListIterator<FloatingObject> it(*m_floatingObjects);
	for ( ; (r = it.current()); ++it) {
		int tx = deltaX + r->left - r->node->xPos() + r->node->marginLeft();
		int ty = deltaY + r->startY - r->node->yPos() + r->node->marginTop();
		r->node->getRenderersInRect(boxInfoList, tx, ty,rect);
	}

}
#endif

void RenderBlock::paint(PaintInfo& i, int _tx, int _ty)
{
    _tx += m_x;
    _ty += m_y;

    // Check if we need to do anything at all.
    if (!isInlineFlow() && !isRoot()) {
        QRect overflowBox = overflowRect(false);
        overflowBox.inflate(maximalOutlineSize(i.phase));
        overflowBox.setX(overflowBox.x() + _tx);
        overflowBox.setY(overflowBox.y() + _ty);
        bool intersectsOverflowBox = overflowBox.intersects(i.r);
        if (!intersectsOverflowBox) {
            // Check floats next.
            QRect floatBox = floatRect();
            floatBox.inflate(maximalOutlineSize(i.phase));
            floatBox.setX(floatBox.x() + _tx);
            floatBox.setY(floatBox.y() + _ty);
            if (!floatBox.intersects(i.r))
                return;
        }
    }

    return paintObject(i, _tx, _ty);
}

void RenderBlock::paintChildren(PaintInfo& i, int _tx, int _ty)
{
    // We don't paint our own background, but we do let the kids paint their backgrounds.
    PaintInfo paintInfo(i.p, i.r, i.phase == PaintActionChildBlockBackgrounds ? PaintActionChildBlockBackground : i.phase,
                        paintingRootForChildren(i));
    bool isPrinting = (i.p->device()->devType() == QInternal::Printer);

    for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
        // Check for page-break-before: always, and if it's set, break and bail.
        if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
            inRootBlockContext() && (_ty + child->yPos()) > i.r.y() &&
            (_ty + child->yPos()) < i.r.y() + i.r.height()) {
            canvas()->setBestTruncatedAt(_ty + child->yPos(), this, true);
            return;
        }

        if (!child->layer() && !child->isFloating())
            child->paint(paintInfo, _tx, _ty);

        // Check for page-break-after: always, and if it's set, break and bail.
        if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS &&
            inRootBlockContext() && (_ty + child->yPos() + child->height()) > i.r.y() &&
            (_ty + child->yPos() + child->height()) < i.r.y() + i.r.height()) {
            canvas()->setBestTruncatedAt(_ty + child->yPos() + child->height() + child->collapsedMarginBottom(), this, true);
            return;
        }
    }
}

void RenderBlock::paintCaret(PaintInfo& i, CaretType type)
{
    const Selection &s = type == CursorCaret ? document()->part()->selection() : document()->part()->dragCaret();
    NodeImpl *caretNode = s.start().node();
    RenderObject *renderer = caretNode ? caretNode->renderer() : 0;
    if (renderer && (renderer == this || renderer->containingBlock() == this) && caretNode && caretNode->isContentEditable()) {
        if (type == CursorCaret) {
            document()->part()->paintCaret(i.p, i.r);
        } else {
            document()->part()->paintDragCaret(i.p, i.r);
        }
    }
}

void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
{
    PaintAction paintAction = i.phase;

    // If we're a repositioned run-in or a compact, don't paint background/borders.
    bool inlineFlow = isInlineFlow();

    // 1. paint background, borders etc
    if (!inlineFlow &&
        (paintAction == PaintActionBlockBackground || paintAction == PaintActionChildBlockBackground) &&
        shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE) {
        paintBoxDecorations(i, _tx, _ty);
    }

    // We're done.  We don't bother painting any children.
    if (paintAction == PaintActionBlockBackground)
        return;

    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
    int scrolledX = _tx;
    int scrolledY = _ty;
    if (hasOverflowClip())
        m_layer->subtractScrollOffset(scrolledX, scrolledY);

    // 2. paint contents
    if (childrenInline())
        paintLines(i, scrolledX, scrolledY);
    else
        paintChildren(i, scrolledX, scrolledY);

    // 3. paint selection
    if (!inlineFlow)
        paintSelection(i, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.

    // 4. paint floats.
    if (!inlineFlow && (paintAction == PaintActionFloat || paintAction == PaintActionSelection))
        paintFloats(i, scrolledX, scrolledY, paintAction == PaintActionSelection);

    // 5. paint outline.
    if (!inlineFlow && paintAction == PaintActionOutline &&
        style()->outlineWidth() && style()->visibility() == VISIBLE)
        paintOutline(i.p, _tx, _ty, width(), height(), style());

    // 6. paint caret.
    // If the caret's node's render object's containing block is this block, and the paint action is PaintActionForeground,
    // then paint the caret.
    if (!inlineFlow && paintAction == PaintActionForeground) {
        paintCaret(i, CursorCaret);
        paintCaret(i, DragCaret);
    }

#ifdef BOX_DEBUG
    if ( style() && style()->visibility() == VISIBLE ) {
        if(isAnonymous())
            outlineBox(i.p, _tx, _ty, "green");
        if(isFloating())
            outlineBox(i.p, _tx, _ty, "yellow");
        else
            outlineBox(i.p, _tx, _ty);
    }
#endif
}

void RenderBlock::paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection)
{
    if (!m_floatingObjects)
        return;

    FloatingObject* r;
    QPtrListIterator<FloatingObject> it(*m_floatingObjects);
    for ( ; (r = it.current()); ++it) {
        // Only paint the object if our noPaint flag isn't set.
        if (!r->noPaint && !r->node->layer()) {
            PaintInfo info(i.p, i.r, paintSelection ? PaintActionSelection : PaintActionBlockBackground, i.paintingRoot);
            int tx = _tx + r->left - r->node->xPos() + r->node->marginLeft();
            int ty = _ty + r->startY - r->node->yPos() + r->node->marginTop();
            r->node->paint(info, tx, ty);
            if (!paintSelection) {
                info.phase = PaintActionChildBlockBackgrounds;
                r->node->paint(info, tx, ty);
                info.phase = PaintActionFloat;
                r->node->paint(info, tx, ty);
                info.phase = PaintActionForeground;
                r->node->paint(info, tx, ty);
                info.phase = PaintActionOutline;
                r->node->paint(info, tx, ty);
            }
        }
    }
}

void RenderBlock::paintEllipsisBoxes(PaintInfo& i, int _tx, int _ty)
{
    if (!shouldPaintWithinRoot(i) || !firstLineBox())
        return;

    if (style()->visibility() == VISIBLE && i.phase == PaintActionForeground) {
        // We can check the first box and last box and avoid painting if we don't
        // intersect.
        int yPos = _ty + firstLineBox()->yPos();;
        int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
        if( (yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
            return;

        // See if our boxes intersect with the dirty rect.  If so, then we paint
        // them.  Note that boxes can easily overlap, so we can't make any assumptions
        // based off positions of our first line box or our last line box.
        for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
            yPos = _ty + curr->yPos();
            h = curr->height();
            if (curr->ellipsisBox() && (yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
                curr->paintEllipsisBox(i, _tx, _ty);
        }
    }
}

void RenderBlock::setSelectionState(SelectionState s)
{
    if (m_selectionState == s)
        return;

    if (s == SelectionInside && m_selectionState != SelectionNone)
        return;

    if ((s == SelectionStart && m_selectionState == SelectionEnd) ||
        (s == SelectionEnd && m_selectionState == SelectionStart))
        m_selectionState = SelectionBoth;
    else
        m_selectionState = s;

    RenderBlock* cb = containingBlock();
    if (cb && !cb->isCanvas())
        cb->setSelectionState(s);
}

bool RenderBlock::shouldPaintSelectionGaps() const
{
    return m_selectionState != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
}

bool RenderBlock::isSelectionRoot() const
{
    // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
    return (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
            isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable());
}

GapRects RenderBlock::selectionGapRects()
{
    if (!shouldPaintSelectionGaps())
        return GapRects();

    int tx, ty;
    absolutePosition(tx, ty);

    int lastTop = -borderTopExtra();
    int lastLeft = leftSelectionOffset(this, lastTop);
    int lastRight = rightSelectionOffset(this, lastTop);

    return fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight);
}

void RenderBlock::paintSelection(PaintInfo& i, int tx, int ty)
{
    if (shouldPaintSelectionGaps() && i.phase == PaintActionForeground) {
        int lastTop = -borderTopExtra();
        int lastLeft = leftSelectionOffset(this, lastTop);
        int lastRight = rightSelectionOffset(this, lastTop);
        fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &i);
    }
}

GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, int& lastTop, int& lastLeft, int& lastRight,
                                        const PaintInfo* i)
{
    // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
    // fixed).
    GapRects result;
    if (!isBlockFlow())
        return result;

    if (childrenInline())
        result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);
    else
        result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);

    // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
    if (rootBlock == this && (m_selectionState != SelectionBoth && m_selectionState != SelectionEnd))
        result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height() + borderBottomExtra(),
                                                    rootBlock, blockX, blockY, i));
    return result;
}

GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
                                              int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* i)
{
    GapRects result;

    RenderObject* selStart = canvas()->selectionStart();
    // If there is no selection, don't try to get the selection's containing block.
    // If we do, we'll crash.
    bool containsStart = (selStart && (selStart == this || selStart->containingBlock() == this));

    if (!firstLineBox()) {
     

⌨️ 快捷键说明

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