webkit 绘制部分代码解析

webkit进行最终绘制的逻辑是从frameview进行刷新调用
       RenderLayer
    RenderBlock
    RenderBox
加入我们针对各个elemenet的定制的情况
    下面我们看一个具体的调用的流程:
#0  WebCore::RenderTheme::paint (this=0x24eed0, o=0xd15fa8, paintInfo=@0x4ef83ee0, r=@0x4ef83e1c) at external/webkit/WebCore/rendering/RenderTheme.cpp:222
#1  0xa842f7c6 in WebCore::RenderBox::paintBoxDecorations (this=0xd15fa8, paintInfo=@0x4ef83ee0, tx=991, ty=103) at external/webkit/WebCore/rendering/RenderBox.cpp:636
#2  0xa8426eec in WebCore::RenderBlock::paintObject (this=0xd15fa8, paintInfo=@0x4ef83ee0, tx=1324891872, ty=103) at external/webkit/WebCore/rendering/RenderBlock.cpp:1729
#3  0xa84241fc in WebCore::RenderBlock::paint (this=0xd15fa8, paintInfo=@0x4ef83ee0, tx=991, ty=103) at external/webkit/WebCore/rendering/RenderBlock.cpp:1558
#4  0xa8416a78 in WebCore::InlineBox::paint (this=0xd8e158, paintInfo=@0x3df, tx=<value optimized out>, ty=101) at external/webkit/WebCore/rendering/InlineBox.cpp:173
#5  0xa8418b2a in WebCore::InlineFlowBox::paint (this=0xd8e17c, paintInfo=@0x4ef83fbc, tx=<value optimized out>, ty=<value optimized out>)
    at external/webkit/WebCore/rendering/InlineFlowBox.cpp:673
#6  0xa8418b2a in WebCore::InlineFlowBox::paint (this=0xd8e1b8, paintInfo=@0x4ef84060, tx=<value optimized out>, ty=<value optimized out>)
    at external/webkit/WebCore/rendering/InlineFlowBox.cpp:673
#7  0xa84712dc in WebCore::RootInlineBox::paint (this=0x24eed0, paintInfo=@0xd15fa8, tx=1324891872, ty=1324891676) at external/webkit/WebCore/rendering/RootInlineBox.cpp:166
#8  0xa844e0c0 in WebCore::RenderLineBoxList::paint (this=<value optimized out>, renderer=<value optimized out>, paintInfo=<value optimized out>, tx=<value optimized out>,
    ty=101) at external/webkit/WebCore/rendering/RenderLineBoxList.cpp:204
#9  0xa8423e36 in WebCore::RenderBlock::paintContents (this=0xd15e38, paintInfo=@0x4ef84390, tx=991, ty=101) at external/webkit/WebCore/rendering/RenderBlock.cpp:1665
#10 0xa8426f6c in WebCore::RenderBlock::paintObject (this=0xd15e38, paintInfo=@0x4ef84390, tx=<value optimized out>, ty=101)
    at external/webkit/WebCore/rendering/RenderBlock.cpp:1754
#11 0xa84241fc in WebCore::RenderBlock::paint (this=0xd15e38, paintInfo=@0x4ef84390, tx=991, ty=101) at external/webkit/WebCore/rendering/RenderBlock.cpp:1558
#12 0xa8449756 in WebCore::RenderLayer::paintLayer (this=0xd15eb0, rootLayer=<value optimized out>, p=0x4ef84a48, paintDirtyRect=<value optimized out>, paintBehavior=0,
    paintingRoot=0x0, overlapTestRequests=0x4ef8495c, paintFlags=0) at external/webkit/WebCore/rendering/RenderLayer.cpp:2338
#13 0xa8449838 in WebCore::RenderLayer::paintLayer (this=0xacee9c, rootLayer=<value optimized out>, p=0x4ef84a48, paintDirtyRect=<value optimized out>, paintBehavior=0,
    paintingRoot=0x0, overlapTestRequests=0x4ef8495c, paintFlags=0) at external/webkit/WebCore/rendering/RenderLayer.cpp:2363
#14 0xa8449838 in WebCore::RenderLayer::paintLayer (this=0xaced68, rootLayer=<value optimized out>, p=0x4ef84a48, paintDirtyRect=<value optimized out>, paintBehavior=0,
    paintingRoot=0x0, overlapTestRequests=0x4ef8495c, paintFlags=0) at external/webkit/WebCore/rendering/RenderLayer.cpp:2363
