/*****************************************************************************\
*                           Systems Research Group                            *
*******************************************************************************


   #####     ####    ##    ##   ######   ##    ##  ##        ########  #######  
  #######   ######   ###   ##  ########  ###   ##  ##        ########  ######## 
 ##        ##    ##  ####  ##  ##    ##  ####  ##  ##           ##     ##    ## 
 ##        ########  ## ## ##  ##    ##  ## ## ##  ##           ##     #######  
 ##        ##    ##  ##  ####  ##    ##  ##  ####  ##           ##     ##    ## 
 ##        ##    ##  ##  ####  ##    ##  ##  ####  ##           ##     ##    ## 
  #######  ##    ##  ##   ###  ########  ##   ###  ########  ########  ######## 
   #####   ##    ##  ##    ##   ######   ##    ##  ########  ########  #######  


*******************************************************************************
*   I. D. Wilson           Last Modified   -   IDW   -   18/09/83             *
\*****************************************************************************/



SECTION "CANONLIB"


GET "LIBHDR"
GET "bcpl.canonhdr"


LET canon.open( resolution )  BE
$(
//  Initialise the package.  The resolution given to us is:
//
//      resolution.half      :   120 x 120 bits per inch
//      resolution.full      :   240 x 240 bits per inch

    bitbuffer     :=  0
    bitcount      :=  0

    setresolution( resolution )

    canon.origin( 0, 0 )
    canon.moveto( 0, 0 )
    canon.orientation( orientation.up )

    canon.heightfactor( 1 )
    canon.widthfactor( 1 )

    initchars()

    startplot( resolution )
$)



AND setresolution( resolution )  BE
$(
//  Set the paper size, depending on whether this is full or half scale
//  resoltion.

    resolution.x  :=  maxbits.x
    resolution.y  :=  maxbits.y

    IF  resolution  =  resolution.full  THEN
    $(
        resolution.x  :=  resolution.x * 2
        resolution.y  :=  resolution.y * 2
    $)
$)



AND canon.origin( x, y )  BE
$(
//  Set the origin for plotter space to be "x, y"

    origin.x  :=  x
    origin.y  :=  y
$)



AND canon.moveto( x, y )  BE
$(
//  Move to a specific positon on the page.  This does nothing to the
//  output streams, but just resets out internal pointers into the
//  virtual page.

    xpos  :=  origin.x + x
    ypos  :=  origin.y + y
$)



AND canon.orientation( o )  BE  orientation  :=  o



AND canon.moveby( x, y )  BE
$(
//  Move the pen relative to the current pen position.

    xpos  :=  xpos + x
    ypos  :=  ypos + y
$)



AND canon.hline( length )  BE
$(
//  Draw a horizontal line.  The line length may be negative indicating that
//  the line must be drawn in the negative direction.  Whatever, we must leave
//  the virtual pen where the line finishes.

    LET n.xpos  =  xpos + length
    LET n.ypos  =  ypos

    drawline( xpos, ypos, n.xpos, n.ypos )

    xpos  :=  n.xpos
    ypos  :=  n.ypos
$)



AND canon.vline( length )  BE
$(
//  Draw a vertical line.  The line length may be negative indicating that
//  the line must be drawn in the negative direction.  Whatever, we must leave
//  the virtual pen where the line finishes.

    LET n.xpos  =  xpos
    LET n.ypos  =  ypos + length

    drawline( xpos, ypos, n.xpos, n.ypos )

    xpos  :=  n.xpos
    ypos  :=  n.ypos
$)


AND drawline( x1, y1, x2, y2 )  BE
$(
//  Draw a line in user space from (x1, y1) to (x2, y2).  We must first
//  transform this into absolute space, so we can decide which way
//  to draw the line.

    LET abs.x1  =  transform.x( x1, y1 )
    LET abs.x2  =  transform.x( x2, y2 )
    LET abs.y1  =  transform.y( x1, y1 )
    LET abs.y2  =  transform.y( x2, y2 )

    //  Now decide whether the line is actually horizontal or vertical.

    TEST  abs.x1 = abs.x2  THEN  verticalline( abs.x1, abs.y1, abs.y2 )    ELSE
    TEST  abs.y1 = abs.y2  THEN  horizontalline( abs.y1, abs.x1, abs.x2 )  ELSE

          //  Not a straight line.  Don't handle this at the moment.

          RETURN
$)



