CIF/SVG output mappings
For each update of a single attribute of an element in the SVG image, an output mapping is needed. An output mapping essentially defines a connection between the CIF specification and the SVG image, for updating that specific attribute of that specific element.
A simple output mapping
Assume we have the following CIF specification:
cont pos der 1.0;
Where variable pos
is the position of some object, say a box. Then the following output mapping:
svgout id "box" attr "x" value pos;
Keeps the value of the x
attribute of the SVG element with id box
equal to the value of continuous variable pos
.
Syntax
The general syntax of CIF/SVG output mappings is:
svgout id <id> attr <attr> value <value>;
svgout id <id> attr <attr> value <value> file <file>;
svgout id <id> text value <value>;
svgout id <id> text value <value> file <file>;
The svgout
keyword is followed by a specification of an SVG element id. Every output mapping must specify the id of an SVG element, and an SVG element with that id must exist in the SVG image. The id
indicates the element for which an attribute or text is to be updated.
The id
is followed by a specification of what part of the SVG element is to updated. That is, either an attribute or text (label) is updated.
After that, the value of the attribute or text (label) is specified.
In the syntax examples above, we see that it is also allowed to declare an optional local SVG file declaration, that only applies to that specific output declaration.
SVG element id
Every output mapping needs to specify the id of the SVG element to update. The id is checked, to make sure an SVG element with that id actually exists in the SVG image.
Only valid SVG names may be used as ids. Valid SVG names start with a letter (a
to z
, A
to Z
), an underscore (_
), or a colon (:
), and may be followed by more of the same characters, as well as dashes (-
), dots (.
), and numbers (0
to 9
).
Ids must be put between double quotes. For instance, to use some-name
as id, it must be written as "some-name"
.
Instead of using a hard coded SVG element id, it is also allowed to use an expression that when evaluated results in the SVG element id. Such an expression must evaluate to a string
typed value, and must be statically evaluable (must not refer to variables that can change value during simulation, etc). For instance:
// Hard coded SVG element id.
svgout id "box" attr "width" value ...;
// Computed SVG element id.
const string c = "bo";
svgout id c + "x" attr "width" value ...;
The first output mapping applies to the SVG element with the id box
. The box
id is hard coded into the output mapping. The second output mapping uses the expression c + "x"
to specify the SVG element id. Once the expression is evaluated (its value is computed), this results in the string
typed value "box"
. As such, the second mapping applies to the SVG element with id box
as well.
The expressions may also refer to for instance algebraic parameters of automaton definitions. Since different values can be given to the parameters for each instantiation, this allows the SVG element id to vary for the different instantiations of the automaton definition. This particular usage allows for reuse and scalable solutions. The lamps example and workstation example are good examples of this usage. This usage is often combined with CIF/SVG copy declarations and CIF/SVG move declarations.
SVG attribute name
Every output mapping needs to specify the name of the attribute of the SVG element to update (or text
, see the Text labels section). Similarly to specifying ids, attribute names must be valid SVG names. They also need to be put between double quotes. Unlike SVG element ids, it is not possible to use expressions to specify attribute names. That is, only hard coded names can be used to specify attribute names.
It is not allowed to change the ids of SVG elements, as it could lead to duplicate or missing ids. As such, output mappings for the id
attribute (in any casing) are explicitly not supported. Similarly, changing the style
attribute (in any casing) using an output mapping is explicitly not supported, to avoid conflicting style changes. See also the SVG presentation attributes vs CSS style attributes section for more information about the style
attribute.
The supported attributes for an SVG element depend on what kind of element it is. For instance, a rect
element can have an x
and y
position, a width
and height
, a fill
color, etc. A g
element (a group) however, does not support those position attributes. It is beyond the scope of this document to go into more detail. The software however, will warn about using attribute names that are not supported according to the SVG standard (to catch simple spelling mistakes), and specifying attributes on elements that don’t support them. Consult the official SVG specification for further details. The examples showcase several commonly used attributes as well.
SVG presentation attributes vs CSS style attributes
SVG uses two kinds of attributes: SVG presentation attributes, and CSS style attributes. For instance, in the following partial SVG image:
<rect fill="red" id="rect1" width="25" height="25" x="65" y="5"/>
<rect style="fill:red;" id="rect2" width="25" height="25" x="15" y="5"/>
Rectangle rect1
uses the SVG presentation attribute fill
to specify the fill color the rectangle. Rectangle rect2
uses the CSS style attribute fill
to specify the fill color the rectangle. The SVG presentation attributes are all direct attributes of the SVG element. CSS style attributes on the other hand, are always part of the SVG presentation attribute style
.
CSS stands for Cascading Style Sheets, and it is a style sheet language used for describing the look and formatting of a document. It’s best known for its use in styling web pages written in HTML. Like SVG, CSS is an international standard developed and maintained by the World Wide Web Consortium (W3C). SVG reuses the CSS standard for its CSS style attributes. The most commonly used attributes for certain elements are also available in the SVG standard as SVG presentation attributes. Furthermore, SVG adds additional presentation attributes not found in CSS.
If an attribute is specified on an element using both an SVG presentation attribute, and a CSS style attribute, the CSS style attribute usually takes precedence. The output mappings handle all of this automatically and transparently. That is, you just specify the attribute name in the header of the output mapping, and the simulator makes sure the proper attribute is update, regardless of whether it is an SVG presentation attribute, or a CSS style attribute. It is explicitly not supported to change the style
attribute directly (using an output mapping), in order to avoid conflicting style changes when other output mappings update CSS style attributes that are part of that same style
SVG presentation attribute.
Text labels
Changing the text of text labels is a special case, as text is not stored in attributes. Consider the following partial SVG image, which contains a text label (created using Inkscape, and with some of the irrelevant details omitted):
<text x="5" y="5" id="text1" style="font-size:16px;">
<tspan x="5" y="5" id="tspan2">
The actual text.
</tspan>
</text>
Here we see a text
element with id text1
, which contains a tspan
element with id tspan2
. The tspan
element contains some text. To change the text of this text label, use one of the following mappings:
svgout id "text1" text value ...;
svgout id "tspan2" text value ...;
Here, instead of the attr
keyword followed by the name of the attribute, we simply specify the text
keyword. We can either use the id of the text
element, or the id of the tspan
element. More precisely, we can use the id of an element that contains text (such as the tspan
element in our example), or an element (such as the text
element in our example) that has a single child, which contains text, or an element that has a single child, which has an single child, which contains text, etc.
In practice, it is usually the easiest to use the Object Properties panel of Inkscape, to get the properties of the text label. The ID that is then shown, is the id of the text
element.
Output mapping value
In order for an output mapping to be able to update attributes or text labels, it needs a value. The simple output mapping example already showed how a value can be specified. This section further explains the details of the specification of such values.
The value
keyword is followed by an expression. This expression may for instance be a literal value, such as 1
, true
, 1.0
, "some text"
, or [1, 2]
. At first, it might not seem useful to use a literal as a value for an output mapping, since the mapping will then produce the same value every time it is applied. However, the rate example shows why this can in fact be very useful.
The expressions however, may also contain references to variables (discrete, input, continuous, or algebraic), functions, constants, locations, etc. For instance, we could use the value of a continuous variable and multiply it by two, by using x * 2
as expression, assuming that the continuous variable is named x
. Since we may refer to the state of the CIF specification, the value of the expression can change as the simulation continues, resulting in different values being mapped to the image.
The expressions can also include if
expressions, which are particularly powerful in this context. Using if
expressions, a different value can be used for several different conditions. See the workstation example for an example of using if
expressions in an output mapping.
Quoting and escaping
The value expression of an output mapping may be of any type. The result of evaluating the expression is converted to a textual representation that closely resembles the textual syntax of CIF, before using it to set the value of an attribute, or the text of a text label. For string literals this means that the text is escaped, and double quotes are added. If however the result of the expression is a string
typed value, then that string is used 'as is' (without quoting, and without escaping). Thus, consider the following examples:
svgout id "..." attr "..." value ["a\"b"];
svgout id "..." attr "..." value "a\"b";
The value of the first output mapping is a list that contains a single string value, while the value of the second output mapping is a string value directly. This results in the following texts being used as values of the attributes:
["a\"b"]
a"b
That is, in general string values are quoted and escaped, as is the case for the first example, where the result is a list. However, if the entire result is a string, as is the case with the second example, the string value is used 'as is', without quoting and without escaping.
Whitespace handling
If the textual result of an output mapping contains a new line character (for instance due to including \n
in a string literal or format pattern), the new line character is ignored by SVG. Furthermore, tabs (\t
) are replaced by a single space character. Finally, by default consecutive spaces (including tabs) are merged together into a single space, and spaces at the beginning and end of the output of a mapping are discarded by SVG.
This essentially renders \n
and \t
useless, as the first is ignored, and for the second spaces can be used instead.
This also means that it is not possible to set multiple lines of text using a single output mapping. This is a fundamental restriction of SVG, not of CIF/SVG output mappings. In order to set multiple lines of text, multiple output mappings are needed, where each mapping sets a different text label (a different line).
Note that if you enter multiple lines of text in Inkscape, this results in a single text
element, with multiple tspan
child elements. The actual text of such tspan
elements can then be updated using an output mapping for each tspan
element. The benefit over multiple text labels (multiple text
elements with a single tspan
child element each) is that the one text
element can be moved, making all the tspan
child elements automatically move with it. That is, the lines of text are kept together by Inkscape.
Uniqueness of output mappings
All output mappings must be unique, per SVG image. That is, no two mappings may use the exact same SVG element id and attribute name. Similarly, no two mappings may update the same text. That is, for the example above, it is not allowed to specify two mappings for the text of the SVG element with id text1
. However, since both elements text1
and tspan1
have the same text, it is also not allowed to specify output mappings for the text of those two elements.
Application
SVG output mappings are applied for states frames, throughout simulation. Their first application is after copy declarations and move declarations declarations have been applied. For more information, see the Application order section.