Merge m-c to inbound

This commit is contained in:
Ryan VanderMeulen 2012-06-10 21:36:29 -04:00
commit 21fa61e832
6 changed files with 1126 additions and 0 deletions

View File

@ -0,0 +1,85 @@
/* This file is autogenerated by makegsubfonts.py */
/*
Features defined in gsubtest fonts with associated base
codepoints for each feature:
cp = codepoint for feature featX
cp default PASS
cp featX=1 FAIL
cp featX=2 FAIL
cp+1 default FAIL
cp+1 featX=1 PASS
cp+1 featX=2 FAIL
cp+2 default FAIL
cp+2 featX=1 FAIL
cp+2 featX=2 PASS
*/
var gFeatures = {
"MWL1": 0xe000, "NUM2": 0xe004, "PRIV": 0xe008, "T3ST": 0xe00c,
"TPSP": 0xe010, "abvf": 0xe014, "abvm": 0xe018, "abvs": 0xe01c,
"afrc": 0xe020, "akhn": 0xe024, "blwf": 0xe028, "blwm": 0xe02c,
"blws": 0xe030, "c2pc": 0xe034, "c2sc": 0xe038, "calt": 0xe03c,
"case": 0xe040, "ccmp": 0xe044, "cfar": 0xe048, "cjct": 0xe04c,
"clig": 0xe050, "cpct": 0xe054, "cpsp": 0xe058, "cswh": 0xe05c,
"curs": 0xe060, "cv00": 0xe064, "cv01": 0xe068, "cv02": 0xe06c,
"cv03": 0xe070, "cv04": 0xe074, "cv05": 0xe078, "cv06": 0xe07c,
"cv07": 0xe080, "cv08": 0xe084, "cv09": 0xe088, "cv10": 0xe08c,
"cv11": 0xe090, "cv12": 0xe094, "cv13": 0xe098, "cv14": 0xe09c,
"cv15": 0xe0a0, "cv16": 0xe0a4, "cv17": 0xe0a8, "cv18": 0xe0ac,
"cv19": 0xe0b0, "cv20": 0xe0b4, "cv21": 0xe0b8, "cv22": 0xe0bc,
"cv23": 0xe0c0, "cv24": 0xe0c4, "cv25": 0xe0c8, "cv26": 0xe0cc,
"cv27": 0xe0d0, "cv28": 0xe0d4, "cv29": 0xe0d8, "cv30": 0xe0dc,
"cv31": 0xe0e0, "cv32": 0xe0e4, "cv33": 0xe0e8, "cv34": 0xe0ec,
"cv35": 0xe0f0, "cv36": 0xe0f4, "cv37": 0xe0f8, "cv38": 0xe0fc,
"cv39": 0xe100, "cv40": 0xe104, "cv41": 0xe108, "cv42": 0xe10c,
"cv43": 0xe110, "cv44": 0xe114, "cv45": 0xe118, "cv46": 0xe11c,
"cv47": 0xe120, "cv48": 0xe124, "cv49": 0xe128, "cv50": 0xe12c,
"cv51": 0xe130, "cv52": 0xe134, "cv53": 0xe138, "cv54": 0xe13c,
"cv55": 0xe140, "cv56": 0xe144, "cv57": 0xe148, "cv58": 0xe14c,
"cv59": 0xe150, "cv60": 0xe154, "cv61": 0xe158, "cv62": 0xe15c,
"cv63": 0xe160, "cv64": 0xe164, "cv65": 0xe168, "cv66": 0xe16c,
"cv67": 0xe170, "cv68": 0xe174, "cv69": 0xe178, "cv70": 0xe17c,
"cv71": 0xe180, "cv72": 0xe184, "cv73": 0xe188, "cv74": 0xe18c,
"cv75": 0xe190, "cv76": 0xe194, "cv77": 0xe198, "cv78": 0xe19c,
"cv79": 0xe1a0, "cv80": 0xe1a4, "cv81": 0xe1a8, "cv82": 0xe1ac,
"cv83": 0xe1b0, "cv84": 0xe1b4, "cv85": 0xe1b8, "cv86": 0xe1bc,
"cv87": 0xe1c0, "cv88": 0xe1c4, "cv89": 0xe1c8, "cv90": 0xe1cc,
"cv91": 0xe1d0, "cv92": 0xe1d4, "cv93": 0xe1d8, "cv94": 0xe1dc,
"cv95": 0xe1e0, "cv96": 0xe1e4, "cv97": 0xe1e8, "cv98": 0xe1ec,
"cv99": 0xe1f0, "dist": 0xe1f4, "dlig": 0xe1f8, "dnom": 0xe1fc,
"expt": 0xe200, "falt": 0xe204, "fin2": 0xe208, "fin3": 0xe20c,
"fina": 0xe210, "frac": 0xe214, "fwid": 0xe218, "half": 0xe21c,
"haln": 0xe220, "halt": 0xe224, "hist": 0xe228, "hkna": 0xe22c,
"hlig": 0xe230, "hngl": 0xe234, "hojo": 0xe238, "hwid": 0xe23c,
"init": 0xe240, "isol": 0xe244, "ital": 0xe248, "jalt": 0xe24c,
"jp04": 0xe250, "jp78": 0xe254, "jp83": 0xe258, "jp90": 0xe25c,
"kern": 0xe260, "lfbd": 0xe264, "liga": 0xe268, "ljmo": 0xe26c,
"lnum": 0xe270, "locl": 0xe274, "ltra": 0xe278, "ltrm": 0xe27c,
"mark": 0xe280, "med2": 0xe284, "medi": 0xe288, "mgrk": 0xe28c,
"mkmk": 0xe290, "mset": 0xe294, "nalt": 0xe298, "nlck": 0xe29c,
"nukt": 0xe2a0, "numr": 0xe2a4, "onum": 0xe2a8, "opbd": 0xe2ac,
"ordn": 0xe2b0, "ornm": 0xe2b4, "palt": 0xe2b8, "pcap": 0xe2bc,
"pkna": 0xe2c0, "pnum": 0xe2c4, "pref": 0xe2c8, "pres": 0xe2cc,
"pstf": 0xe2d0, "psts": 0xe2d4, "pwid": 0xe2d8, "qwid": 0xe2dc,
"rand": 0xe2e0, "rkrf": 0xe2e4, "rlig": 0xe2e8, "rphf": 0xe2ec,
"rtbd": 0xe2f0, "rtla": 0xe2f4, "rtlm": 0xe2f8, "ruby": 0xe2fc,
"salt": 0xe300, "sinf": 0xe304, "size": 0xe308, "smcp": 0xe30c,
"smpl": 0xe310, "ss00": 0xe314, "ss01": 0xe318, "ss02": 0xe31c,
"ss03": 0xe320, "ss04": 0xe324, "ss05": 0xe328, "ss06": 0xe32c,
"ss07": 0xe330, "ss08": 0xe334, "ss09": 0xe338, "ss10": 0xe33c,
"ss11": 0xe340, "ss12": 0xe344, "ss13": 0xe348, "ss14": 0xe34c,
"ss15": 0xe350, "ss16": 0xe354, "ss17": 0xe358, "ss18": 0xe35c,
"ss19": 0xe360, "ss20": 0xe364, "ss21": 0xe368, "subs": 0xe36c,
"sups": 0xe370, "swsh": 0xe374, "titl": 0xe378, "tjmo": 0xe37c,
"tnam": 0xe380, "tnum": 0xe384, "trad": 0xe388, "twid": 0xe38c,
"unic": 0xe390, "valt": 0xe394, "vatu": 0xe398, "vert": 0xe39c,
"vhal": 0xe3a0, "vjmo": 0xe3a4, "vkna": 0xe3a8, "vkrn": 0xe3ac,
"vpal": 0xe3b0, "vrt2": 0xe3b4, "zero": 0xe3b8
};

