转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7685517

# CSS在WebKit和Chromium中的实现

## 概述

前面章节介绍了CSS的三种基本要素,大概可以分成选择器,各种基本样式和CSS3引入的变形、变换和动画等。本章在此基础上,着重介绍CSS是如何在WebKit和Chromium得到支持的。首先介绍的是CSS解析器,而后分别阐述上面三种基本要素如何在WebKit和Chromium中实现的。

接前面章节,这里仍然以之前的CSS例子为基础来介绍本章的内容。为方便起见,依旧包含该例子,如下图所示。

## CSS解析器

CSS的词法其实并不复杂,其分析工作由bison完成,具体实现可以在文件CSSGrammar.y中找到,详细过程这里不在赘述。其主要工作是解析词法并调用CSSParser的回调函数来生成结果,例如上例中的第4行到第17行,第4行首先是识别选择器,后面是各个属性的识别,最后,这些全部构成了基本的StyleRule类型(关于类型会在后面介绍),所以调用CSSParser的createStyleRule函数,该函数将选择器和属性列表的中间表示最后处理生成其内部表示保存在一个规则StyleRule中。对于其他的类型,作类似的处理。

解析器对上层的接口是CSSParser,所有任务均有其处理。那么上面例子中有哪些场景会需要创建CSSParser的实例呢?显而易见地有两处地方,第一个是第4行到第17行,当DOM建立好之后在创建RenderObject的时候会调用CSSParser;第二个是第29行,在该段JavaScript代码被执行时,JavaScript引擎会间接调用CSSParser为元素的属性style解析。但其实还有一个地方会使用到CSSParser。

实际上WebKit(其他渲染引擎应该也类似吧K)会为每个网页设置一个缺省的样式,这决定了你所没有设置的元素及其它们的属性缺省值和将要显示的效果。通常来讲,不同的WebKit的移植(port)会有不同的缺省样式。

解析后的结果应该是一系列的样式规则,下面让我们来看看这些规则在WebKit中的内部表示。

## 样式的内部表示

被解析后的CSS样式其实就是一组样式规则,每一个规则包含一组选择器和一组样式属性。如前面例子中第4行到第17行所示。这些数据在WebKit中都有相应的内部表示,为了便于理解,下图给出了CSS的表示和内部结果表示的对应图。

值得一提的是选择器部分,上图是一个选择器列表,这在现实中是比较常见的。举个例子, a[class=abc]其实是两个选择器,第一个是’a’,它一个标签选择器;第二个是’[class=abc]’,它是一个属性选择器。

这里例子中的样式规则是一种基本的样式类型。CSS的标准包含了多种规则类型:

Style:这个是基本类型,一般大多数规则属于这个类型;

Import:是WebKit中为方便引入的,其对应的是一个导入CSS文件的Style元素

Media: 对应于CSS标准中的@media类型

Fontface: CSS3新引入的自定义字体的规则类型

Page: 对于CSS标准中的@page类型

Keyframes: WebKit的@-webkit-key-frames类型,可以用来指定特定帧的样式属性信息

Region:对CSS标准正在进行中的Regions的支持,这方便了开发者对页面进行分区域来排版。详见参考文献2.

下图给出了这些类型在WebKit中的定义及其关系。

这里有必要解释一下StyleRuleImport类,这个一个伪类型,CSS中并没有该类型的定义,只是WebKit处理CSS文件方便引入的。该类需要两个类来辅助完成,一个是StyleSheetContents类,就是CSS文件中各个规则的处理和内部表示,这些规则被称为子规则,构成一个列表;另外一个是CSSStyleSheet,该类是个包装类,代表CSS文件,包含一个StyleSheetContents对象。

## 选择器(CSSSelector类)

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

在CSS介绍那一章中,我们知道有多达42种选择器类型,例如。在WebKit的CSSSelector类中,它们被称为伪类型(PseudoType),其含义是表示CSS标准中定义的类型,而主要用于匹配算法的类型定义为Match,它包含Id, Class, Extract, Set, List, Hyphen,PseudoClass,PseudoElement, Contain, Begin, End, PagePseudoClass。这些类型是通过抽象标准中的类型而得来,例如:first-of-type,:last-of-type,:only-of-typed等等都属于PseudoClass。具体的匹配算法参考代码(文件ElementRuleCollector.cpp),这里不在赘述。

