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:
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user