#15 0xa8449976 in WebCore::RenderLayer::paint (this=<value optimized out>, p=0xa8449977, damageRect=@0x3df, paintBehavior=<value optimized out>, paintingRoot=0x0)
    at external/webkit/WebCore/rendering/RenderLayer.cpp:2142
#16 0xa83d6f1c in WebCore::FrameView::paintContents (this=0xa7f0c0, p=<value optimized out>, rect=<value optimized out>) at external/webkit/WebCore/page/FrameView.cpp:1775
通过这个过程我们就可以看到最终调用到的RenderTheme的过程,实际上这些都是一些修饰的东西
修饰的东西的来源是paintBoxDecorations
而调用这个修饰之前的RenderBlock::paintObject就是对整个内容绘制
我们查看一下这个内容:
void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
{
    PaintPhase paintPhase = paintInfo.phase;

    // 1. paint background, borders etc
    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
        if (hasBoxDecorations())
            paintBoxDecorations(paintInfo, tx, ty);
        if (hasColumns())
            paintColumnRules(paintInfo, tx, ty);
    }

    if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
        paintMask(paintInfo, tx, ty);
        return;
    }

    // We're done.  We don't bother painting any children.
    if (paintPhase == PaintPhaseBlockBackground)
        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())
        layer()->subtractScrolledContentOffset(scrolledX, scrolledY);

    // 2. paint contents
    if (paintPhase != PaintPhaseSelfOutline) {
        if (hasColumns())
            paintColumnContents(paintInfo, scrolledX, scrolledY);
        else
            paintContents(paintInfo, scrolledX, scrolledY);
    }

    // 3. paint selection
    // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
    bool isPrinting = document()->printing();
    if (!isPrinting && !hasColumns())
        paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.

    // 4. paint floats.
    if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
        if (hasColumns())
            paintColumnContents(paintInfo, scrolledX, scrolledY, true);
        else
            paintFloats(paintInfo, scrolledX, scrolledY, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
    }

    // 5. paint outline.
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
        paintOutline(paintInfo.context, tx, ty, width(), height(), style());

    // 6. paint continuation outlines.
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
        if (inlineContinuation() && inlineContinuation()->hasOutline() && inlineContinuation()->style()->visibility() == VISIBLE) {
            RenderInline* inlineRenderer = toRenderInline(inlineContinuation()->node()->renderer());
            if (!inlineRenderer->hasSelfPaintingLayer())
                containingBlock()->addContinuationWithOutline(inlineRenderer);
            else if (!inlineRenderer->firstLineBox())
                inlineRenderer->paintOutline(paintInfo.context, tx - x() + inlineRenderer->containingBlock()->x(),
                                             ty - y() + inlineRenderer->containingBlock()->y());
        }
        paintContinuationOutlines(paintInfo, tx, ty);
    }

    // 7. paint caret.
    // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
    // then paint the caret.
    if (paintPhase == PaintPhaseForeground) {        
        paintCaret(paintInfo, scrolledX, scrolledY, CursorCaret);
        paintCaret(paintInfo, scrolledX, scrolledY, DragCaret);
    }
}
这个函数里面包含的paintContents就是对于内容的绘制过程

我们还发现这个paintBoxDecorations里面包含对于背景的绘制

void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
    if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
        return;

    int x = m_x;
    int y = m_y;
    int w = width();
    int h = height();

    // Constrain our background/border painting to the line top and bottom if necessary.
    bool strictMode = renderer()->document()->inStrictMode();
    if (!hasTextChildren() && !strictMode) {
        RootInlineBox* rootBox = root();
        int bottom = min(rootBox->lineBottom(), y + h);
        y = max(rootBox->lineTop(), y);
        h = bottom - y;
    }
    
    // Move x/y to our coordinates.
    tx += x;
    ty += y;
    
    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, Normal, tx, ty, w, h);

        Color c = styleToUse->backgroundColor();
        paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), tx, ty, w, h);

        if (styleToUse->boxShadow())
            paintBoxShadow(context, styleToUse, Inset, 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, w, h));
                boxModelObject()->paintBorder(context, startX, ty, totalWidth, h, renderer()->style());
                context->restore();
            }
        }
    }
}

paintFillLayers里面就是包含着对于背景的绘制

如果对这篇讲的技术有任何疑问,第一时间获得文章更新,每天发布一篇技术大牛的原创文章,更多技术信息分享

欢迎关注个人微信公众平台:程序员互动联盟,扫一扫下方二维码或搜索微信号coder_online即可关注,在线帮您解决技术难点,给大牛直接出难题。

                                                                                                


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值