Dusted off - made to work to some extent
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
venv
|
venv
|
||||||
svgs
|
svgs/
|
||||||
ttf
|
ttf/
|
||||||
idea
|
idea
|
||||||
|
__pycache__/
|
||||||
|
|||||||
5
arch-linux.txt
Normal file
5
arch-linux.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
arch packages: fontforge python-svgwrite-1.4.3-5
|
||||||
|
|
||||||
|
prep:
|
||||||
|
mkdir svgs
|
||||||
|
k
|
||||||
22
ffimport.py
22
ffimport.py
@@ -18,6 +18,7 @@ def run(path, font_name):
|
|||||||
font.fontname = font_name
|
font.fontname = font_name
|
||||||
# noinspection SpellCheckingInspection
|
# noinspection SpellCheckingInspection
|
||||||
font.familyname = 'Hershey'
|
font.familyname = 'Hershey'
|
||||||
|
print(os.listdir(os.path.join(svg_folder, font_name)))
|
||||||
for svg in os.listdir(os.path.join(svg_folder, font_name)):
|
for svg in os.listdir(os.path.join(svg_folder, font_name)):
|
||||||
if svg[-4:] == '.svg':
|
if svg[-4:] == '.svg':
|
||||||
match = re.match(r'ascii(\d+)_l(-?[\d.]+)_r(-?[\d.]+).svg', svg)
|
match = re.match(r'ascii(\d+)_l(-?[\d.]+)_r(-?[\d.]+).svg', svg)
|
||||||
@@ -26,18 +27,29 @@ def run(path, font_name):
|
|||||||
|
|
||||||
glyph = font.createMappedChar(character)
|
glyph = font.createMappedChar(character)
|
||||||
# Import the outlines *before* setting the bearings. Otherwise, everything will be reset.
|
# Import the outlines *before* setting the bearings. Otherwise, everything will be reset.
|
||||||
glyph.importOutlines(os.path.join(svg_folder, font_name, svg))
|
|
||||||
|
print("and then?", os.path.join(svg_folder, font_name, svg))
|
||||||
|
glyph.importOutlines(os.path.join(svg_folder, font_name, svg)) # SILENT CRASH
|
||||||
|
|
||||||
|
|
||||||
glyph.stroke('circular', stroke_size, 'round', 'round')
|
glyph.stroke('circular', stroke_size, 'round', 'round')
|
||||||
# glyph.correctDirection()
|
glyph.correctDirection()
|
||||||
glyph.removeOverlap()
|
|
||||||
glyph.simplify()
|
glyph.simplify()
|
||||||
glyph.left_side_bearing = float(match.group(2))
|
glyph.round()
|
||||||
|
glyph.removeOverlap()
|
||||||
|
|
||||||
|
#glyph.stroke('circular', stroke_size, 'round', 'round')
|
||||||
|
# glyph.correctDirection()
|
||||||
|
#glyph.removeOverlap()
|
||||||
|
#glyph.simplify()
|
||||||
|
glyph.left_side_bearing = int(round(float(match.group(2))))
|
||||||
# Compensate for the stroke with on the right side bearing
|
# Compensate for the stroke with on the right side bearing
|
||||||
glyph.right_side_bearing = float(match.group(3)) - stroke_size
|
glyph.right_side_bearing = int(round(float(match.group(3)) - stroke_size))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f'Not a SVG file: {os.path.join(svg_folder, font_name, svg)}')
|
print(f'Not a SVG file: {os.path.join(svg_folder, font_name, svg)}')
|
||||||
|
|
||||||
# Assumes ttf folder exists
|
# Assumes ttf folder exists
|
||||||
|
print("Done gen, writing")
|
||||||
ttf_folder = os.path.join(path, 'ttf')
|
ttf_folder = os.path.join(path, 'ttf')
|
||||||
font.generate(os.path.join(ttf_folder, font_name + '.ttf'))
|
font.generate(os.path.join(ttf_folder, font_name + '.ttf'))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from dataclasses import Metadata
|
from local_dataclasses import Metadata
|
||||||
|
|
||||||
types = {'p': 'Plain', 's': 'Simplex', 'd': 'Duplex', 'cs': 'Complex_Small', 'c': 'Complex', 't': 'Triplex'}
|
types = {'p': 'Plain', 's': 'Simplex', 'd': 'Duplex', 'cs': 'Complex_Small', 'c': 'Complex', 't': 'Triplex'}
|
||||||
names = {'roman': 'Roman', 'greek': 'Greek', 'italic': 'Italic', 'script': 'Script', 'cyril': 'Cyrillic',
|
names = {'roman': 'Roman', 'greek': 'Greek', 'italic': 'Italic', 'script': 'Script', 'cyril': 'Cyrillic',
|
||||||
|
|||||||
12
main.py
12
main.py
@@ -7,7 +7,7 @@ from sys import argv
|
|||||||
import hmpparser
|
import hmpparser
|
||||||
import ocxparser
|
import ocxparser
|
||||||
import svggenerator
|
import svggenerator
|
||||||
from dataclasses import Metadata
|
from local_dataclasses import Metadata
|
||||||
|
|
||||||
path = os.getcwd()
|
path = os.getcwd()
|
||||||
svgs_folder = os.path.join(os.getcwd(), 'svgs')
|
svgs_folder = os.path.join(os.getcwd(), 'svgs')
|
||||||
@@ -15,12 +15,10 @@ font_forge_path = 'C:\\Program Files (x86)\\FontForgeBuilds\\bin'
|
|||||||
|
|
||||||
|
|
||||||
def generate_ttf(font_name):
|
def generate_ttf(font_name):
|
||||||
if os.path.isdir(os.path.join(svgs_folder, font_name)):
|
print('GEN', font_name, path)
|
||||||
# Remember that the command must be single-line.
|
# 'gdb', '--args',
|
||||||
# That is why we use semicolons instead of line breaks.
|
subprocess.run([ 'fontforge', '-c', f'import os;os.chdir(r"{path}");import ffimport;ffimport.run(r"{path}", "{font_name}")'])
|
||||||
os.chdir(font_forge_path)
|
exit()
|
||||||
subprocess.run(['fontforge', '-c',
|
|
||||||
f'import os;os.chdir(r"{path}");import ffimport;ffimport.run(r"{path}", "{font_name}")'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from dataclasses import Glyph
|
from local_dataclasses import Glyph
|
||||||
|
|
||||||
offset = ord('R')
|
offset = ord('R')
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,31 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import svgwrite
|
import svgwrite
|
||||||
from svgwrite.shapes import Polyline
|
from svgwrite.path import Path
|
||||||
|
|
||||||
from dataclasses import Glyph, Metadata
|
from local_dataclasses import Glyph, Metadata
|
||||||
|
|
||||||
base = 16
|
base = 16
|
||||||
cap = -16
|
cap = -16
|
||||||
svg_size = 1024
|
svg_size = 1024
|
||||||
guard = 12
|
guard = 12
|
||||||
line_style = {'fill': 'none', 'stroke': 'black', 'stroke-width': 0, 'stroke-linecap': 'round',
|
|
||||||
'stroke-linejoin': 'round'}
|
|
||||||
|
|
||||||
|
|
||||||
def generate(glyph: Glyph, metadata: Metadata):
|
def generate(glyph: Glyph, metadata: Metadata):
|
||||||
"""Uses the glyph and the metadata to create the SVGs.
|
print(f"Generating character '{metadata.character}' for font {metadata.font_name}")
|
||||||
|
|
||||||
The subfolder is the font name.
|
|
||||||
The SVG name contains the metadata necessary to import the glyph to the font.
|
|
||||||
"""
|
|
||||||
print(f'Generating character \'{metadata.character}\' for font {metadata.font_name}')
|
|
||||||
|
|
||||||
# Assumes font folder already exists
|
|
||||||
font_path = os.path.join(os.getcwd(), 'svgs', metadata.font_name)
|
font_path = os.path.join(os.getcwd(), 'svgs', metadata.font_name)
|
||||||
|
|
||||||
left_side_bearing, right_side_bearing = _calculate_bearings(glyph)
|
left_side_bearing, right_side_bearing = _calculate_bearings(glyph)
|
||||||
svg_filename = f'ascii{str(metadata.ascii_value)}_l{left_side_bearing}_r{right_side_bearing}.svg'
|
svg_filename = f'ascii{str(metadata.ascii_value)}_l{left_side_bearing}_r{right_side_bearing}.svg'
|
||||||
dwg = svgwrite.Drawing(os.path.join(font_path, svg_filename), viewBox=f"0 0 {svg_size} {svg_size}")
|
|
||||||
|
dwg = svgwrite.Drawing(
|
||||||
|
os.path.join(font_path, svg_filename),
|
||||||
|
viewBox=f"0 0 {svg_size} {svg_size}"
|
||||||
|
)
|
||||||
|
|
||||||
points = []
|
points = []
|
||||||
|
|
||||||
for coordinate in glyph.coordinates:
|
for coordinate in glyph.coordinates:
|
||||||
if coordinate:
|
if coordinate:
|
||||||
x, y = coordinate
|
x, y = coordinate
|
||||||
@@ -36,20 +33,27 @@ def generate(glyph: Glyph, metadata: Metadata):
|
|||||||
y = _map_to_svg(y)
|
y = _map_to_svg(y)
|
||||||
points.append((x, y))
|
points.append((x, y))
|
||||||
else:
|
else:
|
||||||
# Pen up
|
|
||||||
# Always check if line is empty (i.e. points array is empty).
|
|
||||||
# Empty lines can cause problems.
|
|
||||||
if points:
|
if points:
|
||||||
dwg.add(Polyline(points, **line_style))
|
_add_path(dwg, points)
|
||||||
points = []
|
points = []
|
||||||
|
|
||||||
# Finalize the drawing
|
|
||||||
if points:
|
if points:
|
||||||
dwg.add(Polyline(points, **line_style))
|
_add_path(dwg, points)
|
||||||
|
|
||||||
dwg.save()
|
dwg.save()
|
||||||
|
|
||||||
|
|
||||||
|
def _add_path(dwg, points):
|
||||||
|
if not points:
|
||||||
|
return
|
||||||
|
|
||||||
|
p = Path()
|
||||||
|
p.push(f"M {points[0][0]} {points[0][1]}")
|
||||||
|
for x, y in points[1:]:
|
||||||
|
p.push(f"L {x} {y}")
|
||||||
|
dwg.add(p)
|
||||||
|
|
||||||
|
|
||||||
def _calculate_bearings(glyph: Glyph):
|
def _calculate_bearings(glyph: Glyph):
|
||||||
if glyph.coordinates:
|
if glyph.coordinates:
|
||||||
leftmost_point = _map_to_svg(min(coordinate[0] for coordinate in glyph.coordinates if coordinate))
|
leftmost_point = _map_to_svg(min(coordinate[0] for coordinate in glyph.coordinates if coordinate))
|
||||||
@@ -63,7 +67,4 @@ def _calculate_bearings(glyph: Glyph):
|
|||||||
|
|
||||||
|
|
||||||
def _map_to_svg(x):
|
def _map_to_svg(x):
|
||||||
# Scale proportionally (* svg_size / (base - cap))
|
|
||||||
# Guard to avoid going out of bounds after stroking the character
|
|
||||||
# Offset, since the SVG starts at zero (+ svg_size / 2)
|
|
||||||
return x * (svg_size - 2 * guard) / (base - cap) + svg_size / 2
|
return x * (svg_size - 2 * guard) / (base - cap) + svg_size / 2
|
||||||
|
|||||||
Reference in New Issue
Block a user