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,这个来进行初始化


这次先总结到,下次再有新的想法继续。



Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