RenderBlock表明一个物体代表一个block,他内部的对象要被竖着排列。他内部的对象要么都是RenderBox,要么都是RenderLine.
RenderLine表明一个物体,这个物体从其外部来看,是要被放置到一个line内部的。他内部的物体必须全都是RenderLine.
为了满足上述原则,webkit会手动加入一些renderobject。
css标准里讲,一个Object的in-flowchildren说的是一个object的除了fixed和absoluted定位孩子之外的普通孩子。
一个对象可以说成是inlineblock, 意思是这个对象内部的孩子需要竖着排列,但是这个对象自己从外部来看要放置到一个line里。
Posted by DaveHyatt onThursday, August 9th, 2007 at 2:59 pm
In the previous entry I talked about the basic structure of a CSSbox. In this article I’m going to talk about subclasses ofRenderBox
and about the concepts of block andinline.
A block flow is a box designed either to contain lines(e.g., a paragraph) or to contain other blocks that it stacksvertically. Example block flow elements in HTML are p and div.
An inline flow is an object that is designed to be part ofa line. Example inline flow elements in HTML are a, b,i and span.
In WebCore, there are three renderer classes that cover block andinline flows. RenderBlock
, RenderInline
andtheir common superclass RenderFlow
.
RenderFlow.h
RenderBlock.h
RenderInline.h
An inline flow can be changed to a block flow (and vice versa)using the CSS display property.
div { display: inline }
span { display: block }
In addition to block and inline flows, there is another kind ofelement that can act as a block or inline: the replaced element. Areplaced element is an element whose rendering is unspecifiedby CSS. How the contents of the object render is left up to theelement itself. Examples of replaced elements are images, formcontrols, iframes, plugins and applets.
A replaced element can also be either block-level or inline-level.When a replaced element acts as a block, it will get stackedvertically as though it represents its own paragraph. When a replacedelement acts as an inline, it will be part of a line inside aparagraph. Replaced elements are inline by default.
Form controls are actually a strange special case. They are stillreplaced elements, but because they are implemented by the engine,controls actually ultimately subclass from RenderBlock
.As a result, the concept of being replaced can’t really be confinedto a single common subclass, and is therefore represented as a bit onRenderObject
instead. The isReplaced
methodcan be used to ask if an object is a replaced element.
bool isReplaced() const
Images, plugins, frames and applets all inherit from a commonsubclass that implements replaced element behavior. This class isRenderReplaced
.
TheInline Block
One of the most confusingly named objects in CSS is theinline-block. Inline blocks are block flows that are designedto sit on a line. In effect they are like inline replaced elements onthe outside, but on the inside they are block flows. The displayproperty in CSS can be used to create inline blocks. Inline blockswill report true if asked if they are replaced.
div { display: inline-block }
Tables
Tables in HTML are block-level by default. However they can alsobe made into inlines using the CSS display property with a value ofinline-table.
table { display: inline-table }
Again, from the outside an inline-table is like an inline replacedelement (and will return true from isReplaced), but on the inside theobject is still just a table.
In WebCore the RenderTable
class represents a table.It inherits from RenderBlock for reasons that will be covered in thepositioning section later.
Text
Raw text is represented using the RenderText
class.Text is always considered inline by WebCore, since it is alwaysplaced on lines.
GettingBlock and Inline Information
The most basic method for obtaining block vs. inline status is theisInline
function. This method asks if an object isdesigned to be part of a line. It does not care what the interior ofthe element is (e.g., text, image, an inline flow, an inline-block oran inline-table).
bool isInline() const
One of the common mistakes people make when working with therender tree is assuming that isInline
means an object isalways an inline flow, text or an inline replaced element. Howeverbecause of inline-blocks and inline-tables, this method can returntrue even for these objects.
To ask if an object is actually a block or inline flow, thefollowing methods should be used.
bool isInlineFlow() const
bool isBlockFlow() const
These methods are essentially asking questions about the interiorof the object. An inline-block for example is still a block flow andnot an inline flow. It is inline on the outside, but on the inside itis a block flow.
The exact class type can be queried for blocks and inlines usingthe following methods.
bool isRenderBlock() const
bool isRenderInline() const
The isRenderBlock
method is useful in the context ofpositioning, since both block flows and tables act as positionedobject containers.
To ask if an object is specifically an inline block or inlinetable, the isInlineBlockOrInlineTable
method can beused.
bool isInlineBlockOrInlineTable() const
Childrenof Block Flows
Block flows have a simple invariant regarding their children thatthe render tree always obeys. That rule can be summarized as follows:
All in-flow children of a block flow must be blocks, or allin-flow children of a block flow must be inlines.
In other words, once you exclude floating and positioned elements,all of the children of a block flow in the render tree must returntrue from isInline
or they must all return false fromisInline
. The render tree will change its structure asneeded to preserve this invariant.
The childrenInline
method is used to ask whether thechildren of a block flow are inlines or blocks.
bool childrenInline() const
Childrenof Inline Flows
Children of inline flows have an even simpler invariant that mustbe maintained.
All in-flow children of an inline flow must be inlines.
AnonymousBlocks
In order to preserve the block flow child invariant (only inlinechildren or only block children), the render tree will constructobjects called anonymous blocks. Consider the followingexample:
<div>
Some text
<div>
Some more text
</div>
</div>
In the above example, the outer div has two children: some textand another div. The first child is an inline, but the second childis a block. Because this combination of children violates theall-inline or all-block child rule, the render tree will construct ananonymous block flow to wrap the text. The render tree thereforebecomes:
<div>
<anonymous block>
Some text
</anonymous block>
<div>
Some more text
</div>
</div>
The isAnonymousBlock
method can be used to ask if arenderer is an anonymous block flow.
bool isAnonymousBlock() const
Whenever a block flow has inline children and a block objectsuddenly tries to insert itself as a child, anonymous blocks will becreated as needed to wrap all of the inlines. Contiguous inlines willshare a single common anonymous block, so the number of anonymousblocks can be kept to a minimum. The makeChildrenNonInline
method in RenderBlock
is the function that performs thisadjustment.
void makeChildrenNonInline(RenderObject *insertionPoint)
Blocksinside Inline Flows
One of the nastiest constructs you will see in HTML is when ablock is placed inside an inline flow. Here is an example:
<i>Italic only <b>italic and bold
<div>
Wow, a block!
</div>
<div>
Wow, another block!
</div>
More italic and bold text</b> More italic text</i>
The two divs violate the invariant that all of the children of thebold element must be inlines. The render tree has to perform a rathercomplicated series of steps in order to fix up the tree. Threeanonymous blocks are constructed. The first block holds all of theinlines that come before the divs. The second anonymous block holdsthe divs. The third anonymous block holds all of the inlines thatcome after the divs.
<anonymous pre block>
<i>Italic only <b>italic and bold</b></i>
</anonymous pre block>
<anonymous middle block>
<div>
Wow, a block!
</div>
<div>
Wow, another block!
</div>
</anonymous middle block>
<anonymous post block>
<i><b>More italic and bold text</b> More italic text</i>
</anonymous post block>
Notice that the bold and italic renderers had to split into tworender objects, since they are in both the anonymous pre block andthe anonymous post block. In the case of the bold DOM element, itschildren are in the pre block, but then continue into the middleblock and then finally continue into the post block. The render treeconnects these objects via a continuation chain.
RenderFlow* continuation() const
bool isInlineContinuation() const
The first bold renderer in the pre block is the one that can beobtained from the b
DOM element using the element’srenderer()
method. This renderer has as itscontinuation()
the middle anonymous block. The middleanonymous block has as its continuation()
the secondbold renderer. In this way code that needs to examine the renderersthat represent the children of the DOM element can still do sorelatively easily.
In the above example the i
DOM element also split.Its children are all in the pre and post blocks, and therefore onlyone connection is needed. The italic renderer in the pre block setsits continuation()
to the italic renderer in the postblock.
The function that performs the recursive splitting of inline flowsand that creates the continuation chain connections is calledsplitFlow
and is in RenderInline.cpp
.
You can follow any responses to this entry through the RSS2.0 feed. Both comments and pings are currently closed.