SVG 1.2 - 27 October 2004

Previous | Top | Next

9 Vector effects

The default rendering for a shape is to fill the geometry with a specified paint, then stroke the outline with a specified paint and finally the option to draw markers at the vertices.

Vector effects offer the following options:

9.1 The vectorEffect element

The vectorEffect element defines a transformation of a primitive shape's outline that happens before it is drawn. The transformation is described as a series of vector effect primitive processing nodes, where input(s) and the output of every node can be considered to be SVG path data. Any primitive shape or path element can reference a vector effect through the vector-effect property. Alternatively, vector effects can be used as a drawing element; in such case its input is considered to be empty (and the vePath element must be used to get input data).

vectorEffect Schema

  <define name='vectorEffect'>
    <element name='vectorEffect'>
      <ref name='attlist.vectorEffect'/>
      <ref name='SVG.vectorEffect.content'/>
    </element>
  </define>

  <define name='attlist.vectorEffect' combine='interleave'>
    <ref name='SVG.Core.attrib'/>
    <optional>
      <attribute name='vectorEffectUnits' a:defaultValue='userSpaceOnUse'>
        <choice>
          <value>userSpaceOnUse</value>
          <value>objectBoundingBox</value>
        </choice>
      </attribute>
    </optional>
    <optional>
      <attribute name='clipout' a:defaultValue='normal'>
        <choice>
          <value>normal</value>
          <value>clip</value>
        </choice>
      </attribute>
    </optional>
  </define>

  <define name='SVG.vectorEffect.content'>
    <zeroOrMore>
      <ref name='SVG.Description.class'/>
    </zeroOrMore>
    <zeroOrMore>
      <choice>
        <ref name='animate'/>
        <ref name='set'/>
        <ref name='vePath'/>
        <ref name='veSetback'/>
        <ref name='veStrokePath'/>
        <ref name='veAffine'/>
        <ref name='veJoin'/>
        <ref name='veReverse'/>
        <ref name='veUnion'/>
        <ref name='veIntersect'/>
        <ref name='veExclude'/>
        <ref name='veFill'/>
        <ref name='veStroke'/>
        <ref name='veMarker'/>
      </choice>
    </zeroOrMore>
  </define>

  <define name='SVG.VECommon.attrib' combine='interleave'>
    <optional>
      <attribute name='in'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
    <optional>
      <attribute name='result'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
  </define>

  <define name='SVG.VECommon-2.attrib' combine='interleave'>
    <ref name='SVG.VECommon.attrib'/>
    <optional>
      <attribute name='in2'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
  </define>

  <define name='VEtransform.attrib' combine='interleave'>
    <optional>
      <attribute name='transform'/>
    </optional>
  </define>

  <define name='VEtransformPath.attrib' combine='interleave'>
    <optional>
      <attribute name='transformPath'/>
    </optional>
  </define>

  <define name='VEPrimitive.content'>
    <empty/>
  </define>

The vectorEffectUnits attribute allows "userSpaceOnUse" or "objectBoundingBox" as values. The default is "userSpaceOnUse". The output of the last vector effect node is considered to be the result of the complete vector effect. That path is used when shape's outline is normally used (inside clipPath, for text flows and text on a path, and when referenced by a vePath element).

The clipout attribute allows "normal" or "clip" as values. The value "normal" means that results of the individual fill operations are composited with each other (using srcOver). The value "clip" means that painting operations should be processed last to first and after every painting operation a clipping should be applied that excludes (clips out) the path just painted from the paintable region. The effect is that areas that were painted already won't be painted over.

This is the default vectorEffect that corresponds to the default SVG painting behavior:

<vectorEffect>
  <veFill/>
  <veStroke/>
  <veMarker/>
</vectorEffect>

The following vector effect results in no rendering (i.e., neither the fill, the stroke, nor the markers are rendered).

<vectorEffect/>

9.2 Common vector effect primitive attributes

The following attributes are available on all vector effect primitives.

result = name of output

The result attribute specifies the location, if necessary, of the output from the current vector effect primitive. It is analogous to the result attribute on filter effect primitives. If not specified, the value is empty, and the result is only passed to the following primitive. Animatable: no.

in = "SourcePath" | name of input
in2 = "SourcePath" | name of input

The in and in2 attributes define the input locations for the current vector effect primitive. The value of "SourcePath" means that the outline of the shape that references this effect is used. Any other values refer to the output of another node within this vectorEffect identified by the value of its result attribute. If this attribute is omitted, for the first primitive the value "SourcePath" is used, and the output of the previous primitive is used for all other nodes. The path used for "SourcePath"is always pre-transformed to be in the correct coordinate space depending on the value of the vectorEffectUnits attribute value. Animatable: no

transform = <transform>
trandformPath = <transform>

The transform and transformPath attributes supply coordinate space transformations for some vector effect elements. The difference between them is that the transform attribute defines the coordinate space where a particular operation occurs so that the input is transformed into that coordinate space, the vector effect operation applied and then the inverse transform applied to the result. In contrast, transformPath is simply applied to the input of the particular operation. The default value is empty. Animatable: yes.

9.3 The veStrokePath element

veStrokePath Schema

  <define name='veStrokePath'>
    <element name='veStrokePath'>
      <ref name='attlist.veStrokePath'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veStrokePath' combine='interleave'>
    <ref name='SVG.VECommon.attrib'/>
    <ref name='VEtransform.attrib'/>
    <ref name='SVG.stroke-dasharray.attrib'/>
    <ref name='SVG.stroke-dashoffset.attrib'/>
    <ref name='SVG.stroke-linecap.attrib'/>
    <ref name='SVG.stroke-linejoin.attrib'/>
    <ref name='SVG.stroke-miterlimit.attrib'/>
    <ref name='SVG.stroke-width.attrib'/>
  </define>

The veStrokePath element produces an outline of the input path's stroke. It is calculated using the given stroke parameters. The default parameter values come from the corresponding computed property values of the source element. Width attribute percentages are interpreted relative to the source element stroke-width property.

9.4 The veSetback element

veSetback Schema

  <define name='veSetback'>
    <element name='veSetback'>
      <ref name='attlist.veSetback'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veSetback' combine='interleave'>
    <ref name='SVG.VECommon.attrib'/>
    <ref name='VEtransform.attrib'/>
    <optional>
      <attribute name='setback-offset'/>
    </optional>
  </define>

The veSetback element performs a path "setback" operation: it breaks the path into individual segments and shortens both ends of every segment by the distance specified by setback-offset. If offset is a list of four lengths it is interpreted as follows:

9.5 The veAffine element

veAffine Schema

  <define name='veAffine'>
    <element name='veAffine'>
      <ref name='attlist.veAffine'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veAffine' combine='interleave'>
    <ref name='SVG.VECommon.attrib'/>
    <ref name='VEtransformPath.attrib'/>
  </define>

The veAffine element transforms a path using the specified transformation matrix.

9.6 The veReverse element

veReverse Schema

  <define name='veReverse'>
    <element name='veReverse'>
      <ref name='attlist.veReverse'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veReverse' combine='interleave'>
    <ref name='SVG.VECommon.attrib'/>
  </define>

The veReverse element reverses the direction of the path. The path is adjusted such that all of the vertices on the path are put in reverse order (i.e., if there are N vertices numbered 0 to N-1, then vertex K is moved to position N-K-1) with adjustments to the path commands and control points to produce the same shape as the original path. In effect, it is as if the path segments have been played backward.

There are a variety of effects that rendering results from a veReverse operation. They include swapping the begin and end markers and a 180 degree orientation change for automatically oriented markers. There are potentially different results when rendering compound paths.

9.7 The veJoin element

veJoin Schema

  <define name='veJoin'>
    <element name='veJoin'>
      <ref name='attlist.veJoin'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veJoin' combine='interleave'>
    <ref name='SVG.VECommon-2.attrib'/>
    <optional>
      <attribute name='connect'>
        <choice>
          <value>none</value>
          <value>line</value>
        </choice>
      </attribute>
    </optional>
  </define>

The veJoin element joins two paths together by a concatenation operation on the path data commands for the two paths (the path referenced by in2 is concatenated to the end of the path referenced by in). The connect attribute can be either "line" or "none". In case of "none", the path segments are merged together. In case of "line" an "M" command that starts the second path is replaced with "L".

9.8 The veUnion element

veUnion Schema

  <define name='veUnion'>
    <element name='veUnion'>
      <ref name='attlist.veUnion'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veUnion' combine='interleave'>
    <ref name='SVG.VECommon-2.attrib'/>
  </define>

The veUnion element produces an outline of the union of two shapes. The geometric effect is equivalent to the result of a geometric computation of additive clipping paths (i.e., logical OR'ing of the silhouettes produced by each of the shapes).

9.9 The veIntersect element

veIntersect Schema

  <define name='veIntersect'>
    <element name='veIntersect'>
      <ref name='attlist.veIntersect'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veIntersect' combine='interleave'>
    <ref name='SVG.VECommon-2.attrib'/>
  </define>

The veIntersect element produces an outline of the intersection of two shapes. The geometric effect is equivalent to the result of a geometric computation of nested clipping paths.

9.10 The veExclude element

veExclude Schema

  <define name='veExclude'>
    <element name='veExclude'>
      <ref name='attlist.veExclude'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veExclude' combine='interleave'>
    <ref name='SVG.VECommon-2.attrib'/>
  </define>

The veExclude element produces an outline of the exclusion of the second shape, provided by in2, from the first shape, provided by in. The geometric effect of veExclude is equivalent to a geometric "clip out" computation where the resulting path geometry is the geometric clip of the first shape against a composite shape consisting of a veJoin of: (a) a very large rectangle (i.e., a rectangle whose bounding box is outside the bounds of the first shape) and (b) the second shape after a veReverse operation.

9.11 The veFill element

veFill Schema

  <define name='veFill'>
    <element name='veFill'>
      <ref name='attlist.veFill'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veFill' combine='interleave'>
    <optional>
      <attribute name='in'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
    <ref name='SVG.fill.attrib'/>
    <ref name='VEtransform.attrib'/>
  </define>

The veFill element fills a shape using the paint given by the fill property and the opacity value given by the fill-opacity property. For the fill property, values of "currentStroke" and "currentFill" correspond to the computed value of stroke and fill on the source element. For the fill-opacity property, values of "currentStrokeOpacity" and "currentFillOpacity" correspond to the computed value of stroke-opacity and fill-opacity on the source element. The output of the veFill element is the same as its input.

9.12 The veStroke element

veStroke Schema

  <define name='veStroke'>
    <element name='veStroke'>
      <ref name='attlist.veStroke'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veStroke' combine='interleave'>
    <optional>
      <attribute name='in'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
    <ref name='SVG.fill.attrib'/>
    <ref name='VEtransform.attrib'/>
  </define>

The veStroke element creates a shape that represents the path of the shape's stroke (taking into account the stroke properties on the source element) and then fills the stroke using the paint server given by the fill property and the opacity value given by the fill-opacity property. For the fill property, values of "currentStroke" and "currentFill" mean the computed value of stroke and fill on the source element. For the fill-opacity property, values of "currentStrokeOpacity" and "currentFillOpacity" mean the computed value of stroke-opacity and fill-opacity on the source element. The output of the veStroke element is the same as its input.

Note that the veStroke element has fill and fill-opacity attributes and not stroke and stroke-opacity attributes. This is because the conceptual model for stroking within vector effects is that you first perform an implicit veStrokePath operation to create a new shape, and then you paint the region of (i.e., you "fill") that new shape.

9.13 The veMarker element

veMarker Schema

  <define name='veMarker'>
    <element name='veMarker'>
      <ref name='attlist.veMarker'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veMarker' combine='interleave'>
    <optional>
      <attribute name='in'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
    <ref name='SVG.Marker.attrib'/>
  </define>

The veMarker element draws markers along the input path. Its output is the same as its input.

9.14 The veMarkerPath element

veMarkerPath Schema

  <define name='veMarkerPath'>
    <element name='veMarkerPath'>
      <ref name='attlist.veMarkerPath'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.veMarkerPath' combine='interleave'>
    <optional>
      <attribute name='in'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
    <ref name='SVG.Marker.attrib'/>
  </define>

The veMarkerPath element behaves like veMarker but instead of drawing it produces its output by taking the union of the paths of all the markers.

9.15 The vePath element

vePath Schema

  <define name='vePath'>
    <element name='vePath'>
      <ref name='attlist.vePath'/>
      <ref name='SVG.vePath.content'/>
    </element>
  </define>

  <define name='attlist.vePath' combine='interleave'>
    <optional>
      <attribute name='result'>
        <data type='NMTOKEN'/>
      </attribute>
    </optional>
  </define>

  <define name='SVG.vePath.content'>
    <oneOrMore>
      <ref name='vePathRef'/>
    </oneOrMore>
  </define>

The vePath element does not take input and its result is the path taken from the shape(s) which it references. The path references come from child vePathRef elements. Individual paths are transformed according to the transformPath attribtue on vePathRef and then joined together in the same manner as veJoin.

9.16 The vePathRef element

vePathRef Schema

  <define name='vePathRef'>
    <element name='vePathRef'>
      <ref name='attlist.vePathRef'/>
      <ref name='VEPrimitive.content'/>
    </element>
  </define>

  <define name='attlist.vePathRef' combine='interleave'>
    <ref name='SVG.XLinkRequired.attrib'/>
    <ref name='VEtransform.attrib'/>
    <optional>
      <attribute name='connect'/>
    </optional>
    <optional>
      <attribute name='reverse'/>
    </optional>
  </define>

The vePathRef element is a child node for the vePath element that references an individual path. It is an error for this element to reference anything but a primitive shape, a path or a text element.

9.17 Examples

A non-scaling line width, with non-scaling markers:

<vectorEffect>
  <veFill/>
  <veStroke transform="ref(host)"/>
  <veMarker transform="ref(host)"/>
</vectorEffect>

Non-scaling fill/stroke patterns:

<vectorEffect>
  <veFill transform="ref(host)"/>
  <veStrokePath in="SourcePath"/>
  <veFill transform="ref(host)" fill="StrokePaint"/>
  <veMarker in="SourcePath" transform="ref(host)"/>
</vectorEffect>

An effect that strokes a path twice, once normally and then again with a thinner red stroke:

<vectorEffect>
  <veStroke/>
  <veStroke fill="red" stroke-width-adjust="50%"/>
</vectorEffect>

Using vector effects to produce shared borders on paths:

<defs>
  <path id="border1" d="..."/>
  <path id="border2" d="..."/>
  <path id="border3" d="..."/>
  <path id="border4" d="..."/>
  <path id="border5" d="..."/>
</defs>
<vectorEffect>
  <vePath>
    <vePathRef xlink:href="#border1"/>
    <vePathRef xlink:href="#border2"/>
    <vePathRef xlink:href="#border3"/>
  </vePath>
  <veFill color="red"/>
  <vePath>
    <vePathRef xlink:href="#border4"/>
    <vePathRef reverse="true" xlink:href="#border2"/>
    <vePathRef xlink:href="#border5"/>
  </vePath>
  <veFill color="blue"/>
</vectorEffect>

9.18 The vector-effect property

The vector-effect property specifies the vector effect to use when drawing an object. Vector effects are applied before any of the other compositing operations: filters, masks and clips.

vector-effect
Value: 'default' | 'non-scaling-stroke' | 'inherit' | <uri>
Initial: 'default'
Applies to: graphical elements
Inherited: no
Percentages: N/A
Media: visual
Animatable: yes

The value 'default' corresponds to the following vector effect:

<vectorEffect>
  <veFill/>
  <veStroke/>
  <veMarker/>
</vectorEffect>

It is the default rendering behaviour from SVG 1.1.

The value 'non-scaling-stroke' is a keyword for a predefined vector effect that causes an object's stroke-width to be unaffected by transformations and zooming. That is:

<vectorEffect>
  <veFill/>
  <veStrokePath in="SourcePath"/>
  <veFill transform="ref(host)" fill="currentStroke"/>
  <veMarker in="SourcePath" transform="ref(host)"/>
</vectorEffect>

The URI value references a vectorEffect element that should be used as the vector effect.

The value "non-scaling-stroke" is designed so that it can be implemented without the entire vector effect engine. For example, profiles of SVG may restrict the values of vector-effect to be "default" or "non-scaling-stroke". In effect this requires no processing of vector effects, rather it is always the default rendering order with a different set of transformations.