WebCore Rendering 2 - 块和内联

        在上一篇文章中,我们讲到了CSS盒模型的基本结构。在本文中,我们将继续讨论RenderBox类(继承于RenderObject类),以及关于块(block)和内联(inline)的概念。

        一个块流(block flow)是一种盒类型,包括多行内容(例如,一个段落),或者其他按垂直顺序依次排列的块。在HTML里,p元素和div元素都是块流元素。

        一个内联流(inline flow)则是属于一行中的某个部分。在HTML里,a元素、b元素、i元素和span元素都是内联块流元素。

        在WebCore里,有3种渲染类(rendererclass)覆盖了块流和内联流。RenderBlock类,RenderInline类,以及它们的共同父类RenderFlow

        RenderFlow.h

        RenderBlock.h

        RenderInline.h        CSSdisplay属性,可以将内联流改变为块流(反之亦然)。

        div { display:inline }

        span { display:block }

        除了块流和内联流之外,还有一种类型元素可以扮演一个块或内联:被替换元素(replayced element)。被替换元素,是指元素的渲染不是通过CSS来指定的元素。被替换元素的内容,从该元素的左上角开始渲染。img元素、表单控件、iframe元素、插件(plugins)和JAVA小程序(applets)都属于被替换元素。

        一个被替换元素可以是块级(block-level)的,也可以是内联级(inline-level)的。当被替换元素是一个块元素时,它将被依次垂直地排列,就像一个段落元素一样。当被替换元素是一个内联元素时,它就是一个段落中的一行里的一部分。默认情况下,被替换元素是一个内联元素。

        表单控件属于特例。虽然它们属于被替换元素,但是,因为它们是Web引擎实现的元素,所以,实际上,它们是继承于RenderBlock类的子类。因此,“被替换元素”这一概念不能成为一个简单的、公共的子类,而是,通过RenderObject的某个成员来表示。通过isReplayced方法,可以得出对象是否一个被替换元素。

        bool isReplaced() const

图像(images),插件(plugins),框架(frames),以及Java小程序(applets)都是继承于一个公共的实现了被替换元素形为的子类。这个类就是RenderReplaced类。

        RenderReplaced.