### StyleResolver和RenderStyle

在样式规则解析完成之后,剩下的问题是如何把这样规则应用到具体的元素上。这就涉及到两个主要的类:StyleResolver和RenderStyle。

StyleResolver是管理类,其负责根据样式规则为每一个Document中的元素匹配响应的样式属性,它和Document 节点是一一对应关系,也就是说WebKit为每个Document创建一个StyleResolver对象,为所有该Document中的节点计算样式,并将其结果保存到RenderStyle对象中。

RenderStyle是元素所有样式属性的内部表示。由于其包含了所有样式属性,为了节约空间,WebKit将属性分为两种类型:常用属性和非常用属性。非常用属性会进行分组合并,并且仅在需要时创建,这相对有效地节约了内存。该对象在被StyleResolver创建后由该元素所对应的RenderObject所拥有。

那么StyleResolver是如何为一个DOM元素生成RenderStyle对象的呢?大致地有如下几个主要步骤:

1.      首先创建一个新的RenderStyle对象

2.      从它的父亲那里继承它的一切可以继承的属性

3.      如果是link类元素,设置link属性

4.      而后是样式规则的匹配,从已知规则中找到匹配到的属性

5.      将匹配到的属性应用到RenderStyle对象中

6.      为该DOM元素的RenderStyle做一些修正工作

7.      清理StyleResolver,为下次匹配请求做准备

## RenderStyle 和RenderObject

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

##JavaScript设置样式

JavaScript有能力设置任何元素的样式值,如例子中第29行所示,其原则是覆盖样式中同一属性的值。大致的过程是,JavaScript引擎调用设置属性值的公共处理函数,然后该函数调用属性值解析函数,在这个例子中则是CSS的JS绑定函数,而后将解析后的信息设置到元素的style属性的样式webkitTransform中,然后设置该元素需要重新计算style和invalidate它的style属性,如下图所示。

在这之后,重新绘制请求被处理时,WebKit先会重新计算布局,而后在渲染相应的区域。

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

在WebKit渲染基础中,我们介绍了DOM数,Render树和RenderLayer树,根据WebKit的设计原则,可以知道上面HTML例子的三种树结构如下图所示。也就是说,元素P的内容会被包含在中间的RenderLayer中,Div元素的内容会被会包含单独的最下面的RenderLayer中,因为Div元素的需要做CSS的3D变形。

我们知道RenderLayer会有一个后端存储空间,Chromium中是一个FrameBuffer,该层会转成一个Texture,那些CSS3的变形,变换和动画效果将作用于该Texture上,而后绘制在网页的framebuffer中。

变形比较简单,WebKit和Chromium内部有一个Matrix来表示平移,旋转,缩放和扭曲等变形,因为OpenGL有直接对变形的支持,所以只需创建响应的OpenGL变换操作即可。

变换和动画的实现大致相同,前面解析的过程跟其他属性没有区别,其结果会保存于Animation对象中。在chromium的实现中,CC(chromium compositor, 前面介绍过)中有两个主要类对其提供支持,一个是CCLayerAnimationController,一个是CCActiveAnimation。前者是控制动画的行为,后者则是包含动画相关参数和状态。这一部分其实很复杂,有兴趣的读者可以自行阅读代码。

## 源文件目录

third_party/WebKit/Source/WebCore/css/

与CSS解析,内部表示生成等一系列相关的类

third_party/WebKit/Source/WebCore/rendering/style

渲染所需要的样式的支持类,其依赖于CSS解析器及其结果

## 参考文献

1.      http://www.w3schools.com/css

2.      http://dev.w3.org/csswg/css3-regions/

By yongsheng@chromium.org

