Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
michael@0 | 1 | |
michael@0 | 2 | import os |
michael@0 | 3 | import textwrap |
michael@0 | 4 | from xml.etree import ElementTree |
michael@0 | 5 | from fontTools.ttLib import TTFont, newTable |
michael@0 | 6 | from fontTools.misc.psCharStrings import T2CharString |
michael@0 | 7 | from fontTools.ttLib.tables.otTables import GSUB,\ |
michael@0 | 8 | ScriptList, ScriptRecord, Script, DefaultLangSys,\ |
michael@0 | 9 | FeatureList, FeatureRecord, Feature,\ |
michael@0 | 10 | LookupList, Lookup, AlternateSubst, SingleSubst |
michael@0 | 11 | |
michael@0 | 12 | # paths |
michael@0 | 13 | directory = os.path.dirname(__file__) |
michael@0 | 14 | shellSourcePath = os.path.join(directory, "gsubtest-shell.ttx") |
michael@0 | 15 | shellTempPath = os.path.join(directory, "gsubtest-shell.otf") |
michael@0 | 16 | featureList = os.path.join(directory, "gsubtest-features.txt") |
michael@0 | 17 | javascriptData = os.path.join(directory, "gsubtest-features.js") |
michael@0 | 18 | outputPath = os.path.join(os.path.dirname(directory), "gsubtest-lookup%d") |
michael@0 | 19 | |
michael@0 | 20 | baseCodepoint = 0xe000 |
michael@0 | 21 | |
michael@0 | 22 | # ------- |
michael@0 | 23 | # Features |
michael@0 | 24 | # ------- |
michael@0 | 25 | |
michael@0 | 26 | f = open(featureList, "rb") |
michael@0 | 27 | text = f.read() |
michael@0 | 28 | f.close() |
michael@0 | 29 | mapping = [] |
michael@0 | 30 | for line in text.splitlines(): |
michael@0 | 31 | line = line.strip() |
michael@0 | 32 | if not line: |
michael@0 | 33 | continue |
michael@0 | 34 | if line.startswith("#"): |
michael@0 | 35 | continue |
michael@0 | 36 | # parse |
michael@0 | 37 | values = line.split("\t") |
michael@0 | 38 | tag = values.pop(0) |
michael@0 | 39 | mapping.append(tag); |
michael@0 | 40 | |
michael@0 | 41 | # -------- |
michael@0 | 42 | # Outlines |
michael@0 | 43 | # -------- |
michael@0 | 44 | |
michael@0 | 45 | def addGlyphToCFF(glyphName=None, program=None, private=None, globalSubrs=None, charStringsIndex=None, topDict=None, charStrings=None): |
michael@0 | 46 | charString = T2CharString(program=program, private=private, globalSubrs=globalSubrs) |
michael@0 | 47 | charStringsIndex.append(charString) |
michael@0 | 48 | glyphID = len(topDict.charset) |
michael@0 | 49 | charStrings.charStrings[glyphName] = glyphID |
michael@0 | 50 | topDict.charset.append(glyphName) |
michael@0 | 51 | |
michael@0 | 52 | def makeLookup1(): |
michael@0 | 53 | # make a variation of the shell TTX data |
michael@0 | 54 | f = open(shellSourcePath) |
michael@0 | 55 | ttxData = f.read() |
michael@0 | 56 | f.close() |
michael@0 | 57 | ttxData = ttxData.replace("__familyName__", "gsubtest-lookup1") |
michael@0 | 58 | tempShellSourcePath = shellSourcePath + ".temp" |
michael@0 | 59 | f = open(tempShellSourcePath, "wb") |
michael@0 | 60 | f.write(ttxData) |
michael@0 | 61 | f.close() |
michael@0 | 62 | |
michael@0 | 63 | # compile the shell |
michael@0 | 64 | shell = TTFont(sfntVersion="OTTO") |
michael@0 | 65 | shell.importXML(tempShellSourcePath) |
michael@0 | 66 | shell.save(shellTempPath) |
michael@0 | 67 | os.remove(tempShellSourcePath) |
michael@0 | 68 | |
michael@0 | 69 | # load the shell |
michael@0 | 70 | shell = TTFont(shellTempPath) |
michael@0 | 71 | |
michael@0 | 72 | # grab the PASS and FAIL data |
michael@0 | 73 | hmtx = shell["hmtx"] |
michael@0 | 74 | glyphSet = shell.getGlyphSet() |
michael@0 | 75 | |
michael@0 | 76 | failGlyph = glyphSet["F"] |
michael@0 | 77 | failGlyph.decompile() |
michael@0 | 78 | failGlyphProgram = list(failGlyph.program) |
michael@0 | 79 | failGlyphMetrics = hmtx["F"] |
michael@0 | 80 | |
michael@0 | 81 | passGlyph = glyphSet["P"] |
michael@0 | 82 | passGlyph.decompile() |
michael@0 | 83 | passGlyphProgram = list(passGlyph.program) |
michael@0 | 84 | passGlyphMetrics = hmtx["P"] |
michael@0 | 85 | |
michael@0 | 86 | # grab some tables |
michael@0 | 87 | hmtx = shell["hmtx"] |
michael@0 | 88 | cmap = shell["cmap"] |
michael@0 | 89 | |
michael@0 | 90 | # start the glyph order |
michael@0 | 91 | existingGlyphs = [".notdef", "space", "F", "P"] |
michael@0 | 92 | glyphOrder = list(existingGlyphs) |
michael@0 | 93 | |
michael@0 | 94 | # start the CFF |
michael@0 | 95 | cff = shell["CFF "].cff |
michael@0 | 96 | globalSubrs = cff.GlobalSubrs |
michael@0 | 97 | topDict = cff.topDictIndex[0] |
michael@0 | 98 | topDict.charset = existingGlyphs |
michael@0 | 99 | private = topDict.Private |
michael@0 | 100 | charStrings = topDict.CharStrings |
michael@0 | 101 | charStringsIndex = charStrings.charStringsIndex |
michael@0 | 102 | |
michael@0 | 103 | features = sorted(mapping) |
michael@0 | 104 | |
michael@0 | 105 | # build the outline, hmtx and cmap data |
michael@0 | 106 | cp = baseCodepoint |
michael@0 | 107 | for index, tag in enumerate(features): |
michael@0 | 108 | |
michael@0 | 109 | # tag.pass |
michael@0 | 110 | glyphName = "%s.pass" % tag |
michael@0 | 111 | glyphOrder.append(glyphName) |
michael@0 | 112 | addGlyphToCFF( |
michael@0 | 113 | glyphName=glyphName, |
michael@0 | 114 | program=passGlyphProgram, |
michael@0 | 115 | private=private, |
michael@0 | 116 | globalSubrs=globalSubrs, |
michael@0 | 117 | charStringsIndex=charStringsIndex, |
michael@0 | 118 | topDict=topDict, |
michael@0 | 119 | charStrings=charStrings |
michael@0 | 120 | ) |
michael@0 | 121 | hmtx[glyphName] = passGlyphMetrics |
michael@0 | 122 | |
michael@0 | 123 | for table in cmap.tables: |
michael@0 | 124 | if table.format == 4: |
michael@0 | 125 | table.cmap[cp] = glyphName |
michael@0 | 126 | else: |
michael@0 | 127 | raise NotImplementedError, "Unsupported cmap table format: %d" % table.format |
michael@0 | 128 | cp += 1 |
michael@0 | 129 | |
michael@0 | 130 | # tag.fail |
michael@0 | 131 | glyphName = "%s.fail" % tag |
michael@0 | 132 | glyphOrder.append(glyphName) |
michael@0 | 133 | addGlyphToCFF( |
michael@0 | 134 | glyphName=glyphName, |
michael@0 | 135 | program=failGlyphProgram, |
michael@0 | 136 | private=private, |
michael@0 | 137 | globalSubrs=globalSubrs, |
michael@0 | 138 | charStringsIndex=charStringsIndex, |
michael@0 | 139 | topDict=topDict, |
michael@0 | 140 | charStrings=charStrings |
michael@0 | 141 | ) |
michael@0 | 142 | hmtx[glyphName] = failGlyphMetrics |
michael@0 | 143 | |
michael@0 | 144 | for table in cmap.tables: |
michael@0 | 145 | if table.format == 4: |
michael@0 | 146 | table.cmap[cp] = glyphName |
michael@0 | 147 | else: |
michael@0 | 148 | raise NotImplementedError, "Unsupported cmap table format: %d" % table.format |
michael@0 | 149 | |
michael@0 | 150 | # bump this up so that the sequence is the same as the lookup 3 font |
michael@0 | 151 | cp += 3 |
michael@0 | 152 | |
michael@0 | 153 | # set the glyph order |
michael@0 | 154 | shell.setGlyphOrder(glyphOrder) |
michael@0 | 155 | |
michael@0 | 156 | # start the GSUB |
michael@0 | 157 | shell["GSUB"] = newTable("GSUB") |
michael@0 | 158 | gsub = shell["GSUB"].table = GSUB() |
michael@0 | 159 | gsub.Version = 1.0 |
michael@0 | 160 | |
michael@0 | 161 | # make a list of all the features we will make |
michael@0 | 162 | featureCount = len(features) |
michael@0 | 163 | |
michael@0 | 164 | # set up the script list |
michael@0 | 165 | scriptList = gsub.ScriptList = ScriptList() |
michael@0 | 166 | scriptList.ScriptCount = 1 |
michael@0 | 167 | scriptList.ScriptRecord = [] |
michael@0 | 168 | scriptRecord = ScriptRecord() |
michael@0 | 169 | scriptList.ScriptRecord.append(scriptRecord) |
michael@0 | 170 | scriptRecord.ScriptTag = "DFLT" |
michael@0 | 171 | script = scriptRecord.Script = Script() |
michael@0 | 172 | defaultLangSys = script.DefaultLangSys = DefaultLangSys() |
michael@0 | 173 | defaultLangSys.FeatureCount = featureCount |
michael@0 | 174 | defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount) |
michael@0 | 175 | defaultLangSys.ReqFeatureIndex = 65535 |
michael@0 | 176 | defaultLangSys.LookupOrder = None |
michael@0 | 177 | script.LangSysCount = 0 |
michael@0 | 178 | script.LangSysRecord = [] |
michael@0 | 179 | |
michael@0 | 180 | # set up the feature list |
michael@0 | 181 | featureList = gsub.FeatureList = FeatureList() |
michael@0 | 182 | featureList.FeatureCount = featureCount |
michael@0 | 183 | featureList.FeatureRecord = [] |
michael@0 | 184 | for index, tag in enumerate(features): |
michael@0 | 185 | # feature record |
michael@0 | 186 | featureRecord = FeatureRecord() |
michael@0 | 187 | featureRecord.FeatureTag = tag |
michael@0 | 188 | feature = featureRecord.Feature = Feature() |
michael@0 | 189 | featureList.FeatureRecord.append(featureRecord) |
michael@0 | 190 | # feature |
michael@0 | 191 | feature.FeatureParams = None |
michael@0 | 192 | feature.LookupCount = 1 |
michael@0 | 193 | feature.LookupListIndex = [index] |
michael@0 | 194 | |
michael@0 | 195 | # write the lookups |
michael@0 | 196 | lookupList = gsub.LookupList = LookupList() |
michael@0 | 197 | lookupList.LookupCount = featureCount |
michael@0 | 198 | lookupList.Lookup = [] |
michael@0 | 199 | for tag in features: |
michael@0 | 200 | # lookup |
michael@0 | 201 | lookup = Lookup() |
michael@0 | 202 | lookup.LookupType = 1 |
michael@0 | 203 | lookup.LookupFlag = 0 |
michael@0 | 204 | lookup.SubTableCount = 1 |
michael@0 | 205 | lookup.SubTable = [] |
michael@0 | 206 | lookupList.Lookup.append(lookup) |
michael@0 | 207 | # subtable |
michael@0 | 208 | subtable = SingleSubst() |
michael@0 | 209 | subtable.Format = 2 |
michael@0 | 210 | subtable.LookupType = 1 |
michael@0 | 211 | subtable.mapping = { |
michael@0 | 212 | "%s.pass" % tag : "%s.fail" % tag, |
michael@0 | 213 | "%s.fail" % tag : "%s.pass" % tag, |
michael@0 | 214 | } |
michael@0 | 215 | lookup.SubTable.append(subtable) |
michael@0 | 216 | |
michael@0 | 217 | path = outputPath % 1 + ".otf" |
michael@0 | 218 | if os.path.exists(path): |
michael@0 | 219 | os.remove(path) |
michael@0 | 220 | shell.save(path) |
michael@0 | 221 | |
michael@0 | 222 | # get rid of the shell |
michael@0 | 223 | if os.path.exists(shellTempPath): |
michael@0 | 224 | os.remove(shellTempPath) |
michael@0 | 225 | |
michael@0 | 226 | def makeLookup3(): |
michael@0 | 227 | # make a variation of the shell TTX data |
michael@0 | 228 | f = open(shellSourcePath) |
michael@0 | 229 | ttxData = f.read() |
michael@0 | 230 | f.close() |
michael@0 | 231 | ttxData = ttxData.replace("__familyName__", "gsubtest-lookup3") |
michael@0 | 232 | tempShellSourcePath = shellSourcePath + ".temp" |
michael@0 | 233 | f = open(tempShellSourcePath, "wb") |
michael@0 | 234 | f.write(ttxData) |
michael@0 | 235 | f.close() |
michael@0 | 236 | |
michael@0 | 237 | # compile the shell |
michael@0 | 238 | shell = TTFont(sfntVersion="OTTO") |
michael@0 | 239 | shell.importXML(tempShellSourcePath) |
michael@0 | 240 | shell.save(shellTempPath) |
michael@0 | 241 | os.remove(tempShellSourcePath) |
michael@0 | 242 | |
michael@0 | 243 | # load the shell |
michael@0 | 244 | shell = TTFont(shellTempPath) |
michael@0 | 245 | |
michael@0 | 246 | # grab the PASS and FAIL data |
michael@0 | 247 | hmtx = shell["hmtx"] |
michael@0 | 248 | glyphSet = shell.getGlyphSet() |
michael@0 | 249 | |
michael@0 | 250 | failGlyph = glyphSet["F"] |
michael@0 | 251 | failGlyph.decompile() |
michael@0 | 252 | failGlyphProgram = list(failGlyph.program) |
michael@0 | 253 | failGlyphMetrics = hmtx["F"] |
michael@0 | 254 | |
michael@0 | 255 | passGlyph = glyphSet["P"] |
michael@0 | 256 | passGlyph.decompile() |
michael@0 | 257 | passGlyphProgram = list(passGlyph.program) |
michael@0 | 258 | passGlyphMetrics = hmtx["P"] |
michael@0 | 259 | |
michael@0 | 260 | # grab some tables |
michael@0 | 261 | hmtx = shell["hmtx"] |
michael@0 | 262 | cmap = shell["cmap"] |
michael@0 | 263 | |
michael@0 | 264 | # start the glyph order |
michael@0 | 265 | existingGlyphs = [".notdef", "space", "F", "P"] |
michael@0 | 266 | glyphOrder = list(existingGlyphs) |
michael@0 | 267 | |
michael@0 | 268 | # start the CFF |
michael@0 | 269 | cff = shell["CFF "].cff |
michael@0 | 270 | globalSubrs = cff.GlobalSubrs |
michael@0 | 271 | topDict = cff.topDictIndex[0] |
michael@0 | 272 | topDict.charset = existingGlyphs |
michael@0 | 273 | private = topDict.Private |
michael@0 | 274 | charStrings = topDict.CharStrings |
michael@0 | 275 | charStringsIndex = charStrings.charStringsIndex |
michael@0 | 276 | |
michael@0 | 277 | features = sorted(mapping) |
michael@0 | 278 | |
michael@0 | 279 | # build the outline, hmtx and cmap data |
michael@0 | 280 | cp = baseCodepoint |
michael@0 | 281 | for index, tag in enumerate(features): |
michael@0 | 282 | |
michael@0 | 283 | # tag.pass |
michael@0 | 284 | glyphName = "%s.pass" % tag |
michael@0 | 285 | glyphOrder.append(glyphName) |
michael@0 | 286 | addGlyphToCFF( |
michael@0 | 287 | glyphName=glyphName, |
michael@0 | 288 | program=passGlyphProgram, |
michael@0 | 289 | private=private, |
michael@0 | 290 | globalSubrs=globalSubrs, |
michael@0 | 291 | charStringsIndex=charStringsIndex, |
michael@0 | 292 | topDict=topDict, |
michael@0 | 293 | charStrings=charStrings |
michael@0 | 294 | ) |
michael@0 | 295 | hmtx[glyphName] = passGlyphMetrics |
michael@0 | 296 | |
michael@0 | 297 | # tag.fail |
michael@0 | 298 | glyphName = "%s.fail" % tag |
michael@0 | 299 | glyphOrder.append(glyphName) |
michael@0 | 300 | addGlyphToCFF( |
michael@0 | 301 | glyphName=glyphName, |
michael@0 | 302 | program=failGlyphProgram, |
michael@0 | 303 | private=private, |
michael@0 | 304 | globalSubrs=globalSubrs, |
michael@0 | 305 | charStringsIndex=charStringsIndex, |
michael@0 | 306 | topDict=topDict, |
michael@0 | 307 | charStrings=charStrings |
michael@0 | 308 | ) |
michael@0 | 309 | hmtx[glyphName] = failGlyphMetrics |
michael@0 | 310 | |
michael@0 | 311 | # tag.default |
michael@0 | 312 | glyphName = "%s.default" % tag |
michael@0 | 313 | glyphOrder.append(glyphName) |
michael@0 | 314 | addGlyphToCFF( |
michael@0 | 315 | glyphName=glyphName, |
michael@0 | 316 | program=passGlyphProgram, |
michael@0 | 317 | private=private, |
michael@0 | 318 | globalSubrs=globalSubrs, |
michael@0 | 319 | charStringsIndex=charStringsIndex, |
michael@0 | 320 | topDict=topDict, |
michael@0 | 321 | charStrings=charStrings |
michael@0 | 322 | ) |
michael@0 | 323 | hmtx[glyphName] = passGlyphMetrics |
michael@0 | 324 | |
michael@0 | 325 | for table in cmap.tables: |
michael@0 | 326 | if table.format == 4: |
michael@0 | 327 | table.cmap[cp] = glyphName |
michael@0 | 328 | else: |
michael@0 | 329 | raise NotImplementedError, "Unsupported cmap table format: %d" % table.format |
michael@0 | 330 | cp += 1 |
michael@0 | 331 | |
michael@0 | 332 | # tag.alt1,2,3 |
michael@0 | 333 | for i in range(1,4): |
michael@0 | 334 | glyphName = "%s.alt%d" % (tag, i) |
michael@0 | 335 | glyphOrder.append(glyphName) |
michael@0 | 336 | addGlyphToCFF( |
michael@0 | 337 | glyphName=glyphName, |
michael@0 | 338 | program=failGlyphProgram, |
michael@0 | 339 | private=private, |
michael@0 | 340 | globalSubrs=globalSubrs, |
michael@0 | 341 | charStringsIndex=charStringsIndex, |
michael@0 | 342 | topDict=topDict, |
michael@0 | 343 | charStrings=charStrings |
michael@0 | 344 | ) |
michael@0 | 345 | hmtx[glyphName] = failGlyphMetrics |
michael@0 | 346 | for table in cmap.tables: |
michael@0 | 347 | if table.format == 4: |
michael@0 | 348 | table.cmap[cp] = glyphName |
michael@0 | 349 | else: |
michael@0 | 350 | raise NotImplementedError, "Unsupported cmap table format: %d" % table.format |
michael@0 | 351 | cp += 1 |
michael@0 | 352 | |
michael@0 | 353 | # set the glyph order |
michael@0 | 354 | shell.setGlyphOrder(glyphOrder) |
michael@0 | 355 | |
michael@0 | 356 | # start the GSUB |
michael@0 | 357 | shell["GSUB"] = newTable("GSUB") |
michael@0 | 358 | gsub = shell["GSUB"].table = GSUB() |
michael@0 | 359 | gsub.Version = 1.0 |
michael@0 | 360 | |
michael@0 | 361 | # make a list of all the features we will make |
michael@0 | 362 | featureCount = len(features) |
michael@0 | 363 | |
michael@0 | 364 | # set up the script list |
michael@0 | 365 | scriptList = gsub.ScriptList = ScriptList() |
michael@0 | 366 | scriptList.ScriptCount = 1 |
michael@0 | 367 | scriptList.ScriptRecord = [] |
michael@0 | 368 | scriptRecord = ScriptRecord() |
michael@0 | 369 | scriptList.ScriptRecord.append(scriptRecord) |
michael@0 | 370 | scriptRecord.ScriptTag = "DFLT" |
michael@0 | 371 | script = scriptRecord.Script = Script() |
michael@0 | 372 | defaultLangSys = script.DefaultLangSys = DefaultLangSys() |
michael@0 | 373 | defaultLangSys.FeatureCount = featureCount |
michael@0 | 374 | defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount) |
michael@0 | 375 | defaultLangSys.ReqFeatureIndex = 65535 |
michael@0 | 376 | defaultLangSys.LookupOrder = None |
michael@0 | 377 | script.LangSysCount = 0 |
michael@0 | 378 | script.LangSysRecord = [] |
michael@0 | 379 | |
michael@0 | 380 | # set up the feature list |
michael@0 | 381 | featureList = gsub.FeatureList = FeatureList() |
michael@0 | 382 | featureList.FeatureCount = featureCount |
michael@0 | 383 | featureList.FeatureRecord = [] |
michael@0 | 384 | for index, tag in enumerate(features): |
michael@0 | 385 | # feature record |
michael@0 | 386 | featureRecord = FeatureRecord() |
michael@0 | 387 | featureRecord.FeatureTag = tag |
michael@0 | 388 | feature = featureRecord.Feature = Feature() |
michael@0 | 389 | featureList.FeatureRecord.append(featureRecord) |
michael@0 | 390 | # feature |
michael@0 | 391 | feature.FeatureParams = None |
michael@0 | 392 | feature.LookupCount = 1 |
michael@0 | 393 | feature.LookupListIndex = [index] |
michael@0 | 394 | |
michael@0 | 395 | # write the lookups |
michael@0 | 396 | lookupList = gsub.LookupList = LookupList() |
michael@0 | 397 | lookupList.LookupCount = featureCount |
michael@0 | 398 | lookupList.Lookup = [] |
michael@0 | 399 | for tag in features: |
michael@0 | 400 | # lookup |
michael@0 | 401 | lookup = Lookup() |
michael@0 | 402 | lookup.LookupType = 3 |
michael@0 | 403 | lookup.LookupFlag = 0 |
michael@0 | 404 | lookup.SubTableCount = 1 |
michael@0 | 405 | lookup.SubTable = [] |
michael@0 | 406 | lookupList.Lookup.append(lookup) |
michael@0 | 407 | # subtable |
michael@0 | 408 | subtable = AlternateSubst() |
michael@0 | 409 | subtable.Format = 1 |
michael@0 | 410 | subtable.LookupType = 3 |
michael@0 | 411 | subtable.alternates = { |
michael@0 | 412 | "%s.default" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.fail" % tag], |
michael@0 | 413 | "%s.alt1" % tag : ["%s.pass" % tag, "%s.fail" % tag, "%s.fail" % tag], |
michael@0 | 414 | "%s.alt2" % tag : ["%s.fail" % tag, "%s.pass" % tag, "%s.fail" % tag], |
michael@0 | 415 | "%s.alt3" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.pass" % tag] |
michael@0 | 416 | } |
michael@0 | 417 | lookup.SubTable.append(subtable) |
michael@0 | 418 | |
michael@0 | 419 | path = outputPath % 3 + ".otf" |
michael@0 | 420 | if os.path.exists(path): |
michael@0 | 421 | os.remove(path) |
michael@0 | 422 | shell.save(path) |
michael@0 | 423 | |
michael@0 | 424 | # get rid of the shell |
michael@0 | 425 | if os.path.exists(shellTempPath): |
michael@0 | 426 | os.remove(shellTempPath) |
michael@0 | 427 | |
michael@0 | 428 | def makeJavascriptData(): |
michael@0 | 429 | features = sorted(mapping) |
michael@0 | 430 | outStr = [] |
michael@0 | 431 | |
michael@0 | 432 | outStr.append("") |
michael@0 | 433 | outStr.append("/* This file is autogenerated by makegsubfonts.py */") |
michael@0 | 434 | outStr.append("") |
michael@0 | 435 | outStr.append("/* ") |
michael@0 | 436 | outStr.append(" Features defined in gsubtest fonts with associated base") |
michael@0 | 437 | outStr.append(" codepoints for each feature:") |
michael@0 | 438 | outStr.append("") |
michael@0 | 439 | outStr.append(" cp = codepoint for feature featX") |
michael@0 | 440 | outStr.append("") |
michael@0 | 441 | outStr.append(" cp default PASS") |
michael@0 | 442 | outStr.append(" cp featX=1 FAIL") |
michael@0 | 443 | outStr.append(" cp featX=2 FAIL") |
michael@0 | 444 | outStr.append("") |
michael@0 | 445 | outStr.append(" cp+1 default FAIL") |
michael@0 | 446 | outStr.append(" cp+1 featX=1 PASS") |
michael@0 | 447 | outStr.append(" cp+1 featX=2 FAIL") |
michael@0 | 448 | outStr.append("") |
michael@0 | 449 | outStr.append(" cp+2 default FAIL") |
michael@0 | 450 | outStr.append(" cp+2 featX=1 FAIL") |
michael@0 | 451 | outStr.append(" cp+2 featX=2 PASS") |
michael@0 | 452 | outStr.append("") |
michael@0 | 453 | outStr.append("*/") |
michael@0 | 454 | outStr.append("") |
michael@0 | 455 | outStr.append("var gFeatures = {"); |
michael@0 | 456 | cp = baseCodepoint |
michael@0 | 457 | |
michael@0 | 458 | taglist = [] |
michael@0 | 459 | for tag in features: |
michael@0 | 460 | taglist.append("\"%s\": 0x%x" % (tag, cp)) |
michael@0 | 461 | cp += 4 |
michael@0 | 462 | |
michael@0 | 463 | outStr.append(textwrap.fill(", ".join(taglist), initial_indent=" ", subsequent_indent=" ")) |
michael@0 | 464 | outStr.append("};"); |
michael@0 | 465 | outStr.append(""); |
michael@0 | 466 | |
michael@0 | 467 | if os.path.exists(javascriptData): |
michael@0 | 468 | os.remove(javascriptData) |
michael@0 | 469 | |
michael@0 | 470 | f = open(javascriptData, "wb") |
michael@0 | 471 | f.write("\n".join(outStr)) |
michael@0 | 472 | f.close() |
michael@0 | 473 | |
michael@0 | 474 | |
michael@0 | 475 | # build fonts |
michael@0 | 476 | |
michael@0 | 477 | print "Making lookup type 1 font..." |
michael@0 | 478 | makeLookup1() |
michael@0 | 479 | |
michael@0 | 480 | print "Making lookup type 3 font..." |
michael@0 | 481 | makeLookup3() |
michael@0 | 482 | |
michael@0 | 483 | # output javascript data |
michael@0 | 484 | |
michael@0 | 485 | print "Making javascript data file..." |
michael@0 | 486 | makeJavascriptData() |