Webkit内核探究——Webkit CSS实现

news2024/11/15 11:12:15

文章目录

  • 前言
  • 1、CSS是什么
  • 2、CSS实现模型
  • 3、CSS默认样式表
  • 4、CSS解析
  • 5、CSS如何作用于Render Tree

前言

CSSWebkit中的实现属于相对独立的一个模块,注意这里说的是相对。

CSSWebkit中的作用自然是不言而喻的,在Web早期,文档的结构和样式还未分离的那个时代,HTML担负了文档的结构和样式这两个双重任 务,即HTML既负责文档的结构,同时文档的样式也通过HTML中通过标签的属性来指定。可想而知,在那个时候HMTL页面的开发和使用比起现在而言是多 么的不便。

不过仔细想想,这恐怕与当时的技术发展程度有着很大大关,首先,那个时候互联网远不像现在这样普及,另外,网页也远不如现在这样复杂,不像现在, 可以说,世界上信息的主要传播方式是以网页形式出现的,没数据说明,但我觉得至少趋势是这样的。 就这样,互联网在不断的前进之中,直到后来CSS的出现,大大的改进了Web的开发模式,从此,文档的结构和样式被清晰的一分为二。HTML主要负责文档 的结构,而CSS则担负着文档的样式指定。

关于CSS的介绍网上已经有很多了,在这里将主要从Webkit实现的角度对其进行介绍。

1、CSS是什么

CSSCascading Style Sheets的缩写,按照官方定义,它可以被认为是一个样式表语言 ,它允许用户通过它来为结构化文档(HTML文档)指定样式。通过使用CSS用户可以将文档的内容和样式分离,从而简化Web页面的开发和维护。

既然说它是一个样式表语言,那么它就有相应的语法规则,规定了如何如何来书写一个样式表,让其作用与文档内容达到书写者想要的外观。CSS的语法规 则是比较简单的, 自顶向下的来看,一个级联样式表(CSS)是由一系列的规则(ruler)组成的, 每一条规则又是由一个选择器(selector)和若干条声明(Declearation)组成的。每条声明(Declearation)又是一个键值 对,由属性(property)和值(value)来组成,如下图所示。
在这里插入图片描述
从这里可以看到,语法是很简单的,使用起来也确实很简单。注意,我在这里只是说使用简单,就跟铅笔一样,谁都会用,铅笔的使用当然是简单的不能再简 单了,但是就是这样普通的工具,在专业人士和普通人的手里所能创造出的东西是截然不同的。所以我想说的是,你能很快的学会如何使用CSS并不代表你编织出 漂亮的网页,它只是一个工具,能发挥到什么程度还得看人。

转回来,从其简单的语法来看,似乎是只要简单的将其转化为对应的程序设计模型即可,但实际中,CSS的实现还是比较复杂的,其复杂性就在于,CSS 本身的复杂程度,它定义了一系列的规则来决定为哪些元素来指定样式,以及样式的继承关系,哪些是继承的,哪些是非继承的,以及作用于同一个元素的多个样式 的叠加,还有就是它对所有能指定的样式都有完整的对应的属性集。所以从实现的角度来看,一个完整的,兼容于标准的CSS实现,需要顾及到的东西还是很多 的。

2、CSS实现模型

webkit css部分的实现代码为于目录webcore/css中,算是webkit中一个相对独立的模块,下面类图是我为了更好的了解css实现所作,大致勾勒出了CSS的内部实现。
在这里插入图片描述
用户所书写的css文档,最终会转化为webkit内部的模型表示,这里有几个比较重要的类。

3、CSS默认样式表

Webkit CSS的实现可以看到,即使你不指定任何样式表,实际上当CSS模块运作起来的时候,它都会载入几张默认的样式表,要知道,在 CSSStyleSelector的构造函数中,总是会调用loadDefaultStyle() 这个函数,其作用就是载入默认的样式表。

这些默认的样式表包含了一些HTML元素的最基本的样式信息。相信在使用css的用户中,大多数人都不会在对

指定样式的时候 会为其添加一条 display:block吧,是啊,几乎所有使用 css html的人都知道 div是一个块级元素,所以没人会多此一举,但是通过了解其 CSS模块的具体实现,我们可以知道,这些个默认的样式表其实就已经为我们 指定了一系列我们认为的想当然的规则。

这四个默认样式表是:

  • html4UserAgentStyleSheet。
  • quirksUserAgentStyleSheet。
  • svgUserAgentStyleSheet。
  • sourceUserAgentStyleSheet。

额,从名字上大致也能够了解1, 2了吧,它们不是以文件形式存储,而是在CSS中以字符数组的形式出现,也就是说作为数据编到代码里面去了,应该是考虑到每次都要使用默认样式表而为了减少I/O造成的性能损失。

为了说明我前面所说的,这些默认样式表描述的都是些个关于HTML元素的最基本的信息,还是来看个例子吧,

比如说html4UserAgentStyleSheet,从名字上可以看到,这张应该就是传说中的浏览器默认样式表了。看看都有些啥吧,这里只截取个片段。

 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  }

