第3章:渲染模型

SVG 2 渲染模型将遵循合成与混合规范定义的规则。

会议记录:2012年西雅图/巴黎面对面会议第3天

负责人:Nikos(行动项3332)。

状态:完成。

3.1. 引言

SVG的实现必须按照本章所述的渲染模型进行实现,并根据符合性要求附录中的说明进行修改,该附录描述了实现可能偏离的情况。 在实践中,由于输出设备的限制(例如,可能只支持有限范围的颜色),以及在实现精确数学模型方面的实际限制(例如,现实性能的曲线用直线近似,近似值只需足够精确以满足符合性要求),允许一定的可变性。

关于符合性要求的附录描述了实际实现可能偏离该描述的程度。在实践中,实际实现可能会因为输出设备的限制(例如,可能只支持有限范围的颜色)以及在实现精确数学模型方面的实际限制而略有偏离(例如,现实性能的曲线用直线近似,近似值只需足够精确以满足符合性要求)。

3.2. 渲染树

SVG文档最终渲染表示的组件与文档模型中的基本元素之间并没有一对一的关系。 图形的外观反映了一种平行结构——渲染树, 其中某些元素被排除,另一些元素被重复。

SVG命名空间中的许多元素并不直接代表图形文档的一个组件。 相反,它们定义图形效果、元数据、 用于表示其他元素的内容, 或在特定条件下显示的替代内容。 在动态文档中,图形的某些组件 可能会根据交互或动画进行渲染或不渲染。 这些未渲染的元素不会直接包含在渲染树中。

由于SVG支持图形子组件的重用, 某些元素会被多次渲染。 每个单独的渲染可能具有上下文相关的样式, 并可能以不同的比例或变换进行光栅化。

3.2.1. 定义

渲染树

渲染树是一个在SVG文档片段中被渲染的元素集合。 它是从文档树生成的, 通过排除未渲染元素 并插入用于重用图形的额外片段。 图形按照渲染树的顺序进行绘制和合成, 受绘制顺序属性的重新排序影响。 注意,尽管没有视觉效果的元素仍可能存在于渲染树中。

已渲染元素

在当前文档的渲染树中具有直接表示的元素。 包括在元素使用元素阴影树中的已渲染实例。 不包括影响渲染的元素, 作为重用图形的源定义, 但自身并不直接被渲染。 参见已渲染与未渲染元素

未渲染元素

在当前文档的渲染树中没有直接表示的元素。 它仍可能通过重用图形或图形效果影响渲染树。 参见已渲染与未渲染元素

重用图形

包含在渲染树中的图形组件, 但在文档模型中没有单一直接等价元素。 它们可能通过阴影DOM元素表示 (如重用的图形使用use元素), 或作为图形效果生成的图像片段 (如模式或遮罩)。

从不渲染元素

任何类型的元素是从不直接渲染的, 无论上下文或显示样式值。 它包括以下元素: clipPathdefsdesclinearGradientmarkermaskmetadatapatternradialGradientscriptstyletitle; 它还包括一个symbol元素,该元素不是 实例根使用元素阴影树

可渲染元素

任何类型的元素可以渲染树中具有直接表示, 作为图形、容器、文本、音频或动画。 它包括以下元素: aaudiocanvascircleellipseforeignObjectgiframeimagelinepathpolygonpolylinerectsvgswitchtexttextPathtspanunknownusevideo; 它还包括一个symbol元素,该元素 实例根使用元素阴影树

可渲染元素在特定文档或时间点可能会被渲染,也可能不会被渲染。

3.2.2. 渲染与非渲染元素

在任何给定时间,每个 SVG 元素 (或元素实例使用元素阴影树中) 要么是渲染的,要么是非渲染的。 元素当前是否被渲染不仅影响其视觉显示,还影响 交互性和几何计算。

元素在以下四种情况下未被渲染

非渲染元素:

非渲染元素在文档可访问性树中不被表示。 尽管如此,它们仍然是文档模型的一部分, 并参与样式继承和级联

3.2.3. 控制可见性:‘display’和‘visibility’属性的影响

SVG 使用两个属性来切换通常渲染元素的可见显示: displayvisibility。 尽管它们在静态文档中具有相似的可见效果, 但在概念上是不同的。

