1
+ import numpy as np
2
+
3
+ class AnsiGraphics :
4
+ """
5
+ This class manages ansi fonts and colours.
6
+ """
7
+
8
+ # VGA Palette
9
+ VGA_PAL = [
10
+ np .array ([0 , 0 , 0 ]) / 255.0 ,
11
+ np .array ([170 , 0 , 0 ]) / 255.0 ,
12
+ np .array ([0 , 170 , 0 ]) / 255.0 ,
13
+ np .array ([170 , 85 , 0 ]) / 255.0 ,
14
+ np .array ([0 , 0 , 170 ]) / 255.0 ,
15
+ np .array ([170 , 0 , 170 ]) / 255.0 ,
16
+ np .array ([0 , 170 , 170 ]) / 255.0 ,
17
+ np .array ([170 , 170 , 170 ]) / 255.0 ,
18
+ np .array ([85 , 85 , 85 ]) / 255.0 ,
19
+ np .array ([255 , 85 , 85 ]) / 255.0 ,
20
+ np .array ([85 , 255 , 85 ]) / 255.0 ,
21
+ np .array ([255 , 255 , 85 ]) / 255.0 ,
22
+ np .array ([85 , 85 , 255 ]) / 255.0 ,
23
+ np .array ([255 , 85 , 255 ]) / 255.0 ,
24
+ np .array ([85 , 255 , 255 ]) / 255.0 ,
25
+ np .array ([255 , 255 , 255 ]) / 255.0
26
+ ];
27
+
28
+ def __init__ (self , font_file ):
29
+ """
30
+ Reads the font to use and prepares it for usage.
31
+ Fonts are files with a sequence of bits specifying 8x16 characters.
32
+ """
33
+ # Read the font
34
+ f = open ("vga.fnt" , "rb" )
35
+ in_bits = []
36
+ try :
37
+ byte = f .read (1 )
38
+ while len (byte ) != 0 :
39
+ bin_str = bin (int .from_bytes (byte , 'little' ))[2 :]
40
+ for bit in bin_str .zfill (8 ):
41
+ in_bits .append (bit )
42
+ byte = f .read (1 )
43
+ finally :
44
+ f .close ()
45
+
46
+ # Split into chars
47
+ self .font_chars = []
48
+ for i in range (0 , 256 ):
49
+ char_bits = np .array (in_bits [i * 16 * 8 : (i + 1 ) * 16 * 8 ])
50
+ char_bits = char_bits .reshape (16 , 8 ).astype (float )
51
+ self .font_chars .append (char_bits )
52
+
53
+ # It's 2018 and memory is cheap, so lets precompute every possible fore/back/char combination
54
+ self .colour_chars = []
55
+ for char_idx in range (0 , 256 ):
56
+ fg_chars = []
57
+ for fg_idx in range (0 , 16 ):
58
+ bg_chars = []
59
+ for bg_idx in range (0 , 16 ):
60
+ char_base = self .font_chars [char_idx ][:]
61
+ char_col = np .zeros ((char_base .shape [0 ], char_base .shape [1 ], 3 ))
62
+ char_col [np .where (char_base == 1 )] = AnsiGraphics .VGA_PAL [fg_idx ]
63
+ char_col [np .where (char_base == 0 )] = AnsiGraphics .VGA_PAL [bg_idx ]
64
+ bg_chars .append (char_col )
65
+ fg_chars .append (bg_chars )
66
+ self .colour_chars .append (fg_chars )
67
+
68
+ def vga_colour (self , pal_idx ):
69
+ """
70
+ Returns the VGA palette colour with the given index as an RGP triplet.
71
+ """
72
+ return AnsiGraphics .VGA_PAL [idx ]
73
+
74
+ def char_bitmap (self , char_idx ):
75
+ """
76
+ Returns the font character with the given index as a binary bitmap.
77
+ """
78
+ return self .font_chars [idx ]
79
+
80
+ def coloured_char (self , char_idx , fg_idx , bg_idx ):
81
+ """
82
+ Returns the font character with the given index and given fore and back colours as an RGP bitmap.
83
+ """
84
+ return self .colour_chars [char_idx ][fg_idx ][bg_idx ]
85
+
0 commit comments