您的位置:首页 > 移动开发 > Android开发

Android webkit image的加载过程解析(三)

2013-12-31 18:22 363 查看
#############################################

本文为极度寒冰原创,转载请注明出处

#############################################

顺着前面的文章进行分析,我们就可以找到我们需要继续解析的堆栈。

#0  android::WebViewCore::contentDraw (this=0x2a1c6f68) at external/webkit/Source/WebKit/android/jni/WebViewCore.cpp:969
#1  0x48f8ad3c in android::ChromeClientAndroid::attachRootGraphicsLayer (this=<value optimized out>, layer=<value optimized out>)
at external/webkit/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp:112
#2  0x48dcfd8c in WebCore::RenderLayerCompositor::attachRootPlatformLayer (this=0x2a3b3f58, attachment=WebCore::RenderLayerCompositor::RootLayerAttachedViaChromeClient)
at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1895
#3  0x48dd03e4 in WebCore::RenderLayerCompositor::ensureRootPlatformLayer (this=0x2a3b3f58) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1842
#4  0x48dd0432 in WebCore::RenderLayerCompositor::enableCompositingMode (this=0x2a3b3f58, enable=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:153
#5  WebCore::RenderLayerCompositor::enableCompositingMode (this=0x2a3b3f58, enable=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:147
#6  0x48dd051a in WebCore::RenderLayerCompositor::updateBacking (this=0x2a3b3f58, layer=0x2a3fa67c, shouldRepaint=WebCore::RenderLayerCompositor::CompositingChangeRepaintNow)
at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:360
#7  0x48dd05da in WebCore::RenderLayerCompositor::updateLayerCompositingState (this=<value optimized out>, layer=0x2a3fa67c, shouldRepaint=<value optimized out>)
at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:437
#8  0x48dca85a in WebCore::RenderLayer::styleChanged (this=0x2a3fa67c, diff=WebCore::StyleDifferenceEqual, oldStyle=0x0) at external/webkit/Source/WebCore/rendering/RenderLayer.cpp:4119
#9  0x48db78e6 in WebCore::RenderBoxModelObject::styleDidChange (this=0x2a3fa600, diff=WebCore::StyleDifferenceEqual, oldStyle=0x0) at external/webkit/Source/WebCore/rendering/RenderBoxModelObject.cpp:363
#10 0x48db2122 in WebCore::RenderBox::styleDidChange (this=0x2a3fa600, diff=<value optimized out>, oldStyle=0x0) at external/webkit/Source/WebCore/rendering/RenderBox.cpp:300
#11 0x48da903a in WebCore::RenderBlock::styleDidChange (this=0x2a3fa600, diff=WebCore::StyleDifferenceEqual, oldStyle=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderBlock.cpp:239
#12 0x48dd998a in WebCore::RenderObject::setStyle (this=0x2a3fa600, style=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderObject.cpp:1634
#13 0x48dd9260 in WebCore::RenderObject::setAnimatableStyle (this=0x2a3fa600, style=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderObject.cpp:1551
#14 0x48d06d82 in WebCore::Node::createRendererAndStyle (this=0x2a42fb70) at external/webkit/Source/WebCore/dom/Node.cpp:1508
其实Render的部分也没有想象中的那么复杂,只是会有一些布局,排版方面的交错的地方。

前面的分析我们知道了RenderBoxModelObject::styleDidChange,那么我们先来看一下这个函数的实现:

void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
updateBoxModelInfoFromStyle();

if (requiresLayer()) {
if (!layer()) {
if (s_wasFloating && isFloating())
setChildNeedsLayout(true);
m_layer = new (renderArena()) RenderLayer(this);
setHasLayer(true);
m_layer->insertOnlyThisLayer();
if (parent() && !needsLayout() && containingBlock()) {
m_layer->setNeedsFullRepaint();
m_layer->updateLayerPositions();
}
}
} else if (layer() && layer()->parent()) {
setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
setHasReflection(false);
m_layer->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
if (s_wasFloating && isFloating())
setChildNeedsLayout(true);
}

if (layer()) {
layer()->styleChanged(diff, oldStyle);
if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
setChildNeedsLayout(true);
}
}
这个函数有一个requiresLayer()的判断,requiresLayer的函数原型为:

virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns() || style()->hasFixedBackgroundImage(); }

这个里面的值来简单的说明一下:

isRoot() --> 顾名思义,判断当前节点是否为根节点

isPositioned() --> 判断是否为absolute定位方式,或者fixed定位方式

isRelPositioned() --> 判断是否为relative定位方式

isTransparent() --> 对应于css属性的opacity(透明度),只有当opacity小于1.0时,返回值才为真。

hasOverflowClip() --> 判断属性规定当内容溢出元素框时发生的事情。当overflow:auto/scroll/hidden的时候会被置为true.

