Files
makemeahanzi/main.py
2015-08-25 11:45:13 -04:00

111 lines
4.3 KiB
Python
Executable File

#!/usr/bin/python
'''
Extracts one or more characters from each of the svg fonts in the SVG directory
and packages them into a 'chars.html' output file.
'''
import math
import os
import random
import sys
import median
import stroke_extractor
COLORS = ['#0074D9', '#2ECC40', '#FFDC00', '#FF4136', '#7FDBFF',
'#001F3F', '#39CCCC', '#3D9970', '#01FF70', '#FF851B']
SCALE = 0.16
SVG_DIR = 'derived'
TRANSFORM = 'scale({0:.2g}, -{0:0.2g}) translate(0, -900)'.format(SCALE)
def augment_glyph(glyph):
'''
Takes an HTML SVG object and returns a list of addition SVG elements that
should be added to the glyph to show diagnostic data for our algorithm.
'''
name = get_html_attribute(glyph, 'glyph-name')
d = get_html_attribute(glyph, 'd')
assert name and d, 'Missing glyph-name or d for glyph:\n{0}'.format(glyph)
extractor = stroke_extractor.StrokeExtractor(name, d)
# We augment the glyph with three types of information:
# - The extracted strokes. Each one is drawn in a random color.
# - The endpoints of the original paths, with corners in red, others in blue.
# - The detected bridges, line segments drawn in white.
result = []
for i, stroke in enumerate(extractor.strokes):
result.append('<path fill="{0}" {1} d="{2}" />'.format(
COLORS[i % len(COLORS)], 'stroke="black" stroke-width="2"', stroke.d()))
for path in extractor.paths:
for element in path:
result.append(
'<circle cx="{0}" cy="{1}" r="4" fill="blue" stroke="blue"/>'.format(
int(element.end.real), int(element.end.imag)))
corners = extractor.corners
for corner in corners.itervalues():
result.append(
'<circle cx="{0}" cy="{1}" r="4" fill="red" stroke="red" '
'data-angle="{2}"/>'.format(
int(corner.point.real), int(corner.point.imag), corner.angle))
for index1 in extractor.bridges:
for index2 in extractor.bridges[index1]:
if index1 > index2:
continue
result.append(
'<line x1="{0}" y1="{1}" x2="{2}" y2="{3}" style="{4}"/>'.format(
int(corners[index1].point.real), int(corners[index1].point.imag),
int(corners[index2].point.real), int(corners[index2].point.imag),
'stroke:white;stroke-width:8'))
return result
def get_html_attribute(glyph, attribute):
'''
Takes an HTML SVG object and returns the path data from the "d" field.
'''
left = ' {0}="'.format(attribute)
start = max(glyph.find(left), glyph.find(left.replace(' ', '\n')))
end = glyph.find('"', start + len(left))
assert start >= 0 and end >= 0, \
'Glyph missing {0}=".*" block:\n{1}'.format(attribute, repr(glyph))
return glyph[start + len(left):end].replace('\n', ' ')
if __name__ == '__main__':
assert len(sys.argv) > 1, 'Usage: ./getchar.py <unicode_codepoint>+'
svgs = [file_name for file_name in os.listdir(SVG_DIR)
if file_name.endswith('.svg') and not file_name.startswith('.')]
glyphs = []
for file_name in svgs:
glyphs.append([])
with open(os.path.join(SVG_DIR, file_name)) as file:
data = file.read()
for codepoint in sys.argv[1:]:
index = data.find('unicode="&#x{0};"'.format(codepoint))
if index < 0:
print >> sys.stderr, '{0}: missing {1}'.format(file_name, codepoint)
continue
(left, right) = ('<glyph', '/>')
(start, end) = (data.rfind(left, 0, index), data.find(right, index))
if start < 0 or end < 0:
print >> sys.stderr, '{0}: malformed {1}'.format(file_name, codepoint)
continue
glyphs[-1].append(data[start:end + len(right)])
# Construct an HTML file that includes the extracted glyphs, along with
# diagnostic data for our stroke extraction algorithm.
with open('chars.html', 'w') as f:
f.write('<!DOCTYPE html>\n <html>\n <body>\n')
for row in glyphs:
f.write(' <div>\n')
for glyph in row:
size = int(1024*SCALE)
f.write(' <svg width="{0}" height="{0}">\n'.format(size))
f.write(' <g transform="{0}">\n'.format(TRANSFORM))
f.write(glyph.replace('<glyph', '<path') + '\n')
for extra in augment_glyph(glyph):
f.write(extra + '\n')
f.write(' </g>\n')
f.write(' </svg>\n')
f.write(' </div>\n')
f.write(' </body>\n </html>')