有关displayvisibility的定义,请参见 CSS 2.1 规范。 [CSS2]

display设置为none 会导致元素未被渲染。 当应用于 图形元素文本内容元素容器元素时,设置displaynone 会导致该元素(及其所有后代)不成为渲染树的一部分。 请注意,display不是一个继承属性。

具有任何其他display值的元素 除none外,都会正常渲染。

display属性仅适用于可渲染元素。 在一个从未直接渲染 或基于条件处理而未渲染的元素上设置display: none没有效果。

display属性影响给定元素的直接处理, 但不阻止它被其他元素引用。 例如,在path元素上设置 display: none会阻止该元素直接渲染到画布上, 但path 元素仍然可以被textPath元素引用, 并且其几何形状将在路径文本处理时被使用。

当应用于图形元素use元素时, 将visibility设置为hiddencollapse 会导致该元素未被绘制。 但它仍然是渲染树的一部分。 它可能对指针事件敏感 (取决于pointer-events的值), 可能会接收焦点(取决于tabindex的值), 参与边界框计算和剪切路径, 并影响文本布局。

visibility属性仅直接影响 图形元素文本内容元素和当它是文本内容元素的子元素时的 a元素。 由于visibility是一个继承属性, 因此, 虽然它对use元素或容器元素本身没有影响, 其继承值可以影响后代元素。

3.2.4. 重用图形

在文档的一个部分(或在另一个文档)定义的图形内容 可以用于渲染其他元素。 从渲染的角度来看,有两种类型的重用图形:

阴影 DOM 元素的渲染方式与普通元素相同, 就像宿主元素(例如use元素) 是一个容器,阴影内容是其后代一样。 阴影 DOM 元素上的样式和几何属性 与其在源文档中的对应元素 独立解析。 display属性对 阴影元素具有正常效果, 除了适用于symbol元素的特殊规则。

出于混合目的,use元素形成了一个非孤立组

相比之下, 图形效果元素生成一个自包含的 SVG 片段, 独立渲染为堆叠上下文 和一个孤立组。 该片段的画布是缩放的。 图形效果元素的子内容 在该画布中渲染和合成。 整个平面画布在与其他绘画层混合时 被视为矢量图像。

图形效果元素任何子内容上的display属性 在设置为none时具有正常效果, 排除该子树用于渲染。 然而,图形效果并不会因图形效果元素或祖先上的display: none值而改变。

3.3. 绘图模型

SVG 使用“绘图模型”进行渲染。绘制 通过连续的操作应用于输出设备,使得每个操作都在输出设备的某个区域上绘制, 可能会遮盖之前已经涂抹的部分。 每绘制一个对象或组后,它就成为下一个绘制操作的背景的一部分。 SVG 2 支持先进的混合模式和合成操作,以控制每个绘制操作如何与背景交互。 这些绘制操作的规则在 合成与混合规范中概述。

3.4. 渲染顺序

SVG 中的元素在三维空间中定位。除了它们在SVG 视口的 x 和 y 轴上的位置外,SVG 元素还 在 z 轴上定位。z 轴的位置定义了它们的绘制顺序。

沿 z 轴,元素被分组为堆叠上下文

3.4.1. 在 SVG 中建立堆叠上下文

如果满足以下条件,必须在 SVG 元素上为其后代建立新的堆叠上下文:

堆叠上下文是用于描述在文档渲染时,元素一个个绘制在其他元素上面的顺序的概念工具,且用于确定在指针事件中哪个元素最高。堆叠上下文 不影响元素在 DOM 树中的位置,其存在或缺失不会影响元素在画布的 X-Y 平面上的位置、大小或方向——仅影响其绘制的顺序。

堆叠上下文可以包含进一步的堆叠上下文。从其父堆叠上下文的角度来看,堆叠上下文是原子的;祖先堆叠上下文中的元素不能介入其任何元素之间。

每个元素属于一个堆叠上下文。堆叠上下文中的元素必须按照文档顺序进行堆叠。

除了foreignObject元素外,SVG 元素创建的堆叠上下文的从后到前 的堆叠顺序为:

  1. 形成堆叠上下文的元素的背景和边框(如果有)
  2. 后代,按树的顺序

由于foreignObject元素在 CSS 术语中创建一个 “固定位置的包含块”,因此由foreignObject元素创建的堆叠上下文的堆叠顺序规范规则为 CSS 2.1 附录 E 中的规则。

