34 The Soft Path Subsystem

This section describes a set of commands for creating soft paths as opposed to the commands of the previous section, which created hard paths. A soft path is a path that can still be “changed” or “molded.” Once you (or the PGF system) is satisfied with a soft path, it is turned into a hard path, which can be inserted into the resulting .pdf or .ps file.

Note that the commands described in this section are “high-level” in the sense that they are not implemented in driver files, but rather directly by the PGF-system layer. For this reason, the commands for creating soft paths do not start with \pgfsys@, but rather with \pgfsyssoftpath@. On the other hand, as a user you will never use these commands directly, so they are described as part of the low-level interface.

34.1 Path Creation Process

When the user writes a command like \draw (0bp,0bp) -- (10bp,0bp); quite a lot happens behind the scenes:

  1. The frontend command is translated by TikZ into commands of the basic layer. In essence, the command is translated to something like


    \pgfpathmoveto{\pgfpoint{0bp}{0bp}}
    \pgfpathlineto{\pgfpoint{10bp}{0bp}}
    \pgfusepath{stroke}
  2. The \pgfpathxxxx command do not directly call “hard” commands like \pgfsys@xxxx. Instead, the command \pgfpathmoveto invokes a special command called \pgfsyssoftpath@moveto and \pgfpathlineto invokes \pgfsyssoftpath@lineto.

    The \pgfsyssoftpath@xxxx commands, which are described below, construct a soft path. Each time such a command is used, special tokens are added to the end of an internal macro that stores the soft path currently being constructed.

  3. When the \pgfusepath is encountered, the soft path stored in the internal macro is “invoked.” Only now does a special macro iterate over the soft path. For each line-to or move-to operation on this path it calls an appropriate \pgfsys@moveto or \pgfsys@lineto in order to, finally, create the desired hard path, namely, the string of literals in the .pdf or .ps file.
  4. After the path has been invoked, \pgfsys@stroke is called to insert the literal for stroking the path.

Why such a complicated process? Why not have \pgfpathlineto directly call \pgfsys@lineto and be done with it? There are two reasons:

  1. The PDF specification requires that a path is not interrupted by any non-path-construction commands. Thus, the following code will result in a corrupted .pdf:


    \pgfsys@moveto{0}{0}
    \pgfsys@setlinewidth{1}
    \pgfsys@lineto{10}{0}
    \pgfsys@stroke

    Such corrupt code is tolerated by most viewers, but not always. It is much better to create only (reasonably) legal code.

  2. A soft path can still be changed, while a hard path is fixed. For example, one can still change the starting and end points of a soft path or do optimizations on it. Such transformations are not possible on hard paths.

34.2 Starting and Ending a Soft Path

No special action must be taken in order to start the creation of a soft path. Rather, each time a command like \pgfsyssoftpath@lineto is called, a special token is added to the (global) current soft path being constructed.

However, you can access and change the current soft path. In this way, it is possible to store a soft path, to manipulate it, or to invoke it.

\pgfsyssoftpath@getcurrentpath{<macro name>}

This command will store the current soft path in <macro name>.

\pgfsyssoftpath@setcurrentpath{<macro name>}

This command will set the current soft path to be the path stored in <macro name>. This macro should store a path that has previously been extracted using the \pgfsyssoftpath@getcurrentpath command and has possibly been modified subsequently.

\pgfsyssoftpath@invokecurrentpath

This command will turn the current soft path in a “hard” path. To do so, it iterates over the soft path and calls an appropriate \pgfsys@xxxx command for each element of the path. Note that the current soft path is not changed by this command. Thus, in order to start a new soft path after the old one has been invoked and is no longer needed, you need to set the current soft path to be empty. This may seems strange, but it is often useful to immediately use the last soft path again.

\pgfsyssoftpath@flushcurrentpath

This command will invoke the current soft path and then set it to be empty.

34.3 Soft Path Creation Commands

\pgfsyssoftpath@moveto{<x>}{<y>}

This command appends a “move-to” segment to the current soft path. The coordinates <x> and <y> are given as normal TEX dimensions.

Example: One way to draw a line:


\pgfsyssoftpath@moveto{0pt}{0pt}
\pgfsyssoftpath@lineto{10pt}{10pt}
\pgfsyssoftpath@flushcurrentpath
\pgfsys@stroke

\pgfsyssoftpath@lineto{<x>}{<y>}

Appends a “line-to” segment to the current soft path.

\pgfsyssoftpath@curveto{<a>}{<b>}{<c>}{<d>}{<x>}{<y>}

Appends a “curve-to” segment to the current soft path with controls (a,b) and (c,d).

\pgfsyssoftpath@rect{<lower left x>}{<lower left y>}{<width>}{<height>}

Appends a rectangle segment to the current soft path.

\pgfsyssoftpath@closepath

Appends a “close-path” segment to the current soft path.

34.4 The Soft Path Data Structure

A soft path is stored in a standardized way, which makes it possible to modify it before it becomes “hard.” Basically, a soft path is a long sequence of triples. Each triple starts with a token that identifies what is going on. This token is followed by two dimensions in braces. For example, the following is a soft path that means “the path starts at (0bp,0bp) and then continues in a straight line to (10bp,0bp).”


\pgfsyssoftpath@movetotoken{0bp}{0bp}\pgfsyssoftpath@linetotoken{10bp}{0bp}

A curve-to is hard to express in this way since we need six numbers to express it, not two. For this reasons, a curve-to is expressed using three triples as follows: The command


\pgfsyssoftpath@curveto{1bp}{2bp}{3bp}{4bp}{5bp}{6bp}

results in the following three triples:


\pgfsyssoftpath@curvetosupportatoken{1bp}{2bp}
\pgfsyssoftpath@curvetosupportbtoken{3bp}{4bp}
\pgfsyssoftpath@curvetotoken{5bp}{6bp}

These three triples must always “remain together.” Thus, a lonely supportbtoken is forbidden.

In details, the following tokens exist: