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

Make pixmap merge inside a base class.

Also suport fonts being taken from a string rather, than from file only.
This commit is contained in:
2022-04-18 19:19:16 +02:00
parent 5543105dfb
commit ac17fe8b24
2 changed files with 145 additions and 140 deletions

View File

@@ -58,18 +58,132 @@ class DockApp:
pywmgeneral.open_xwindow(len(sys.argv), sys.argv, self.width, pywmgeneral.open_xwindow(len(sys.argv), sys.argv, self.width,
self.height) self.height)
def prepare_pixmaps(self, background=None, patterns=None, style='3d', def prepare_pixmaps(self):
margin=3): """builds and sets the pixmap of the program.
dockapp_size = (self.width, self.height) the (width)x(height) upper left area is the work area in which we put
what we want to be displayed.
(self.char_width, self.char_height, self.charset_start, the remaining upper right area contains patterns that can be used for
self.charset_width) = helpers.init_pixmap(background, patterns, blanking/resetting portions of the displayed area.
style, dockapp_size[0],
dockapp_size[1], margin, the remaining lower area defines the character set. this is initialized
self.font, using the corresponding named character set. a file with this name must
self.background_color, be found somewhere in the path.
self.palette)
palette is a dictionary
1: of integers <- [0..15] to colors.
2: of single chars to colors.
a default palette is provided, and can be silently overwritten with the
one passed as parameter.
The XBM mask is created out of the XPM.
"""
palette = {}
patterns = self.patterns
font_width = 0
font_height = 0
if self.font:
# Read provided xpm file with font definition
palette, fontdef = helpers.read_xpm(self.font)
font_width = self.charset_width = len(fontdef[0])
font_height = len(fontdef)
if self.font_dimentions is None:
(self.char_width,
self.char_height) = helpers.get_font_char_size(self.font)
else:
self.char_width, self.char_height = self.font_dimentions
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')
else:
palette[' '] = 'None'
palette_values = {v: k for k, v in palette.items()}
# merge defined palette colors to existing one
if self.palette:
for key, color in self.palette.items():
color = helpers.normalize_color(color)
if color in palette_values:
continue
if key not in palette:
palette[key] = color
else:
new_key = helpers.get_unique_key(palette)
palette[new_key] = color
palette_values = {v: k for k, v in palette.items()}
bevel = helpers.get_unique_key(palette)
palette[bevel] = self.bevel_color
# handle bg color
bg = helpers.normalize_color(self.background_color)
key = helpers.get_unique_key(palette)
palette[key] = bg
bg = key
if patterns is None:
patterns = [bg * self.width] * self.height
if self.style == '3d':
ex = bevel
else:
ex = bg
if self.background is None:
self.background = (
[' ' * self.width for item in range(self.margin)] +
[' ' * self.margin + bg * (self.width - 2 * self.margin - 1) +
ex + ' ' * (self.margin)
for item in range(self.margin,
self.height - self.margin - 1)] +
[' ' * self.margin + ex * (self.width - 2 * self.margin) +
' ' * (self.margin)] +
[' ' * self.width for item in range(self.margin)])
elif isinstance(self.background,
list) and not isinstance(self.background[0], str):
nbackground = [[' '] * self.width for i in range(self.height)]
for ((left, top), (right, bottom)) in self.background:
for x in range(left, right+1):
for y in range(top, bottom):
if x < right:
nbackground[y][x] = bg
else:
nbackground[y][x] = ex
nbackground[bottom][x] = ex
self.background = [''.join(item) for item in nbackground]
self.charset_start = self.height + len(patterns)
xpmwidth = max(len(self.background[0]), len(patterns[0]), font_width)
xpmheight = len(self.background) + len(patterns) + font_height
xpm = ([f'{xpmwidth} {xpmheight} {len(palette)} 1'] +
[f'{k}\tc {v}'
for k, v in list(palette.items()) if v == 'None'] +
[f'{k}\tc {v}'
for k, v in list(palette.items()) if v != 'None'] +
[item + ' ' * (xpmwidth - len(item))
for item in self.background + patterns])
if self.font:
xpm += [line + ' ' * (xpmwidth - len(line)) for line in fontdef]
with open('/tmp/foo.xpm', 'w') as fobj:
fobj.write('/* XPM */\nstatic char *_x_[] = {\n')
for item in xpm:
fobj.write(f'"{item}"\n')
fobj.write('};\n')
pywmgeneral.include_pixmap(xpm)
def redraw(self): def redraw(self):
pywmgeneral.redraw_window() pywmgeneral.redraw_window()

View File

