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

📄 inlineflowbox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    ty += m_y;        int w = width();    int h = height();    int my = max(ty, paintInfo.rect.y());    int mh;    if (ty < paintInfo.rect.y())        mh = max(0, h - (paintInfo.rect.y() - ty));    else        mh = min(paintInfo.rect.height(), h);    GraphicsContext* context = paintInfo.context;        // 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 = renderer()->style(m_firstLine);    if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {        // Shadow comes first and is behind the background and border.        if (styleToUse->boxShadow())            paintBoxShadow(context, styleToUse, tx, ty, w, h);        Color c = styleToUse->backgroundColor();        paintFillLayers(paintInfo, 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() && renderer()->style()->hasBorder()) {            StyleImage* borderImage = renderer()->style()->borderImage().image();            bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom());            if (hasBorderImage && !borderImage->isLoaded())                return; // Don't paint anything while we wait for the image to load.            // The simple case is where we either have no border image or we are the only box for this object.  In those            // cases only a single call to draw is required.            if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))                boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), includeLeftEdge(), includeRightEdge());            else {                // We have a border image that spans multiple lines.                // We need to adjust _tx and _ty by the width of all previous lines.                // Think of border image 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 image 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();                context->save();                context->clip(IntRect(tx, ty, width(), height()));                boxModelObject()->paintBorder(context, startX, ty, totalWidth, h, renderer()->style());                context->restore();            }        }    }}void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty){    if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)        return;    // Move x/y to our coordinates.    tx += m_x;    ty += m_y;        int w = width();    int h = height();    int my = max(ty, paintInfo.rect.y());    int mh;    if (ty < paintInfo.rect.y())        mh = max(0, h - (paintInfo.rect.y() - ty));    else        mh = min(paintInfo.rect.height(), h);        // Figure out if we need to push a transparency layer to render our mask.    bool pushTransparencyLayer = false;    const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();    StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();    if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())        pushTransparencyLayer = true;        CompositeOperator compositeOp = CompositeDestinationIn;    if (pushTransparencyLayer) {        paintInfo.context->setCompositeOperation(CompositeDestinationIn);        paintInfo.context->beginTransparencyLayer(1.0f);        compositeOp = CompositeSourceOver;    }    paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);        bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom());    if (!hasBoxImage || !maskBoxImage->isLoaded())        return; // Don't paint anything while we wait for the image to load.    // The simple case is where we are the only box for this object.  In those    // cases only a single call to draw is required.    if (!prevLineBox() && !nextLineBox()) {        boxModelObject()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, renderer()->style(), maskNinePieceImage, compositeOp);    } else {        // We have a mask image that spans multiple lines.        // We need to adjust _tx and _ty by the width of all previous lines.        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()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, renderer()->style(), maskNinePieceImage, compositeOp);        paintInfo.context->restore();    }        if (pushTransparencyLayer)        paintInfo.context->endTransparencyLayer();}static bool shouldDrawTextDecoration(RenderObject* obj){    for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) {        if (curr->isRenderInline())            return true;        if (curr->isText() && !curr->isBR()) {            if (!curr->style()->collapseWhiteSpace())                return true;            Node* currElement = curr->node();            if (!currElement)                return true;            if (!currElement->isTextNode())                return true;            if (!static_cast<Text*>(currElement)->containsOnlyWhitespace())                return true;        }    }    return false;}void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, 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 (renderer()->style()->htmlHacks() || !renderer()->shouldPaintWithinRoot(paintInfo) ||        renderer()->style()->visibility() != VISIBLE)        return;        // We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text.    if (paintInfo.phase == PaintPhaseSelection && paintInfo.forceBlackText)        return;    GraphicsContext* context = paintInfo.context;    tx += m_x;    ty += m_y;    RenderStyle* styleToUse = renderer()->style(m_firstLine);    int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();    if (deco != TDNONE &&         ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&        shouldDrawTextDecoration(renderer())) {        int x = m_x + borderLeft() + paddingLeft();        int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());        RootInlineBox* rootLine = root();        if (rootLine->ellipsisBox()) {            int ellipsisX = rootLine->ellipsisBox()->x();            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);            }        }        // We must have child boxes and have decorations defined.        tx += borderLeft() + paddingLeft();        Color underline, overline, linethrough;        underline = overline = linethrough = styleToUse->color();        if (!parent())            renderer()->getTextDecorationColors(deco, underline, overline, linethrough);        bool isPrinting = renderer()->document()->printing();        context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.        bool paintUnderline = deco & UNDERLINE && !paintedChildren;        bool paintOverline = deco & OVERLINE && !paintedChildren;        bool paintLineThrough = deco & LINE_THROUGH && paintedChildren;        bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255);        int baselinePos = renderer()->style(m_firstLine)->font().ascent();        if (!isRootInlineBox())            baselinePos += borderTop() + paddingTop();        bool setClip = false;        int extraOffset = 0;        ShadowData* shadow = styleToUse->textShadow();        if (!linesAreOpaque && shadow && shadow->next) {            IntRect clipRect(tx, ty, w, baselinePos + 2);            for (ShadowData* s = shadow; s; s = s->next) {                IntRect shadowRect(tx, ty, w, baselinePos + 2);                shadowRect.inflate(s->blur);                shadowRect.move(s->x, s->y);                clipRect.unite(shadowRect);                extraOffset = max(extraOffset, max(0, s->y) + s->blur);            }            context->save();            context->clip(clipRect);            extraOffset += baselinePos + 2;            ty += extraOffset;            setClip = true;        }        bool setShadow = false;        do {            if (shadow) {                if (!shadow->next) {                    // The last set of lines paints normally inside the clip.                    ty -= extraOffset;                    extraOffset = 0;                }                context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color);                setShadow = true;                shadow = shadow->next;            }            if (paintUnderline) {                context->setStrokeColor(underline);                context->setStrokeStyle(SolidStroke);                // Leave one pixel of white between the baseline and the underline.                context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting);            }            if (paintOverline) {                context->setStrokeColor(overline);                context->setStrokeStyle(SolidStroke);                context->drawLineForText(IntPoint(tx, ty), w, isPrinting);            }            if (paintLineThrough) {                context->setStrokeColor(linethrough);                context->setStrokeStyle(SolidStroke);                context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting);            }        } while (shadow);        if (setClip)            context->restore();        else if (setShadow)            context->clearShadow();    }}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){    for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {        if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))            return false;    }    return true;}int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox){    int result = -1;    for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {        int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);        if (currResult != -1 && result == -1)            result = currResult;    }    return result;}void InlineFlowBox::clearTruncation(){    for (InlineBox *box = firstChild(); box; box = box->nextOnLine())        box->clearTruncation();}#ifndef NDEBUGvoid InlineFlowBox::checkConsistency() const{#ifdef CHECK_CONSISTENCY    ASSERT(!m_hasBadChildList);    const InlineBox* prev = 0;    for (const InlineBox* child = m_firstChild; child; child = child->nextOnLine()) {        ASSERT(child->parent() == this);        ASSERT(child->prevOnLine() == prev);        prev = child;    }    ASSERT(prev == m_lastChild);#endif}#endif} // namespace WebCore

⌨️ 快捷键说明

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