3.5. 元素的渲染方式

单个图形元素被视为一个非孤立组, 构成图形元素的组件(填充、描边等)(参见绘制形状和文本)是 该组的成员。参见组如何渲染

3.6. 组的渲染方式

g元素(参见容器元素 )创建一个合成组。 类似地,use 元素为其阴影内容创建一个合成组。 合成与混合 规范规范性地描述了如何渲染合成组。 在 SVG 中,可以对一个组应用效果。例如,透明度、滤镜或蒙版。这些效果在对组应用任何变换之前 立即应用于组的渲染结果,然后在组与组背景混合和合成之前应用。 对组应用任何此类效果会使该组隔离。

因此,渲染合成组遵循以下步骤:
如果该组是隔离的:

  1. 初始背景 设置为使用rgba(0,0,0,0)初始化的新缓冲区
  2. 该组中是图形元素g元素的内容被 按顺序渲染到初始背景
  3. 应用修改组画布的滤镜和其他效果

    为了提供高质量的渲染,滤镜 原语和其他位图效果必须在操作 坐标空间中应用。

  4. 应用组变换
  5. 将组画布与组背景混合和合成
else (该组不是隔离的):
  1. 初始背景 设置为组背景
  2. 该组中是图形元素g元素的内容被 按顺序渲染到初始背景。 组变换在每个元素渲染时应用。

3.6.1. 对象和组的不透明度:‘opacity’属性的影响

有关opacity的定义,请参见CSS颜色模块第3版。[css-color-3]

属性opacity指定给定图形元素或容器元素在绘制到画布时的透明度。当应用于容器元素时,这被称为组透明度;当应用于单个渲染元素时,这被称为对象透明度。然而,这两种操作的原理是相同的。

在SVG中,还有几个与透明度相关的属性:

这四个透明度属性参与中间渲染操作。然而,对象和组的透明度可以视为后处理操作。概念上,适用opacity的对象或组被渲染到一个RGBA离屏图像中。整个离屏图像随后以指定的opacity值统一混合到画布中。 因此,opacity的存在使得该组变为孤立的。

属性opacity适用于以下SVG元素: svggsymbolmarkeraswitchuseunknown以及图形元素

以下示例说明了opacity属性在对象和组上的各种用法。

<svg xmlns="http://www.w3.org/2000/svg"
     width="600" height="175" viewBox="0 0 1200 350">

  <!-- 背景蓝色矩形 -->
  <rect x="100" y="100" width="1000" height="150" fill="blue">

  <!-- 从不透明到几乎透明的红色圆圈 -->
  <circle cx="200" cy="100" r="50" fill="red" opacity="1">
  <circle cx="400" cy="100" r="50" fill="red" opacity=".8">
  <circle cx="600" cy="100" r="50" fill="red" opacity=".6">
  <circle cx="800" cy="100" r="50" fill="red" opacity=".4">
  <circle cx="1000" cy="100" r="50" fill="red" opacity=".2">

  <!-- 不透明组,不透明圆圈 -->
  <g opacity="1">
    <circle cx="182.5" cy="250" r="50" fill="red" opacity="1">
    <circle cx="217.5" cy="250" r="50" fill="green" opacity="1">
  </g>
  <!-- 组透明度:.5,不透明圆圈 -->
  <g opacity=".5">
    <circle cx="382.5" cy="250" r="50" fill="red" opacity="1">
    <circle cx="417.5" cy="250" r="50" fill="green" opacity="1">
  </g>
  <!-- 不透明组,半透明绿色在红色上 -->
  <g opacity="1">
    <circle cx="582.5" cy="250" r="50" fill="red" opacity=".5">
    <circle cx="617.5" cy="250" r="50" fill="green" opacity=".5">
  </g>
  <!-- 不透明组,半透明红色在绿色上 -->
  <g opacity="1">
    <circle cx="817.5" cy="250" r="50" fill="green" opacity=".5">
    <circle cx="782.5" cy="250" r="50" fill="red" opacity=".5">
  </g>
  <!-- 组透明度.5,半透明绿色在红色上 -->
  <g opacity=".5">
    <circle cx="982.5" cy="250" r="50" fill="red" opacity=".5">
    <circle cx="1017.5" cy="250" r="50" fill="green" opacity=".5">
  </g>
