doomcc/dcc/text.py

88 lines
3 KiB
Python
Raw Normal View History

import dcc.config
import dcc.doom_base
import sys
import textwrap
import wand.drawing
import wand.image
2025-06-15 13:31:32 -04:00
def draw_text(self, img, text, font_size=64, wrap_dist=0.75):
textlines = text.splitlines()
2025-06-15 13:31:32 -04:00
with wand.drawing.Drawing() as draw:
draw.font = self.thumbnail_font
2025-06-15 13:31:32 -04:00
draw.font_size = font_size
draw.fill_color = wand.color.Color(self.thumbnail_text_fill)
draw.stroke_color = wand.color.Color(self.thumbnail_text_stroke)
2025-06-15 13:31:32 -04:00
draw.stroke_width = font_size * 5 / 32
draw.text_interline_spacing = -font_size / 4
target_width = wrap_dist * img.width
def eval_metrics(txt):
metrics = draw.get_font_metrics(img, wrapped_text, True)
return (metrics.text_width, metrics.text_height)
for idx, wrapped_text in enumerate(textlines):
while True:
width, height = eval_metrics(wrapped_text)
if width <= target_width:
break
columns = len(wrapped_text)
while columns > 0:
columns -= 1
wrapped_text = '\n'.join(
textwrap.wrap(wrapped_text, columns)
)
wrapped_width, _ = eval_metrics(wrapped_text)
if wrapped_width <= target_width:
break
if columns == 0:
raise Exception(
"couldn't calculate text wrapping; "
+ f"final attempt was {wrapped_text}"
)
textlines[idx] = wrapped_text
wrapped_text = '\n'.join(textlines)
draw.text(5, int(draw.font_size) + 5, wrapped_text)
2025-06-15 13:31:32 -04:00
draw(img)
draw.stroke_color = wand.color.Color("none")
draw.stroke_width = 0
draw.text(5, int(draw.font_size)+5, wrapped_text)
2025-06-15 13:31:32 -04:00
draw(img)
2025-07-06 14:33:42 -04:00
dcc.config.Base.draw_text = draw_text
2025-07-06 14:33:42 -04:00
class Text(dcc.doom_base.WadMap):
2025-06-15 13:31:32 -04:00
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
parser.add_argument("--nomap", action="store_true")
parser.add_argument("--demotype", default="UV-Max Demo")
parser.add_argument("--stdin", "--stdin-only", action="store_true")
2025-06-15 13:31:32 -04:00
return parser
2025-06-15 13:31:32 -04:00
def take_action(self, parsed_args):
text = None
if not parsed_args.stdin:
map_names = self._config.get("map_names")
if map_names is not None:
text = map_names.get(f"map{parsed_args.map}")
if text is None:
text = sys.stdin.read().rstrip()
2025-06-15 13:31:32 -04:00
if not parsed_args.nomap:
text = "MAP{}: {}".format(parsed_args.map, text)
text = "{}\n{}".format(text, parsed_args.demotype)
with wand.image.Image(
height=self.thumbnail_height,
width=self.thumbnail_width
2025-06-15 13:31:32 -04:00
) as img:
self.draw_text(
img, text,
)
2025-06-15 13:31:32 -04:00
img.trim()
img.reset_coords()
img.save(filename=self.text_thumb_path())