| #!/usr/bin/env python3 |
| # Copyright 2015 Google, Inc. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # Google Author(s): Doug Felt |
| |
| from __future__ import print_function |
| import argparse |
| import os |
| import os.path |
| import re |
| import sys |
| |
| from fontTools import ttx |
| |
| import add_svg_glyphs |
| |
| def do_generate_test_html(font_basename, pairs, glyph=None, verbosity=1): |
| header = r"""<!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <style type="text/css"> |
| @font-face { font-family: svgfont; src: url("%s") } |
| body { font-family: sans-serif; font-size: 24px } |
| #emoji span { font-family: svgfont, sans-serif } |
| #panel { font-family: svgfont, sans-serif; font-size: 256px } |
| #paneltitle { font-family: sans-serif; font-size: 36px } |
| </style> |
| <script type="text/javascript"> |
| function hexify(text) { |
| var surr_offset = 0x10000 - (0xd800 << 10) - 0xdc00 |
| var str = text.trim() |
| var len = str.length |
| var result = "" |
| for (var i = 0; i < len; ++i) { |
| var cp = str.charCodeAt(i) |
| if (cp >= 0xd800 && cp < 0xdc00 && i < len - 1) { |
| ncp = str.charCodeAt(i+1) |
| if (ncp >= 0xdc00 && ncp < 0xe000) { |
| cp = (cp << 10) + ncp + surr_offset |
| ++i; |
| } |
| } |
| result += " 0x" + cp.toString(16) |
| } |
| return result |
| }; |
| |
| function showText(event) { |
| var text = event.target.textContent |
| var p = document.getElementById('panel') |
| p.textContent = text |
| p = document.getElementById('paneltitle') |
| p.textContent = hexify(text) |
| }; |
| |
| function setup() { |
| var t = document.getElementById('emoji') |
| var tdlist = t.getElementsByTagName('span') |
| for (var i = 0; i < tdlist.length; ++i) { |
| var e = tdlist[i] |
| e.onmouseover = showText |
| } |
| }; |
| </script> |
| </head>""" |
| |
| body_head = r"""<body onload="setup();"> |
| <p>Test for SVG glyphs in %(font)s. It uses the proposed |
| <a href="http://lists.w3.org/Archives/Public/public-svgopentype/2013Jul/0003.html">SVG-in-OpenType format</a>. |
| View using Firefox 26 and later. |
| <div style="float:left; text-align:center; margin:0 10px; width:40%%"> |
| <div id='panel' style="margin-left:auto; margin-right:auto">%(glyph)s</div> |
| <div id='paneltitle' style="margin-left:auto; margin-right:auto">%(glyph_hex)s</div> |
| </div> |
| <div id='emoji'><p>""" |
| |
| body_tail = r"""</div> |
| </body> |
| </html> |
| """ |
| |
| font_name = font_basename + ".woff" |
| html_name = font_basename + "_test.html" |
| |
| found_initial_glyph = False |
| initial_glyph_str = None; |
| initial_glyph_hex = None; |
| text_parts = [] |
| for glyphstr, _ in pairs: |
| name_parts = [] |
| hex_parts = [] |
| for cp in glyphstr: |
| hex_str = hex(ord(cp)) |
| name_parts.append('&#x%s;' % hex_str[2:]) |
| hex_parts.append(hex_str) |
| glyph_str = ''.join(name_parts) |
| |
| if not found_initial_glyph: |
| if not glyph or glyph_str == glyph: |
| initial_glyph_str = glyph_str |
| initial_glyph_hex = ' '.join(hex_parts) |
| found_initial_glyph = True |
| elif not initial_glyph_str: |
| initial_glyph_str = glyph_str |
| initial_glyph_hex = ' '.join(hex_parts) |
| |
| text = '<span>%s</span>' % glyph_str |
| text_parts.append(text) |
| |
| if verbosity and glyph and not found_initial_glyph: |
| print("Did not find glyph '%s', using initial glyph '%s'" % (glyph, initial_glyph_str)) |
| elif verbosity > 1 and not glyph: |
| print("Using initial glyph '%s'" % initial_glyph_str) |
| |
| lines = [header % font_name] |
| lines.append(body_head % {'font':font_name, 'glyph':initial_glyph_str, |
| 'glyph_hex':initial_glyph_hex}) |
| lines.extend(text_parts) # we'll end up with space between each emoji |
| lines.append(body_tail) |
| output = '\n'.join(lines) |
| with open(html_name, 'w') as fp: |
| fp.write(output) |
| if verbosity: |
| print('Wrote ' + html_name) |
| |
| |
| def do_generate_fonts(template_file, font_basename, pairs, reuse=0, verbosity=1): |
| out_woff = font_basename + '.woff' |
| if reuse > 1 and os.path.isfile(out_woff) and os.access(out_woff, os.R_OK): |
| if verbosity: |
| print('Reusing ' + out_woff) |
| return |
| |
| out_ttx = font_basename + '.ttx' |
| if reuse == 0: |
| add_svg_glyphs.add_image_glyphs(template_file, out_ttx, pairs, verbosity=verbosity) |
| elif verbosity: |
| print('Reusing ' + out_ttx) |
| |
| quiet=verbosity < 2 |
| font = ttx.TTFont(flavor='woff', quiet=quiet) |
| font.importXML(out_ttx, quiet=quiet) |
| font.save(out_woff) |
| if verbosity: |
| print('Wrote ' + out_woff) |
| |
| |
| def main(argv): |
| usage = """This will search for files that have image_prefix followed by one or more |
| hex numbers (separated by underscore if more than one), and end in ".svg". |
| For example, if image_prefix is "icons/u", then files with names like |
| "icons/u1F4A9.svg" or "icons/u1F1EF_1F1F5.svg" will be found. It generates |
| an SVG font from this, converts it to woff, and also generates an html test |
| page containing text for all the SVG glyphs.""" |
| |
| parser = argparse.ArgumentParser( |
| description='Generate font and html test file.', epilog=usage) |
| parser.add_argument('template_file', help='name of template .ttx file') |
| parser.add_argument('image_prefix', help='location and prefix of image files') |
| parser.add_argument('-i', '--include', help='include files whoses name matches this regex') |
| parser.add_argument('-e', '--exclude', help='exclude files whose name matches this regex') |
| parser.add_argument('-o', '--out_basename', help='base name of (ttx, woff, html) files to generate, ' |
| 'defaults to the template base name') |
| parser.add_argument('-g', '--glyph', help='set the initial glyph text (html encoded string), ' |
| 'defaults to first glyph') |
| parser.add_argument('-rt', '--reuse_ttx_font', dest='reuse_font', help='use existing ttx font', |
| default=0, const=1, action='store_const') |
| parser.add_argument('-r', '--reuse_font', dest='reuse_font', help='use existing woff font', |
| const=2, action='store_const') |
| parser.add_argument('-q', '--quiet', dest='v', help='quiet operation', default=1, |
| action='store_const', const=0) |
| parser.add_argument('-v', '--verbose', dest='v', help='verbose operation', |
| action='store_const', const=2) |
| args = parser.parse_args(argv) |
| |
| pairs = add_svg_glyphs.collect_glyphstr_file_pairs( |
| args.image_prefix, 'svg', include=args.include, exclude=args.exclude, verbosity=args.v) |
| add_svg_glyphs.sort_glyphstr_tuples(pairs) |
| |
| out_basename = args.out_basename |
| if not out_basename: |
| out_basename = args.template_file.split('.')[0] # exclude e.g. '.tmpl.ttx' |
| if args.v: |
| print("Output basename is %s." % out_basename) |
| do_generate_fonts(args.template_file, out_basename, pairs, reuse=args.reuse_font, verbosity=args.v) |
| do_generate_test_html(out_basename, pairs, glyph=args.glyph, verbosity=args.v) |
| |
| if __name__ == '__main__': |
| main(sys.argv[1:]) |