def _fakeEditor(): from fontio3.name import name _fakeNameTable = {(1, 0, 0, 290): "Tight", (1, 0, 0, 291): "Loose"} e = utilities.fakeEditor(0x1000) e.name = name.Name(_fakeNameTable) return e
def _fakeEditor(nameTableIndex): from fontio3 import name e = utilities.fakeEditor(0x10000) e.name = name.name.Name() e.name[(3, 1, 1033, nameTableIndex)] = "Test string" return e
def _makeTest(addStacker=False): """ The test case being made has two base marks, glyphs 40 and 45. There are 4 attaching marks: glyphs 12 (above), 13 (above), 14 (below), and 15 (below). If addStacker is True, glyph 40 will also be added as an attaching mark, as well as remaining a base mark. """ from fontio3 import hmtx from fontio3.GDEF import GDEF_v1 base1_above = anchor_coord.Anchor_Coord(300, 1700) base1_below = anchor_coord.Anchor_Coord(290, -75) base2_above = anchor_coord.Anchor_Coord(450, 1600) base2_below = anchor_coord.Anchor_Coord(450, -30) mark1_anchor = anchor_coord.Anchor_Coord(250, 110) mark2_anchor = anchor_coord.Anchor_Coord(350, 100) mark3_anchor = anchor_coord.Anchor_Coord(350, -20) mark4_anchor = anchor_coord.Anchor_Coord(255, 5) base1 = baserecord.BaseRecord([ base1_above, # class 0 base1_below ]) # class 1 base2 = baserecord.BaseRecord([ base2_above, # class 0 base2_below ]) # class 1 base = basearray.BaseArray({40: base1, 45: base2}) mark1 = markrecord.MarkRecord(0, mark1_anchor) mark2 = markrecord.MarkRecord(0, mark2_anchor) mark3 = markrecord.MarkRecord(1, mark3_anchor) mark4 = markrecord.MarkRecord(1, mark4_anchor) mark = markarray.MarkArray({ 12: mark1, 13: mark2, 14: mark3, 15: mark4 }) if addStacker: mark5_anchor = anchor_coord.Anchor_Coord(102, 104) mark5 = markrecord.MarkRecord(0, mark5_anchor) mark[40] = mark5 r = MarkToMark(mark, base) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[12] = hmtx.MtxEntry(0, 50) e.hmtx[30] = hmtx.MtxEntry(900, 50) e.hmtx[40] = hmtx.MtxEntry(0, 50) e.GDEF = GDEF_v1.GDEF() e.GDEF.glyphClasses[12] = 3 e.GDEF.glyphClasses[30] = 1 e.GDEF.glyphClasses[40] = 3 return r, e
def _fakeEditor(): from fontio3.glyf import glyf, ttsimpleglyph e = utilities.fakeEditor(0x10000) e.glyf = glyf.Glyf() e.glyf[40] = ttsimpleglyph._testingValues[2] return e
def _makeTest(): """ The test case here recognizes the glyph sequence 25-80-26, where 25 is the backtrack and 26 the lookahead. The position of glyph 80 is adjusted. """ from fontio3 import hmtx, utilities from fontio3.GPOS import single, value from fontio3.opentype import (lookup, pschainglyph_glyphtuple, pschainglyph_key, pslookupgroup, pslookuprecord) s1 = single.Single({80: value.Value(xPlacement=-25)}) lk1 = lookup.Lookup([s1]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) psg1 = pslookupgroup.PSLookupGroup([psr1]) backPart = pschainglyph_glyphtuple.GlyphTuple([25]) inPart = pschainglyph_glyphtuple.GlyphTuple([80]) lookPart = pschainglyph_glyphtuple.GlyphTuple([26]) key1 = pschainglyph_key.Key([backPart, inPart, lookPart]) r = ChainGlyph({key1: psg1}) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[25] = hmtx.MtxEntry(900, 50) e.hmtx[26] = hmtx.MtxEntry(970, 40) e.hmtx[80] = hmtx.MtxEntry(1020, 55) return r, e
def _makeTest(): """ The test case being made has two base glyphs, glyphs 40 and 45. There are 4 marks: glyphs 12 (above), 13 (above), 14 (below), and 15 (below). """ from fontio3 import hmtx from fontio3.GDEF import GDEF_v1 glyph1_above = anchor_coord.Anchor_Coord(300, 1700) glyph1_below = anchor_coord.Anchor_Coord(290, -75) glyph2_above = anchor_coord.Anchor_Coord(450, 1600) glyph2_below = anchor_coord.Anchor_Coord(450, -30) mark1_anchor = anchor_coord.Anchor_Coord(250, 110) mark2_anchor = anchor_coord.Anchor_Coord(350, 100) mark3_anchor = anchor_coord.Anchor_Coord(350, -20) mark4_anchor = anchor_coord.Anchor_Coord(255, 5) glyph1 = baserecord.BaseRecord([ glyph1_above, # class 0 glyph1_below ]) # class 1 glyph2 = baserecord.BaseRecord([ glyph2_above, # class 0 glyph2_below ]) # class 1 base = basearray.BaseArray({40: glyph1, 45: glyph2}) mark1 = markrecord.MarkRecord(0, mark1_anchor) mark2 = markrecord.MarkRecord(0, mark2_anchor) mark3 = markrecord.MarkRecord(1, mark3_anchor) mark4 = markrecord.MarkRecord(1, mark4_anchor) mark = markarray.MarkArray({ 12: mark1, 13: mark2, 14: mark3, 15: mark4 }) r = MarkToBase(mark, base) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[12] = hmtx.MtxEntry(0, 50) e.hmtx[13] = hmtx.MtxEntry(0, 30) e.hmtx[14] = hmtx.MtxEntry(0, 45) e.hmtx[15] = hmtx.MtxEntry(0, 55) e.hmtx[40] = hmtx.MtxEntry(900, 50) e.hmtx[45] = hmtx.MtxEntry(970, 50) e.GDEF = GDEF_v1.GDEF() e.GDEF.glyphClasses[12] = 3 e.GDEF.glyphClasses[13] = 3 e.GDEF.glyphClasses[14] = 3 e.GDEF.glyphClasses[15] = 3 return r, e
def _fakeEditor(): from fontio3.head import head from fontio3.glyf import glyf, ttsimpleglyph e = utilities.fakeEditor(200) e.glyf = glyf.Glyf() e.glyf[40] = ttsimpleglyph._testingValues[2] e.head = head.Head() return e
def _fakeEditor(nameIndices): from fontio3.name import name e = utilities.fakeEditor(0x10000) e.name = name.Name() for n in nameIndices: e.name[(1, 0, 0, n)] = "a name" return e
def _fakeEditor(): from fontio3 import hmtx from fontio3.glyf import glyf, ttsimpleglyph e = utilities.fakeEditor(0x10000) e.glyf = glyf.Glyf() e.glyf[40] = ttsimpleglyph._testingValues[2] e.hmtx = hmtx.Hmtx() e.hmtx[5] = hmtx.MtxEntry(2000, 50) e.hmtx[12] = hmtx.MtxEntry(2100, 40) e.hmtx[40] = hmtx.MtxEntry(0, 30) return e
def _fakeEditor(): from fontio3.name import name _fakeNameTable = { (1, 0, 0, 303): "Required Ligatures On", (1, 0, 0, 304): "Common Ligatures On", (1, 0, 0, 306): "Regular", (1, 0, 0, 307): "Small Caps" } e = utilities.fakeEditor(0x1000) e.name = name.Name(_fakeNameTable) return e
def _makeTest(): """ The test case here recognizes the glyph sequence 1-2-3, and adjusts the positioning of class 2. """ from fontio3 import hmtx, utilities from fontio3.GPOS import single, value from fontio3.opentype import (classdef, lookup, pschainclass_classtuple, pschainclass_key, pslookupgroup, pslookuprecord) v1 = value.Value(xPlacement=-25) v2 = value.Value(xPlacement=-29) s1 = single.Single({80: v1, 81: v2, 82: v1}) lk1 = lookup.Lookup([s1]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) psg = pslookupgroup.PSLookupGroup([psr1]) backPart = pschainclass_classtuple.ClassTuple([1]) inPart = pschainclass_classtuple.ClassTuple([1]) lookPart = pschainclass_classtuple.ClassTuple([1]) key = pschainclass_key.Key([backPart, inPart, lookPart]) cdBack = classdef.ClassDef({25: 1}) cdIn = classdef.ClassDef({80: 1, 81: 1, 82: 1}) cdLook = classdef.ClassDef({26: 1}) r = ChainClass({key: psg}, classDefBacktrack=cdBack, classDefInput=cdIn, classDefLookahead=cdLook) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[25] = hmtx.MtxEntry(900, 50) e.hmtx[26] = hmtx.MtxEntry(970, 40) e.hmtx[80] = hmtx.MtxEntry(1020, 55) e.hmtx[81] = hmtx.MtxEntry(1090, 85) e.hmtx[82] = hmtx.MtxEntry(1050, 70) return r, e
def _makeTest(): """ The test case here recognizes the glyph sequence 25-80-26, and adjusts the positioning of glyphs 25 and 26. """ from fontio3 import hmtx from fontio3.GPOS import single, value from fontio3.opentype import (lookup, pscontextglyph_key, pslookupgroup, pslookuprecord) s1 = single.Single({25: value.Value(xPlacement=-25)}) s2 = single.Single({26: value.Value(xPlacement=25)}) s3 = single.Single({12: value.Value(xPlacement=-15)}) s4 = single.Single({12: value.Value(xPlacement=15)}) lk1 = lookup.Lookup([s1]) lk2 = lookup.Lookup([s2]) lk3 = lookup.Lookup([s3]) lk4 = lookup.Lookup([s4]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) psr2 = pslookuprecord.PSLookupRecord(2, lk2) psr3 = pslookuprecord.PSLookupRecord(0, lk3) psr4 = pslookuprecord.PSLookupRecord(2, lk4) psg1 = pslookupgroup.PSLookupGroup([psr1, psr2]) psg2 = pslookupgroup.PSLookupGroup([psr3, psr4]) key1 = pscontextglyph_key.Key([25, 80, 26], ruleOrder=0) key2 = pscontextglyph_key.Key([12, 15, 12], ruleOrder=1) r = ContextGlyph({key1: psg1, key2: psg2}) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[12] = hmtx.MtxEntry(700, 50) e.hmtx[15] = hmtx.MtxEntry(690, 50) e.hmtx[25] = hmtx.MtxEntry(900, 50) e.hmtx[26] = hmtx.MtxEntry(970, 40) e.hmtx[80] = hmtx.MtxEntry(1020, 55) return r, e
def _fakeEditor(): """ For purposes of test cases, glyphs 10-19 are marks with zero advance, and glyphs 20-39 are bases, with advances equal to 40 times the glyph index. """ from fontio3 import hmtx e = utilities.fakeEditor(0x10000) h = e.hmtx = hmtx.Hmtx() ME = hmtx.MtxEntry for g in range(10, 20): h[g] = ME(0, 50) for g in range(20, 40): h[g] = ME(g * 40, 30) return e
def _makeTest(): from fontio3 import hmtx, utilities from fontio3.GPOS import single, value from fontio3.opentype import (coverageset, lookup, pschaincoverage_coveragetuple, pschaincoverage_key, pslookupgroup, pslookuprecord) v1 = value.Value(xPlacement=-25) v2 = value.Value(xPlacement=-29) s1 = single.Single({80: v1, 81: v2, 82: v1}) lk1 = lookup.Lookup([s1]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) psg = pslookupgroup.PSLookupGroup([psr1]) cs1 = coverageset.CoverageSet([20, 22]) cs2 = coverageset.CoverageSet([23]) cs3 = coverageset.CoverageSet([80, 81, 82]) cs4 = coverageset.CoverageSet([22]) cs5 = coverageset.CoverageSet([20, 40]) ct1 = pschaincoverage_coveragetuple.CoverageTuple([cs1, cs2]) ct2 = pschaincoverage_coveragetuple.CoverageTuple([cs3]) ct3 = pschaincoverage_coveragetuple.CoverageTuple([cs4, cs5]) key = pschaincoverage_key.Key([ct1, ct2, ct3]) r = ChainCoverage({key: psg}) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[20] = hmtx.MtxEntry(910, 42) e.hmtx[22] = hmtx.MtxEntry(900, 50) e.hmtx[23] = hmtx.MtxEntry(970, 40) e.hmtx[40] = hmtx.MtxEntry(890, 8) e.hmtx[80] = hmtx.MtxEntry(1020, 55) e.hmtx[81] = hmtx.MtxEntry(1090, 85) e.hmtx[82] = hmtx.MtxEntry(1020, 55) return r, e
def _makeTest(): from fontio3 import hmtx, utilities from fontio3.GPOS import single, value from fontio3.opentype import ( coverageset, lookup, pscontextcoverage_key, pslookupgroup, pslookuprecord) v1 = value.Value(xPlacement=-25) v2 = value.Value(xPlacement=-29) s1 = single.Single({20: v1, 25: v2}) lk1 = lookup.Lookup([s1]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) v1 = value.Value(xPlacement=-31) v2 = value.Value(xPlacement=-19) s2 = single.Single({25: v1, 26: v2}) lk2 = lookup.Lookup([s2]) psr2 = pslookuprecord.PSLookupRecord(2, lk2) psg = pslookupgroup.PSLookupGroup([psr1, psr2]) key = pscontextcoverage_key.Key([ coverageset.CoverageSet([20, 25]), coverageset.CoverageSet([81, 82]), coverageset.CoverageSet([25, 26])]) r = ContextCoverage({key: psg}) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[20] = hmtx.MtxEntry(910, 42) e.hmtx[25] = hmtx.MtxEntry(900, 50) e.hmtx[26] = hmtx.MtxEntry(970, 40) e.hmtx[80] = hmtx.MtxEntry(1020, 55) e.hmtx[81] = hmtx.MtxEntry(1090, 85) return r, e
def _makeTest(): """ The test case here recognizes the glyph sequence 1-2-3, and adjusts the positioning of classes 1 and 3. """ from fontio3 import hmtx, utilities from fontio3.GPOS import single, value from fontio3.opentype import ( classdef, lookup, pscontextclass_key, pslookupgroup, pslookuprecord) v1 = value.Value(xPlacement=-25) v2 = value.Value(xPlacement=-29) s1 = single.Single({20: v1, 25: v2}) lk1 = lookup.Lookup([s1]) psr1 = pslookuprecord.PSLookupRecord(0, lk1) s2 = single.Single({26: value.Value(xPlacement=25)}) lk2 = lookup.Lookup([s2]) psr2 = pslookuprecord.PSLookupRecord(2, lk2) psg = pslookupgroup.PSLookupGroup([psr1, psr2]) key = pscontextclass_key.Key([1, 2, 3]) cd = classdef.ClassDef({20: 1, 25: 1, 80: 2, 81: 2, 26: 3}) r = ContextClass({key: psg}, classDef=cd) e = utilities.fakeEditor(0x10000) e.hmtx = hmtx.Hmtx() e.hmtx[20] = hmtx.MtxEntry(910, 42) e.hmtx[25] = hmtx.MtxEntry(900, 50) e.hmtx[26] = hmtx.MtxEntry(970, 40) e.hmtx[80] = hmtx.MtxEntry(1020, 55) e.hmtx[81] = hmtx.MtxEntry(1090, 85) return r, e
def _fakeEditor(nameIndex): from fontio3.name import name e = utilities.fakeEditor(0x10000) e.name = name.Name({(1, 0, 0, nameIndex): "a name"}) return e
def fromfolder(cls, path, **kwArgs): """ Synthesize an Editor_UFO from reading a UFO "file" (which is actually a folder structure). """ raise NotImplementedError( "Reading UFOs is not currently supported, sorry!") e = fakeEditor(4, name=True) e.head = head.head.Head() e.hhea = hhea.Hhea() # # metainfo: http://unifiedfontobject.org/versions/ufo3/metainfo.html # ------------------------------------------------------------------ metainfopath = os.path.join(path, "metainfo.plist") metainfo = plistlib.readPlist(metainfopath) # # fontinfo: http://unifiedfontobject.org/versions/ufo3/fontinfo.html # ------------------------------------------------------------------ fontinfopath = os.path.join(path, "fontinfo.plist") if os.path.exists(fontinfopath): fontinfo = plistlib.readPlist(fontinfopath) # Generic Identification Information e.name[(3, 1, 1033, 1)] = fontinfo.get('familyName', 'Unknown') e.name[(3, 1, 1033, 2)] = fontinfo.get('styleName', 'Regular') if e.name[(3, 1, 1033, 2)] == 'Regular': e.name[(3, 1, 1033, 4)] = e.name[(3, 1, 1033, 2)] else: e.name[(3, 1, 1033, 4)] = "%s %s" % (e.name[(3, 1, 1033, 1)], e.name[(3, 1, 1033, 2)]) if 'styleMapFamilyName' in fontinfo: pass # e.head.macStyle = fontinfo.get('styleMapStyleName', 'Regular') vMaj = fontinfo.get('versionMajor', 1) vMin = fontinfo.get('versionMinor', 0) e.name[(3, 1, 1033, 5)] = "Version %d.%d - imported by fontio3" % (vMaj, vMin) e.head.fontRevision = (vMaj * 65536) + (vMin / 65536) # Generic Legal Information if 'copyright' in fontinfo: e.name[(3, 1, 1033, 0)] = fontinfo['copyright'] if 'trademark' in fontinfo: e.name[(3, 1, 1033, 7)] = fontinfo['trademark'] # Generic Dimension Information e.head.unitsPerEm = fontinfo.get('unitsPerEm', 2048) e.head.descent = fontinfo.get('descender', -410) if 'xHeight' in fontinfo: pass if 'capHeight' in fontinfo: pass e.head.ascent = fontinfo.get('ascender', 1634) if 'italicAngle' in fontinfo: pass # Generic Miscellaneous Information if 'note' in fontinfo: pass # OpenType gasp Table Fields if 'openTypeGaspRangeRecords' in fontinfo: e.gasp = gasp.gasp.Gasp() for rec in fontinfo['openTypeGaspRangeRecords']: pass # OpenType head Table Fields if 'openTypeHeadCreated' in fontinfo: e.head.created = time.strptime(fontinfo['openTypeHeadCreated'], "%Y/%m/%d %H:%M:%S") e.head.lowestRecPPEM = fontinfo.get('openTypeHeadLowestRecPPEM', 9) if 'openTypeHeadFlags' in fontinfo: for bitnum in fontinfo: e.head.flags[{ 0: 'baselineAtY0', 1: 'sidebearingAtX0', 2: 'opticalScalingViaHints', 3: 'forcePPEMToInteger', 4: 'opticalAdvanceViaHints', 5: 'verticalBaselineAtX0', 6: 'layoutRequired', 7: 'hasDefaultLayoutFeatures', 8: 'requiresReordering', 9: 'requiresRearrangement', 10: 'isMicrotypeLossless', 11: 'isConverted', 12: 'isClearType' }.get(bitnum)] = True # OpenType hhea Table Fields if 'openTypeHheaAscender' in fontinfo: e.hhea.ascent = fontinfo['openTypeHheaAscender'] if 'openTypeHheaDescender' in fontinfo: e.hhea.descent = fontinfo['openTypeHheaDescender'] if 'openTypeHheaLineGap' in fontinfo: e.hhea.lineGap = fontinfo['openTypeHheaLineGap'] if 'openTypeHheaCaretSlopeRise' in fontinfo: e.hhea.caretSlopeRise = fontinfo['openTypeHheaCaretSlopeRise'] if 'openTypeHheaCaretSlopeRun' in fontinfo: e.hhea.caretSlopeRun = fontinfo['openTypeHheaCaretSlopeRise'] if 'openTypeHheaCaretOffset' in fontinfo: e.hhea.caretOffset = fontinfo['openTypeHheaCaretOffset'] # OpenType Name Table Fields for k in _ufoKeyToNameIDMap: if k[0] in fontinfo: e.name[(3, 1, 1033, k[1])] = fontinfo[k[0]] if 'openTypeNameRecords' in fontinfo: for d in fontinfo['openTypeNameRecords']: k = (d['platformID'], d['encodingID'], d['languageID'], d['nameID']) e.name[k] = d['string'] return e
def _fakeEditor(): from fontio3.head import head e = utilities.fakeEditor(0x10000) e.head = head.Head() return e