• 转载: WebCore渲染之一:基础


    (转载自: http://www.cnblogs.com/jz1108/archive/2012/07/02/2573045.html

    文档树

    网页会被解析成一个包含若干结点的树形结构,即文档对象模型(DOM)。树中所有结点的基类为Node。

    Node.h

    结点被划分为若干类型。与渲染代码相关的结点类型包括:

    • Document(文档类):树的根节点总为文档。有三个文档相关的类:Document、HTMLDocument和SVGDocument。第一个用来表示除SVG文档以外的所有XML文档。第二个继承自Document,只表示HTML文档。第三个也继承自Document,用来表示SVG文档(涉及:Document.hHTMLDocument.h)。
    • Elements(元素类):在HTML或XML代码中的标签最终会变为元素。从渲染角度看,元素是一个具有标记名的结点,可用来在渲染时转换为某个特定的子类,从而获取其数据。(涉及:Element.h
    • Text(文本):元素之间的纯文本会被转化为一个文本结点。文本结点负责存储纯文本信息,渲染树可通过它来获取数据(涉及:Text.h)。

    渲染树

    渲染树是渲染过程的核心。渲染树和DOM树很像,都是树形结构,树中的每个元素可对应到文档、元素或者文本结点。渲染树还能包含一些DOM树中没有的结点。

    渲染树结点的基类为RenderObject。

    RenderObject.h

    DOM结点所对应的RenderObject对象可通过Node的renderer()方法获得。

    RenderObject* renderer() const

    以下方法是遍历渲染树最常用的:

    RenderObject* firstChild() const;
    RenderObject* lastChild() const;
    RenderObject* previousSibling() const;
    RenderObject* nextSibling() const;

    下面的例子我们循环访问了一个渲染结点的子结点。这在渲染树的代码中很常见。

    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
        ...
    }

    创建渲染树

    渲染结点通过一个叫做attachment的过程创建出来。随着文档被解析、DOM结点被添加,一个叫做attach的方法会被DOM结点调用来创建每个渲染结点。

    void attach()

    attach方法为DOM结点计算样式信息。如果元素CSS的display属性为none,或者元素是某个display为none的元素的子元素,那么渲染结点就不会被创建。结点相关的子类与CSS的display属性一起决定了该创建什么样的渲染结点。

    Attach是一个自顶向下的递归过程。一个父结点的渲染结点的创建总会早于其子结点的渲染结点的创建。

    销毁渲染树

    在DOM结点被移除时或者整个文档被销毁时(比如关闭页面),渲染结点会随之销毁。此时DOM结点的detach方法就会被调用,用来销毁渲染结点。

    void detach()

    Detach是一个自底向上的递归操作。子结点的渲染结点会先于其父节点销毁。

    获取样式信息

    在attach过程中,DOM会通过CSS获取元素样式信息。结果会存储在RenderStyle对象中。

    RenderStyle.h

    每个WebKit支持的CSS属性都可通过该对象查询。RenderStyles对象是引用计数的对象,如果DOM结点创建了一个渲染结点,那么它将调用渲染结点的setStyle方法将样式信息与之关联。

    void setStyle(RenderStyle*)

    渲染结点增加了一个对样式对象的引用,该引用将一直被维护除非结点获得一个新样式或者被销毁。

    RenderStyle可通过RenderObject的style()方法获得。

    RenderStyle* style() const

    CSS盒模型

    RenderObject中的一个主要子类为RenderBox,该子类表示遵循CSS盒模型的对象,这些对象会有自己的border(边框)、padding(内边距)、margin(外边距)、width(宽)和height(高)。不过现在一些没有遵循CSS盒模型的对象也继承于RenderBox(例如:SVG对象)。这个问题以后会在重构渲染树的过程中修复。

    CSS 2.1规范的这幅图描述了CSS盒模型的各个部分。下面的方法可用来获取边框和内外边距。RenderStyle只有在获取原始样式信息时用到,因为RenderObject的计算结果会有很大差别(特别是表格元素,它可以将单元格的padding属性覆盖,表格之间的边框也可以重叠在一起)。

    复制代码
    int marginTop() const;
    int marginBottom() const;
    int marginLeft() const;
    int marginRight() const;
    
    int paddingTop() const;
    int paddingBottom() const;
    int paddingLeft() const;
    int paddingRight() const;
    
    int borderTop() const;
    int borderBottom() const;
    int borderLeft() const;
    int borderRight() const;
    复制代码

    width()和height()方法给出宽度和高度(包含边框的)。

    int width() const;
    int height() const;

    client box包含了边框和滚动条,padding也包括:

    int clientLeft() const { return borderLeft(); }
    int clientTop() const { return borderTop(); }
    int clientWidth() const;
    int clientHeight() const;

    content box用来描述不包含border和padding的CSS盒子:

    IntRect contentBox() const;
    int contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
    int contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }

    当盒子出现滚动条时,它被放在border和padding之间。滚动条的大小被包含在client width和client height中。滚动条不算在content box内。滚动条的大小以及当前滚动的位置可通过RenderObject获取。这个问题后续在单独章节中再详细说明。

    int scrollLeft() const;
    int scrollTop() const;
    int scrollWidth() const;
    int scrollHeight() const;

    盒子还有x和y的位置属性。这些位置相对于元素的父元素,父元素来决定盒子该放置在什么地方。这个规则存在许多例外情况,这也是渲染树中最令人困惑的地方。

    int xPos() const;
    int yPos() const;
  • 相关阅读:
    第二章、Redis入门介绍
    最高的牛
    增减序列
    激光炸弹
    分形之城
    约数之和
    奇怪的汉诺塔
    费解的开关
    递归实现排列型枚举
    递归实现组合型枚举
  • 原文地址:https://www.cnblogs.com/zjfazc/p/2573626.html
Copyright © 2020-2023  润新知