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

📄 inlineflowbox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{    int maxPositionTop = 0;    int maxPositionBottom = 0;    int maxAscent = 0;    int maxDescent = 0;    // Figure out if we're in strict mode.  Note that we can't simply use !style()->htmlHacks(),    // because that would match almost strict mode as well.    RenderObject* curr = renderer();    while (curr && !curr->node())        curr = curr->container();    bool strictMode = (curr && curr->document()->inStrictMode());        computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);    if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom))        adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);    int maxHeight = maxAscent + maxDescent;    int topPosition = heightOfBlock;    int bottomPosition = heightOfBlock;    int selectionTop = heightOfBlock;    int selectionBottom = heightOfBlock;    placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);    setVerticalOverflowPositions(topPosition, bottomPosition);    setVerticalSelectionPositions(selectionTop, selectionBottom);        heightOfBlock += maxHeight;        return heightOfBlock;}void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,                                              int maxPositionTop, int maxPositionBottom){    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        // The computed lineheight needs to be extended for the        // positioned elements        if (curr->renderer()->isPositioned())            continue; // Positioned placeholders don't affect calculations.        if (curr->y() == PositionTop || curr->y() == PositionBottom) {            int lineHeight = curr->renderer()->lineHeight(m_firstLine);            if (curr->y() == PositionTop) {                if (maxAscent + maxDescent < lineHeight)                    maxDescent = lineHeight - maxAscent;            }            else {                if (maxAscent + maxDescent < lineHeight)                    maxAscent = lineHeight - maxDescent;            }            if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))                break;        }        if (curr->isInlineFlowBox())            static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);    }}static int verticalPositionForBox(InlineBox* curr, bool firstLine){    if (curr->renderer()->isText())        return curr->parent()->y();    if (curr->renderer()->isBox())        return toRenderBox(curr->renderer())->verticalPosition(firstLine);    return toRenderInline(curr->renderer())->verticalPositionFromCache(firstLine);}void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,                                             int& maxAscent, int& maxDescent, bool strictMode){    if (isRootInlineBox()) {        // Examine our root box.        int lineHeight = renderer()->lineHeight(m_firstLine, true);        int baseline = renderer()->baselinePosition(m_firstLine, true);        if (hasTextChildren() || strictMode) {            int ascent = baseline;            int descent = lineHeight - ascent;            if (maxAscent < ascent)                maxAscent = ascent;            if (maxDescent < descent)                maxDescent = descent;        }    }        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->renderer()->isPositioned())            continue; // Positioned placeholders don't affect calculations.                bool isInlineFlow = curr->isInlineFlowBox();        int lineHeight = curr->renderer()->lineHeight(m_firstLine);        int baseline = curr->renderer()->baselinePosition(m_firstLine);        curr->setY(verticalPositionForBox(curr, m_firstLine));        if (curr->y() == PositionTop) {            if (maxPositionTop < lineHeight)                maxPositionTop = lineHeight;        }        else if (curr->y() == PositionBottom) {            if (maxPositionBottom < lineHeight)                maxPositionBottom = lineHeight;        }        else if ((!isInlineFlow || static_cast<InlineFlowBox*>(curr)->hasTextChildren()) || curr->boxModelObject()->hasHorizontalBordersOrPadding() || strictMode) {            int ascent = baseline - curr->y();            int descent = lineHeight - ascent;            if (maxAscent < ascent)                maxAscent = ascent;            if (maxDescent < descent)                maxDescent = descent;        }        if (curr->isInlineFlowBox())            static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);    }}void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode,                                         int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom){    if (isRootInlineBox())        setY(yPos + max(0, maxAscent - renderer()->baselinePosition(m_firstLine, true))); // Place our root box.        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->renderer()->isPositioned())            continue; // Positioned placeholders don't affect calculations.                // Adjust boxes to use their real box y/height and not the logical height (as dictated by        // line-height).        bool isInlineFlow = curr->isInlineFlowBox();        if (isInlineFlow)            static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);        bool childAffectsTopBottomPos = true;        if (curr->y() == PositionTop)            curr->setY(yPos);        else if (curr->y() == PositionBottom)            curr->setY(yPos + maxHeight - curr->renderer()->lineHeight(m_firstLine));        else {            if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode)                childAffectsTopBottomPos = false;            int posAdjust = maxAscent - curr->renderer()->baselinePosition(m_firstLine);            if (!childAffectsTopBottomPos)                posAdjust = max(0, posAdjust);            curr->setY(curr->y() + yPos + posAdjust);        }                int newY = curr->y();        int overflowTop = 0;        int overflowBottom = 0;        if (curr->isText() || curr->isInlineFlowBox()) {            const Font& font = curr->renderer()->style(m_firstLine)->font();            newY += curr->renderer()->baselinePosition(m_firstLine) - font.ascent();            for (ShadowData* shadow = curr->renderer()->style()->textShadow(); shadow; shadow = shadow->next) {                overflowTop = min(overflowTop, shadow->y - shadow->blur);                overflowBottom = max(overflowBottom, shadow->y + shadow->blur);            }            for (ShadowData* boxShadow = curr->renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {                overflowTop = min(overflowTop, boxShadow->y - boxShadow->blur);                overflowBottom = max(overflowBottom, boxShadow->y + boxShadow->blur);            }            for (ShadowData* textShadow = curr->renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {                overflowTop = min(overflowTop, textShadow->y - textShadow->blur);                overflowBottom = max(overflowBottom, textShadow->y + textShadow->blur);            }            if (curr->renderer()->hasReflection()) {                RenderBox* box = toRenderBox(curr->renderer());                overflowTop = min(overflowTop, box->reflectionBox().y());                overflowBottom = max(overflowBottom, box->reflectionBox().bottom());            }            if (curr->isInlineFlowBox())                newY -= curr->boxModelObject()->borderTop() + curr->boxModelObject()->paddingTop();        } else if (!curr->renderer()->isBR()) {            RenderBox* box = toRenderBox(curr->renderer());            newY += box->marginTop();            overflowTop = box->overflowTop(false);            overflowBottom = box->overflowHeight(false) - box->height();        }        curr->setY(newY);        if (childAffectsTopBottomPos) {            selectionTop = min(selectionTop, newY);            selectionBottom = max(selectionBottom, newY + curr->height());            topPosition = min(topPosition, newY + overflowTop);            bottomPosition = max(bottomPosition, newY + curr->height() + overflowBottom);        }    }    if (isRootInlineBox()) {        const Font& font = renderer()->style(m_firstLine)->font();        setY(y() + renderer()->baselinePosition(m_firstLine, true) - font.ascent());        if (hasTextChildren() || strictMode) {            selectionTop = min(selectionTop, y());            selectionBottom = max(selectionBottom, y() + height());        }    }}bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty){    // Check children first.    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {        if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) {            renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));            return true;        }    }    // Now check ourselves.    IntRect rect(tx + m_x, ty + m_y, m_width, height());    if (visibleToHitTesting() && rect.contains(x, y)) {        renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space.        return true;    }        return false;}void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty){    int xPos = tx + m_x - renderer()->maximalOutlineSize(paintInfo.phase);    int w = width() + 2 * renderer()->maximalOutlineSize(paintInfo.phase);    int shadowLeft = 0;    int shadowRight = 0;    for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {        shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);        shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);    }    for (ShadowData* textShadow = renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {        shadowLeft = min(textShadow->x - textShadow->blur, shadowLeft);        shadowRight = max(textShadow->x + textShadow->blur, shadowRight);    }    xPos += shadowLeft;    w += -shadowLeft + shadowRight;    bool intersectsDamageRect = xPos < paintInfo.rect.right() && xPos + w > paintInfo.rect.x();    if (intersectsDamageRect && paintInfo.phase != PaintPhaseChildOutlines) {        if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {            // Add ourselves to the paint info struct's list of inlines that need to paint their            // outlines.            if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {                RenderInline* inlineFlow = toRenderInline(renderer());                if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) {                    // Add ourselves to the containing block of the entire continuation so that it can                    // paint us atomically.                    RenderBlock* block = renderer()->containingBlock()->containingBlock();                    block->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));                } else if (!inlineFlow->isInlineContinuation())                    paintInfo.outlineObjects->add(inlineFlow);            }        } else if (paintInfo.phase == PaintPhaseMask) {            paintMask(paintInfo, tx, ty);            return;        } else {            // 1. Paint our background, border and box-shadow.            paintBoxDecorations(paintInfo, tx, ty);            // 2. Paint our underline and overline.            paintTextDecorations(paintInfo, tx, ty, false);        }    }    if (paintInfo.phase == PaintPhaseMask)        return;    PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;    RenderObject::PaintInfo childInfo(paintInfo);    childInfo.phase = paintPhase;    childInfo.paintingRoot = renderer()->paintingRootForChildren(paintInfo);        // 3. Paint our children.    if (paintPhase != PaintPhaseSelfOutline) {        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {            if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())                curr->paint(childInfo, tx, ty);        }    }    // 4. Paint our strike-through    if (intersectsDamageRect && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))        paintTextDecorations(paintInfo, tx, ty, true);}void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,                                    int my, int mh, int _tx, int _ty, int w, int h, CompositeOperator op){    if (!fillLayer)        return;    paintFillLayers(paintInfo, c, fillLayer->next(), my, mh, _tx, _ty, w, h, op);    paintFillLayer(paintInfo, c, fillLayer, my, mh, _tx, _ty, w, h, op);}void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,                                   int my, int mh, int tx, int ty, int w, int h, CompositeOperator op){    StyleImage* img = fillLayer->image();    bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());    if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op);    else {        // We have a fill 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.        // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,        // but it isn't even clear how this should work at all.        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();        paintInfo.context->save();        paintInfo.context->clip(IntRect(tx, ty, width(), height()));        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op);        paintInfo.context->restore();    }}void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, int tx, int ty, int w, int h){    if ((!prevLineBox() && !nextLineBox()) || !parent())        boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s);    else {        // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't        // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines        boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge());    }}void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty){    if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)        return;    // Move x/y to our coordinates.    tx += m_x;

⌨️ 快捷键说明

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