AND horizontalline( y, x1, x2 )  BE
$(    
    LET xstart  =  x1 < x2  ->  x1, x2
    LET ystart  =  y
    LET xlen    =  ABS (x1 - x2)  +  1

    startbitmap( xstart, ystart, xlen, 1 )

    FOR  i = 1  TO  xlen  DO  wrbit( 1 )

    flushbits()
$)



AND verticalline( x, y1, y2 )  BE
$(
    LET xstart  =  x
    LET ystart  =  y1 < y2  ->  y1, y2
    LET ylen    =  ABS (y1 - y2)  +  1

    startbitmap( xstart, ystart, 1, ylen )

    FOR  i = 1  TO  ylen  DO
    $(
        wrbit( 1 )
        flushbits()
    $)
$)



AND canon.heightfactor( n )  BE
$(
    heightfactor     :=  n
    charsize.height  :=  charheight * heightfactor
$)



AND canon.widthfactor( n )  BE
$(
    widthfactor     :=  n
    charsize.width  :=  charwidth * widthfactor
$)



AND canon.writes( string )  BE
    FOR  i = 1  TO  string % 0  DO
        canon.wrch( string % i )



AND canon.wrch( ch )  BE
$(
//  White a character at the current pen position.  The data for the 
//  character is in the vector "chars".  

    LET bitmap  =  chars!ch

    TEST  ch = '*E'  THEN  RETURN
    ELSE

    TEST  ch = '*P'  THEN  $(  canon.newpage() ;  RETURN  $)
    ELSE

    TEST  ch = '*N'  THEN  $(  movedown() ;  RETURN  $)
    ELSE

    TEST  ch = '*S'  THEN  $(  movealong() ;  RETURN  $)
    ELSE

    TEST  bitmap = 0  THEN  RETURN
    ELSE
    $(
        //  We have a character to be printed.  

        writecharacter( bitmap, xpos, ypos )

        movealong()
    $)
$)



AND writecharacter( bitmap, x, y )  BE
$(
//  Write a character at position (x, y) in user space.  We must transform
//  the character depending on orientation.

    LET abs.x    =  transform.x( x, y )
    LET abs.y    =  transform.y( x, y )

    LET rotated  =  orientation = orientation.right  |
                    orientation = orientation.left

    LET xsize    =  rotated  ->  charsize.height,  charsize.width
    LET ysize    =  rotated  ->  charsize.width,   charsize.height
    LET xfactor  =  rotated  ->  heightfactor,     widthfactor
    LET yfactor  =  rotated  ->  widthfactor,      heightfactor
    LET xbits    =  rotated  ->  charheight,       charwidth
    LET ybits    =  rotated  ->  charwidth,        charheight

    LET start.x  =  0
    LET start.y  =  0

    //  We must position the bitmap so that the logical position of (x, y) is
    //  the top left hand corner of the character.

    SWITCHON  orientation  INTO
    $(
        CASE orientation.up    :  start.x  :=  abs.x
                                  start.y  :=  abs.y
                                  ENDCASE

        CASE orientation.right :  start.x  :=  abs.x - xsize
                                  start.y  :=  abs.y
                                  ENDCASE

        CASE orientation.down  :  start.x  :=  abs.x - xsize
                                  start.y  :=  abs.y - ysize
                                  ENDCASE

        CASE orientation.left  :  start.x  :=  abs.x
                                  start.y  :=  abs.y - ysize
                                  ENDCASE
                                  
        DEFAULT                :  RETURN
    $)

    startbitmap( start.x, start.y, xsize, ysize )
        
    FOR  row = 1  TO  ybits  DO
    $(
        FOR  repeatrow = 1  TO  yfactor  DO
        $(
            FOR  column = 1  TO  xbits  DO
            $(
                LET offset     =  (row - 1) * xbits  +  column
                LET bitoffset  =  transformation( offset )
                LET ch         =  bitmap % bitoffset
                LET bit        =  ch = 'x'  ->  1,  0

                FOR  repeatcolumn = 1  TO  xfactor  DO  wrbit( bit )
            $)
    
            flushbits()
        $)
    $)
$)



AND canon.newpage()  BE
$(
    breakplot()

    canon.moveto( 0, 0 )
$)



AND canon.newline()  BE  movedown()



AND movealong()  BE  
    xpos  :=  xpos  +  charsize.width



AND movedown()  BE
$(
    xpos  :=  0
    ypos  :=  ypos  +  charsize.height
$)



AND canon.close()  BE
$(
//  Close the plot down in reasonable style.  This means terminating the
//  plot, and freeing any space which we grabbed.

    endplot()

    freevec( chars )
$)



AND initchars()  BE
$(
//  Initialise the character fount, given the character vector "chars".  The
//  bitmap for the characters is actually in STRING format, so that we can
//  easily draw characters horizontally or vertically.

    chars  :=  gvec( 255 )

    FOR  i = 0  TO  255  DO  chars!i  :=  0

    chars!'!'   :=  "...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *........*
                    *...xx...*
                    *........"

    chars!'"'   :=  ".xx.xx..*
                    *.xx.xx..*
                    *.xx.xx..*
                    *........*
                    *........*
                    *........*
                    *........*
                    *........"

    chars!'#'   :=  "..xx.xx.*
                    *..xx.xx.*
                    *.xxxxxxx*
                    *..xx.xx.*
                    *.xxxxxxx*
                    *..xx.xx.*
                    *..xx.xx.*
                    *........"

    chars!'$'   :=  "....xx..*
                    *..xxxxxx*
                    *.xx.x...*
                    *..xxxxx.*
                    *....x.xx*
                    *.xxxxxx.*
                    *...xx...*
                    *........"

    chars!'%'   :=  ".xx.....*
                    *.xx..xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *.xx..xx.*
                    *.....xx.*
                    *........"

    chars!'&'   :=  "..xxx...*
                    *.xx.xx..*
                    *.xx.xx..*
                    *..xxx...*
                    *.xx.xx.x*
                    *.xx..xx.*
                    *..xxx.xx*
                    *........"

    chars!'*''  :=  "....xx..*
                    *...xx...*
                    *..xx....*
                    *........*
                    *........*
                    *........*
                    *........*
                    *........"

    chars!'('   :=  "....xx..*
                    *...xx...*
                    *..xx....*
                    *..xx....*
                    *..xx....*
                    *...xx...*
                    *....xx..*
                    *........"

    chars!')'   :=  "..xx....*
                    *...xx...*
                    *....xx..*
                    *....xx..*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *........"

    chars!'**'  :=  "........*
                    *...xx...*
                    *.xxxxxx.*
                    *..xxxx..*
                    *.xxxxxx.*
                    *...xx...*
                    *........*
                    *........"

    chars!'+'   :=  "........*
                    *...xx...*
                    *...xx...*
                    *.xxxxxx.*
                    *...xx...*
                    *...xx...*
                    *........*
                    *........"

    chars!','   :=  "........*
                    *........*
                    *........*
                    *........*
                    *........*
                    *...xx...*
                    *...xx...*
                    *..xx...."

    chars!'-'   :=  "........*
                    *........*
                    *........*
                    *.xxxxxx.*
                    *........*
                    *........*
                    *........*
                    *........"

    chars!'.'   :=  "........*
                    *........*
                    *........*
                    *........*
                    *........*
                    *...xx...*
                    *...xx...*
                    *........"

    chars!'/'   :=  "........*
                    *.....xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *.xx.....*
                    *........*
                    *........"

    chars!'0'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx.xxx.*
                    *.xxxxxx.*
                    *.xxx.xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'1'   :=  "...xx...*
                    *..xxx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *.xxxxxx.*
                    *........"

    chars!'2'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.....xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *.xxxxxx.*
                    *........"

    chars!'3'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.....xx.*
                    *...xxx..*
                    *.....xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'4'   :=  "....xx..*
                    *...xxx..*
                    *..xxxx..*
                    *.xx.xx..*
                    *.xxxxxx.*
                    *....xx..*
                    *....xx..*
                    *........"

    chars!'5'   :=  ".xxxxxx.*
                    *.xx.....*
                    *.xxxxx..*
                    *.....xx.*
                    *.....xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'6'   :=  "...xxx..*
                    *..xx....*
                    *.xx.....*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'7'   :=  ".xxxxxx.*
                    *.....xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *..xx....*
                    *..xx....*
                    *........"

    chars!'8'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'9'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *.....xx.*
                    *....xx..*
                    *..xxx...*
                    *........"

    chars!':'   :=  "........*
                    *........*
                    *...xx...*
                    *...xx...*
                    *........*
                    *...xx...*
                    *...xx...*
                    *........"

    chars!';'   :=  "........*
                    *........*
                    *...xx...*
                    *...xx...*
                    *........*
                    *...xx...*
                    *...xx...*
                    *..xx...."

    chars!'<'   :=  "....xx..*
                    *...xx...*
                    *..xx....*
                    *.xx.....*
                    *..xx....*
                    *...xx...*
                    *....xx..*
                    *........"

    chars!'='   :=  "........*
                    *........*
                    *.xxxxxx.*
                    *........*
                    *.xxxxxx.*
                    *........*
                    *........*
                    *........"

    chars!'>'   :=  "..xx....*
                    *...xx...*
                    *....xx..*
                    *.....xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *........"

    chars!'?'   :=  "..xxxx..*
                    *.xx..xx.*
                    *....xx..*
                    *...xx...*
                    *...xx...*
                    *........*
                    *...xx...*
                    *........"

    chars!'@'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx.xxx.*
                    *.xx.x.x.*
                    *.xx.xxx.*
                    *.xx.....*
                    *..xxxx..*
                    *........"

    chars!'A'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'B'   :=  ".xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *........"

    chars!'C'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'D'   :=  ".xxxx...*
                    *.xx.xx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx.xx..*
                    *.xxxx...*
                    *........"

    chars!'E'   :=  ".xxxxxx.*
                    *.xx.....*
                    *.xx.....*
                    *.xxxxx..*
                    *.xx.....*
                    *.xx.....*
                    *.xxxxxx.*
                    *........"

    chars!'F'   :=  ".xxxxxx.*
                    *.xx.....*
                    *.xx.....*
                    *.xxxxx..*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *........"

    chars!'G'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx.....*
                    *.xx.xxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'H'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'I'   :=  ".xxxxxx.*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *.xxxxxx.*
                    *........"

    chars!'J'   :=  "..xxxxx.*
                    *....xx..*
                    *....xx..*
                    *....xx..*
                    *....xx..*
                    *.xx.xx..*
                    *..xxx...*
                    *........"

    chars!'K'   :=  ".xx..xx.*
                    *.xx.xx..*
                    *.xxxx...*
                    *.xxx....*
                    *.xxxx...*
                    *.xx.xx..*
                    *.xx..xx.*
                    *........"

    chars!'L'   :=  ".xx.....*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *.xxxxxx.*
                    *........"

    chars!'M'   :=  ".xx...xx*
                    *.xxx.xxx*
                    *.xxxxxxx*
                    *.xx.x.xx*
                    *.xx.x.xx*
                    *.xx...xx*
                    *.xx...xx*
                    *........"

    chars!'N'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *.xxx.xx.*
                    *.xxxxxx.*
                    *.xx.xxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'O'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'P'   :=  ".xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *........"

    chars!'Q'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx.x.x.*
                    *.xx.xx..*
                    *..xx.xx.*
                    *........"

    chars!'R'   :=  ".xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *.xx.xx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'S'   :=  "..xxxx..*
                    *.xx..xx.*
                    *.xx.....*
                    *..xxxx..*
                    *.....xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'T'   :=  ".xxxxxx.*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *........"

    chars!'U'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'V'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *...xx...*
                    *........"

    chars!'W'   :=  ".xx...xx*
                    *.xx...xx*
                    *.xx.x.xx*
                    *.xx.x.xx*
                    *.xxxxxxx*
                    *.xxx.xxx*
                    *.xx...xx*
                    *........"

    chars!'X'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *...xx...*
                    *..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'Y'   :=  ".xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *........"

    chars!'Z'   :=  ".xxxxxx.*
                    *.....xx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *.xx.....*
                    *.xxxxxx.*
                    *........"

    chars!'^'   :=  "...xx...*
                    *..xxxx..*
                    *.xx..xx.*
                    *.x....x.*
                    *........*
                    *........*
                    *........*
                    *........"

    chars!'_'   :=  "........*
                    *........*
                    *........*
                    *........*
                    *........*
                    *........*
                    *........*
                    *xxxxxxxx"

    chars!'a'   :=  "........*
                    *........*
                    *..xxxx..*
                    *.....xx.*
                    *..xxxxx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *........"

    chars!'b'   :=  ".xx.....*
                    *.xx.....*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *........"

    chars!'c'   :=  "........*
                    *........*
                    *..xxxx..*
                    *.xx..xx.*
                    *.xx.....*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'d'   :=  ".....xx.*
                    *.....xx.*
                    *..xxxxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *........"

    chars!'e'   :=  "........*
                    *........*
                    *..xxxx..*
                    *.xx..xx.*
                    *.xxxxxx.*
                    *.xx.....*
                    *..xxxx..*
                    *........"

    chars!'f'   :=  "...xxx..*
                    *..xx....*
                    *..xx....*
                    *.xxxxx..*
                    *..xx....*
                    *..xx....*
                    *..xx....*
                    *........"

    chars!'g'   :=  "........*
                    *........*
                    *..xxxxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *.....xx.*
                    *..xxxx.."

    chars!'h'   :=  ".xx.....*
                    *.xx.....*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'i'   :=  "...xx...*
                    *........*
                    *..xxx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *..xxxx..*
                    *........"

    chars!'j'   :=  "...xx...*
                    *........*
                    *..xxx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *.xxx...."

    chars!'k'   :=  ".xx.....*
                    *.xx.....*
                    *.xx..xx.*
                    *.xx.xx..*
                    *.xxxx...*
                    *.xx.xx..*
                    *.xx..xx.*
                    *........"

    chars!'l'   :=  ".xxx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *..xxxx..*
                    *........"

    chars!'m'   :=  "........*
                    *........*
                    *..xx.xx.*
                    *.xxxxxxx*
                    *.xx.x.xx*
                    *.xx.x.xx*
                    *.xx...xx*
                    *........"

    chars!'n'   :=  "........*
                    *........*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *........"

    chars!'o'   :=  "........*
                    *........*
                    *..xxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *........"

    chars!'p'   :=  "........*
                    *........*
                    *.xxxxx..*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xxxxx..*
                    *.xx.....*
                    *.xx....."

    chars!'q'   :=  "........*
                    *........*
                    *..xxxxx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *.....xx.*
                    *.....xxx"

    chars!'r'   :=  "........*
                    *........*
                    *.xx.xx..*
                    *.xxx.xx.*
                    *.xx.....*
                    *.xx.....*
                    *.xx.....*
                    *........"

    chars!'s'   :=  "........*
                    *........*
                    *..xxxxx.*
                    *.xx.....*
                    *..xxxx..*
                    *.....xx.*
                    *.xxxxx..*
                    *........"

    chars!'t'   :=  "..xx....*
                    *..xx....*
                    *.xxxxx..*
                    *..xx....*
                    *..xx....*
                    *..xx....*
                    *...xxx..*
                    *........"

    chars!'u'   :=  "........*
                    *........*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *........"

    chars!'v'   :=  "........*
                    *........*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxx..*
                    *...xx...*
                    *........"

    chars!'w'   :=  "........*
                    *........*
                    *.xx...xx*
                    *.xx.x.xx*
                    *.xx.x.xx*
                    *.xxxxxxx*
                    *..xx.xx.*
                    *........"

    chars!'x'   :=  "........*
                    *........*
                    *.xx..xx.*
                    *..xxxx..*
                    *...xx...*
                    *..xxxx..*
                    *.xx..xx.*
                    *........"

    chars!'y'   :=  "........*
                    *........*
                    *.xx..xx.*
                    *.xx..xx.*
                    *.xx..xx.*
                    *..xxxxx.*
                    *.....xx.*
                    *..xxxx.."

    chars!'z'   :=  "........*
                    *........*
                    *.xxxxxx.*
                    *....xx..*
                    *...xx...*
                    *..xx....*
                    *.xxxxxx.*
                    *........"


   chars!'|'   :=  "....xx...*
                    *...xx...*
                    *...xx...*
                    *........*
                    *...xx...*
                    *...xx...*
                    *...xx...*
                    *........"
$)