View File

@ -0,0 +1,251 @@
# Feature To Unicode Mapping
# --------------------------
# This file is structured as:
# feature tag target first alternate second alternate third alternate
# with tab being the delimiter.
#
# Lines beginning with # should be ignored.
# Empty or whitespace only lines should be ignored.
abvf
abvm
abvs
afrc
akhn
blwf
blwm
blws
calt
case
ccmp
cfar
cjct
clig
cpct
cpsp
cswh
curs
# cv00 is a deliberately invalid feature tag
cv00
cv01
cv02
cv03
cv04
cv05
cv06
cv07
cv08
cv09
cv10
cv11
cv12
cv13
cv14
cv15
cv16
cv17
cv18
cv19
cv20
cv21
cv22
cv23
cv24
cv25
cv26
cv27
cv28
cv29
cv30
cv31
cv32
cv33
cv34
cv35
cv36
cv37
cv38
cv39
cv40
cv41
cv42
cv43
cv44
cv45
cv46
cv47
cv48
cv49
cv50
cv51
cv52
cv53
cv54
cv55
cv56
cv57
cv58
cv59
cv60
cv61
cv62
cv63
cv64
cv65
cv66
cv67
cv68
cv69
cv70
cv71
cv72
cv73
cv74
cv75
cv76
cv77
cv78
cv79
cv80
cv81
cv82
cv83
cv84
cv85
cv86
cv87
cv88
cv89
cv90
cv91
cv92
cv93
cv94
cv95
cv96
cv97
cv98
cv99
c2pc
c2sc
dist
dlig
dnom
expt
falt
fin2
fin3
fina
frac
fwid
half
haln
halt
hist
hkna
hlig
hngl
hojo
hwid
init
isol
ital
jalt
jp78
jp83
jp90
jp04
kern
lfbd
liga
ljmo
lnum
locl
ltra
ltrm
mark
med2
medi
mgrk
mkmk
mset
nalt
nlck
nukt
numr
onum
opbd
ordn
ornm
palt
pcap
pkna
pnum
pref
pres
pstf
psts
pwid
qwid
rand
rkrf
rlig
rphf
rtbd
rtla
rtlm
ruby
salt
sinf
size
smcp
smpl
# ss00 is a deliberately invalid feature tag
ss00
ss01
ss02
ss03
ss04
ss05
ss06
ss07
ss08
ss09
ss10
ss11
ss12
ss13
ss14
ss15
ss16
ss17
ss18
ss19
ss20
# ss21 is a deliberately invalid feature tag
ss21
subs
sups
swsh
titl
tjmo
tnam
tnum
trad
twid
unic
valt
vatu
vert
vhal
vjmo
vkna
vkrn
vpal
vrt2
zero
MWL1
NUM2
PRIV
T3ST
TPSP

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,304 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<ttFont sfntVersion="OTTO" ttLibVersion="2.2">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="space"/>
<GlyphID id="2" name="F"/>
<GlyphID id="3" name="P"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xae4c554b"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Tue Mar 22 13:46:27 2011"/>
<modified value="Tue Mar 22 13:46:27 2011"/>
<xMin value="100"/>
<yMin value="-10"/>
<xMax value="2204"/>
<yMax value="710"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="1.0"/>
<ascent value="750"/>
<descent value="-250"/>
<lineGap value="9"/>
<advanceWidthMax value="2304"/>
<minLeftSideBearing value="100"/>
<minRightSideBearing value="100"/>
<xMaxExtent value="2204"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="4"/>
</hhea>
<maxp>
<tableVersion value="0x5000"/>
<numGlyphs value="4"/>
</maxp>
<OS_2>
<version value="4"/>
<xAvgCharWidth value="1525"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="None"/>
<fsSelection value="00000001 11000000"/>
<fsFirstCharIndex value="32"/>
<fsLastCharIndex value="80"/>
<sTypoAscender value="750"/>
<sTypoDescender value="-250"/>
<sTypoLineGap value="0"/>
<usWinAscent value="1000"/>
<usWinDescent value="0"/>
<ulCodePageRange1 value="00100000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="750"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContex value="0"/>
</OS_2>
<name>
<namerecord nameID="1" platformID="1" platEncID="0" langID="0x0">
__familyName__
</namerecord>
<namerecord nameID="2" platformID="1" platEncID="0" langID="0x0">
Regular
</namerecord>
<namerecord nameID="3" platformID="1" platEncID="0" langID="0x0">
1.000;TPSP;__familyName__-Regular
</namerecord>
<namerecord nameID="4" platformID="1" platEncID="0" langID="0x0">
__familyName__
</namerecord>
<namerecord nameID="5" platformID="1" platEncID="0" langID="0x0">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="1" platEncID="0" langID="0x0">
__familyName__-Regular
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="0" langID="0x0">
Tal Leming with modifications by John Daggett
</namerecord>
<namerecord nameID="14" platformID="3" platEncID="0" langID="0x0">
http://scripts.sil.org/OFL
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
__familyName__
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;TPSP;__familyName__-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
__familyName__
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
__familyName__-Regular
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Tal Leming with modifications by John Daggett
</namerecord>
<namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
http://scripts.sil.org/OFL
</namerecord>
</name>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
<map code="0x50" name="P"/><!-- LATIN CAPITAL LETTER P -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
<map code="0x50" name="P"/><!-- LATIN CAPITAL LETTER P -->
</cmap_format_4>
</cmap>
<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-75"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>
<CFF>
<CFFFont name="__familyName__-Regular">
<version value="001.000"/>
<FullName value="__familyName__"/>
<FamilyName value="__familyName__"/>
<Weight value="Normal"/>
<isFixedPitch value="0"/>
<ItalicAngle value="0"/>
<UnderlineThickness value="50"/>
<PaintType value="0"/>
<CharstringType value="2"/>
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FontBBox value="100 0 2204 750"/>
<StrokeWidth value="0"/>
<!-- charset is dumped separately as the 'GlyphOrder' element -->
<Encoding name="StandardEncoding"/>
<Private>
<BlueValues value="0 0"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<ForceBold value="0"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
<initialRandomSeed value="0"/>
<defaultWidthX value="750"/>
<nominalWidthX value="2406"/>
</Private>
<CharStrings>
<CharString name=".notdef">
endchar
</CharString>
<CharString name="F">
-102 787 hmoveto
31 119 rlineto
203 hlineto
32 -119 rlineto
246 hlineto
-213 700 rlineto
-296 hlineto
-213 -700 rlineto
-477 hmoveto
237 244 245 162 -245 130 287 164 -524 hlineto
1586 -700 rmoveto
518 180 -281 520 -237 hlineto
-332 -700 rmoveto
237 700 -237 hlineto
-434 -196 rmoveto
60 -228 rlineto
-120 hlineto
endchar
</CharString>
<CharString name="P">
-107 394 306 rmoveto
153 86 82 115 115 -86 82 -153 hvcurveto
-294 -15 91 -670 -91 -15 297 15 -101 291 hlineto
632 -291 rmoveto
-15 276 15 -67 vlineto
-254 690 rlineto
-12 hlineto
-219 -593 rlineto
-69 -25 -46 -28 -59 hhcurveto
-5 -15 259 15 -26 hlineto
-67 -35 34 71 26 hvcurveto
43 116 rlineto
232 hlineto
78 -221 rlineto
599 695 rmoveto
-28 -11 -5 -6 -14 -22 -44 34 -78 hhcurveto
-124 -91 -73 -106 -95 52 -64 147 -61 hvcurveto
126 -52 30 -44 -79 vvcurveto
-81 -55 -50 -81 -103 -85 70 168 -17 vhcurveto
-15 -253 15 hlineto
22 4 13 15 18 45 32 -37 98 hhcurveto
130 92 82 116 83 -32 66 -173 73 hvcurveto
-120 50 -33 43 72 vvcurveto
71 51 49 82 90 65 -92 -119 13 vhcurveto
15 226 hlineto
-1118 -207 rmoveto
-119 -49 -63 -96 vhcurveto
-82 364 82 hlineto
96 49 -63 -119 hvcurveto
312 53 rmoveto
108 -305 rlineto
-221 hlineto
1420 459 rmoveto
-28 -11 -5 -6 -14 -22 -44 34 -78 hhcurveto
-124 -91 -73 -106 -95 52 -64 147 -61 hvcurveto
126 -52 30 -44 -79 vvcurveto
-81 -55 -50 -81 -103 -85 70 168 -17 vhcurveto
-15 -253 15 hlineto
22 4 13 15 18 45 32 -37 98 hhcurveto
130 92 82 116 83 -32 66 -173 73 hvcurveto
-120 50 -33 43 72 vvcurveto
71 51 49 82 90 65 -92 -119 13 vhcurveto
15 226 hlineto
endchar
</CharString>
<CharString name="space">
endchar
</CharString>
</CharStrings>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF>
<hmtx>
<mtx name=".notdef" width="750" lsb="0"/>
<mtx name="F" width="2304" lsb="100"/>
<mtx name="P" width="2299" lsb="100"/>
<mtx name="space" width="750" lsb="0"/>
</hmtx>
</ttFont>

