|
#!/usr/bin/env python3 |
|
|
|
""" |
|
Create samples of each truetype font from the specified directory as |
|
a single html page with png images representing glyphs from each font. |
|
|
|
Original source: https://gist.github.com/sigsergv/9309ad0e3b3c2be65aa58c37d259f580 |
|
Author: Sergey Stolyarov <[email protected]> |
|
License: Public Domain |
|
Requirements: PILLOW |
|
""" |
|
|
|
import argparse |
|
import os |
|
from sys import exit |
|
from PIL import Image, ImageDraw, ImageFont |
|
from datetime import datetime |
|
|
|
p = argparse.ArgumentParser() |
|
p.add_argument('--fonts-dir', dest='fonts_dir', required=True, help='Path to directory with truetype fonts.') |
|
p.add_argument('--output-dir', dest='output_dir', required=True, |
|
help='Path to output directory where index.html and a set of .png images to be created.') |
|
args = p.parse_args() |
|
|
|
SAMPLE_STRING = '''0123456789!@#$%^&*(){}[] |
|
THE FIVE BOXING WIZARDS JUMP QUICKLY. |
|
the five boxing wizards jump quickly. |
|
ЮЖНО-ЭФИОПСКИЙ ГРАЧ УВЁЛ МЫШЬ ЗА ХОБОТ НА СЪЕЗД ЯЩЕРИЦ. |
|
южно-эфиопский грач увёл мышь за хобот на съезд ящериц. |
|
''' |
|
|
|
fonts_dir = args.fonts_dir |
|
out_dir = args.output_dir |
|
|
|
if not os.path.isdir(fonts_dir): |
|
print(f'Fonts directory `{fonts_dir}` not found!') |
|
exit(1) |
|
|
|
if not os.path.isdir(out_dir): |
|
print(f'Output directory `{out_dir}` not found!') |
|
exit(1) |
|
|
|
text_color = (0, 0, 0) |
|
bg_color = (255, 255, 255) |
|
font_size = 48 |
|
|
|
html = '''<html> |
|
<head> |
|
<title>Fonts samples</title> |
|
<style> |
|
body { |
|
background-color: white; |
|
color: black; |
|
font-family: sans-serif; |
|
} |
|
h3 { |
|
border-style: none none solid none; |
|
border-color: black; |
|
border-width: 3px; |
|
} |
|
div.fit img{ |
|
max-width: 100%; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
''' |
|
|
|
html += '<h1>Index of truetype fonts</h1>\n' |
|
html += f'<div>TrueType directory: {fonts_dir}</div>\n' |
|
today = datetime.today().isoformat() |
|
html += f'<div>Generated on: {today}</div>\n' |
|
|
|
fonts_html_block = '' |
|
ttf_num = 0 |
|
font_files = sorted(os.listdir(fonts_dir), key=lambda x: x.lower()) |
|
|
|
fonts = [] |
|
for font_file in os.listdir(fonts_dir): |
|
font_file = os.path.join(fonts_dir, font_file) |
|
if not os.path.isfile(font_file): |
|
# skipping non-files |
|
continue |
|
try: |
|
font = ImageFont.truetype(font_file, font_size) |
|
except: |
|
print(f'`{font_file}` is not a valid truetype font! skipping') |
|
continue |
|
font_name, font_style = font.getname() |
|
fonts.append({ |
|
'font_file': font_file, |
|
'font_family': f'{font_name} {font_style}' |
|
}) |
|
|
|
fonts.sort(key=lambda x:x['font_family'].lower()) |
|
|
|
for ind, v in enumerate(fonts): |
|
font_file = v['font_file'] |
|
fonts_html_block += f'<h3>{v['font_family']}</h3>\n' |
|
|
|
font = ImageFont.truetype(font_file, font_size) |
|
|
|
# calculate text box |
|
dummy_image = Image.new('RGB', (1, 1)) |
|
dummy_draw = ImageDraw.Draw(dummy_image) |
|
bbox = dummy_draw.textbbox((0, 0), SAMPLE_STRING, font=font) |
|
width = bbox[2] - bbox[0] |
|
height = bbox[3] - bbox[1] |
|
|
|
# create target image |
|
image_file = f'img_{ind}.png' |
|
image_path = os.path.join(out_dir, image_file) |
|
image = Image.new('RGB', (width + 20, height + 20), color=bg_color) |
|
draw = ImageDraw.Draw(image) |
|
draw.text((0, 0), SAMPLE_STRING, font=font, fill=text_color) |
|
image.save(image_path, 'png') |
|
|
|
# append to html |
|
fonts_html_block += f'<div class="fit"><img src="{image_file}"></div>\n' |
|
ttf_num += 1 |
|
|
|
html += f'<div>Total files: {ttf_num}</div>\n' |
|
html += fonts_html_block |
|
html += '<div>Generated using script <a href="https://gist.github.com/sigsergv/9309ad0e3b3c2be65aa58c37d259f580">generate-font-samples.py</a></div>' |
|
html += '</body></html>' |
|
|
|
index_html = os.path.join(out_dir, 'index.html') |
|
with open(index_html, 'w') as ifp: |
|
ifp.write(html) |