AND transform.x( x, y )  =  orientation = orientation.up     ->  x,
                            orientation = orientation.right  ->  resolution.x - y,
                            orientation = orientation.down   ->  resolution.x - x,
                            orientation = orientation.left   ->  y,
                                                                 0



AND transform.y( x, y )  =  orientation = orientation.up     ->  y,
                            orientation = orientation.right  ->  x,
                            orientation = orientation.down   ->  resolution.y - y,
                            orientation = orientation.left   ->  resolution.y - x,
                                                                 0



AND transformation( offset )  =  VALOF
$(
//  Take the offset into the transformation vector, and return the actual
//  relevant BIT offset into the character.

    LET transform.up     =  (TABLE   1,  2,  3,  4,  5,  6,  7,  8,
                                     9, 10, 11, 12, 13, 14, 15, 16,
                                    17, 18, 19, 20, 21, 22, 23, 24,
                                    25, 26, 27, 28, 29, 30, 31, 32,
                                    33, 34, 35, 36, 37, 38, 39, 40,
                                    41, 42, 43, 44, 45, 46, 47, 48,
                                    49, 50, 51, 52, 53, 54, 55, 56,
                                    57, 58, 59, 60, 61, 62, 63, 64)

    LET transform.right  =  (TABLE  57, 49, 41, 33, 25, 17,  9,  1,
                                    58, 50, 42, 34, 26, 18, 10,  2,
                                    59, 51, 43, 35, 27, 19, 11,  3,
                                    60, 52, 44, 36, 28, 20, 12,  4,
                                    61, 53, 45, 37, 29, 21, 13,  5,
                                    62, 54, 46, 38, 30, 22, 14,  6,
                                    63, 55, 47, 39, 31, 23, 15,  7,
                                    64, 56, 48, 40, 32, 24, 16,  8)

    LET transform.down   =  (TABLE  64, 63, 62, 61, 60, 59, 58, 57,
                                    56, 55, 54, 53, 52, 51, 50, 49,
                                    48, 47, 46, 45, 44, 43, 42, 41,
                                    40, 39, 38, 37, 36, 35, 34, 33,
                                    32, 31, 30, 29, 28, 27, 26, 25,
                                    24, 23, 22, 21, 20, 19, 18, 17,
                                    16, 15, 14, 13, 12, 11, 10,  9,
                                     8,  7,  6,  5,  4,  3,  2,  1)

    LET transform.left   =  (TABLE   8, 16, 24, 32, 40, 48, 56, 64,
                                     7, 15, 23, 31, 39, 47, 55, 63,
                                     6, 14, 22, 30, 38, 46, 54, 62,
                                     5, 13, 21, 29, 37, 45, 53, 61,
                                     4, 12, 20, 28, 36, 44, 52, 60,
                                     3, 11, 19, 27, 35, 43, 51, 59,
                                     2, 10, 18, 26, 34, 42, 50, 58,
                                     1,  9, 17, 25, 33, 41, 49, 57)

    LET transform        =  orientation = orientation.up     ->  transform.up,
                            orientation = orientation.right  ->  transform.right,
                            orientation = orientation.down   ->  transform.down,
                            orientation = orientation.left   ->  transform.left,
                                                                 0

    RESULTIS  transform!(offset-1)
$)