从上面可以看出,真就是些最基本的属性的指定,如果没有这些默认值指定的话,用户还得自行添加这些规则,那会很麻烦。

其他几张表在此不作分析。

4、CSS解析

CSS使用的时候,只需要将按照其语法规范,书写一个规则集合,然后保存为一个**.css文件,在html中引用即可,当然这里使用的是外部样式表的方式,只是使用CSS的一种方式,在这里我不打算讨论CSS**的几种使用方式,所以都按外部的来。

那么这种按照语法规则书写的CSS样式表式如何转换为Webkit内部的CSS模型的呢,这自然需要通过词法语法分析。在这里,Webkit使用了 自动代码生成工具生成了相应的代码,也就是说词法分析和语法分析这部分代码是自动生成的,但它们不够完整,然后我们需要自己写一些配合性的代码才能让真个 CSS模块工作起来,说的再白一些,就是需要我们自己是写一些函数让那些个自动生成的代码来Call Back,用过其他各类解析器的朋友们应该很熟悉这个吧。如果谁对这部分代码有兴趣,可以研究一下。我倒是曾经为找一个跨平台的bug调过这部分代码,结 构还是蛮简单的,代码看起来稍多了些。入口是yylexyyparse,有兴趣可以自己看看。

那么Webkit中实现的这些个Call Back们在哪里呢?就在CSSParser中了,显然,刨去生成的代码不说,需要手工完成的CSS解析代码部分就是这个了。CSS的一些解析功能的入口 也在此处,它们会调用lex,parse等生成代码。相对的,生成代码中需要的Call Back也需要在这里实现。

