Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 #!/usr/bin/python
2 # vim: set shiftwidth=4 tabstop=8 autoindent expandtab:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 # For general fontforge documentation, see:
8 # http://fontforge.sourceforge.net/
9 # For fontforge scripting documentation, see:
10 # http://fontforge.sourceforge.net/scripting-tutorial.html
11 # http://fontforge.sourceforge.net/scripting.html
12 # and most importantly:
13 # http://fontforge.sourceforge.net/python.html
15 # To install what you need, on Ubuntu,
16 # sudo apt-get install python-fontforge
18 from __future__ import print_function
19 import fontforge
21 em = 1000
23 def newMathFont(aName):
24 print("Generating %s.otf..." % aName, end="")
25 mathFont = fontforge.font()
26 mathFont.fontname = aName
27 mathFont.familyname = aName
28 mathFont.fullname = aName
29 mathFont.copyright = "Copyright (c) 2014 Mozilla Corporation"
30 mathFont.encoding = "UnicodeFull"
32 # Create a space character. Also force the creation of some MATH subtables
33 # so that OTS will not reject the MATH table.
34 g = mathFont.createChar(ord(" "), "space")
35 g.width = em
36 g.italicCorrection = 0
37 g.topaccent = 0
38 g.mathKern.bottomLeft = tuple([(0,0)])
39 g.mathKern.bottomRight = tuple([(0,0)])
40 g.mathKern.topLeft = tuple([(0,0)])
41 g.mathKern.topRight = tuple([(0,0)])
42 mathFont[ord(" ")].horizontalVariants = "space"
43 mathFont[ord(" ")].verticalVariants = "space"
44 return mathFont
46 def saveMathFont(aFont):
47 aFont.em = em
48 aFont.ascent = aFont.descent = em/2
49 aFont.hhea_ascent = aFont.os2_typoascent = aFont.os2_winascent = em/2
50 aFont.descent = aFont.hhea_descent = em/2
51 aFont.os2_typodescent = aFont.os2_windescent = em/2
52 aFont.hhea_ascent_add = aFont.hhea_descent_add = 0
53 aFont.os2_typoascent_add = aFont.os2_typodescent_add = 0
54 aFont.os2_winascent_add = aFont.os2_windescent_add = 0
55 aFont.os2_use_typo_metrics = True
56 aFont.generate(aFont.fontname + ".otf")
57 print(" done.")
59 ################################################################################
60 # Glyph variants and constructions
61 f = newMathFont("stretchy")
62 nvariants = 3
64 # Draw boxes for the size variants and glues
65 for i in range(0, nvariants):
66 s = em * (i + 1)
68 g = f.createChar(-1, "h%d" % i)
69 p = g.glyphPen()
70 p.moveTo(0, -em)
71 p.lineTo(0, em)
72 p.lineTo(s, em)
73 p.lineTo(s, -em)
74 p.closePath()
75 g.width = s
77 g = f.createChar(-1, "v%d" % i)
78 p = g.glyphPen()
79 p.moveTo(0, 0)
80 p.lineTo(0, s)
81 p.lineTo(2 * em, s)
82 p.lineTo(2 * em, 0)
83 p.closePath();
84 g.width = 2 * em
86 # Draw some pieces for stretchy operators
87 s = em * nvariants
89 g = f.createChar(-1, "left")
90 p = g.glyphPen()
91 p.moveTo(0, -2 * em)
92 p.lineTo(0, 2 * em)
93 p.lineTo(s, em)
94 p.lineTo(s, -em)
95 p.closePath();
96 g.width = s
98 g = f.createChar(-1, "right")
99 p = g.glyphPen()
100 p.moveTo(0, -em)
101 p.lineTo(0, em)
102 p.lineTo(s, 2 * em)
103 p.lineTo(s, -2 * em)
104 p.closePath();
105 g.width = s
107 g = f.createChar(-1, "hmid")
108 p = g.glyphPen()
109 p.moveTo(0, -em)
110 p.lineTo(0, em)
111 p.lineTo(s, 2 * em)
112 p.lineTo(2 * s, em)
113 p.lineTo(2 * s, -em)
114 p.lineTo(s, -2 * em)
115 p.closePath();
116 g.width = 2 * s
118 g = f.createChar(-1, "bottom")
119 p = g.glyphPen()
120 p.moveTo(0, 0)
121 p.lineTo(0, s)
122 p.lineTo(2 * em, s)
123 p.lineTo(4 * em, 0)
124 p.closePath();
125 g.width = 4 * em
127 g = f.createChar(-1, "top")
128 p = g.glyphPen()
129 p.moveTo(0, 0)
130 p.lineTo(4 * em, 0)
131 p.lineTo(2 * em, -s)
132 p.lineTo(0, -s)
133 p.closePath();
134 g.width = 4 * em
136 g = f.createChar(-1, "vmid")
137 p = g.glyphPen()
138 p.moveTo(0, s)
139 p.lineTo(2 * em, s)
140 p.lineTo(4 * em, 0)
141 p.lineTo(2 * em, -s)
142 p.lineTo(0, -s)
143 p.closePath();
144 g.width = 3 * em
146 # Create small rectangle of various size for some exotic arrows that are
147 # unlikely to be stretchable with standard fonts.
148 hstretchy = [
149 0x219C, # leftwards wave arrow
150 0x219D, # rightwards wave arrow
151 0x219E, # leftwards two headed arrow
152 0x21A0, # rightwards two headed arrow
153 0x21A2 # leftwards arrow with tail
154 ]
155 vstretchy = [
156 0x219F, # upwards two headed arrow
157 0x21A1, # downwards two headed arrow
158 0x21A5, # upwards arrow from bar
159 0x21A7, # downwards arrow from bar
160 0x21A8 # up down arrow with base
161 ]
162 for i in range(0, 1 + nvariants + 1):
163 s = (i + 1) * em/10
165 g = f.createChar(hstretchy[i])
166 p = g.glyphPen()
167 p.moveTo(0, -em/10)
168 p.lineTo(0, em/10)
169 p.lineTo(s, em/10)
170 p.lineTo(s, -em/10)
171 p.closePath()
172 g.width = s
174 g = f.createChar(vstretchy[i])
175 p = g.glyphPen()
176 p.moveTo(0, 0)
177 p.lineTo(0, s)
178 p.lineTo(2 * em/10, s)
179 p.lineTo(2 * em/10, 0)
180 p.closePath();
181 g.width = 2 * em/10
183 # hstretchy[0] and vstretchy[0] have all the variants and the components. The others only have one of them.
184 s = em * nvariants
186 f[hstretchy[0]].horizontalVariants = "uni219C h0 h1 h2"
187 f[hstretchy[0]].horizontalComponents = (("left", False, 0, 0, s), \
188 ("h2", True, 0, 0, s), ("hmid", False, 0, 0, 2 * s), ("h2", True, 0, 0, s), \
189 ("right", False, 0, 0, s))
191 f[hstretchy[1]].horizontalVariants = "uni219D h0"
192 f[hstretchy[2]].horizontalVariants = "uni219E h1"
193 f[hstretchy[3]].horizontalVariants = "uni21A0 h2"
194 f[hstretchy[4]].horizontalVariants = "uni21A2 h2"
195 f[hstretchy[4]].horizontalComponents = f[hstretchy[0]].horizontalComponents
197 f[vstretchy[0]].verticalVariants = "uni219F v0 v1 v2"
198 f[vstretchy[0]].verticalComponents = (("bottom", False, 0, 0, s), \
199 ("v2", True, 0, 0, s), ("vmid", False, 0, 0, 2 * s), ("v2", True, 0, 0, s), \
200 ("top", False, 0, 0, s))
202 f[vstretchy[1]].verticalVariants = "uni21A1 v0"
203 f[vstretchy[2]].verticalVariants = "uni21A5 v1"
204 f[vstretchy[3]].verticalVariants = "uni21A7 v2"
205 f[vstretchy[4]].verticalVariants = "uni21A8"
206 f[vstretchy[4]].verticalComponents = f[vstretchy[0]].verticalComponents
208 ################################################################################
209 # Testing DisplayOperatorMinHeight
210 f.math.DisplayOperatorMinHeight = 8 * em
211 largeop = [0x2A1B, 0x2A1C] # integral with overbar/underbar
213 # Draw boxes of size 1, 2, 7, 8, 9em.
214 for i in [1, 2, 7, 8, 9]:
215 s = em * i
216 if i == 1 or i == 2:
217 g = f.createChar(largeop[i-1])
218 else:
219 g = f.createChar(-1, "L%d" % i)
220 p = g.glyphPen()
221 p.moveTo(0, 0)
222 p.lineTo(0, s)
223 p.lineTo(s, s)
224 p.lineTo(s, 0)
225 p.closePath();
226 g.width = s
228 f[largeop[0]].verticalVariants = "uni2A1B L7 L8 L9"
229 f[largeop[1]].verticalVariants = "uni2A1C L8"
231 saveMathFont(f)