|Maintainer||Stephen Tetley <email@example.com>|
- data Picture u
- type DPicture = Picture Double
- data FontCtx
- data Primitive u
- type DPrimitive = Primitive Double
- data XLink
- data PrimPath u
- type DPrimPath = PrimPath Double
- data PrimPathSegment u
- type DPrimPathSegment = PrimPathSegment Double
- data PrimLabel u
- type DPrimLabel = PrimLabel Double
- type KerningChar u = (u, EncodedChar)
- type DKerningChar = KerningChar Double
- class Num a => PSUnit a where
Picture is a leaf attributed tree - where attributes are colour, line-width etc. It is parametric on the unit type of points (typically Double).
Wumpus's leaf attributed tree, is not directly matched to PostScript's picture representation, which might be considered a node attributed tree (if you consider graphics state changes less imperatively - setting attributes rather than global state change).
Considered as a node-attributed tree PostScript precolates graphics state updates downwards in the tree (vis-a-vis inherited attributes in an attibute grammar), where a graphics state change deeper in the tree overrides a higher one.
Wumpus on the other hand, simply labels each leaf with its drawing attributes - there is no attribute inheritance. When it draws the PostScript picture it does some optimization to avoid generating excessive graphics state changes in the PostScript code.
Omitting some details, Picture is a simple non-empty leaf-labelled rose tree via:
tree = Leaf [primitive] | Picture [tree]
The additional constructors are convenience:
Clip nests a picture (tree) inside a clipping path.
Group constructor allows local shared graphics state
updates for the SVG renderer - in some instances this can
improve the code size of the generated SVG.
Set the font delta for SVG rendering.
Note - this does not change the default colour or font style. It is solely a backdoor into the SVG renderer to potential allow some code size reductions.
Wumpus's drawings are built from two fundamental primitives: paths (straight line segments and Bezier curves) and labels (single lines of text).
Ellipses are a included as a primitive only for optimization
- drawing a reasonable circle with Bezier curves needs at
least eight curves. This is inconvenient for drawing dots
which can otherwise be drawn with a single
Wumpus does not follow PostScript employing arc as a general path primitive - arcs are used only to draw ellipses. This is because arcs do not enjoy the nice properties of Bezier curves, whereby the affine transformation of a Bezier curve can simply be achieved by the affine transformation of it's control points.
Ellipses are represented by their center, half-width and half-height. Half-width and half-height are used so the bounding box can be calculated using only multiplication, and thus initially only obliging a Num constraint on the unit. Though typically for affine transformations a Fractional constraint is also obliged.
To represent XLink hyperlinks, Primitives can be annotated with some a hyperlink (similarly a a font change for better SVG code generation) and grouped - a hyperlinked arrow would want the tip and the arrow body both to be incorporated in the link even though they are two drawings.
This means that Primitives aren't strictly primitive as the actual implementation is a tree.
|Eq u => Eq (Primitive u)|
|Show u => Show (Primitive u)|
|PSUnit u => Format (Primitive u)|
|Num u => Translate (Primitive u)|
|Num u => Scale (Primitive u)|
|(Real u, Floating u) => RotateAbout (Primitive u)|
|(Real u, Floating u) => Rotate (Primitive u)|
|(Real u, Floating u, FromPtSize u) => Boundary (Primitive u)|
Primitives can be grouped with hyperlinks in SVG output.
PrimPath - start point and a list of path segments.
PrimPathSegment - either a cubic Bezier curve or a line.
Label - represented by baseline left point and text.
A Char (possibly escaped) paired with is displacement from the previous KerningChar.