Portability | GHC with TypeFamilies and more |
---|---|
Stability | unstable |
Maintainer | Stephen Tetley <stephen.tetley@gmail.com> |
This module re-exports types and functions from Wumpus.Core.PictureInternal but makes them opaque.
- data Picture u
- type DPicture = Picture Double
- data Primitive u
- type DPrimitive = Primitive Double
- data Path u
- type DPath = Path Double
- data PathSegment u
- type DPathSegment = PathSegment Double
- data Label u
- type DLabel = Label Double
- type PathProps = (PSRgb, DrawPath)
- type LabelProps = (PSRgb, FontAttr)
- type EllipseProps = (PSRgb, DrawEllipse)
- data DrawPath
- data DrawEllipse
Picture types
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.
Apropos the constructors, Picture is a simple non-empty leaf-labelled rose tree via:
Single (aka leaf) | Picture (OneList tree)
Where OneList is a variant of the standard list type that disallows empty lists.
The additional constructors are convenience:
PicBlank
has a bounding box but no content and is useful for
some picture language operations (e.g. hsep
).
Clip
nests a picture (tree) inside a clipping path.
Eq u => Eq (Picture u) | |
Show u => Show (Picture u) | |
(Num u, Pretty u) => Pretty (Picture u) | |
(Num u, Ord u) => Translate (Picture u) | |
(Num u, Ord u) => Scale (Picture u) | |
(Floating u, Real u) => RotateAbout (Picture u) | |
(Floating u, Real u) => Rotate (Picture u) | |
Boundary (Picture u) | |
(Num u, Ord u) => Move (Picture u) | |
(Num u, Ord u) => Vertical (Picture u) | |
(Num u, Ord u) => Horizontal (Picture u) | |
(Num u, Ord u) => Blank (Picture u) | |
(Num u, Ord u) => Composite (Picture u) |
Wumpus's drawings are built from two fundamental primitives: paths (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 arc
command.
Wumpus does not follow PostScript and employ arcs as general path primitives - they 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.
Eq u => Eq (Primitive u) | |
Show u => Show (Primitive u) | |
Pretty u => Pretty (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) | |
(Fractional u, Floating u, Ord u) => Boundary (Primitive u) |
type DPrimitive = Primitive DoubleSource
Path - start point and a list of path segments.
data PathSegment u Source
PathSegment - either a cubic Bezier curve or a line.
Eq u => Eq (PathSegment u) | |
Show u => Show (PathSegment u) | |
Pretty u => Pretty (PathSegment u) | |
Pointwise (PathSegment u) |
type DPathSegment = PathSegment DoubleSource
Label - represented by bottom left corner and text.
Drawing styles
type LabelProps = (PSRgb, FontAttr)Source
type EllipseProps = (PSRgb, DrawEllipse)Source
Note when drawn filled and drawn stroked the same polygon will have (slightly) different size:
- A filled shape fills within the boundary of the shape
- A stroked shape draws a pen line around the boundary of the shape. The actual size depends on the thickness of the line (stroke width).
data DrawEllipse Source
Ellipses and circles are always closed.