tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mathfont.py (7619B)


      1 import fontforge
      2 
      3 PUA_startCodePoint = 0xE000
      4 em = 1000
      5 
      6 
      7 def create(aName, aCopyRight):
      8    print("Generating %s.woff..." % aName, end="")
      9    mathFont = fontforge.font()
     10    mathFont.fontname = aName
     11    mathFont.familyname = aName
     12    mathFont.fullname = aName
     13    mathFont.copyright = aCopyRight
     14    mathFont.encoding = "UnicodeFull"
     15 
     16    # Create a space character. Also force the creation of some MATH subtables
     17    # so that OTS will not reject the MATH table.
     18    g = mathFont.createChar(ord(" "), "space")
     19    g.width = em
     20    g.italicCorrection = 0
     21    g.topaccent = 0
     22    g.mathKern.bottomLeft = tuple([(0, 0)])
     23    g.mathKern.bottomRight = tuple([(0, 0)])
     24    g.mathKern.topLeft = tuple([(0, 0)])
     25    g.mathKern.topRight = tuple([(0, 0)])
     26    mathFont[ord(" ")].horizontalVariants = "space"
     27    mathFont[ord(" ")].verticalVariants = "space"
     28    return mathFont
     29 
     30 
     31 def drawRectangleGlyph(glyph, width, ascent, descent=0, padding_left=0):
     32    p = glyph.glyphPen()
     33    p.moveTo(padding_left, -descent)
     34    p.lineTo(padding_left, ascent)
     35    p.lineTo(padding_left + width, ascent)
     36    p.lineTo(padding_left + width, -descent)
     37    p.closePath()
     38    glyph.width = padding_left + width
     39 
     40 
     41 def createSquareGlyph(aFont, aCodePoint):
     42    g = aFont.createChar(aCodePoint)
     43    drawRectangleGlyph(g, em, em, 0)
     44 
     45 
     46 def drawHexaDigit(aGlyph, aX, aValue):
     47    t = em / 10
     48    p = aGlyph.glyphPen(replace=False)
     49    if aValue == 0:
     50        p.moveTo(aX + t, t)
     51        p.lineTo(aX + t, em - t)
     52        p.lineTo(aX + em / 2 - t, em - t)
     53        p.lineTo(aX + em / 2 - t, t)
     54        p.closePath()
     55    elif aValue == 1:
     56        p.moveTo(aX + em / 2 - t, em - t)
     57        p.lineTo(aX + em / 2 - t, t)
     58        p.endPath()
     59    elif aValue == 2:
     60        p.moveTo(aX + t, em - t)
     61        p.lineTo(aX + em / 2 - t, em - t)
     62        p.lineTo(aX + em / 2 - t, em / 2)
     63        p.lineTo(aX + t, em / 2)
     64        p.lineTo(aX + t, t)
     65        p.lineTo(aX + em / 2 - t, t)
     66        p.endPath()
     67    elif aValue == 3:
     68        p.moveTo(aX + t, em - t)
     69        p.lineTo(aX + em / 2 - t, em - t)
     70        p.lineTo(aX + em / 2 - t, t)
     71        p.lineTo(aX + t, t)
     72        p.endPath()
     73        p.moveTo(aX + t, em / 2)
     74        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
     75        p.endPath()
     76    elif aValue == 4:
     77        p.moveTo(aX + em / 2 - t, em - t)
     78        p.lineTo(aX + em / 2 - t, t)
     79        p.endPath()
     80        p.moveTo(aX + t, em - t)
     81        p.lineTo(aX + t, em / 2)
     82        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
     83        p.endPath()
     84    elif aValue == 5:
     85        p.moveTo(aX + em / 2 - t, em - t)
     86        p.lineTo(aX + t, em - t)
     87        p.lineTo(aX + t, em / 2)
     88        p.lineTo(aX + em / 2 - t, em / 2)
     89        p.lineTo(aX + em / 2 - t, t)
     90        p.lineTo(aX + t, t)
     91        p.endPath()
     92    elif aValue == 6:
     93        p.moveTo(aX + em / 2 - t, em - t)
     94        p.lineTo(aX + t, em - t)
     95        p.lineTo(aX + t, t)
     96        p.lineTo(aX + em / 2 - t, t)
     97        p.lineTo(aX + em / 2 - t, em / 2)
     98        p.lineTo(aX + 2.5 * t, em / 2)
     99        p.endPath()
    100    elif aValue == 7:
    101        p.moveTo(aX + t, em - t)
    102        p.lineTo(aX + em / 2 - t, em - t)
    103        p.lineTo(aX + em / 2 - t, t)
    104        p.endPath()
    105    elif aValue == 8:
    106        p.moveTo(aX + t, t)
    107        p.lineTo(aX + t, em - t)
    108        p.lineTo(aX + em / 2 - t, em - t)
    109        p.lineTo(aX + em / 2 - t, t)
    110        p.closePath()
    111        p.moveTo(aX + 2.5 * t, em / 2)
    112        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
    113        p.endPath()
    114    elif aValue == 9:
    115        p.moveTo(aX + t, t)
    116        p.lineTo(aX + em / 2 - t, t)
    117        p.lineTo(aX + em / 2 - t, em - t)
    118        p.lineTo(aX + t, em - t)
    119        p.lineTo(aX + t, em / 2)
    120        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
    121        p.endPath()
    122    elif aValue == 10:  # A
    123        p.moveTo(aX + t, t)
    124        p.lineTo(aX + t, em - t)
    125        p.lineTo(aX + em / 2 - t, em - t)
    126        p.lineTo(aX + em / 2 - t, t)
    127        p.endPath()
    128        p.moveTo(aX + 2.5 * t, em / 2)
    129        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
    130        p.endPath()
    131    elif aValue == 11:  # b
    132        p.moveTo(aX + t, em - t)
    133        p.lineTo(aX + t, t)
    134        p.lineTo(aX + em / 2 - t, t)
    135        p.lineTo(aX + em / 2 - t, em / 2)
    136        p.lineTo(aX + 2.5 * t, em / 2)
    137        p.endPath()
    138    elif aValue == 12:  # C
    139        p.moveTo(aX + em / 2 - t, em - t)
    140        p.lineTo(aX + t, em - t)
    141        p.lineTo(aX + t, t)
    142        p.lineTo(aX + em / 2 - t, t)
    143        p.endPath()
    144    elif aValue == 13:  # d
    145        p.moveTo(aX + em / 2 - t, em - t)
    146        p.lineTo(aX + em / 2 - t, t)
    147        p.lineTo(aX + t, t)
    148        p.lineTo(aX + t, em / 2)
    149        p.lineTo(aX + em / 2 - 2.5 * t, em / 2)
    150        p.endPath()
    151    elif aValue == 14:  # E
    152        p.moveTo(aX + em / 2 - t, em - t)
    153        p.lineTo(aX + t, em - t)
    154        p.lineTo(aX + t, t)
    155        p.lineTo(aX + em / 2 - t, t)
    156        p.endPath()
    157        p.moveTo(aX + em / 2 - t, em / 2)
    158        p.lineTo(aX + 2.5 * t, em / 2)
    159        p.endPath()
    160    elif aValue == 15:  # F
    161        p.moveTo(aX + em / 2 - t, em - t)
    162        p.lineTo(aX + t, em - t)
    163        p.lineTo(aX + t, t)
    164        p.endPath()
    165        p.moveTo(aX + em / 2 - t, em / 2)
    166        p.lineTo(aX + 2.5 * t, em / 2)
    167        p.endPath()
    168 
    169 
    170 def createGlyphFromValue(aFont, aCodePoint):
    171    g = aFont.createChar(aCodePoint)
    172    value = aCodePoint
    173    for i in range(0, 5):
    174        drawHexaDigit(g, (5 - (i + 1)) * em / 2, value % 16)
    175        value /= 16
    176    g.width = 5 * em // 2
    177    g.stroke("circular", em / 10, "square", "miter", "cleanup")
    178 
    179 
    180 def createSizeVariants(aFont, aUsePUA=False, aCenterOnBaseline=False):
    181    if aUsePUA:
    182        codePoint = PUA_startCodePoint
    183    else:
    184        codePoint = -1
    185    for size in (0, 1, 2, 3):
    186        g = aFont.createChar(codePoint, "v%d" % size)
    187        if aCenterOnBaseline:
    188            drawRectangleGlyph(g, em, (size + 1) * em / 2, (size + 1) * em / 2)
    189        else:
    190            drawRectangleGlyph(g, em, (size + 1) * em, 0)
    191        if aUsePUA:
    192            codePoint += 1
    193        g = aFont.createChar(codePoint, "h%d" % size)
    194        if aCenterOnBaseline:
    195            drawRectangleGlyph(g, (size + 1) * em, em / 2, em / 2)
    196        else:
    197            drawRectangleGlyph(g, (size + 1) * em, em, 0)
    198        if aUsePUA:
    199            codePoint += 1
    200 
    201 
    202 def createStretchy(aFont, codePoint, isHorizontal):
    203    if isHorizontal:
    204        aFont[codePoint].horizontalVariants = "h0 h1 h2 h3"
    205        # Part: (glyphName, isExtender, startConnector, endConnector, fullAdvance)
    206        aFont[codePoint].horizontalComponents = \
    207            (("h2", False, 0, em, 3 * em),
    208             ("h1", True, em, em, 2 * em))
    209    else:
    210        aFont[codePoint].verticalVariants = "v0 v1 v2 v3"
    211        # Part: (glyphName, isExtender, startConnector, endConnector, fullAdvance)
    212        aFont[codePoint].verticalComponents = \
    213            (("v2", False, 0, em, 3 * em),
    214             ("v1", True, em, em, 2 * em))
    215 
    216 
    217 def save(aFont):
    218    aFont.em = em
    219    aFont.ascent = aFont.hhea_ascent = aFont.os2_typoascent = em
    220    aFont.descent = aFont.hhea_descent = aFont.os2_typodescent = 0
    221    # aFont.os2_winascent, aFont.os2_windescent should be the maximum of
    222    # ascent/descent for all glyphs. Does fontforge compute them automatically?
    223    aFont.hhea_ascent_add = aFont.hhea_descent_add = 0
    224    aFont.os2_typoascent_add = aFont.os2_typodescent_add = 0
    225    aFont.os2_winascent_add = aFont.os2_windescent_add = 0
    226    aFont.os2_use_typo_metrics = True
    227    aFont.generate("../../fonts/math/%s.woff" % aFont.fontname)
    228    if aFont.validate() == 0:
    229        print(" done.")
    230    else:
    231        print(" validation error!")
    232        exit(1)