&      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~              !!!!!!!!!"#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%%%&GHCunstablestephen.tetley@gmail.comVersion number  (0,16,0) !'Convert a join list to a regular list. 'Build a join list from a regular list.  This builds a tall skinny list. )WARNING - throws an error on empty list. Create an empty join list. Create a singleton join list. /Cons an element to the front of the join list. .Snoc an element to the tail of the join list. =Extract the first element of a join list - i.e. the leftmost ? element of the left spine. An error is thrown if the list is  empty. <This function performs a traversal down the left spine, so  unlike head2 on regular lists this function is not performed  in constant time. 8This function throws a runtime error on the empty list. &Right-associative fold of a JoinList. %Left-associative fold of a JoinList. #Access the left end of a sequence. <Unlike the corresponing operation on Data.Sequence this is = not a cheap operation, the joinlist must be traversed down + the left spine to find the leftmost node. :Also the traversal may involve changing the shape of the  underlying binary tree. $Access the right end of a sequence. <Unlike the corresponing operation on Data.Sequence this is = not a cheap operation, the joinlist must be traversed down + the left spine to find the leftmost node. :Also the traversal may involve changing the shape of the  underlying binary tree.     GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>9 Doc is a Join List ... !'Create an empty, zero length document. ")Create a document from a ShowS function. #6Horizontally concatenate two documents with no space  between them. $<Horizontally concatenate two documents with a single space  between them. %6Vertical concatenate two documents with a line break. &'2Horizontally concatenate a list of documents with (<>). (2Horizontally concatenate a list of documents with (<+>). )9Vertically concatenate a list of documents, with a line  break between each doc. *)Create a document from a literal string. <The string should not contain newlines (though this is not  enforced). +,Create a document from a literal character. *The char should not be a tab or newline. ,Show the Int as a Doc.  int = text . show -Show the Integer as a Doc. .Show an "integral value" as a Doc via . /Show the Float as a Doc. 0Show the Double as a Doc. 18Show the Int as hexadecimal, padding up to 4 digits if  necessary. 9No trucation occurs if the value has more than 4 digits. 22Create a Doc containing a single space character. 3!Create a Doc containing a comma, ",". 4&Create a Doc containing a semi colon, ";". 5!Create a Doc containing newline, "\n". 6:Fill a doc to the supplied length, padding the right-hand  side with spaces. >Note - this function is expensive - it unrolls the functional  representation of the String. /Also it should only be used for single line Doc's. 7String version of 6. This is more efficient than 6 as the input is a string " so its length is more accesible. 6Padding is the space character appended to the right. 8Left-padding version of 7. 9=Punctuate the Doc list with the separator, producing a Doc. :,Enclose the final Doc within the first two. +There are no spaces between the documents:  enclose l r d = l <> d <> r ;&Enclose the Doc within single quotes. <&Enclose the Doc within double quotes. =Enclose the Doc within parens (). >'Enclose the Doc within square brackets []. ?$Enclose the Doc within curly braces {}. @&Enclose the Doc within angle brackets <>. A&Create a Doc containing a left paren, '('. B'Create a Doc containing a right paren, ')'. C/Create a Doc containing a left square bracket, '['. D0Create a Doc containing a right square bracket, ']'. E,Create a Doc containing a left curly brace, '{'. F-Create a Doc containing a right curly brace, '}'. G.Create a Doc containing a left angle bracket, '<'. H/Create a Doc containing a right angle bracket, '>'. I;Comma separate the list of documents and enclose in square  brackets. J<Comma separate the list of documents and enclose in parens. K9Separate the list with a semicolon and enclose in curly  braces. LHorizontally indent a Doc. &Note - this space-prefixes the Doc on the current line. It = does not indent subsequent lines if the Doc spans multiple  lines. MWrite a Doc to file. 1 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM1 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM1 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMGHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>>NOPQRSTUVWXYZ[This one is from Chris Okasaki's "Even Higher-Order  Functions for Parsing". \;Peek tries the supplied parse, but does not consume input  ** even when the parse succeeds **. ]^_`abcdeApplicative cons. fghijklmnoo" an alias for Control.Applicative . pqrstuvwxyz{|}~5NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~5QRTSPONUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~5NOPQRTSSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>;Opaque type representing a parser that consumes arbitrary  space.  Unlike Parsec'1s lexeme parser, this can be customized so that 0 e.g. newlines are not consumed as white space. #Build a lexeme parser that handles space. Space' is zero or more elements matching the isSpace  predicate from  Data.Char. -Build a lexeme parser that handles arbitrary space. space5 is parametric, for instance this can manufacture a : lexeme parser that consumes space and tab chars but not  newline. ;Build a lexeme parser that handles start-and-end delimited  comments and arbitrary space. ;Build a lexeme parser that handles line spanning comments  an arbitrary space. ;Build a lexeme parser that handles start-and-end delimited ' comments, line comments and arbitrary space. <Wrap a CharParser with a lexeme parser, the CharParser will : consume trailing space according to the strategy of the  LexemeParser. GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>8GhostScript version that the aliases were derived from. ghostscript_version :: String  ghostscript_version = gs8.54 A map from standard Adode PostScript font name to the 0 equivalent GhostScript font and AFM file name. >It is expected that all GhostScript AFM files will be located  in the same directory. Get the .afm metrics file. <Note this return only the file name and not the path to it. 0 The full path must be resolved in client code. %Get the GhostScript font name alias. 5Get the GhostScript version number that the FontMap  represents. 4Map from PostScript font name to the corresponding  GhostScript name and file. 0Naming is correct for GhostSCript version 8.54. GHCunstablestephen.tetley@gmail.com 6velo consumes the list as per map, but builds it back , as a Hughes list - so items can be dropped  replaced, repeated, etc... GHCunstablestephen.tetley@gmail.com =ScalingContext is a dictionary of two functions for scaling  in X and Y. =Build a ScalingContext where both X and Y are scaled by the  same uniform step. @The dimensions (types) of the ScalingContext are unified - the 3 output type and the input types are all the same. 4Build a ScalingContext for scaling Int coordinates. 7The scaling factors in X and Y can be different sizes.  GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>*A map between a font name and MetricsOps.  for a particular named font. )Operations on the metrics set of a font. >The is the internal representation used by Wumpus-Basic after  parsing the font file. A lookup from code point to  width vector. ?Note - in PostScript terminology a width vector is not obliged 9 to be left-to-right (writing direction 0). It could be & top-to-bottom (writing direction 1). A Unicode code-point. 8This ignores the Char code lookup and just returns the  default advance vector.  GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>$5The metrics read from a font file by a font loader. "NOTE - FontProps is parametric on cu - Character Unit and  not on the usual u. A typical character unit is , < the unit of measurement for AFM files (1000th of a point). =The is the initial representation used by Wumpus-Basic as an ' syntax tree when loading font files. 9Monospace defaults are used if the font loader fails to  extract the necessary fields. =The values are taken from the font correpsonding to Courier  in the distributed font files. >Wumpus needs a very small subset of AFM files, common to both  version 2.0 and version 4.1. >Note - Bounding Box is mandatory for AFM versions 3.0 and 4.1 ?Cap Height is optional in AFM versions 3.0 and 4.1. As Wumpus ? uses cap height in calculations, glyph metrics must be build / with an arbitrary value if it is not present. *Encoding Scheme is optional in AFM files. Afm files index glyphs by PostScript character code. This & is not the same as Unicode, ASCII... #It is expected to be determined by EncodingScheme in the " Global Font Information Section. Wrapped Double representing 1/1000 of the scale factor < (Point size) of a font. AFM files encode all measurements  as these units. =Compute the size of a measurement in Afm units scaled by the  point size of the font. 9Build a MetricsOps function table, from a character unit 2 scaling function and FontProps read from a file. """ GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com> aka liftIO The standard monadic sequence would finish on first fail = for the FontLoadIO monad. As we want to be able to sequence 9 the loading of a list of fonts, this is not really the B behaviour we want for Wumpus. Instead we prefer to use fallback @ metrics and produce an inaccurate drawing on a font load error * rather than fail and produce no drawing. 8Afm files do not have a default advance vec so use the  monospace default. Afm files hopefully have  CapHeight and FontBBox properties < in the header. Use the monospace default only if they are  missing.  GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>;Strictly speaking a fontBBox is measured in integer units.  GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>    GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>    >The unit of Margin is always Double representing Points, e.g. @ 1.0 is 1 Point. Margins are not scaled relative to the current  font size. The default value is 2 point. 2Type synonym for DrawingContext update functions.  - the "graphics state" of Wumpus-Basic. B DrawingContext is operated on within a Reader monad rather than  a State monad so "updates" are delineated within a local  operation (called localize# in Wumpus), rather than permanent  until overridden as per set of a State monad. Note - round_corner_factor is only accounted for by some 6 graphic objects (certain Path objects and Shapes in @ Wumpus-Drawing for instance). There many be many objects that 4 ignore it and are drawn only with angular corners. :Also note - in contrast to most other drawing objects in ; Wumpus, none of the measurement values are parameteric - ( usually notated with the type variable u in Wumpus. This is ; so Wumpus can (potentially) support different units e.g. = centimeters rather than just Doubles (represening printers @ points), though adding support for other units has a very low  priority. Courier  "Project a value out of a context. !     !     !        !GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>%"#Because textAttr* is so commonly used here is a functional  version that avoids tupling. $%&'()*!Size of the round corner factor. +"Get the (x,y) margin around text. >Note - not all text operations in Wumpus are drawn with text  margin. ,-./09Vertical distance between baselines of consecutive text  lines. 1The mark4 height is the height of a lowercase letter in the  current font. =Arrowheads, dots etc. should generally be drawn at the mark  height. 23=Get the font bounding box - this is the maximum boundary of @ the glyphs in the font. The span of the height is expected to 5 be bigger than the cap_height plus descender depth. 45-Note - descender is expected to be negative. 63This is the distance from cap_height to descender. 789:;<=Height of a lower case 'x' in Courier. 'x'" has no ascenders or descenders. >?@=Query the dimensions of the text using the current font size ) but using metrics derived from Courier. 8Note - the width will generally be a over-estimate for  non-monospaced fonts. AThe heigth of n lines of text, which is  n lines + n-1 line spacers B#The default padding is half of the  char width. C$Vector from baseline left to center ""#$%&'()*+,-./0123456789:;<=>?@ABC""#$%&'()*+,-./1203456789:;<=>?@ABC""#$%&'()*+,-./0123456789:;<=>?@ABCGHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>$DEE :  xsep * ysep -> DrawingContextF  F  GSet the line width to a thick. Note this context update is  oblivious - operationally the  line width is set to exactly 2.0. HI JKL MNOPQRSTUVWXYZ<Set the font size to double the current size, note the font 7 size also controls the size of dots, arrowsheads etc. [:Set the font size to half the current size, note the font 7 size also controls the size of dots, arrowsheads etc. ;As fontsize is an integer this is not exact - half size of  15pt type is 7pt. \]^_`DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`DEFGHIJKLMNOPQRSTUVXWYZ[\]^_`DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`GHC highly unstablestephen.tetley@gmail.com a4A monad that supplies points, e.g. a turtle monad. ** WARNING *** - the idea behind this class is somewhat = half-baked. It may be revised or even dropped in subsequent  versions of Wumpus-Basic. bc;DUnit is always for fully saturated type constructors, so = (seemingly) an equivalent type family is needed for monads. d9Advance vectors provide an idiom for drawing consecutive > graphics. PostScript uses them to draw left-to-right text - 9 each character has an advance vector for the width and > as characters are drawn they successively displace the start 9 point for the next character with their advance vector. Type alias for Vec2. e8An enumeratied type representing the compass positions. fghijklmn:Vertical alignment - align to the left, center or bottom. opqr;Horizontal alignment - align to the top, center or bottom. stuvA Bifunctor class. >Again, it would be nice if there was a Bifunctor class in the  Haskell Base libraries... wxyzA Semigroup class. ?The perhaps unusual name is the TeX name for the circled plus ? glyph. It would be nice if there was a semigroup class in the  Haskell Base libraries... {|}~7Extract the horizontal component of an advance vector. ;For left-to-right latin text, the vertical component of an 8 advance vector is expected to be 0. Ingoring it seems  permissible when drawing text. 6Extract the verticall component of an advance vector. abcdefghijklmnopqrstuvwxyz{|}~ z{|vwxy}~rutsnqpoemlkjihgfdcab abbcdemlkjihgffghijklmnqpoopqrutsstuvwxywxyz{{|}~GHC highly unstablestephen.tetley@gmail.com) Alias of ( where the unit type is specialized to  Double.  Alias of ( where the unit type is specialized to  Double.  Alias of ( where the unit type is specialized to  Double. Type specialized verison of  where the static arguments  are the  start point and the  end point. = ConnectorCF :: DrawingContext -> Point2 u -> Point2 u -> a Type specialized verison of  where the static arguments  are the  start point and the angle of displacement. : LocThetaCF :: DrawingContext -> Point2 u -> Radian -> a Type specialized verison of  where the static argument  is the  start point. + LocCF :: DrawingContext -> Point2 u -> a  Variation of  with two parametric static arguments. ?The first argument is commonly a point representing the start  point /1 origin of a drawing. The second argument might B typically be the angle of displacement (for drawing arrowheads) > or an end point (for drawing connectors between two points). ) CF2 :: DrawingContext -> r1 -> r2 -> a   Variation of  with one parametric static argument. @The static argument is commonly a point representing the start  point / origin of a drawing. # CF1 :: DrawingContext -> r1 -> a :Most drawing operations in Wumpus-Basic have an implicit  graphics state the , so the most primitive ? building block is a function from the DrawingContext to some  polymorphic answer. @This functional type is represented concretely as the initials  CF for contextual function.  CF :: DrawingContext -> a Run a CF' (context function) with the supplied  DrawingContext. Run a CF1' (context function) with the supplied  DrawingContext and static argument. Run a CF1' (context function) with the supplied  DrawingContext and two static arguments. #Lift a zero-arity context function  to an arity one  context function . #Lift a zero-arity context function  to an arity two  context function . #Lift an arity one context function  to an arity two  context function . Promote a function 'from one argument to a Context Function  to an arity one Context Function. 7The type signature is as explanatory as a description: ' promoteR1 :: (r1 -> CF a) -> CF1 r1 a Promote a function (from two arguments to a Context Function  to an arity two Context Function. 7The type signature is as explanatory as a description: 0 promoteR2 :: (r1 -> r2 -> CF a) -> CF2 r1 r2 a ;Apply an arity-one Context Function to a single argument, < downcasting it by one level, making an arity-zero Context  function. 7The type signature is as explanatory as a description: $ apply1R1 :: CF1 r1 a -> r1 -> CF a 7Apply an arity-two Context Function to two arguments, = downcasting it by two levels, making an arity-zero Context  function. 7The type signature is as explanatory as a description: - apply2R2 :: CF2 r1 r2 a -> r1 -> r2 -> CF a 6Apply an arity-two Context Function to one argument, ; downcasting it by one level, making an arity-one Context  function. 7The type signature is as explanatory as a description: + apply1R2 :: CF2 r1 r2 a -> r2 -> CF1 r1 a +Extract the drawing context from a CtxFun.  (ctx -> ctx) 6Apply the projection function to the drawing context.  (ctx -> a) -> (ctx -> a) *Extract the drawing context from a LocCF.  (ctx -> pt -> ctx)  Extract the start point from a LocCF.  (ctx -> pt -> pt) /Extract the drawing context from a LocThetaCF.  (ctx -> pt -> ang -> ctx)  Extract the start point from a LocThetaCF.  (ctx -> pt -> ang -> pt) %Extract the angle from a LocThetaCF.  (ctx -> pt -> ang -> ang) 0Extract the drawing context from a ConnectorCF.  (ctx -> pt1 -> pt2 -> ctx) ,Extract the start point from a ConnectorCF.  (ctx -> pt1 -> pt2 -> pt1) *Extract the end point from a ConnectorCF.  (ctx -> pt1 -> pt2 -> pt2)  Downcast a * function by applying it to the supplied 0 point, making an arity-zero Context Function.  Remember a  function is a  context function where  the static argument" is specialized to a start point.  Downcast a ! function by applying it to the : supplied angle, making an arity-one Context Function (a  ).  Downcast a ! function by applying it to the 9 supplied point and angle, making an arity-zero Context  Function (a ).  Downcast a ! function by applying it to the = start and end point, making an arity-zero Context Function  (a ). Chaining combinator - the answer of the A first Context Function is feed to the second Context Function. 'This contrasts with the usual idiom in  Wumpus-Basic where A composite graphics are built by applying both functions to the  same initial static argument.  Desciption: >Evaluate the first Context Function with the drawing context  and the  initial state st0#. The result of the evaluation is  a new state st1 and and answer a1. ?Evaluate the second Context Function with the drawing context  and the new state st1, producing a new state s2 and an  answer a2. 1Return the result of combining the answers with  op :: (ans -> ans -> ans) and the second state s2.  H (ctx -> s1 -> (w,s1)) -> (ctx -> s1 -> (w,s1)) -> (ctx -> s1 -> (w,s1))?This models chaining start points together, which is the model @ PostScript uses for text output when successively calling the  show operator. ###GHC highly unstablestephen.tetley@gmail.com# is a type representing functions  from Radian * Point to Point. <It is useful for building arrowheads which are constructed @ with an implicit angle representing the direction of the line  at the arrow tip. # is a type representing functions  from Radian to Radian. ?It is especially useful for building composite graphics where @ one part of the graphic is drawn from a different start point  to the other part. # is a type representing functions  from Point to Point. ?It is especially useful for building composite graphics where @ one part of the graphic is drawn from a different start point  to the other part. Move the start-point of a  with the supplied  displacement function. Move the start-point of a  with the supplied  displacement function. Move the start-point of a  with the supplied  displacement function. Change the inclination of a  with the supplied  displacement function.  :  x -> y -> PointDisplace  Build a combinator to move Points by the supplied x and  y distances.  :  (V2 x y) -> PointDisplace   Version of ' where the displacement is supplied as & a vector rather than two parameters.  :  x -> PointDisplace  Build a combinator to move Points by horizontally the  supplied x distance.  :  y -> PointDisplace  Build a combinator to move Points vertically by the supplied  y distance.  :  dist -> ThetaPointDisplace  Build a combinator to move Points in parallel to the ; direction of the implicit angle by the supplied distance  dist.  :  dist -> ThetaPointDisplace  Build a combinator to move Points perpendicular to the < inclnation of the implicit angle by the supplied distance  dist.  :  vec -> ThetaPointDisplace  This is a combination of displaceParallel and  displacePerpendicular%, with the x component of the vector 5 displaced in parallel and the y component displaced  perpendicular. GHC highly unstablestephen.tetley@gmail.com =Graphics objects, even simple ones (line, arrow, dot) might = need more than one primitive (path or text label) for their ? construction. Hence, the primary representation that all the $ others are built upon must support  concatenation of  primitives. 8Wumpus-Core has a type Picture - made from one or more ? Primitives - but Pictures include support for affine frames. > For drawing many simple graphics (dots, connector lines...) ? that do not need individual affine transformations this is a ; penalty. A list of Primitives is therefore more suitable 2 representation, and a Hughes list which supports " efficient concatenation is wise. 9Collect elementary graphics as part of a larger drawing. 'TraceM works much like a writer monad.    GHC highly unstablestephen.tetley@gmail.com A query on the DrawingContext.  Alias for . 9A query on the DrawingContext respective to the supplied  point.  Alias for . 9A query on the DrawingContext respective to the supplied  point and angle.  Alias for . :An Image always returns a pair of some polymorphic answer a  and a PrimGraphic. $Note a PrimGraphic cannot be empty. %Draw a PrimGraphic repsective to the DrawingContext and  return some answer a. %Draw a PrimGraphic respective to the DrawingContext and ( the supplied point, return some answer a. %Draw a PrimGraphic respective to the DrawingContext and  the supplied point and angle.    GHC highly unstablestephen.tetley@gmail.com Alias of % where the unit type is specialized  to Double.  Originated2 drawing - produce a primitive respective to the > supplied start-point, access the DrawingContext as required.  Alias of ( where the unit type is specialized to  Double.  Originated2 drawing - produce a primitive respective to the > supplied start-point, access the DrawingContext as required.  Alias of ( where the unit type is specialized to  Double. @Simple drawing - produce a primitive, access the DrawingContext B as required, e.g for fill colour, stroke colur, line width, etc.  :  alternative * [image] -> Image  produces a composite  from a list of  Image'(s. If the list is empty the alternative Image is  used. This contrasts to | - when used for Image's,  oconcat has the same type signature as  safeconcat but  oconcat8 considers its arguments to be an already destructured  list: ' oconcat (head::Image) (rest::[Image]) !Ignore the answer produced by an , a  etc. Use this function to turn an  into a , a  'LocImage into a . "Replace the answer produced by an , a  etc. :Apply the supplied function to the answer produced by an  , a  etc.  : % context_function * graphic -> Image   Build an  from a context function () that generates  the answer and a  that draws the .  : 0 loc_context_function * loc_graphic -> LocImage  Loc version of . The 0 is built as a function from an implicit start  point to the answer.  : 3 loc_theta_cf * loc_theta_graphic -> LocThetaImage  LocTheta version of . The * is built as a function from an implicit 5 start point and angle of inclination to the answer.  :  LocGraphic  Build an empty  (i.e. a function  from Point to Graphic&). This is a path with a start point  but no path segments. The  is treated as a null primitive by   Wumpus-Core0 and is not drawn, although it does generate a 3 minimum bounding box at the implicit start point.  :  LocThetaGraphic  Build an empty  (i.e. a function  %from Point and Inclination to Graphic). The  is treated as a null primitive by   Wumpus-Core0 and is not drawn, although it does generate a 3 minimum bounding box at the implicit start point. .Decorate an Image by superimposing a Graphic. ;Note - this function has a very general type signature and ! supports various graphic types: 1 decorate :: Image u a -> Graphic u -> Image u a : decorate :: LocImage u a -> LocGraphic u -> LocImage u a I decorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a Anterior decorate* - decorate an Image by superimposing it  on a Graphic. BNote - here the Graphic has access to the result produced by the  the Image unlike . ;Again, this function has a very general type signature and ! supports various graphic types: 2 adecorate :: Image u a -> Graphic u -> Image u a ; adecorate :: LocImage u a -> LocGraphic u -> LocImage u a J adecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a Superior decorate) - decorate an image by superimposing a  graphic on top of it. ANote, here the Graphic has access to the result produced by the  the Image unlike . ;Again, this function has a very general type signature and ! supports various graphic types: 2 sdecorate :: Image u a -> Graphic u -> Image u a ; sdecorate :: LocImage u a -> LocGraphic u -> LocImage u a J sdecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a Hyperlink a graphic object. >This function has a very general type signature and supports  various graphic types: . hyperlink :: XLink -> Graphic u -> Graphic u . hyperlink :: XLink -> Image u a -> Image u a 4 hyperlink :: XLink -> LocImage u a -> LocImage u a > hyperlink :: XLink -> LocThetaImage u a -> LocThetaImage u a GHC highly unstablestephen.tetley@gmail.com Advance vector& graphic - this partially models the  PostScript show command which moves the  current point by the 4 advance (width) vector as each character is drawn.  : ) loc_context_function * graphic -> Image   Build an  from a context function () that 0 generates the answer displacement vector and a   that draws the .  :  AdvGraphic  Build an empty . The  is treated as a null primitive by   Wumpus-Core1 and is not drawn, the answer vetor generated is  the empty vector (V2 0 0). !Concatenate the two AdvGraphics. >Concatenate the two AdvGraphics spacing them by the supplied  vector. (Concatenate the list of AdvGraphic with . (Concatenate the list of AdvGraphic with . (Concatenate the list of AdvGraphic with . <Render the supplied AdvGraphic, but swap the result advance @ for the supplied vector. This function has behaviour analogue  to fill in the  wl-pprint library.   GHC highly unstablestephen.tetley@gmail.com Alias of  where the unit type is  specialized to Double. 8ConnectorImage is a connector drawn between two points  constructing an Image. <Usually the answer type of a ConnectorImage will be a Path . (defined in Wumpus-Drawing) so the points at midway,  atstart7 etc. or the end directions and tangents can be taken  on it.  Alias of  where the unit type is  specialized to Double. :ConnectorGraphic is a connector drawn between two points  contructing a Graphic.  : 2 conn_context_function * conn_graphic -> LocImage   Connector version of . The * is built as a function from an implicit % start and end points to the answer.  :  ConnectorGraphic  Build an empty . The  is treated as a null primitive by   Wumpus-Core0 and is not drawn, although it does generate a @ bounding box around the rectangular hull of the start and end  points. GHC highly unstablestephen.tetley@gmail.com# :  [next_vector] -> (Point2 ~> PrimPath)  Create a path  - i.e. a functional type  from Point to PrimPath. This is the analogue to  in  Wumpus-Core , but the  result is produced within the DrawingContext.  :  (Point ~> PrimPath)  Create an empty path  - i.e. a functional type  from Point to PrimPath. This is the analogue to  in  Wumpus-Core , but the  result is produced within the DrawingContext.  :  path -> Graphic  This is the analogue to  in  Wumpus-core , but the ? drawing properties (colour, line width, etc.) are taken from  the implicit DrawingContext.  :  path -> Graphic  This is the analogue to  in  Wumpus-core , but the ? drawing properties (colour, line width, etc.) are taken from  the implicit DrawingContext.  :  path -> Graphic  This is the analogue to  in  Wumpus-core , but the ( fill colour is taken from the implicit DrawingContext.  :  path -> Graphic  This is the analogue to  in  Wumpus-core , but the > drawing properties (fill colour, border colour, line width, # etc.) are taken from the implicit DrawingContext.  :  string -> LocGraphic  Create a text  - i.e. a functional type  from Point to Graphic. ;The implicit point of the LocGraphic is the baseline left. This is the analogue to  in  Wumpus-core , but the A text properties (font family, font size, colour) are taken from  the implicit DrawingContext.  :  string -> LocThetaGraphic  Create a text  - i.e. a functional type  from Point and Angle to Graphic. ?The implicit point of the LocGraphic is the baseline left, the 0 implicit angle is rotation factor of the text. @Note - rotated text often does not render well in PostScript or - SVG. Rotated text should be used sparingly. This is the analogue to  in  Wumpus-core.  :  escaped_text -> LocGraphic  Create a text  - i.e. a functional type  from Point to Graphic. ;The implicit point of the LocGraphic is the baseline left. This is the analogue to  in  Wumpus-core, but A the text properties (font family, font size, colour) are taken  from the implicit DrawingContext.  : ! escaped_text -> LocThetaGraphic  Create a text  - i.e. a functional type  from Point and Angle to Graphic. ?The implicit point of the LocGraphic is the baseline left, the 0 implicit angle is rotation factor of the text. @Note - rotated text often does not render well in PostScript or - SVG. Rotated text should be used sparingly. This is the analogue to   in  Wumpus-core, but A the text properties (font family, font size, colour) are taken  from the implicit DrawingContext.  :  [kern_char] -> LocGraphic  "Create a horizontally kerned text  - i.e. a  functional type from Point to Graphic. ;The implicit point of the LocGraphic is the baseline left. This is the analogue to ! in  Wumpus-core, but A the text properties (font family, font size, colour) are taken  from the implicit DrawingContext.  :  [kern_char] -> LocGraphic   Create a vertically kerned text  - i.e. a  functional type from Point to Graphic. ;The implicit point of the LocGraphic is the baseline left. This is the analogue to " in  Wumpus-core, but A the text properties (font family, font size, colour) are taken  from the implicit DrawingContext.  :  vec_to -> LocGraphic  Create a stright line  - i.e. a functional type  from Point to Graphic. >The implicit point of the LocGraphic is the start point, the A end point is calculated by displacing the start point with the  supplied vector. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  : ' start_point * end_point -> LocGraphic  Create a straight line , the start and end point  are supplied explicitly. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  : ! start_point * control_point1 * . control_point2 * end_point -> Graphic  Create a Bezier curve , all control points are  supplied explicitly. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.    :  radius -> LocGraphic  Create a stroked circle  - the implicit point is 7 center. The circle is drawn with four Bezier curves. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.    :  radius -> LocGraphic  Create a filled circle  - the implicit point is 7 center. The circle is drawn with four Bezier curves. +The fill colour is taken from the implicit DrawingContext.    :  radius -> LocGraphic  Create a bordered circle  - the implicit point is 7 center. The circle is drawn with four Bezier curves. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext.    : # x_radius * y_radius -> LocGraphic  Create a stroked ellipse  - the implicit point is 8 center. The ellipse is drawn with four Bezier curves. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.    : ( x_radius * y_radius -> LocThetaGraphic  Create a stroked ellipse  - the implicit point < is center and the angle is rotation about the center. The , ellipse is drawn with four Bezier curves. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a filled ellipse  - the implicit point is 8 center. The ellipse is drawn with four Bezier curves. +The fill colour is taken from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a filled ellipse  - the implicit point < is center and the angle is rotation about the center. The - ellipse is drawn with four Bezier curves. +The fill colour is taken from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a bordered ellipse  - the implicit point is 8 center. The ellipse is drawn with four Bezier curves. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a bordered ellipse  - the implicit point < is center and the angle is rotation about the center. The - ellipse is drawn with four Bezier curves. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext. #Supplied point is  bottom-left.  :  width * height -> LocGraphic  Create a stroked rectangle  - the implicit point is  bottom-left. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  :  width * height -> LocGraphic  Create a filled rectangle  - the implicit point is  the bottom-left. +The fill colour is taken from the implicit DrawingContext.  :  width * height -> LocGraphic  Create a bordered rectangle  - the implicit point is  bottom-left. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext.  :  radius -> LocGraphic  Create a stroked circle  - the implicit point is  the center. 5This is a efficient representation of circles using  PostScript's arc or SVG's circle in the generated : output. However, stroked-circles do not draw well after ; non-uniform scaling - the pen width is scaled as well as  the shape. 8For stroked circles that can be adequately scaled, use    instead. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  :  radius -> LocGraphic  Create a filled circle  - the implicit point is  the center. 5This is a efficient representation of circles using  PostScript's arc or SVG's circle in the generated ; output. As the circle is filled rather than drawn with a  "pen" a  filledDisk can be scaled. +The fill colour is taken from the implicit DrawingContext.  :  radius -> LocGraphic  Create a bordered circle  - the implicit point is  the center. 5This is a efficient representation of circles using  PostScript's arc or SVG's circle in the generated = output. However, bordereded circles do not draw well after B non-uniform scaling - the pen width of the outline is scaled as  well as the shape. 9For bordered circles that can be adequately scaled, use    instead. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a stroked ellipse  - the implicit point is  the center. 5This is a efficient representation of circles using  PostScript's arc or SVG's ellipse in the generated ; output. However, stroked ellipses do not draw well after ; non-uniform scaling - the pen width is scaled as well as  the shape. 9For stroked ellipses that can be adequately scaled, use    instead. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a filled ellipse  - the implicit point is  the center. 6This is a efficient representation of ellipses using  PostScript's arc or SVG's ellipse in the generated < output. As the ellipse is filled rather than drawn with a  "pen" a filledEllipseDisk can be scaled. +The fill colour is taken from the implicit DrawingContext.  : # x_radius * y_radius -> LocGraphic  Create a bordered ellipse  - the implicit point is  the center. 6This is a efficient representation of ellipses using  PostScript's arc or SVG's ellipse in the generated > output. However, bordereded ellipses do not draw well after B non-uniform scaling - the pen width of the outline is scaled as  well as the shape. :For bordered ellipses that can be adequately scaled, use   instead. >The background fill colour and the outline stroke properties  are taken from the implicit DrawingContext. !     !     !     GHC highly unstablestephen.tetley@gmail.com %LocThetaGraphic with a bounding box. &Note the size of bounding box for the "same" shape will vary 6 according to the rotation. A bounding box is always ' orthonormal (?) to the x- and y-axes.  LocGraphic with a bounding box.  Graphic with a bounding box. !! :  theta * bbox -> BBox  Rotate a bounding box by theta about its center. Take the  new bounding box. @Remember that bounding boxes are always orthonormal rectangles, > so the dimensions as well as the positions may change under  rotation. "" :  BoundedLocGraphic  Build an empty . The " is treated as a null primitive  by  Wumpus-Core- and is not drawn, although it does generate 9 the minimum bounding box with both the bottom-left and 2 upper-right corners at the implicit start point. ## :  BoundedLocThetaGraphic  Build an empty . The # is treated as a null primitive  by  Wumpus-Core- and is not drawn, although it does generate 9 the minimum bounding box with both the bottom-left and @ upper-right corners at the implicit start point (the implicit  inclination can be ignored). $%&'  !"#$%&'  "#!$%&'  !"#$%&'GHC highly unstablestephen.tetley@gmail.com()*+,-./01>Datatype enumerating positions within a rectangle that can be  derived for a :. 2345674Utility datatype representing orientation within a  rectangular frame,. ObjectPos is useful for graphics such as > text where the start point is not necessarily at the center  (or bottom left).  E x_minor is the horizontal distance from the left to the start point  F x_major is the horizontal distance from the start point to the right  E y_minor is the vertical distance from the bottom to the start point  B y_major is the vertical distance from the start point to the top "Values should be not be negative! 8A positionable Image. 9=Version of PosImage specialized to Double for the unit type. :A positionable Graphic. ;?Version of PosGraphic specialized to Double for the unit type. $<Concatenation here essentially turns both ObjectPos objects  into  center-form# then finds the maximum rectangle. %5Find the half-width and half-height of an ObjectPos. Essentially this is  center-form of an ObjectPos, but  in  center-form there is duplication:   xminor == xmajor  yminor == ymajor ,So instead, the result type is just a pair. << : ( object_pos * loc_graphic -> PosGraphic   Create a 8 from an 67 describing how it / is orientated within a border rectangle and a  that  draws it. == : " pos_image * rect_pos -> LocImage  Downcast a 8 to a  by supplying it  with a 1 (start position). >> : 0 pos_image * start_point * rect_pos -> LocImage  Downcast a : to an  by supplying it  with an initial point and a 1 (start position). &<The vector from some Rectangle position to the start point. ?2Calculate the bounding box formed by locating the 67  at the supplied point. ()*+,-./0123456789:;<=>?1()*+,-./076543289:;<=>?()*+,-./01 ()*+,-./02345676543289:;<=>?GHC unstablestephen.tetley@gmail.com'(@)*ABCDE<Run the drawing returning only the output it produces, drop * any answer from the monadic computation. F=Run the drawing ignoring the output it produces, return the & answer from the monadic computation. >Note - this useful for testing, generally one would want the : opposite behaviour (return the drawing, ignore than the  answer). GHIJUnsafe promotion of HPrim to Picture. 3If the HPrim is empty, a run-time error is thrown. KSafe promotion of HPrim to (Maybe Picture). If the HPrim is empty, then Nothing is returned. LUnsafe promotion of (Maybe Picture) to Picture. This is equivalent to:  ! fromMaybe (error "empty") $ pic ;This function is solely a convenience, using it saves one  import and a few characters. If the supplied value is Nothing a run-time error is thrown. MN2Draw a Graphic taking the drawing style from the  drawing context.  This operation is analogeous to tell in a Writer monad. OHyperlink version of N. P1Draw an Image taking the drawing style from the  drawing context. ?The graphic representation of the Image is drawn in the Trace $ monad, and the result is returned. Q Forgetful P. RHyperlink version of P. S Forgetful R. TU@ABCDEFGHIJKLMNOPQRSTU@BACDEFGHIJKLMNOPQRSTU@ABCDEFGHIJKLMNOPQRSTUGHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>V!Anchors in the center of a side. ;Sides are addressable by index. Following TikZ, side 1 is @ expected to be the top of the shape. If the shape has an apex A instead of a side then side 1 is expected to be the first side  left of the apex. >Implementations are also expected to modulo the side number, + rather than throw an out-of-bounds error. WX9Anchors at the bottom left and right corners of a shape. YZ[6Anchors at the top left and right corners of a shape. >For some shapes (Rectangle) the TikZ convention appears to be 5 have cardinals as the corner anchors, but this doesn't seem @ to be uniform. Wumpus will need to reconsider anchors at some  point... \]^6Anchor on a border that can be addressed by an angle. ?The angle is counter-clockwise from the right-horizontal, i.e.  0 is east. _`?Secondary group of cardinal (compass) positions on an object. =It seems possible that for some objects defining the primary = compass points (north, south,...) will be straight-forward 7 whereas defining the secondary compass points may be ; problematic, hence the compass points are split into two  classes. abcde,Cardinal (compass) positions on an object. ;Note - in TikZ cardinal anchors are not necessarily at the @ equivalent radial position, for instance reactangle north-east = is the top-right corner whether or not this is incident at  45deg. .Wumpus generally follows the TikZ convention. fghijApex of an object. klCenter of an object. mnn : ' extract_func * dist * object -> Point  <Derive a anchor by projecting a line from the center of an : object through the intermediate anchor (produced by the ? extraction function). The final answer point is located along - the projected line at the supplied distance dist. <E.g. take the north of a rectangle and project it 10 units  further on:   projectAnchor north 10 my_rect ?If the distance is zero the answer with be whatever point the # the extraction function produces. :If the distance is negative the answer will be along the B projection line, between the center and the intermediate anchor. @If the distance is positive the anchor will be extend outwards  from the intermediate anchor. oo : + object_a * object_b -> (Point_a, Point_b)  .Find the radial connectors points for objects a and b along ! the line joining their centers. VWXYZ[\]^_`abcdefghijklmnolmjkefghi`abcd^_[\]XYZVWnoVWWXYZYZ[\]\]^__`abcdabcdefghifghijkklmmnoGHC unstablestephen.tetley@gmail.com0+,pA Contextual Picture. This type corresponds to the - type in Wumpus-Core, but  it is embedded with a  (for font properties, ) fill colour etc.). So it is a function  from DrawingContext to Picture. ?Internally the result is actually a (Maybe Picture) and not a : Picture, this is a trick to promote the extraction from ; possibly empty drawings (created by TraceDrawing) to the = top-level of the type hierarchy where client code can deal ; with empty drawings explicitly (empty Pictures cannot be  rendered by Wumpus-Core).   a `oplus` b The z (semigroup) instance for p draws picture = a in front of picture b in the z-order, neither picture is < moved. (Usually the picture composition operators in this > module move the second picture aligning it somehow with the  first). q?Version of CtxPicture specialized to Double for the unit type. rr : , drawing_ctx * ctx_picture -> Maybe Picture  Run a p with the supplied   producing a -. 8The resulting Picture may be empty. Wumpus-Core cannot ? generate empty pictures as they have no bounding box, so the A result is wrapped within a Maybe. This delegates reponsibility - for handling empty pictures to client code. ss : & drawing_ctx * ctx_picture -> Picture  Unsafe version of r. ;This function throws a runtime error when supplied with an  empty CtxPicture. tt :  trace_drawing -> CtxPicture   Transform a @ into a p. uu : " path * ctx_picture -> CtxPicture  Clip a picture with a path. vv : # trafo * ctx_picture -> CtxPicture  /Apply a picture transformation function to the -  warpped in a p. ./The center of a picture. 0'Extract the mid point of the top edge. 1*Extract the mid point of the bottom edge. 2(Extract the mid point of the left edge. 3)Extract the mid point of the right edge. 4Extract the top-left corner. 5Extract the top-right corner. 6 Extract the bottom-left corner. 7!Extract the bottom-right corner. 89:;<=>ww : + ctx_picture1 * ctx_picture2 -> CtxPicture    a `cxpBeneath` b  Similarly beneath, draws the first picture behind the second 3 picture in the z-order, neither picture is moved. xDraw a, move b) so its center is at the same center as  a, b) is drawn over underneath in the zorder.  a `cxpUniteCenter` b y  a `cxpRight` b *Horizontal composition - position picture b to the right of  picture a. z  a `cxpDown` b (Vertical composition - position picture b down from picture  a. {*Center the picture at the supplied point. || :  ctx_picture1 * [ctx_picture] -> CtxPicture  8Make a row of pictures concatenating them horizontally. Note - this function is in destructor form. As Wumpus cannot 1 make a Picture from an empty list of Pictures,  destructor form decomposes the list into the head and the  rest8 in the function signature, rather than take a possibly ( empty list and have to throw an error. }} :  ctx_picture1 * [ctx_picture] -> CtxPicture  9Make a column of pictures concatenating them vertically. Note - this function is in destructor form. ~  cxpRightSep n a b Horizontal composition - move b, placing it to the right  of a with a horizontal gap of n separating the pictures.   cxpDownSep n a b Vertical composition - move b, placing it below a with a  vertical gap of n separating the pictures.   picRowSep n x xs !Concatenate the list of pictures xs horizontally with  hspace starting at x&. The pictures are interspersed with  spaces of n units.   vsepPic n xs !Concatenate the list of pictures xs vertically with  vspace starting at x&. The pictures are interspersed with  spaces of n units. ?  cxpAlignH align a b Horizontal composition - move b, placing it to the right  of a0 and align it with the top, center or bottom of a.   cxpAlignV align a b Vertical composition - move b, placing it below a 0 and align it with the left, center or right of a. @  cxpAlignSepH align sep a b Spacing version of  - move b to the right of a  separated by sep units, align b according to align.   cxpAlignSepV align sep a b !Spacing version of alignV - move b below a  separated by sep units, align b according to align.  Variant of |% that aligns the pictures as well as  concatenating them.  Variant of }% that aligns the pictures as well as  concatenating them.  Variant of |% that aligns the pictures as well as ! concatenating and spacing them.  Variant of }% that aligns the pictures as well as ! concatenating and spacing them. A  a `oplus` b Place 'drawing' a over b. The idea of over here is in = terms z-ordering, nither picture a or b are actually moved. pqrstuvwxyz{|}~pqrstuvwxyz{|}~pqrstuvwxyz{|}~ GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com> :  ang -> Quadrant  Get the quadrant of an angle.  :  ang -> Radian  8Modulo an angle so it lies in quadrant I (north east),  i.e. modulo into the range 0..(pi/2). BCD : ' half_width * half_height * ang -> Vec  @Find where a radial line extended from (0,0) with the elevation  ang; intersects with an enclosing rectangle. The rectangle is  centered at (0,0). ?Internally the calculation is made in quadrant I (north east), > symmetry is used to translate result to the other quadrants.  :  width * height * ang -> Vec  *Find where a line from (0,0) in direction ang intersects the ; top or right side of a rectangle in QI (left side is the " y-axis, bottom is the x-axis). / ang must be in the @range 0 < ang <= 90 deg@.  $ width and height must be positive.  : ' half_width * half_height * ang -> Vec  @Find where a radial line extended from (0,0) with the elevation  ang7 intersects with an enclosing diamond. The diamond is  centered at (0,0). ?Internally the calculation is made in quadrant I (north east), > symmetry is used to translate result to the other quadrants.  : # half_base_width * height_minor * " height_minor * ang -> Vec  @Find where a radial line extended from (0,0) with the elevation  ang: intersects with an enclosing triangle. The triangle has @ the centroid at (0,0), so solutions in quadrants I and II are > intersections with a simple line. Intersections in quadrants = III and IV can intersect either the respective side or the  base.  :  width * height * ang -> Vec  ,Find where a line from (0,0) with elevation ang intersects B the hypotenuse a right triangle in QI (the legs of the triangle  take the x and y-axes). + ang must be in the @range 0 < ang <= 90@.  $ width and height must be positive.  : + top_width * height * top_right_ang -> Vec  ,Find where a line from (0,0) with elevation ang intersects > the either the lines A_B or B_D in a right trapezoid in QI. @The right trapezoid has a variable right side. Left side is the = y-axis (C_A), bottom side is the x-axis (C_D), top side is  parallel to the x-axis (A_B).   A B  -----  | \  | \  -------  C D   A B  -------  | /  | /  -----  C D ) ang must be in the range 0 < ang <= 90.  ( top_width and height must be positive. EtraingleLeftSide : - base_width * left_ang * right_ang -> Length     C  /\  / \  / \  / \  /________\  A B  < Calculate A_C given side A_B, angle C/A\B and angle A/B\C.  : . top_width * height * top_right_ang -> Length  !Find the length of the line C_D:   A B  -----  | \  | \  -------  C D  A B  -------  | /  | /  -----  C D !GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com> A functional type from  initial point to point list. Supplied point is  bottom-left, subsequenct points are & counter-clockise so [ bl, br, tr, tl ] .  diamondPath : 5 half_width * half_height * center_point -> PrimPath   : ' num_points * radius * center -> [point]   isocelesTriangle bw h pt<Supplied point is the centriod of the triangle. This has a . nicer visual balance than using half-height.  isocelesTriangle bw h pt<Supplied point is the centriod of the triangle. This has a . nicer visual balance than using half-height.   side_length * ctr -> [Points]   &GHC highly unstablestephen.tetley@gmail.com     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com> :   path_to_afm_fonts * [font_name] -> IO (metrics, messages)  "Load the supplied list of fonts. <Note - if a font fails to load a message is written to the  log and monospaced fallback metrics are used. FG>These are values extracted from Courier in the core 14 fonts. #GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com> :   path_to_gs_fonts * [font_name] -> IO (metrics, messages)  "Load the supplied list of fonts. <Note - if a font fails to load a message is written to the  log and monospaced fallback metrics are used. HIJ)These are values extracted from the file  n022003l.afm  which is the font NimbusMonL-Regu , GhostScript' s eqivalent $ font for the core 14 font Courier. $GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>'02x2 matrix, considered to be in row-major form.  (M2'2 a b  c d) Line in equational form, i.e. Ax + By + C = 0. A Strict cubic Bezier curve. K#Construct the identity 2x2 matrix:  (M2'2 1 0  0 1 ) Determinant of a 2x2 matrix. Transpose a 2x2 matrix.  : ! point1 * point2 -> LineEquation  <Construct a line in equational form bisecting the supplied  points.  :  x * line_equation -> Point  1Calculate the point on the line for the supplied x value.  :  y * line_equation -> Point  1Calculate the point on the line for the supplied y value.  :  point -> line -> Distance  <Find the distance from a point to a line in equational form  using this formula:   P(u,v)  L: Ax + By + C = 0   (A*u) + (B*v) + C  -----------------  sqrt $ (A^2) +(B^2) <A positive distance indicates the point is above the line,  negative indicates below.  : ) half_width * half_height -> [LineSegment]  *Compute the line segments of a rectangle.  :  [point] -> [LineSegment]  5Build the line segments of a polygon fome a list of  its vertices.  : ( start_point * control_1 * control_2 *  end_point -> Length  5Find the length of a Bezier curve. The result is an  approximation, with the  tolerance is 0.1 of a point. This A seems good enough for drawing (potentially the tolerance could  be larger still). 9The result is found through repeated subdivision so the $ calculation is potentially costly. L Jens Gravesen'$s bezier arc-length approximation. =Note this implementation is parametrized on error tolerance. M6Length of the tree lines spanning the control points. N/Length of the cord - start point to end point. "Curve subdivision via de Casteljau' s algorithm. 2subdivide with an affine weight along the line... O : 2 apex_angle * radius * rotation * center -> [Point]   . ang should be in the range 0 < ang < 360deg. & if 0 < ang <= 90 returns 4 points & if 90 < ang <= 180 returns 7 points ' if 180 < ang <= 270 returns 10 points ' if 270 < ang < 360 returns 13 points  : 8 apex_angle * radius * rotation * center -> BezierCurve  . ang should be in the range 0 < ang <= 90deg. Affine combination...  : % start_point * end_point -> Midpoint  >Mid-point on the line formed between the two supplied points.  : " start_point * end_point -> Angle  ?Calculate the counter-clockwise angle between the line formed - by the two points and the horizontal plane. """%GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>  :  line1 * line2 -> Maybe Point  6Find the intersection of two lines, if there is one. <Lines are infinite they are represented by points on them,  they are not line segments.  An answer of Nothing( may indicate wither the lines coincide  or the are parallel.  : . line_segment1 * line_segment2 -> Maybe Point  >Find the intersection of two line segments, if there is one.  An answer of Nothing# indicates that the line segments - coincide, or that there is no intersection.  : $ line_segment * line -> Maybe Point  >Find the intersection of a line and a line segment, if there  is one.  An answer of Nothing& indicates that the the line and line 5 segment coincide, or that there is no intersection. PQCheck the point is "within" the span of the line. #Note - this function is to be used *after* an intersection ) has been found. Hence it is not export. R.Note - its important to use tolerance for the  withPoints  function. SIs the curve cut by the line? ?The curve might cut at the start or end points - which is good @ as it saves performing a subdivision. But make the return type  a bit involved.  :: & radial_origin * theta * [line_segment] -> Maybe Point  .Find the first intersection of a line through  radial_origin  at angle theta+ and the supplied line segments, if there  is one. T9The tolerance on Radian equality should be acceptable...  :  point * ang -> Line  Make an infinite line /% plane passing through the supplied  with elevation ang.  U'()*+,-./0123456789:;<=>?@ABCDEFG6HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~QXSV                                                       S R V  !"##$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~              !!!!!!!!!"#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%%%w           8                !\"#$%&'()*+,-S.T/0123456789:;<=>?@ABCDE F G H I"J"K#L#M#N$O$P$Q$R$S%T%U%V%W%XYwumpus-basic-0.16.0Wumpus.Basic.VersionNumberWumpus.Basic.Utils.JoinList$Wumpus.Basic.Utils.FormatCombinators$Wumpus.Basic.Utils.ParserCombinatorsWumpus.Basic.Utils.TokenParsers-Wumpus.Basic.System.FontLoader.Base.GSFontMapWumpus.Basic.Utils.HList'Wumpus.Basic.Kernel.Base.ScalingContext%Wumpus.Basic.Kernel.Base.GlyphMetrics-Wumpus.Basic.System.FontLoader.Base.Datatypes1Wumpus.Basic.System.FontLoader.Base.FontLoadMonad1Wumpus.Basic.System.FontLoader.Base.AfmParserBase3Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser/Wumpus.Basic.System.FontLoader.Base.AfmV2Parser'Wumpus.Basic.Kernel.Base.DrawingContext Wumpus.Basic.Kernel.Base.QueryDC!Wumpus.Basic.Kernel.Base.UpdateDC!Wumpus.Basic.Kernel.Base.BaseDefs#Wumpus.Basic.Kernel.Base.ContextFun(Wumpus.Basic.Kernel.Objects.Displacement)Wumpus.Basic.Kernel.Base.WrappedPrimitive'Wumpus.Basic.Kernel.Objects.BaseObjects#Wumpus.Basic.Kernel.Objects.Graphic*Wumpus.Basic.Kernel.Objects.AdvanceGraphic%Wumpus.Basic.Kernel.Objects.Connector-Wumpus.Basic.Kernel.Objects.DrawingPrimitives#Wumpus.Basic.Kernel.Objects.Bounded$Wumpus.Basic.Kernel.Objects.PosImage(Wumpus.Basic.Kernel.Objects.TraceDrawing Wumpus.Basic.Kernel.Base.Anchors&Wumpus.Basic.Kernel.Objects.CtxPictureWumpus.Basic.Geometry.QuadrantWumpus.Basic.Geometry.Paths"Wumpus.Basic.System.FontLoader.Afm*Wumpus.Basic.System.FontLoader.GhostScriptWumpus.Basic.Geometry.Base"Wumpus.Basic.Geometry.IntersectionWumpus.Basic.Kernelwumpus_basic_versionViewR:>EmptyRViewL:<EmptyLJoinListtoListfromList fromListFtoListFtoListMzipWithIntoListnullemptyoneconssnocjoinheadtakeLlength takeWhileL accumMapLviewlviewrunViewLunViewRFormatformatDocSDocshowsDoc<><+>vconcatseparatehcathsepvcattextcharintintegerintegralfloatdoublehex4spacecomma semicolonlinefill fillStringR fillStringL punctuateenclosesquotesdquotesparensbracketsbracesangleslparenrparenlbracketrbracketlbracerbracelangleranglelisttupled semiBracesindentwriteDoc ParseError CharResult CharParserParserResultOkayFail runParserrunParserEitherapplyfailure throwError lookaheadpeekeofequalssatisfyoneOfnoneOfchainl1chainr1chainlchainrchoicecountbetweenoption optionMaybe optionUnitskipOneskipMany skipMany1many1sepBysepBy1sepEndBy sepEndBy1manyTill manyTill1stringanyCharupperlowerletteralphaNumdigithexDigitoctDigitnewlinetab LexemeParserspaceLexemeParserspaceCharLexemeParsercommentLexemeParsercommentLineLexemeParsercommentMultiLexemeParserlexeme whiteSpaceoctBaseoctHaskhexBasenatural GSFontMapghostscript_versionghostscript_fontmap gsMetricsFile gsFontAliasgsVersionNumberghostscript_fontmap_8_54HemptyHwrapHconsHsnocHappendHunfoldrHveloHconcatHtoListH fromListHScalingContext scale_in_x scale_in_yscaleXscaleYscalePtscaleVecunitXunitYuniformScalingcoordinateScaling GlyphMetricsFontMetricsOps MetricsOpsget_bounding_box get_cw_tableget_cap_height get_descenderCharWidthTable CodePointFontNameemptyGlyphMetrics lookupFont insertFontmonospace_metrics FontPropsfp_bounding_boxfp_default_adv_vec fp_adv_vecs fp_cap_height fp_descenderMonospaceDefaultsdefault_letter_bboxdefault_cap_heightdefault_descenderdefault_char_widthAfmGlyphMetrics afm_char_codeafm_width_vector afm_char_nameAfmFile afm_encodingafm_letter_bboxafm_cap_height afm_descenderafm_glyph_metrics GlobalInfoAfmKeyAfmBoundingBoxPSEncodingScheme PSCharCodeAfmUnitafmValue afmUnitScalebuildMetricsOps FontLoadIO FontLoadErr runFontLoadIOevalFontLoadIO loadError logLoadMsg promoteIO promoteEither runParserFLIO sequenceAllbuildAfmFontProps checkFontPath afmFileParserrunQuery textQuery getFontBBoxgetEncodingScheme getCapHeightcharBBoxmetric keyStringPair versionNumberstartCharMetricskeyName newlineOrEOF uptoNewlinenamename1seminumbercinthexIntoctIntsymbolafmV4Dot1Parser afmV2Parser DrawingCtxMaskDClocalize TextMargin text_margin_x text_margin_yDrawingContextFDrawingContext glyph_tablesfallback_metrics stroke_props font_props stroke_colour fill_colourline_spacing_factorround_corner_factor text_marginstandardContextmetricsContextdefault_drawing_contextasksDCwithFontMetricstextAttr withTextAttr strokeAttrwithStrokeAttrfillAttr withFillAttr borderedAttrwithBorderedAttrgetRoundCornerSize getTextMargin getLineWidth getFontAttr getFontSize getFontFacebaselineSpacing markHeightmarkHalfHeightglyphBoundingBoxglyphCapHeightglyphDescenderglyphVerticalSpan cwLookupTablemonoFontPointSize monoCharWidth monoTextWidthmonoTextLength monoCapHeightmonoLowerxHeightmonoDescenderDepthmonoAscenderHeightmonoTextDimensionsmonoMultiLineHeightmonoDefaultPaddingmonoVecToCenterroundCornerFactor textMargin lineWidththick ultrathickthincapButtcapRound capSquare joinMiter joinRound joinBevel dashPatternunit_dash_patternphasedphase doublegaps doubledashesfontAttrfontFacefontSize scalesize doublesizehalfsize swapColoursbothStrokeColourbothFillColour strokeColour fillColour PointSupplyMpositionMonUnit AdvanceVecCardinal NORTH_WESTWEST SOUTH_WESTSOUTH SOUTH_EASTEAST NORTH_EASTNORTHVAlignVRightVCenterVLeftHAlignHBottomHCenterHTopBimapbimapbimapLbimapROPlusoplusoconcatreplaceLreplaceRadvanceHadvanceV DConnectorCF DLocThetaCFDLocCF ConnectorCF LocThetaCFLocCFCF2CF1CFrunCFrunCF1runCF2lift0R1lift0R2lift1R2 promoteR1 promoteR2apply1R1apply2R2apply1R2 drawingCtxqueryCtxlocCtxlocPoint locThetaCtx locThetaPoint locThetaAngconnCtx connStartconnEndatrotatRotconnectchain1ThetaPointDisplace ThetaDisplace PointDisplace moveStartmoveStartThetamoveStartThetaPointmoveStartThetaAngledisplace displaceVec displaceH displaceV northwards southwards eastwards westwardsnortheastwardsnorthwestwardssoutheastwardssouthwestwardsdisplaceParalleldisplacePerpendicular displaceOrthothetaNorthwardsthetaSouthwardsthetaEastwardsthetaWestwardsthetaNortheastwardsthetaNorthwestwardsthetaSoutheastwardsthetaSouthwestwardsgetPrimGraphic PrimGraphicHPrimtraceTraceM hprimToListsingleH primGraphic metamorphPrimcollectH DrawingInfoLocDrawingInfoLocThetaDrawingInfoImageAns GraphicAnsImageLocImage LocThetaImageDImage DLocImageDLocThetaImageDLocThetaGraphicLocThetaGraphic DLocGraphic LocGraphicDGraphicGraphic safeconcat ignoreAns replaceAnsmapAns intoImage intoLocImageintoLocThetaImageemptyLocGraphicemptyLocThetaGraphicdecorate adecorate sdecorate hyperlink DAdvGraphic AdvGraphicintoAdvGraphicemptyAdvGraphicadvcatadvsep advconcatadvspace advpunctuateadvfillDConnectorImageConnectorImageDConnectorGraphicConnectorGraphicintoConnectorImageemptyConnectorGraphiclocPath emptyLocPath openStroke closedStroke filledPath borderedPathtextline rtextline escapedline rescapedline hkernline vkernline straightLinestraightLineGraphic curveGraphic strokedCircle filledCircleborderedCirclestrokedEllipserstrokedEllipse filledEllipserfilledEllipseborderedEllipserborderedEllipsestrokedRectanglefilledRectangleborderedRectangle strokedDisk filledDisk borderedDiskstrokedEllipseDiskfilledEllipseDiskborderedEllipseDiskDBoundedLocThetaGraphicBoundedLocThetaGraphicDBoundedLocGraphicBoundedLocGraphicDBoundedGraphicBoundedGraphiccenterOrthoBBoxemptyBoundedLocGraphicemptyBoundedLocThetaGraphicillustrateBoundedGraphicillustrateBoundedLocGraphic illustrateBoundedLocThetaGraphic bbrectangleCENTERNNSSEEWWNENWSESW RectPosition op_y_major op_y_minor op_x_major op_x_minor ObjectPosPosImage DPosImage PosGraphic DPosGraphic makePosImagestartPos atStartPosobjectPosBounds TraceDrawing TraceDrawingT DTraceDrawingDTraceDrawingTrunTraceDrawingexecTraceDrawingevalTraceDrawingrunTraceDrawingTexecTraceDrawingTevalTraceDrawingTliftToPictureUliftToPictureMb mbPictureUquerydrawxdrawdrawidrawi_xdrawixdrawi_nodenodeiSideMidpointAnchor sideMidpointBottomCornerAnchorbottomLeftCornerbottomRightCornerTopCornerAnchor topLeftCornertopRightCorner RadialAnchor radialAnchorCardinalAnchor2 northeast southeast southwest northwestCardinalAnchornorthsoutheastwest ApexAnchorapex CenterAnchorcenter projectAnchorradialConnectorPoints CtxPicture DCtxPicture runCtxPicturerunCtxPictureU drawTracingclipCtxPicture mapCtxPicture cxpBeneathcxpUniteCentercxpRightcxpDown cxpCenteredAtcxpRow cxpColumn cxpRightSep cxpDownSep cxpRowSep cxpColumnSep cxpAlignH cxpAlignV cxpAlignSepH cxpAlignSepV cxpAlignRowcxpAlignColumncxpAlignRowSepcxpAlignColumnSepQuadrantQUAD_SEQUAD_SWQUAD_NWQUAD_NEquadrantqiModulorectRadialVector rectangleQIdiamondRadialVectortriangleRadialVector triangleQIrightTrapezoidQIrightTrapeziumBaseWidth LocCoordPathcoordinatePrimPathrectangleCoordPathdiamondCoordPathpolygonCoordPathisoscelesTriangleCoordPathisoscelesTrianglePointsequilateralTriangleCoordPathequilateralTrianglePointsloadAfmMetrics loadGSMetricsM2'2 Matrix2'2 DMatrix2'2 line_eqn_C line_eqn_B line_eqn_A LineEquation DLineEquation LineSegment DLineSegment BezierCurve DBezierCurvehalf_pitwo_pi identity2'2det2'2 transpose2'2 lineEquation pointViaX pointViaYpointLineDistancerectangleLineSegmentspolygonLineSegments bezierLength subdivide subdividetbezierArcPointsbezierMinorArc affineCombmidpoint lineAngle interLineLineinterLinesegLineseginterLinesegLineinterCurveLine findIntersect makePlaneJoinOneEmpty joinfoldr joinfoldlIndentLineDoc1unDocindentSrunDocbaseGHC.Real fromIntegralpadr getParserFKSKyieldalt eagerMany eagerSome<:>Control.ApplicativesomegetLexemeParser lineComment spanCommentendLinegetGlyphMetrics getAfmUnit getFontLoadIO FontLoadLoggetFontLoadLogmessage1extractCapHeightextractDescenderextractFontBBox globalInfo getDescenderfontBBoxlpcharMetricsV4Dot1 widthVector characterCode charMetricsV2standardTextMargin wumpus_blackwumpus_light_graywumpus_courier glyphQuery withFontSizemonoTotalCharHeightupdateStrokePropsupdateFontProps thick_lineultra_thick_line thin_line setLineCap setLineJoinunCF2unCF1unCFgetHPrim graphicAnswumpus-core-0.43.0Wumpus.Core.Picture vectorPath emptyPathostrokecstroke fillStroke textlabel rtextlabel escapedlabel rescapedlabel hkernlabel vkernlabel rectanglePathconcatObjectPos halfDists startVectorgetTraceDrawinggetTraceDrawingT getCtxPictureWumpus.Core.PictureInternalPicture boundaryExtr boundaryCtr boundaryN boundaryS boundaryE boundaryW boundaryNW boundaryNE boundarySW boundarySEboundaryLeftEdgeboundaryRightEdgeboundaryBottomEdgeboundaryTopEdge cxpConcat mbpostcomb megaCombR alignMove alignMove2$fOPlusCtxPicturenegateXnegateYnegateXYtriangleLeftSideafmLoadFontCalcsafm_mono_defaults_4_1gsLoadFontCalcsresolveFontFileghostscript_mono_defaults_8_54lift2Matrix2'2gravesenLengthctrlPolyLength cordLengthkappambCheck withinPoints tolerancecut quadrantCheck