AND startplot( resolution )  BE
$(
    wrch( #X00 )          //  Start plot code
    wrch( resolution )    //  Resolution
$)



AND endplot()  BE
$(
    wrch( #X02 )    //  End plot
$)



AND startbitmap( xoffset, yoffset, xlength, ylength )  BE
$(
    wrch( #X03 )    //  Bits to be set

    writeword( xoffset )
    writeword( yoffset )
    writeword( xlength )
    writeword( ylength )
$)



AND flushbits()  BE
    UNTIL  bitcount = 0  DO
        wrbit( 0 )



AND breakplot()  BE
$(
    wrch( #X01 )    //  End of page
$)



AND writeword( word )  BE
$(
    wrch( (word >> 8) & #XFF )
    wrch( (word)      & #XFF )
$)



AND wrbit( bit )  BE
$(
    bitbuffer  :=  (bitbuffer << 1)  +  bit
    bitcount   :=  bitcount + 1

    IF  bitcount = bitsperbyte  THEN
    $(
        wrch( bitbuffer )
        
        bitbuffer  :=  0
        bitcount   :=  0
    $)
$)



AND gvec( size )  =  VALOF
$(
    LET v  =  getvec( size )

    IF  v = 0  THEN  abort( 103 )    //  Error.Getvecfailure

    RESULTIS  v
$)


