注:【转载请注明文章来源、保持原样】css
出处:http://www.cnblogs.com/jyli/archive/2010/01/31/1660364.html
做者:李嘉昱html
CSS在Webkit中的实现属于相对独立的一个模块,注意这里说的是相对。web
CSS在Webkit中的做用天然是不言而喻的,在Web早期,文档的结构和样式还未分离的那个时代,HTML担负了文档的结构和样式这两个双重任 务,即HTML既负责文档的结构,同时文档的样式也经过HTML中经过标签的属性来指定。可想而知,在那个时候HMTL页面的开发和使用比起如今而言是多 么的不便。数组
不过仔细想一想,这恐怕与当时的技术发展程度有着很大大关,首先,那个时候互联网远不像如今这样普及,另外,网页也远不如如今这样复杂,不像如今, 能够说,世界上信息的主要传播方式是以网页形式出现的,没数听说明,但我以为至少趋势是这样的。 就这样,互联网在不断的前进之中,直到后来CSS的出现,大大的改进了Web的开发模式,今后,文档的结构和样式被清晰的一分为二。HTML主要负责文档 的结构,而CSS则担负着文档的样式指定。浏览器
关于CSS的介绍网上已经有不少了,在这里将主要从Webkit实现的角度对其进行介绍。app
CSS是什么svg
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模块的具体实现,咱们能够知道,这些个默认的样式表其实就已经为咱们 指定了一系列咱们认为的想固然的规则。
这四个默认样式表是
额,从名字上大体也可以了解1, 2了吧,它们不是以文件形式存储,而是在CSS中以字符数组的形式出现,也就是说做为数据编到代码里面去了,应该是考虑到每次都要使用默认样式表而为了减小I/O形成的性能损失。
为了说明我前面所说的,这些默认样式表描述的都是些个关于HTML元素的最基本的信息,仍是来看个例子吧,
好比说html4UserAgentStyleSheet,从名字上能够看到,这张应该就是传说中的浏览器默认样式表了。看看都有些啥吧,这里只截取个片断。
1 html { 2 display : block 3 } 4 5 head { 6 display : none 7 } 8 9 meta { 10 display : none 11 } 12 13 title { 14 display : none 15 } 16 17 link { 18 display : none 19 } 20 21 style { 22 display : none 23 } 24 25 script { 26 display : none 27 } 28 29 body { 30 display : block ; 31 margin : 8px 32 } 33 34 p { 35 display : block ; 36 margin : 1.0__qem 0px 37 } 38 39 div { 40 display : block 41 } 42 43 layer { 44 display : block 45 }
从上面能够看出,真就是些最基本的属性的指定,若是没有这些默认值指定的话,用户还得自行添加这些规则,那会很麻烦。
其余几张表在此不做分析。
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(),该函数将在通常性的规则须要被创建的时候调用。
1 CSSRule * CSSParser::createStyleRule(CSSSelector * selector) 2 { 3 CSSStyleRule * rule = 0 ; 4 if (selector) { 5 rule = new CSSStyleRule(styleElement); 6 m_parsedStyleObjects.append(rule); 7 rule -> setSelector(sinkFloatingSelector(selector)); 8 rule -> setDeclaration( new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties)); 9 } 10 clearProperties(); 11 return rule; 12 }
从该函数的实现能够很清楚的看到,解析器达到某条件须要建立一个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可参见个人其余文章)。
(...)
(待续..)