mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-15 23:00:15 -07:00
93 lines
3.7 KiB
Python
93 lines
3.7 KiB
Python
'Things used by Text Printing feature. License CC0-1.0-only'
|
|
|
|
from .pf2 import PF2S
|
|
|
|
class TextCanvas():
|
|
'Canvas for text printing, requires PF2 lib'
|
|
broken: bool = False
|
|
width: int
|
|
height: int
|
|
canvas: bytearray = None
|
|
rtl: bool
|
|
wrap: bool
|
|
scale: int
|
|
pf2 = None
|
|
def __init__(self, width, *, wrap=False, rtl=False,
|
|
font_path='font.pf2', font_data_io=None, scale=1):
|
|
if font_data_io is None:
|
|
font_data_io = open(font_path, 'rb')
|
|
self.pf2 = PF2S(font_data_io, scale=scale)
|
|
if self.pf2.broken:
|
|
self.broken = True
|
|
return
|
|
self.width = width
|
|
self.wrap = wrap
|
|
self.rtl = rtl
|
|
self.scale = scale
|
|
self.height = self.pf2.max_height + self.pf2.descent
|
|
self.flush_canvas()
|
|
def flush_canvas(self):
|
|
'Flush the canvas, returning the canvas data'
|
|
if self.canvas is None:
|
|
pbm_data = None
|
|
else:
|
|
pbm_data = bytearray(self.canvas)
|
|
self.canvas = bytearray(self.width * self.height // 8)
|
|
return pbm_data
|
|
def puttext(self, text):
|
|
''' Put the specified text to canvas.
|
|
It's a generator, will `yield` the data produced, per line.
|
|
'''
|
|
text = text.replace('\t', ' ' * 4)
|
|
canvas_length = len(self.canvas)
|
|
pf2 = self.pf2
|
|
current_width = 0
|
|
last_space_at = -1
|
|
width_at_last_space = 0
|
|
break_points = set()
|
|
characters = {}
|
|
for i, s in enumerate(text):
|
|
if s not in characters:
|
|
characters[s] = pf2[s]
|
|
char = characters[s]
|
|
if s == ' ':
|
|
last_space_at = i
|
|
width_at_last_space = current_width
|
|
if (current_width > self.width and
|
|
last_space_at != -1):
|
|
break_points.add(last_space_at)
|
|
current_width -= width_at_last_space
|
|
if s == '\n':
|
|
current_width = 0
|
|
continue
|
|
current_width += pf2.point_size // 2 # + char.x_offset
|
|
current_width = 0
|
|
for i, s in enumerate(text):
|
|
char = characters[s]
|
|
if ((self.wrap and i in break_points) or s == '\n' or
|
|
current_width + char.width > self.width):
|
|
# print(current_width, end=' ')
|
|
yield self.flush_canvas()
|
|
current_width = 0
|
|
if s in ' ':
|
|
continue
|
|
if ord(s) in range(0x00, 0x20): # glyphs that should not be printed out
|
|
continue
|
|
for x in range(char.width):
|
|
for y in range(char.height):
|
|
rtl_current_width = self.width - current_width - char.width - 1
|
|
target_x = x + char.x_offset
|
|
target_y = pf2.ascent + (y - char.height) - char.y_offset
|
|
canvas_byte = (self.width * target_y + current_width + target_x) // 8
|
|
canvas_bit = 7 - (self.width * target_y + current_width + target_x) % 8
|
|
if self.rtl:
|
|
canvas_byte = (self.width * target_y + rtl_current_width + target_x) // 8
|
|
canvas_bit = 7 - (self.width * target_y + rtl_current_width + target_x) % 8
|
|
else:
|
|
canvas_byte = (self.width * target_y + current_width + target_x) // 8
|
|
canvas_bit = 7 - (self.width * target_y + current_width + target_x) % 8
|
|
if canvas_byte < 0 or canvas_byte >= canvas_length:
|
|
continue
|
|
self.canvas[canvas_byte] |= char.get_bit(x, y) << canvas_bit
|
|
current_width += char.device_width
|