diff options
Diffstat (limited to 'test/svg/build_ttx_fonts.py')
-rwxr-xr-x | test/svg/build_ttx_fonts.py | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/test/svg/build_ttx_fonts.py b/test/svg/build_ttx_fonts.py new file mode 100755 index 000000000..d7e7f5b8f --- /dev/null +++ b/test/svg/build_ttx_fonts.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 + +# Build the ttx cairo svg test fonts from svg files +# The svg files use the naming convention +# <font-name>.<char>.<test-name>.svg +# eg "circle.A.cx_cy_r.svg" +# +# <font-name> is use to create the name of the ttx font. +# <char> is a ascii hex character (uppercase) that the font fill map to the SVG description. +# <test-name> is a descriptive name of the SVG file and is not used to build the font… +# +# This script looks for all files matching the above pattern and +# creates one ttx font for each unique <font-name>. Each font will +# contain up to 16 characters. The SVG description of each character +# and the character that maps to the SVG description is obtained from +# the SVG file beginning with <font-name>.<char>. + +import argparse +import os +import re +import sys +import xml.dom.minidom + +TEMPLATE_FILE="svg-font-template.ttx" + +glyph_names = { + '0': 'zero', + '1': 'one', + '2': 'two', + '3': 'three', + '4': 'four', + '5': 'five', + '6': 'six', + '7': 'seven', + '8': 'eight', + '9': 'nine', + 'A': 'A', + 'B': 'B', + 'C': 'C', + 'D': 'D', + 'E': 'E', + 'F': 'F' +} + +# files is list of (char, filename) +def build_font(font_name, files, in_dir, out_dir, no_reformat): + name = "cairo-svg-test-" + font_name + doc = xml.dom.minidom.parse(os.path.join(in_dir, TEMPLATE_FILE)) + glyph_id = 1 + text_nl = doc.createTextNode('\n\n') + for f in sorted(files): + glyph_name = glyph_names[f[0]] + + glyph_order = doc.getElementsByTagName('GlyphOrder')[0] + glyph_id_elem = doc.createElement('GlyphID') + glyph_id_elem.setAttribute('id', str(glyph_id)) + glyph_id_elem.setAttribute('name', glyph_name) + glyph_order.appendChild(glyph_id_elem) + glyph_order.appendChild(text_nl) + + hmtx = doc.getElementsByTagName('hmtx')[0] + mtx = doc.createElement('mtx') + mtx.setAttribute('name', glyph_name) + mtx.setAttribute('width', '1100') + mtx.setAttribute('lsb', '0') + hmtx.appendChild(mtx) + + cmap_format = doc.getElementsByTagName('cmap_format_4')[0] + map = doc.createElement('map') + map.setAttribute('code', hex(ord(f[0]))) + map.setAttribute('name', glyph_name) + cmap_format.appendChild(map) + + glyf = doc.getElementsByTagName('glyf')[0] + tt_glyph = doc.createElement('TTGlyph') + tt_glyph.setAttribute('name', glyph_name) + glyf.appendChild(tt_glyph) + contour = doc.createElement('contour') + tt_glyph.appendChild(contour) + pt = doc.createElement('pt') + pt.setAttribute('x', "0") + pt.setAttribute('y', "0") + pt.setAttribute('on', "1") + contour.appendChild(pt) + pt = doc.createElement('pt') + pt.setAttribute('x', "0") + pt.setAttribute('y', "1000") + pt.setAttribute('on', "1") + contour.appendChild(pt) + pt = doc.createElement('pt') + pt.setAttribute('x', "1000") + pt.setAttribute('y', "1000") + pt.setAttribute('on', "1") + contour.appendChild(pt) + pt = doc.createElement('pt') + pt.setAttribute('x', "1000") + pt.setAttribute('y', "0") + pt.setAttribute('on', "1") + contour.appendChild(pt) + instructions = doc.createElement('instructions') + tt_glyph.appendChild(instructions) + + svg = doc.getElementsByTagName('SVG')[0] + svgdoc = doc.createElement('svgDoc') + svgdoc.setAttribute('startGlyphID', str(glyph_id)) + svgdoc.setAttribute('endGlyphID', str(glyph_id)) + with open(os.path.join(in_dir, f[1]), 'r') as svg_file: + svg_data = svg_file.read() + cdata = doc.createCDATASection(svg_data) + svgdoc.appendChild(cdata) + svg.appendChild(svgdoc) + glyph_id += 1 + + name_record = doc.getElementsByTagName('namerecord')[0] + name_record.firstChild.replaceWholeText(name.replace("-", " ").title()) + name_record = doc.getElementsByTagName('namerecord')[2] + name_record.firstChild.replaceWholeText(name.replace("-", " ").title() + " Regular") + + ttx_filename = os.path.join(out_dir, name + '.ttx') + ttf_filename = os.path.join(out_dir, name + '.ttf') + with open(ttx_filename, 'w') as ttx_file: + doc.writexml(ttx_file) + + if not no_reformat: + # Convert to ttf and back to ttx. This reformats the ttx file + # which allows better quality diffs. + if os.path.exists(ttf_filename): + os.remove(ttf_filename) + os.system("ttx " + ttx_filename) + os.remove(ttx_filename) + os.system("ttx " + ttf_filename) + os.remove(ttf_filename) + +def build_file_list(in_dir): + dict = {} + regex_prog = re.compile(r"([^\.]+)\.(.)\.[^\.]+\.svg", re.ASCII) + files = os.listdir(in_dir) + for f in files: + match = regex_prog.fullmatch(f) + if match: + fontname = match.group(1) + character = match.group(2) + if (fontname not in dict): + dict[fontname] = [(character, f)]; + else: + dict[fontname].append((character, f)) + return dict + +if __name__=='__main__': + parser = argparse.ArgumentParser(description='Build ttx fonts.') + parser.add_argument("-i", nargs=1, metavar="indir", default=["."], help="Input directory") + parser.add_argument("-o", nargs=1, metavar="outdir", default=["."], help="Output directory") + parser.add_argument("-n", action='store_true', help="Don't reformat the output.") + args = parser.parse_args() + in_dir = args.i[0] + out_dir = args.o[0] + no_reformat = args.n + file_list = build_file_list(in_dir) + font_name = None + for key, value in file_list.items(): + build_font(key, value, in_dir, out_dir, no_reformat) |