diff options
Diffstat (limited to 'misc/pylib/robofab/gString.py')
-rwxr-xr-x | misc/pylib/robofab/gString.py | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/misc/pylib/robofab/gString.py b/misc/pylib/robofab/gString.py new file mode 100755 index 000000000..01f319da3 --- /dev/null +++ b/misc/pylib/robofab/gString.py @@ -0,0 +1,625 @@ +"""A bunch of stuff useful for glyph name comparisons and such. + +1. A group of sorted glyph name lists that can be called directly: +2. Some tools to work with glyph names to do things like build control strings.""" + +import string + +###################################################### +# THE LISTS +###################################################### + +uppercase_plain = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AE', 'OE', 'Oslash', 'Thorn', 'Eth',] + +uppercase_accents = ['Aacute', 'Abreve', 'Acaron', 'Acircumflex', 'Adblgrave', 'Adieresis', 'Agrave', 'Amacron', 'Aogonek', 'Aring', 'Aringacute', 'Atilde', 'Bdotaccent', 'Cacute', 'Ccaron', 'Ccircumflex', 'Cdotaccent', 'Dcaron', 'Dcedilla', 'Ddotaccent', 'Eacute', 'Ebreve', 'Ecaron', 'Ecircumflex', 'Edblgrave', 'Edieresis', 'Edotaccent', 'Egrave', 'Emacron', 'Eogonek', 'Etilde', 'Fdotaccent', 'Gacute', 'Gbreve', 'Gcaron', 'Gcedilla', 'Gcircumflex', 'Gcommaaccent', 'Gdotaccent', 'Gmacron', 'Hcedilla', 'Hcircumflex', 'Hdieresis', 'Hdotaccent', 'Iacute', 'Ibreve', 'Icaron', 'Icircumflex', 'Idblgrave', 'Idieresis', 'Idieresisacute', 'Idieresisacute', 'Idotaccent', 'Igrave', 'Imacron', 'Iogonek', 'Itilde', 'Jcircumflex', 'Kacute', 'Kcaron', 'Kcedilla', 'Kcommaaccent', 'Lacute', 'Lcaron', 'Lcedilla', 'Lcommaaccent', 'Ldotaccent', 'Macute', 'Mdotaccent', 'Nacute', 'Ncaron', 'Ncedilla', 'Ncommaaccent', 'Ndotaccent', 'Ntilde', 'Oacute', 'Obreve', 'Ocaron', 'Ocircumflex', 'Odblgrave', 'Odieresis', 'Ograve', 'Ohorn', 'Ohungarumlaut', 'Omacron', 'Oogonek', 'Otilde', 'Pacute', 'Pdotaccent', 'Racute', 'Rcaron', 'Rcedilla', 'Rcommaaccent', 'Rdblgrave', 'Rdotaccent', 'Sacute', 'Scaron', 'Scedilla', 'Scircumflex', 'Scommaaccent', 'Sdotaccent', 'Tcaron', 'Tcedilla', 'Tcommaaccent', 'Tdotaccent', 'Uacute', 'Ubreve', 'Ucaron', 'Ucircumflex', 'Udblgrave', 'Udieresis', 'Udieresisacute', 'Udieresisacute', 'Udieresisgrave', 'Udieresisgrave', 'Ugrave', 'Uhorn', 'Uhungarumlaut', 'Umacron', 'Uogonek', 'Uring', 'Utilde', 'Vtilde', 'Wacute', 'Wcircumflex', 'Wdieresis', 'Wdotaccent', 'Wgrave', 'Xdieresis', 'Xdotaccent', 'Yacute', 'Ycircumflex', 'Ydieresis', 'Ydotaccent', 'Ygrave', 'Ytilde', 'Zacute', 'Zcaron', 'Zcircumflex', 'Zdotaccent', 'AEacute', 'Ccedilla', 'Oslashacute', 'Ldot'] + +uppercase_special_accents = ['Dcroat', 'Lslash', 'Hbar', 'Tbar', 'LL', 'Eng'] + +uppercase_ligatures = ['IJ'] + +uppercase = uppercase_plain+uppercase_accents+uppercase_special_accents+uppercase_ligatures + +lowercase_plain = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'dotlessi', 'dotlessj', 'ae', 'oe', 'oslash', 'thorn', 'eth', 'germandbls', 'longs',] + +lowercase_accents = ['aacute', 'abreve', 'acaron', 'acircumflex', 'adblgrave', 'adieresis', 'agrave', 'amacron', 'aogonek', 'aring', 'aringacute', 'atilde', 'bdotaccent', 'cacute', 'ccaron', 'ccircumflex', 'cdotaccent', 'dcaron', 'dcedilla', 'ddotaccent', 'dmacron', 'eacute', 'ebreve', 'ecaron', 'ecircumflex', 'edblgrave', 'edieresis', 'edotaccent', 'egrave', 'emacron', 'eogonek', 'etilde', 'fdotaccent', 'gacute', 'gbreve', 'gcaron', 'gcedilla', 'gcircumflex', 'gcommaaccent', 'gdotaccent', 'gmacron', 'hcedilla', 'hcircumflex', 'hdieresis', 'hdotaccent', 'iacute', 'ibreve', 'icaron', 'icircumflex', 'idblgrave', 'idieresis', 'idieresisacute', 'idieresisacute', 'igrave', 'imacron', 'iogonek', 'itilde', 'jcaron', 'jcircumflex', 'kacute', 'kcaron', 'kcedilla', 'kcommaaccent', 'lacute', 'lcaron', 'lcedilla', 'lcommaaccent', 'ldotaccent', 'macute', 'mdotaccent', 'nacute', 'ncaron', 'ncedilla', 'ncommaaccent', 'ndotaccent', 'ntilde', 'oacute', 'obreve', 'ocaron', 'ocircumflex', 'odblgrave', 'odieresis', 'ograve', 'ohorn', 'ohungarumlaut', 'omacron', 'oogonek', 'otilde', 'pacute', 'pdotaccent', 'racute', 'rcaron', 'rcedilla', 'rcommaaccent', 'rdblgrave', 'rdotaccent', 'sacute', 'scaron', 'scedilla', 'scircumflex', 'scommaaccent', 'sdotaccent', 'tcaron', 'tcedilla', 'tcommaaccent', 'tdieresis', 'tdotaccent', 'uacute', 'ubreve', 'ucaron', 'ucircumflex', 'udblgrave', 'udieresis', 'udieresisacute', 'udieresisacute', 'udieresisgrave', 'udieresisgrave', 'ugrave', 'uhorn', 'uhungarumlaut', 'umacron', 'uogonek', 'uring', 'utilde', 'vtilde', 'wacute', 'wcircumflex', 'wdieresis', 'wdotaccent', 'wgrave', 'wring', 'xdieresis', 'xdotaccent', 'yacute', 'ycircumflex', 'ydieresis', 'ydotaccent', 'ygrave', 'yring', 'ytilde', 'zacute', 'zcaron', 'zcircumflex', 'zdotaccent', 'aeacute', 'ccedilla', 'oslashacute', 'ldot', ] + +lowercase_special_accents = ['dcroat', 'lslash', 'hbar', 'tbar', 'kgreenlandic', 'longs', 'll', 'eng'] + +lowercase_ligatures = ['fi', 'fl', 'ff', 'ffi', 'ffl', 'ij'] + +lowercase = lowercase_plain+lowercase_accents+lowercase_special_accents+lowercase_ligatures + +smallcaps_plain = ['A.sc', 'B.sc', 'C.sc', 'D.sc', 'E.sc', 'F.sc', 'G.sc', 'H.sc', 'I.sc', 'J.sc', 'K.sc', 'L.sc', 'M.sc', 'N.sc', 'O.sc', 'P.sc', 'Q.sc', 'R.sc', 'S.sc', 'T.sc', 'U.sc', 'V.sc', 'W.sc', 'X.sc', 'Y.sc', 'Z.sc', 'AE.sc', 'OE.sc', 'Oslash.sc', 'Thorn.sc', 'Eth.sc', ] + +smallcaps_accents = ['Aacute.sc', 'Acircumflex.sc', 'Adieresis.sc', 'Agrave.sc', 'Aring.sc', 'Atilde.sc', 'Ccedilla.sc', 'Eacute.sc', 'Ecircumflex.sc', 'Edieresis.sc', 'Egrave.sc', 'Iacute.sc', 'Icircumflex.sc', 'Idieresis.sc', 'Igrave.sc', 'Ntilde.sc', 'Oacute.sc', 'Ocircumflex.sc', 'Odieresis.sc', 'Ograve.sc', 'Otilde.sc', 'Scaron.sc', 'Uacute.sc', 'Ucircumflex.sc', 'Udieresis.sc', 'Ugrave.sc', 'Yacute.sc', 'Ydieresis.sc', 'Zcaron.sc', 'Ccedilla.sc', 'Lslash.sc', ] + +smallcaps_special_accents = ['Dcroat.sc', 'Lslash.sc', 'Hbar.sc', 'Tbar.sc', 'LL.sc', 'Eng.sc'] + +smallcaps_ligatures = ['IJ.sc'] + +smallcaps = smallcaps_plain + smallcaps_accents + smallcaps_special_accents + smallcaps_ligatures + +all_accents = uppercase_accents + uppercase_special_accents + lowercase_accents +lowercase_special_accents + smallcaps_accents + smallcaps_special_accents + +digits = ['one', 'onefitted', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero'] + +digits_oldstyle = ['eight.oldstyle', 'five.oldstyle', 'four.oldstyle', 'nine.oldstyle', 'one.oldstyle', 'seven.oldstyle', 'six.oldstyle', 'three.oldstyle', 'two.oldstyle', 'zero.oldstyle'] + +digits_superior = ['eight.superior', 'five.superior', 'four.superior', 'nine.superior', 'one.superior', 'seven.superior', 'six.superior', 'three.superior', 'two.superior', 'zero.superior'] + +digits_inferior = ['eight.inferior', 'five.inferior', 'four.inferior', 'nine.inferior', 'one.inferior', 'seven.inferior', 'three.inferior', 'two.inferior', 'zero.inferior'] + +fractions = ['oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onequarter', 'threequarters', 'onethird', 'twothirds', 'onehalf'] + +currency = ['dollar', 'cent', 'currency', 'Euro', 'sterling', 'yen', 'florin', 'franc', 'lira'] + +currency_oldstyle = ['cent.oldstyle', 'dollar.oldstyle'] + +currency_superior = ['cent.superior', 'dollar.superior'] + +currency_inferior = ['cent.inferior', 'dollar.inferior'] + +inferior = ['eight.inferior', 'five.inferior', 'four.inferior', 'nine.inferior', 'one.inferior', 'seven.inferior', 'three.inferior', 'two.inferior', 'zero.inferior', 'cent.inferior', 'dollar.inferior', 'comma.inferior', 'hyphen.inferior', 'parenleft.inferior', 'parenright.inferior', 'period.inferior'] + +superior = ['eight.superior', 'five.superior', 'four.superior', 'nine.superior', 'one.superior', 'seven.superior', 'six.superior', 'three.superior', 'two.superior', 'zero.superior', 'cent.superior', 'dollar.superior', 'Rsmallinverted.superior', 'a.superior', 'b.superior', 'comma.superior', 'd.superior', 'equal.superior', 'e.superior', 'glottalstopreversed.superior', 'hhook.superior', 'h.superior', 'hyphen.superior', 'i.superior', 'j.superior', 'l.superior', 'm.superior', 'n.superior', 'o.superior', 'parenleft.superior', 'parenright.superior', 'period.superior', 'plus.superior', 'r.superior', 'rturned.superior', 's.superior', 't.superior', 'w.superior', 'x.superior', 'y.superior'] + +accents = ['acute', 'acutecomb', 'breve', 'caron', 'cedilla', 'circumflex', 'commaaccent', 'dblgrave', 'dieresis', 'dieresisacute', 'dieresisacute', 'dieresisgrave', 'dieresisgrave', 'dotaccent', 'grave', 'dblgrave', 'gravecomb', 'hungarumlaut', 'macron', 'ogonek', 'ring', 'ringacute', 'tilde', 'tildecomb', 'horn', 'Acute.sc', 'Breve.sc', 'Caron.sc', 'Cedilla.sc', 'Circumflex.sc', 'Dieresis.sc', 'Dotaccent.sc', 'Grave.sc', 'Hungarumlaut.sc', 'Macron.sc', 'Ogonek.sc', 'Ring.sc', 'Tilde.sc'] + +dashes = ['hyphen', 'endash', 'emdash', 'threequartersemdash', 'underscore', 'underscoredbl', 'figuredash'] + +legal = ['trademark', 'trademarksans', 'trademarkserif', 'copyright', 'copyrightsans', 'copyrightserif', 'registered', 'registersans', 'registerserif'] + +ligatures = ['fi', 'fl', 'ff', 'ffi', 'ffl', 'ij', 'IJ'] + +punctuation = ['period', 'periodcentered', 'comma', 'colon', 'semicolon', 'ellipsis', 'exclam', 'exclamdown', 'exclamdbl', 'question', 'questiondown'] + +numerical = ['percent', 'perthousand', 'infinity', 'numbersign', 'degree', 'colonmonetary', 'dotmath'] + +slashes = ['slash', 'backslash', 'bar', 'brokenbar', 'fraction'] + +special = ['ampersand', 'paragraph', 'section', 'bullet', 'dagger', 'daggerdbl', 'asterisk', 'at', 'asciicircum', 'asciitilde'] + + +dependencies = { + 'A': ['Aacute', 'Abreve', 'Acaron', 'Acircumflex', 'Adblgrave', 'Adieresis', 'Agrave', 'Amacron', 'Aogonek', 'Aring', 'Aringacute', 'Atilde'], + 'B': ['Bdotaccent'], + 'C': ['Cacute', 'Ccaron', 'Ccircumflex', 'Cdotaccent', 'Ccedilla'], + 'D': ['Dcaron', 'Dcedilla', 'Ddotaccent'], + 'E': ['Eacute', 'Ebreve', 'Ecaron', 'Ecircumflex', 'Edblgrave', 'Edieresis', 'Edotaccent', 'Egrave', 'Emacron', 'Eogonek', 'Etilde'], + 'F': ['Fdotaccent'], + 'G': ['Gacute', 'Gbreve', 'Gcaron', 'Gcedilla', 'Gcircumflex', 'Gcommaaccent', 'Gdotaccent', 'Gmacron'], + 'H': ['Hcedilla', 'Hcircumflex', 'Hdieresis', 'Hdotaccent'], + 'I': ['Iacute', 'Ibreve', 'Icaron', 'Icircumflex', 'Idblgrave', 'Idieresis', 'Idieresisacute', 'Idieresisacute', 'Idotaccent', 'Igrave', 'Imacron', 'Iogonek', 'Itilde'], + 'J': ['Jcircumflex'], + 'K': ['Kacute', 'Kcaron', 'Kcedilla', 'Kcommaaccent'], + 'L': ['Lacute', 'Lcaron', 'Lcedilla', 'Lcommaaccent', 'Ldotaccent', 'Ldot'], + 'M': ['Macute', 'Mdotaccent'], + 'N': ['Nacute', 'Ncaron', 'Ncedilla', 'Ncommaaccent', 'Ndotaccent', 'Ntilde'], + 'O': ['Oacute', 'Obreve', 'Ocaron', 'Ocircumflex', 'Odblgrave', 'Odieresis', 'Ograve', 'Ohorn', 'Ohungarumlaut', 'Omacron', 'Oogonek', 'Otilde'], + 'P': ['Pacute', 'Pdotaccent'], + 'R': ['Racute', 'Rcaron', 'Rcedilla', 'Rcommaaccent', 'Rdblgrave', 'Rdotaccent'], + 'S': ['Sacute', 'Scaron', 'Scedilla', 'Scircumflex', 'Scommaaccent', 'Sdotaccent'], + 'T': ['Tcaron', 'Tcedilla', 'Tcommaaccent', 'Tdotaccent'], + 'U': ['Uacute', 'Ubreve', 'Ucaron', 'Ucircumflex', 'Udblgrave', 'Udieresis', 'Udieresisacute', 'Udieresisacute', 'Udieresisgrave', 'Udieresisgrave', 'Ugrave', 'Uhorn', 'Uhungarumlaut', 'Umacron', 'Uogonek', 'Uring', 'Utilde'], + 'V': ['Vtilde'], + 'W': ['Wacute', 'Wcircumflex', 'Wdieresis', 'Wdotaccent', 'Wgrave'], + 'X': ['Xdieresis', 'Xdotaccent'], + 'Y': ['Yacute', 'Ycircumflex', 'Ydieresis', 'Ydotaccent', 'Ygrave', 'Ytilde'], + 'Z': ['Zacute', 'Zcaron', 'Zcircumflex', 'Zdotaccent'], + 'AE': ['AEacute'], + 'Oslash': ['Oslashacute'], + + 'a': ['aacute', 'abreve', 'acaron', 'acircumflex', 'adblgrave', 'adieresis', 'agrave', 'amacron', 'aogonek', 'aring', 'aringacute', 'atilde'], + 'b': ['bdotaccent'], + 'c': ['cacute', 'ccaron', 'ccircumflex', 'cdotaccent', 'ccedilla'], + 'd': ['dcaron', 'dcedilla', 'ddotaccent', 'dmacron'], + 'e': ['eacute', 'ebreve', 'ecaron', 'ecircumflex', 'edblgrave', 'edieresis', 'edotaccent', 'egrave', 'emacron', 'eogonek', 'etilde'], + 'f': ['fdotaccent'], + 'g': ['gacute', 'gbreve', 'gcaron', 'gcedilla', 'gcircumflex', 'gcommaaccent', 'gdotaccent', 'gmacron'], + 'h': ['hcedilla', 'hcircumflex', 'hdieresis', 'hdotaccent'], + 'i': ['iacute', 'ibreve', 'icaron', 'icircumflex', 'idblgrave', 'idieresis', 'idieresisacute', 'idieresisacute', 'igrave', 'imacron', 'iogonek', 'itilde'], + 'j': ['jcaron', 'jcircumflex'], + 'k': ['kacute', 'kcaron', 'kcedilla', 'kcommaaccent'], + 'l': ['lacute', 'lcaron', 'lcedilla', 'lcommaaccent', 'ldotaccent', 'ldot'], + 'm': ['macute', 'mdotaccent'], + 'n': ['nacute', 'ncaron', 'ncedilla', 'ncommaaccent', 'ndotaccent', 'ntilde'], + 'o': ['oacute', 'obreve', 'ocaron', 'ocircumflex', 'odblgrave', 'odieresis', 'ograve', 'ohorn', 'ohungarumlaut', 'omacron', 'oogonek', 'otilde'], + 'p': ['pacute', 'pdotaccent'], + 'r': ['racute', 'rcaron', 'rcedilla', 'rcommaaccent', 'rdblgrave', 'rdotaccent'], + 's': ['sacute', 'scaron', 'scedilla', 'scircumflex', 'scommaaccent', 'sdotaccent'], + 't': ['tcaron', 'tcedilla', 'tcommaaccent', 'tdieresis', 'tdotaccent'], + 'u': ['uacute', 'ubreve', 'ucaron', 'ucircumflex', 'udblgrave', 'udieresis', 'udieresisacute', 'udieresisacute', 'udieresisgrave', 'udieresisgrave', 'ugrave', 'uhorn', 'uhungarumlaut', 'umacron', 'uogonek', 'uring', 'utilde'], + 'v': ['vtilde'], + 'w': ['wacute', 'wcircumflex', 'wdieresis', 'wdotaccent', 'wgrave', 'wring'], + 'x': ['xdieresis', 'xdotaccent'], + 'y': ['yacute', 'ycircumflex', 'ydieresis', 'ydotaccent', 'ygrave', 'yring', 'ytilde'], + 'z': ['zacute', 'zcaron', 'zcircumflex', 'zdotaccent'], + 'ae': ['aeacute'], + 'oslash': ['oslashacute'], + } +###################################################### +# MISC TOOLS +###################################################### + +def breakSuffix(glyphname): + """ + Breaks the glyphname into a two item list + 0: glyphname + 1: suffix + + if a suffix is not found it returns None + """ + if glyphname.find('.') != -1: + split = glyphname.split('.') + return split + else: + return None + +def findAccentBase(accentglyph): + """Return the base glyph of an accented glyph + for example: Ugrave.sc returns U.sc""" + base = splitAccent(accentglyph)[0] + return base + +def splitAccent(accentglyph): + """ + Split an accented glyph into a two items + 0: base glyph + 1: accent list + + for example: Yacute.scalt45 returns: (Y.scalt45, [acute]) + and: aacutetilde.alt45 returns (a.alt45, [acute, tilde]) + """ + base = None + suffix = '' + accentList=[] + broken = breakSuffix(accentglyph) + if broken is not None: + suffix = broken[1] + base = broken[0] + else: + base=accentglyph + ogbase=base + temp_special = lowercase_special_accents + uppercase_special_accents + if base in lowercase_plain + uppercase_plain + smallcaps_plain: + pass + elif base not in temp_special: + for accent in accents: + if base.find(accent) != -1: + base = base.replace(accent, '') + accentList.append(accent) + counter={} + for accent in accentList: + counter[ogbase.find(accent)] = accent + counterList = counter.keys() + counterList.sort() + finalAccents = [] + for i in counterList: + finalAccents.append(counter[i]) + accentList = finalAccents + if len(suffix) != 0: + base = '.'.join([base, suffix]) + return base, accentList + + +###################################################### +# UPPER, LOWER, SMALL +###################################################### + +casedict = { + 'germandbls' : 'S/S', + 'dotlessi' : 'I', + 'dotlessj' : 'J', + 'ae' : 'AE', + 'aeacute' : 'AEacute', + 'oe' : 'OE', + 'll' : 'LL' + } + +casedictflip = {} + +smallcapscasedict = { + 'germandbls' : 'S.sc/S.sc', + 'question' : 'question.sc', + 'questiondown' : 'questiondown.sc', + 'exclam' : 'exclam.sc', + 'exclamdown' : 'exclamdown.sc', + 'ampersand' : 'ampersand.sc' + } + +class _InternalCaseFunctions: + """internal functions for doing gymnastics with the casedicts""" + + def expandsmallcapscasedict(self): + for i in casedict.values(): + if i not in smallcapscasedict.keys(): + if len(i) > 1: + if i[:1].upper() == i[:1]: + smallcapscasedict[i] = i[:1] + i[1:] + '.sc' + + for i in uppercase: + if i + '.sc' in smallcaps: + if i not in smallcapscasedict.keys(): + smallcapscasedict[i] = i + '.sc' + + def flipcasedict(self): + for i in casedict.keys(): + if i.find('dotless') != -1: + i = i.replace('dotless', '') + casedictflip[casedict[i]] = i + + def expandcasedict(self): + for i in lowercase_ligatures: + casedict[i] = i.upper() + for i in lowercase: + if i not in casedict.keys(): + if string.capitalize(i) in uppercase: + casedict[i] = string.capitalize(i) + + +def upper(glyphstring): + """Convert all possible characters to uppercase in a glyph string.""" + + _InternalCaseFunctions().expandcasedict() + uc = [] + for i in glyphstring.split('/'): + if i.find('.sc') != -1: + if i[-3] != '.sc': + x = i.replace('.sc', '.') + else: + x = i.replace('.sc', '') + i = x + suffix = '' + bS = breakSuffix(i) + if bS is not None: + suffix = bS[1] + i = bS[0] + if i in casedict.keys(): + i = casedict[i] + if len(suffix) != 0: + i = '.'.join([i, suffix]) + uc.append(i) + return '/'.join(uc) + +def lower(glyphstring): + """Convert all possible characters to lowercase in a glyph string.""" + + _InternalCaseFunctions().expandcasedict() + _InternalCaseFunctions().flipcasedict() + lc = [] + for i in glyphstring.split('/'): + if i.find('.sc') != -1: + if i[-3] != '.sc': + x = i.replace('.sc', '.') + else: + x = i.replace('.sc', '') + i = x + suffix = '' + bS = breakSuffix(i) + if breakSuffix(i) is not None: + suffix = bS[1] + i = bS[0] + if i in casedictflip.keys(): + i = casedictflip[i] + if len(suffix) != 0: + i = '.'.join([i, suffix]) + lc.append(i) + return '/'.join(lc) + +def small(glyphstring): + """Convert all possible characters to smallcaps in a glyph string.""" + + _InternalCaseFunctions().expandcasedict() + _InternalCaseFunctions().expandsmallcapscasedict() + sc = [] + for i in glyphstring.split('/'): + suffix = '' + bS = breakSuffix(i) + if bS is not None: + suffix = bS[1] + if suffix == 'sc': + suffix = '' + i = bS[0] + if i in lowercase: + if i not in smallcapscasedict.keys(): + i = casedict[i] + if i in smallcapscasedict.keys(): + i = smallcapscasedict[i] + if i != 'S.sc/S.sc': + if len(suffix) != 0: + if i[-3:] == '.sc': + i = ''.join([i, suffix]) + else: + i = '.'.join([i, suffix]) + sc.append(i) + return '/'.join(sc) + + +###################################################### +# CONTROL STRING TOOLS +###################################################### + + +controldict = { + 'UC' : ['/H/H', '/H/O/H/O', '/O/O'], + 'LC' : ['/n/n', '/n/o/n/o', '/o/o'], + 'SC' : ['/H.sc/H.sc', '/H.sc/O.sc/H.sc/O.sc', '/O.sc/O.sc'], + 'DIGITS' : ['/one/one', '/one/zero/one/zero', '/zero/zero'], + } + + +def controls(glyphname): + """Send this a glyph name and get a control string + with all glyphs separated by slashes.""" + controlslist = [] + for value in controldict.values(): + for v in value: + for i in v.split('/'): + if len(i) > 0: + if i not in controlslist: + controlslist.append(i) + cs = '' + if glyphname in controlslist: + for key in controldict.keys(): + for v in controldict[key]: + if glyphname in v.split('/'): + con = controldict[key] + striptriple = [] + hold1 = '' + hold2 = '' + for i in ''.join(con).split('/'): + if len(i) != 0: + if i == hold1 and i == hold2: + pass + else: + striptriple.append(i) + hold1 = hold2 + hold2 = i + constr = '/' + '/'.join(striptriple) + # this is a bit of a hack since FL seems to have trouble + # when it encounters the same string more than once. + # so, let's stick the glyph at the end to differentiate it. + # for example: HHOHOOH and HHOHOOO + cs = constr + '/' + glyphname + else: + suffix = '' + bS = breakSuffix(glyphname) + if bS is not None: + suffix = bS[1] + glyphname = bS[0] + if suffix[:2] == 'sc': + controls = controldict['SC'] + elif glyphname in uppercase: + controls = controldict['UC'] + elif glyphname in lowercase: + controls = controldict['LC'] + elif glyphname in digits: + controls = controldict['DIGITS'] + else: + controls = controldict['UC'] + if len(suffix) != 0: + glyphname = '.'.join([glyphname, suffix]) + cs = controls[0] + '/' + glyphname + controls[1] + '/' + glyphname + controls[2] + return cs + + +def sortControlList(list): + """Roughly sort a list of control strings.""" + + controls = [] + for v in controldict.values(): + for w in v: + for x in w.split('/'): + if len(x) is not None: + if x not in controls: + controls.append(x) + temp_digits = digits + digits_oldstyle + fractions + temp_currency = currency + currency_oldstyle + ss_uppercase = [] + ss_lowercase = [] + ss_smallcaps = [] + ss_digits = [] + ss_currency = [] + ss_other = [] + for i in list: + glyphs = i.split('/') + c = glyphs[2] + for glyph in glyphs: + if len(glyph) is not None: + if glyph not in controls: + c = glyph + if c in uppercase: + ss_uppercase.append(i) + elif c in lowercase: + ss_lowercase.append(i) + elif c in smallcaps: + ss_smallcaps.append(i) + elif c in temp_digits: + ss_digits.append(i) + elif c in temp_currency: + ss_currency.append(i) + else: + ss_other.append(i) + ss_uppercase.sort() + ss_lowercase.sort() + ss_smallcaps.sort() + ss_digits.sort() + ss_currency.sort() + ss_other.sort() + return ss_uppercase + ss_lowercase + ss_smallcaps + ss_digits + ss_currency + ss_other + + +# under contruction! +kerncontroldict = { + 'UC/UC' : ['/H/H', '/H/O/H/O/O'], + 'UC/LC' : ['', '/n/n/o/n/e/r/s'], + 'UC/SORTS' : ['/H/H', '/H/O/H/O/O'], + 'UC/DIGITS' : ['/H/H', '/H/O/H/O/O'], + 'LC/LC' : ['/n/n', '/n/o/n/o/o'], + 'LC/SORTS' : ['/n/n', '/n/o/n/o/o'], + 'LC/DIGITS' : ['', '/n/n/o/n/e/r/s'], + 'SC/SC' : ['/H.sc/H.sc', '/H.sc/O.sc/H.sc/O.sc/O.sc'], + 'UC/SC' : ['', '/H.sc/H.sc/O.sc/H.sc/O.sc/O.sc'], + 'SC/SORTS' : ['/H.sc/H.sc', '/H.sc/O.sc/H.sc/O.sc/O.sc'], + 'SC/DIGITS' : ['', '/H.sc/H.sc/O.sc/H.sc/O.sc/O.sc'], + 'DIGITS/DIGITS' : ['/H/H', '/H/O/H/O/O'], + 'DIGITS/SORTS' : ['/H/H', '/H/O/H/O/O'], + 'SORTS/SORTS' : ['/H/H', '/H/O/H/O/O'], + } + +def kernControls(leftglyphname, rightglyphname): + """build a control string based on the left glyph and right glyph""" + + sorts = currency + accents + dashes + legal + numerical + slashes + special + + l = leftglyphname + r = rightglyphname + lSuffix = '' + rSuffix = '' + bSL = breakSuffix(l) + if bSL is not None: + lSuffix = bSL[1] + l = bSL[0] + bSR = breakSuffix(r) + if bSR is not None: + rSuffix = bSR[1] + r = bSR[0] + if lSuffix[:2] == 'sc' or rSuffix[:2] == 'sc': + if l in uppercase or r in uppercase: + controls = kerncontroldict['UC/SC'] + elif l in digits or r in digits: + controls = kerncontroldict['SC/DIGITS'] + elif l in sorts or r in sorts: + controls = kerncontroldict['SC/SORTS'] + else: + controls = kerncontroldict['SC/SC'] + elif l in uppercase or r in uppercase: + if l in lowercase or r in lowercase: + controls = kerncontroldict['UC/LC'] + elif l in digits or r in digits: + controls = kerncontroldict['UC/DIGITS'] + elif l in sorts or r in sorts: + controls = kerncontroldict['UC/SORTS'] + else: + controls = kerncontroldict['UC/UC'] + elif l in lowercase or r in lowercase: + if l in uppercase or r in uppercase: + controls = kerncontroldict['UC/LC'] + elif l in digits or r in digits: + controls = kerncontroldict['LC/DIGITS'] + elif l in sorts or r in sorts: + controls = kerncontroldict['LC/SORTS'] + else: + controls = kerncontroldict['LC/LC'] + elif l in digits or r in digits: + if l in uppercase or r in uppercase: + controls = kerncontroldict['UC/DIGITS'] + elif l in lowercase or r in lowercase: + controls = kerncontroldict['LC/DIGITS'] + elif l in sorts or r in sorts: + controls = kerncontroldict['DIGITS/SORTS'] + else: + controls = kerncontroldict['DIGITS/DIGITS'] + elif l in sorts and r in sorts: + controls = kerncontroldict['SORTS/SORTS'] + else: + controls = kerncontroldict['UC/UC'] + + if len(lSuffix) != 0: + l = '.'.join([l, lSuffix]) + if len(rSuffix) != 0: + r = '.'.join([r, rSuffix]) + + cs = controls[0] + '/' + l + '/' + r + controls[1] + + return cs + + +###################################################### + +class _testing: + def __init__(self): + print + print '##### testing!' + # self.listtest() + # self.accentbasetest() + # self.controlstest() + self.upperlowersmalltest() + # self.stringsorttest() + + def listtest(self): + testlist = [ + uppercase, + uppercase_accents, + lowercase, + lowercase_accents, + smallcaps, + smallcaps_accents, + digits, + digits_oldstyle, + digits_superior, + digits_inferior, + fractions, + currency, + currency_oldstyle, + currency_superior, + currency_inferior, + inferior, + superior, + accents, + dashes, + legal, + ligatures, + punctuation, + numerical, + slashes, + special + ] + for i in testlist: + print i + + + def accentbasetest(self): + print findAccentBase('Adieresis') + print findAccentBase('Adieresis.sc') + print findAccentBase('Thorn.sc') + print findAccentBase('notaralglyphname') + + + def controlstest(self): + print kernControls('A', 'a.swash') + print kernControls('A.sc', '1') + print kernControls('bracket.sc', 'germandbls') + print kernControls('2', 'X') + print kernControls('Y', 'X') + print kernControls('Y.alt', 'X') + print kernControls('Y.scalt', 'X') + #print controls('x') + #print controls('germandbls') + #print controls('L') + #print controls('L.sc') + #print controls('Z.sc') + #print controls('seven') + #print controls('question') + #print controls('unknown') + + def upperlowersmalltest(self): + u = upper('/H/i/Z.sc/ampersand.sc/dotlessi/germandbls/four.superior/LL') + l = lower('/H/I/Z.sc/ampersand.sc/dotlessi/germandbls/four.superior/LL') + s = small('/H/i/Z.sc/ampersand.alt/dotlessi/germandbls/four.superior/LL') + print u + print l + print s + print lower(u) + print upper(l) + print upper(s) + print lower(s) + + def stringsorttest(self): + sample = "/H/H/Euro/H/O/H/O/Euro/O/O /H/H/R/H/O/H/O/R/O/O /H/H/question/H/O/H/O/question/O/O /H/H/sterling/H/O/H/O/sterling/O/O /n/n/r/n/o/n/o/r/o/o" + list = string.split(sample, ' ') + x = sortControlList(list) + print x + +if __name__ == '__main__': + _testing()
\ No newline at end of file |