理解WebKit和Chromium: WebKit的CSS实现相关推荐

  1. 理解WebKit和Chromium: WebKit渲染基础

    转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7292131 # WebKit渲染基础 ## 概述 WebKit是一个渲染引擎,而 ...

  2. 理解WebKit和Chromium: WebKit, WebKit2, Chromium和Chrome介绍

    转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7292164 ##概述 在介绍本系列各个专题之前,有必要先解释一下极其容易混淆的几 ...

  3. 理解WebKit和Chromium: WebKit和Chromium组成

    转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7300074 在"WebKit,WebKit2,Chromium和Chr ...

  4. 理解WebKit和Chromium: WebKit和Blink

    转载请注明出处:http://blog.csdn.net/milado_nju/ 关注Web和HTML5领域的人最近应该都有了解WebKit项目的重磅消息,那就是Google退出WebKit项目,创建 ...

  5. 理解WebKit和Chromium: 前言

    注:朱永盛老师的<理解WebKit和Chromium>系列非常经典,在这里转发一下目录. 转载请注明原文地址:http://blog.csdn.net/milado_nju 这几年来,我阅 ...

  6. 理解WebKit和Chromium: Canvas2D及其实现

    转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7293012 # Canvas 2D及其在WebKit和Chromium中的实现 ...

  7. 理解WebKit和Chromium: Content API和CEF3

    转载请注明原文地址:http://blog.csdn.net/milado_nju/article/details/7455373 # Content API及CEF3 ## 概述 相信你一定看过下面 ...

  8. 【读书笔记】【WebKit技术内 幕(二)】Chromium Webkit资源加载与网络栈、DOM树、HTML解释器、影子DOM、CSS解释器和样式布局、网页层次与渲染、绘图上下文、

    文章目录 前言 Something great 第4章 资源加载和网络栈 Webkit 资源加载 Chromium多进程资源加载 Chromium 网络栈 第5章 HTML解释器和DOM模型 DOM模 ...

  9. (转) 理解WebKit和Chromium

    WebKit是一个渲染引擎,而不是一个浏览器,它专注于网页内容展示,其中渲染是其中核心的部分之一.本章着重于对渲染部分的基础进行一定程度的了解和认识,主要理解基于DOM树来介绍Render树和Rend ...

最新文章

  1. Servicehot和你说说运维自动化的那些事儿
  2. 杭州云栖大会阿里云放大招,8K远程医疗会诊引关注
  3. GoldenGate 12.3 MA架构介绍系列(4)–Restful API介绍
  4. 大学计算机基础试题第一套,大学计算机基础试题及答案(完整版)
  5. Trapcode Particular 5 - Particle
  6. CAN协议详解-01
  7. Java制作五子棋人机对战
  8. 计算机等级考试数据库三级模拟题7
  9. 增加虚拟android内存,怎么给安卓手机增加虚拟内存?
  10. 远程桌面连接时无法访问远程计算机的计算机属性提示系统调用失败,远程过程调用失败【应对技巧】...
  11. b站React禹哥版视频笔记-React应用(基于react脚手架)
  12. 集合 Collection
  13. 【装Linux系统时卡在logo处】禁用独显驱动
  14. php 歌词同步,HTML5实践之歌词同步播放器的示例代码分享
  15. java des 中文乱码_网络上DesUtil.java关于汉字加密解密出现乱码的问题
  16. QIIME2-傻瓜式安装
  17. android 记录路线轨迹_Android定位并记录轨迹项目源码
  18. zookeeper疑难杂症
  19. 【第134期】 游戏策划:我录用了一位待业半年的往届生
  20. 马达震动测试软件,电机震动如何测试

热门文章

  1. 微信小程序调用局域网服务器,微信小程序中使用mdns api扫描局域网内的打印机...
  2. 你应该考这些证书,特别是在校生
  3. Python旅游景点推荐系统 爬虫 酒店 旅游新闻
  4. AutoCAD 2013 .net插件创建向导现在支持Map 3D,Civil 3D,AutoCAD Architecture 和AutoCAD MEP...
  5. 哈工大2018年秋计算机系统复习
  6. 已解决使用Python分割图片
  7. 跳妹儿学编程之ScratchJr(六):第一个ScratchJr程序HelloWorld以及ScratchJr程序如何执行
  8. 天猫精灵 python_树莓派通过snowboy唤醒引擎(Python2、Python3的都可以),自定义唤醒词、关键字,达到小爱同学、天猫精灵一样的唤醒方式的全套教程...
  9. vue实现轮播图(跑马灯、无缝滚动、无限切换效果)
  10. 【华为】MPLS及MPLS VPN概念