Webkit生成一个render节点的过程

Webkit如何生成一个render节点

生成Element:

首先通过解析一个HTML文件,解析出一个tag, 然后通过tag生成HTMLElemen节点,调用堆栈如下:

 

0# HEMLSelectElement      (HTMLSelectElement.cpp)

1# HTMLSelectElement::create     (同上)

2# selectConstructor       (路径为:androidrootPath/out/target/product/yourproduct/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/webcore/HTMLElementFacty.cpp)

3# HTMLElementFactory::createHTMLElement     (路径同上)

4# HTMLConstructionSite::createHTMLElement     (HTMLConstructionSite.cpp)

5# HTMLConstructionSite::insertHTMLElement  

6# HTMLTreeBuilder::processStartTagForInBody      (HTMLTressBuilder.cpp)

7# HTMLTreeBuilder::processStartTag 

8# HTMLTreeBuilder::constructTreeFromAtomicToken 

9# HTMLTreeBuilder::constructTreeFromToken

10# HTMLDocumentParser::pumpTokenizer     (HTMLDocumentParser.cpp)

11# HTMLDocumentParser::pumpTokenizerifPossible

12# HTMLDocumentParser::append

13# DocumentWriter::addData     (DocumentWriter.cpp)

14# DocumentLoader::commitData     (DocumentLoader.cpp)

15# FrameLoaderClientAndroid::committedLoad      (FrameLoaderClientAndroid.cpp)

16# DocumentLoader::commitLoad     (DocumentLoader.cpp)

17# ResourceLoader::didReceiveData      (ResourceLoader.cpp)

18# MainResourceLoader::didReceiveData     (MainResourceLoader.cpp)

19# ResourceLoader::didReceiveData     (ResourceLoader.cpp)

20# WebUrlLoaderClient::didReceiveData     (WebUrlLoaderClient.cpp)

21# DispatchToMethod<android::WebUrlLoaderClient, void (android::WeburlLoaderClient::*) (scoped_refptr<net::IOBuffer>, int), scoped_refptr<net::IOBuffter>, int>     (tuple.h)

22# RunTask        (WebUrlLoaderClient.cpp)

23# dispatchFunctionsFromMainThread     (webkit/Source/Webkit/JavaScriptCore/wtf/MainThread.cpp)

24# JavaSharedClient::ServiceFunctionPtrQueue     (webkit/source/WebKit/android/jni/JavaSharedClient.cpp)

25# dvmPlatformInvoke     (dalvik/vm/arch/arm/CallEABI.S)

26# dvmCallJNIMethod       (dalvik/vm/Jni.cpp)

27# dvmCheckCallJNIMethod    (dalvik/vm/CheckJni.cpp)

28# dalvik_mterp       (dalvik/vm/mterp/out/InterpAsm-armv7-a-neon.S)

 

3#处函数,根据tag名称选择对应的元素类进行构建:


 

PassRefPtr<HTMLElement> HTMLElementFactory::createHTMLElement(const QualifiedName& qName, Document* document, HTMLFormElement* formElement, bool createdByParser)
{
    if(!document)
        return 0;

    if(!gFunctionMap)
        createFunctionMap();
    if(constructorFunction function = gFunctionMap->get(qName.localName().impl()))
        return function(qName, document, formElement, createByParser);

    return HTMLElement::create(qName, document);
}


其中个FunctionMap是一个map表,根据tagname,映射对应的元素构建函数

 

然后再生成attr:接着上面堆栈4# 函数:

PassRefPtr<Element> HTMLconstructionSite::creatHTMLElement(AtomicHTMLToken & token)
{
    QualifiedName tagName(nullAtom, token.name(), xhtmlNamespaceURI);
    RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, currentNode()->document(), form(). true);
    element->setAttributeMap(token.takeAtributes(), m_fragmentScriptingPermission);
    return element.release();
}


生成万Element节点 紧接着就设置Attribute, 堆栈如下:

0# HTMLSelectElement::ParseMappedAttribute     (HTMLSelectElement.cpp)
1# StyledElement::attributeChanged     (StyledElement.cpp)
2# Element::setAttributeMap     (Element.cpp)
3# HTMLConstructionSite::createHTMLElement     (HTMLConstructionSite.cpp)
4# HTMLConstructionSite::createHTMLElement 
5# ......


然后退回到堆栈5#处:HTMLConstructionSite::insertHTMLElement, 函数为:

void HTMLconstructionSit::insertHTMLElement(AtomicHTMLtoken& token)
{
    m_openElements.push(attachToCurrent(createHTMLElement(token)));

}

根据element生成renderobject

接下来根据element,生成对应的renderobject.

首先需要根据element,生成style, 接着上步往下走,堆栈为:

0# CSSStyleSelector::styleForElement    (CSSStyleSelector.cpp)
1# Node::styleForRenderer     (Node.cpp)
2# Node::createRendererAndStyle
3# Node::createRendererIfNeeded
4# Element::attach     (Element.cpp)
5# HTMLFormControlElement::attach     (HTMLFormControlElement.cpp)
6# HTMLConstructionSite::attach     (HTMLConstructionSite.cpp)
7# HTMLConstructionSite::attachToCurrent
8# HTMLConstructionSite::insertHTMLElement
9# ......


在 CSSStyleSelector::styleForElement中:会生成renderobject的RenderStyle, 然后根据设置的属性和默认属性进行各种配置。

生成和配置完RenderStyle, 再生成RenderObject, 然后将RenderStyle设置到RenderObject中:

RenderObject* Node::createRendererAndStyle()
{
    ASSERT(!renderer());
    ASSERT(document()->shouldCreateRenderers());

    ContainerNode* parent = parentNodeForRenderingAndStyle();
    ASSERT(parent);

    if(!shouldCreateRendererFor(this, parent))
        retnurn 0;

    PefPtr<RenderStyle> style = styleRenderer();
    if(!rendererIsNeeded(style.get()))
        return 0;

    RenderObject* newRenderer = createRender(document()->renderArena(), style.get());
    if(!newRenderer)
        return 0;

    if(!parent->renderer()->isChildAllowed(newRenderer, style.get()))
    {
        newRenderer->destroy();
         return 0;
    }

    setRenderer(newRenderer);
    newRenderer->setAnimatableStyle(style.release());
  
    return newRenderer;
}


createRender是HTMLElement类的一个虚拟函数,是要是继承了此类的类都可以自定义CreateRender. 如果没有定义,则调用基类的函数实现。此处HTMLSelectElement重写了此函数,所以调用HTMLSelectelement类的createRender函数,来生成一个 RenderMenuList对象:

RenderObject* HTMLSelectElment::creatRenderer(RenderArena* arena, RenderStyle*)
{
    if(m_data.usersMenuList())
    {
        return new (arena)RenderMenuList(this);
    }

    return new (arena)RenderListBox(htis);
}


到这里一个renderobject节点就已经生成完了,然后就会把节点attach到父节点上:

void Node::createRendererIfNeeded()
{
    if(!document()->shouldCreateRenderers())
        return;

    ASSERT(!renderer());

    RenderObject* newRenderer = createRendererAndStyle();

#if ENABKE(FULLSCREEN_API)
    if(document()->webkitisFullScreen() && document()->webkitCurrentFullScreenElement() == this)
    newRenderer = wrapWithRenderFullScreen(newRenderer, document());
#endif

    if(!newRenderer)
        return;

    parentNodeForRenderingAndStyle()->renderer()->addChild(newRenderer, nextRenderer());
}


 

 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值