summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2017-02-20 12:17:42 -0800
committerKeith Packard <keithp@keithp.com>2017-02-20 12:34:02 -0800
commit1301d576d9bface4cc625e4a4187401f93f54444 (patch)
tree300e0b243fb5ee300fa9e483efed86dd498c9118
parenta487d2fcba57141f6b083d5612c76bac5ad1ac7c (diff)
altos: Add bitmap drawing code
Includes solid fills, text and lines. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/draw/5x7.bdf3190
-rw-r--r--src/draw/Makefile4
-rw-r--r--src/draw/ao_blt.c294
-rw-r--r--src/draw/ao_copy.c75
-rw-r--r--src/draw/ao_draw.h119
-rw-r--r--src/draw/ao_draw_int.h136
-rw-r--r--src/draw/ao_font.h139
-rw-r--r--src/draw/ao_line.c314
-rw-r--r--src/draw/ao_pattern.c80
-rw-r--r--src/draw/ao_rect.c46
-rw-r--r--src/draw/ao_text.c65
-rwxr-xr-xsrc/draw/font-convert150
-rw-r--r--src/draw/line.5c389
13 files changed, 5001 insertions, 0 deletions
diff --git a/src/draw/5x7.bdf b/src/draw/5x7.bdf
new file mode 100644
index 00000000..b511f289
--- /dev/null
+++ b/src/draw/5x7.bdf
@@ -0,0 +1,3190 @@
+STARTFONT 2.1
+COMMENT Copyright 1991 Massachusetts Institute of Technology
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software
+COMMENT and its documentation for any purpose and without fee is
+COMMENT hereby granted, provided that the above copyright notice
+COMMENT appear in all copies and that both that copyright notice and
+COMMENT this permission notice appear in supporting documentation,
+COMMENT and that the name of M.I.T. not be used in advertising or
+COMMENT publicity pertaining to distribution of the software without
+COMMENT specific, written prior permission. M.I.T. makes no
+COMMENT representations about the suitability of this software for
+COMMENT any purpose. It is provided "as is" without express or
+COMMENT implied warranty.
+COMMENT
+COMMENT M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+COMMENT INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+COMMENT FITNESS, IN NO EVENT SHALL M.I.T. BE LIABLE FOR ANY SPECIAL,
+COMMENT INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+COMMENT RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+COMMENT ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+COMMENT ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+COMMENT OF THIS SOFTWARE.
+COMMENT
+COMMENT Author: Stephen Gildea, MIT X Consortium, June 1991
+COMMENT
+FONT -Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO8859-1
+SIZE 7 75 75
+FONTBOUNDINGBOX 5 7 0 -1
+STARTPROPERTIES 21
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 7
+POINT_SIZE 70
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+FONT_ASCENT 6
+FONT_DESCENT 1
+UNDERLINE_POSITION 0
+DESTINATION 1
+DEFAULT_CHAR 0
+COPYRIGHT "Copyright 1991 Massachusetts Institute of Technology"
+ENDPROPERTIES
+CHARS 224
+STARTCHAR C000
+ENCODING 0
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+f0
+f0
+f0
+f0
+f0
+00
+ENDCHAR
+STARTCHAR C001
+ENCODING 1
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+70
+f8
+70
+20
+00
+ENDCHAR
+STARTCHAR C002
+ENCODING 2
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+50
+a0
+50
+a0
+00
+ENDCHAR
+STARTCHAR C003
+ENCODING 3
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+e0
+a0
+a0
+70
+20
+20
+ENDCHAR
+STARTCHAR C004
+ENCODING 4
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+80
+c0
+b0
+20
+30
+20
+ENDCHAR
+STARTCHAR C005
+ENCODING 5
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+80
+c0
+60
+50
+60
+50
+ENDCHAR
+STARTCHAR C006
+ENCODING 6
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+c0
+30
+20
+30
+20
+ENDCHAR
+STARTCHAR C007
+ENCODING 7
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C010
+ENCODING 8
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+70
+20
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR C011
+ENCODING 9
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+d0
+b0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR C012
+ENCODING 10
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR C013
+ENCODING 11
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+e0
+00
+00
+00
+ENDCHAR
+STARTCHAR C014
+ENCODING 12
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+e0
+20
+20
+20
+ENDCHAR
+STARTCHAR C015
+ENCODING 13
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+38
+20
+20
+20
+ENDCHAR
+STARTCHAR C016
+ENCODING 14
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR C017
+ENCODING 15
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+f8
+20
+20
+20
+ENDCHAR
+STARTCHAR C020
+ENCODING 16
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+f8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C021
+ENCODING 17
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+00
+00
+f8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C022
+ENCODING 18
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f8
+00
+00
+00
+ENDCHAR
+STARTCHAR C023
+ENCODING 19
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+f8
+00
+00
+ENDCHAR
+STARTCHAR C024
+ENCODING 20
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+f8
+00
+ENDCHAR
+STARTCHAR C025
+ENCODING 21
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+38
+20
+20
+20
+ENDCHAR
+STARTCHAR C026
+ENCODING 22
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+e0
+20
+20
+20
+ENDCHAR
+STARTCHAR C027
+ENCODING 23
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+20
+20
+20
+f8
+00
+00
+00
+ENDCHAR
+STARTCHAR C030
+ENCODING 24
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f8
+20
+20
+20
+ENDCHAR
+STARTCHAR C031
+ENCODING 25
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR C032
+ENCODING 26
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+20
+40
+20
+10
+70
+00
+ENDCHAR
+STARTCHAR C033
+ENCODING 27
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+10
+20
+40
+70
+00
+ENDCHAR
+STARTCHAR C034
+ENCODING 28
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+50
+50
+50
+00
+ENDCHAR
+STARTCHAR C035
+ENCODING 29
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+10
+70
+20
+70
+40
+00
+ENDCHAR
+STARTCHAR C036
+ENCODING 30
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+30
+40
+e0
+40
+b0
+00
+ENDCHAR
+STARTCHAR C037
+ENCODING 31
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR C040
+ENCODING 32
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR !
+ENCODING 33
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR "
+ENCODING 34
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+50
+50
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR #
+ENCODING 35
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+50
+f8
+50
+f8
+50
+00
+ENDCHAR
+STARTCHAR $
+ENCODING 36
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+70
+a0
+70
+28
+70
+00
+ENDCHAR
+STARTCHAR %
+ENCODING 37
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+90
+20
+40
+90
+10
+00
+ENDCHAR
+STARTCHAR &
+ENCODING 38
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+40
+a0
+40
+a0
+50
+00
+ENDCHAR
+STARTCHAR '
+ENCODING 39
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+40
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR (
+ENCODING 40
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR )
+ENCODING 41
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR *
+ENCODING 42
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+a0
+40
+e0
+40
+a0
+00
+ENDCHAR
+STARTCHAR +
+ENCODING 43
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+20
+f8
+20
+20
+00
+ENDCHAR
+STARTCHAR ,
+ENCODING 44
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+60
+40
+80
+ENDCHAR
+STARTCHAR -
+ENCODING 45
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f0
+00
+00
+00
+ENDCHAR
+STARTCHAR .
+ENCODING 46
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+60
+60
+00
+ENDCHAR
+STARTCHAR /
+ENCODING 47
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+10
+20
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+a0
+a0
+a0
+40
+00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+c0
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+10
+20
+40
+f0
+00
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+60
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+60
+a0
+f0
+20
+20
+00
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+80
+e0
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+20
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR :
+ENCODING 58
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+00
+ENDCHAR
+STARTCHAR ;
+ENCODING 59
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+60
+40
+80
+ENDCHAR
+STARTCHAR <
+ENCODING 60
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR =
+ENCODING 61
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+00
+f0
+00
+00
+ENDCHAR
+STARTCHAR >
+ENCODING 62
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR ?
+ENCODING 63
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+20
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR @
+ENCODING 64
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+b0
+b0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+e0
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+b0
+90
+70
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+f0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+10
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+a0
+c0
+c0
+a0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+f0
+f0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+d0
+d0
+b0
+b0
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+e0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+d0
+60
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+e0
+a0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+40
+20
+90
+60
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+60
+60
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+f0
+f0
+90
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+20
+40
+80
+f0
+00
+ENDCHAR
+STARTCHAR [
+ENCODING 91
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+80
+80
+80
+80
+e0
+00
+ENDCHAR
+STARTCHAR \
+ENCODING 92
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+40
+20
+10
+00
+00
+ENDCHAR
+STARTCHAR ]
+ENCODING 93
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+20
+20
+20
+20
+e0
+00
+ENDCHAR
+STARTCHAR ^
+ENCODING 94
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR _
+ENCODING 95
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+f0
+00
+ENDCHAR
+STARTCHAR `
+ENCODING 96
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+40
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+e0
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+10
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+40
+e0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+60
+80
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+00
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+00
+20
+20
+20
+a0
+40
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+a0
+c0
+a0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+a0
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+90
+70
+10
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+00
+00
+70
+c0
+30
+e0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+40
+e0
+40
+40
+30
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+a0
+a0
+a0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+f0
+f0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+50
+20
+40
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+20
+40
+f0
+00
+ENDCHAR
+STARTCHAR {
+ENCODING 123
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+c0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR |
+ENCODING 124
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR }
+ENCODING 125
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+80
+40
+60
+40
+40
+80
+00
+ENDCHAR
+STARTCHAR ~
+ENCODING 126
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Blank
+ENCODING 127
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C160
+ENCODING 160
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C161
+ENCODING 161
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+00
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR C162
+ENCODING 162
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+70
+a0
+a0
+70
+20
+ENDCHAR
+STARTCHAR C163
+ENCODING 163
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+30
+40
+e0
+40
+b0
+00
+ENDCHAR
+STARTCHAR C164
+ENCODING 164
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+88
+70
+50
+70
+88
+00
+ENDCHAR
+STARTCHAR C165
+ENCODING 165
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+40
+e0
+40
+40
+00
+ENDCHAR
+STARTCHAR C166
+ENCODING 166
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+20
+00
+20
+20
+00
+ENDCHAR
+STARTCHAR C167
+ENCODING 167
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+30
+40
+60
+50
+30
+10
+60
+ENDCHAR
+STARTCHAR C168
+ENCODING 168
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C169
+ENCODING 169
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+88
+a8
+c8
+a8
+88
+70
+ENDCHAR
+STARTCHAR C170
+ENCODING 170
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+a0
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C171
+ENCODING 171
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+48
+90
+48
+00
+00
+ENDCHAR
+STARTCHAR C172
+ENCODING 172
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR C173
+ENCODING 173
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f0
+00
+00
+00
+ENDCHAR
+STARTCHAR C174
+ENCODING 174
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+88
+e8
+c8
+c8
+88
+70
+ENDCHAR
+STARTCHAR C175
+ENCODING 175
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C176
+ENCODING 176
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C177
+ENCODING 177
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+f8
+20
+20
+f8
+00
+ENDCHAR
+STARTCHAR C178
+ENCODING 178
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR C179
+ENCODING 179
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+60
+20
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR C180
+ENCODING 180
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C181
+ENCODING 181
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR C182
+ENCODING 182
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+d0
+d0
+50
+50
+50
+00
+ENDCHAR
+STARTCHAR C183
+ENCODING 183
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C184
+ENCODING 184
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+20
+40
+ENDCHAR
+STARTCHAR C185
+ENCODING 185
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+60
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR C186
+ENCODING 186
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C187
+ENCODING 187
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+48
+90
+00
+00
+ENDCHAR
+STARTCHAR C188
+ENCODING 188
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+90
+30
+70
+10
+ENDCHAR
+STARTCHAR C189
+ENCODING 189
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+b0
+10
+20
+30
+ENDCHAR
+STARTCHAR C190
+ENCODING 190
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+c0
+40
+d0
+30
+70
+10
+ENDCHAR
+STARTCHAR C191
+ENCODING 191
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+00
+40
+80
+a0
+40
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C193
+ENCODING 193
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C194
+ENCODING 194
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C195
+ENCODING 195
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C196
+ENCODING 196
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C197
+ENCODING 197
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C198
+ENCODING 198
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+a0
+b0
+e0
+a0
+b0
+00
+ENDCHAR
+STARTCHAR C199
+ENCODING 199
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+80
+90
+60
+40
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C201
+ENCODING 201
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C202
+ENCODING 202
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C203
+ENCODING 203
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C204
+ENCODING 204
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C205
+ENCODING 205
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C206
+ENCODING 206
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C207
+ENCODING 207
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C208
+ENCODING 208
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+50
+d0
+50
+50
+e0
+00
+ENDCHAR
+STARTCHAR C209
+ENCODING 209
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+b0
+90
+d0
+b0
+b0
+90
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C211
+ENCODING 211
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C212
+ENCODING 212
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C213
+ENCODING 213
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C214
+ENCODING 214
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C215
+ENCODING 215
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR C216
+ENCODING 216
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+b0
+b0
+d0
+d0
+e0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C218
+ENCODING 218
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C219
+ENCODING 219
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C220
+ENCODING 220
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C221
+ENCODING 221
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR C222
+ENCODING 222
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+e0
+90
+e0
+80
+80
+00
+ENDCHAR
+STARTCHAR C223
+ENCODING 223
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+e0
+90
+d0
+a0
+80
+ENDCHAR
+STARTCHAR a-grave
+ENCODING 224
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C225
+ENCODING 225
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C226
+ENCODING 226
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C227
+ENCODING 227
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C228
+ENCODING 228
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C229
+ENCODING 229
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+60
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C230
+ENCODING 230
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+b0
+a0
+70
+00
+ENDCHAR
+STARTCHAR C231
+ENCODING 231
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+80
+80
+60
+40
+ENDCHAR
+STARTCHAR e-grave
+ENCODING 232
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C233
+ENCODING 233
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C234
+ENCODING 234
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C235
+ENCODING 235
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C236
+ENCODING 236
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+40
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C237
+ENCODING 237
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+80
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C238
+ENCODING 238
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C239
+ENCODING 239
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C240
+ENCODING 240
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+30
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C241
+ENCODING 241
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR C242
+ENCODING 242
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C243
+ENCODING 243
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C244
+ENCODING 244
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C245
+ENCODING 245
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C246
+ENCODING 246
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C247
+ENCODING 247
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+00
+f0
+00
+60
+00
+ENDCHAR
+STARTCHAR C248
+ENCODING 248
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+b0
+d0
+e0
+00
+ENDCHAR
+STARTCHAR C249
+ENCODING 249
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C250
+ENCODING 250
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C251
+ENCODING 251
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C252
+ENCODING 252
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C253
+ENCODING 253
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+90
+90
+50
+20
+40
+ENDCHAR
+STARTCHAR C254
+ENCODING 254
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+e0
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR C255
+ENCODING 255
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+90
+90
+50
+20
+40
+ENDCHAR
+ENDFONT
diff --git a/src/draw/Makefile b/src/draw/Makefile
new file mode 100644
index 00000000..0a542a1f
--- /dev/null
+++ b/src/draw/Makefile
@@ -0,0 +1,4 @@
+BDF=5x7.bdf
+
+ao_font.h: font-convert $(BDF)
+ nickle font-convert $(BDF) > $@
diff --git a/src/draw/ao_blt.c b/src/draw/ao_blt.c
new file mode 100644
index 00000000..e3f45221
--- /dev/null
+++ b/src/draw/ao_blt.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define O 0
+#define I AO_ALLONES
+
+struct ao_merge_rop {
+ uint32_t ca1, cx1, ca2, cx2;
+};
+
+const struct ao_merge_rop ao_merge_rop[16] = {
+ {O, O, O, O}, /* clear 0x0 0 */
+ {I, O, O, O}, /* and 0x1 src AND dst */
+ {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */
+ {O, O, I, O}, /* copy 0x3 src */
+ {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */
+ {O, I, O, O}, /* noop 0x5 dst */
+ {O, I, I, O}, /* xor 0x6 src XOR dst */
+ {I, I, I, O}, /* or 0x7 src OR dst */
+ {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */
+ {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */
+ {O, I, O, I}, /* invert 0xa NOT dst */
+ {I, I, O, I}, /* orReverse 0xb src OR NOT dst */
+ {O, O, I, I}, /* copyInverted 0xc NOT src */
+ {I, O, I, I}, /* orInverted 0xd NOT src OR dst */
+ {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */
+ {O, O, O, I}, /* set 0xf 1 */
+};
+
+#define ao_do_merge_rop(src, dst) \
+ (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2))
+
+#define ao_do_dst_invarient_merge_rop(src) (((src) & _ca2) ^ _cx2)
+
+#define ao_do_mask_merge_rop(src, dst, mask) \
+ (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask)))
+
+#define ao_dst_invarient_merge_rop() (_ca1 == 0 && _cx1 == 0)
+
+void
+ao_blt(uint32_t *src_line,
+ int16_t src_stride,
+ int16_t src_x,
+ uint32_t *dst_line,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height,
+ uint8_t rop,
+ uint8_t reverse,
+ uint8_t upsidedown)
+{
+ uint32_t *src, *dst;
+ uint32_t _ca1, _cx1, _ca2, _cx2;
+ uint8_t dst_invarient;
+ uint32_t startmask, endmask;
+ int16_t nmiddle, n;
+ uint32_t bits1, bits;
+ int16_t left_shift, right_shift;
+
+ _ca1 = ao_merge_rop[rop].ca1;
+ _cx1 = ao_merge_rop[rop].cx1;
+ _ca2 = ao_merge_rop[rop].ca2;
+ _cx2 = ao_merge_rop[rop].cx2;
+ dst_invarient = ao_dst_invarient_merge_rop();
+
+ if (upsidedown) {
+ src_line += (height - 1) * src_stride;
+ dst_line += (height - 1) * dst_stride;
+ src_stride = -src_stride;
+ dst_stride = -dst_stride;
+ }
+
+ ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
+ if (reverse) {
+ src_line += ((src_x + width - 1) >> AO_SHIFT) + 1;
+ dst_line += ((dst_x + width - 1) >> AO_SHIFT) + 1;
+ src_x = (src_x + width - 1) & AO_MASK;
+ dst_x = (dst_x + width - 1) & AO_MASK;
+ } else {
+ src_line += src_x >> AO_SHIFT;
+ dst_line += dst_x >> AO_SHIFT;
+ src_x &= AO_MASK;
+ dst_x &= AO_MASK;
+ }
+ if (src_x == dst_x) {
+ while (height--) {
+ src = src_line;
+ src_line += src_stride;
+ dst = dst_line;
+ dst_line += dst_stride;
+ if (reverse) {
+ if (endmask) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--)
+ *--dst = ao_do_dst_invarient_merge_rop(*--src);
+ }
+ else {
+ while (n--) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_merge_rop(bits, *dst);
+ }
+ }
+ if (startmask) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ }
+ }
+ else {
+ if (startmask) {
+ bits = *src++;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--)
+ *dst++ = ao_do_dst_invarient_merge_rop(*src++);
+ }
+ else {
+ while (n--) {
+ bits = *src++;
+ *dst = ao_do_merge_rop(bits, *dst);
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = *src;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ }
+ }
+ } else {
+ if (src_x > dst_x) {
+ left_shift = src_x - dst_x;
+ right_shift = AO_UNIT - left_shift;
+ } else {
+ right_shift = dst_x - src_x;
+ left_shift = AO_UNIT - right_shift;
+ }
+ while (height--) {
+ src = src_line;
+ src_line += src_stride;
+ dst = dst_line;
+ dst_line += dst_stride;
+
+ bits1 = 0;
+ if (reverse) {
+ if (src_x < dst_x)
+ bits1 = *--src;
+ if (endmask) {
+ bits = ao_right(bits1, right_shift);
+ if (ao_right(endmask, left_shift)) {
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ }
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--) {
+ bits = ao_right(bits1, right_shift);
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ --dst;
+ *dst = ao_do_dst_invarient_merge_rop(bits);
+ }
+ } else {
+ while (n--) {
+ bits = ao_right(bits1, right_shift);
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ --dst;
+ *dst = ao_do_merge_rop(bits, *dst);
+ }
+ }
+ if (startmask) {
+ bits = ao_right(bits1, right_shift);
+ if (ao_right(startmask, left_shift)) {
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ }
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ }
+ }
+ else {
+ if (src_x > dst_x)
+ bits1 = *src++;
+ if (startmask) {
+ bits = ao_left(bits1, left_shift);
+ if (ao_left(startmask, right_shift)) {
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ }
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--) {
+ bits = ao_left(bits1, left_shift);
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ *dst = ao_do_dst_invarient_merge_rop(bits);
+ dst++;
+ }
+ }
+ else {
+ while (n--) {
+ bits = ao_left(bits1, left_shift);
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ *dst = ao_do_merge_rop(bits, *dst);
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = ao_left(bits1, left_shift);
+ if (ao_left(endmask, right_shift)) {
+ bits1 = *src;
+ bits |= ao_right(bits1, right_shift);
+ }
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ }
+ }
+ }
+}
+
+void
+ao_solid(uint32_t and,
+ uint32_t xor,
+ uint32_t *dst,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height)
+{
+ uint32_t startmask, endmask;
+ int16_t nmiddle;
+ int16_t n;
+
+ dst += dst_x >> AO_SHIFT;
+ dst_x &= AO_MASK;
+
+ ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
+
+ if (startmask)
+ dst_stride--;
+
+ dst_stride -= nmiddle;
+ while (height--) {
+ if (startmask) {
+ *dst = ao_do_mask_rrop(*dst, and, xor, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (!and)
+ while (n--)
+ *dst++ = xor;
+ else
+ while (n--) {
+ *dst = ao_do_rrop(*dst, and, xor);
+ dst++;
+ }
+ if (endmask)
+ *dst = ao_do_mask_rrop(*dst, and, xor, endmask);
+ dst += dst_stride;
+ }
+}
diff --git a/src/draw/ao_copy.c b/src/draw/ao_copy.c
new file mode 100644
index 00000000..47067bb8
--- /dev/null
+++ b/src/draw/ao_copy.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define bound(val,max,other) do { \
+ if (val < 0) { \
+ other -= val; \
+ val = 0; \
+ } \
+ if (val > max) { \
+ other -= (val - max); \
+ val = max; \
+ } \
+ } while (0)
+
+#define bound2(a, max_a, b, max_b) do { \
+ bound(a, max_a, b); \
+ bound(b, max_b, a); \
+ } while (0)
+
+void
+ao_copy(const struct ao_bitmap *dst,
+ int16_t dst_x,
+ int16_t dst_y,
+ int16_t width,
+ int16_t height,
+ const struct ao_bitmap *src,
+ int16_t src_x,
+ int16_t src_y,
+ uint8_t rop)
+{
+ int16_t dst_x2 = dst_x + width, dst_y2 = dst_y + height;
+ int16_t src_x2 = src_x + width, src_y2 = src_y + height;
+ uint8_t reverse = 0;
+ uint8_t upsidedown = 0;
+
+ bound2(dst_x, dst->width, src_x, src->width);
+ bound2(dst_x2, dst->width, src_x2, src->width);
+ bound2(dst_y, dst->height, src_y, src->height);
+ bound2(dst_y2, dst->height, src_y2, src->height);
+
+ if (dst == src) {
+ reverse = (dst_x > src_x);
+ upsidedown = (dst_y > src_y);
+ }
+
+ if (dst_x < dst_x2 && dst_y < dst_y2) {
+ ao_blt(src->base + src_y * src->stride,
+ src->stride,
+ src_x,
+ dst->base + dst_y * dst->stride,
+ dst->stride,
+ dst_x,
+ dst_x2 - dst_x,
+ dst_y2 - dst_y,
+ rop,
+ reverse,
+ upsidedown);
+ }
+}
+
diff --git a/src/draw/ao_draw.h b/src/draw/ao_draw.h
new file mode 100644
index 00000000..92150fc1
--- /dev/null
+++ b/src/draw/ao_draw.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_DRAW_H_
+#define _AO_DRAW_H_
+
+struct ao_bitmap {
+ uint32_t *base;
+ int16_t stride; /* in units */
+ int16_t width; /* in pixels */
+ int16_t height; /* in pixels */
+};
+
+struct ao_pattern {
+ uint8_t pattern[8];
+};
+
+void
+ao_copy(const struct ao_bitmap *dst,
+ int16_t dst_x,
+ int16_t dst_y,
+ int16_t width,
+ int16_t height,
+ const struct ao_bitmap *src,
+ int16_t src_x,
+ int16_t src_y,
+ uint8_t rop);
+
+void
+ao_rect(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ uint32_t fill,
+ uint8_t rop);
+
+void
+ao_pattern(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ const struct ao_pattern *pattern,
+ int16_t pat_x,
+ int16_t pat_y,
+ uint8_t rop);
+
+void
+ao_line(const struct ao_bitmap *dst,
+ int16_t x1,
+ int16_t y1,
+ int16_t x2,
+ int16_t y2,
+ uint32_t fill,
+ uint8_t rop);
+
+void
+ao_text(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ char *string,
+ uint32_t fill,
+ uint8_t rop);
+
+struct ao_font {
+ int width;
+ int height;
+ int ascent;
+ int descent;
+};
+
+extern const struct ao_font ao_font;
+
+#define AO_SHIFT 5
+#define AO_UNIT (1 << AO_SHIFT)
+#define AO_MASK (AO_UNIT - 1)
+#define AO_ALLONES ((uint32_t) -1)
+
+/*
+ * dst
+ * 0 1
+ *
+ * 0 a b
+ * src
+ * 1 c d
+ *
+ * ROP = abcd
+ */
+
+#define AO_CLEAR 0x0 /* 0 */
+#define AO_AND 0x1 /* src AND dst */
+#define AO_AND_REVERSE 0x2 /* src AND NOT dst */
+#define AO_COPY 0x3 /* src */
+#define AO_AND_INVERTED 0x4 /* NOT src AND dst */
+#define AO_NOOP 0x5 /* dst */
+#define AO_XOR 0x6 /* src XOR dst */
+#define AO_OR 0x7 /* src OR dst */
+#define AO_NOR 0x8 /* NOT src AND NOT dst */
+#define AO_EQUIV 0x9 /* NOT src XOR dst */
+#define AO_INVERT 0xa /* NOT dst */
+#define AO_OR_REVERSE 0xb /* src OR NOT dst */
+#define AO_COPY_INVERTED 0xc /* NOT src */
+#define AO_OR_INVERTED 0xd /* NOT src OR dst */
+#define AO_NAND 0xe /* NOT src OR NOT dst */
+#define AO_SET 0xf /* 1 */
+
+#endif /* _AO_DRAW_H_ */
diff --git a/src/draw/ao_draw_int.h b/src/draw/ao_draw_int.h
new file mode 100644
index 00000000..433aa409
--- /dev/null
+++ b/src/draw/ao_draw_int.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_DRAW_INT_H_
+#define _AO_DRAW_INT_H_
+
+static inline uint32_t
+ao_expand(uint32_t bits)
+{
+ return ~((bits & 1)-1);
+}
+
+static inline uint32_t
+ao_xor(uint8_t rop, uint32_t fg)
+{
+ fg = ao_expand(fg);
+
+ return (fg & ao_expand(rop >> 1)) |
+ (~fg & ao_expand(rop >> 3));
+}
+
+static inline uint32_t
+ao_and(uint8_t rop, uint32_t fg)
+{
+ fg = ao_expand(fg);
+
+ return (fg & ao_expand(rop ^ (rop >> 1))) |
+ (~fg & ao_expand((rop>>2) ^ (rop>>3)));
+}
+
+static inline uint32_t
+ao_left(uint32_t bits, int16_t shift) {
+ return bits >> shift;
+}
+
+static inline uint32_t
+ao_right(uint32_t bits, int16_t shift) {
+ return bits << shift;
+}
+
+static inline uint32_t
+ao_right_mask(int16_t x) {
+ if ((AO_UNIT - x) & AO_MASK)
+ return ao_left(AO_ALLONES,(AO_UNIT - x) & AO_MASK);
+ else
+ return 0;
+}
+
+static inline uint32_t
+ao_left_mask(int16_t x) {
+ if (x & AO_MASK)
+ return ao_right(AO_ALLONES, x & AO_MASK);
+ else
+ return 0;
+}
+
+static inline uint32_t
+ao_bits_mask(int16_t x, int16_t w) {
+ return ao_right(AO_ALLONES, x & AO_MASK) &
+ ao_left(AO_ALLONES,(AO_UNIT - (x + w)) & AO_MASK);
+}
+
+#define ao_mask_bits(x,w,l,n,r) { \
+ n = (w); \
+ r = ao_right_mask((x)+n); \
+ l = ao_left_mask(x); \
+ if (l) { \
+ n -= AO_UNIT - ((x) & AO_MASK); \
+ if (n < 0) { \
+ n = 0; \
+ l &= r; \
+ r = 0; \
+ } \
+ } \
+ n >>= AO_SHIFT; \
+}
+
+#define ao_clip(val,min,max) do { \
+ if (val < min) { \
+ val = min; \
+ } else if (val > max) { \
+ val = max; \
+ } \
+ } while (0)
+
+static inline uint32_t
+ao_do_mask_rrop(uint32_t dst, uint32_t and, uint32_t xor, uint32_t mask) {
+ return (dst & (and | ~mask)) ^ (xor & mask);
+}
+
+static inline uint32_t
+ao_do_rrop(uint32_t dst, uint32_t and, uint32_t xor) {
+ return (dst & and) ^ xor;
+}
+
+void
+ao_blt(uint32_t *src_line,
+ int16_t src_stride,
+ int16_t src_x,
+ uint32_t *dst_line,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height,
+ uint8_t rop,
+ uint8_t reverse,
+ uint8_t upsidedown);
+
+void
+ao_solid(uint32_t and,
+ uint32_t xor,
+ uint32_t *dst,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height);
+
+int16_t
+ao_glyph(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ uint8_t c,
+ uint8_t rop);
+
+#endif /* _AO_DRAW_INT_H_ */
diff --git a/src/draw/ao_font.h b/src/draw/ao_font.h
new file mode 100644
index 00000000..5e31dd11
--- /dev/null
+++ b/src/draw/ao_font.h
@@ -0,0 +1,139 @@
+static const uint8_t glyph_bytes[1568] = {
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x04, 0x0e, 0x1f, 0x0e, 0x04, 0x00, 0x0a, 0x05,
+ 0x0a, 0x05, 0x0a, 0x05, 0x00, 0x05, 0x07, 0x05, 0x05, 0x0e, 0x04, 0x04, 0x03, 0x01, 0x03, 0x0d,
+ 0x04, 0x0c, 0x04, 0x03, 0x01, 0x03, 0x06, 0x0a, 0x06, 0x0a, 0x01, 0x01, 0x03, 0x0c, 0x04, 0x0c,
+ 0x04, 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x09,
+ 0x0b, 0x0d, 0x09, 0x04, 0x04, 0x0c, 0x05, 0x05, 0x05, 0x02, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1f, 0x00, 0x04, 0x04, 0x04, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x02, 0x04, 0x08, 0x0e, 0x00, 0x02, 0x04, 0x08,
+ 0x04, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x0e, 0x04, 0x0e,
+ 0x02, 0x00, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x0a, 0x0a,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x00, 0x00, 0x0e, 0x05, 0x0e,
+ 0x14, 0x0e, 0x00, 0x01, 0x09, 0x04, 0x02, 0x09, 0x08, 0x00, 0x00, 0x02, 0x05, 0x02, 0x05, 0x0a,
+ 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x04, 0x00, 0x02,
+ 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, 0x00, 0x05, 0x02, 0x07, 0x02, 0x05, 0x00, 0x00, 0x04, 0x04,
+ 0x1f, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00,
+ 0x02, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x06, 0x09,
+ 0x08, 0x04, 0x02, 0x0f, 0x00, 0x0f, 0x08, 0x06, 0x08, 0x09, 0x06, 0x00, 0x04, 0x06, 0x05, 0x0f,
+ 0x04, 0x04, 0x00, 0x0f, 0x01, 0x07, 0x08, 0x09, 0x06, 0x00, 0x06, 0x01, 0x07, 0x09, 0x09, 0x06,
+ 0x00, 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x06, 0x09, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06,
+ 0x09, 0x09, 0x0e, 0x08, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
+ 0x00, 0x06, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00, 0x02, 0x05, 0x04, 0x02, 0x00, 0x02, 0x00,
+ 0x06, 0x09, 0x0d, 0x0d, 0x01, 0x06, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x07, 0x09,
+ 0x07, 0x09, 0x09, 0x07, 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x00, 0x07, 0x09, 0x09, 0x09,
+ 0x09, 0x07, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x01,
+ 0x00, 0x06, 0x09, 0x01, 0x0d, 0x09, 0x0e, 0x00, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07,
+ 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, 0x09, 0x05, 0x03,
+ 0x03, 0x05, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x09, 0x09,
+ 0x09, 0x00, 0x09, 0x0b, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00,
+ 0x07, 0x09, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x09, 0x09, 0x0b, 0x06, 0x08, 0x07, 0x09,
+ 0x09, 0x07, 0x05, 0x09, 0x00, 0x06, 0x09, 0x02, 0x04, 0x09, 0x06, 0x00, 0x07, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x06, 0x06,
+ 0x00, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x06, 0x06, 0x09, 0x09, 0x00, 0x05,
+ 0x05, 0x05, 0x02, 0x02, 0x02, 0x00, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x00, 0x07, 0x01, 0x01,
+ 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04,
+ 0x07, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
+ 0x03, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x01, 0x01,
+ 0x07, 0x09, 0x09, 0x07, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x08, 0x08, 0x0e, 0x09,
+ 0x09, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04, 0x0a, 0x02, 0x07, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x0e, 0x09, 0x06, 0x01, 0x0e, 0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02,
+ 0x00, 0x03, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x05, 0x02, 0x01, 0x01, 0x05,
+ 0x03, 0x05, 0x09, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x05, 0x0f, 0x09,
+ 0x09, 0x00, 0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x06, 0x00,
+ 0x00, 0x00, 0x07, 0x09, 0x09, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x09, 0x09, 0x0e, 0x08, 0x00, 0x00,
+ 0x07, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x03, 0x0c, 0x07, 0x00, 0x02, 0x02, 0x07, 0x02,
+ 0x02, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x02,
+ 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x00,
+ 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02, 0x00, 0x00, 0x0f, 0x04, 0x02, 0x0f, 0x00, 0x04, 0x02, 0x03,
+ 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x06, 0x02, 0x02,
+ 0x01, 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04,
+ 0x0e, 0x05, 0x05, 0x0e, 0x04, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x11, 0x0e, 0x0a,
+ 0x0e, 0x11, 0x00, 0x05, 0x05, 0x02, 0x07, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04,
+ 0x00, 0x0c, 0x02, 0x06, 0x0a, 0x0c, 0x08, 0x06, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+ 0x11, 0x15, 0x13, 0x15, 0x11, 0x0e, 0x06, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x09, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
+ 0x00, 0x00, 0x0e, 0x11, 0x17, 0x13, 0x13, 0x11, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x1f, 0x00, 0x06, 0x04,
+ 0x02, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x07, 0x01, 0x0e, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x04,
+ 0x06, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x12, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x0c, 0x0e, 0x08, 0x01, 0x01, 0x01, 0x0d, 0x08,
+ 0x04, 0x0c, 0x03, 0x03, 0x02, 0x0b, 0x0c, 0x0e, 0x08, 0x02, 0x00, 0x02, 0x01, 0x05, 0x02, 0x00,
+ 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09,
+ 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f,
+ 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x0e, 0x05, 0x0d, 0x07, 0x05, 0x0d,
+ 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x02, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f,
+ 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07,
+ 0x01, 0x01, 0x0f, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02,
+ 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00,
+ 0x07, 0x0a, 0x0b, 0x0a, 0x0a, 0x07, 0x00, 0x0d, 0x09, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09,
+ 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09,
+ 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06,
+ 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x0e, 0x0d, 0x0d, 0x0b, 0x0b, 0x07, 0x00, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x07, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x07, 0x09, 0x0b, 0x05, 0x01,
+ 0x02, 0x04, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x02, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x0a,
+ 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x05, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x00, 0x0e, 0x09,
+ 0x0d, 0x0a, 0x00, 0x06, 0x06, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x05, 0x0e,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x02, 0x02, 0x04, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04,
+ 0x02, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x02, 0x05, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x05, 0x00, 0x06,
+ 0x0d, 0x03, 0x06, 0x00, 0x01, 0x02, 0x03, 0x02, 0x02, 0x07, 0x00, 0x02, 0x01, 0x03, 0x02, 0x02,
+ 0x07, 0x00, 0x02, 0x05, 0x03, 0x02, 0x02, 0x07, 0x00, 0x05, 0x00, 0x03, 0x02, 0x02, 0x07, 0x00,
+ 0x02, 0x0c, 0x06, 0x09, 0x09, 0x06, 0x00, 0x0a, 0x05, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02, 0x04,
+ 0x06, 0x09, 0x09, 0x06, 0x00, 0x04, 0x02, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06, 0x00, 0x06, 0x09,
+ 0x09, 0x06, 0x00, 0x0a, 0x05, 0x06, 0x09, 0x09, 0x06, 0x00, 0x05, 0x00, 0x06, 0x09, 0x09, 0x06,
+ 0x00, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x0b, 0x07, 0x00, 0x02,
+ 0x04, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x06, 0x00, 0x09,
+ 0x09, 0x09, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x0a,
+ 0x04, 0x02, 0x00, 0x01, 0x07, 0x09, 0x09, 0x07, 0x01, 0x0a, 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02,
+};
+
+static const uint16_t glyph_pos[256] = {
+ 0, 7, 14, 21, 28, 35, 42, 49,
+ 56, 63, 70, 77, 84, 91, 98, 105,
+ 112, 119, 126, 133, 140, 147, 154, 161,
+ 168, 175, 182, 189, 196, 203, 210, 217,
+ 224, 231, 238, 245, 252, 259, 266, 273,
+ 280, 287, 294, 301, 308, 315, 322, 329,
+ 336, 343, 350, 357, 364, 371, 378, 385,
+ 392, 399, 406, 413, 420, 427, 434, 441,
+ 448, 455, 462, 469, 476, 483, 490, 497,
+ 504, 511, 518, 525, 532, 539, 546, 553,
+ 560, 567, 574, 581, 588, 595, 602, 609,
+ 616, 623, 630, 637, 644, 651, 658, 665,
+ 672, 679, 686, 693, 700, 707, 714, 721,
+ 728, 735, 742, 749, 756, 763, 770, 777,
+ 784, 791, 798, 805, 812, 819, 826, 833,
+ 840, 847, 854, 861, 868, 875, 882, 889,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 896, 903, 910, 917, 924, 931, 938, 945,
+ 952, 959, 966, 973, 980, 987, 994, 1001,
+ 1008, 1015, 1022, 1029, 1036, 1043, 1050, 1057,
+ 1064, 1071, 1078, 1085, 1092, 1099, 1106, 1113,
+ 1120, 1127, 1134, 1141, 1148, 1155, 1162, 1169,
+ 1176, 1183, 1190, 1197, 1204, 1211, 1218, 1225,
+ 1232, 1239, 1246, 1253, 1260, 1267, 1274, 1281,
+ 1288, 1295, 1302, 1309, 1316, 1323, 1330, 1337,
+ 1344, 1351, 1358, 1365, 1372, 1379, 1386, 1393,
+ 1400, 1407, 1414, 1421, 1428, 1435, 1442, 1449,
+ 1456, 1463, 1470, 1477, 1484, 1491, 1498, 1505,
+ 1512, 1519, 1526, 1533, 1540, 1547, 1554, 1561,
+};
+
+#define GLYPH_WIDTH 5
+#define GLYPH_HEIGHT 7
+#define GLYPH_ASCENT 6
diff --git a/src/draw/ao_line.c b/src/draw/ao_line.c
new file mode 100644
index 00000000..ed1fc21c
--- /dev/null
+++ b/src/draw/ao_line.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define ao_mask(x,w) (ao_right(AO_ALLONES,(x) & AO_MASK) & \
+ ao_left(AO_ALLONES,(FB_UNIT - ((x)+(w))) & AO_MASK))
+
+
+/* out of clip region codes */
+#define OUT_LEFT 0x08
+#define OUT_RIGHT 0x04
+#define OUT_ABOVE 0x02
+#define OUT_BELOW 0x01
+
+/* major axis for bresenham's line */
+#define X_AXIS 0
+#define Y_AXIS 1
+
+/*
+ * Line clipping. Clip to the box, bringing the coordinates forward while
+ * preserving the actual slope and error
+ *
+ *
+ * X major line, clip X:
+ *
+ * adjust_x = -x;
+ *
+ * e += adjust_x * e1;
+ *
+ * adjust_y = (e + -e3-1) / -e3;
+ *
+ * e -= adjust_y / -e3;
+ *
+ * X major line, clip Y:
+ *
+ * adjust_y = -y;
+
+ *
+ * e -= adjust_y / -e3;
+ *
+ * adjust_x = e / e1;
+ */
+
+
+
+
+static void
+ao_bres(const struct ao_bitmap *dst_bitmap,
+ int16_t signdx,
+ int16_t signdy,
+ int16_t axis,
+ int16_t x1,
+ int16_t y1,
+ int16_t e,
+ int16_t e1,
+ int16_t e3,
+ int16_t len,
+ uint32_t and,
+ uint32_t xor)
+{
+ int16_t stride = dst_bitmap->stride;
+ uint32_t *dst = dst_bitmap->base;
+ uint32_t mask0, mask;
+
+ mask0 = 1;
+ if (signdx < 0)
+ mask0 = ao_right(1, AO_UNIT - 1);
+
+ if (signdy < 0)
+ stride = -stride;
+
+ dst = dst + y1 * stride + (x1 >> AO_SHIFT);
+ mask = ao_right(1, x1 & AO_MASK);
+
+ while (len--) {
+ /* clip each point */
+
+ *dst = ao_do_mask_rrop(*dst, and, xor, mask);
+
+ if (axis == X_AXIS) {
+ if (signdx < 0)
+ mask = ao_left(mask, 1);
+ else
+ mask = ao_right(mask, 1);
+ if (!mask) {
+ dst += signdx;
+ mask = mask0;
+ }
+ e += e1;
+ if (e >= 0) {
+ dst += stride;
+ e += e3;
+ }
+ } else {
+ dst += stride;
+ e += e1;
+ if (e >= 0) {
+ if (signdx < 0)
+ mask = ao_left(mask, 1);
+ else
+ mask = ao_right(mask, 1);
+ if (!mask) {
+ dst += signdx;
+ mask = mask0;
+ }
+ e += e3;
+ }
+ }
+ }
+}
+
+struct ao_cc {
+ int16_t major;
+ int16_t minor;
+ int16_t sign_major;
+ int16_t sign_minor;
+ int16_t e;
+ int16_t e1;
+ int16_t e3;
+ int8_t first;
+};
+
+/* line clipping box */
+struct ao_cbox {
+ int16_t maj1, min1;
+ int16_t maj2, min2;
+};
+
+/* -b <= a, so we need to make a bigger */
+static int16_t
+div_ceil(int32_t a, int16_t b) {
+ return (a + b + b - 1) / b - 1;
+}
+
+static int16_t
+div_floor_plus_one(int32_t a, int16_t b) {
+ return (a + b) / b;
+}
+
+static int8_t
+ao_clip_line(struct ao_cc *c, struct ao_cbox *b)
+{
+ int32_t adjust_major = 0, adjust_minor = 0;
+
+ /* Clip major axis */
+ if (c->major < b->maj1) {
+ if (c->sign_major <= 0)
+ return FALSE;
+ adjust_major = b->maj1 - c->major;
+ } else if (c->major >= b->maj2) {
+ if (c->sign_major >= 0)
+ return FALSE;
+ adjust_major = c->major - (b->maj2-1);
+ }
+
+ /* Clip minor axis */
+ if (c->minor < b->min1) {
+ if (c->sign_minor <= 0)
+ return FALSE;
+ adjust_minor = b->min1 - c->minor;
+ } else if (c->minor >= b->min2) {
+ if (c->sign_minor >= 0)
+ return FALSE;
+ adjust_minor = c->minor - (b->min2-1);
+ }
+
+ /* If unclipped, we're done */
+ if (adjust_major == 0 && adjust_minor == 0)
+ return TRUE;
+
+ /* See how much minor adjustment would happen during
+ * a major clip. This is a bit tricky because line drawing
+ * isn't symmetrical when the line passes exactly between
+ * two pixels, we have to pick which one gets drawn
+ */
+ int32_t adj_min;
+
+ if (!c->first)
+ adj_min = div_ceil(c->e + adjust_major * c->e1, -c->e3);
+ else
+ adj_min = div_floor_plus_one(c->e + adjust_major * c->e1, -c->e3);
+
+ if (adj_min < adjust_minor) {
+ if (c->first)
+ adjust_major = div_ceil(c->e - adjust_minor * c->e3, c->e1);
+ else
+ adjust_major = div_floor_plus_one(c->e - adjust_minor * c->e3, c->e1);
+ } else {
+ adjust_minor = adj_min;
+ }
+
+ c->e += adjust_major * c->e1 + adjust_minor * c->e3;
+
+ c->major += c->sign_major * adjust_major;
+ c->minor += c->sign_minor * adjust_minor;
+
+ return TRUE;
+}
+
+void
+ao_line(const struct ao_bitmap *dst,
+ int16_t x1,
+ int16_t y1,
+ int16_t x2,
+ int16_t y2,
+ uint32_t fill,
+ uint8_t rop)
+{
+ int16_t adx, ady;
+ int16_t e, e1, e2, e3;
+ int16_t signdx = 1, signdy = 1;
+ int16_t axis;
+ int16_t len;
+ struct ao_cc clip_1, clip_2;
+ struct ao_cbox cbox;
+
+ if ((adx = x2 - x1) < 0) {
+ adx = -adx;
+ signdx = -1;
+ }
+ if ((ady = y2 - y1) < 0) {
+ ady = -ady;
+ signdy = -1;
+ }
+
+ if (adx > ady) {
+ axis = X_AXIS;
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+
+ clip_1.major = x1;
+ clip_1.minor = y1;
+ clip_2.major = x2;
+ clip_2.minor = y2;
+ clip_1.sign_major = signdx;
+ clip_1.sign_minor = signdy;
+
+ cbox.maj1 = 0;
+ cbox.maj2 = dst->width;
+ cbox.min1 = 0;
+ cbox.min2 = dst->height;
+ } else {
+ axis = Y_AXIS;
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+
+ clip_1.major = y1;
+ clip_1.minor = x1;
+ clip_2.major = y2;
+ clip_2.minor = x2;
+ clip_1.sign_major = signdy;
+ clip_1.sign_minor = signdx;
+
+ cbox.maj1 = 0;
+ cbox.maj2 = dst->height;
+ cbox.min1 = 0;
+ cbox.min2 = dst->width;
+ }
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ clip_1.first = TRUE;
+ clip_2.first = FALSE;
+ clip_2.e = clip_1.e = e;
+ clip_2.e1 = clip_1.e1 = e1;
+ clip_2.e3 = clip_1.e3 = e3;
+ clip_2.sign_major = -clip_1.sign_major;
+ clip_2.sign_minor = -clip_1.sign_minor;
+
+ if (!ao_clip_line(&clip_1, &cbox))
+ return;
+
+ if (!ao_clip_line(&clip_2, &cbox))
+ return;
+
+ len = clip_1.sign_major * (clip_2.major - clip_1.major) + clip_2.first;
+
+ if (len <= 0)
+ return;
+
+ if (adx > ady) {
+ x1 = clip_1.major;
+ y1 = clip_1.minor;
+ } else {
+ x1 = clip_1.minor;
+ y1 = clip_1.major;
+ }
+ ao_bres(dst,
+ signdx,
+ signdy,
+ axis,
+ x1,
+ y1,
+ clip_1.e, e1, e3, len,
+ ao_and(rop, fill),
+ ao_xor(rop, fill));
+}
diff --git a/src/draw/ao_pattern.c b/src/draw/ao_pattern.c
new file mode 100644
index 00000000..0d1dc765
--- /dev/null
+++ b/src/draw/ao_pattern.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+static inline uint32_t
+ao_pattern_expand(uint8_t v, uint8_t rot)
+{
+ uint32_t r;
+
+ if (rot)
+ v = ao_left(v, 8-rot) | ao_right(v, rot);
+ r = v;
+ return (r << 24) | (r << 16) | (r << 8) | (r);
+}
+
+static inline int
+min(int a, int b) {
+ return a < b ? a : b;
+}
+
+void
+ao_pattern(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ const struct ao_pattern *pattern,
+ int16_t pat_x,
+ int16_t pat_y,
+ uint8_t rop)
+{
+ uint32_t pat[8];
+
+ int16_t x2 = x + width;
+ int16_t y2 = y + height;
+
+ ao_clip(x, 0, dst->width);
+ ao_clip(x2, 0, dst->width);
+ ao_clip(y, 0, dst->height);
+ ao_clip(y2, 0, dst->height);
+
+ if (x < x2 && y < y2) {
+ int xrot = (x - pat_x) & 7;
+ int yrot = (y - pat_y) & 7;
+ int i;
+ int16_t dst_x, dst_y;
+
+ for (i = 0; i < 8; i++)
+ pat[(i + yrot) & 7] = ao_pattern_expand(pattern->pattern[i], xrot);
+ for (dst_y = y; dst_y < y2; dst_y += 8) {
+ int h = min(y2 - dst_y, 8);
+ for (dst_x = x; dst_x < x2; dst_x += 8) {
+ int w = min(x2 - dst_x, 8);
+
+ ao_blt(pat, 1, 0,
+ dst->base + dst_y * dst->stride,
+ dst->stride,
+ dst_x,
+ w, h,
+ rop,
+ 0, 0);
+ }
+ }
+ }
+}
+
diff --git a/src/draw/ao_rect.c b/src/draw/ao_rect.c
new file mode 100644
index 00000000..71fa4aea
--- /dev/null
+++ b/src/draw/ao_rect.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+void
+ao_rect(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ uint32_t fill,
+ uint8_t rop)
+{
+ int16_t x2 = x + width;
+ int16_t y2 = y + height;
+
+ ao_clip(x, 0, dst->width);
+ ao_clip(x2, 0, dst->width);
+ ao_clip(y, 0, dst->height);
+ ao_clip(y2, 0, dst->height);
+
+ if (x < x2 && y < y2) {
+ ao_solid(ao_and(rop, fill),
+ ao_xor(rop, fill),
+ dst->base + y * dst->stride,
+ dst->stride,
+ x,
+ x2 - x,
+ y2 - y);
+ }
+}
+
diff --git a/src/draw/ao_text.c b/src/draw/ao_text.c
new file mode 100644
index 00000000..7ce2a623
--- /dev/null
+++ b/src/draw/ao_text.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+#include "ao_font.h"
+
+const struct ao_font ao_font = {
+ .width = GLYPH_WIDTH,
+ .height = GLYPH_HEIGHT,
+ .ascent = GLYPH_ASCENT,
+ .descent = GLYPH_HEIGHT - GLYPH_ASCENT,
+};
+
+void
+ao_text(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ char *string,
+ uint32_t fill,
+ uint8_t rop)
+{
+ uint32_t src[GLYPH_HEIGHT];
+ char c;
+ int h;
+
+ struct ao_bitmap src_bitmap = {
+ .base = src,
+ .stride = 1,
+ .width = GLYPH_WIDTH,
+ .height = GLYPH_HEIGHT
+ };
+
+ y -= GLYPH_ASCENT;
+
+ rop = (rop & 3) | 0x4;
+
+ if ((fill&1) == 0)
+ rop ^= 3;
+
+ while ((c = *string++)) {
+ const uint8_t *bytes = &glyph_bytes[glyph_pos[(uint8_t) c]];
+
+ for (h = 0; h < GLYPH_HEIGHT; h++)
+ src[h] = bytes[h];
+
+ ao_copy(dst,
+ x, y, GLYPH_WIDTH, GLYPH_HEIGHT,
+ &src_bitmap,
+ 0, 0, rop);
+ x += GLYPH_WIDTH;
+ }
+}
diff --git a/src/draw/font-convert b/src/draw/font-convert
new file mode 100755
index 00000000..1985e418
--- /dev/null
+++ b/src/draw/font-convert
@@ -0,0 +1,150 @@
+#!/usr/bin/nickle
+
+typedef struct {
+ int[] bytes;
+ int width;
+ int height;
+ int encoding;
+ int location;
+} glyph_t;
+
+typedef struct {
+ glyph_t[...] glyphs;
+ int default_char;
+ int ascent;
+} font_t;
+
+glyph_t
+read_glyph(file f)
+{
+ glyph_t glyph = { .encoding = -1, .bytes = (int[...]){}, .width = 0 };
+
+ while (!File::end(f)) {
+ string l = fgets(f);
+
+ string[*] tokens = String::split(l, " ");
+ if (dim(tokens) == 0)
+ continue;
+
+ switch (tokens[0]) {
+ case "ENCODING":
+ glyph.encoding = atoi(tokens[1]);
+ break;
+ case "DWIDTH":
+ glyph.width = atoi(tokens[1]);
+ break;
+ case "BBX":
+ glyph.height = atoi(tokens[2]);
+ break;
+ case "ENDCHAR":
+ return glyph;
+ case "BITMAP":
+ while (!File::end(f)) {
+ string l = fgets(f);
+ if (l == "ENDCHAR")
+ return glyph;
+ glyph.bytes[dim(glyph.bytes)] = atoi(l, 16);
+ }
+ break;
+ }
+ }
+ return glyph;
+}
+
+font_t read_font(file f) {
+ font_t font = { .glyphs = {}, .default_char = -1 };
+ bool in_head = true;
+
+ while (in_head && !File::end(f)) {
+ string l = File::fgets(f);
+
+ string[*] tokens = String::split(l, " ");
+ switch (tokens[0]) {
+ case "DEFAULT_CHAR":
+ font.default_char = atoi(tokens[1]);
+ break;
+ case "FONT_ASCENT":
+ font.ascent = atoi(tokens[1]);
+ break;
+ case "CHARS":
+ in_head = false;
+ break;
+ }
+ }
+ while (!File::end(f)) {
+ glyph_t glyph = read_glyph(f);
+ if (glyph.encoding == -1)
+ break;
+ font.glyphs[dim(font.glyphs)] = glyph;
+ }
+ return font;
+}
+
+int
+flip_byte(int x)
+{
+ int dest = 0;
+
+ for (int i = 0; i < 8; i++)
+ dest |= ((x >> (7 - i)) & 1) << i;
+ return dest;
+}
+
+void print_font(font_t font) {
+ int width = font.glyphs[0].width;
+ int height = font.glyphs[0].height;
+ int[256] pos = { -1 ... };
+ int[...] bytes;
+
+ if (false) {
+ for (int i = 1; i < dim(font.glyphs); i++) {
+ if (font.glyphs[i].width != width ||
+ font.glyphs[i].height != height)
+ {
+ File::fprintf(stderr, "font not constant size, glyph %d is %dx%d\n",
+ font.glyphs[i].encoding, font.glyphs[i].width, font.glyphs[i].height);
+ exit(1);
+ }
+ }
+ }
+
+ if (font.default_char == -1)
+ font.default_char = font.glyphs[0].encoding;
+
+ /* build byte array */
+ for (int i = 0; i < dim(font.glyphs); i++) {
+ pos[font.glyphs[i].encoding] = dim(bytes);
+ for (int b = 0; b < dim(font.glyphs[i].bytes); b++)
+ bytes[dim(bytes)] = font.glyphs[i].bytes[b];
+ }
+
+ /* Fill in default glyph */
+ for (int i = 0; i < dim(pos); i++)
+ if (pos[i] == -1)
+ pos[i] = pos[font.default_char];
+
+ printf("static const uint8_t glyph_bytes[%d] = {", dim(bytes));
+ for (int b = 0; b < dim(bytes); b++) {
+ if ((b & 15) == 0)
+ printf("\n\t");
+ printf("0x%02x, ", flip_byte(bytes[b]));
+ }
+ printf("\n};\n\n");
+
+ printf("static const uint16_t glyph_pos[%d] = {", dim(pos));
+ for (int i = 0; i < dim(pos); i++) {
+ if ((i & 7) == 0)
+ printf("\n\t");
+ printf("%4d, ", pos[i]);
+ }
+ printf("\n};\n\n");
+
+ printf("#define GLYPH_WIDTH %d\n", width);
+ printf("#define GLYPH_HEIGHT %d\n", height);
+ printf("#define GLYPH_ASCENT %d\n", font.ascent);
+}
+
+twixt (file f = File::open(argv[1], "r"); File::close(f)) {
+ font_t font = read_font(f);
+ print_font(font);
+}
diff --git a/src/draw/line.5c b/src/draw/line.5c
new file mode 100644
index 00000000..747768b0
--- /dev/null
+++ b/src/draw/line.5c
@@ -0,0 +1,389 @@
+#!/usr/bin/nickle
+
+autoimport Cairo;
+autoload PRNG;
+
+int
+sign(int x)
+{
+ return x == 0 ? 0 : x < 0 ? -1 : 1;
+}
+
+int X_AXIS = 0;
+int Y_AXIS = 1;
+
+typedef struct {
+ int major;
+ int minor;
+ int sign_major;
+ int sign_minor;
+ int e;
+ int e1;
+ int e3;
+ bool first;
+} clip_context;
+
+typedef struct {
+ int maj1, min1, maj2, min2;
+} clip_box;
+
+typedef struct {
+ int x1, y1, x2, y2;
+} box;
+
+typedef struct {
+ int x, y;
+} point;
+
+typedef struct {
+ int x1, y1, x2, y2;
+ box b;
+ point[] clipped;
+ point[] run;
+} test;
+
+box bounds = { .x1 = 10, .x2 = 30, .y1 = 10, .y2 = 30 };
+
+int
+div_ceil(a, b) {
+ a += b;
+ assert(a >= 0 && b > 0, "bad divide args %d %d\n", a, b);
+ return (a + b - 1) // b - 1;
+}
+
+int
+div_floor_plus_one(a, b) {
+ a += b;
+ assert(a >= 0 && b > 0, "bad divide args %d %d\n", a, b);
+ return a // b;
+}
+
+bool
+clip(*clip_context c, *clip_box b)
+{
+ int adjust_major = 0, adjust_minor = 0;
+
+ /* Clip major axis */
+ if (c->major < b->maj1) {
+ if (c->sign_major <= 0)
+ return false;
+ adjust_major = b->maj1 - c->major;
+ } else if (c->major >= b->maj2) {
+ if (c->sign_major >= 0)
+ return false;
+ adjust_major = c->major - (b->maj2-1);
+ }
+
+ /* Clip minor axis */
+ if (c->minor < b->min1) {
+ if (c->sign_minor <= 0)
+ return false;
+ adjust_minor = b->min1 - c->minor;
+ } else if (c->minor >= b->min2) {
+ if (c->sign_minor >= 0)
+ return false;
+ adjust_minor = c->minor - (b->min2-1);
+ }
+
+ /* If unclipped, we're done */
+ if (adjust_major == 0 && adjust_minor == 0)
+ return true;
+
+ /* See how much minor adjustment would happen during
+ * a major clip. This is a bit tricky because line drawing
+ * isn't symmetrical when the line passes exactly between
+ * two pixels, we have to pick which one gets drawn
+ */
+ int adj_min;
+
+ if (!c->first)
+ adj_min = div_ceil(c->e + adjust_major * c->e1, -c->e3);
+ else
+ adj_min = div_floor_plus_one(c->e + adjust_major * c->e1, -c->e3);
+
+ /* Compare that to the minor clip and pick
+ * the larger amount.
+ */
+ printf ("\tinitial major %d minor %d error %d e1 %d e3 %d\n", c->major, c->minor, c->e, c->e1, c->e3);
+
+ if (adj_min < adjust_minor) {
+ printf("\tminor clip dominates %d < %d. adjust major %d -> ",
+ adj_min, adjust_minor, adjust_major);
+ if (c->first)
+ adjust_major = div_ceil(c->e - adjust_minor * c->e3, c->e1);
+ else
+ adjust_major = div_floor_plus_one(c->e - adjust_minor * c->e3, c->e1);
+ printf("%d\n", adjust_major);
+ } else {
+ printf("\tminor clip dominates %d > %d. adjust minor %d -> ",
+ adj_min, adjust_minor, adjust_minor);
+ adjust_minor = adj_min;
+ printf("%d\n", adjust_minor);
+ }
+
+ c->e += adjust_major * c->e1 + adjust_minor * c->e3;
+
+ c->major += c->sign_major * adjust_major;
+ c->minor += c->sign_minor * adjust_minor;
+
+ printf ("\tadjust major %d adjust minor %d e %d e1 %d e3 %e\n",
+ adjust_major, adjust_minor, c->e, c->e1, c->e3);
+
+ if (c->e >= 0)
+ printf ("error positive e %d e1 %d e3 %d\n",
+ c->e, c->e1, c->e3);
+ if (c->e < c->e3)
+ printf ("error magnitude too large e %d e1 %d e3 %d\n", c->e, c->e1, c->e3);
+
+ return true;
+}
+
+test
+line(int x1, int y1, int x2, int y2, *box b) {
+
+ int dx = x2 - x1;
+ int dy = y2 - y1;
+ int signdx = sign(dx);
+ int signdy = sign(dy);
+ int adx = abs(dx);
+ int ady = abs(dy);
+ int axis;
+ int e, e1, e2, e3;
+ int len;
+ clip_context clip_1, clip_2;
+ clip_box c;
+ bool clipped = false;
+ test t = {
+ .x1 = x1,
+ .y1 = y1,
+ .x2 = x2,
+ .y2 = y2,
+ .b = *b,
+ .clipped = (point[...]) {},
+ .run = (point[...]) {}
+ };
+
+ if (adx >= ady) {
+ axis = X_AXIS;
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ len = adx;
+
+ clip_1.major = x1;
+ clip_1.minor = y1;
+ clip_2.major = x2;
+ clip_2.minor = y2;
+ clip_1.sign_major = signdx;
+ clip_1.sign_minor = signdy;
+
+ c.maj1 = b->x1;
+ c.maj2 = b->x2;
+ c.min1 = b->y1;
+ c.min2 = b->y2;
+ } else {
+ axis = Y_AXIS;
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ len = ady;
+
+ clip_1.major = y1;
+ clip_1.minor = x1;
+ clip_2.major = y2;
+ clip_2.minor = x2;
+ clip_1.sign_major = signdy;
+ clip_1.sign_minor = signdx;
+ c.maj1 = b->y1;
+ c.maj2 = b->y2;
+ c.min1 = b->x1;
+ c.min2 = b->x2;
+ }
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ clip_1.first = true;
+ clip_2.first = false;
+ clip_2.e = clip_1.e = e;
+ clip_2.e1 = clip_1.e1 = e1;
+ clip_2.e3 = clip_1.e3 = e3;
+ clip_2.sign_major = -clip_1.sign_major;
+ clip_2.sign_minor = -clip_1.sign_minor;
+
+ printf ("clip start:\n");
+ if (!clip(&clip_1, &c))
+ clipped = true;
+
+ printf("clip end:\n");
+ if (!clip(&clip_2, &c))
+ clipped = true;
+
+ int clip_len;
+ int clip_x, clip_y;
+ int clip_e;
+ int x_major, x_minor;
+ int y_major, y_minor;
+
+ clip_len = clip_1.sign_major * (clip_2.major - clip_1.major);
+ if (clip_len < 0)
+ clipped = true;
+
+ int x, y;
+
+ if (axis == X_AXIS) {
+ x = clip_1.major;
+ y = clip_1.minor;
+ x_major = clip_1.sign_major;
+ x_minor = 0;
+ y_major = 0;
+ y_minor = clip_1.sign_minor;
+ } else {
+ x = clip_1.minor;
+ y = clip_1.major;
+ x_major = 0;
+ x_minor = clip_1.sign_minor;
+ y_major = clip_1.sign_major;
+ y_minor = 0;
+ }
+
+ clip_e = clip_1.e;
+
+ if (clipped)
+ clip_len = -1;
+
+ while (clip_len-- >= 0) {
+ t.clipped[dim(t.clipped)] = (point) { .x = x, .y = y };
+ x += x_major;
+ y += y_major;
+ clip_e += e1;
+ if (clip_e >= 0) {
+ x += x_minor;
+ y += y_minor;
+ clip_e += e3;
+ }
+ }
+
+ x = x1;
+ y = y1;
+
+ while (len-- >= 0) {
+ if (bounds.x1 <= x && x < bounds.x2 &&
+ bounds.y1 <= y && y < bounds.y2) {
+ t.run[dim(t.run)] = (point) { .x = x, .y = y };
+ }
+ x += x_major;
+ y += y_major;
+ e += e1;
+ if (e >= 0) {
+ x += x_minor;
+ y += y_minor;
+ e += e3;
+ }
+ }
+ return t;
+}
+
+void read_events (Cairo::cairo_t cr)
+{
+ file event = Cairo::open_event(cr);
+
+ while (!File::end(event)) {
+ string event_line = File::fgets(event);
+ if (String::index(event_line, "delete") >= 0)
+ exit(0);
+ }
+}
+
+#for (int y = 0; y < 20; y++)
+
+void
+show(cairo_t cr, test t)
+{
+ rectangle(cr, 0, 0, 40, 40);
+ set_source_rgba(cr, 1, 1, 1, 1);
+ fill(cr);
+
+ set_source_rgba(cr, 0, 1, 0, .2);
+ set_line_width(cr, 0.1);
+ for (int x = 0; x < 40; x++) {
+ move_to(cr, 0, x);
+ line_to(cr, 40, x);
+ move_to(cr, x, 0);
+ line_to(cr, x, 40);
+ }
+ stroke(cr);
+
+ rectangle(cr, t.b.x1, t.b.y1, t.b.x2 - t.b.x1, t.b.y2 - t.b.y1);
+ set_line_width(cr, 0.1);
+ set_source_rgba(cr, 0, 0, 0, 1);
+ stroke(cr);
+
+ move_to(cr, t.x1+.5, t.y1+.5);
+ line_to(cr, t.x2+.5, t.y2+.5);
+ move_to(cr, t.x2, t.y2);
+ line_to(cr, t.x2+1, t.y2+1);
+ move_to(cr, t.x2+1, t.y2);
+ line_to(cr, t.x2, t.y2+1);
+ stroke(cr);
+
+ void pixels(point[] pt) {
+ for (int i = 0; i < dim(pt); i++) {
+ rectangle(cr, pt[i].x, pt[i].y, 1, 1);
+ }
+ fill(cr);
+ }
+
+ set_source_rgba(cr, 1, 0, 0, .5);
+ pixels(t.clipped);
+
+ set_source_rgba(cr, 0, 0, 1, .5);
+ pixels(t.run);
+}
+
+bool
+compare(test t)
+{
+ if (dim(t.clipped) != dim(t.run))
+ return false;
+
+ for (int i = 0; i < dim(t.clipped); i++)
+ if (t.clipped[i] != t.run[i])
+ return false;
+ return true;
+}
+
+void
+doit(int i)
+{
+ int n;
+ *box b = &bounds;
+
+ cairo_t cr = new(800, 800);
+
+ scale(cr, 20, 20);
+
+ for (;;) {
+ PRNG::srandom(i);
+ int x1 = PRNG::randint(40);
+ int x2 = PRNG::randint(40);
+ int y1 = PRNG::randint(40);
+ int y2 = PRNG::randint(40);
+
+ test t = line (x1, y1, x2, y2, &bounds);
+ show(cr, t);
+ if (!compare(t)) {
+ printf("line %d -- %d x %d - %d x %d\n", i, x1, y1, x2, y2);
+ gets();
+ }
+ i++;
+ }
+
+ read_events(cr);
+}
+
+int i = 0;
+if (dim(argv) > 1)
+ i = atoi(argv[1]);
+
+doit(i);