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

📄 render_line.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            if (curr->isInlineFlowBox()) {
                newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
                            curr->object()->borderBottom() + curr->object()->paddingBottom();
                newY -= curr->object()->borderTop() + curr->object()->paddingTop();
                newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
            }
        }
        else if (!curr->object()->isBR()) {
            newY += curr->object()->marginTop();
            newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
        }

        curr->setYPos(newY);
        curr->setHeight(newHeight);
        curr->setBaseline(newBaseline);

        if (childAffectsTopBottomPos) {
            if (newY < topPosition)
                topPosition = newY;
            if (newY + newHeight > bottomPosition)
                bottomPosition = newY + newHeight;
        }
    }

    if (isRootInlineBox()) {
        const QFontMetrics &fm = object()->fontMetrics( m_firstLine );
        setHeight(fm.ascent()+fm.descent());
        setYPos(yPos() + baseline() - fm.ascent());
        setBaseline(fm.ascent());
        if (hasTextChildren() || strictMode) {
            if (yPos() < topPosition)
                topPosition = yPos();
            if (yPos() + height() > bottomPosition)
                bottomPosition = yPos() + height();
        }
    }
}

void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
{
    // First shrink our kids.
    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
        if (curr->object()->isPositioned())
            continue; // Positioned placeholders don't affect calculations.

        if (curr->isInlineFlowBox())
            static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos);
    }

    // See if we have text children. If not, then we need to shrink ourselves to fit on the line.
    if (!hasTextChildren()) {
        if (yPos() < topPos)
            setYPos(topPos);
        if (yPos() + height() > bottomPos)
            setHeight(bottomPos - yPos());
        if (baseline() > height())
            setBaseline(height());
    }
}

bool InlineFlowBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
{
    // Check children first.
    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
        if (!curr->object()->layer() && curr->nodeAtPoint(i, x, y, tx, ty)) {
            object()->setInnerNode(i);
            return true;
        }
    }

    // Now check ourselves.
    QRect rect(tx + m_x, ty + m_y, m_width, m_height);
    if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
        object()->setInnerNode(i);
        return true;
    }

    return false;
}

void InlineFlowBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
{
    bool intersectsDamageRect = true;
    int xPos = tx + m_x - object()->maximalOutlineSize(i.phase);
    int w = width() + 2 * object()->maximalOutlineSize(i.phase);
    if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
        intersectsDamageRect = false;

    if (intersectsDamageRect) {
        if (i.phase == PaintActionOutline) {
            // Add ourselves to the paint info struct's list of inlines that need to paint their
            // outlines.
            if (object()->style()->visibility() == VISIBLE && object()->style()->outlineWidth() > 0 &&
                !object()->isInlineContinuation()) {
                if (!i.outlineObjects)
                    i.outlineObjects = new QPtrDict<RenderFlow>;
                if (!i.outlineObjects->find(flowObject()))
                    i.outlineObjects->insert(flowObject(), flowObject());
            }
        }
        else {
            // 1. Paint our background and border.
            paintBackgroundAndBorder(i, tx, ty);

            // 2. Paint our underline and overline.
            paintDecorations(i, tx, ty, false);
        }
    }

    // 3. Paint our children.
    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
        if (!curr->object()->layer())
            curr->paint(i, tx, ty);
    }

    // 4. Paint our strike-through
    if (intersectsDamageRect && i.phase != PaintActionOutline)
        paintDecorations(i, tx, ty, true);
}

void InlineFlowBox::paintBackgrounds(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
                                     int my, int mh, int _tx, int _ty, int w, int h)
{
    if (!bgLayer)
        return;
    paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h);
    paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h);
}

void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
                                    int my, int mh, int _tx, int _ty, int w, int h)
{
    CachedImage* bg = bgLayer->backgroundImage();
    bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) &&
                              !bg->isTransparent() && !bg->isErrorImage();
    if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent())
        object()->paintBackgroundExtended(p, c, bgLayer, my, mh, _tx, _ty, w, h, borderLeft(), borderRight());
    else {
        // We have a background image that spans multiple lines.
        // We need to adjust _tx and _ty by the width of all previous lines.
        // Think of background painting on inlines as though you had one long line, a single continuous
        // strip.  Even though that strip has been broken up across multiple lines, you still paint it
        // as though you had one single line.  This means each line has to pick up the background where
        // the previous line left off.
        int xOffsetOnLine = 0;
        for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
            xOffsetOnLine += curr->width();
        int startX = _tx - xOffsetOnLine;
        int totalWidth = xOffsetOnLine;
        for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
            totalWidth += curr->width();
        QRect clipRect(_tx, _ty, width(), height());
        clipRect = p->xForm(clipRect);
        p->save();
        p->addClip(clipRect);
        object()->paintBackgroundExtended(p, c, bgLayer, my, mh, startX, _ty,
                                          totalWidth, h, borderLeft(), borderRight());
        p->restore();
    }
}

