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()); }