anjia / blog

博客,积累与沉淀
106 stars 4 forks source link

Servo 的 style 系统 #9

Open anjia opened 5 years ago

anjia commented 5 years ago

Servo 的 style 系统

  1. selector 的实现
    • style 系统通用了很多东西,为了能和 Servo 的 layout 系统、Stylo 共享(Stylo 项目旨在把 Servo 的 style 系统集成到 Gecko 中)
    • 主要的通用特性是选择器的 SelectorImpl,这里有解析伪元素和其它伪类的所有逻辑。对应的规范是 Selectors Level 4 / Tree-Structural pseudo-classes
    • Servo 扩展了这一特性,以便在 Stylo 和 Servo 间分享更多的东西
    • 主要的 Servo 实现(用在常规构建中)是 SelectorImpl
  2. DOM glue(胶水)
    • 为了让 DOM、layout 和 style 能在不同的模块库里,这里涉及了一些特性
    • style 的 dom 特性TDocument TElement TNode TRestyleDamage)就是 layout 和 style 之间的主要的“墙”
    • layout 的 wrapper 模块可确保 layout 的特性
  3. stylelist
    • stylelist 结构保存文档的所有选择器和设备特征
    • 样式表的 CSS 规则被转成 [Rule](),并根据伪元素(见 [PerPseudoElementSelectorMap]())、样式表的来源(见[PerOriginSelectorMap]())和优先级(见[PerOriginSelectormap]()的normalimportant字段),将其引入到 [SelectorMap]()
    • 每个 [pipeline]() 创建一次 stylelist 结构,在该管道对应的 LayoutThread 中
  4. properties 模块
    • [properties 模块]()是一个 mako 模板,所有 properties、computed value 的计算和层叠逻辑都在那
    • 它是一个包含大量代码的复杂模板。主函数是 [cascase 函数](),这里执行所有计算
  5. 伪元素的处理
    • 介绍
      • 伪元素是 style 系统中棘手的一块。并非所有的伪元素都非常常见,因此有些伪元素可能会跳过层叠
      • 截止目前,Servo 有五个[伪元素]()
        • [::before]() 和 [::after]()
        • [::selection]()
        • ::-servo-details-summary
        • ::-servo-details-content
      • 两个 ::-servo-details- 伪类都是私有的,i.e. 它们只解析来自 User-Agent 样式表里的
      • Servo 有三个不同的方式去层叠伪元素,它们定义在 [PseudoElementCascadeType]()
    • Eager 层叠
      • 这个模块计算 computed values 给定节点的伪类,通过 style 系统的第一个 pass
      • 这用于所有的伪类元素,到目前为止,它是唯一方式一个公共的伪元素应该被层叠(关于它的解释见下方)
    • Precomputed 层叠
      • 根本就没有层叠。被标记为这样的伪元素不被层叠
      • 应用于这类伪类元素的唯一规则是全局规则(*|*选择器的规则),它们被直接应用到元素的 style,如果展示
      • ::-servo-details-content是这种伪类元素的一个例子,在 UA 样式表中的所有规则-有选择器 *|*::-servo-details-content(也仅有这些)被评估通过元素的style(除去display的值,那会被layout重写)
      • 私有伪类元素的首选类型(尽管它们中的而一些可能需要选择器,往下看)
    • Lazy 层叠
      • Lazy 层叠允许懒计算伪元素的样式,即,仅在需要的时候才会计算
      • 目前(对于 Servo,对于 stylo 而言不是那么多),支持这种伪元素的选择器只是可以在布局树上匹配的选择器的子集,它不能保存来自 DOM 树的所有数据
      • 该子集包括标签和属性选择器,足以制作::-servo-details-summary lazy伪元素(关于它,只需要知道它是否在open细节元素中)
      • 由于没有其他选择器适用于它,这(至少现在)不是公共伪元素的可接受类型,但应考虑用于私有伪元素

https://github.com/servo/servo/blob/master/docs/components/style.md

anjia commented 5 years ago

Servo 中的 Crates #10