hasTransform() --> Transform是CSS3的一种高级属性,字面上就是变形,改变的意思。在CSS3中transform主要包括以下几种:旋转rotate、扭曲skew、缩放scale和移动translate以及矩阵变形matrix

hasMask() --> Mask在Css3中,属性为对象建立一个覆盖于表面的膜

hasReflection() --> reflection常被用来做图片倒影时使用

style()->specifiesColumns() --> 这些都是节点的内部属性

style()->hasFixedBackgroundImage() --> 这些都是节点的内部属性

如果要创建一个RenderLayer,就需要上面的requiresLayer()返回为真,所以能够触发创建一个RenderLayer的css属性为:position:absolute,relative,fixed(static不能,它为无特殊定位,对象遵循HTML定位规则);opacity:小于1 (大于1,isTransparent()函数返回假,不会创建RenderLayer;小于0的时候,该函数也返回真,会创建RenderLayer)

因为CSS为排版的属性,而排版对应不同的RenderLayer,所以必需遵循一定的规则才可以进行RenderLayer的创建(满足上述条件之一即可认定需要创建RenderLayer)。

然后在下面的判断中,如果当前没有一个RenderLayer的话,就会去重新创建一个新的m_layer, 紧接着去设置setHasLayer(true).

setHasLayer是设置内部的变量m_hasLayer为true。而通过查看hasLayer之后,我们可以确定,只有在m_hasLayer为true之后,RenderLayer才会被创建。

m_layer->insertOnlyThisLayer()函数就会将新创建的RenderLayer插入到RenderLayer树中去了。

在这边,因为刚才已经成功创建了RenderLayer,所以layer()肯定是有值为true,于是进入到了这个判断中。于是执行RenderLayer中的styleChanged方法。

RenderLayer的styleChanged方法中,也有一点需要注意的问题。即软件渲染和硬件加速的问题。

我们经常碰到一些问题是在硬件加速的情况下才会出现,比如模拟器在没有打开gpu on的时候,就是启用软件加速。

这边的话 #if USE(ACCELERATED_COMPOSITING) 肯定是为true的,我们进入到了这个里面的判断。

于是就有了刚才堆栈中的compositor()->updateLayerCompositingState(this)这个函数。

从名字中我们就可以看出,这个是使用硬件加速开始进行Layer的合成。

先介绍一下RenderLayerCompositor类:WebKit中渲染部分‘掌控大局’的类,管理RenderLayer树结构,它通过浏览器的设置来决定是否创建RenderLayer以及是否硬件加速合成,同时也决定是否为RenderLayer创建RenderLayerBacking

那么什么是RenderLayerBacking呢?RenderLayerBacking主要用来管理和控制相对应的RenderLayer的合成行为,包含很多GraphicsLayer对象,这些对象用于表示层内容,前景(foreground)内容等等

updateLayerCompositingState主要用来判断当前的RenderLayerBacking是否需要更新。

在这个堆栈的

#2  0x48dcfd8c in WebCore::RenderLayerCompositor::attachRootPlatformLayer (this=0x2a3b3f58, attachment=WebCore::RenderLayerCompositor::RootLayerAttachedViaChromeClient)
at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1895
#3  0x48dd03e4 in WebCore::RenderLayerCompositor::ensureRootPlatformLayer (this=0x2a3b3f58) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1842
#4  0x48dd0432 in WebCore::RenderLayerCompositor::enableCompositingMode (this=0x2a3b3f58, enable=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:153
#5  WebCore::RenderLayerCompositor::enableCompositingMode (this=0x2a3b3f58, enable=<value optimized out>) at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:147
#6  0x48dd051a in WebCore::RenderLayerCompositor::updateBacking (this=0x2a3b3f58, layer=0x2a3fa67c, shouldRepaint=WebCore::RenderLayerCompositor::CompositingChangeRepaintNow)
at external/webkit/Source/WebCore/rendering/RenderLayerCompositor.cpp:360
部分都是比较好理解的,按照这个函数搜一下code,就可以了解这个都是一些100%要进行的调用。

在android平台上面,如果是一个独立的element,并且Tag是iframeTag,frame,object的时候就返回所对应的标签。

如果是这些标签的话,我们就会在RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ?RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;的时候得到RootLayerAttachedViaEnclosingFrame标签,而如果不是的话,就会得到的是RootLayerAttachedViaChromeClient标签。

因此,在void RenderLayerCompositor::attachRootPlatformLayer(RootLayerAttachment attachment)中,我们就可以看到page->chrome()->client()->attachRootGraphicsLayer(frame, rootPlatformLayer());

于是就对应到了android::ChromeClientAndroid::attachRootGraphicsLayer。。

到了这个函数,我们也就找到了android使用contentDraw的方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: