1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/reftests/fonts/math/generate.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,231 @@ 1.4 +#!/usr/bin/python 1.5 +# vim: set shiftwidth=4 tabstop=8 autoindent expandtab: 1.6 +# This Source Code Form is subject to the terms of the Mozilla Public 1.7 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.9 + 1.10 +# For general fontforge documentation, see: 1.11 +# http://fontforge.sourceforge.net/ 1.12 +# For fontforge scripting documentation, see: 1.13 +# http://fontforge.sourceforge.net/scripting-tutorial.html 1.14 +# http://fontforge.sourceforge.net/scripting.html 1.15 +# and most importantly: 1.16 +# http://fontforge.sourceforge.net/python.html 1.17 + 1.18 +# To install what you need, on Ubuntu, 1.19 +# sudo apt-get install python-fontforge 1.20 + 1.21 +from __future__ import print_function 1.22 +import fontforge 1.23 + 1.24 +em = 1000 1.25 + 1.26 +def newMathFont(aName): 1.27 + print("Generating %s.otf..." % aName, end="") 1.28 + mathFont = fontforge.font() 1.29 + mathFont.fontname = aName 1.30 + mathFont.familyname = aName 1.31 + mathFont.fullname = aName 1.32 + mathFont.copyright = "Copyright (c) 2014 Mozilla Corporation" 1.33 + mathFont.encoding = "UnicodeFull" 1.34 + 1.35 + # Create a space character. Also force the creation of some MATH subtables 1.36 + # so that OTS will not reject the MATH table. 1.37 + g = mathFont.createChar(ord(" "), "space") 1.38 + g.width = em 1.39 + g.italicCorrection = 0 1.40 + g.topaccent = 0 1.41 + g.mathKern.bottomLeft = tuple([(0,0)]) 1.42 + g.mathKern.bottomRight = tuple([(0,0)]) 1.43 + g.mathKern.topLeft = tuple([(0,0)]) 1.44 + g.mathKern.topRight = tuple([(0,0)]) 1.45 + mathFont[ord(" ")].horizontalVariants = "space" 1.46 + mathFont[ord(" ")].verticalVariants = "space" 1.47 + return mathFont 1.48 + 1.49 +def saveMathFont(aFont): 1.50 + aFont.em = em 1.51 + aFont.ascent = aFont.descent = em/2 1.52 + aFont.hhea_ascent = aFont.os2_typoascent = aFont.os2_winascent = em/2 1.53 + aFont.descent = aFont.hhea_descent = em/2 1.54 + aFont.os2_typodescent = aFont.os2_windescent = em/2 1.55 + aFont.hhea_ascent_add = aFont.hhea_descent_add = 0 1.56 + aFont.os2_typoascent_add = aFont.os2_typodescent_add = 0 1.57 + aFont.os2_winascent_add = aFont.os2_windescent_add = 0 1.58 + aFont.os2_use_typo_metrics = True 1.59 + aFont.generate(aFont.fontname + ".otf") 1.60 + print(" done.") 1.61 + 1.62 +################################################################################ 1.63 +# Glyph variants and constructions 1.64 +f = newMathFont("stretchy") 1.65 +nvariants = 3 1.66 + 1.67 +# Draw boxes for the size variants and glues 1.68 +for i in range(0, nvariants): 1.69 + s = em * (i + 1) 1.70 + 1.71 + g = f.createChar(-1, "h%d" % i) 1.72 + p = g.glyphPen() 1.73 + p.moveTo(0, -em) 1.74 + p.lineTo(0, em) 1.75 + p.lineTo(s, em) 1.76 + p.lineTo(s, -em) 1.77 + p.closePath() 1.78 + g.width = s 1.79 + 1.80 + g = f.createChar(-1, "v%d" % i) 1.81 + p = g.glyphPen() 1.82 + p.moveTo(0, 0) 1.83 + p.lineTo(0, s) 1.84 + p.lineTo(2 * em, s) 1.85 + p.lineTo(2 * em, 0) 1.86 + p.closePath(); 1.87 + g.width = 2 * em 1.88 + 1.89 +# Draw some pieces for stretchy operators 1.90 +s = em * nvariants 1.91 + 1.92 +g = f.createChar(-1, "left") 1.93 +p = g.glyphPen() 1.94 +p.moveTo(0, -2 * em) 1.95 +p.lineTo(0, 2 * em) 1.96 +p.lineTo(s, em) 1.97 +p.lineTo(s, -em) 1.98 +p.closePath(); 1.99 +g.width = s 1.100 + 1.101 +g = f.createChar(-1, "right") 1.102 +p = g.glyphPen() 1.103 +p.moveTo(0, -em) 1.104 +p.lineTo(0, em) 1.105 +p.lineTo(s, 2 * em) 1.106 +p.lineTo(s, -2 * em) 1.107 +p.closePath(); 1.108 +g.width = s 1.109 + 1.110 +g = f.createChar(-1, "hmid") 1.111 +p = g.glyphPen() 1.112 +p.moveTo(0, -em) 1.113 +p.lineTo(0, em) 1.114 +p.lineTo(s, 2 * em) 1.115 +p.lineTo(2 * s, em) 1.116 +p.lineTo(2 * s, -em) 1.117 +p.lineTo(s, -2 * em) 1.118 +p.closePath(); 1.119 +g.width = 2 * s 1.120 + 1.121 +g = f.createChar(-1, "bottom") 1.122 +p = g.glyphPen() 1.123 +p.moveTo(0, 0) 1.124 +p.lineTo(0, s) 1.125 +p.lineTo(2 * em, s) 1.126 +p.lineTo(4 * em, 0) 1.127 +p.closePath(); 1.128 +g.width = 4 * em 1.129 + 1.130 +g = f.createChar(-1, "top") 1.131 +p = g.glyphPen() 1.132 +p.moveTo(0, 0) 1.133 +p.lineTo(4 * em, 0) 1.134 +p.lineTo(2 * em, -s) 1.135 +p.lineTo(0, -s) 1.136 +p.closePath(); 1.137 +g.width = 4 * em 1.138 + 1.139 +g = f.createChar(-1, "vmid") 1.140 +p = g.glyphPen() 1.141 +p.moveTo(0, s) 1.142 +p.lineTo(2 * em, s) 1.143 +p.lineTo(4 * em, 0) 1.144 +p.lineTo(2 * em, -s) 1.145 +p.lineTo(0, -s) 1.146 +p.closePath(); 1.147 +g.width = 3 * em 1.148 + 1.149 +# Create small rectangle of various size for some exotic arrows that are 1.150 +# unlikely to be stretchable with standard fonts. 1.151 +hstretchy = [ 1.152 + 0x219C, # leftwards wave arrow 1.153 + 0x219D, # rightwards wave arrow 1.154 + 0x219E, # leftwards two headed arrow 1.155 + 0x21A0, # rightwards two headed arrow 1.156 + 0x21A2 # leftwards arrow with tail 1.157 +] 1.158 +vstretchy = [ 1.159 + 0x219F, # upwards two headed arrow 1.160 + 0x21A1, # downwards two headed arrow 1.161 + 0x21A5, # upwards arrow from bar 1.162 + 0x21A7, # downwards arrow from bar 1.163 + 0x21A8 # up down arrow with base 1.164 +] 1.165 +for i in range(0, 1 + nvariants + 1): 1.166 + s = (i + 1) * em/10 1.167 + 1.168 + g = f.createChar(hstretchy[i]) 1.169 + p = g.glyphPen() 1.170 + p.moveTo(0, -em/10) 1.171 + p.lineTo(0, em/10) 1.172 + p.lineTo(s, em/10) 1.173 + p.lineTo(s, -em/10) 1.174 + p.closePath() 1.175 + g.width = s 1.176 + 1.177 + g = f.createChar(vstretchy[i]) 1.178 + p = g.glyphPen() 1.179 + p.moveTo(0, 0) 1.180 + p.lineTo(0, s) 1.181 + p.lineTo(2 * em/10, s) 1.182 + p.lineTo(2 * em/10, 0) 1.183 + p.closePath(); 1.184 + g.width = 2 * em/10 1.185 + 1.186 +# hstretchy[0] and vstretchy[0] have all the variants and the components. The others only have one of them. 1.187 +s = em * nvariants 1.188 + 1.189 +f[hstretchy[0]].horizontalVariants = "uni219C h0 h1 h2" 1.190 +f[hstretchy[0]].horizontalComponents = (("left", False, 0, 0, s), \ 1.191 +("h2", True, 0, 0, s), ("hmid", False, 0, 0, 2 * s), ("h2", True, 0, 0, s), \ 1.192 +("right", False, 0, 0, s)) 1.193 + 1.194 +f[hstretchy[1]].horizontalVariants = "uni219D h0" 1.195 +f[hstretchy[2]].horizontalVariants = "uni219E h1" 1.196 +f[hstretchy[3]].horizontalVariants = "uni21A0 h2" 1.197 +f[hstretchy[4]].horizontalVariants = "uni21A2 h2" 1.198 +f[hstretchy[4]].horizontalComponents = f[hstretchy[0]].horizontalComponents 1.199 + 1.200 +f[vstretchy[0]].verticalVariants = "uni219F v0 v1 v2" 1.201 +f[vstretchy[0]].verticalComponents = (("bottom", False, 0, 0, s), \ 1.202 +("v2", True, 0, 0, s), ("vmid", False, 0, 0, 2 * s), ("v2", True, 0, 0, s), \ 1.203 +("top", False, 0, 0, s)) 1.204 + 1.205 +f[vstretchy[1]].verticalVariants = "uni21A1 v0" 1.206 +f[vstretchy[2]].verticalVariants = "uni21A5 v1" 1.207 +f[vstretchy[3]].verticalVariants = "uni21A7 v2" 1.208 +f[vstretchy[4]].verticalVariants = "uni21A8" 1.209 +f[vstretchy[4]].verticalComponents = f[vstretchy[0]].verticalComponents 1.210 + 1.211 +################################################################################ 1.212 +# Testing DisplayOperatorMinHeight 1.213 +f.math.DisplayOperatorMinHeight = 8 * em 1.214 +largeop = [0x2A1B, 0x2A1C] # integral with overbar/underbar 1.215 + 1.216 +# Draw boxes of size 1, 2, 7, 8, 9em. 1.217 +for i in [1, 2, 7, 8, 9]: 1.218 + s = em * i 1.219 + if i == 1 or i == 2: 1.220 + g = f.createChar(largeop[i-1]) 1.221 + else: 1.222 + g = f.createChar(-1, "L%d" % i) 1.223 + p = g.glyphPen() 1.224 + p.moveTo(0, 0) 1.225 + p.lineTo(0, s) 1.226 + p.lineTo(s, s) 1.227 + p.lineTo(s, 0) 1.228 + p.closePath(); 1.229 + g.width = s 1.230 + 1.231 +f[largeop[0]].verticalVariants = "uni2A1B L7 L8 L9" 1.232 +f[largeop[1]].verticalVariants = "uni2A1C L8" 1.233 + 1.234 +saveMathFont(f)