1
0
mirror of https://github.com/gryf/wmdocklib.git synced 2025-12-18 12:00:20 +01:00

Added ability to define multiple bitmap font sources.

By defining attribute "fonts" in the DockApp inherited class, now there
is possible for adding more than one character sets.
This commit is contained in:
2022-05-03 18:40:53 +02:00
parent 1085074596
commit dca4bf5440
2 changed files with 93 additions and 59 deletions

View File

@@ -82,7 +82,7 @@ So below is the example for displaying random number:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.font = FONTS self.fonts = [wmdocklib.BitmapFonts(FONTS, self.dimensions)]
def run(self): def run(self):
self.prepare_pixmaps() self.prepare_pixmaps()
@@ -91,7 +91,7 @@ So below is the example for displaying random number:
def main_loop(self): def main_loop(self):
while True: while True:
self.add_string(f'{random.randint(0, 999):3}', 1, 1) self.fonts[0].add_string(f'{random.randint(0, 999):3}', 1, 1)
self.redraw() self.redraw()
time.sleep(0.1) time.sleep(0.1)

View File

@@ -11,22 +11,15 @@ class DockApp:
width = 64 width = 64
height = 64 height = 64
margin = 3 margin = 3
x_offset = 3
y_offset = 3
palette = {"1": "black", palette = {"1": "black",
"2": "white"} "2": "white"}
background_color = 'black' background_color = 'black'
style = '3d' style = '3d'
bevel_color = '#bebebe' bevel_color = '#bebebe'
font_dimentions = None
def __init__(self, args=None): def __init__(self, args=None):
self.args = args self.args = args
self.charset_start = None self.fonts = []
self.charset_width = 0
self.char_width = None
self.char_height = None
self.font = None
self.background = None self.background = None
self.patterns = None self.patterns = None
self._debug = False self._debug = False
@@ -64,17 +57,18 @@ class DockApp:
def prepare_pixmaps(self): def prepare_pixmaps(self):
"""builds and sets the pixmap of the program. """builds and sets the pixmap of the program.
the (width)x(height) upper left area is the work area in which we put The (width)x(height) upper left area is the work area in which we put
what we want to be displayed. what we want to be displayed. Also, nothing prevents us from putting
anything on the right of that image and do the copying from there.
the remaining upper right area contains patterns that can be used for The remaining upper right area contains patterns that can be used for
blanking/resetting portions of the displayed area. blanking/resetting portions of the displayed area.
the remaining lower area defines the character set. this is initialized The remaining lower area defines the character sets. This is
using the corresponding named character set. a file with this name must initialized using the corresponding named character set. Fonts
be found somewhere in the path. definition are holded by corresponding instances of BitmapFonts class.
palette is a dictionary Palette is a dictionary
1: of integers <- [0..15] to colors. 1: of integers <- [0..15] to colors.
2: of single chars to colors. 2: of single chars to colors.
@@ -85,37 +79,22 @@ class DockApp:
""" """
palette = {} palette = {}
patterns = self.patterns patterns = self.patterns
font_width = 0 fonts = []
font_height = 0
if self.background: if self.background:
palette, background = helpers.read_xpm(self.background) palette, background = helpers.read_xpm(self.background)
if self.font: if self.fonts:
# Read provided xpm file with font definition for font in self.fonts:
font_palette, fontdef = helpers.read_xpm(self.font) if not palette:
font_width = self.charset_width = len(fontdef[0]) palette = font.palette
font_height = len(fontdef) fonts.append(font.bitmap)
if not palette: else:
palette = font_palette # merge background and font_palette and remap characters
else: palette, fontdef = helpers.merge_palettes(palette,
# merge background and font_palette and remap characters font.palette,
palette, fontdef = helpers.merge_palettes(palette, font.bitmap)
font_palette, fonts.append(fontdef)
fontdef)
# user provided font dimension tuple have precedence
if self.font_dimentions is not None:
self.char_width, self.char_height = self.font_dimentions
else:
(self.char_width,
self.char_height) = helpers.get_font_char_size(self.font)
if self.char_width is None:
# font filename doesn't provide hints regarding font size
raise ValueError('Cannot infer font size either from font '
'name (does not contain wxh), or from '
'font_dimentions attribute')
if not palette: if not palette:
palette[' '] = 'None' palette[' '] = 'None'
@@ -163,10 +142,15 @@ class DockApp:
' ' * (self.margin)] + ' ' * (self.margin)] +
[' ' * self.width for item in range(self.margin)]) [' ' * self.width for item in range(self.margin)])
self.charset_start = self.height + len(patterns) charset_start = self.height + len(patterns)
for font in self.fonts:
font.update(charset_start)
charset_start += font.charset_height
xpmwidth = max(len(background[0]), len(patterns[0]), font_width) xpmwidth = max(len(background[0]), len(patterns[0]),
xpmheight = len(background) + len(patterns) + font_height max([f.charset_width for f in self.fonts]))
xpmheight = (len(background) + len(patterns) +
sum([f.charset_height for f in self.fonts]))
xpm = ([f'{xpmwidth} {xpmheight} {len(palette)} 1'] + xpm = ([f'{xpmwidth} {xpmheight} {len(palette)} 1'] +
[f'{k}\tc {v}' [f'{k}\tc {v}'
@@ -175,8 +159,9 @@ class DockApp:
for k, v in list(palette.items()) if v != 'None'] + for k, v in list(palette.items()) if v != 'None'] +
[item + ' ' * (xpmwidth - len(item)) [item + ' ' * (xpmwidth - len(item))
for item in background + patterns]) for item in background + patterns])
if self.font: if self.fonts:
xpm += [line + ' ' * (xpmwidth - len(line)) for line in fontdef] xpm += [f"{line:{xpmwidth}}" for x in self.fonts
for line in x.bitmap]
if self._debug: if self._debug:
fd, fname = tempfile.mkstemp(suffix='.xpm') fd, fname = tempfile.mkstemp(suffix='.xpm')
@@ -190,6 +175,41 @@ class DockApp:
pywmgeneral.include_pixmap(xpm) pywmgeneral.include_pixmap(xpm)
def redraw(self):
pywmgeneral.redraw_window()
class BitmapFonts:
"""
A class for representing a character set.
"""
x_offset = 3
y_offset = 3
def __init__(self, font_data, dimensions=None):
"""
Load and initialize font data. font_data might be either string.
"""
self.palette = None
self.bitmap = None
self.charset_width = None
self.charset_height = None
self.charset_start = None
self.width = 0
self.height = 0
self.font_dimentions = (0, 0)
if dimensions:
self.font_dimentions = dimensions
self._load_font(font_data)
self._set_font_size(font_data)
def update(self, charset_start):
"""
Update information on font position in merged pixmap, so that methods
add_string/add_char can calculate char position correctly.
"""
self.charset_start = charset_start
def add_char(self, ch, x, y, drawable=None): def add_char(self, ch, x, y, drawable=None):
"""Paint the character ch at position x, y in the window. """Paint the character ch at position x, y in the window.
@@ -199,22 +219,22 @@ class DockApp:
""" """
# linelength is the amount of bits the character set uses on each row. # linelength is the amount of bits the character set uses on each row.
linelength = self.charset_width - (self.charset_width % linelength = self.charset_width - (self.charset_width %
self.char_width) self.width)
# pos is the horizontal index of the box containing ch. # pos is the horizontal index of the box containing ch.
pos = (ord(ch)-32) * self.char_width pos = (ord(ch)-32) * self.width
# translate pos into ch_x, ch_y, rolling back and down each linelength # translate pos into ch_x, ch_y, rolling back and down each linelength
# bits. character definition start at row 64, column 0. # bits. character definition start at row 64, column 0.
ch_y = int((pos / linelength)) * self.char_height + self.charset_start ch_y = int((pos / linelength)) * self.height + self.charset_start
ch_x = pos % linelength ch_x = pos % linelength
target_x = x + self.x_offset target_x = x + self.x_offset
target_y = y + self.y_offset target_y = y + self.y_offset
if drawable is None: if drawable is None:
pywmgeneral.copy_xpm_area(ch_x, ch_y, self.char_width, pywmgeneral.copy_xpm_area(ch_x, ch_y, self.width,
self.char_height, target_x, target_y) self.height, target_x, target_y)
else: else:
drawable.xCopyAreaFromWindow(ch_x, ch_y, self.char_width, drawable.xCopyAreaFromWindow(ch_x, ch_y, self.width,
self.char_height, target_x, target_y) self.height, target_x, target_y)
def add_string(self, string, x, y, drawable=None): def add_string(self, string, x, y, drawable=None):
"""Add a string at the given x and y positions. """Add a string at the given x and y positions.
@@ -223,7 +243,21 @@ class DockApp:
last_width = 0 last_width = 0
for letter in string: for letter in string:
self.add_char(letter, x + last_width, y, drawable) self.add_char(letter, x + last_width, y, drawable)
last_width += self.char_width last_width += self.width
def redraw(self): def _set_font_size(self, font_data):
pywmgeneral.redraw_window() if self.font_dimentions[0]:
self.width, self.height = self.font_dimentions
else:
self.width, self.height = helpers.get_font_char_size(font_data)
if not self.width:
# font filename doesn't provide hints regarding font size
raise ValueError('Cannot infer font size either from font '
'name (does not contain wxh), or from '
'font_dimentions attribute')
def _load_font(self, font_data):
self.palette, self.bitmap = helpers.read_xpm(font_data)
self.charset_width = len(self.bitmap[0])
self.charset_height = len(self.bitmap)