webkit 绘制流程解析(2)
webkit在绘制的时候首先要确定一个大的容器,所有的绘制都是在这个容器内展开。
根据我之前做传统webkit的经验一般都是针对某个窗口就对应window,在android系统上也不例外:
具体参考代码如下
#ifPLATFORM(ANDROID)
classWebCoreViewBridge;
typedefWebCoreViewBridge* PlatformWidget;
#endif
#ifPLATFORM(GTK)
typedefstruct _GtkWidget GtkWidget;
typedefstruct _GtkContainer GtkContainer;
typedefGtkWidget* PlatformWidget;
#endif
可以看见这个PlatformWidget类型在不同的平台对应的数据类型不同
记得当初对接DirectFB的时候底层PlatformWidget对接的就是
typedefIDirectFBWindow BalWidget;
typedefBalWidget* PlatformWidget;
这样我们进行webkit绘制的时候用的FrameView对接的实体就是上述表述的物理实体
而且还有一个重要点:
classFrameView : public ScrollView
classScrollView : public Widget, public ScrollbarClient
看下Widget的实现
Widget(PlatformWidget= 0);
virtual~Widget();
PlatformWidgetplatformWidget() const { return m_widget; }
voidsetPlatformWidget(PlatformWidget widget)
{
if(widget != m_widget) {
releasePlatformWidget();
m_widget= widget;
retainPlatformWidget();
}
}
我们发现Widget对应的重要的参数就是上面介绍的PlatformWidget就是各个平台的实体(起的名字也是那么贴切)
那么下面我大致抓取一个frameView的调用底层的backtrace流程
用的gtk平台运行的webkit,涉及到绘制逻辑层次和各个平台还没有什么具体的关联
#0 WebCore::RenderBoxModelObject::paintFillLayerExtended (this=0x79d388,paintInfo=..., c=..., bgLayer=0x746618, tx=0, ty=0, w=800, h=535,box=0x0,
op=WebCore::CompositeSourceOver,backgroundObject=0x0) at../../WebCore/rendering/RenderBoxModelObject.cpp:444
#1 0x00007ffff64401d3 in WebCore::RenderBox::paintFillLayer(this=0x79d388, paintInfo=..., c=..., fillLayer=0x746618, tx=0, ty=0,width=800, height=535,
op=WebCore::CompositeSourceOver,backgroundObject=0x0) at ../../WebCore/rendering/RenderBox.cpp:758
#2 0x00007ffff6440159 in WebCore::RenderBox::paintFillLayers(this=0x79d388, paintInfo=..., c=..., fillLayer=0x746618, tx=0, ty=0,width=800, height=535,
op=WebCore::CompositeSourceOver,backgroundObject=0x0) at ../../WebCore/rendering/RenderBox.cpp:753
#3 0x00007ffff643f664 in WebCore::RenderBox::paintRootBoxDecorations(this=0x79d388, paintInfo=..., tx=0, ty=0) at../../WebCore/rendering/RenderBox.cpp:605
#4 0x00007ffff643f782 in WebCore::RenderBox::paintBoxDecorations(this=0x79d388, paintInfo=..., tx=0, ty=0) at../../WebCore/rendering/RenderBox.cpp:618
#5 0x00007ffff640b964 in WebCore::RenderBlock::paintObject(this=0x79d388, paintInfo=..., tx=0, ty=0) at../../WebCore/rendering/RenderBlock.cpp:1709
#6 0x00007ffff640ac7e in WebCore::RenderBlock::paint(this=0x79d388, paintInfo=..., tx=0, ty=0) at../../WebCore/rendering/RenderBlock.cpp:1536
#7 0x00007ffff6483b43 in WebCore::RenderLayer::paintLayer(this=0x746418, rootLayer=0x75e108, p=0x7fffffffd820,paintDirtyRect=..., paintBehavior=0, paintingRoot=0x0,
overlapTestRequests=0x7fffffffd600,paintFlags=0) at ../../WebCore/rendering/RenderLayer.cpp:2303
#8 0x00007ffff6483ffe in WebCore::RenderLayer::paintLayer(this=0x75e108, rootLayer=0x75e108, p=0x7fffffffd820,paintDirtyRect=..., paintBehavior=0, paintingRoot=0x0,
overlapTestRequests=0x7fffffffd600,paintFlags=0) at ../../WebCore/rendering/RenderLayer.cpp:2356
#9 0x00007ffff64830a3 in WebCore::RenderLayer::paint(this=0x75e108, p=0x7fffffffd820, damageRect=..., paintBehavior=0,paintingRoot=0x0)
at../../WebCore/rendering/RenderLayer.cpp:2133
#100x00007ffff62e4934 in WebCore::FrameView::paintContents(this=0x745e90, p=0x7fffffffd820, rect=...) at../../WebCore/page/FrameView.cpp:1745
#110x00007ffff634db2e in WebCore::ScrollView::paint(this=0x745e90, context=0x7fffffffd820, rect=...) at../../WebCore/platform/ScrollView.cpp:790
#120x00007ffff677b83b in webkit_web_view_expose_event (widget=0x73b070,event=0x7fffffffdd60) at../../WebKit/gtk/webkit/webkitwebview.cpp:481
#130x00007ffff55b6188 in ?? () from /usr/lib/libgtk-x11-2.0.so.0
#140x00007ffff35e201e in g_closure_invoke (closure=0x669f00,return_value=0x7fffffffda30, n_param_values=2, param_values=0x770430,invocation_hint=0x7fffffffd9f0)
at../../gobject/gclosure.c:767
#150x00007ffff35f8140 in signal_emit_unlocked_R (node=0x669f70,detail=<value optimized out>, instance=<value optimizedout>, emission_return=<value optimized out>,
instance_and_params=<valueoptimized out>) at ../../gobject/gsignal.c:3290
#160x00007ffff35f97fb in g_signal_emit_valist (instance=0x73b070,signal_id=<value optimized out>, detail=0,var_args=0x7fffffffdbe0) at ../../gobject/gsignal.c:2993
#170x00007ffff35f9f73 in g_signal_emit (instance=0x79d388,signal_id=4294955216, detail=4294954096) at../../gobject/gsignal.c:3040
#180x00007ffff56cd0cf in ?? () from /usr/lib/libgtk-x11-2.0.so.0
#190x00007ffff55af996 in gtk_main_do_event () from/usr/lib/libgtk-x11-2.0.so.0
#200x00007ffff520a94a in ?? () from /usr/lib/libgdk-x11-2.0.so.0
#210x00007ffff520a8f7 in ?? () from /usr/lib/libgdk-x11-2.0.so.0
#220x00007ffff52073db in ?? () from /usr/lib/libgdk-x11-2.0.so.0
#230x00007ffff5209251 in gdk_window_process_all_updates () from/usr/lib/libgdk-x11-2.0.so.0
#240x00007ffff5531591 in ?? () from /usr/lib/libgtk-x11-2.0.so.0
#250x00007ffff51e5db6 in ?? () from /usr/lib/libgdk-x11-2.0.so.0
#260x00007ffff2ef4522 in g_main_dispatch (context=0x640210) at../../glib/gmain.c:2440
#27g_main_context_dispatch (context=0x640210) at../../glib/gmain.c:3013
#280x00007ffff2ef8bf8 in g_main_context_iterate (context=0x640210,block=<value optimized out>, dispatch=<value optimized out>,self=<value optimized out>)
at../../glib/gmain.c:3091
#290x00007ffff2ef9105 in g_main_loop_run (loop=0x87fb30) at../../glib/gmain.c:3299
#300x00007ffff55afbc7 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#310x00000000004025d5 in main (argc=2, argv=0x7fffffffe278) at../../WebKitTools/GtkLauncher/main.c:209
上面的标志红色代表绘制的关键步骤
具体的绘制介绍在我前一篇博客中有所涉及http://blog.csdn.net/lihui130135/article/details/7265089
我们在研究webkit代码的时候
经常发现WebCore::PlatformGraphicsContext这种类别
这个是webkit对各个平台抽线出来的公共类,在逻辑层次的绘制都在这个类基础上进行
屏蔽各个平台的操作细节
下面是列举的GraphicsContext类一些基本操作:
voidfillRect(const FloatRect&);
voidfillRect(const FloatRect&, const Color&, ColorSpace);
voidfillRect(const FloatRect&, Generator&);
voidfillRoundedRect(const IntRect&, const IntSize& topLeft, constIntSize& topRight, const IntSize& bottomLeft, const IntSize&bottomRight, const Color&, ColorSpace);
voidclearRect(const FloatRect&);
voidstrokeRect(const FloatRect&);
voidstrokeRect(const FloatRect&, float lineWidth);
voiddrawImage(Image*, ColorSpace styleColorSpace, const IntPoint&,CompositeOperator = CompositeSourceOver);
voiddrawImage(Image*, ColorSpace styleColorSpace, const IntRect&,CompositeOperator = CompositeSourceOver, bool useLowQualityScale =false);
voiddrawImage(Image*, ColorSpace styleColorSpace, const IntPoint&destPoint, const IntRect& srcRect, CompositeOperator =CompositeSourceOver);
voiddrawImage(Image*, ColorSpace styleColorSpace, const IntRect&destRect, const IntRect& srcRect, CompositeOperator =CompositeSourceOver, bool useLowQualityScale = false);
voiddrawImage(Image*, ColorSpace styleColorSpace, const FloatRect&destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
CompositeOperator =CompositeSourceOver, bool useLowQualityScale = false);
voiddrawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect&destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator =CompositeSourceOver, bool useLowQualityScale = false);
voiddrawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect&destRect, const IntRect& srcRect,
Image::TileRule hRule =Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
CompositeOperator =CompositeSourceOver, bool useLowQualityScale = false);
voidsetImageInterpolationQuality(InterpolationQuality);
只是截取了部分函数,说明基本的操作都可以这么做
这个GraphicsContext类针对每次不同的绘制动作都会自己生成新的对象
例如:
staticvoid draw_page_callback(GtkPrintOperation* op, GtkPrintContext*context, gint page_nr, gpointer user_data)
{
PrintContext*printContext = reinterpret_cast<PrintContext*>(user_data);
if(page_nr >= printContext->pageCount())
return;
cairo_t*cr = gtk_print_context_get_cairo_context(context);
GraphicsContext ctx(cr);
floatwidth = gtk_print_context_get_width(context);
printContext->spoolPage(ctx,page_nr, width);
}
staticgboolean webkit_web_view_expose_event(GtkWidget* widget,GdkEventExpose* event)
{
WebKitWebView*webView = WEBKIT_WEB_VIEW(widget);
WebKitWebViewPrivate*priv = webView->priv;
Frame*frame = core(webView)->mainFrame();
if(frame->contentRenderer() && frame->view()) {
frame->view()->layoutIfNeededRecursive();
cairo_t*cr = gdk_cairo_create(event->window);
GraphicsContextctx(cr);
cairo_destroy(cr);
ctx.setGdkExposeEvent(event);
GOwnPtr<GdkRectangle>rects;
intrectCount;
gdk_region_get_rectangles(event->region,&rects.outPtr(), &rectCount);
//Avoid recursing into the render tree excessively
boolcoalesce = shouldCoalesce(event->area, rects.get(), rectCount);
if(coalesce) {
IntRectrect = event->area;
ctx.clip(rect);
if(priv->transparent)
ctx.clearRect(rect);
frame->view()->paint(&ctx,rect);
}else {
for(int i = 0; i < rectCount; i++) {
IntRectrect = rects.get()[i];
ctx.save();
ctx.clip(rect);
if(priv->transparent)
ctx.clearRect(rect);
frame->view()->paint(&ctx,rect);
ctx.restore();
}
}
}
returnFALSE;
}
这个是针对gtk平台摘取代码段
在android平台上是在webviewcore.cpp的文件下面
SkPicture*WebViewCore::rebuildPicture(const SkIRect& inval)
{
WebCore::FrameView*view = m_mainFrame->view();
intwidth = view->contentsWidth();
intheight = view->contentsHeight();
SkPicture*picture = new SkPicture();
SkAutoPictureRecordarp(picture, width, height, PICT_RECORD_FLAGS);
SkAutoMemoryUsageProbemup(__FUNCTION__);
SkCanvas*recordingCanvas = arp.getRecordingCanvas();
gButtonMutex.lock();
WTF::Vector<Container>buttons(m_buttons);
gButtonMutex.unlock();
WebCore::PlatformGraphicsContextpgc(recordingCanvas, &buttons);
WebCore::GraphicsContextgc(&pgc);
recordingCanvas->translate(-inval.fLeft,-inval.fTop);
recordingCanvas->save();
view->platformWidget()->draw(&gc,WebCore::IntRect(inval.fLeft,
inval.fTop,inval.width(), inval.height()));
m_rebuildInval.op(inval,SkRegion::kUnion_Op);
DBG_SET_LOGD("m_rebuildInval={%d,%d,r=%d,b=%d}",
m_rebuildInval.getBounds().fLeft,m_rebuildInval.getBounds().fTop,
m_rebuildInval.getBounds().fRight,m_rebuildInval.getBounds().fBottom);
gButtonMutex.lock();
updateButtonList(&buttons);
gButtonMutex.unlock();
returnpicture;
}
android平台下对应实际图形库是skia,所以初始化的时候SkCanvas*recordingCanvas,这个来进行初始化
这次先总结到,下次再有新的想法继续。