内联块(The Inline Block

        CCS里,最使人迷惑的就是“内联块(inline-block)”。首先,内联块是一个块流,另一方面,内联块又是位于一行中的。实际上,对于外部,内联块就像内联的被替换元素,而在内联块内部是块流。可以通过CSS的显示属性来创建内联块。对于内联块元素,isReplaced方法将返回true,即,内联块被当作一个被替换元素。

        div { display:inline-block }

表格(Tables

        默认情况下,在HTML里,表格元素是块级元素。然而,可以通过将CSS显示属性设置为inline-table,将一个表格转换为内联元素。

        table { display:inline-table }

        再次强调,对于外部来说,内联表格就相当是一个内联的被替换元素(所以,isReplaced方法会返回true),但是,对于表格本身,表格仍是一个表格。

        WebCore里,RenderTable类表示一个表格。RenderTable类继承于RendeBlock类,为什么是这个继承关系将于文章后面的排版章节讲述。

        RenderTable.h

文本(Text

        纯文本通过RenderText类表示。在WebCore里,文本通常被当作是内联元素,因为,它通常们于各行当中。

        RenderText.h

获取块和内联信息(Getting Blockand Inline Information

        最常用的用于判断对象是块还是内联的方法是isInline方法。该方法返回对象是否是一行的一部分。它并不需要理会元素的内部(例如,文本,图片,内联流,内联块,还是内联表格)。

        bool isInline()const

        大家通过会误认为:在渲染树(render tree)中,isInline即表示对象是否为内联流、文本,或者内联的被替换元素。然而,对于内联块(inline-blocks)和内联表格(inline-tables),isInline方法也是返回true的。

        如果需要精确判断一个对象是否是块流或内联流,就应该使用以下的方法。

        bool isInlineFlow() const

        bool isBlockFlow() const

        这两个方法会根据对象的内部实际情况,来返回相应的结果。例如,一个内联块元素,是一个块流,而不是一个内联流。内联块元素,在外部看来,是内联的,但是,内联块内部是块流。

        如果需要判断对应的类类型,可以使用以下的方法。

        bool isRenderBlock() const

        bool isRenderInline() const

        在排版过程中,isRenderBlock方法十分有用,因为,块流和表格都是被排版对象的容器。

如果需要判断一个对象是否是内联块,或是内联表格,可以使用isInlineBlockOrInlineTable方法。

        bool isInlineBlockOrInlineTable() const

块流的孩子(Children ofBlock Flows

       块流有一个关于其孩子元素的渲染树总是满足的规则。这个规则可以总结如下:

       块流的孩子必须全部都是块元素或全部都是内联元素。

       即,除去浮动(floating)元素和绝对定位元素,在渲染树中,块流的全部孩子的isInline方法必须都返回true,或者都返回false。为了满足这个规则,渲染树会做相应的变动。

       childrenInline方法就是用于获知一个块流的孩子是否都是内联元素或块元素。

       boolchildrenInline() const

内联的孩子(Children of InlineFlows

       内联流也有一个关于其孩子元素的规则。

       内联流的孩子必须都是内联元素。

匿名块(Anonymous Blocks

       为了满足块流关于其孩子的规则(全部都是内联元素或全部都是块元素),渲染树将构建一些对象,这些对象名叫匿名块。考虑下面这个例子:

       <div>

       Sometext

       <div>

       Somemore text

       </div>

       </div>

       上面的例子中,外层的div元素有两个孩子:“some text”和另外一个div元素。第一个孩子是内联元素,而第二个孩子是块元素。因为,这不满足“全是内联”或“全是块”的规则,渲染树会构建匿名块来包装文本。从而,渲染树变成以下这样:

       <div>

       <anonymousblock>

       Sometext

       </anonymousblock>

       <div>

       Somemore text

       </div>

       </div>

       isAnonymousBlock方法可以告知某个渲染树节点是否一个匿名块流。

       bool isAnonymousBlock() const

       当一个块流既有内联元素,又有块元素时,并且,在准备将其孩子元素加入到渲染树中时,渲染树会根据需要,自动创建匿名块元素,以用来包装这些内联元素。连续的内联元素将共享一个公共的匿名块,所以,匿名块的个数将会被尽量的少。RenderBlock类的makeChildrenNonInline方法将执行上面描述的这项修正工作。

       void makeChildrenNonInline(RenderObject *insertionPoint)

内联流里的块元素(Blocks insideInline Flows

       HTML里,最另人讨厌的一种情况就是:一个块元素将放置于内联流里。下面是一个例子:

       <i>Italiconly <b>italic and bold

       <div>

       Wow,a block!

       </div>

       <div>

       Wow,another block!

       </div>

       Moreitalic and bold text</b> More italic text</i>

       两个div元素,破坏了bold元素的孩子必须全部是内联元素的规则。渲染树不得不进行一系列相当复杂的操作来修正。对于上面这个例子,3个匿名块会被构建。第一个匿名块将第一个div元素之前的内联元素包含起来。第二匿名块将两个div元素包含起来。第三个匿名块将第二个div元素之后的内联元素包含起来。

       <anonymouspre block>

       <i>Italiconly <b>italic and bold</b></i>

       </anonymouspre block>

       <anonymousmiddle block>

       <div>

       Wow,a block!

       </div>

       <div>

       Wow,another block!

       </div>

       </anonymousmiddle block>

       <anonymouspost block>

<i><b>Moreitalic and bold text</b> More italic text</i>

       </anonymouspost block>

       注意,bold元素和italic元素的被分别分割成两个渲染树节点,因为,它们同时存在于第一个匿名块和第三个匿名块。在DOM树中,blod元素的孩子在第一个匿名块中,然后,又会到第二个匿名块中,最后,又会到第三个匿名块中。渲染树通过一个名叫“连续链(continuation chain)”的操作来连接这些对象。

       RenderFlow*continuation() const

       BoolisInlineContinuation() const

       在第一个匿名块里的第一个bold渲染树节点,可以通过对应的DOM树中的b节点的renderer方法获得。然后,该渲染树节点的continuation方法将会返回第二个匿名块的渲染树节点。而第二个匿名块的continuation方法将返回第二个bold渲染树节点。按照这种方式,需要保证的是DOM元素的孩子所对应的渲染树节点也可以轻易地做出类似的操作。

       在上面的例子中,DOM树中的i节点同样被分割。它的孩子只存在第一个和第三个匿名块中,所以,只需要一个连接操作。在第一个匿名块中的italic渲染树节点的continuation方法返回在第三个匿名块中的italic渲染树节点。

       位于RenderInline.cpp文件的splitFlow方法,就是用来递归分割内联流和创建“连续链(continuationchain)”。

 

 

原文地址:http://www.webkit.org/blog/115/webcore-rendering-ii-blocks-and-inlines/

你可能感兴趣的:(java,html,iframe,css,div,plugins)