@@ -118,8 +118,8 @@ def get_vertical_spacing(num_lines, margin, height, y_offset):
return h / (num_lines - 1) return h / (num_lines - 1)
def read_xpm(filename): def read_xpm(obj):
"""Read the xpm in filename. """Read the xpm in filename or treat object as a string with XPM data.
Return the pair (palette, pixels). Return the pair (palette, pixels).
@@ -129,8 +129,11 @@ def read_xpm(filename):
Raise IOError if we run into trouble when trying to read the file. This Raise IOError if we run into trouble when trying to read the file. This
function has not been tested extensively. do not try to use more than function has not been tested extensively. do not try to use more than
""" """
with open(filename, 'r') as fobj: if obj.startswith('/* XPM */'):
lines = fobj.read().split('\n') lines = [line for line in obj.split('\n')]
else:
with open(obj, 'r') as fobj:
lines = fobj.read().split('\n')
string = ''.join(lines) string = ''.join(lines)
data = [] data = []
@@ -157,132 +160,6 @@ def read_xpm(filename):
return palette, data return palette, data
def init_pixmap(background=None, patterns=None, style='3d', width=64,
height=64, margin=3, font_name=None, bg="black", palette=None):
"""builds and sets the pixmap of the program.
the (width)x(height) upper left area is the work area in which we put
what we want to be displayed.
the remaining upper right area contains patterns that can be used for
blanking/resetting portions of the displayed area.
the remaining lower area defines the character set. this is initialized
using the corresponding named character set. a file with this name must
be found somewhere in the path.
palette is a dictionary
1: of integers <- [0..15] to colors.
2: of single chars to colors.
a default palette is provided, and can be silently overwritten with the
one passed as parameter.
The XBM mask is created out of the XPM.
"""
def get_unique_key(dict_to_check):
for char in range(40, 126):
char = chr(char)
if char not in dict_to_check:
return char
def normalize_color(color):
if color.startswith('#'):
return color
else:
return get_color_code(color)
# Read provided xpm file with font definition
global char_width, char_height
char_width, char_height, fontdef, font_palette = read_font(font_name)
palette_values = {v: k for k, v in font_palette.items()}
if not palette:
palette = font_palette
else:
# make sure we don't overwrite font colors
for key, color in palette.items():
color = normalize_color(color)
if color in palette_values:
continue
if key not in font_palette:
font_palette[key] = color
else:
new_key = get_unique_key(font_palette)
font_palette[new_key] = color
palette_values = {v: k for k, v in font_palette.items()}
palette = font_palette
bevel = get_unique_key('#bebebe')
palette[bevel] = '#bebebe'
# handle bg color
bg = normalize_color(bg)
key = get_unique_key(palette)
palette[key] = bg
bg = key
if patterns is None:
patterns = [bg * width] * height
if style == '3d':
ex = bevel
else:
ex = bg
if background is None:
background = [' ' * width for item in range(margin)] + \
[' ' * margin +
bg * (width - 2 * margin - 1) +
ex + ' ' * (margin)
for item in range(margin, height-margin-1)] + \
[' ' * margin + ex * (width - 2 * margin) + ' ' * (margin)] + \
[' ' * width for item in range(margin)]
elif isinstance(background, list) and not isinstance(background[0], str):
nbackground = [[' ']*width for i in range(height)]
for ((left, top), (right, bottom)) in background:
for x in range(left, right+1):
for y in range(top, bottom):
if x < right:
nbackground[y][x] = bg
else:
nbackground[y][x] = ex
nbackground[bottom][x] = ex
background = [''.join(item) for item in nbackground]
global charset_start, charset_width
charset_start = height + len(patterns)
charset_width = len(fontdef[0])
xpmwidth = max(len(background[0]), len(patterns[0]), len(fontdef[0]))
xpmheight = len(background) + len(patterns) + len(fontdef)
xpm = [
'%s %s %d 1' % (xpmwidth, xpmheight, len(palette)),
] + [
'%s\tc %s' % (k, v)
for k,v in list(palette.items())
if v == 'None'
] + [
'%s\tc %s' % (k,v)
for k,v in list(palette.items())
if v != 'None'
] + [
item+' '*(xpmwidth-len(item))
for item in background + patterns
] + [
line + ' '*(xpmwidth-len(line))
for line in fontdef
]
pywmgeneral.include_pixmap(xpm)
return char_width, char_height, charset_start, charset_width
def redraw_xy(x, y): def redraw_xy(x, y):
"""Redraw a given region of the window.""" """Redraw a given region of the window."""
pywmgeneral.redraw_window_xy(x, y) pywmgeneral.redraw_window_xy(x, y)
@@ -365,3 +242,17 @@ def get_color_code(color_name, rgb_fname=None):
return f'#{r:02x}{g:02x}{b:02x}' return f'#{r:02x}{g:02x}{b:02x}'
return None return None
def get_unique_key(dict_to_check):
for char in range(40, 126):
char = chr(char)
if char not in dict_to_check:
return char
def normalize_color(color):
if color.startswith('#'):
return color
else:
return get_color_code(color)