Webkit内核探究【2】——Webkit CSS实现
注:【转载请注明文章来源、保持原样】
出处:http://www.cnblogs.com/jyli/archive/2010/01/31/1660364.html 
作者:李嘉昱
CSS在Webkit中的实现属于相对独立的一个模块,注意这里说的是相对。
CSS在Webkit中的作用自然是不言而喻的,在Web早期,文档的结构和样式还未分离的那个时代,HTML担负了文档的结构和样式这两个双重任
务,即HTML既负责文档的结构,同时文档的样式也通过HTML中通过标签的属性来指定。可想而知,在那个时候HMTL页面的开发和使用比起现在而言是多
 么的不便。
不过仔细想想,这恐怕与当时的技术发展程度有着很大大关,首先,那个时候互联网远不像现在这样普及,另外,网页也远不如现在这样复杂,不像现在,
可以说,世界上信息的主要传播方式是以网页形式出现的,没数据说明,但我觉得至少趋势是这样的。
就这样,互联网在不断的前进之中,直到后来CSS的出现,大大的改进了Web的开发模式,从此,文档的结构和样式被清晰的一分为二。HTML主要负责文档
 的结构,而CSS则担负着文档的样式指定。
关于CSS的介绍网上已经有很多了,在这里将主要从Webkit实现的角度对其进行介绍。
CSS是什么
CSS是Cascading Style Sheets的缩写,按照官方定义,它可以被认为是一个样式表语言,它允许用户通过它来为结构化文档(HTML文档)指定样式。通过使用CSS用户可以将文档的内容和样式分离,从而简化Web页面的开发和维护。
既然说它是一个样式表语言,那么它就有相应的语法规则,规定了如何如何来书写一个样式表,让其作用与文档内容达到书写者想要的外观。CSS的语法规
 则是比较简单的, 自顶向下的来看,一个级联样式表(CSS)是由一系列的规则(rule)组成的,
每一条规则又是由一个选择器(selector)和若干条声明(Declearation)组成的。每条声明(Declearation)又是一个键值
对,由属性(property)和值(value)来组成,如下图所示。

原图片出处:http://dabrook.org/cc/Basic-Anatomy-of-a-CSS-Rule.png
从这里可以看到,语法是很简单的,使用起来也确实很简单。注意,我在这里只是说使用简单,就跟铅笔一样,谁都会用,铅笔的使用当然是简单的不能再简
单了,但是就是这样普通的工具,在专业人士和普通人的手里所能创造出的东西是截然不同的。所以我想说的是,你能很快的学会如何使用CSS并不代表你编织出
 漂亮的网页,它只是一个工具,能发挥到什么程度还得看人。
转回来,从其简单的语法来看,似乎是只要简单的将其转化为对应的程序设计模型即可,但实际中,CSS的实现还是比较复杂的,其复杂性就在于,CSS
本身的复杂程度,它定义了一系列的规则来决定为哪些元素来指定样式,以及样式的继承关系,哪些是继承的,哪些是非继承的,以及作用于同一个元素的多个样式
 的叠加,还有就是它对所有能指定的样式都有完整的对应的属性集。所以从实现的角度来看,一个完整的,兼容于标准的CSS实现,需要顾及到的东西还是很多
 的。
CSS实现模型
webkit css部分的实现代码为于目录webcore/css中,算是webkit中一个相对独立的模块,下面类图是我为了更好的了解css实现所作,大致勾勒出了CSS的内部实现。

用户所书写的css文档,最终会转化为webkit内部的模型表示,这里有几个比较重要的类。
(待续...)
CSS默认样式表
从Webkit CSS的实现可以看到,即使你不指定任何样式表,实际上当CSS模块运作起来的时候,它都会载入几张默认的样式表,要知道,在
CSSStyleSelector的构造函数中,总是会调用loadDefaultStyle()这个函数,其作用就是载入默认的样式表。
这些默认的样式表包含了一些HTML元素的最基本的样式信息。相信在使用css的用户中,大多数人都不会在对<div>指定样式的时候
 会为其添加一条display:block吧,是啊,几乎所有使用css
html的人都知道div是一个块级元素,所以没人会多此一举,但是通过了解其CSS模块的具体实现,我们可以知道,这些个默认的样式表其实就已经为我们
 指定了一系列我们认为的想当然的规则。
这四个默认样式表是
- html4UserAgentStyleSheet
 - quirksUserAgentStyleSheet
 - svgUserAgentStyleSheet
 - sourceUserAgentStyleSheet
 
