=o      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                  ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~        !!!!!!!!!!!""##$$ $ $ $ % %%%%%%%%%%&&&&&&&&& &!&"&#&$&%&&&'&(&)&*&+&,&-&.&/&0&1&2&3&4&5&6&7&8&9&:&;&<&='>'?(@(A(B(C(D)E)F)G)H)I)J)K)L)M)N)O)P)Q)R)S)T*U*V*W*X*Y*Z*[*\*]*^*_*`*a*b*c*d*e*f*g*h*i*j*k*l*m*n*,GHCunstablestephen.tetley@gmail.comVersion number  (0,18,0) !opq'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. r&Right-associative fold of a JoinList. s%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 ... tuvwxyz!'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>>NOPQ}~RSTUVWXYZ[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. 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... GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>!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. 9Anchors at the bottom left and right corners of a shape. 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  for the diagonal positions. =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. ,Cardinal (compass) positions on an object. @Cardinal anchors should be at their equivalent radial position. ? However, some shapes may not be able to easily define radial A positions or may be able to provide more efficient definitions B for the cardinal anchors. Hence the redundancy seems justified. Apex of an object. Center of an object. !Note an Anchor is just a Point2.  : ' 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.  : + object_a * object_b -> (Point_a, Point_b)  .Find the radial connectors points for objects a and b along ! the line joining their centers. GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>). is a Hughes list of Strings, so it supports  efficient append.  - type synonym for String. :A map between a font name and the respective FontMetrics. 0 store a subset of the properties available in ? a font file - enough to calculate accurate bounding boxes and  positions for text.  3 Bounding box representing the maximum glyph area. # Width vectors for each character.  Cap height  Descender depth. <Because Wumpus always needs font metrics respective to the : current point size, the actual fields are all functions. %A lookup function from code point to  width vector. >The unit is always stored as a Double representing PostScript  points. ?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). 7A family group of FontDefs (regular, bold, italic and  bold-italic). ?It is convenient for some higher-level text objects in Wumpus  (particularly Doc, in Wumpus-Drawing) to treat a font and its 2 standard weights as the same entity. This allows Doc API to  provide a bold, operation to simply change to the the bold > weight of the current family, rather than use the primitive  set_font2 operation to change to an explicitly named font. FontDef wraps FontFace! from Wumpus-Core with file name # information for the font loaders. A Unicode code-point. Extract the regular weight  from a . Extract the bold weight  from a . ANote - this falls back to the regular weight if the font family / has no bold weight. To get the bold weight or Nothing if it ( is not present use the record selector ff_bold.  Extract the italic weight  from a . ANote - this falls back to the regular weight if the font family 3 has no italic weight. To get the italic weight or Nothing if + it is not present use the record selector  ff_italic.  Extract the  bold-italic weight  from a  . ANote - this falls back to the regular weight if the font family > has no bold-italic weight. To get the bold-italic weight or  Nothing/ if it is not present use the record selector  ff_bold_italic. !Print the loader errors from the  to std-out.  : ( name * font_table -> Maybe FontMetrics  !Lookup a font in the font_table.  : / name * font_metrics * font_table -> FontTable  )Insert a named font into the font_table. 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. 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>;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> GHC highly unstablestephen.tetley@gmail.com79An enumerated type representing horizontal and vertical  directions. 8An enumeratied type representing the compass positions.  !"#$%&:Vertical alignment - align to the left, center or bottom. '()*;Horizontal alignment - align to the top, center or bottom. +,-.(Decorating with resepct to the Z-order   SUPERIOR - in front.  ANTERIOR - behind. /0123456789:;The empty data type - i.e. () - wrapped with a phantom unit  parameter. <=A Bifunctor class. >Again, it would be nice if there was a Bifunctor class in the  Haskell Base libraries... >?@AA 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... BC;Type family to access the unit parameter of a TraceDrawing * or a promoted TraceDrawingT transformer. DD :  list_head * [rest] -> Ans  Semigroup version of mconcat from the module  Data.Monoid. *As a semigroup cannot build a zero value, concat cannot # handle the empty list. So to make D a safe function : the input list is already destructured by one cons cell. 9Effectively this means that client code must handle the ! empty list case, before calling D. EE :  alternative * [list] -> Ans E uses B' to create a summary value from a list  of values. When supplied the empty list E returns the supplied   alternative2 value. If the list is inhabited, the alternative  value is discarded. This contrasts to D$ where the single value represents + the head of an already destructured list. FGH71 an object that gives access to its unit at the  functor position. I61 an object that gives access to its unit at the  functor position. J1Convert a scalar value from one unit to another. K<Unit convert an object that gives access to its unit at the  Functor position. In practive this will be *all* Image answers. LMNSum a list of Vectors. >Note - this function is a candidate to go in Wumpus-Core, but A it will be added when there is an intrinsic reason to to update  Core (bug fix, or API change). 7 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN7CABDE=>?@FG;<89:567HIJKLM1432.0/*-,+&)('%$#"! N7%$#"!  !"#$%&)(''()*-,++,-.0//014322345676789:9:;<<=>?@>?@ABBCDEFGHIJKLMNGHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>O#Wrapped Double representing an En. P$Wrapped Double representing an Em. QWrapped Double Pica unit type. Pica is 12 Points. R(Wrapped Double representing Centimeter. S5Cast a value in Centimeters to some Fractional type. ;Note - this casting should only be used for non-contextual  units such as Double. TConvert Double to Centimer. U.Cast a value in Pica to some Fractional type. ;Note - this casting should only be used for non-contextual  units such as Double. VConvert a Double to a Pica. OPQRSTUVRSTQUVPOOPQRSTUVGHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>/WW is equivalent to the to the  MonadReader - class, but the environment type is fixed to lk. To avoid name clashes with mtl this scheme is used:   askDC = ask  asksDC = asks  localize = local $Note, because the derived operation query (aka asks) is 3 expected to be used more often than queryCtx (aka ask) it  gets the more convenient name. XYZ[5ConnectorProps control the drawing of connectors in  Wumpus-Drawing.   conn_src_space :: Em  conn_dst_space :: Em @Source and destination spacers - these add spacing between the B respective connector points and the tips of the drawn connector.   conn_src_offset :: Em  conn_dst_offset :: Em =Source and destination offsets - these offset the drawing of > the connector perpendicular to the direction of line formed B between the connector points (a positive offset is drawn above, > a negative offset below). The main use of offsets is to draw  parallel line connectors.   conn_arc_ang :: Radian  Control the bend of an arc connector.   conn_src_arm :: Em  conn_dst_arm :: Em  Control the arm/ length of a jointed connector - arms are the % initial segments of the connector.   conn_loop_size :: Em  Control the height of a loop connector.   conn_box_halfsize :: Em :Control the size of a connector box. Connector boxes are @ drawn with the exterior lines projected out from the connector $ points a halfsize above and below. \]^_`abcdefThe text margin is measured in P so it is relative to the  current font size. The default value is 0.5. ghij2Type synonym for DrawingContext update functions. klk - 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 - in contrast to most other drawing objects in Wumpus, ; none of the types of measurement values are parameteric ) (usually notated with the type variable u in Wumpus). Types  are either + representing PostScript points or Em - a ? contextual size that is interpreted according to the current  font size. :It is easier to specialize all the measurement types and  within the lk and add parametricity to the  getters and setters instead. lmnopqrstuvwxyzz :  font_size -> DrawingContext   Create a lk. Note -  font_size) is used for sizing more than just text > labels. Arrowheads, plot marks and other elements have their % metrics derived from the font size. (No real font metrics are present in the lk  created by z. Static, hard-coded fallback  metrics derived from the Courier font are available but 7 these metrics might not accurately correspond to the  Courier3 available to the the final renderer (GhostScript,  an SVG viewer, etc.). =Use this constructor for drawings that make primitive use of  text.   font_metrics_table: empty  font_load_log: empty ( fallback_metrics: monospace_metrics  font_face: Courier + font_size: @supplied_font_size@ L stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter.  stroke_colour: black ! fill_colour: light_gray  text_colour: black  line_spacing_factor: 0.2  round_corner_factor: 0 ( text_margin: (0.5 em, 0.5 em)  conn_src_sep: 0  conn_dst_sep: 0  conn_src_offset: 0  conn_dst_offset: 0  conn_arc_ang: pi / 12  conn_src_arm: 1  conn_dst_arm: 1  conn_loop_size: 2 {{ : , font_size * font_metrics -> DrawingContext   Create a lk$ with font metrics loaded from the  file system. Note -  font_size) is used for sizing more than just text > labels. Arrowheads, plot marks and other elements have their % metrics derived from the font size. =Use this constructor for drawings that make use of the text  objects provided by Wumpus-Drawing (DocText and RotText). || : ) font_load_result -> DrawinContextUpdate  >Add the font metrics from the FontLoadResult, if a font with $ the same name alreay exists in the lk it will be - replaced. Error and warning messages in the font_load_result  will be appended to the  font_load_log. }} :  DrawingContextF  $Reset the drawing properties in the lk to their 4 default values. This changes the following fields: L stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter.  stroke_colour: black ! fill_colour: light_gray  text_colour: black  line_spacing_factor: 0.2  round_corner_factor: 0 ( text_margin: (0.5 em, 0.5 em) ~~ :  DrawingContextF  !Reset the drawing metrics in the lk to their 3 default values. This is a more limited version of  }# and changes the following fields: L stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter.  line_spacing_factor: 0.2  round_corner_factor: 0 ( text_margin: (0.5 em, 0.5 em) Courier )WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)klmnopqrstuvwxyjfghi[\]^_`abcdez{|}~WXYZ)WXYZXYZ[ \]^_`abcde\]^_`abcdefghighijklmnopqrstuvwxylmnopqrstuvwxyz{|}~GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>$;Get the Point corresponding the grid coordinates scaled by  the snap-grid scaling factors. <Scale a vector coordinate by the snap-grid scaling factors. Absolute units. "Get the (x,y) margin around text. >Note - not all text operations in Wumpus are drawn with text  margin. 7Vertical distance between descender of a line and the  cap-height of the line below. =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. Height of a capital letter. -Note - descender is expected to be negative. 3This is the distance from cap_height to descender. 6Note the CharWidthLookup is not parameteric on units.  CharWidth2 is always Double representing PostScript points. 2 Client code must convert this value accordingly. """GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>> : $ x_unit * y_unit -> DrawingContextF  Set the snap grid factors" - a snap grid is an alternative 5 coordinate space, it can be convenient for drawing  " box and arrow" diagrams. set_line_width : $ width_in_points -> DrawingContextF  /Set the line_width to the supplied point size. !Initially the line width is 1.0. Constant+ variations of the function maybe be more  convenient: 7 line_default, line_thin, line_thick, line_ultra_thick Set the line_width to default - 1.0. Set the line_width to thin - 0.5. Set the line_width to thick - 2.0. Set the line_width to  ultra_thick - 4.0. ;Set the line width to a size relative to the current font : size. The size is calculated with the supplied function. )Set the line_cap to the default which is butt. This is a synonym for . Set the line_cap to butt. 6Butt chamfers off the stroke, flush to the end point. This is the default.  .-------.  |=======|  '-------' Set the line_cap to round. 8This rounds the end of the stroke and the visually the 3 rounding slightly extends the length of the line.  .-------.  ( ======= )  '-------' Set the line_cap to square. @This squares off the end of the stroke, but visual extends the  stroke by half the line width.  .---------.  | ======= |  '---------' *Set the line_join to the default which is miter. This is a synonym for . Set the line_join to miter. >This extends the joining line segments to form a sharp miter. This is the default.  /\  /..\  /./\.\  /./ \.\  /./ \.\ Set the line_join to round. 8This rounds off the corner of the joined line segments.  \.\  \.\  ,.)  /./  /./ Set the line_join to round. ?This bevels off the corner of the joined line segments with a  notch.  __  /..\  /./\.\  /./ \.\  /./ \.\ Set the dash pattern. Initially the dash pattern is . Set the dash_pattern to solid - i.e. no dash pattern. This is the default. ,Set the dash pattern to draw a dotted line. ?A dot is actually a square - side length is equal to the line  width. 3The spacing between dots is 2 times the dot width. ;Set the dash pattern to draw a tightly packed dotted line. ?A dot is actually a square - side length is equal to the line  width. 4The spacing between dots is equal to the dot width. 4Set the dash pattern to draw a loosely dotted line. ?A dot is actually a square - side length is equal to the line  width. 3The spacing between dots is 4 times the dot width. ,Set the dash pattern to draw a dashed line. <The dash length is 3 times the line width, the spacing is 2  times the line width. <Set the dash pattern to draw a tightly packed, dashed line. ;The dash length is 3 times the line width, the spacing is  equal to the line width. 4Set the dash pattern to draw a loosely dashed line. <The dash length is 3 times the line width, the spacing is 4  times the line width. 3Set the font attributes, point size and font face. Set the font face. Set the point size. (This controls the drawing size of both 3 text labels and marks (e.g. dots and arrowheads). 4Scale the current point size by the supplied ratio. :Note - as fonts can only be drawn at integral sizes this > operation is not exact - for instance scaling 15pt by (1%2)  results in 7pt. ?Set the point size (font and mark size) to double the current  size. <Set the point size to half the current size, note the point 7 size also controls the size of dots, arrowsheads etc. :Note - as fonts can only be drawn at integral sizes this 9 operation is not exact - half size of 15pt type is 7pt.  : " x_sep * y_sep -> DrawingContextF  Note - this is in Em units. Set the text margin to (0,0). ?This produces a tight box around the text vertically measured A to the cap-height and descender. Therefore some characters may 9 extend outside the margin (e.g. accented capitals like  A-grave). +Set the text margin to (0.25 em, 0.25 em). )Set the text margin to (0.5 em, 0.5 em). )Set the text margin to (1.0 em, 1.0 em). Set the stroke colour. Set the fill colour. Set the text colour. :Set the stroke, fill and text colours to a single colour. )Swap the stroke colour and fill colours. 6Set the fill colour to use the current stroke colour. 6Set the stroke colour to use the current fill colour. 4Set the fill colour to use the current text colour. 6Set the stroke colour to use the current fill colour. 6Set the text colour to use the current stroke colour. 4Set the text colour to use the current fill colour. Normalize to zero if negative. "Set the connector source spacing. ;The spacing is used as a projection along the line formed 0 between connector points making the connection looser if  required. >The default value is 0. Negative values are not allowed, they  are normalized to 0. 'Set the connector destination spacing. ;The spacing is used as a projection along the line formed 0 between connector points making the connection looser if  required. >The default value is 0. Negative values are not allowed, they  are normalized to 0. :Set the connector source and destination spacings to the  same length. !Set the connector source offset. ,The offset is used to shift the start point upwards 8 perpendicular to its true origin (negative values are < downwards). This can be used to draw a connector with two  parallel lines, for example. ?Upwards and downwards in this description are dependent on the A direction of the line, of course. Generally the documentations = consider lines are left-to-right unless specifically noted. &Set the connector destination offset. See  for an explanation. Set the connector arc angle. %Set the connector source arm length. *Set the connector destination arm length. ;Set the connector source and destination arms to the same  length. Set the connector loop size.  Set the connector box halfsize. 888GHC 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. 3This type is essentially internal to Wumpus-Basic. A wrapped version of  from Wumpus-Core that  supports Monoid. 3This type is essentially internal to Wumpus-Basic. Map Extract the internal list of  from a . Form a  from a . GHC highly unstablestephen.tetley@gmail.com'Decorate an object ?oliterate - drops the graphic from the first object replacing & it with the graphic from the second. Type specialized version of . Type specialized version of . Unit u is a phantom. 4For the moment the second fun is type preserving... 7Convert a PrimW where the answer is some functor type  parametrized by the unit. 7Convert a PrimW where the answer is oblivious to unit. #Constructor for Primtive graphics. Clip an Image. Having empty at the specific  type is useful. 0Note - the kind of f allows fo unit annotation. 1Replace the answer produced by a graphic object. Do not export... Should a decoration "lift"& a query (Pure) to an image (PrimW)? Currently I don't think it should. GHC highly unstablestephen.tetley@gmail.comConcatenation with movement - the second object is moved  next to the first.  / hconcat is equivalent to @(<>)@ in WL-PPrint.  (infixr 6) 0 vconcat is equivalent to @(<$>)@ in WL_PPrint.  (infixr 5) Minimal defintion is  ,  is usually   flip superior.   `superior` (infixr 6)  `anterior` (infixr 6)    ,Horizontally concatenate a list of objects.  Note - the first argument is an  alternative - this is drawn 2 if the list is empty, otherwise it is not drawn.  *Vertically concatenate a list of objects.  Note - the first argument is an  alternative - this is drawn 2 if the list is empty, otherwise it is not drawn.                  GHC highly unstablestephen.tetley@gmail.comType specialized version of . Type specialized version of . =ConnectorImage - function from DrawingContext and start and  end points to a polymorphic answer and a graphic  primitive. " zero-apply" a Connector. Use this to convert  or   with Functor answer. Use this to convert  with unit-less answer.  Having empty at the specific  type is useful.    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 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. ## :  Vec2 -> PointDisplace   Alias for .+^ from Data.AffineSpace. $$ :  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. 'Angular version of  dispDirection. =The displacement direction is with respect to implicit angle  of inclination, so:  up == perpendicular ! down == perdendicular . negate  left == parallel . negate  right == parallel (Angular version of  dispCardinal. =The displacement direction is with respect to implicit angle  of inclination, so:  north == perpendicular  east == parallel ! south == perdendicular . negate  etc. )*+,-./012345678!"#$%&'()*+,-./012345678"!#$%&'()*+,-./012345678!"#$%&'()*+,-./012345678GHC highly unstablestephen.tetley@gmail.com9:Type specialized version of <. ;Type specialized version of =. <= LocThetaImage# - function from start point and ! DrawingContext to a polymorphic answer and a graphic   primitive (PrimW). >?@ABCD" zero-apply" a LocQuery. Use this to convert < or = with Functor  answer. Use this to convert = with unit-less answer. EHaving empty at the specific = type is useful. FG Downcast a =* function by applying it to the supplied  point, making an . HIJKThis is analogue to  replicate in the Prelude. LM9:;<=>?@ABCDEFGHIJKLM=<;:9>?@ABCDEFGHIJKLM9:;<=>?@ABCDEFGHIJKLMGHC highly unstablestephen.tetley@gmail.comNOAdvance 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. P9Advance 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. Q7Extract 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. R6Extract the verticall component of an advance vector. SRun an O turning it into an =. TT : - loc_context_function * graphic -> AdvObject   Build an O from a context function (CF) that 0 generates the answer displacement vector and a <  that draws the O. UemptyAdvObjectAU :  AdvObject  Build an empty O. The U is treated as a null primitive by   Wumpus-Core2 and is not drawn, the answer vector generated is  the zero vector (V2 0 0). VDesign note - this is rather uncool. $Here it would be nicer if PrimW didn't cover two cases - ? queries (Pure) and images (PrimW). However implementing this 9 would double the amount of code and then require extra 5 bind-like combinators to promote queries to images. This is simulated in appendW# by dropping any graphic embedded A in a PrimW (everything should be a query anyway). But it would @ be nicer in this particular case, if the type system enforced  this. Primitive combination. <Move second object by the advance vector of the first. Sum  both advance vectors. W8Draw the first AdvObject and use the advance vector to  displace the second AdvObject. 5The final answer is the sum of both advance vectors. X(Concatenate the list of AdvObjects with W. Y7Combine the AdvObjects using the answer vector of the A first object plus the separator to move the start of the second  object. ZList version of  nextSpace. [Repeat the AdvObject n times, moving each time with  W. \:Concatenate the list of AdvObjects, going next and adding  the separator at each step. ];Render the supplied AdvObject, but swap the result advance @ for the supplied vector. This function has behaviour analogue  to fill in the  wl-pprint library. NOPQRSTUVWXYZ[\]PQRONSTUVWXYZ[\]NOPQRSTUVWXYZ[\]GHC highly unstablestephen.tetley@gmail.com^_Chain algorithm. Linear simply iterates points. Prefix runs the left chain n times then runs the right - chain from the end point of the left chain. -Note the tail of of result list is infinite. :As any prefixes will be generated fully. This potentially  produces a  space bubble where a long prefix has to be > generated without the streaming of lazy evaluation. However, < chains that are long enough to cause this problem will be / problematic for a PostScript or SVG renderer. In short - don't make long chains. :Take n elements - also return the last of element in the 9 tuple so it can be accessed without a second traversal. Note (n > 0) `Returns the end point... aReturns no answer, just a <. bcdefghiOuter and inner steppers. j ^_`abcdefghij _^`abcdefghij ^_`abcdefghijGHC highly unstablestephen.tetley@gmail.comklType specialized version of n. mType specialized version of o. noo. - function from start point, inclination and ! DrawingContext to a polymorphic answer and a graphic   primitive (PrimW). pqrstuv" zero-apply" a LocThetaQuery. Use this to convert LocThetaThetaGraphic or LocThetaThetaImage  with Functor answer. Use this to convert o with unit-less answer. wHaving empty at the specific o type is useful. x Downcast a o! function by applying it to the  supplied angle, making a =. yklmnopqrstuvwxynolmkpqrstuvwxyklmnopqrstuvwxyGHC highly unstablestephen.tetley@gmail.com%z9Unit parametric version of KerningChar from Wumpus-Core. {{ :  [next_vector] -> LocImage PrimPath  Create a path query - i.e. a functional type  from Point to PrimPath. This is the analogue to  vectorPath in  Wumpus-Core , but the  result is produced within the DrawingContext. || :  (Point ~> PrimPath)  Create an empty path query - i.e. a functional type  from Point to PrimPath. This is the analogue to  emptyPath in  Wumpus-Core , but the  result is produced within the DrawingContext. }} :  (Point ~> PrimPath)  >Create a PrimPath made of straight line segments joining the  supplied points. This is the analogue to  in  Wumpus-Core, but  it is polymorphic on unit. ~~ :  (Point ~> PrimPath)  2Create a path made of curve segments joining the  supplied points. This is the analogue to  in  Wumpus-Core, but  it is polymorphic on unit.  :  path -> Graphic  This is the analogue to the  function in   Wumpus-Core3, but the drawing properties (colour, line width, # etc.) are taken from the implicit DrawingContext.  :  DrawStyle * path -> Graphic  7Draw a closed path according to the supplied DrawStyle " ( fill | stroke | fill_stroke).  :  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 n - 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 n - 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.  : ' 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.  :  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.  curveLine : ! 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.  : & start_point * end_point -> Connector  Create a straight line , the start and end point  are supplied implicitly. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext. Helper for circle drawing.  : " DrawStyle * radius -> LocGraphic  Create a circle < - the implicit point is 7 center. The circle is drawn with four Bezier curves. /The respective line or fill properties for the 1 are  taken from the implicit DrawingContext. Helper for ellipse drawing. Helper for ellipse drawing. strokedEllipse : # 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 -> LocGraphic  Create a bordered ellipse n - 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. strokedRectangle :  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.  :  radius -> LocGraphic  Create a 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 fill or stroke properties for the respective DrawStyle are  taken from the implicit DrawingContext. strokeEllipseDisk : # 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  strokedEllipse instead. =The line properties (colour, pen thickness, etc.) are taken  from the implicit DrawingContext. z{|}~{|}~zz{|}~GHC highly unstablestephen.tetley@gmail.com  :  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. Build an empty < returning a bounding box. 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. Build an empty n returning a bounding box. The  is treated as a  null primitive by  Wumpus-Core and is not drawn, although : it does generate the minimum bounding box with both the B bottom-left and upper-right corners at the implicit start point 6Draw a BoundedGraphic, illustrating the bounding box. 9Draw a BoundedLocGraphic, illustrating the bounding box. >Draw a BoundedLocThetaGraphic, illustrating the bounding box.    GHC highly unstablestephen.tetley@gmail.com64Utility datatype representing orientation within a  rectangular frame*. RectPos 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! ?Datatype enumerating the addressable positions of a rectangle  that can be derived for a  PosObject. >Concatenation here essentially turns both Orientation objects  into  center-form# then finds the maximum rectangle. 7Find the half-width and half-height of an Orientation. Essentially this is  center-form of an Orientation, but  in  center-form there is duplication:   xminor == xmajor  yminor == ymajor ,So instead, the result type is just a pair. The vector from a  to the start point. 2Calculate the bounding box formed by locating the   at the supplied point. Second Orientation is moved  to the right of the first along  the spine i.e the baseline. Second Orientation is moved below the first along the spine @ i.e. the vertical point between the left minor and right major * (not the same as the horizontal center). xmin and xmaj same as left. xmin same as left. xmin and ymaj same as left. 5Align second below - xmin and ymaj are same as left. (Align second below - ymaj same as left. 5Align second below - xmaj and ymaj are same as left. Move second right. Move second below. 000 GHC highly unstablestephen.tetley@gmail.com>Version of PosObject specialized to Double for the unit type. A positionable "Object" that is drawn as a  BoundedLocGraphic. *Helper for PosObject - a LocImage that is  pre-applied to  the DrawingContext. ?This is somewhat contrived, but the orientation and the result ? graphic from a PosImage have to be generated within the same  DrawingContext.   Version of  that produces a  = that returns a bounding box. The / is run with only rect-address as an explicit B argument (start-point is implicit). The corresponding answer is  an  arity one2 Graphic that needs drawing with the start-point.  : % object_pos * loc_image -> PosObject   Create a  from an  describing how it / is orientated within a border rectangle and a = that  draws it.  This is the primary) constructor for PosObjects. Because the > PosObject type is considered as a specialized object it does ? not have the range of functions of LocImage or LocThetaImage.  :  PosObject  Build an empty PosGraphicObject. #Apply a DrawingContext update to a . Extend the orientation.  Illustrate a  by super-imposing its . This turns the  into a = drawn at the locus  of the PosObject.       GHC unstablestephen.tetley@gmail.com!9Collect elementary graphics as part of a larger drawing. 'TraceM works much like a writer monad. <Run the drawing returning only the output it produces, drop * any answer from the monadic computation. =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). Unsafe promotion of HPrim to Picture. 3If the HPrim is empty, a run-time error is thrown. Safe promotion of HPrim to (Maybe Picture). If the HPrim is empty, then Nothing is returned. Unsafe 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. 2Draw a Graphic taking the drawing style from the  drawing context. This function is the  forgetful version of .  Commonly, it is used to draw  objects which  have no answer. 1Draw 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. ;Draw a LocImage at the supplied Anchor taking the drawing  style from the drawing context. This function is the  forgetful version of .  Commonly, it is used to draw < objects which  have no answer. :Draw a LocImage at the supplied Point 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. >Draw a ConnectorGraphic with the supplied Anchors taking the  drawing style from the drawing context. This function is the  forgetful version of .  Commonly, it is used to draw  objects which  have no answer. ;Draw a ConnectorImage with the supplied Points 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. 8Draw the object with the supplied grid coordinate. The - actual position is scaled according to the  snap_grid_factors in the drawing context. This function is the  forgetful version of .  Commonly, it is used to draw < objects which  have no answer. 8Draw the object with the supplied grid coordinate. The - actual position is scaled according to the  snap_grid_factors in the drawing context. <Draw a connector between two objects. The projection of the ? connector line is drawn on the line from center to center of @ the objects, the actual start and end points of the drawn line > are the radial points on the objects borders that cross the  projected line. This function is the  forgetful version of .  Commonly, it is used to draw < objects which  have no answer. <Draw a connector between two objects. The projection of the ? connector line is drawn on the line from center to center of @ the objects, the actual start and end points of the drawn line > are the radial points on the objects borders that cross the  projected line.  GHC unstablestephen.tetley@gmail.comA  Contextual Picture.  . CtxPicture = DrawingContext -> Maybe Picture This type corresponds to the  type in Wumpus-Core, but  it is embedded with a lk (for font properties, @ fill colour etc.). The DrawingContext is embedded so that font  metrics - loaded in IO& can be passed into the pure world of  .  Internally a context picture is a function from  lk to (Maybe Picture). The Maybe represents > that it is possible to construct empty Pictures, even though   Wumpus-Core0 cannot render them. Just as the DrawingContext > pushes font-metrics from the IO to the pure world, the Maybe ? lifts the problem of unrenderable Pictures into the API where , client code must deal with it explicitly. ?(In practice, it is very unlikely a program will create empty  pictures and runCtxPictureU can be used without worry). &Note - pictures are fixed to the unit Double (representing A PostScript points). Pictures are intentionally unsophisticated, ? any fine grained control of units should be delegated to the A elements that build the picture (Graphics, LocGraphics, etc.).  : , drawing_ctx * ctx_picture -> Maybe Picture  Run a  with the supplied lk  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.  : & drawing_ctx * ctx_picture -> Picture  Unsafe version of . ;This function throws a runtime error when supplied with an  empty CtxPicture.  :  trace_drawing -> CtxPicture   Transform a  into a .  : 2 scalar_unit_value * trace_drawing -> CtxPicture   Variant of & with a phantom first argument - the ) phantom identifies the unit type of the  . It is % not scurtinized at the value level.  : # trafo * ctx_picture -> CtxPicture  /Apply a picture transformation function to the   warpped in a . Draw a, move b) so its center is at the same center as  a, b) is drawn over underneath in the zorder.  a `cxpUniteCenter` b   a `cxpRight` b *Horizontal composition - position picture b to the right of  picture a.   a `cxpBelow` b (Vertical composition - position picture b down from picture  a. *Center the picture at the supplied point.   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. !  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. #  cxpAlignSpaceH align sep a b Spacing version of ! - move b to the right of a  separated by sep units, align b according to align. $  cxpAlignSpaceV align sep a b !Spacing version of alignV - move b below a  separated by sep units, align b according to align. %  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. &"Avoid initial mempty for mconcat. +GHC highly unstablestephen.tetley@gmail.com  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>'( Promote an IO action into the the  FontLoadIO monad. This function is equivalent to 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> :   path_to_afm_fonts * [font_name] -> IO FontLoadResult  "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.  :  3 path_to_afm_fonts * font_def -> IO FontLoadResult  Load a single AFM font. >Note - if the font fails to load a message is written to the  log and monospaced fallback metrics are used. -.>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 FontLoadResult  "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.  :  3 path_to_gs_fonts * font_name -> IO FontLoadResult  !Load a single GhostScript font. >Note - if the font fails to load a message is written to the  log and monospaced fallback metrics are used. /0)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. $GHC highly unstablestephen.tetley@gmail.com 4A FontLoader is an action from a list of fonts to a   returned in IO.  Fonts are supplied in a list of Either FontDef FontFamily, > this is a little cumbersome but it allows the loader to load  individual fonts and /' or a whole families with a single API  call. 16Environment variable pointing to the GhostScript font  directory.  WUMPUS_GS_FONT_DIR 2:Environment variable pointing to the diretory containing  the Adobe Font Metrics files.  WUMPUS_AFM_FONT_DIR   /Tries to find the GhostScript metrics first... 2Runs the IO action on the loader if it finds one. ,Either of one of the environment variables  WUMPUS_AFM_FONT_DIR or WUMPUS_GS_FONT_DIR must be defined + and point to their respective directory. 34          %GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>   2Vertices are from the center to (bl, br, tr, tl).  #base_width * height -> (BL,BR,Apex)2Vertices are from the centeriod to (bl, br,apex).   height -> (BL,BR,Apex)"Point is centroid (not incenter).   side_length -> (BL,BR,Apex)         &GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>+A Strict cubic Bezier curve. Line in equational form, i.e. Ax + By + C = 0.  !"#)Infinite line represented by two points. $%&02x2 matrix, considered to be in row-major form.  (M2'2 a b  c d) '()*5+#Construct the identity 2x2 matrix:  (M2'2 1 0  0 1 ) ,Determinant of a 2x2 matrix. -Transpose a 2x2 matrix. .. :  point * ang -> Line  :Make an infinite line passing through the supplied point  inclined by ang. // : ! point1 * point2 -> LineEquation  <Construct a line in equational form bisecting the supplied  points. 00 :  x * line_equation -> Point  1Calculate the point on the line for the supplied x value. 11 :  y * line_equation -> Point  1Calculate the point on the line for the supplied y value. 22 :  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. 33 : ) half_width * half_height -> [LineSegment]  *Compute the line segments of a rectangle. 44 :  [point] -> [LineSegment]  5Build the line segments of a polygon fome a list of  its vertices. 55 : ( 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. 6 Jens Gravesen'$s bezier arc-length approximation. =Note this implementation is parametrized on error tolerance. 76Length of the tree lines spanning the control points. 8/Length of the cord - start point to end point. 6"Curve subdivision via de Casteljau' s algorithm. 72subdivide with an affine weight along the line... 988 : 5 apex_angle * radius * inclination * 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 99 : 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. & !"#$%&'()*+,-./0123456789:;<&()*&'%+,-#$. !"/0123456789:;<& !" !"#$$%&''()*+,-./0123456789:;<'GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>:;=>=>=>=>(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 either 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. AA : $ 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. <=Check 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 exported. >?B@Is 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. CC :: & 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. A9The tolerance on Radian equality should be acceptable... ?@ABC?@ABC?@ABC)GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>D A vector chain building a path. 4The vectors are relative to the predecessor, so the  rendering of a D iterates the start point. :A polygon PathAlg should have steps for all sides of the : polygon with the end point generated by the last vector # coinciding with thet start point. BCDEFGEFGH'Create a PathAlg from the vertex list. >When the PathAlg is run the supplied point will be the start  of the path. I9Create a PathAlg from the vector list - the first vector  displaces the  start point" the subsequent vectors displace  the  current tip*. Figuratively, this is rather like Logo  turtle drawing. 3When the PathAlg is run, the supplied point is the locus of 8 the path and it does not form part of the path proper. +This constructor is typically used to make  shape paths where A the supplied point is the center and the generated path is the  border. J=Note this creates a path where the first vector represents a  moveto), then the subsequence vectors represent linetos. <Create a PathAlg from the vector list - each vector in the 9 input list iterates to the start point rather then the  cumulative tip. 3When the PathAlg is run, the supplied point is the locus of 8 the path and it does not form part of the path proper. Like I), this constructor is typically used to  make  shape paths(. Some shapes are easier to express as 3 iterated displacements of the center rather than  turtle drawing. KImplicit start point is center, the genearated moves are ' counter-clockwise so the move-list is 0 [ moveto_bl, moveto_br, moveto_tr, moveto_tl ] LImplicit start point is  bottom-left, subsequent moves are ( counter-clockwise so the move-list is: 0 [ moveto_br, moveto_tr, moveto_tl, moveto_bl ] MM : % half_width * half_height -> PathAlg  NN :  base_width * height -> PathAlg  'Start point is centtroid not incenter. OO :  num_points * radius -> PathAlg  PP : & radius * angle1 * angle2 -> PathAlg  H1Helper - generate four vectors building a minor (< 90 deg)  arc. @The first vec is from center - for cumulative arcs this should  only taken once. QIHelper - diff 7Note diff relies on the pointlist cycling the endpoint   [p0, ..., p0] 2This is how Wumpus-Core generates Bezier circles. J6Helper - divide an arc into quadrants plus remainder. R # width * height * bottom_left_angleS  base_width * top_width * heightDEFGHIJKLMNOPQRSDEFGHIJKLMNOPQRSDEFGHIJKLMNOPQRS*GHChighly unstable)Stephen Tetley <stephen.tetley@gmail.com>&TA Quadrant algorithm. UVWXYZ[\]^_`` :  ang -> Quadrant  Get the quadrant of an angle. KK :  ang -> Radian  7Modulo an angle so it lies in quadrant I (north east)   by reflection - thats to say:  / If the angle is in QI the result is identity.  : If the angle is in QII it is reflected about the Y-axis.   e.g. 170deg becomes 10deg.  : If the angle is in QIII it is reflected about both axes.   e.g. 190deg becomes 10deg. : If the angle is in QIV it is reflected about the X-axis.   e.g. 350deg becomes 10deg. aL$Reuse a QI algorithm to work in QII provided it works  under reflection. M%Reuse a QI algorithm to work in QIII provided it works  under reflection. N$Reuse a QI algorithm to work in QIV provided it works  under reflection. O8Negate a vector in X - aka reflect it about the Y-axis. P8Negate a vector in Y - aka reflect it about the X-axis. Q=Negate a vector in X and Y - aka reflect it about both axes. RBuilder for the usual case of Quadrant algorithm where A each quadrant is calculated in QI then the answer is reflected  to the respective quadrant. 'Calulating for QI is usually easier... bl :  dx * dy -> RadialIntersect  ,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. cc :  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. dd : " dx * dy * ang -> RadialIntersect  ,Find where a line from (0,0) with elevation ang intersects  a quadrilateral in H acute form in QI.  + ang must be in the @range 0 < ang <= 90@.  ; dx (top width @bc@) and dy (height @ab) must be positive.  Horizontal acute quadrilateral (H because one of the two  "sides of interest" is horizontal, acute because the  angle of interest bcd is acute:   b---*----c  | /  | %  | /  a----d  STee : " dx * dy * ang -> RadialIntersect  ,Find where a line from (0,0) with elevation ang intersects  a quadrilateral in H obtus form in QI.  + ang must be in the @range 0 < ang <= 90@.  ; dx (top width @bc@) and dy (height @ab) must be positive. H Obtus quadrilateral (H because one of the two  "sides of interest" is horizontal, obtus because the  angle interest bcd is obtuse:   b---*----c  | \  | %  | \  a------------d  ff :  width * height -> QuadrantAlg  @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. gg :  width * height -> QuadrantAlg  @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. hh : $ base_width * height -> QuadrantAlg  @Find where a radial line extended from (0,0) with the elevation  ang3 intersects with an enclosing isosceles triangle.  Note the center/ of the triangle (0,0) is the centroid not the  incenter. ?Internally the calculation is made in quadrant I (north east), > symmetry is used to translate result to the other quadrants. ii : ' 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. jj : ' 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. kk : # 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. ll :  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. mm : + 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. UtraingleLeftSide : - 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. nn : . top_width * height * top_right_ang -> Length  !Find the length of the line C_D:   A B  -----  | \  | \  -------  C D  A B  -------  | /  | /  -----  C D TUVWXYZ[\]^_`abcdefghijklmn[_^]\`ZTUVWXYabcdegfhijklmnTUVWXYUVWXYZ[_^]\\]^_`abcdefghijklmn,GHC highly unstablestephen.tetley@gmail.comc   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnV-./0123456789:;<=>?@ABCDEFGHIJKLM<NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~W^Y\                                     ! " # $ % & ' ( ) * + , - . / 0 1 Y X \ 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W W X Y Z [ \ ] ^ _ ` a b c d e f g h ijklmnopqrstuvvwxyz{|}~     QSUT !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmenopqrstuvwxyz{|}~        !! ! ! ! ! !!!!!""##$$$$$%%%%% %!%"%#%$%%%&&'&(&(&)&*&*&+&,&,&-&.&/&0&0&1&2&3&4&5&6&7&8&9&:&;&<&=&>&?&@&A&B&C&D&E&F&G&H'I'J(K(L(M(N(O)P)Q)R)S)T)U)V)W)X)Y)Z)[)\)])^)_*`*`*a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*yz{|}~0z}         jklm%)KOa|                       !!!"!>!#!$!%"&"'#(#)$*$+$,$-&.&/&0&1&2'3'4(5(6(7(8(9(:)P);)<)=)>)?)@)A)B*C*D*E*F*G*H*I*J*K*L*MNwumpus-basic-0.18.0Wumpus.Basic.VersionNumberWumpus.Basic.Utils.JoinList$Wumpus.Basic.Utils.FormatCombinators$Wumpus.Basic.Utils.ParserCombinatorsWumpus.Basic.Utils.TokenParsersWumpus.Basic.Utils.HList#Wumpus.Basic.Kernel.Objects.Anchors$Wumpus.Basic.Kernel.Base.FontSupport(Wumpus.Basic.System.FontLoader.Datatypes,Wumpus.Basic.System.FontLoader.AfmParserBase.Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser*Wumpus.Basic.System.FontLoader.AfmV2Parser!Wumpus.Basic.Kernel.Base.BaseDefsWumpus.Basic.Kernel.Base.Units'Wumpus.Basic.Kernel.Base.DrawingContext Wumpus.Basic.Kernel.Base.QueryDC!Wumpus.Basic.Kernel.Base.UpdateDC)Wumpus.Basic.Kernel.Base.WrappedPrimitive!Wumpus.Basic.Kernel.Objects.Basis"Wumpus.Basic.Kernel.Objects.Concat%Wumpus.Basic.Kernel.Objects.Connector(Wumpus.Basic.Kernel.Objects.Displacement$Wumpus.Basic.Kernel.Objects.LocImage%Wumpus.Basic.Kernel.Objects.AdvObject!Wumpus.Basic.Kernel.Objects.Chain)Wumpus.Basic.Kernel.Objects.LocThetaImage-Wumpus.Basic.Kernel.Objects.DrawingPrimitives#Wumpus.Basic.Kernel.Objects.Bounded'Wumpus.Basic.Kernel.Objects.Orientation%Wumpus.Basic.Kernel.Objects.PosObject(Wumpus.Basic.Kernel.Objects.TraceDrawing&Wumpus.Basic.Kernel.Objects.CtxPicture,Wumpus.Basic.System.FontLoader.FontLoadMonad*Wumpus.Basic.System.FontLoader.AfmTopLevel)Wumpus.Basic.System.FontLoader.GSTopLevelWumpus.Basic.System.FontLoaderWumpus.Basic.Geometry.VerticesWumpus.Basic.Geometry.Base Wumpus.Basic.Geometry.Illustrate"Wumpus.Basic.Geometry.IntersectionWumpus.Basic.Geometry.PathsWumpus.Basic.Geometry.QuadrantWumpus.Basic.KernelWumpus.Basic.Geometrywumpus_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 whiteSpaceoctBaseoctHaskhexBasenaturalHemptyHwrapHconsHsnocHappendHunfoldrHveloHconcatHtoListH prefixListH fromListHSideMidpointAnchor sideMidpointBottomCornerAnchorbottomLeftCornerbottomRightCornerTopCornerAnchor topLeftCornertopRightCorner RadialAnchor radialAnchorCardinalAnchor2 northeast southeast southwest northwestCardinalAnchornorthsoutheastwest ApexAnchorapex CenterAnchorcenterAnchor projectAnchorradialConnectorPointsFontLoadResultloaded_font_table loader_errors FontLoadLog FontLoadMsg FontTable FontMetricsget_bounding_box get_cw_tableget_cap_height get_descenderCharWidthLookup FontFamily ff_regularff_bold ff_italicff_bold_italicFontDef font_def_face gs_file_name afm_file_name CodePointFontName regularWeight boldWeight italicWeightboldItalicWeightemptyFontTable fontLoadMsgprintLoadErrors 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 PSCharCodebuildMetricsOps afmFileParserrunQuery textQuery getFontBBoxgetEncodingScheme getCapHeightcharBBoxmetric keyStringPair versionNumberstartCharMetricskeyName newlineOrEOF uptoNewlinenamename1seminumbercinthexIntoctIntsymbolafmV4Dot1Parser afmV2Parser DirectionRIGHTLEFTDOWNUPCardinal NORTH_WESTWEST SOUTH_WESTSOUTH SOUTH_EASTEAST NORTH_EASTNORTHVAlignVRightVCenterVLeftHAlignHBottomHCenterHTopZDecoANTERIORSUPERIOR DrawStyle FILL_STROKESTROKEFILL InterpretUnit normalizedinterp ScalarUnit fromPsPoint toPsPointUNilBimapbimapbimapLbimapROPlusoplusMonUnitoconcat altconcatreplaceLreplaceRdinterpF normalizeF uconvert1 uconvertF intraMapPointintraMapFunctorvsumEnEmPica Centimetercmdcmpicadpica DrawingCtxMaskDCasksDClocalizeConnectorPropsdc_conn_src_spacedc_conn_dst_spacedc_conn_src_offsetdc_conn_dst_offsetdc_conn_arc_angdc_conn_src_armdc_conn_dst_armdc_conn_loop_sizedc_conn_box_halfsize TextMargin text_margin_x text_margin_yDrawingContextFDrawingContextdc_font_metrics_tabledc_font_load_logdc_fallback_metrics dc_font_face dc_font_sizedc_snap_grid_factorsdc_stroke_propsdc_stroke_colourdc_fill_colourdc_text_colourdc_line_spacing_factordc_text_margindc_connector_propsstandardContextmetricsContext addFontTablesreset_drawing_propertiesreset_drawing_metricswithFontMetrics normalizeCtx normalizeCtxF dinterpCtx dinterpCtxF uconvertCtx1 uconvertCtxF pointSize strokeAttrfillAttr borderedAttrtextAttrpositionsnapmove textMargin getLineWidth getFontAttr getFontSize getFontFace getTextColour textlineSpaceglyphBoundingBox capHeight descender verticalSpan cwLookupTableconnectorSrcSpaceconnectorDstSpaceconnectorSrcOffsetconnectorDstOffsetconnectorArcAngleconnectorSrcArmconnectorDstArmconnectorLoopSizeconnectorBoxHalfSizesnap_grid_factorsset_line_width line_default line_thin line_thickline_ultra_thickrelative_line_width cap_defaultcap_butt cap_round cap_square join_default join_miter join_round join_bevelset_dash_pattern solid_line dotted_line packed_dotted loose_dotted dashed_line packed_dashed loose_dashed font_attrset_font set_font_sizescale_point_sizedouble_point_sizehalf_point_size text_margintext_margin_nonetext_margin_tighttext_margin_defaulttext_margin_loose stroke_colour fill_colour text_colour single_colour swap_coloursfill_use_stroke_colourstroke_use_fill_colourfill_use_text_colourstroke_use_text_colourtext_use_stroke_colourtext_use_fill_colour source_space dest_spaceuniform_conn_space source_offset dest_offsetconn_arc_anglesource_arm_len dest_arm_lenuniform_arm_lenconn_loop_sizeconn_box_halfsizeHPrimCatPrimprim1cpmap hprimToListsingleHDecoratedecorate elaborate obliterate hyperlinkUConvertuconvFuconvZQueryDGraphicDImageGraphicImagePrimW primAnswerrunImagezapQuery primGraphic clipImage uconvImageF uconvImageZ emptyImageboth ignoreAns replaceAns AlignSpace halignSpace valignSpaceAlignhalignvalignCatSpacehspacevspaceConcathconcatZConcatanteriorsuperiorcatvsepalignRow alignColumn alignRowSepalignColumnSepConnectorQueryDConnectorGraphicDConnectorImageConnectorGraphicConnectorImagerunConnectorImagerunConnectorQueryconnect promoteConn applyConn qpromoteConn qapplyConnzapConnectorQueryemptyConnectorImageThetaPointDisplace PointDisplacedisplace dispParalleldispPerpendicular dispOrthodispDirectionThetadispCardinalThetago_upgo_downgo_leftgo_rightgo_northgo_southgo_eastgo_west go_north_east go_north_west go_south_east go_south_west go_up_left go_up_right go_down_left go_down_rightLocQuery DLocGraphic DLocImage LocGraphicLocImage runLocImage runLocQuery promoteLocapplyLoc qpromoteLoc qapplyLoc zapLocQuery emptyLocImage moveStartatdistribdistribHdistribV duplicate duplicateH duplicateV DAdvObject AdvObject AdvanceVecadvanceHadvanceV runAdvObject makeAdvObjectemptyAdvObjectblankAdvObjectadvanceadvancesadvspace evenspace advrepeatadvfillIterationSchemeChainAlgchainchain_ linearChain prefixChainiterationScheme chainIteratechainHchainV tableRight tableDown radialChain LocThetaQueryDLocThetaGraphicDLocThetaImageLocThetaGraphic LocThetaImagerunLocThetaImagerunLocThetaQuerypromoteLocTheta applyLocThetaqpromoteLocThetaqapplyLocThetazapLocThetaQueryemptyLocThetaImageincline atInclineKernCharlocPP emptyLocPPvertexPPcurvePP dcOpenPath dcClosedPath dcTextlabel dcRTextlabeldcEscapedlabeldcREscapedlabel hkernLine vkernLine straightLinelocStraightLine curvedLinestraightConnectordcCircle dcEllipse dcREllipse dcRectangledcDisk dcEllipseDiskBoundedLocThetaGraphicBoundedLocGraphicBoundedGraphiccenterOrthoBBoxemptyBoundedLocGraphicemptyBoundedLocThetaGraphicillustrateBoundedGraphicillustrateBoundedLocGraphic illustrateBoundedLocThetaGraphic bbrectangle Orientation or_x_minor or_x_major or_y_minor or_y_major RectAddressBLRBLCBLLSWSENWNEWWEESSNNCENTERorientationStartorientationBoundsextendOrientation extendOLeft extendORight extendODown extendOUppadHEven padXMinor padXMajorpadVEven padYMinor padYMajor spineRight spineBelow halignBottomO halignCenterO halignTopO valignLeftO valignCenterO valignRightO spinemoveH spinemoveVbinmoveHBottombinmoveHCenter binmoveHTop binmoveVLeftbinmoveVCenter binmoveVRight DPosObject PosObject runPosObject makePosObjectemptyPosObjectlocalPosObject decoPosObjectextendPosObjectmapOrientationillustratePosObjectDTraceDrawingT DTraceDrawing TraceDrawingT TraceDrawingTraceMtrace fontDeltarunTraceDrawingexecTraceDrawingevalTraceDrawingrunTraceDrawingTexecTraceDrawingTevalTraceDrawingTliftToPictureUliftToPictureMb mbPictureU evalQuerydrawdrawidrawldrawlidrawcdrawcinodenodeidrawrcdrawrci CtxPicture runCtxPicturerunCtxPictureU drawTracing udrawTracing mapCtxPicture uniteCenter centeredAt FontLoadIO runFontLoadIOevalFontLoadIO loadError tellLoadMsg promoteIO promoteEither runParserFLIO sequenceAllbuildAfmFontProps checkFontPathloadAfmFontMetrics loadAfmFont1loadGSFontMetrics loadGSFont1 FontLoaderafmLoaderByEnv gsLoaderByEnvsimpleFontLoaderdefault_font_loader_help Vertices4 Vertices3 Vertices2 runVertices2 runVertices3 runVertices4rectangleVerticesisoscelesTriangleVerticesequilateralTriangleVerticesparallelogramVerticesisoscelesTrapeziumVertices DBezierCurve BezierCurve DLineSegment LineSegment DLineEquation LineEquation line_eqn_A line_eqn_B line_eqn_CLine DMatrix2'2 Matrix2'2M2'2 quarter_pihalf_pitwo_pi identity2'2det2'2 transpose2'2 inclinedLine lineEquation pointViaX pointViaYpointLineDistancerectangleLineSegmentspolygonLineSegments bezierLength subdivide subdividetbezierArcPointsbezierMinorArc affineCombmidpoint lineAngleillustrateLineillustrateLineSegment interLineLineinterLinesegLineseginterLinesegLineinterCurveLine findIntersectPathAlgrunPathAlgPoint runPathAlgVecdrawVertexPathAlgpathStartIsStartpathStartIsLocuspathIterateLocusrectanglePathAlgblRectanglePathAlgdiamondPathAlgisoscelesTriPathAlgpolygonPathAlg arcPathAlg circlePathAlgparallelogramPathAlgisoscelesTrapeziumPathAlg QuadrantAlg calc_quad1 calc_quad2 calc_quad3 calc_quad4RadialIntersectQuadrantQUAD_SEQUAD_SWQUAD_NWQUAD_NEquadrantrunQuadrantAlg hypotenuseQI rectangleQIhquadrilAcuteQIhquadrilObtusQIdiamondQuadrantAlgrectangleQuadrantAlgisoscelesTriQuadrantAlgrectRadialVectordiamondRadialVectortriangleRadialVector triangleQIrightTrapezoidQIrightTrapeziumBaseWidthJoinOneEmpty joinfoldr joinfoldlIndentDoc1unDocindentSrunDocbaseGHC.Real fromIntegralpadr getParserFKSKyieldalt eagerMany eagerSome<:>Control.ApplicativesomegetLexemeParser lineComment spanCommentendLinegetFontLoadLog getFontTablewumpus-core-0.51.0Wumpus.Core.FontSizeAfmUnit globalInfo getDescenderfontBBoxlpcharMetricsV4Dot1 widthVector characterCode charMetricsV2getEngetEmgetPica getCentimeterghc-prim GHC.TypesDoubledefault_text_margindefault_connector_propsdefault_line_spacing wumpus_blackwumpus_light_graywumpus_courier glyphQuery connectorAsksupdateStrokeProps withFontSize setLineCap setLineJoinWumpus.Core.GraphicPropsSolid connectorUpdnormZerogetHPrimWumpus.Core.PictureInternal PrimitiveCat1CZerogetQuerygetImage bimapPrimW szconvPrimF szconvPrimZ getCatPrim decorateImageelaborateImageobliterateImagehyperlinkImagegetConnectorQuerygetConnectorImageuconvConnectorImageFuconvConnectorImageZ getLocQuery getLocImageuconvLocImageFuconvLocImageZ getAdvObjectAdvDrawappendWadvpluslistcatScheme scheme_start scheme_stepPXL1interpChainAlgrunInf takeAndLastemptyLoc scHorizontal scVertical scStepper scCirculargetLocThetaQuerygetLocThetaImageuconvLocThetaImageFuconvLocThetaImageZtextPrim strokePrimfillPrimfillStrokePrimtextLoc strokeLocfillLoc fillStrokeLoc textLocThetaWumpus.Core.PicturevertexPrimPathcurvedPrimPathostroke textlabel rtextlabel escapedlabel rescapedlabel uconvKernChar hkernlabel vkernlabel circlePath ellipsePath rellipsePath rectanglePathconcatOrientation halfDistsupDowndownUp leftRight rightLeft getPosObjectPosDrawpoconcatillustrateOrientation genMoveAlign genMoveSepH genMoveSepVgetTraceDrawingTgetTraceDrawing fontDeltaMonfontDeltaTransPicture getCtxPictureleftEdge rightEdge bottomEdgetopEdge combineP2moveSndcxpRightcxpBelow cxpRightSep cxpDownSep cxpAlignH cxpAlignVcxpAlignSpaceHcxpAlignSpaceV$fOPlusCtxPicture$fMonoidCtxPicture getFontLoadIOextractCapHeightextractDescenderextractFontBBoxafmLoadFontMetricsafm_mono_defaults_4_1gsLoadFontMetricsghostscript_mono_defaults_8_54wumpus_gs_font_dirwumpus_afm_font_dir envLookupfontListlift2Matrix2'2gravesenLengthctrlPolyLength cordLengthkappaemlineenDotmbCheck withinPointspvenvecut quadrantCheckpath_alg_schemepath_alg_steps PathAlgSchemeSTART_IS_LOCUSSTART_IS_STARTminorArcQuadVecdiffarcdivreflectionModuloQIreflectCalcQ2ToQ1reflectCalcQ3ToQ1reflectCalcQ4ToQ1negateXnegateYnegateXYmakeReflectionQuadrantAlg bisecting_dc bisectingHToptriangleLeftSide