How to cite this paper
DeRose, Steven J. “Graceful Diagramming with SVG plus AVTs.” Presented at Balisage: The Markup Conference 2026, Washington, DC, August 3 - 7, 2026. In Proceedings of Balisage: The Markup Conference 2026. Balisage Series on Markup Technologies, vol. 31 (2026). https://doi.org/10.4242/BalisageVol31.DeRose01.
Balisage: The Markup Conference 2026
August 3 - 7, 2026
Balisage Paper: Graceful Diagramming with SVG plus AVTs
Steven J. DeRose
Steve DeRose has been working with electronic document and hypertext systems
since 1979. He holds degrees in Computer Science and Linguistics and a Ph.D. in
Computational Linguistics from Brown University.
He co-founded Electronic Book Technologies in 1989 to build the first SGML
browser and retrieval system, DynaText,
and has been deeply
involved in document standards including XML, TEI, HyTime, HTML 4, XPath,
XPointer, EAD, Open eBook, OSIS, and others. He has served as adjunct faculty at
Brown and Calvin Universities and has written many papers, two books, and more
than fifteen patents. Most recently he has been working as a consultant in text
analytics.
Copyright 2026, Steven J. DeRose. This work is licensed under a Creative Commons
Attribution-Share-alike 3.0 unported license. See [http://creativecommons.org/licenses/by-sa/3.0/]
for more information.
Abstract
SVG is a mature XML vocabulary for vector graphics, but it has little parametric
structure and lacks semantic binding between connectors and the objects they
connect. Drawings produced in SVG are often hard to post-process, maintain, or
reason about. This paper introduces MVG (Meta Vector Graphics), an extension layer
over SVG that addresses these isues and can be implemented dynamically or via
preprocessing into plain SVG 1.0.
MVG adds general parameter passing via an XSLT-compatible Attribute Value Template
syntax, at two conformance levels: heiti-conformant
processors perform simple named-parameter substitution — nearly trivial to implement
— while kenning-conformant processors support full
XPath expression evaluation at the same syntactic hook. A port model provides named
attachment points on shapes, enabling connectors and labels to bind semantically
rather than to coordinates. MVG also adds shape primitives that SVG would otherwise
represent opaquely. Together these additions allow users to work at a level of
abstraction closer to their own conceptual models, with benefits for authoring,
editing, and downstream processing. Python code implementing MVG as a preprocessor
is provided.
Table of Contents
- 1. Introduction: Three Pain Points
-
- 1.1 The reuse/parameterization problem
- 1.2 The connection problem
-
- 1.2.1 Connectors
- 1.2.2 Labels
- 1.2.3 Decorated basic shapes
- 1.2.4 Walls vs. rooms
- 1.2.5 Ports
- 1.3 The creeping generality problem
- 1.4 Symbol libraries
- 2 General approach
-
- 2.1 Prior work
- 2.2 Parameter replacement
-
- 2.2.1 Automatic parameters
- 2.2.2 Levels of support
- 2.2.3 The scaling problem and
@scale-lock
- 2.3 Port and anchor models
-
- 2.3.1 Port definition
- 2.3.2 Port reference
- 2.3.3 Connector routing
- 3. Design Principles
- 4. Additional Shapes
-
- 4.1
mvg:rpolygon —
- 4.2
mvg:roundpolygon —
- 4.3
mvg:star —
- 4.4
mvg:arc —
- 4.5
mvg:smoothcurve —
- 4.6
mvg:wave —
- 4.7
mvg:spiral —
- 4.8
mvg:curly-brace —
- 4.9
mvg:tile —
- 4.10 itransform
- 4.11 coil (from TikZ)
- 4.12
mvg:block-arrow —
- 4.13 block_arc (from OOXML)
- 4.14 Line types
- 4.15 Arrowheads
- 5. Connectables
-
- 5.1. Connectors
- 5.2 Labels
- 5.3 Decorators
- 6. Conclusions
1. Introduction: Three Pain Points
SVG [SVG11] is a well-established and reliable XML schema for drawing. It
differs from many drawing tools in providing very few shapes, mainly <rectangle>,
<circle>, and <ellipse> plus generic tools such as <polyline>, <polygon>,
and <path>. Any other shapes must be constructed from these.
For customization and structure it offers a few tools to define macro
objects,
which are used via <use> with #
plus their ID on @href:
-
<g> (for group
) is rendered where defined. It is useful for re-using objects
(via <use>) rather than repeating them entirely.
-
<symbol> is a more pure
definition. It is only rendered when referenced. It
also imposes its own local co-ordinate space (with clipping to that viewbox).
-
<marker> is very similar to <symbol> but adds the option of auto-rotation to the current
direction of a <path>, and the notion of a refX/refY point to be
considered the origin when placed. These are especially useful for arrowheads,
so their direction and precise placement are appropriate to the line they are
attached to.
Co-ordinates can generally be expressed as percentages of the viewbox height and width.
For example, this defines a rectangle with a horizontal bisecting line:
<symbol id="bisected_box" viewBox="0 0 100 200">
<rect x="0" y="0" width="100" height="200"/>
<line x1="0%" y1="50%" x2="100%" y2="50%"/>
</symbol>
This can be instantiated via <use>, which may also set x,
y, height, and
width.
This paper introduces MVG
(short for Meta Vector Graphics
), a
layer on top of SVG that tries to address three main pain points related to
re-use:
-
The lack of a general way for <use> to pass values to a referenced object to modify
its
treatment. This notion adds a lot of power, specifically to make objects
declarative rather than procedural.
-
The lack of a way to attach things (such as ends of lines) to SVG objects rather than
co-ordinates.
-
The lack of some shapes (common in drawing apps) that are not easy to construct.
1.1 The reuse/parameterization problem
SVG can draw anything with enough paths (or even a single <path> element, raising
and
lowering the pen as needed). The most salient barrier to creating novel objects and
expressing them as such, is the lack of a way to pass in values on each use, that
modify that use.
<use> only allows passing a very small set of predefined properties:
-
x, y, width, and height, without
which re-use would be of little use. transform, which is important for resizing, rotating, etc.
And href.
-
Presentational attributes (fill, stroke, opacity, etc.) can
be inherited from the calling context, but
not passed in (which is not at all the same
thing).
Such values are known as parameters
, and are ubiquitous in programming, formal
logic, math, markup languages, and elsewhere. They greatly reduce space and
complexity. SVG uses parameters heavily for its built-in constructs; users just
can't have any for themselves. Consider drawing the unit octagon in SVG:
<polygon points="0.9239,0.3827 0.3827,0.9239 -0.3827,0.9239 -0.9239,0.3827
-0.9239,-0.3827 -0.3827,-0.9239 0.3827,-0.9239 0.9239,-0.3827" />
This is very general: any figure at all can be drawn. However, humans have concepts
and terms
for many more specific shapes (and coin new ones regularly). Humans also associate
many shapes closely with meanings. Regular polygons are the bread and butter of
drawing; yet to get them in SVG involves calculating and repeating all those
coordinates.
Most users would have to look up how to get from octagon, radius 1
to the set
of points just shown, and would not readily recognize the points as being a unit octagon.
For developers, the verbose representation is very slightly easier to implement:
def polygon_from_points(points: list[tuple[float, float]]) -> None:
moveto(points[0])
for pt in points[1:]:
lineto(pt)
lineto(points[0])
versus this for regular polygons:
def regular_polygon(cx: float, cy: float, r: float, n: int) -> None:
offset = math.radians(90 / n)
moveto(cx + r * math.cos(offset),
cy + r * math.sin(offset))
for k in range(1, n + 1):
lineto(cx + r * math.cos(2 * math.pi * k / n + offset),
cy + r * math.sin(2 * math.pi * k / n + offset))
The difference is minor for someone writing graphics code, and they must write similar
code
anyway — it just goes elsewhere. Having regular_polygon also saves on creating and parsing a long string of
points, and fits basic principles of software engineering such as Don't
repeat yourself
, as well as being more compact and less
error-prone.
For power users such as someone writing transforms over the
SVG, porting data, or looking at the actual values for any reason, the gain is vast.
With just points it takes real work even to identify all the octagons, especially
given floating-point number issuess. Just grouping objects into meaningful types is
a big win [DeRo20].
Many drawing programs retain shape types internally, but don't exported that data.
Inkscape
makes heavy use of custom options in a separate namespace, which is similar to our
approach below.
1.2 The connection problem
The first problem I consider is that SVG lacks a notion of connecting things to other
things
per se (cf [DeRo14]). It does support referring to objects by ID
for re-use, but this cannot be leveraged for this line should end at that
object
. Actual attachment is implicit, mainly (a) is drawn by the
same <symbol> object
, and (b) happens to be located
nearby
.
1.2.1 Connectors
The most obvious need for logical attachment to objects is the connector
. A
connector expresses a semantic relationship between objects. These are
ubiquitous in diagrams of all kinds (see definitions in [DeRo20]), but in SVG no such concept exists. Connectors also differ from most other
lines in that they commonly have meaningful direction and terminal
arrowheads.
Connectors are trivial for developers to support — you simply retrieve the referenced
object's location and use those co-ordinates. However, the distinct problem of
routing the connectors can be harder.
Minimal routing solutions are simple: draw a straight line from start to end, or
let the user set the route just like they would for <polyline>. But better
automatic routing is harder, and a point of competition for
implementations.
Omitting the notion of connectors does not ease the routing problem, but adds substantial
extra work for users, bloats the data, compromises portability and
post-processability, and leads to aesthetic problems.
-
Most obviously, if a user moves either box that seems connected, the line doesn't follow.
-
Endpoints are imprecise. Snapping helps, but is typically to the
background grid, not the target box edge.
-
Automated processing cannot fix this. Searching for the nearest vertex
is a good heuristic, but often fails.
The amount of manual editing work this one omission creates is astonishing, particularly
given how ubiquitous connectors are in drawing programs, how conceptually and structurally
distinct they are, and how easy they are to implement (at least with basic routing).
1.2.2 Labels
A very similar issue arises because SVG objects do not own labels. A large share of
boxes want
<text> labels, but in SVG that attachment cannot be readily expressed. One
can mebed a <text> object inside another shape, but it doesn't help because
one cannot pass specific text in when it is <use>d.
1.2.3 Decorated basic shapes
A third example emerges from the shape inventories of many drawing apps. Many shapes
are
merely slight modifications of others. For example, folder
is a
rectangle with a small tab added; page
is a rectangle with a
folded corner; flowchart subprocess
and draw.io's
envelope
are rectangles with extra lines; and so on.
Some cases are achievable with <symbol>, but as before the lack of parameters is limiting.
For example, it can't express a <folder> that can position its tab wherever
the user wants, or a <decorated-rect> that lets the user choose another shape
as decorator.
1.2.4 Walls vs. rooms
A similar case shows up in architecture apps: walls and doors are highly salient user
objects,
but have an awkward relationship: a wall's two sides belong to different rooms,
and some rooms (such as a porch) are not even completely enclosed. Some apps,
such as SweetHome 3D [https://github.com/ralic/sweethome-3d], use an XML file format
and/or can export SVG, but even though walls and rooms may be linked by IDs,
they are not inherently related. Worse, they are not even co-located (room edges
may be offset by half the walls' thicknesses, with odd consequences).
1.2.5 Ports
At minimum, supporting such connections requires only a way to draw line-like objects
whose
end locations are given as IDREFs to objects (rather than co-incident
co-ordinates). But it is very useful (and common outside SVG) to specify
where on such an object to attach. Most
drawing apps provide a notion of ports
(aka
handles
, glue points
, or
anchors
), which can be defined on shapes and are attached
to.
Without ports, routing can default. The connection semantic is then intact, but rendering
is
be ideal. Ports address this.
The user easily provides port choices when they create line
in the first place; apps typically provide snap to
functionality
for this. SVG requires roughly the same work on creation, but adds much work on
any edit. The precision problems mentioned earlier may seem minor, but [Will94] points out that even slight misalignments come across as
mistakes in graphic design:
A problem with many non-designers' publications is a subtle lack of alignment [36]
All these minor misalignments add up to create a visually messy page. [37]
If your alignments are strong, you can choose to break through the alignment consciously and it will look intentional. [41]
1.3 The creeping generality problem
Beyond parameters and ports, SVG has no user-accessible constructs for looping or
calculation (other than expressing co-ordinates as percentages of the current
viewbox). Rendering some kinds of objects requires multiple operations, such as
iterating through a points or path attribute. Another common need is calculating locations
relative to the enclosing shape (SVG does have a notion of % of bounding box
size).
SVG uses all these concepts inside primitives. Making them user-available,
however, is a large design task (as the [Bell18] effort
discovered), so the SVG limitation is understandable even if unfortunate. Adding
such features to SVG has been discussed, but never actually finalized.
SVG does permit embedding Javascript code that operates on the resulting DOM.
However, it runs at load time rather than separately for (say) each <use> of a
given <symbol>. XSLT can similarly process SVG code, tokenize points or other
attributes, and loop or calculate at transform time, writing out more SVG; but it's
not especially easy. MVG instead proposes a very much smaller extension.
1.4 Symbol libraries
SVG decided not to include many predefined shapes. Its inventory includes <rect>,
<circle>, <ellipse>, <line>, <polyline>, <polygon>, and <path>.
Anything can be drawn somehow, but not always descriptively.
Nearly all drawing apps have many more shapes than SVG, many of which are familiar
and
intuitive for users. I examined the shape inventories of several drawing apps,,
primarily graphviz [GVShapes] and [Gans93],
draw.io [Draw], Inkscape [Inkscape], and TikZ
[TikZ]. I also considered Canvas, LibreOffice Draw, and
PowerPoint.
One could never specify all the shapes humans will invent. But some shapes are common,
or even
what [Pike67] christened emic
: they are not merely
a sensory experience, but a more abstract categorial value or symbol.
The good news is that given parameterization and ports only a few shapes enable constructing
many others. MVG thus defines several new drawing objects, particularly ones that
require iteration, calculation, or testing conditions. For example,
<regular_polygon sides=""> needs to iterate sides times and do a calculation each time. Others involve
subdividing a main shape regularly.
The initial MVG implementation is a Python pre-processor that transforms custom elements,
parameterization, and ports into basic SVG 1.0. It will be placed at
https://github.com/sderose/mvg,
and is freely re-usable. It takes only a few hundred lines.
I have sought to choose parameters for consistency across shapes even though shapes
can be
specified in a variety of ways. For example, an ellipse can be specified in any of
the ways listed below, but I follow the SVG precedent (listed first):
-
Center + two radii (cx, cy, rx, ry) — SVG <ellipse>, TikZ \draw (cx,cy) ellipse (rx
and ry), similar to Graphviz.
-
Bounding box — LibreOffice Draw, PowerPoint/OOXML, draw.io show this, but might not
use it internally.
-
Center + semi-major axis + eccentricity — astronomy/orbital mechanics (Kepler), not
drawing tools.
-
Center + semi-major axis + aspect ratio — TikZ shapes.geometric ellipse uses minimum
width/minimum height, which is effectively this. PowerPoint also has
something similar.
-
Parametric angle sweep (cx, cy, rx, ry, start_angle, end_angle) — SVG <path> arc command,
Canvas ctx.ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle).
-
Two foci + point on curve, or two foci + major axis length, or three points on the
curve — mathematicians and some CAD or GIS systems (e.g., FreeCAD constraint-based
sketcher, PostGIS ST_MinimumBoundingCircle-style fitting).
-
Center plus conjugate diameters — two vectors from center defining a parallelogram
that
the ellipse is inscribed in; allows sheared/rotated ellipses without a
rotate parameter (Matplotlib's matplotlib.patches.Ellipse?).
2 General approach
The overall challenges are adding parameter support, adding ports, and defining the
new
symbols. The layered approach minimizes disturbance to SVG implementations. All the
extensions use a separate namespace.
2.1 Prior work
A lot of conceptual ground has been productively explored by others, some of whom
I list here.
I have tried to build on such concepts, aiming at a most bang for the least
buck
compromise.
-
Mary Holstege's extensive work with XSLT, SVG, and other tools for art [Hols20] and [Hols23]
-
XPath/XSLT/XQuery work such as [Kay17a] and [Kay17b]
-
SVG 2 (a CR) and the SVG Parameters proposal (a WD) [Sche09a], [Sche09b], and [Bell18].
-
Inkscape and the Sodipodi namespace [Inkscape]. This architecture is broadly similar, especially in using a secondary namespace
to separate extensions, and mapping them (at some level) to regular SVG.
-
TikZ/PGF [TikZ]. The node-as-first-class-object also appears prominently here, for example, treating
label + bounding box + named anchors as composite unit: \inheritsavedanchors.
-
GraphML [GraphML]. This treats <port> as first-class named element, though the position is left to extensions. As noted
in [DeRo20], GraphML's underlying graph-theoretic model is attractive.
-
Eclipse Layout Kernel [ELK], [Domr23]. ELK seems to have the most formally specified port model in the layout literature:
side + position + constraint level. I have not gone quite that far.
2.2 Parameter replacement
Parameterization requires three conceptual parts: declaration, referencing/use, and
passing.
In XSLT, parameters are declared by full-fledged sub-elements of <xsl:function>.
For
example:
<xsl:function name="clamp" as="xs:double">
<xsl:param name="val" as="xs:double"/>
<xsl:param name="hi" as="xs:double"/>
<xsl:value-of select="min(($val, $hi)) => max(0)"/>
</xsl:function>
For MVG we want parameters on most or all SVG shapes or shape-like objects, and we
don't have
a <function> element already to hand. For this more limited context, the XSLT
form seems to me slightly heavy, especially since the existing drawing objects are
the "functions". A more compact syntax suffices: Parameters are declared merely by
setting them on the object that is to receive them, with the value there as the
default. I have shown initial _
so they cannot collide with SVG
attributes (of course, such attributes must be added to one's schema for validation
to work). It is a simple matter for an application to add the attributes to the
symbol table before interpreting the body:
<symbol id="somegon" _sides="4" _fgcolor="red">
...
</symbol>
Referring to parameters within the function
body (e.g., the
<symbol> element) exactly copies XSLT's Attribute Value Templates (AVT) syntax,
with curly braces and $
:
<symbol id="somegon" _sides="4" _fgcolor="red">
<polygon sides="{$_sides}" foreground="{$_fgcolor}" />
</symbol>
For most cases MVG does not need a whole AVT evaluator, but only two very
constrained specal cases. Thus, MVG developers and users need not implement,
integrate, or really even understand XPath, XSLT, or AVTs; just those special cases
(on which see Section 2.2.2).
Invocation is just using the parameterized drawing element, setting any
non-default parameters by using attributes in the usual way:
<use href="#somegon" _sides="8" _fgcolor="blue"/>
2.2.1 Automatic parameters
Given their importance to almost all objects in SVG, the coordinates of the
bounding box are likely to be needed often. Therefore MVG defines them to be
available as if they were attributes on the object.
Often, they actually are exactly that: x,
y, width,
and height and others are there explicitly, and
so naturally available via AVTs. However, they can be given in other ways, or
modified. For MVG purposes, we want the resolved values (for example, so objects
far away can attach to them). So these attribute names are reserved for that
purpose (experience may recommend adding others):
bbLeft bbRight bbCenterX
bbTop bbBottom bbCenterY
bbWidth bbHeight
2.2.2 Levels of support
The implementation of <use> must interpret the body of the referenced element, replacing
AVT expressions in the same way AVTs work in XSLT. This does mean that the final
interpretation of the used object must wait until it is used (for example, the
implementation can't just interpret it fully when a definition such as
<symbol> is first read, and then naively copy the result for each <use>),
just as it can't finalize x or y. This may involve some architectural
adjustment, but is not in principle difficult.
To enable simplicity of implementation but also higher functionality, MVG defines
two
conformance levels. They are named after two devices of Old Norse skaldic
poetry:
The first is heiti-conformant: a heiti in Norse is a simple synonym substitution — one
name for another, no interpretation required. At this level,
{$sides} in an attribute value is replaced by the literal
string value of the sides parameter. The grammar for references is
not the full AVT language, but merely the {$name} and {id($name)/@name}
(escaping literal "{" by doublilng it is also necessary):
expr ::= "{" "$" name "}"
::= "{" "id($" name ")/@" name "}"
The second, optional conformance level is called kenning. In
Norse, a kenning is a compound poetic
expression requiring interpretive calculation, such as whale-road
for sea. At kenning level, applications
support the entire XPath expression language (thus providing arithmetic, string
handling, XPath axes, etc.). That greatly increases the power, and is especially
valuable for doing arithmetic on co-ordinates. It intergrates in exactly the
same way; only the interpreter for the brace-expressions needs to be
upgraded.
For kenning, MVG permits applications to choose the
version(s) of XPath to support (likely 2 or 3 at this time). Trigonometric
functions are especially important in SVG (see, for example, [Hols20] and [Hols23]). They come for free with
XPath 3 [Robi14], or can be provided in XPath 2 [Berg10] via EXSLT's math
library, or by other
means. The Saxon Java extension mechanism would also work well for this. XPath 1
[Clar16] does not have AVTs.
If starting from scratch, supporting full expressions would involve implementing an
XPath
engine; but many XPath implementations exist, and many apps involving SVG
already have one of those to hand. In that case the extension should be
straightforward.
Parameterization of either level must be supported not only for <symbol> and <use>,
but
for all SVG and MVG elements (that's probably easier anyway; it just goes
directly into generic processing).
text seems to be the only case where {} could occur literally in an SVG attribute, but
brace-doubling works for that.
One could consider using CSS var() and calc() for some level of parameter support. However, that brings
in many other issues, as well as calc having
limited power (see the discussion in [DeRo18]).
2.2.3 The scaling problem and @scale-lock
Some properties should not scale when the object they are
part of scales (perhaps font-size, line-weight, dashed-line segment lengths,
etc) . It may prove necessary to offer a scale-lock setting for these, but with
parameters it is likely possible to get all the needed effects in other
ways.
2.3 Port and anchor models
2.3.1 Port definition
The fundamental requirements for ports include a way to define them when defining
a <symbol> with a name and a location; and a way to attach objects (connectors, labels,
shape-decorators, etc) to them.
An MVG port name is an XML NAME, with three additional requirements. They:
-
must be unique within each <symbol>, but may be re-used in different ones;
-
must not contain .
(more on that below);
-
must not match the name of any attribute SVG defines (especially for <use>).
Port definitions look like this:
<symbol id="foo">
<port name="top" x="100%" y="0"/>
<port name="foo-3" x="10" y="25%"/>
...usual SVG...
</symbol>
x and y attributes, with
co-ordinate values as usual (including possibly with %
), specify
the port's location in the <symbol>'s viewbox. They mayt point outside the
viewbox; one might, after all, want to place something adjacent but outside the
target object.
This method is not great for shapes like circles or ellipses (quick! tell me the x%
and y% for
the upper-right of the unit circle). Many drawing apps support compass points
for this and other uses (for example, Graphviz, TikZ, and mxGraph/Visio). Some
others support numeric angles (for example, TikZ/PGF, though it counts in the
opposite direction from SVG). Therefore, MVG also allows angle as a mutually-exclusive alternative to x and y. angle's value may be either a reference angle
(counting in degrees CW from east), or one of the 8 major compass points (upper
case), or CENTER (which is also the default if none of x, y, or angle is provided):
<port name="port2" angle="NE".../>
For convenience, the 8 compass point abbreviations and CENTER are also predefined
to be port
names with the same meanings. Users may not re-define them via <port>. Port
name ANCHOR also has a special meaning, to be discussed later.
Also allowed is edge segment number plus distance along that edge. MVG currently permits
this
in this form (segments count from 1 like XPath, and the second token defaults to
50% for distance along that segment):
<port name="foo" segment="5 30%" />
This is especially valuable for <polygon> and similar. However, this is only meaningful
given a normative starting segment. That segment is known for polyline and polygon. Curves are construed as having only 1 segment. For shapes
that do not have an obvious starting segment, we define the outermost segment
passing through Θ = 0 as that segment. If the segment number is out of range for
the object, Θ = 0 is used instead.
Note that the precise placement behavior relative to any of these locations is slightly
different for labels, ports, and decorators. A port is actually a point, so on a
rectangle, specifying NE or a corresponding angle means a connector actually
terminates on that corner. However, a label or decorator occupies space with the
object it is bound to, and so needs to know which part of it goes right on the
port.
This is easily solved. Labels and decorators are themselves objects, and so can define
their
own ports. As noted earlier a port named ANCHOR is reserved, which is used as
the label's or decorator's place to align with the specified port on the target
object. ANCHOR can have its location defined like any other port, but it
defaults to the center of the bounding box.
2.3.2 Port reference
Reference to ports may be useful in various places, such as:
-
specifying the attachment target for connectors or similar
-
replacing a point location within <polyline points="..."/> or similar
-
referring to the port's x or y location in cases where SVG expects those as separate
items.
But there are a few syntactic issues for using port names. Using a port requires also
specifying the object (typically via <use>). SVG references typically specify
#
plus an ID value using href. But where should MVG put the port name?
-
It could go on an additional attribute, but that seems a bit clumsy
and doesn't fit neatly into existing SVG objects or XPath queries (
these <polyline> could as well be a new <connector> type):
<polyline start="#obj12" start-port="S" end="#obj30" end-port="NE"/>
-
It could be added as if it were a second fragment identifier, but that is a bit odd:
<polyline start="#obj12#S" end="#obj30#NE"/>
-
It could be compounded onto the ID so the compound remained an XML NAME, but I think
it would be less clear:
<polyline start="#obj12.S" end="#obj30.NE"/>
Considering that such locations could also be quite useful as points, it seems desirable to keep them as single tokens, and to
make a way to refer separately to their actual x and y locations
(post-resolution). But that means x
or y
must also
be specified somehow.
In addition, it is highly desirable to have a compact, readable way to refer to port
locations
in XPath expressions (both in general, and for MVG itself).
Getting at such values is possible, but not pretty in XPath:
id(objId)/port[@name = 'NE']/@x
However, the entire second step can be eliminated by this defining that a port definition
P on
an object has the effect of creating attributes on each <use> of the object
(implementations may calculate these lazily). The attributes' names and values
are:
-
P (the same as the port name), whose value is the string of the resolved co-ordinates
of the
port in that object's viewbox.
-
P.x (that is, the port name with .x
appended), whose value is the x coordinate
of the port; and
-
P.y (that is, the port name with .y
appended), whose value is the y coordinate
of the port.
Note that all these names are still valid XML NAMEs. The dots here are why port names
are not
allowed to contain dots. In XPath, the expression shown above then shortens to
this:
id(objId)/@NE.x
This is just normal XPath given the generated attributes just defined (that is, the
XPath
implementation doesn't have to know that .
is special here).
Within a <symbol> or similar definition, the ID for a particular <use> of
it is not known. This means we need also to add it to the available attributes
(as use_id
).
The same syntax could be embedded within points or other
attributes for implementations that provide no support for more complete XPath
expression syntax in {}.
There is some added value in having access to properties of an object more generally,
particularly width and height, as well as the handy x+width and y+height, which
are the opposite corner of the bounding box (perhaps as x2 and y2. It requires little
effort to support the form above for all SVG elements and attributes (the XPath
would just work). Indeed, it would typically take more programming effort to
avoid that. In that case the port-specific
usage reduces to the convention that the locations of an object's ports are
attributed to the object for convenience.
2.3.3 Connector routing
MVG distinguishes the fact of connection from the routing chosen to render it. Routing
algorithms are highly varied, and differ greatly in complexity. Thus, MVG
defines names for several general approaches, but does not require apps to
implement any but line
and polyline
, which have
the same behaviors as those SVG elements.
MVG introduces a routing attribute for those elements, which
is a pragmatic hint that renderers may treat as a request for a particular
routing method. If an unsupported routing method is requested, apps may simply
fall back to line for lines, and polyline for polylines.
See [Wybr06] and [Tama87] for general information on routing. The defined routing method names in MVG are:
-
direct (straight line from port to port; as noted in [DeRo20] this may be ugly, but at least expresses the correct connection);
-
poly (user-specified waypoints)
-
orthogonal (alternating horizontal and vertical segments, with the first and last segments no
colinear with the face(s) adjacent to the respective port) [Wybr09]
-
curved (for example, using spline interpolation) [Dobk97] and [Frei01]
-
force-directed this acts as if the connectors contain springs, and minimizes stretching force [Eade84] and [Fruc91] Such methods are sometimes integrated with movement of the endpoint shapes
-
auto (obstacle avoidance, not otherwise specified). [Dobk97] and [Dwye09]
-
bundling some algorithms also combine parts of connectors to reduce crowding [Holt06]
Additional types of routing may be supported by implementations, and should be named
beginning
with x-
.
MVG also provides a hint to control what happens when connectors cross. Common renderings
are
(a) do nothing, (b) open a small gap for one, or (c) render a half-circle hop
for one. These can be expressed in MVG as shown below, but applications are not
required to implement them. If an unsupported value is requested, the attribute
is ignored, and SVG's default behavior (essentially none) applies.
<mvg:connector mvg:crossings="bridge|gap|none"...>
Connectors, labels, and lines may also have ports,
3. Design Principles
MVG provides a few elements in a separate namespace from SVG. All can be implemented
fairly
easily in the sort of environment where SVG is in use, and all can be mapped to vanilla
SVG 1. I provide a pre-processor implementation that does just that.
MVG's additions should be highly intuitive to users of XML, XSLT, and SVG, because
they re-use
notions that are very well known there. The overall goal is to make MVG more
descriptive, so users can define shapes and other constructs that correspond better
to
their own conceptual models, and that greatly reduce tedium.
4. Additional Shapes
A review of shape inventories across multiple drawing apps revealed these shapes which
are
difficult to implement merely via SVG <symbol>, even with MVG parameterization added.
Usually this is because they need iteration or non-trivial conditional logic. An MVG
implementation should provide them. I provide implementations of them in Python for
convenience.
The specific criteria for inclusion here are that a shape showed up in at least one
of the
drawing app inventories considered, or greatly eases construction of other shapes;
and
that expressing it in SVG 1.x requires either
-
an unbounded number of elements or coordinates as a function of its parameters — O(n)
SVG for O(1) conceptual content, or
-
a fixed number of coordinates that are opaque encodings of a small parameter set,
with the parametric structure lost. The first criterion is the stronger case; the
second covers shapes like block arrows where the vertex count is fixed but coordinates
are non-recoverable functions of shaft-width, head-width, head-depth, etc.
All these elements also allow the transform or rotate attributes common in SVG.
4.1 mvg:rpolygon —
This represents a regular polygon by its center, radius, number of sides, and rotation:
@cx, @cy, @r, @sides.
4.2 mvg:roundpolygon —
This represents a polygon (not necessarily regular) but with uniform rounded corners.
It is
specified like SVG <polygon>, but adding @corner-r to represent the
radius for the rounded corners.
4.3 mvg:star —
A star polygon, in which alternating vertices have radii of r-inner and r-outer.
@cx, @cy, @n, @r-outer,
@r-inner. n should typically be even. Based on Inkscape
sodipodi:star.
4.4 mvg:arc —
This is similar to ellipse, but can draw just a portion: a circular or elliptical
arc.
@cx, @cy, @r, @start-angle,
@end-angle. SVG has circle and ellipse but lacks this useful case.
Drawn clockwise.
4.5 mvg:smoothcurve —
This draws a smooth spkine curve (such as Catmull-Rom) through @points knots.
User specifies knots only; preprocessor computes Bézier control points. This
can eliminate many cases where SVG ends up containing of large static coordinate
dumps being briefer, more perspicuous, and propertly scalable.
4.6 mvg:wave —
This draws basic sine, cosine, and other periodic curves. @x1 @y1 @x2 @y2,
@type (sine | square | sawtooth | triangle),
@amplitude, @frequency, @phase. x and y
represent placement of the origin. This covers the document shape's bottom edge, but is generally useful in technical
work. Phase is measured in degrees. Phase 0 must be defined for each wave type, for
example sine rises rightward from (0,0). The conventions I have encountered for the
others seem to prefer falling from their maximum amplitude.
type permits x-
prefixed values for extension,
and such extensions must specify their initial phase state.
4.7 mvg:spiral —
Draw an Archimedean spiral. @cx, @cy, @r-start,
@r-end, @turns, @t0 (start fraction,
0–1). Subsumes Inkscape sodipodi:spiral.
4.8 mvg:curly-brace —
This represents the curly braces commonly needed in technical drawing. @x1 @y1 @x2
@y2 (endpoints), @depth (bow depth),
@orientation (left | right). Consists of three Bézier curves
whose control points are computed from the parameters.
4.9 mvg:tile —
This provides simple iteration across x and/or y. Within a bounding box, repeats a
child
element at regular intervals of dx and dy. For example:
<mvg:tile x="0" y="0" width="400" height="300"
dx="50" dy="50"
nx="8" ny="6"
odd-row-phase-x="0.5">
<mvg:ngon sides="6" r="20" cx="0" cy="0" style="fill:none; stroke:#ccc"/>
</mvg:tile>
dx/nx and dy/ny are complementary pairs: specify either spacing or count; the other is derived from
the bounding box dimension. If both are given, count takes precedence and spacing is computed.
Phase attributes @phase-x, @phase-y offset the whole pattern relative to the bounding box. @odd-row-phase-x, @even-row-phase-x, @odd-col-phase-y, @even-col-phase-y do this for alternating rows and columns in units of dx/dy, as needed for brick,
hexagonal, and some other layouts). Rows and columns count from 1. All phase attributes
default to 0.
Basic grids fall out as a special case: a horizontal line child repeated at dy
intervals, plus a vertical line child repeated at dx intervals. A minor
grid can be handled via two nested mvg:tile elements with different
stroke styles.
4.10 itransform
This is somewhat similar to <tile>, but instead of
simply moving the sub-object across the referencing object's bounding box, it
repeatedly applies a transform. This enables positioning things across an affine
path.
4.12 mvg:block-arrow —
This provides an (optionally filled) directional arrow shape. @direction takes
the same values as the angle parameter of
<port>s. @shaft-width, @head-width,
@head-depth define basic arrowhead dimension. @tip
uses the arrowhead types defined below.
4.13 block_arc (from OOXML)
This is basically like arc (see above), but draws the arc twice,
separated by @shaft-width and centered at the given r.
4.14 Line types
SVG <line> already provides extensive control over stroke rendering. Comparison with multiple
drawing apps suggested only a few additions, all expressed as mvg: presentation attributes applicable to any stroked element (shapes, connectors, or
standalone lines):
@mvg:crossings — controls what happens when connectors cross. Three values: none (do nothing, the SVG default), gap (open a small break in the lower connector), and bridge (render a half-circle hop). Implementations are encouraged but not required to implement
all three; the interaction with routing choice is noted in §2.3.3.
@mvg:stroke-repeat and @mvg:stroke-gap — draws multiple copies of the stroke, to make double, triple, or similar lines.
stroke-gap control blank space between the repetitions. The entire set of strokes is centered
where a single stroke would be centered. The result if this is used with dashed lines
is not defined.
@mvg:corner-radius — generalizes SVG's rx/ry on <rect> to <polygon> and <polyline>, with a single uniform radius (no rx/ry distinction). Deliberately avoids the rx/ry names, which mean something different on <ellipse>.
With these additions, nearly all the line-type capabilities of the surveyed apps are
covered.
4.15 Arrowheads
Drawing apps also commonly provide libraries of arrowheads, which can attach to
the ends of (at least) lines. My review found high overlap on basic forms, but much
variation at the edges. A large share of the variations, however, are easily
constructible with general SVG and MVG constructs.
MVG defines but does not require, an <mvg:arrowhead> object that works like SVG
<marker> but has settings that can produce a wide range of arrowheads. Arrowhead
size is governed by the bounding box and transform on <mvg:arrowhead>, just like
SVG <marker>.
The attribute are those of <marker>, plus:
-
shape: either none
(or ), or one of
triangle
, vee
, dot
,
diamond
, box
, tee
,
curve
, crow
(drawn from ER diagrams).
Extensions should be prefixed by x-
. These are the same as in
graphviz once you remove affixes such as used in odiamond
(open diamond). The affixes are covered by the other settings, which also
make them slightly more general than in graphviz. inv
in
graphviz means a 180° rotation, so can be done with SVG's ubiquitous
transform or with marker orient. graphviz normal
is just
triangle
.
Because Unicode has a huge variety of useful arrows (e.g., U+2190–U+21FF),
dingbats, and other shapes, MVG defines the convention that if shape is set to a single Unicode character, that character is used.
The 0 rotation has the character readable from the perspective on one standing on
the line leading up to it, and scaled to fill the <marker> viewbox.
-
filled: open
, halfopen
, or
filled
(the default).
-
clipped: left
, right
, or full
(the default)
MVG does not address the fact that graphviz allows stacking a sequence of
arrowheads onto a line-end.
Several other arrowhead types I found are addressable by the Unicode-character
alternative:
-
some EE conventions (primarily in Europe?) use slash or backslash-like
shapes as arrowheads.
-
OOXML has a bracketArr head, that looks
like a square bracket.
-
LibreOffice has a wavy or zigzag terminus, for which various tildes
(U+0007e, U+FF5E, etc.), wave dash (U+301C), almost equal to (U+2248), or
sine wave (U+223F) may suffice.
-
TikZ has quite a few more.
5. Connectables
5.1. Connectors
Connectors do not require a new element, but are simply a useful combination of <line>
or
<polyline> with parameterization, ports, and the routing pragma. For example:
<mvg:line obj1="id1" port1="e"
obj2="id2" port2="w"
routing="direct"
linetype="dashed"
arrow1="none" arrow2="filled-triangle">
</mvg:line>
<text> objects to serve as labels may be attached to a connector
just as they are to other shapes.
5.2 Labels
SVG <text> objects benefit from parameters and ports, and can simply refer to the
object to
which they attach instead of setting x and
y position manually. It would instead be
feasible to express the attachment the other way. However, that would need to apply
to many (all?) shapes and grouping objects, and would need a way to do either raw
strings, or objects with more structure such as complex formatting properties or
multiple <text> parts.
<text> objects in MVG can define ports just like other objects. By default, their
ANCHOR port is placed at the ANCHOR of the referenced
object (ANCHOR defaults to the center of the relevant bounding
box).
5.3 Decorators
A decorator is the MVG term for a shape (perhaps a
<symbol> or <marker>) attached to a host shape to create a new (sub-)class of
shape. For example, the commonplace folder shape can be constructed (or construed)
as a rectangle with an extra rect or round-rect placed somewhere along the
top.
Given MVG as already described, decorators are simply a concept; no additional elements
are
required. Both shapes can be drawn by an enclosing <symbol> or similar, or one
can be attached by setting its location using a port or coordinate reference to the
host shape. The decorator's own ANCHOR port aligns with the host's
target port, and the decorator inherits the host's coordinate system for rendering
purposes.
Decorator positioning reuses the port-location grammar of §2.3.1: @attach names the host port; @anchor names the decorator's own contact point (default: anchor port of the decorator, which itself defaults to center). The @scale-lock attribute (§2.2.3) prevents decorators from scaling disproportionately when the host
is resized.
No new element type is required. A decorator is any mvg:symbol instance referred to from an @attach attribute on <mvg:use>:
<mvg:use href="#tab" attach="n" anchor="s"
mvg:width="{$tab-w}" mvg:height="{$tab-h}" />
The preprocessor resolves the port coordinates and emits an SVG <use> at the
computed position.
6. Conclusions
This work defines and implements MVG, a layer over SVG that provides more declarative,
user-oriented construction for drawings. Everything in it can be reduced to plain
SVG
(for example, with the provided pre-processor).
It is mainly intended to make it easier, clearer, and more compact to express drawings
descriptively in cases where that is difficult to do in plain SVG. It provides two
conformance levels: heiti-conformant (string
substitution only — nearly trivial to implement) and kenning-conformant (full XPath AVT expression evaluation). The heiti level paves the way for kenning because the latter merely attaches a better AVT expression
evaluator in the same context as the trivial one needed for heiti.
References
[Bell18] Bellamy-Royds, Amelia; Bogdan, Brinza; Lilley, Chris; Schulze, Dirk; Storey, David;
and Willigers, Eric. Scalable Vector Graphics (SVG) 2. W3C Candidate Recommendation
04 October 2018. https://www.w3.org/TR/SVG2/
[Berg10] Berglund, Anders; Boag, Scott; Chamberlin, Don; Fernández, Mary F.; Kay, Michael;
Robie, Jonathan; and Siméon, Jérôme. XML Path Language (XPath) 2.0 (Second Edition).
W3C Recommendation 14 December 2010. https://www.w3.org/TR/xpath20/
[GraphML] Brandes, Ulrik, et al. 2014. Graph
Markup Language (GraphML).
In Tamassia (ed.), Handbook of Graph Drawing and Visualization. CRC Press. http://cs.brown.edu/people/rtamassi/gdhandbook/chapters/graphml.pdf
[Clar16] Clark, James and DeRose, Steve. XML Path Language (XPath) Version 1.0. W3C Recommendation
16 November 1999 (Status updated October 2016). https://www.w3.org/TR/xpath-10/
[SVG11] Dahlström, Erik; Dengler, Patrick; Grasso,
Anthony; Lilley, Chris; McCormack, Cameron; Schepers, Doug; Watt, Jonathan; Ferraiolo,
Jon; FUJISAWA, Jun (藤沢 淳); and Jackson, Dean. Scalable Vector
Graphics (SVG) 1.1 (Second Edition). W3C Recommendation 16 August 2011. https://www.w3.org/TR/SVG11/
[DeRo14] DeRose, Steven J. “What do we still lack? Or: Prolegomena to any future hypertext
system.” Presented at Symposium on HTML5 and XML, Washington, DC, August 4, 2014.
In Proceedings of the Symposium on HTML5 and XML. Balisage Series on Markup Technologies, vol. 14 (2014). doi:https://doi.org/10.4242/BalisageVol14.DeRose01
[DeRo18] DeRose, Steven J. “Dynamic Style: Implementing Hypertext through Embedding Javascript
in CSS.” Presented at Balisage: The Markup Conference 2018, Washington, DC, July 31
- August 3, 2018. In Proceedings of Balisage: The Markup Conference 2018. Balisage Series on Markup Technologies, vol. 21 (2018). doi:https://doi.org/10.4242/BalisageVol21.DeRose01
[DeRo20] DeRose, Steven. “What is a diagram, really?” Presented at Balisage: The Markup Conference
2020, Washington, DC, July 27 - 31, 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol. 25 (2020). doi:https://doi.org/10.4242/BalisageVol25.DeRose01
[Dobk97] Dobkin, D.P.; Gansner, E.R.; Koutsofios, E.; and North, S.C. Implementing a General-Purpose Edge Router.
In DiBattista (ed.), Graph Drawing (GD 1997), LNCS 1353, pp. 262–271. Springer, 1997.
doi:https://doi.org/10.1007/3-540-63938-1_68
[Domr23] Domrös, Sören; von Hanxleden, Reinhard; Spönemann, Miro; Rüegg, Ulf; and Schulze,
Christoph Daniel. The Eclipse Layout Kernel. https://arxiv.org/abs/2311.00533. doi:https://doi.org/10.48550/arXiv.2311.00533
[Draw] JGraph Ltd. draw.io / diagrams.net. https://www.drawio.com
[Dwye09] Dwyer, T. and Nachmanson, L. Fast Edge-Routing for Large Graphs.
In Eppstein & Gansner (eds.), Graph Drawing (GD 2009), LNCS 5849, pp. 147–158. Springer, 2009.
doi:https://doi.org/10.1007/978-3-642-11805-0_15
[Eade84] Eades, P. A Heuristic for Graph Drawing.
Congressus Numerantium 42:149–160, 1984.
[Frei01] Freivalds, K. Curved Edge Routing.
In Freivalds (ed.), Fundamentals of Computation Theory (FCT 2001), LNCS 2138, pp. 126–137. Springer, 2001.
doi:https://doi.org/10.1007/3-540-44669-9_14
[Fruc91] Fruchterman, T.M.J. and Reingold, E.M. Graph Drawing by Force-Directed Placement.
Software: Practice and Experience 21(11):1129–1164, 1991.
doi:https://doi.org/10.1002/spe.4380211102
[Gans93] Gansner, E.R.; Koutsofios, E.; North, S.C.; and Vo, K.-P. A Technique for Drawing Directed Graphs.
IEEE Transactions on Software Engineering 19(3):214–230, 1993.
doi:https://doi.org/10.1109/32.221135
[GVShapes] Graphviz. Node Shapes. https://graphviz.org/doc/info/shapes.html
[Hols20] Holstege, Mary. “XML for Art: A Case Study.” Presented at Balisage: The Markup Conference
2020, Washington, DC, July 27 - 31, 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol. 25 (2020).
doi:https://doi.org/10.4242/BalisageVol25.Holstege01
[Hols23] Holstege, Mary. “Adventures in Single-Sourcing XQuery and XSLT.” Presented at Balisage:
The Markup Conference 2023, Washington, DC, July 31 - August 4, 2023. In Proceedings of Balisage: The Markup Conference 2023. Balisage Series on Markup Technologies, vol. 28 (2023).
doi:https://doi.org/10.4242/BalisageVol28.Holstege01
[Holt06] Holten, D. Hierarchical Edge Bundles: Visualization of Adjacency Relations in Hierarchical Data.
IEEE Transactions on Visualization and Computer Graphics 12(5):741–748, 2006.
doi:https://doi.org/10.1109/TVCG.2006.147
[Inkscape] Inkscape Project. https://inkscape.org
[Kay17a] Kay, Michael, ed. XSL Transformations (XSLT) Version 3.0. W3C Recommendation, 8 June
2017. https://www.w3.org/TR/xslt-30/
[Kay17b] Kay, Michael, ed. XPath and XQuery Functions and Operators 3.1. W3C Recommendation,
21 March 2017. https://www.w3.org/TR/xpath-functions-31/
[Pike67] Pike, Kenneth L. Language in Relation to a Unified Theory of the Structure of Human Behavior. 2nd rev. ed. The Hague: Mouton, 1967. (First published in three parts, 1954–1960.)
[Robi14] Robie, Jonathan; Chamberlin, Don; Dyck, Michael; and Snelson, John. XML Path Language
(XPath) 3.0. W3C Recommendation 08 April 2014. https://www.w3.org/TR/xpath-30/
[Sche09a] Schepers, Doug. SVG Parameters 1.0, Part 1:
Primer. W3C Working Draft 16 June 2009. https://www.w3.org/TR/2009/WD-SVGParamPrimer-20090616/
[Sche09b] Schepers, Doug. SVG Parameters 1.0, Part 2: Language. W3C Working Draft 16 June 2009.
https://www.w3.org/TR/2009/WD-SVGParam-20090616/
[ELK] Schulze, C. Sönke, et al. Eclipse Layout
Kernel. https://eclipse.dev/elk/
[Tama87] Tamassia, R. On Embedding a Graph in the Grid with the Minimum Number of Bends.
SIAM Journal on Computing 16(3):421–444, 1987.
doi:https://doi.org/10.1137/0216030
[TikZ] Tantau, Till. The TikZ and PGF Packages. Manual for version 3.1.x. https://tikz.dev/
[Will94] Williams, Robin. The Non-Designer's Design Book: Design and Typographic Principles for the Visual Novice. Peachpit Press, 1994. ISBN 978-1-56609-159-4.
[Wybr06] Wybrow, M.; Marriott, K.; and Stuckey, P.J. Incremental Connector Routing.
In Healy & Nikolov (eds.), Graph Drawing (GD 2005), LNCS 3843, pp. 446–457. Springer, 2006.
doi:https://doi.org/10.1007/11618058_40
[Wybr09] Wybrow, M.; Marriott, K.; and Stuckey, P.J. Orthogonal Connector Routing.
In Eppstein & Gansner (eds.), Graph Drawing (GD 2009), LNCS 5849, pp. 219–231. Springer, 2009.
doi:https://doi.org/10.1007/978-3-642-11805-0_22
×Bellamy-Royds, Amelia; Bogdan, Brinza; Lilley, Chris; Schulze, Dirk; Storey, David;
and Willigers, Eric. Scalable Vector Graphics (SVG) 2. W3C Candidate Recommendation
04 October 2018. https://www.w3.org/TR/SVG2/
×Berglund, Anders; Boag, Scott; Chamberlin, Don; Fernández, Mary F.; Kay, Michael;
Robie, Jonathan; and Siméon, Jérôme. XML Path Language (XPath) 2.0 (Second Edition).
W3C Recommendation 14 December 2010. https://www.w3.org/TR/xpath20/
×Clark, James and DeRose, Steve. XML Path Language (XPath) Version 1.0. W3C Recommendation
16 November 1999 (Status updated October 2016). https://www.w3.org/TR/xpath-10/
×Dahlström, Erik; Dengler, Patrick; Grasso,
Anthony; Lilley, Chris; McCormack, Cameron; Schepers, Doug; Watt, Jonathan; Ferraiolo,
Jon; FUJISAWA, Jun (藤沢 淳); and Jackson, Dean. Scalable Vector
Graphics (SVG) 1.1 (Second Edition). W3C Recommendation 16 August 2011. https://www.w3.org/TR/SVG11/
×DeRose, Steven J. “What do we still lack? Or: Prolegomena to any future hypertext
system.” Presented at Symposium on HTML5 and XML, Washington, DC, August 4, 2014.
In Proceedings of the Symposium on HTML5 and XML. Balisage Series on Markup Technologies, vol. 14 (2014). doi:https://doi.org/10.4242/BalisageVol14.DeRose01
×DeRose, Steven J. “Dynamic Style: Implementing Hypertext through Embedding Javascript
in CSS.” Presented at Balisage: The Markup Conference 2018, Washington, DC, July 31
- August 3, 2018. In Proceedings of Balisage: The Markup Conference 2018. Balisage Series on Markup Technologies, vol. 21 (2018). doi:https://doi.org/10.4242/BalisageVol21.DeRose01
×DeRose, Steven. “What is a diagram, really?” Presented at Balisage: The Markup Conference
2020, Washington, DC, July 27 - 31, 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol. 25 (2020). doi:https://doi.org/10.4242/BalisageVol25.DeRose01
×Dobkin, D.P.; Gansner, E.R.; Koutsofios, E.; and North, S.C. Implementing a General-Purpose Edge Router.
In DiBattista (ed.), Graph Drawing (GD 1997), LNCS 1353, pp. 262–271. Springer, 1997.
doi:https://doi.org/10.1007/3-540-63938-1_68
×Eades, P. A Heuristic for Graph Drawing.
Congressus Numerantium 42:149–160, 1984.
×Gansner, E.R.; Koutsofios, E.; North, S.C.; and Vo, K.-P. A Technique for Drawing Directed Graphs.
IEEE Transactions on Software Engineering 19(3):214–230, 1993.
doi:https://doi.org/10.1109/32.221135
×Holstege, Mary. “XML for Art: A Case Study.” Presented at Balisage: The Markup Conference
2020, Washington, DC, July 27 - 31, 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol. 25 (2020).
doi:https://doi.org/10.4242/BalisageVol25.Holstege01
×Holstege, Mary. “Adventures in Single-Sourcing XQuery and XSLT.” Presented at Balisage:
The Markup Conference 2023, Washington, DC, July 31 - August 4, 2023. In Proceedings of Balisage: The Markup Conference 2023. Balisage Series on Markup Technologies, vol. 28 (2023).
doi:https://doi.org/10.4242/BalisageVol28.Holstege01
×Holten, D. Hierarchical Edge Bundles: Visualization of Adjacency Relations in Hierarchical Data.
IEEE Transactions on Visualization and Computer Graphics 12(5):741–748, 2006.
doi:https://doi.org/10.1109/TVCG.2006.147
×Pike, Kenneth L. Language in Relation to a Unified Theory of the Structure of Human Behavior. 2nd rev. ed. The Hague: Mouton, 1967. (First published in three parts, 1954–1960.)
×Robie, Jonathan; Chamberlin, Don; Dyck, Michael; and Snelson, John. XML Path Language
(XPath) 3.0. W3C Recommendation 08 April 2014. https://www.w3.org/TR/xpath-30/
×Tamassia, R. On Embedding a Graph in the Grid with the Minimum Number of Bends.
SIAM Journal on Computing 16(3):421–444, 1987.
doi:https://doi.org/10.1137/0216030
×Williams, Robin. The Non-Designer's Design Book: Design and Typographic Principles for the Visual Novice. Peachpit Press, 1994. ISBN 978-1-56609-159-4.
×Wybrow, M.; Marriott, K.; and Stuckey, P.J. Incremental Connector Routing.
In Healy & Nikolov (eds.), Graph Drawing (GD 2005), LNCS 3843, pp. 446–457. Springer, 2006.
doi:https://doi.org/10.1007/11618058_40