额,从名字上大致也能够了解1, 2了吧,它们不是以文件形式存储,而是在CSS中以字符数组的形式出现,也就是说作为数据编到代码里面去了,应该是考虑到每次都要使用默认样式表而为了减少I/O造成的性能损失。
为了说明我前面所说的,这些默认样式表描述的都是些个关于HTML元素的最基本的信息,还是来看个例子吧,
比如说html4UserAgentStyleSheet,从名字上可以看到,这张应该就是传说中的浏览器默认样式表了。看看都有些啥吧,这里只截取个片段。
 html {
     display: block
  }
 head {
     display: none
  }
 meta {
     display: none
  }
 title {
     display: none
  }
 link {
     display: none
  }
 style {
     display: none
  }
 script {
     display: none
  }
 body {
     display: block;
     margin: 8px
  }
 p {
     display: block;
     margin: 1.0__qem 0px
  }
 div {
     display: block
  }
 layer {
     display: block
  }
从上面可以看出,真就是些最基本的属性的指定,如果没有这些默认值指定的话,用户还得自行添加这些规则,那会很麻烦。
其他几张表在此不作分析。
CSS解析
CSS使用的时候,只需要将按照其语法规范,书写一个规则集合,然后保存为一个.css文件,在html中引用即可,当然这里使用的是外部样式表的方式,只是使用CSS的一种方式,在这里我不打算讨论CSS的几种使用方式,所以都按外部的来。
那么这种按照语法规则书写的CSS样式表式如何转换为Webkit内部的CSS模型的呢,这自然需要通过词法语法分析。在这里,Webkit使用了 自动代码生成工具生成了相应的代码,也就是说词法分析和语法分析这部分代码是自动生成的,但它们不够完整,然后我们需要自己写一些配合性的代码才能让真个 CSS模块工作起来,说的再白一些,就是需要我们自己是写一些函数让那些个自动生成的代码来Call Back,用过其他各类解析器的朋友们应该很熟悉这个吧。如果谁对这部分代码有兴趣,可以研究一下。我倒是曾经为找一个跨平台的bug调过这部分代码,结 构还是蛮简单的,代码看起来稍多了些。入口是yylex和yyparse,有兴趣可以自己看看。
那么Webkit中实现的这些个Call Back们在哪里呢?就在CSSParser中了,显然,刨去生成的代码不说,需要手工完成的CSS解析代码部分就是这个了。CSS的一些解析功能的入口 也在此处,它们会调用lex,parse等生成代码。相对的,生成代码中需要的Call Back也需要在这里实现。
举例来说,现在可以来看一个较大单位的回调函数的实现,createStyleRule(),该函数将在一般性的规则需要被建立的时候调用。
CSSRule* CSSParser::createStyleRule(CSSSelector* selector)
{
CSSStyleRule* rule =;
if (selector) {
rule =new CSSStyleRule(styleElement);
m_parsedStyleObjects.append(rule);
rule->setSelector(sinkFloatingSelector(selector));
rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties));
}
clearProperties();
return rule;
}
从该函数的实现可以很清楚的看到,解析器达到某条件需要创建一个CSSStyleRule的时候将调用该函数,该函数的功能是创建一个 CSSStyleRule,并将其添加已解析的样式对象列表m_parsedStyleObjects中去,这里的对象就是指的Rule。那么如此一来, 经过这样一番解析后,作为输入的样式表中的所有Style Rule将被转化为Webkit 的内部模型对象CSSStyleRule对象,存储在m_parsedStyleObjects中,它是一个Vector。
像这样的函数还有createCharsetRule,createImportRule,createMediaRule等等,它们的作用大体上和createStyleRule类似,都是为创建Rule而准备的,只不过是不同类型的Rule。
了解了上面这些,大体上能够就能够了解CSS解析式怎么运作的。但是我们解析所要的结果是什么?通过调用CSSStyleSheet的 parseString函数,上CSS解析过程将启动,解析完一遍后,所有的Rule都将存储在对应的CSSStyleSheet对象中。但是这个时候的 规则依然是不易于处理的,需要将之转换为CSSRuleSet,CSSRuleSet提供了一个addRulesFromSheet方法,能将 CSSStyleSheet中的rule转换为CSSRuleSet中的rule,这样所有的纯样式规则都会放存储在对应的集合当中,这种集合的抽象就是 CSSRuleSet。以后就可以基于这些个CSSRuleSet来决定每个页面中的元素的样式了,后面会有介绍。
(...)
 
CSS如何作用于Render Tree
所谓的作用于Render Tree其实是指基于上面的解析成果来为相应的Render Object来指定特定的样式,这个样式的抽象就是RenderStyle(关于Render Tree可参见我的其他文章)。
(...)
 
(待续..)
Webkit内核探究【2】——Webkit CSS实现的更多相关文章
- Webkit内核探究【1】——Webkit简介
		
出处:http://www.cnblogs.com/jyli/archive/2010/01/31/1660355.html作者:李嘉昱 研究Webkit内核已经有一段时间了,在这期间我花了很多时间去 ...
 - Webkit内核探究【2】——css简介
		
注:[转载请注明文章来源.保持原样] 出处:http://www.cnblogs.com/jyli/archive/2010/01/31/1660364.html 作者:李嘉昱 CSS在Webkit中 ...
 - 【转】.NET多种WebKit内核/Blink内核浏览器初步测评报告
		
第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告 本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23590 报告研究时间:2013-10- ...
 - 从webkit内核简单看css样式和css规则优先级(权重)
		
目录 webkit中样式相关类及类间关系 样式规则匹配 权重(优先级)计算 权重相同时的覆盖原则 webkit中样式相关类及类间关系 资料来源: <webkit技术内幕> 结构相关类: 1 ...
 - 八大Webkit内核浏览器
		
列举出时下最流行的Webkit内核浏览器,所以我们并不会做出评测和对比.PS:本文列举的浏览器有一部分为IE+Webkit双核浏览器,如果您对其他IE内核浏览器很感兴趣<抛弃数据!用体验和感觉告 ...
 - [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
		
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
 - WebKit内核分析之Page
		
参考地址:http://blog.csdn.net/dlmu2001/article/details/6213377 注:本系列博客是在原博主博客基础上增加了自己的理解和片段,可以看源博文获得清晰的结 ...
 - IE8+等兼容、360调用webkit内核小记
		
首先是处理IE8.9等的兼容问题,注意以下几点: 1,尽可能严格要求自己使用w3c推荐的方式编写html/css 2,在html页面顶部添加<!DOCHTML html>,不清楚请查看参考 ...
 - 探索WebKit内核(一)------ 菜鸟起步
		
为什么搞WebKit 如今研究WebKit的人越来越多,俺不能免俗,也增加当中.WebKit的火爆也是得益于浏览器和WebOS的混战,随着Palm WebOS, Chrome OS, Firefox ...
 
随机推荐
- 【转】Lombok:让JAVA代码更优雅
			
原文地址:http://blog.didispace.com/java-lombok-1/ 关于Lombok,其实在网上可以找到很多如何使用的文章,但是很少能找到比较齐全的整理.我也一直寻思着想写一篇 ...
 - 'Project Name' was compiled with optimization
			
'Project Name' was compiled with optimizationhtml, body {overflow-x: initial !important;}html { font ...
 - textmate常用快捷键备忘
			
视图切换 Ctrl + Cmd + F # 折叠第三层 代码编辑 Cmd + Shift + V # 按照历史拷贝顺序来粘贴 Ctrl + Cmd + Option + V # 显示剪贴板 Cmd + ...
 - [mqtt]mqtt嵌入式移植
			
github eclipse paho source code: https://github.com/mqtt/mqtt.github.io/wiki/libraries STM32 mqtt移植: ...
 - connect设置超时的方法
			
在使用TCP的connect连接服务器时,在默认情况下系统使用的是阻塞式socket,如果服务器当前不可用,则connect会等待知道超时时间到达,而这个超时时间是系统内核规定的,并不能使用setSo ...
 - sam9260 adc 测试
			
/* * adc_test.c * * Copyright (C) 2007 Mengrz */ #include <stdio.h> #include <stdlib.h> ...
 - opencv中图像伪彩色处理(C++ / Python)
			
使用OpenCV的预定义的颜色映射来将灰度图像伪彩色化. 1. colormap(色度图)是什么? 假设我们想在地图上显示美国不同地区的温度.我们可以把美国地图上的温度数据叠加为灰度图像——较暗的区域 ...
 - Android文档 - 账户管理器概述
			
账户管理器概述 这个类提供了访问到 用户在线账户的集中式注册中心 的能力.用户为每账户输入一次 认证信息(credentials,包含用户名和密码),过过 点击一次(one-click)完成认证的方式 ...
 - jQuery(七):节点操作
			
jQuery中节点操作主要分为以下几种: 查找节点. 创建节点. 插入节点. 替换节点. 复制节点. 删除节点. 一.查找节点 示例: <!DOCTYPE html> <html l ...
 - jquery 中 $ 符的意义
			
$()就是一个函数名,别把它想得这么神奇.$就是一个字符,比如function a(){};function $(){};是一样的.只是jquery中习惯用$函数来作为对象化的入口而已.你也可以把jq ...