Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  makegsubfonts.py   Sprache: Python

 
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()

Messung V0.5
C=90 H=65 G=78

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge