11 Paths


11.1 Introduction

Path objects are used to represent an outline which can be filled, stroked (see Filling, Stroking and Paint Servers) or used as a clipping path (see Clipping, Masking and Compositing), or for any combination of the three.

A path is described using the concept of a current point. In an analogy with drawing on paper, the current point can be thought of as the location of the pen. The position of the pen can be changed, and the outline of a shape (open or closed) can be traced by dragging the pen in either straight lines or curves.

Paths represent an outline of an object which is defined in terms of moveto (set a new current point), lineto (draw a straight line), curveto (draw a curve using a cubic bezier), arc (elliptical or circular arc) and closepath (close the current shape by drawing a line to the last moveto) elements. Compound paths (i.e., a path with subpaths, each consisting of a single moveto followed by one or more line or curve operations) are possible to allow effects such as "donut holes" in objects.

11.2 Path Data

11.2.1 General information about path data

A path is defined by including a <path> element which contains a d="(path data)" attribute, where the d attribute contains the moveto, line, curve (both cubic and quadratic beziers), arc and closepath instructions. The following example specifies a path in the shape of a triangle. (The M indicates a moveto, the L's indicate lineto's, and the z indicates a closepath:

<?xml version="1.0" standalone="yes"?>
<svg width="4in" height="3in"
     xmlns = 'http://www.w3.org/Graphics/SVG/svg-19990706.dtd'>
  <path d="M 100 100 L 140 100 L 120 140 z"/>
</svg>

Download this example

A <path> element can also contain child <data> elements which also contain d="(path data)" attributes. This ability to have child <data> elements allows for very long path data strings to be broken up into more manageable smaller strings. Here is a <path> element equivalent to the <path> element above, but whose path data is divided into four pieces:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG July 1999//EN" 
  "http://www.w3.org/Graphics/SVG/svg-19990706.dtd">
<svg width="4in" height="3in">
  <path d="M 100 100">
    <data d="L 140 100"/>
    <data d="L 120 140"/>
    <data d="z"/>
  </path>
</svg>

Download this example

All d= attributes are concatenated together to yield a single path specification, with the d= attribute (if present) on the <path> element preceding the d= attributes on the <data> elements. Each d= attribute is restricted to 1023 characters of data. Path data commands cannot be broken across different d= attributes. For example, you cannot split a "moveto" command such that the X-coordinate in on one d= attribute and the Y-coordinate is on another.

The syntax of path data is very abbreviated in order to allow for minimal file size and efficient downloads, since many SVG files will be dominated by their path data. Some of the ways that SVG attempts to minimize the size of path data are as follows:

The path data syntax is a prefix notation (i.e., commands followed by parameters). The only allowable decimal point is a period (".") and no other delimiter characters are allowed. (For example, the following is an invalid numeric value in a path data stream: "13,000.56". Instead, you should say: "13000.56".)

The following sections list the commands.

11.2.2 The "moveto" commands

The "moveto" commands (M or m) establish a new current point. The effect is as if the "pen" were lifted and moved to a new location. A path data segment must begin with either one of the "moveto" commands or one of the "arc" commands. Subsequent "moveto" commands (i.e., when the "moveto" is not the first command) represent the start of a new subpath:

Command Name Parameters Description
M (absolute)
m (relative)
moveto (x y)* Start a new sub-path at the given (x,y) coordinate. M (uppercase) indicates that absolute coordinates will follow; m (lowercase) indicates that relative coordinates will follow. If a relative moveto (m) appears as the first element of the path, then it is treated as a pair of absolute coordinates. If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit lineto commands.

11.2.3 The "closepath" command

The "closepath" (z) causes an automatic straight line to be drawn from the current point to the initial point of the current subpath. "Closepath" differs in behavior from what happens when "manually" closing a subpath via a "lineto" command in how 'stroke-linejoin' and 'stroke-linecap' are implemented. With "closepath", the end of the final segment of the subpath is "joined" with the start of the initial segment of the subpath using the current value of 'stroke-linejoin' . If you instead "manually" close the subpath via a "lineto" command, the start of the first segment and the end of the last segment are not joined but instead are each capped using the current value of 'stroke-linecap':

Command Name Parameters Description
z closepath (none) Close the current subpath by drawing a straight line from the current point to current subpath's most recent starting point (usually, the most recent moveto point).

11.2.4 The "lineto" commands

The various "lineto" commands draw straight lines from the current point to a new point:

Command Name Parameters Description
L (absolute)
l (relative)
lineto (x y)* Draw a line from the current point to the given (x,y) coordinate which becomes the new current point. L (uppercase) indicates that absolute coordinates will follow; l (lowercase) indicates that relative coordinates will follow. A number of coordinates pairs may be specified to draw a polyline. At the end of the command, the new current point is set to the final set of coordinates provided.
H (absolute)
h (relative)
horizontal lineto x* Draws a horizontal line from the current point (cpx, cpy) to (x, cpy). H (uppercase) indicates that absolute coordinates will follow; h (lowercase) indicates that relative coordinates will follow. Multiple x values can be provided (although usually this doesn't make sense). At the end of the command, the new current point becomes (x, cpy) for the final value of x.
V (absolute)
v (relative)
vertical lineto y* Draws a vertical line from the current point (cpx, cpy) to (cpx, y). V (uppercase) indicates that absolute coordinates will follow; v (lowercase) indicates that relative coordinates will follow. Multiple y values can be provided (although usually this doesn't make sense). At the end of the command, the new current point becomes (cpx, y) for the final value of y.

11.2.5 The curve commands

These three groups of commands that draw curves:


The cubic bezier commands are as follows:

Command Name Parameters Description
C (absolute)
c (relative)
curveto (x1 y1 x2 y2 x y)* Draws a cubic bezier curve from the current point to (x,y) using (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve. C (uppercase) indicates that absolute coordinates will follow; c (lowercase) indicates that relative coordinates will follow. Multiple sets of coordinates may be specified to draw a polybezier. At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybezier.
S (absolute)
s (relative)
shorthand/smooth curveto (x2 y2 x y)* Draws a cubic bezier curve from the current point to (x,y). The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. (If there is no previous command or if the previous command was not an C, c, S or s, assume the first control point is coincident with the current point.) (x2,y2) is the second control point (i.e., the control point at the end of the curve). S (uppercase) indicates that absolute coordinates will follow; s (lowercase) indicates that relative coordinates will follow. Multiple sets of coordinates may be specified to draw a polybezier. At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybezier.

The quadratic bezier commands are as follows:

Command Name Parameters Description
Q (absolute)
q (relative)
quadratic bezier curveto (x1 y1 x y)* Draws a quadratic bezier curve from the current point to (x,y) using (x1,y1) as the control point. Q (uppercase) indicates that absolute coordinates will follow; q (lowercase) indicates that relative coordinates will follow. Multiple sets of coordinates may be specified to draw a polybezier. At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybezier.
T (absolute)
t (relative)
Shorthand/smooth quadratic bezier curveto (x y)* Draws a quadratic bezier curve from the current point to (x,y). The control point is assumed to be the reflection of the control point on the previous command relative to the current point. (If there is no previous command or if the previous command was not an Q, q, T or t, assume the control point is coincident with the current point.) T (uppercase) indicates that absolute coordinates will follow; t (lowercase) indicates that relative coordinates will follow. At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybezier.

The elliptical arc commands are as follows:

Command Name Parameters Description
A (absolute)
a (relative)
elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)* Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse is defined two radii (rx, ry) and an x-axis-rotation, which indicates how the ellipse as a whole is rotated relative to the current coordinate system. The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed by the other parameters. large-arc-flag and sweep-flag contribute to the automatic calculations and help determine how the arc is drawn.

The elliptical arc command draws a section of an ellipse which meets the following constraints:

For most situations, there are actually four different arcs (two different ellipses, each with two different arc sweeps) that satisfy these constraints: (Pictures will be forthcoming in a future version of the spec) large-arc-flag and sweep-flag indicate which one of the four arcs should be drawn, as follows:

(We need examples to illustrate all of this! Here is one for the moment. Suppose you have a circle with center (5,5) and radius 2 and you wish to draw an arc from 0 degrees to 90 degrees. Then one way to achieve this would be M 7,5 A 2,2 0 0 1 5,7. In this example, you move to the "0 degree" location on the circle, which is (7,5), since the center is at (5,5) and the circle has radius 2. Since we have circle, the two radii are the same, and in this example both are equal to 2. Since our sweep is 90 degrees, which is less than 180, we set large-arc-flag to 0. We want to draw the sweep in a positive angle direction, so we set sweep-flag to 1. Since we want to draw the arc to the point which is at the 90 degree location of the circle, we set (x,y) to (5,7).)

11.2.6 The grammar for path data

(??? This requires clean-up and a more formal write-up on the terminology.) The following is the BNF for SVG paths. The following notation is used:

svg-path:
    wsp* subpaths?

subpaths:
    subpath
    | subpath subpaths

subpath:
    moveto subpath-elements?

subpath-elements:
    subpath-element-wsp
    | subpath-element-wsp subpath-elements

subpath-element-wsp:
    subpath-element wsp*

subpath-element:
    closepath
    | lineto
    | horizontal-lineto
    | vertical-lineto
    | curveto
    | smooth-curveto
    | quadratic-bezier-curveto
    | smooth-quadratic-bezier-curveto
    | elliptical-arc

moveto:
    ( "M" | "m" ) wsp* moveto-argument-sequence

moveto-argument-sequence:
    coordinate-pair
    | coordinate-pair lineto-argument-sequence

closepath:
    ("Z" | "z") wsp*

lineto:
    ( "L" | "l" ) wsp* lineto-argument-sequence

lineto-argument-sequence:
    coordinate-pair
    | coordinate-pair lineto-argument-sequence

horizontal-lineto:
    ( "H" | "h" ) wsp* horizontal-lineto-argument-sequence

horizontal-lineto-argument-sequence:
    horizontal-lineto-argument
    | horizontal-lineto-argument horizontal-lineto-argument-sequence

horizontal-lineto-argument:
    coordinate

vertical-lineto:
    ( "V" | "v" ) wsp* vertical-lineto-argument-sequence

vertical-lineto-argument-sequence:
    vertical-lineto-argument
    | vertical-lineto-argument vertical-lineto-argument-sequence

vertical-lineto-argument:
    coordinate

curveto:
    ( "C" | "c" ) wsp* curveto-argument-sequence

curveto-argument-sequence:
    curveto-argument
    | curveto-argument curveto-argument-sequence

curveto-argument:
    coordinate-pair coordinate-pair coordinate-pair

smooth-curveto:
    ( "S" | "s" ) wsp* smooth-curveto-argument-sequence

smooth-curveto-argument-sequence:
    smooth-curveto-argument
    | smooth-curveto-argument smooth-curveto-argument-sequence

smooth-curveto-argument:
    coordinate-pair coordinate-pair

quadratic-bezier-curveto:
    ( "Q" | "q" ) wsp* quadratic-bezier-curveto-argument-sequence

quadratic-bezier-curveto-argument-sequence:
    quadratic-bezier-curveto-argument
    | quadratic-bezier-curveto-argument
        quadratic-bezier-curveto-argument-sequence

quadratic-bezier-curveto-argument:
    coordinate-pair coordinate-pair

smooth-quadratic-bezier-curveto:
    ( "T" | "t" ) wsp* smooth-quadratic-bezier-curveto-argument-sequence

smooth-quadratic-bezier-curveto-argument-sequence:
    coordinate-pair
    | coordinate-pair smooth-quadratic-bezier-curveto-argument-sequence

elliptical-arc:
    ( "A" | "a" ) wsp* elliptical-arc-argument-sequence

elliptical-arc-argument-sequence:
    elliptical-arc-argument
    | elliptical-arc-argument elliptical-arc-argument-sequence

elliptical-arc-argument:
    nonnegative-number-comma-wsp nonnegative-number-comma-wsp number-comma-wsp 
        flag-comma-wsp flag-comma-wsp coordinate-pair

coordinate-pair:
    coordinate coordinate

coordinate:
    number-comma-wsp

nonnegative-number-comma-wsp:
    nonnegative-number wsp* comma? wsp*

number-comma-wsp:
    number wsp* comma? wsp*

nonnegative-number:
    integer-constant
    | floating-point-constant

number:
    sign? integer-constant
    | sign? floating-point-constant

flag-comma-wsp:
    flag wsp* comma? wsp*

flag:
    "0" | "1"

comma:
    ","

integer-constant:
    digit-sequence

floating-point-constant:
    fractional-constant exponent?
    | digit-sequence exponent

fractional-constant:
    digit-sequence? "." digit-sequence
    | digit-sequence "."

exponent:
    ( "e" | "E" ) sign? digit-sequence

sign:
    "+" | "-"

digit-sequence:
    digit
    | digit digit-sequence

digit:
    "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

wsp:
    (#x20 | #x9 | #xD | #xA)+

11.3 Markers

To use a marker symbol for arrowheads or polymarkers, you need to define a <marker> element which defines the marker symbol and then refer to that <marker> element using the various marker properties (i.e., 'marker-start', 'marker-end', 'marker-mid' or 'marker') on the given <path> element or vector graphic shape. Here is an example which draws a triangular marker symbol that is drawn as an arrowhead at the end of a path:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG July 1999//EN" 
  "http://www.w3.org/Graphics/SVG/svg-19990706.dtd">
<svg width="4in" height="4in" 
     fit-box-to-viewport="0 0 4000 4000" >
  <defs>
    <marker id="Triangle"
      fit-bbox="0 0 10 10" ref-x="0" ref-y="5" 
      marker-width="1.25" marker-height="1.75"
      orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </marker>
  </defs>
  <desc>Placing an arrowhead at the end of a path.
  </desc>
  <path d="M 1000 1000 L 2000 1000 L 3000 2000"
        style="fill:none; stroke:black; stroke-width:100; 
        marker-end:url(#Triangle)" />
</svg>

Download this example

11.3.1 The <marker> element

The <marker> element defines the graphics that is to be used for drawing arrowheads or polymarkers on a given <path> element or vector graphic shape.

The <marker> element has all of the same attributes as the <symbol> element. Additionally, it has the following marker-specific attributes:

Markers are drawn such that their reference point (i.e., attributes ref-x and ref-y) is positioned at the given vertex.

11.3.2 Marker properties

'marker-start' defines the arrowhead or polymarker that should be drawn at the first vertex of the given <path> element or vector graphic shape. 'marker-end' defines the arrowhead or polymarker that should be drawn at the final vertex. 'marker-mid' defines the arrowhead or polymarker that should be drawn at every other vertex (i.e., every vertex except the first and last).

'marker-start', 'marker-end', marker-mid'
Value:   none |
inherit |
<uri>
Initial:   none
Applies to:  all elements
Inherited:  see Inheritance of Painting Properties below
Percentages:  N/A
Media:  visual
none
Indicates that no marker symbol should be drawn at the given vertex (vertices).
<uri>
The <uri> is an XPointer (???) reference to the ID of a <marker> element which should be used as the arrowhead symbol or polymarker at the given vertex (vertices). If the XPointer is not valid (e.g., it points to an object that is undefined or the object is not a <marker> element), then the marker(s) should not be drawn.

The 'marker' property specifies the marker symbol that should be used for all points on the sets the value for all vertices on the given <path> element or vector graphic shape. It is a short-hand for the three individual marker properties:

'marker'
Value:   see individual properties
Initial:   see individual properties
Applies to:  all elements
Inherited:  see Inheritance of Painting Properties below
Percentages:  N/A
Media:  visual

11.3.3 Details on How Markers are Rendered

The following provides details on how markers are rendered:

For illustrative purposes, we'll repeat the marker example shown earlier:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG July 1999//EN" 
  "http://www.w3.org/Graphics/SVG/svg-19990706.dtd">
<svg width="4in" height="4in" 
     fit-box-to-viewport="0 0 4000 4000" >
  <defs>
    <marker id="Triangle"
      fit-bbox="0 0 10 10" ref-x="0" ref-y="5" 
      marker-width="1.25" marker-height="1.75"
      orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </marker>
  </defs>
  <desc>Placing an arrowhead at the end of a path.
  </desc>
  <path d="M 1000 1000 L 2000 1000 L 3000 2000"
        style="fill:none; stroke:black; stroke-width:100; 
        marker-end:url(#Triangle)" />
</svg>

Download this example

The rendering effect of the above file will be visually identical to the following:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG July 1999//EN" 
  "http://www.w3.org/Graphics/SVG/svg-19990706.dtd">
<svg width="4in" height="4in" 
     fit-box-to-viewport="0 0 4000 4000" >
  <defs>
    <!-- Note: to illustrate the effect of "marker",
      replace "marker" with "symbol" and remove the various 
      marker-specific attributes -->
    <symbol id="Triangle"
      fit-bbox="0 0 10 10" ref-x="0" ref-y="5">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </symbol>
  </defs>
  <desc>File which produces the same effect
      as the marker example file, but without
      using markers.
  </desc>
  <!-- The path draws as before, but without the marker properties -->
  <path d="M 1000 1000 L 2000 1000 L 3000 2000"
        style="fill:none; stroke:black; stroke-width:100" />

  <!-- The following logic simulates drawing a marker 
       at final vertex of the path. -->

  <!-- First off, move the origin of the user coordinate system
       so that the origin is now aligned with the end point of the path. -->
  <g transform="translate(3000 2000)" >

    <!-- Now, rotate the coordinate system 45 degrees because
         the marker specified orient="auto" and the final segment
         of the path is going in the direction of 45 degrees. -->
    <g transform="rotate(45)" >

      <!-- Establish a new viewport with an <svg> element.
           The width/height of the viewport are 1.25 and 1.75 times
           the current stroke-width, respectively. Since the
           current stroke-width is 100, the viewport's width/height
           is 125 by 175. Apply the fit-box-to-viewport attribute
           from the <marker> element onto this <svg> element.
           Transform the marker symbol to align (ref-x,ref-y) with
           the origin of the viewport. -->
      <svg width="125" height="175" 
           fit-box-to-viewport="0 0 10 10"
           transform="translate(0,-5)" >

        <!-- Expand out the contents of the <marker> element. -->
        <path d="M 0 0 L 10 5 L 0 10 z" />
      </svg>
    </g>
  </g>
</svg>

Download this example

11.4 Implementation Notes

A conforming SVG user agent must implement path rendering as follows: