diff options
Diffstat (limited to 'host/matelight/renderers.py')
-rw-r--r-- | host/matelight/renderers.py | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/host/matelight/renderers.py b/host/matelight/renderers.py index 0e223a2..f507513 100644 --- a/host/matelight/renderers.py +++ b/host/matelight/renderers.py @@ -1,11 +1,13 @@ -import numpy as np +import time try: import re2 as re except ImportError: import re +import numpy as np from PIL import Image from pixelterm import xtermcolors from config import * +from font import * default_palette = [ (0x00, 0x00, 0x00), # 0 normal colors @@ -24,17 +26,19 @@ default_palette = [ (0xff, 0x00, 0xff), # 13 (0x00, 0xff, 0xff), # 14 (0xff, 0xff, 0xff)] # 15 +default_colors = (default_palette[8], default_palette[0]) class CharGenerator: def __init__(self, seq=None, lg=None, text=''): - settings = False, False, False, default_palette[8], default_palette[0] + settings = False, False, False, default_colors if lg: - settings = lg,bold, lg.blink, lg.underscore, lg.fg, lg.bg - self.bold, self.blink, self.underscore, self.fg, self.bg = settings + settings = lg.bold, lg.blink, lg.underscore, (lg.fg, lg.bg) + self.bold, self.blink, self.underscore, (self.fg, self.bg) = settings self.text = text - self.parse_escape_sequence(seq) + if seq: + self.parse_escape_sequence(seq) - def parse_escape_sequence(seq): + def parse_escape_sequence(self, seq): codes = list(map(int, seq[2:-1].split(';'))) fg, bg, reverse, i = self.fg, self.bg, False, 0 while i<len(codes): @@ -49,7 +53,7 @@ class CharGenerator: elif a == 49: bg = (0,0,0) elif a == 0: - fg, bg = (0,0,0), (0,0,0) + fg, bg = default_colors self.bold, self.blink, self.underscore = False, False, False elif a in range(30, 38): fg = default_palette[a-30] @@ -57,7 +61,7 @@ class CharGenerator: fg = default_palette[a-90+8] elif a in range(40, 48): bg = default_palette[a-40] - elif a in range(100, 108): + elif a in range(101, 108): bg = default_palette[a-100+8] elif a == 7: reverse = True @@ -68,20 +72,22 @@ class CharGenerator: elif a == 1: # Literally "bright", not bold. self.bold = True i += 1 - fg, bg = bg, fg if reverse else fg, bg + fg, bg = (bg, fg) if reverse else (fg, bg) self.fg, self.bg = fg, bg def generate_char(self, c, now): - fg, bg = self.bg, self.bg if self.blink and now%1.0 < 0.3 else self.fg, self.bg - glyph = font.glyphs_by_codepoint[c] + fg, bg = (self.bg, self.fg) if self.blink and now%1.0 < 0.3 else (self.fg, self.bg) + glyph = FONT.glyphs_by_codepoint[ord(c)] # Please forgive the string manipulation below. lookup = {'0': bg, '1': fg} - return [ list(map(lookup.get, FONT_PADDED_BINARY(int(row, 16)))) for row in glyph.get_data() ] + FONT_PADDED_BINARY = ('{:0'+str(glyph.bbW)+'b}').format + FONT_Y_PAD = [[bg]*glyph.bbW]*(DISPLAY_HEIGHT-FONT_HEIGHT) + return np.swapaxes(np.array([ list(map(lookup.get, FONT_PADDED_BINARY(int(row, 16))[:glyph.bbW])) for row in glyph.get_data() ] + FONT_Y_PAD, dtype=np.uint8), 0, 1) def generate(self, now): chars = [self.generate_char(c, now) for c in self.text] # This refers to inter-letter spacing - space = np.zeros((LETTER_SPACING, DISPLAY_HEIGHT, 3)) + space = np.zeros((LETTER_SPACING, DISPLAY_HEIGHT, 3), dtype=np.uint8) spaces = [space]*(len(chars)-1) everything = chars + spaces everything[::2] = chars @@ -96,25 +102,26 @@ class TextRenderer: """ generators = [] current_generator = CharGenerator() - for esc, char in r'(\x1B\[[0-9;]+m)|(.)'.finditer(text): + for match in re.finditer('(\x1B\[[0-9;]+m)|(.)', text): + esc, char = match.groups() if esc: if current_generator.text != '': generators.append(current_generator) current_generator = CharGenerator(esc, current_generator) elif char: current_generator.text += char - self.generators = generators + [current_generator] - - def frames(self, start): - now = time.time() - zeros = [np.zeros((DISPLAY_WIDTH, DISPLAY_HEIGHT, 3))] + generators = generators + [current_generator] + # Generate the actual frame buffer + zeros = [np.zeros((DISPLAY_WIDTH, DISPLAY_HEIGHT, 3), dtype=np.uint8)] # Pad the array with one screen's worth of zeros on both sides so the text fully scrolls through. - raw = np.concatenate([zeros]+[g.generate(now) for g in generators]+[zeros]) - w,h,_ = raw.size - for i in range(DISPLAY_WIDTH+w, 0, -1): - frame = raw[i:i+DISPLAY_WIDTH, :, :] + now = time.time() + self.raw = np.concatenate(zeros+[g.generate(now) for g in generators]+zeros) + + def frames(self): + w,h,_ = self.raw.shape + for i in range(0, w-DISPLAY_WIDTH, 2): + frame = self.raw[i:i+DISPLAY_WIDTH, :, :] yield frame, 1/DEFAULT_SCROLL_SPEED - raw = np.concatenate([zeros]+[g.generate(now) for g in generators]+[zeros]) class ImageRenderer: def __new__(cls, image_data): |