举例来说,现在可以来看一个较大单位的回调函数的实现,createStyleRule(),该函数将在一般性的规则需要被建立的时候调用。

  CSSRule* CSSParser::createStyleRule(CSSSelector* selector)
  {
     CSSStyleRule* rule = 0;
       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。

像这样的函数还有createCharsetRulecreateImportRulecreateMediaRule等等,它们的作用大体上和createStyleRule类似,都是为创建Rule而准备的,只不过是不同类型的Rule

了解了上面这些,大体上能够就能够了解CSS解析式怎么运作的。但是我们解析所要的结果是什么?通过调用CSSStyleSheetparseString函数,上CSS解析过程将启动,解析完一遍后,所有的Rule都将存储在对应的CSSStyleSheet对象中。但是这个时候的 规则依然是不易于处理的,需要将之转换为CSSRuleSetCSSRuleSet提供了一个addRulesFromSheet方法,能将 CSSStyleSheet中的rule转换为CSSRuleSet中的rule,这样所有的纯样式规则都会放存储在对应的集合当中,这种集合的抽象就是 CSSRuleSet。以后就可以基于这些个CSSRuleSet来决定每个页面中的元素的样式了,后面会有介绍。

5、CSS如何作用于Render Tree

所谓的作用于Render Tree其实是指基于上面的解析成果来为相应的Render Object来指定特定的样式,这个样式的抽象就是RenderStyle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/739601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【运维工程师学习五】数据库

【运维工程师学习五】数据库 1、常用的关系型数据库2、C/S结构3、MariaDB图形客户端4、安装MariaDB5、启动MariaDB及验证启动是否成功6、验证启动——端口7、验证启动——进程8、MariaDB配置文件路径主配置文件解读: 9、MariaDB的配置选项10、MariaDB客户端连接1、在…

Windows下 Oracle 12c 安装保姆级图文详解

Windows下 Oracle 12c 安装步骤如下: 1、将压缩包“winx64_12c_database_1of2.zip“和“winx64_12c_database_2of2.zip”解压到同一目录“database”目录。 2、双击“database”目录下的“setup.exe",软件会加载并初步校验系统是否可以达到了数据…

华为云出品《深入理解高并发编程:Java线程池核心技术》电子书发布

系统拆解线程池核心源码的开源小册 透过源码看清线程池背后的设计和思路 详细解析AQS并发工具类 点击下方链接进入官网,右上角搜索框搜索“《深入理解高并发编程:Java线程池核心技术》” 即可获取下载。 https://auth.huaweicloud.com/authui/login…

01-线性表 (数据结构和算法)

要点: 程序 数据结构 算法 一、数据结构的概述 程序 数据结构 算法 数据结构:计算机存储、组织数据的方式 算法:处理数据的方式 1.1 基本概念和术语 1、数据 数据(data):所有能够输入到计算机中…

【Method】稀疏与压缩感知 | 图像稀疏性及压缩感知方法白话讲解

【Method】稀疏与压缩感知 | 图像稀疏性及压缩感知方法白话讲解 文章目录 【Method】稀疏与压缩感知 | 图像稀疏性及压缩感知方法白话讲解1. 为什么图像是可压缩的:图像空间的广阔2. 什么是Sparsity?3.压缩感知:简介4.压缩感知:数…

matlab学习指南(3):最全MATLAB工具箱Toolbox下载地址大汇总

🌅*🔹** φ(゜▽゜*)♪ **🔹*🌅 欢迎来到馒头侠的博客,该类目主要讲数学建模的知识,大家一起学习,联系最后的横幅! 喜欢的朋友可以关注下,私信下次更新不迷路&#xff0…

火车头采集器AI伪原创【php源码】

本文介绍火车头采集器AI伪原创,对于新媒体从业者来说,会写文章是最基本的职业技能,而伪原创是我们经常使用的技能。今天我要讲的是SEO标兵如何在伪原创上创作文章。 首先,原创性永远是最好的,更受读者欢迎。伪原创的出…

Microsoft Dynamics 365:VS2019引用BC发布的SOAP服务

1、搜索网页服务 2、点击新建 3、选择对象类型:页面、单元、查询,输入ID,勾选即可发布服务 4、复制SOAP URL到浏览器里看看是否可以访问,这样就OK的 5、 右键添加服务引用 6、选择高级 7、添加web引用 8、服务地址粘贴进去查找服…

云原生监控——VictoriaMetrics

1.简介 VictoriaMetrics是一个快速高效且可扩展的监控解决方案和时序数据库,可以作为Prometheus的长期远端存储,具备的特性有: 支持prometheus查询api,同时实现了一个metricsql 查询语言支持全局查询视图,支持多prom…

uniapp引用leaflet地图实现方案

最近在做uniapp实现的移动端app,其中一些模块需要gis地图,在最开始的时候我尝试了使用uniapp官方自带的map组件,但是非常不好用。 后来又引用了mars2d来实现,但是发现这种引用方式会出现一个bug,在浏览器当中使用的时候…

Blueprint —— 入门笔记

蓝图比C性能较慢; 蓝图起作用需在场景中创建实例; 在Event Graph内 按住右键,平移界面;滚动滚轮,缩放界面;按住左键节点,移动节点;右击,显示节点对话框;按住…

外部存储器接口(EMIF)

1 接口信号与控制寄存器 EMIF(External Memory Interface)外部存储器接口为DSP芯片与众多外部设备之间提供一种连接方式,EMIF最常见的用途就是同时连接FLASH和SDRAM。EMIF性能优良,跟外部SDRAM和异步器件连接时,具有很大的方便性和灵活性。根…

ModaHub魔搭社区:常用的相似性度量——浮点向量相似性度量和二进制向量相似性度量

目录 常用的相似性度量 浮点向量相似性度量 二进制向量相似性度量 总结 常用的相似性度量 如果没有相似性度量——计算两个向量之间距离的方法,再好的向量数据库也没有用。因为存在许多度量,我们在这里只讨论最常用的子集。 浮点向量相似性度量 最常见的浮点向量相似…

【数据分析 - 基础入门之pandas篇①】- pandas介绍

文章目录 前言一、pandas介绍二、pandas优势2.1 强大的数据结构支撑2.2 优点 三、pandas学习路线结语相关导读 前言 一、pandas介绍 pandas 是 Python 的 核心数据分析支持库 ,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据…

【JUC进阶】11. BlockingQueue

目录 1、前言 2、BlockingQueue 2.1、ArrayBlockingQueue 2.1.1、take() 2.1.2、put() 2.2、LinkedBlockingQueue 2.3、PriorityBlockingQueue 2.4、SynchronousQueue 3、简单使用 3.1、创建ArrayBlockingQueue 3.2、Demo 1、前言 对于并发程序而言,高性…

python: FileHelper

# encoding: utf-8 # 版权所有 2023 涂聚文有限公司 # 许可信息查看: # 描述: # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 311 # Datetime : 2023/7/9 19:12 # User : geovindu # Product : PyCharm # Proj…

QT事件处理

设计一个闹钟&#xff0c;定时播报内容。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTimerEvent> #include <QDateTime> #include <QMessageBox> #include <QTextToSpeech> #include <QDebug> namespa…

校园闲置物品交易平台的设计与实现(论文+源码)_kaic

摘 要 伴随大数据时代的到来&#xff0c;计算机已成为人们步入个数化生活的必须品。由于计算机技术的成熟&#xff0c;互联网的强大功能也正在被人们以最大限度的开发。通过网络&#xff0c;人们能够足不出户完成校园闲置物品查阅&#xff0c;这在方便学生的同时也解决了在传统…

用于FPGA远程更新的QuickBoot方法

用于FPGA远程更新的QuickBoot方法 用于FPGA远程更新的QuickBoot方法 用于FPGA远程更新的QuickBoot方法1. 远程更新简介2 QuickBoot方案2.1 QuickBoot配置方法2.2 QuickBoot Flash 编程方法 3.QuickBoot实现3.1 Critical Switch World (key point)3.2 QuickBoot存储映射3.3 Bits…

Django ORM中QuerySet常用接口汇总记录

存在模型数据 学生表 课程表 支持链式操作的接口 all接口&#xff1a;用于查询所有数据&#xff0c;相当于&#xff1a;select * from xxx filter接口&#xff1a;根据条件过滤数据 values接口&#xff1a;指定返回的字段&#xff0c;结果是包含 dict 的 QuerySet 对象 valu…