View File

@ -0,0 +1,486 @@
import os
import textwrap
from xml.etree import ElementTree
from fontTools.ttLib import TTFont, newTable
from fontTools.misc.psCharStrings import T2CharString
from fontTools.ttLib.tables.otTables import GSUB,\
ScriptList, ScriptRecord, Script, DefaultLangSys,\
FeatureList, FeatureRecord, Feature,\
LookupList, Lookup, AlternateSubst, SingleSubst
# paths
directory = os.path.dirname(__file__)
shellSourcePath = os.path.join(directory, "gsubtest-shell.ttx")
shellTempPath = os.path.join(directory, "gsubtest-shell.otf")
featureList = os.path.join(directory, "gsubtest-features.txt")
javascriptData = os.path.join(directory, "gsubtest-features.js")
outputPath = os.path.join(os.path.dirname(directory), "gsubtest-lookup%d")
baseCodepoint = 0xe000
# -------
# Features
# -------
f = open(featureList, "rb")
text = f.read()
f.close()
mapping = []
for line in text.splitlines():
line = line.strip()
if not line:
continue
if line.startswith("#"):
continue
# parse
values = line.split("\t")
tag = values.pop(0)
mapping.append(tag);
# --------
# Outlines
# --------
def addGlyphToCFF(glyphName=None, program=None, private=None, globalSubrs=None, charStringsIndex=None, topDict=None, charStrings=None):
charString = T2CharString(program=program, private=private, globalSubrs=globalSubrs)
charStringsIndex.append(charString)
glyphID = len(topDict.charset)
charStrings.charStrings[glyphName] = glyphID
topDict.charset.append(glyphName)
def makeLookup1():
# make a variation of the shell TTX data
f = open(shellSourcePath)
ttxData = f.read()
f.close()
ttxData = ttxData.replace("__familyName__", "gsubtest-lookup1")
tempShellSourcePath = shellSourcePath + ".temp"
f = open(tempShellSourcePath, "wb")
f.write(ttxData)
f.close()
# compile the shell
shell = TTFont(sfntVersion="OTTO")
shell.importXML(tempShellSourcePath)
shell.save(shellTempPath)
os.remove(tempShellSourcePath)
# load the shell
shell = TTFont(shellTempPath)
# grab the PASS and FAIL data
hmtx = shell["hmtx"]
glyphSet = shell.getGlyphSet()
failGlyph = glyphSet["F"]
failGlyph.decompile()
failGlyphProgram = list(failGlyph.program)
failGlyphMetrics = hmtx["F"]
passGlyph = glyphSet["P"]
passGlyph.decompile()
passGlyphProgram = list(passGlyph.program)
passGlyphMetrics = hmtx["P"]
# grab some tables
hmtx = shell["hmtx"]
cmap = shell["cmap"]
# start the glyph order
existingGlyphs = [".notdef", "space", "F", "P"]
glyphOrder = list(existingGlyphs)
# start the CFF
cff = shell["CFF "].cff
globalSubrs = cff.GlobalSubrs
topDict = cff.topDictIndex[0]
topDict.charset = existingGlyphs
private = topDict.Private
charStrings = topDict.CharStrings
charStringsIndex = charStrings.charStringsIndex
features = sorted(mapping)
# build the outline, hmtx and cmap data
cp = baseCodepoint
for index, tag in enumerate(features):
# tag.pass
glyphName = "%s.pass" % tag
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=passGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = passGlyphMetrics
for table in cmap.tables:
if table.format == 4:
table.cmap[cp] = glyphName
else:
raise NotImplementedError, "Unsupported cmap table format: %d" % table.format
cp += 1
# tag.fail
glyphName = "%s.fail" % tag
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=failGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = failGlyphMetrics
for table in cmap.tables:
if table.format == 4:
table.cmap[cp] = glyphName
else:
raise NotImplementedError, "Unsupported cmap table format: %d" % table.format
# bump this up so that the sequence is the same as the lookup 3 font
cp += 3
# set the glyph order
shell.setGlyphOrder(glyphOrder)
# start the GSUB
shell["GSUB"] = newTable("GSUB")
gsub = shell["GSUB"].table = GSUB()
gsub.Version = 1.0
# make a list of all the features we will make
featureCount = len(features)
# set up the script list
scriptList = gsub.ScriptList = ScriptList()
scriptList.ScriptCount = 1
scriptList.ScriptRecord = []
scriptRecord = ScriptRecord()
scriptList.ScriptRecord.append(scriptRecord)
scriptRecord.ScriptTag = "DFLT"
script = scriptRecord.Script = Script()
defaultLangSys = script.DefaultLangSys = DefaultLangSys()
defaultLangSys.FeatureCount = featureCount
defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount)
defaultLangSys.ReqFeatureIndex = 65535
defaultLangSys.LookupOrder = None
script.LangSysCount = 0
script.LangSysRecord = []
# set up the feature list
featureList = gsub.FeatureList = FeatureList()
featureList.FeatureCount = featureCount
featureList.FeatureRecord = []
for index, tag in enumerate(features):
# feature record
featureRecord = FeatureRecord()
featureRecord.FeatureTag = tag
feature = featureRecord.Feature = Feature()
featureList.FeatureRecord.append(featureRecord)
# feature
feature.FeatureParams = None
feature.LookupCount = 1
feature.LookupListIndex = [index]
# write the lookups
lookupList = gsub.LookupList = LookupList()
lookupList.LookupCount = featureCount
lookupList.Lookup = []
for tag in features:
# lookup
lookup = Lookup()
lookup.LookupType = 1
lookup.LookupFlag = 0
lookup.SubTableCount = 1
lookup.SubTable = []
lookupList.Lookup.append(lookup)
# subtable
subtable = SingleSubst()
subtable.Format = 2
subtable.LookupType = 1
subtable.mapping = {
"%s.pass" % tag : "%s.fail" % tag,
"%s.fail" % tag : "%s.pass" % tag,
}
lookup.SubTable.append(subtable)
path = outputPath % 1 + ".otf"
if os.path.exists(path):
os.remove(path)
shell.save(path)
# get rid of the shell
if os.path.exists(shellTempPath):
os.remove(shellTempPath)
def makeLookup3():
# make a variation of the shell TTX data
f = open(shellSourcePath)
ttxData = f.read()
f.close()
ttxData = ttxData.replace("__familyName__", "gsubtest-lookup3")
tempShellSourcePath = shellSourcePath + ".temp"
f = open(tempShellSourcePath, "wb")
f.write(ttxData)
f.close()
# compile the shell
shell = TTFont(sfntVersion="OTTO")
shell.importXML(tempShellSourcePath)
shell.save(shellTempPath)
os.remove(tempShellSourcePath)
# load the shell
shell = TTFont(shellTempPath)
# grab the PASS and FAIL data
hmtx = shell["hmtx"]
glyphSet = shell.getGlyphSet()
failGlyph = glyphSet["F"]
failGlyph.decompile()
failGlyphProgram = list(failGlyph.program)
failGlyphMetrics = hmtx["F"]
passGlyph = glyphSet["P"]
passGlyph.decompile()
passGlyphProgram = list(passGlyph.program)
passGlyphMetrics = hmtx["P"]
# grab some tables
hmtx = shell["hmtx"]
cmap = shell["cmap"]
# start the glyph order
existingGlyphs = [".notdef", "space", "F", "P"]
glyphOrder = list(existingGlyphs)
# start the CFF
cff = shell["CFF "].cff
globalSubrs = cff.GlobalSubrs
topDict = cff.topDictIndex[0]
topDict.charset = existingGlyphs
private = topDict.Private
charStrings = topDict.CharStrings
charStringsIndex = charStrings.charStringsIndex
features = sorted(mapping)
# build the outline, hmtx and cmap data
cp = baseCodepoint
for index, tag in enumerate(features):
# tag.pass
glyphName = "%s.pass" % tag
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=passGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = passGlyphMetrics
# tag.fail
glyphName = "%s.fail" % tag
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=failGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = failGlyphMetrics
# tag.default
glyphName = "%s.default" % tag
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=passGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = passGlyphMetrics
for table in cmap.tables:
if table.format == 4:
table.cmap[cp] = glyphName
else:
raise NotImplementedError, "Unsupported cmap table format: %d" % table.format
cp += 1
# tag.alt1,2,3
for i in range(1,4):
glyphName = "%s.alt%d" % (tag, i)
glyphOrder.append(glyphName)
addGlyphToCFF(
glyphName=glyphName,
program=failGlyphProgram,
private=private,
globalSubrs=globalSubrs,
charStringsIndex=charStringsIndex,
topDict=topDict,
charStrings=charStrings
)
hmtx[glyphName] = failGlyphMetrics
for table in cmap.tables:
if table.format == 4:
table.cmap[cp] = glyphName
else:
raise NotImplementedError, "Unsupported cmap table format: %d" % table.format
cp += 1
# set the glyph order
shell.setGlyphOrder(glyphOrder)
# start the GSUB
shell["GSUB"] = newTable("GSUB")
gsub = shell["GSUB"].table = GSUB()
gsub.Version = 1.0
# make a list of all the features we will make
featureCount = len(features)
# set up the script list
scriptList = gsub.ScriptList = ScriptList()
scriptList.ScriptCount = 1
scriptList.ScriptRecord = []
scriptRecord = ScriptRecord()
scriptList.ScriptRecord.append(scriptRecord)
scriptRecord.ScriptTag = "DFLT"
script = scriptRecord.Script = Script()
defaultLangSys = script.DefaultLangSys = DefaultLangSys()
defaultLangSys.FeatureCount = featureCount
defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount)
defaultLangSys.ReqFeatureIndex = 65535
defaultLangSys.LookupOrder = None
script.LangSysCount = 0
script.LangSysRecord = []
# set up the feature list
featureList = gsub.FeatureList = FeatureList()
featureList.FeatureCount = featureCount
featureList.FeatureRecord = []
for index, tag in enumerate(features):
# feature record
featureRecord = FeatureRecord()
featureRecord.FeatureTag = tag
feature = featureRecord.Feature = Feature()
featureList.FeatureRecord.append(featureRecord)
# feature
feature.FeatureParams = None
feature.LookupCount = 1
feature.LookupListIndex = [index]
# write the lookups
lookupList = gsub.LookupList = LookupList()
lookupList.LookupCount = featureCount
lookupList.Lookup = []
for tag in features:
# lookup
lookup = Lookup()
lookup.LookupType = 3
lookup.LookupFlag = 0
lookup.SubTableCount = 1
lookup.SubTable = []
lookupList.Lookup.append(lookup)
# subtable
subtable = AlternateSubst()
subtable.Format = 1
subtable.LookupType = 3
subtable.alternates = {
"%s.default" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.fail" % tag],
"%s.alt1" % tag : ["%s.pass" % tag, "%s.fail" % tag, "%s.fail" % tag],
"%s.alt2" % tag : ["%s.fail" % tag, "%s.pass" % tag, "%s.fail" % tag],
"%s.alt3" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.pass" % tag]
}
lookup.SubTable.append(subtable)
path = outputPath % 3 + ".otf"
if os.path.exists(path):
os.remove(path)
shell.save(path)
# get rid of the shell
if os.path.exists(shellTempPath):
os.remove(shellTempPath)
def makeJavascriptData():
features = sorted(mapping)
outStr = []
outStr.append("")
outStr.append("/* This file is autogenerated by makegsubfonts.py */")
outStr.append("")
outStr.append("/* ")
outStr.append(" Features defined in gsubtest fonts with associated base")
outStr.append(" codepoints for each feature:")
outStr.append("")
outStr.append(" cp = codepoint for feature featX")
outStr.append("")
outStr.append(" cp default PASS")
outStr.append(" cp featX=1 FAIL")
outStr.append(" cp featX=2 FAIL")
outStr.append("")
outStr.append(" cp+1 default FAIL")
outStr.append(" cp+1 featX=1 PASS")
outStr.append(" cp+1 featX=2 FAIL")
outStr.append("")
outStr.append(" cp+2 default FAIL")
outStr.append(" cp+2 featX=1 FAIL")
outStr.append(" cp+2 featX=2 PASS")
outStr.append("")
outStr.append("*/")
outStr.append("")
outStr.append("var gFeatures = {");
cp = baseCodepoint
taglist = []
for tag in features:
taglist.append("\"%s\": 0x%x" % (tag, cp))
cp += 4
outStr.append(textwrap.fill(", ".join(taglist), initial_indent=" ", subsequent_indent=" "))
outStr.append("};");
outStr.append("");
if os.path.exists(javascriptData):
os.remove(javascriptData)
f = open(javascriptData, "wb")
f.write("\n".join(outStr))
f.close()
# build fonts
print "Making lookup type 1 font..."
makeLookup1()
print "Making lookup type 3 font..."
makeLookup3()
# output javascript data
print "Making javascript data file..."
makeJavascriptData()