</svg>
图像显示不同的圆圈组与背景混合。

每组红色和绿色圆圈首先渲染到一个离屏图像中,然后作为整体与背景蓝色矩形混合,使用给定的opacity值。

在示例中,顶部圆圈的透明度从1.0到0.2不等。底部行展示了五个g元素,每个元素包含重叠的红色和绿色圆圈,如下所示:

3.7. 图形元素的类型

SVG支持三种基本类型的图形元素 可渲染到画布上:

3.7.1. 绘制形状和文本

形状和文本可以被填充(即将油漆应用于形状的内部)和描边(即在形状的轮廓上应用油漆)。

对于某些类型的形状,可以在形状边界上的位置绘制标记符号(它们本身可以由任意组合的形状、文本和图像组成)。每个标记符号都像其图形内容在使用给定标记符号的形状对象之后扩展到SVG文档树一样被绘制。标记符号的图形内容使用与图形元素相同的方法进行渲染。标记符号不适用于文本。

填充、描边和标记的绘制顺序由paint-order属性决定。默认情况下,首先绘制填充,然后是描边,最后是标记符号。标记符号沿着形状的轮廓按顺序渲染,从形状的起始点到结束点。

填充和描边操作是完全独立的;例如,每个填充或描边操作都有其自己的不透明度设置。

SVG支持多种内置类型的油漆,可用于填充和描边操作。这些在油漆服务器中描述。

3.7.2. 绘制光栅图像

当光栅图像被渲染时,原始样本使用标准算法进行“重采样”,以在输出设备上产生所需位置的样本。重采样要求在符合性要求中讨论。

如同HTML [HTML, 10.4.2], 所有具有相同绝对URL和相同图像数据的动画图像都应按组同步渲染到同一时间线,时间线从最少最近添加到组的时间开始。

当用户代理要重新启动显示动画图像的img元素的动画时,期望该img元素节点文档中具有相同绝对URL和相同图像数据的所有动画图像都从头开始重新启动其动画。

3.8. 过滤绘制区域

SVG允许对任何绘制操作进行过滤。(请参见滤镜效果。)

在这种情况下,结果必须好像绘制操作已应用于一个初始化为透明黑色的中间画布,画布的大小由滤镜效果中给出的规则确定,然后通过滤镜效果中定义的过程进行过滤。

3.9. 裁剪和遮罩

SVG支持以下裁剪/遮罩功能:

裁剪和遮罩均在模块CSS遮罩中指定 [css-masking-1].

3.10. 父级合成

SVG文档片段可以是半透明的。

根据合成与混合规范, svg元素总是 创建一个隔离组。 当SVG文档是顶级文档时, 意味着它没有嵌入在其他文档中, 根svg元素 被视为页面组 并与100%不透明的白色背景进行合成。 在所有其他情况下,SVG文档或文档片段与父文档合成时保留不透明度。

3.11. ‘overflow’属性的影响

有关overflow的定义,请参阅层叠样式表第2级修订版1 (CSS 2.1) 规范 [CSS2]。

SVG中overflow属性行为的总结。
元素 初始值 用户代理样式表 自动 可见 隐藏 滚动
文档根svg 可见 不适用 可见 | 滚动 可见 隐藏 滚动
其他svg 可见 隐藏 可见 | 滚动 可见 隐藏 滚动
文本 可见 隐藏 可见 可见 隐藏 隐藏
图案 可见 隐藏 可见 可见 隐藏 隐藏
标记 可见 隐藏 可见 可见 隐藏 隐藏
符号 可见 隐藏 可见 可见 隐藏 隐藏
图像 可见 隐藏 可见 可见 隐藏 隐藏
iframe 可见 隐藏 可见 | 滚动 可见 隐藏 滚动
foreignObject 可见 隐藏 可见 | 滚动 可见 隐藏 滚动

overflow属性具有相同的参数值,并且具有与CSS 2.1中定义的相同含义 ([CSS2],第11.1.1节);然而,以下附加要点适用:

尽管overflow的初始值为自动。在用户代理样式表中,当svg元素不是独立文档的根元素时,该元素的overflow被覆盖,而pattern元素和marker元素的默认值为隐藏。