summaryrefslogtreecommitdiff
path: root/doc/tools/coqrst/notations/fontsupport.py
blob: a3efd97f5b1b45b25e883cd9e1efc79cc8db2365 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##########################################################################
##         #   The Coq Proof Assistant / The Coq Development Team       ##
##  v      #   INRIA, CNRS and contributors - Copyright 1999-2018       ##
## <O___,, #       (see CREDITS file for the list of authors)           ##
##   \VV/  ###############################################################
##    //   #    This file is distributed under the terms of the         ##
##         #     GNU Lesser General Public License Version 2.1          ##
##         #     (see LICENSE file for the text of the license)         ##
##########################################################################
"""Transform a font to center each of its characters in square bounding boxes.

See https://stackoverflow.com/questions/37377476/ for background information.
"""

from collections import Counter

try:
    import fontforge
    import psMat
except ImportError:
    print("This program requires FontForge's python bindings:")
    print("  git clone https://github.com/fontforge/fontforge")
    print("  cd fontforge")
    print("  ./bootstrap")
    print("  ./configure")
    print("  make -j8")
    print("  sudo make install")
    raise

def glyph_height(glyph):
    _, ylo, _, yhi = glyph.boundingBox()
    return yhi - ylo

def scale_single_glyph(glyph, width, height):
    """Center glyph in a box of size width*height"""
    # Some glyphs (such as ‘;’) contain references (‘.’ + ‘,’), and moving the
    # referenced glyphs moves them in all glyphs that reference them.
    # Unlinking copies references into this glyph
    glyph.unlinkThisGlyph()
    # Width
    deltaw = width - glyph.width
    glyph.left_side_bearing += deltaw / 2
    glyph.right_side_bearing += deltaw - glyph.left_side_bearing
    glyph.width = width
    # Height
    ylo = glyph.boundingBox()[1]
    deltah = height - glyph_height(glyph)
    glyph.transform(psMat.translate(0, deltah / 2.0 - ylo))

def avg(lst):
    lst = list(lst)
    return sum(lst) / float(len(lst))

def trim_font(fnt):
    """Remove characters codes beyond 191 front fnt"""
    for g in fnt.glyphs():
        if g.unicode >= 191:
            fnt.removeGlyph(g)
    return fnt

def center_glyphs(src_font_path, dst_font_path, dst_name):
    fnt = trim_font(fontforge.open(src_font_path))

    size = max(g.width for g in fnt.glyphs())
    fnt.ascent, fnt.descent = size, 0
    for glyph in fnt.glyphs():
        scale_single_glyph(glyph, size, size)

    fnt.sfnt_names = []
    fnt.fontname = fnt.familyname = fnt.fullname = dst_name
    fnt.generate(dst_font_path)

if __name__ == '__main__':
    from os.path import dirname, join, abspath
    curdir = dirname(abspath(__file__))
    ubuntumono_path = join(curdir, "UbuntuMono-B.ttf")
    ubuntumono_mod_path = join(curdir, "CoqNotations.ttf")
    center_glyphs(ubuntumono_path, ubuntumono_mod_path, "CoqNotations")