浏览器-06 HTML和CSS解析2

选择器

  • 其实现由CSSSelector类来完成;
  • CSSSelector的作用是储存从解析器生成的结果信息;
  • 这里匹配指的是当需要为每个DOM中的节点计算样式时,WebKit需要根据当前的节点信息来从规则列表中找到能够符合调节的规则,并把规则中的属性列表提取出来生成节点的样式信息;

应用到具体元素上

  • StyleResolver是管理类,负责根据样式规则为每一个Document中的元素匹配相应的样式属性,和Document节点一一对应;即当WebKit为每个Document创建一个StyleResolver对象,就为所有该Document中的节点计算样式,并将其结果保存到RenderStyle对象中;大致步骤
    * 创建一个新的RenderStyle对象从它的父亲那里继承它的一切可以继承的属性;
    * 如果是link类元素,设置link属性;
    * 从已知规则中找到匹配到的属性
    * 将匹配到的属性应用到RenderStyle对象中;
    * 为该DOM元素的RenderStyle做一些修正工作;
    * 清理StyleResolver,为下次匹配请求做准备;

  • RenderStyle是元素所有样式属性的内部表示;为了节约空间,WebKit将属性分为常用属性和非常用属性;非常用属性会进行分组合并,并且仅在需要时创建;该对象在被StyleResolver创建后由该元素所对应的RenderObject所拥有;

  • 元素在匹配生成其样式属性值之后,RenderStyle对象被RenderObject所获得,这个触发一个重新绘制的动作, WebKit此时可以根据样式属性值来计算它的布局和显示;

JavaScript设置样式

  • 大致过程:JavaScript引擎调用设置属性值的公共处理函数,然后该函数调用属性值解析函数;
  • 将解析后的信息设置到元素的style属性的样式中,设置该元素需要重新计算styleinvalidate它的style属性;
  • 在这之后,重新绘制请求被处理时,WebKit先会重新计算布局,而后在渲染相应的区域;

CSS3 变形(transform)、变换(transition)和动画(animation)

  • 上面例子的三种树结构中:元素P的内容会被包􏰁在中间的RenderLayer中,Div元素的内容会被会包􏰁单独的最下面的RenderLayer中,因为Div元素的需要做CSS3D变形;

  • RenderLayer会有一个后端存储空间,Chromium中是一个FrameBuffer,该层会转成一个Texture,那些CSS3的变形,变换和动画效果将作用于该 Texture上,而后绘制在网页的framebuffer中;
  • 变形比较简单,WebKitChromium内部有一个Matrix来表示平移,旋转,缩放和扭曲等变形,因为OpenGL有直接对变形的支持,所以只需创建响应的 OpenGL变换操作即可;
  • 变换和动画的实现大致相同,前面解析的过程一样,其结果会保存于Animation对象中;
    * 在chromium的实现中,chromium compositor中有两个主要类对其提供支持,一个是CCLayerAnimationController,一个是CCActiveAnimation;
    * 前者是控制动画的行为,后者则是包􏰁动画相关参数和状态;

WebKit布局 (Layout)

概述

  • 在渲染每个元素之前,渲染引擎必须知道它的位置大小等布局信息;计算这些信息的过程称之为布局;
  • 布局计算介于DOM树、Render树的创建和元素渲染之间;
  • 布局根据其计算的范围大致可以分为:
    * 第一类是对整个Render树进行的计算;
    * 第二类是对Render树中某个子树 的计算,常见于文本元素或者是overflow:auto块的计算,这种情况一般是其子树布局的改变不会影响其周围元素的 布局,因而不需要重新计算更大范围内的布局;

箱子模型

  • CSS布局计算是基于箱子模型的,其基本构成是一个矩形区域,包􏰁了外边距,内边距,边框和内容;

包含块

  • 当需要计算元素box的位置和大小的时,需要计算它和另外一个矩形区域的相对位置,这个矩形区域称为该元素
    的包􏰁块;
    * 根元素的包􏰁块称为初始包􏰁块,通常它的大小就是可视区域(viewport)的大小;
    * 对于其他位置属性设置为static或者relative元素,它的包􏰁块就是的最近的祖先的箱子模型中的内容区域;
    * 如果元素的位置属性为fixed,其脱离文档,固定在可视区域的某个特定位置;
    * 如果元素的位置属性为absolute,其包􏰁块由最近的包􏰁属性absolute, relative或者fixed的祖先决定,具体规则:
    * 如果其是一个inline元素,那么元素的包􏰁块是该包祖先的第一个和最后一个inline盒子的内边距的区域;
    * 否则,则是由该祖先的内边距所包围的区域;

  • webkit中理解:
    * Render节点的包􏰁块是该节点的负责决定该节点的祖先节点对应的块区域;
    * 根节点RenderView表示的就是初始包􏰁块,其初始大小始终是可视区域的大小;

布局计算

  • 布局计算的相关信息都保存在RenderStyle对象中,该对象属于Render节点;
  • RenderStyle就是包􏰁各个样式的属性值;同时,Render节点也包􏰁一个位数组,该数组会保存一些用来表示是否需要重新计算布局等信息;
  • 计算布局的主要由RenderObject中的layout方法来完成:
    * 首先,layout会判断Render节点是否需要重新计算,通常这通过检查位数组中的相应标记位,子节点是否需要计算布局等来确定;
    * 一般来说,初始显示,:可视区域变化,样式值变化(如动画,JavaScript操作样式值)等都会需要重新计算布局;
    * 其次,它会遍历其每一个子节点,依次计算它们的布局;
    * 然后,对于每一个元素,它会实现自己的layout方法,根据特定的算法来计算该类型元素的布局;
    * 如果页面元素定义了其自己的宽高,那么webkit按照其定义的宽高来确定其大小,而对于象文本节点这样的Inline元素则需要结合其字体大小及文字的多少等来确定其对应的宽高;
    * 如果页面元素所确定的宽高超过了布局容器包􏰁块所能提供的宽高,同时其overflow属性为visibleauto,则会提供滚动条来保证显示其所有内容;
    * 除非定义了页面元素 的宽高,一般说来页面元素的宽高是在布局的时候通过相关计算得出来;
posted @ 2015-12-11 23:21  JinksPeng  阅读(222)  评论(0编辑  收藏  举报