Skip to content

Commit

Permalink
Add a FONTSPLITTING_EXTRA parameter to consider non-Unicode glyphs in…
Browse files Browse the repository at this point in the history
… the splitting. Use this param for STIX.
  • Loading branch information
fred-wang committed Sep 4, 2013
1 parent 39eb2d7 commit 5ef283f
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 17 deletions.
4 changes: 3 additions & 1 deletion fonts/OpenTypeMath/Asana-Math/config.py
Expand Up @@ -22,6 +22,8 @@
MATHFONT = "Asana-Math.otf"
MAINFONTS = None

FONTSPLITTING_EXTRA = {}

FONTDATA = {
"FileVersion": "2.3",
"Year": "2013",
Expand All @@ -30,7 +32,7 @@
"lineH": .8,
"lineD": .2,
"hasStyleChar": True
}
}

RULECHAR = 0x2212

Expand Down
2 changes: 2 additions & 0 deletions fonts/OpenTypeMath/Gyre-Pagella/config.py
Expand Up @@ -22,6 +22,8 @@
MATHFONT="texgyrepagella-math.otf"
MAINFONTS = None

FONTSPLITTING_EXTRA = {}

FONTDATA = {
"FileVersion": "2.3",
"Year": "2013",
Expand Down
2 changes: 2 additions & 0 deletions fonts/OpenTypeMath/Gyre-Termes/config.py
Expand Up @@ -22,6 +22,8 @@
MATHFONT="texgyretermes-math.otf"
MAINFONTS = None

FONTSPLITTING_EXTRA = {}

FONTDATA = {
"FileVersion": "2.3",
"Year": "2013",
Expand Down
2 changes: 2 additions & 0 deletions fonts/OpenTypeMath/Latin-Modern/config.py
Expand Up @@ -22,6 +22,8 @@
MATHFONT = "latinmodern-math.otf"
MAINFONTS = None

FONTSPLITTING_EXTRA = {}

FONTDATA = {
"FileVersion": "2.3",
"Year": "2013",
Expand Down
2 changes: 2 additions & 0 deletions fonts/OpenTypeMath/Neo-Euler/config.py
Expand Up @@ -22,6 +22,8 @@
MATHFONT = "euler.otf"
MAINFONTS = None

FONTSPLITTING_EXTRA = {}

FONTDATA = {
"FileVersion": "2.3",
"Year": "2013",
Expand Down
75 changes: 74 additions & 1 deletion fonts/OpenTypeMath/STIX-Web/config.py
Expand Up @@ -26,7 +26,80 @@
"Bold": "STIX-Bold.otf",
"Italic": "STIX-Italic.otf",
"BoldItalic": "STIX-BoldItalic.otf"
}

FONTSPLITTING_EXTRA = {
"Alphabets": {
(0xE053,0xE057),
0xE05D,
0xE068,
0xE0A2,
0xE0B3,
(0xE0BD,0xE0BE),
(0xE0DD,0xE0E2),
(0xE17C,0xE1B3),
(0xE2FC,0xE370)
},
"Marks": {
0xE05E,
(0xE061,0xE067),
(0xE0D8,0xE0DA),
(0xE28C,0xE28D)
},
"Arrows": {
(0xE112,0xE115),
(0xE11A,0xE11F),
(0xE120,0xE137)
},
"Operators": {
(0xE004,0xE02B),
(0xE035,0xE052),
(0xE059,0xE05C),
(0xE06B,0xE098),
0xE0BB,
0xE0EC,
(0xE109,0xE10A),
(0xE14C,0xE14F),
0xE28E,
(0xE292,0xE293),
(0xE3C2,0xE3C4)
},
"Symbols": {
(0xE0BF,0xE0D6), # Chemical structures
(0xE09A,0xE09B)
},
"Shapes": {
(0xE000,0xE002),
0xE099,
(0xE0A7,0xE0B2),
0xE0D7,
0xE0E3,
(0xE0E5,0xE0EB),
(0xE0ED,0xE0EF),
0xE0F1,
0xE104,
(0xE10C,0xE111),
(0xE116,0xE119),
(0xE28F,0xE291),
(0xE3C7,0xE3C8),
("uni25A9.var", 0xE400)
},
"Misc": {
0xE02F,
(0xE0B4,0xE0B9),
0xE0BC,
(0xE0DB,0xE0DC),
(0xE0A4,0xE0A6),
(0xE0F2,0xE0F7), # Physics
(0xE0F8,0xE0FA),
(0xE0FB,0xE103),
(0xE105,0xE108),
(0xE138,0xE13A)
},
"Variants": {
(0xE261,0xE285) # oldstyle numbers
}
}

FONTDATA = {
"FileVersion": "2.3",
Expand Down Expand Up @@ -66,7 +139,7 @@
TEXOLDSTYLE = "offsetN: 0xE261, remap: {0xE262: 0xE265, 0xE263: 0xE269, \
0xE264: 0xE26D, 0xE265: 0xE271, 0xE266: 0xE275, 0xE267: 0xE279, \
0xE268: 0xE27D, 0xE269: 0xE281, 0xE26A: 0xE285}"
TEXOLDSTYLEFONTS = ["NONUNICODE"]
TEXOLDSTYLEFONTS = ["VARIANTS"]

SMALLOPFONTS = None

Expand Down
9 changes: 5 additions & 4 deletions fonts/OpenTypeMath/fontSplitting.py
Expand Up @@ -18,8 +18,8 @@

# This table must be sorted.
#
# The script searching in this table assumes it to be sorted. If it does not
# found a character, it will assume it is "NONUNICODE".
# fontUtil::computeNormalSizeSplitting assumes the table to be sorted. If it
# does not found a character, it will assume it is "NONUNICODE".
#

COPYRIGHT = "Copyright (c) 2013 The MathJax Consortium"
Expand Down Expand Up @@ -321,7 +321,7 @@
(0xA720, 0xA7FF), # Latin Extended-D
(0xFB00, 0xFB4F) # Alphabetic Presentation Forms
],
["Alphabets"
["Alphabets",
(0x0384, 0x0390), # Greek and Coptic
(0x03AA, 0x03B0), # Greek and Coptic
(0x03CA, 0x03CE), # Greek and Coptic
Expand Down Expand Up @@ -372,5 +372,6 @@
(0x2150, 0x218F), # Number Forms
(0x2460, 0x24FF), # Enclosed Alphanumerics
(0x2700, 0x27BF) # Dingbats
]
],
["Variants"] # Used for oldstyle numbers and glyph variants
]
33 changes: 29 additions & 4 deletions fonts/OpenTypeMath/fontUtil.py
Expand Up @@ -18,6 +18,7 @@

from __future__ import print_function

import sys
from shutil import copyfile
import fontforge
from fontSplitting import FONTSPLITTING, COPYRIGHT
Expand Down Expand Up @@ -87,11 +88,18 @@ def saveFont(aFamily, aFont):
aFont.generate("%s/ttf/%s.ttf" % (aFamily, aFont.fontname))
aFont.generate("%s/svg/%s.svg" % (aFamily, aFont.fontname))

def hasNonEmptyGlyph(aFont, aGlyphName):
# Check that the font has the glyph and that this glyph is not empty.
if not(aGlyphName in aFont and
aFont[aGlyphName].isWorthOutputting()):
return False

return True

def moveGlyph(aFontFrom, aFontTo, aOldPosition, aNewPosition = None):
# Ignore glyphs that have already been deleted before
# (Otherwise, FontForge will copy them as "blank" glyphs)
if not(aOldPosition in aFontFrom and
aFontFrom[aOldPosition].isWorthOutputting()):
if not hasNonEmptyGlyph(aFontFrom, aOldPosition):
return

# Move the glyph from the font aFontFrom at position aOldPosition
Expand All @@ -109,6 +117,20 @@ def moveRange(aFontFrom, aFontTo, aRangeStart, aRangeEnd):
for codePoint in range(aRangeStart, aRangeEnd+1):
moveGlyph(aFontFrom, aFontTo, codePoint)

def moveSubset(aFontFrom, aFontTo, aSubset):
# move the glyphs in a subset described.
for r in aSubset:
if type(r) == int:
# Single code point: move one glyph.
moveGlyph(aFontFrom, aFontTo, r)
elif type(r) == tuple:
if type(r[0]) == int:
# (start, end): move the range of glyphs.
moveRange(aFontFrom, aFontTo, r[0], r[1])
elif type(r[0]) == str:
# (glyphname, newcodepoint): move a non-Unicode glyph
moveGlyph(aFontFrom, aFontTo, r[0], r[1])

def getTestString(aFont, aMaxLength):
s = ""
# Pick at most 10 glyphs from the font to build a test string
Expand Down Expand Up @@ -441,6 +463,9 @@ def computeNormalSizeSplitting(self):
size0[codePoint] = name.upper()
break

# FIXME: also search in FONTSPLITTING_EXTRA?
# (In theory this should not be needed, since NonUnicode components
# are directly copied into SizeMax).
if not(found):
size0[codePoint] = "NONUNICODE"

Expand Down Expand Up @@ -584,7 +609,7 @@ def moveToPlane0PUA(self, aGlyphName):
if aGlyphName not in self.mPUAContent:
# New piece: copy it into the PUA and save the code point.
if self.mPUAPointer > 0xF8FF:
raise BaseException("Too many characters in the PUA. Not supported by the font splitter.")
raise BaseException("Too many characters in the Plane 0 PUA. Not supported by the font splitter.")
codePoint = self.mPUAPointer
self.mMathFont.selection.select(aGlyphName)
self.mMathFont.copy()
Expand All @@ -607,7 +632,7 @@ def copySizeVariant(self, aIsHorizontal, aSize,
style = aStyle
elif aSize == 0:
if self.isPrivateCharacter(aGlyphName):
print("Warning: non-Unicode glyphs %s used for the normal size! Will be copied to the PUA of Size %d..." % (aGlyphName, self.mMaxSize))
print("Warning: non-Unicode glyphs %s used for the normal size! Will be copied to the PUA of Size %d..." % (aGlyphName, self.mMaxSize), file=sys.stderr)
style = None
codePoint = self.moveToPlane0PUA(aGlyphName)
size = self.mMaxSize
Expand Down
29 changes: 22 additions & 7 deletions fonts/OpenTypeMath/splitFont.py
Expand Up @@ -110,12 +110,11 @@ def boolToString(b):
for subset in FONTSPLITTING:
name = subset[0]
font=fontUtil.newFont(FONTFAMILY, fontFile, config, name, weight)
for i in range(1,len(subset)):
r = subset[i]
if type(r) == int:
fontUtil.moveGlyph(oldfont, font, r)
else:
fontUtil.moveRange(oldfont, font, r[0], r[1])
fontUtil.moveSubset(oldfont, font, subset)

if name in config.FONTSPLITTING_EXTRA:
fontUtil.moveSubset(oldfont, font,
config.FONTSPLITTING_EXTRA[name])

if name == "Monospace" and "u1D670" in font:
# For the monospace font, ensure that the space has the
Expand All @@ -131,8 +130,24 @@ def boolToString(b):

# Save the rest of the glyphs in a NonUnicode font
font=fontUtil.newFont(FONTFAMILY, fontFile, config, "NonUnicode", weight)
PUAPointer = 0xE000
for g in oldfont.glyphs():
fontUtil.moveGlyph(oldfont, font, g.glyphname)

if g.glyphname == ".notdef":
continue

if PUAPointer > 0xF8FF:
raise BaseException("Too many characters in the Plane 0 PUA. Not supported by the font splitter.")

if fontUtil.hasNonEmptyGlyph(oldfont, PUAPointer):
print("Warning: 0x%X is already present in the Plane 0 PUA of the original font. %s will not be moved." % (PUAPointer, g.glyphname),
file=sys.stderr)
fontUtil.moveGlyph(oldfont, font, g.glyphname)
else:
fontUtil.moveGlyph(oldfont, font, g.glyphname, PUAPointer)

PUAPointer += 1

fontUtil.saveFont(FONTFAMILY, font)
font.close()
oldfont.close()
Expand Down

0 comments on commit 5ef283f

Please sign in to comment.