mirror of
https://github.com/freedoom/freedoom.git
synced 2025-08-31 20:16:55 -04:00
Python 2 is very near end-of-life, and Python3-compatible changes to a few scripts introduced compatibility problems with 2.7 again. It went unnoticed for me since my system symlinks "python" to "python3", but it broke the build on systems where that symlink is still python2. At this point in time, I feel it is worth targetting modern Python and forgetting about 2.7.
151 lines
4.2 KiB
Python
Executable file
151 lines
4.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
# Script to generate text graphics using the "small" (HUD) font.
|
|
#
|
|
|
|
from PIL import Image
|
|
from glob import glob
|
|
import sys
|
|
import re
|
|
|
|
from image_dimensions import *
|
|
from tint import image_tint
|
|
|
|
DIMENSION_MATCH_RE = re.compile(r"(\d+)[x,](\d+)")
|
|
|
|
|
|
class SmallTextGenerator(object):
|
|
def __init__(self):
|
|
self.get_font_widths()
|
|
|
|
# Width of a space character in pixels.
|
|
SPACE_WIDTH = 4
|
|
# Height of the font.
|
|
FONT_HEIGHT = 8
|
|
# Regexp to match dimensions/x,y coordinate pair.
|
|
|
|
def compile_kerning_table(self, kerning_table):
|
|
"""Given a dictionary of kerning patterns, compile Regexps."""
|
|
|
|
result = {}
|
|
for pattern, adjust in kerning_table.items():
|
|
result[re.compile(pattern)] = adjust
|
|
return result
|
|
|
|
def get_font_widths(self):
|
|
charfiles = glob("../stcfn*.png")
|
|
self.char_widths = {}
|
|
for c in range(128):
|
|
filename = self.char_filename(chr(c))
|
|
if filename not in charfiles:
|
|
continue
|
|
w, _ = get_image_dimensions(filename)
|
|
self.char_widths[chr(c)] = w
|
|
|
|
def __contains__(self, c):
|
|
return c in self.char_widths
|
|
|
|
def char_width(self, c):
|
|
return self.char_widths[c]
|
|
|
|
def char_filename(self, c):
|
|
return "../stcfn%03d.png" % (ord(c))
|
|
|
|
def draw_for_text(self, image, text, x, y):
|
|
text = text.upper()
|
|
new_image = image.copy()
|
|
x1, y1 = x, y
|
|
|
|
for c in text:
|
|
if c == "\n":
|
|
y1 += self.FONT_HEIGHT
|
|
x1 = x
|
|
elif c == " ":
|
|
x1 += self.SPACE_WIDTH
|
|
|
|
if c not in self:
|
|
continue
|
|
|
|
filename = self.char_filename(c)
|
|
char_image = Image.open(filename)
|
|
char_image.load()
|
|
new_image = self.paste_image(new_image, char_image, x1, y1)
|
|
x1 += self.char_width(c)
|
|
return new_image
|
|
|
|
def paste_image(self, image, src, x, y):
|
|
int_image = Image.new("RGBA", image.size, (0, 0, 0, 0))
|
|
int_image.paste(src, (x, y))
|
|
new_image = Image.alpha_composite(image, int_image)
|
|
return new_image
|
|
|
|
|
|
def parse_command_line(args):
|
|
if len(args) < 4 or (len(args) % 2) != 0:
|
|
return None
|
|
|
|
result = {"filename": args[0], "background": None, "strings": []}
|
|
|
|
m = DIMENSION_MATCH_RE.match(args[1])
|
|
if not m:
|
|
return None
|
|
result["dimensions"] = (int(m.group(1)), int(m.group(2)))
|
|
|
|
i = 2
|
|
while i < len(args):
|
|
if args[i] == "-background":
|
|
result["background"] = args[i + 1]
|
|
i += 2
|
|
continue
|
|
|
|
m = DIMENSION_MATCH_RE.match(args[i])
|
|
if not m:
|
|
return None
|
|
|
|
xy = (int(m.group(1)), int(m.group(2)))
|
|
|
|
result["strings"].append((xy, args[i + 1]))
|
|
i += 2
|
|
|
|
return result
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
args = parse_command_line(sys.argv[1:])
|
|
|
|
if not args:
|
|
print("Usage: smtextgen <filename> <size> [...text commands...]")
|
|
print("Where each text command looks like:")
|
|
print(" [x,y] [text]")
|
|
sys.exit(0)
|
|
|
|
smallfont = SmallTextGenerator()
|
|
|
|
if args["background"] is not None:
|
|
background_image = Image.open(args["background"])
|
|
background_image.load()
|
|
background_image = background_image.convert("RGBA")
|
|
|
|
image = Image.new("RGBA", args["dimensions"], (0, 0, 0, 0))
|
|
|
|
for xy, string in args["strings"]:
|
|
# Allow contents of a file to be included with special prefix:
|
|
if string.startswith("include:"):
|
|
with open(string[8:]) as f:
|
|
string = f.read()
|
|
|
|
# Allow special notation to indicate an image file to just draw
|
|
# rather than rendering a string.
|
|
if string.startswith("file:"):
|
|
src_image = Image.open(string[5:])
|
|
src_image.load()
|
|
image = smallfont.paste_image(image, src_image, xy[0], xy[1])
|
|
else:
|
|
image = smallfont.draw_for_text(image, string, xy[0], xy[1])
|
|
|
|
if args["background"] is not None:
|
|
image = Image.alpha_composite(background_image, image)
|
|
|
|
image.save(args["filename"])
|