void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty)
{
    if (!object()->shouldPaintWithinRoot(i) || object()->style()->visibility() != VISIBLE ||
        i.phase != PaintActionForeground)
        return;

    // Move x/y to our coordinates.
    _tx += m_x;
    _ty += m_y;

    int w = width();
    int h = height();

    int my = kMax(_ty, i.r.y());
    int mh;
    if (_ty < i.r.y())
        mh= kMax(0, h - (i.r.y() - _ty));
    else
        mh = kMin(i.r.height(), h);

    QPainter* p = i.p;

    // You can use p::first-line to specify a background. If so, the root line boxes for
    // a line may actually have to paint a background.
    RenderStyle* styleToUse = object()->style(m_firstLine);
    if ((!parent() && m_firstLine && styleToUse != object()->style()) ||
        (parent() && object()->shouldPaintBackgroundOrBorder())) {
        QColor c = styleToUse->backgroundColor();
        paintBackgrounds(p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h);

        // :first-line cannot be used to put borders on a line. Always paint borders with our
        // non-first-line style.
        if (parent() && object()->style()->hasBorder())
            object()->paintBorder(p, _tx, _ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge());
    }
}

static bool shouldDrawDecoration(RenderObject* obj)
{
    bool shouldDraw = false;
    for (RenderObject* curr = obj->firstChild();
         curr; curr = curr->nextSibling()) {
        if (curr->isInlineFlow()) {
            shouldDraw = true;
            break;
        }
        else if (curr->isText() && !curr->isBR() && (curr->style()->whiteSpace() == PRE ||
                 !curr->element() || !curr->element()->containsOnlyWhitespace())) {
            shouldDraw = true;
            break;
        }
    }
    return shouldDraw;
}

void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren)
{
    // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in
    // almost-strict mode or strict mode).
    if (object()->style()->htmlHacks() || !object()->shouldPaintWithinRoot(i) ||
        object()->style()->visibility() != VISIBLE)
        return;

    QPainter* p = i.p;
    _tx += m_x;
    _ty += m_y;
    RenderStyle* styleToUse = object()->style(m_firstLine);
    int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
    if (deco != TDNONE &&
        ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
        shouldDrawDecoration(object())) {
        int x = m_x + borderLeft() + paddingLeft();
        int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
        RootInlineBox* rootLine = root();
        if (rootLine->ellipsisBox()) {
            int ellipsisX = rootLine->ellipsisBox()->xPos();
            int ellipsisWidth = rootLine->ellipsisBox()->width();

            // FIXME: Will need to work with RTL
            if (rootLine == this) {
                if (x + w >= ellipsisX + ellipsisWidth)
                    w -= (x + w - ellipsisX - ellipsisWidth);
            }
            else {
                if (x >= ellipsisX)
                    return;
                if (x + w >= ellipsisX)
                    w -= (x + w - ellipsisX);
            }
        }

#if APPLE_CHANGES
        // Set up the appropriate text-shadow effect for the decoration.
        // FIXME: Support multiple shadow effects.  Need more from the CG API before we can do this.
        bool setShadow = false;
        if (styleToUse->textShadow()) {
            p->setShadow(styleToUse->textShadow()->x, styleToUse->textShadow()->y,
                         styleToUse->textShadow()->blur, styleToUse->textShadow()->color);
            setShadow = true;
        }
#endif

        // We must have child boxes and have decorations defined.
        _tx += borderLeft() + paddingLeft();

        QColor underline, overline, linethrough;
        underline = overline = linethrough = styleToUse->color();
        if (!parent())
            object()->getTextDecorationColors(deco, underline, overline, linethrough);

        if (styleToUse->font() != p->font())
            p->setFont(styleToUse->font());

        if (deco & UNDERLINE && !paintedChildren) {
            p->setPen(underline);
            p->drawLineForText(_tx, _ty, m_baseline, w);
        }
        if (deco & OVERLINE && !paintedChildren) {
            p->setPen(overline);
            p->drawLineForText(_tx, _ty, 0, w);
        }
        if (deco & LINE_THROUGH && paintedChildren) {
            p->setPen(linethrough);
            p->drawLineForText(_tx, _ty, 2*m_baseline/3, w);
        }

#if APPLE_CHANGES
        if (setShadow)
            p->clearShadow();
#endif
    }
}

InlineBox* InlineFlowBox::firstLeafChild()
{
    return firstLeafChildAfterBox();
}

InlineBox* InlineFlowBox::lastLeafChild()
{
    return lastLeafChildBeforeBox();
}

InlineBox* InlineFlowBox::firstLeafChildAfterBox(InlineBox* start)
{
    InlineBox* leaf = 0;
    for (InlineBox* box = start ? start->nextOnLine() : firstChild(); box && !leaf; box = box->nextOnLine())
        leaf = box->firstLeafChild();
    if (start && !leaf && parent())
        return parent()->firstLeafChildAfterBox(this);
    return leaf;
}

InlineBox* InlineFlowBox::lastLeafChildBeforeBox(InlineBox* start)
{
    InlineBox* leaf = 0;
    for (InlineBox* box = start ? start->prevOnLine() : lastChild(); box && !leaf; box = box->prevOnLine())
        leaf = box->lastLeafChild();
    if (start && !leaf && parent())
        return parent()->lastLeafChildBeforeBox(this);
    return leaf;
}

RenderObject::SelectionState InlineFlowBox::selectionState()
{
    return RenderObject::SelectionNone;
}

bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)

⌨️ 快捷键说明

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