summaryrefslogtreecommitdiff
path: root/misc/pylib/robofab/tools/accentBuilder.py
diff options
context:
space:
mode:
Diffstat (limited to 'misc/pylib/robofab/tools/accentBuilder.py')
-rwxr-xr-xmisc/pylib/robofab/tools/accentBuilder.py348
1 files changed, 0 insertions, 348 deletions
diff --git a/misc/pylib/robofab/tools/accentBuilder.py b/misc/pylib/robofab/tools/accentBuilder.py
deleted file mode 100755
index d122222fd..000000000
--- a/misc/pylib/robofab/tools/accentBuilder.py
+++ /dev/null
@@ -1,348 +0,0 @@
-"""A simple set of tools for building accented glyphs.
-# Hey look! A demonstration:
-from robofab.accentBuilder import AccentTools, buildRelatedAccentList
-font = CurrentFont
-# a list of accented glyphs that you want to build
-myList=['Aacute', 'aacute']
-# search for glyphs related to glyphs in myList and add them to myList
-myList=buildRelatedAccentList(font, myList)+myList
-# start the class
-at=AccentTools(font, myList)
-# clear away any anchors that exist (this is optional)
-at.clearAnchors()
-# add necessary anchors if you want to
-at.buildAnchors(ucXOffset=20, ucYOffset=40, lcXOffset=15, lcYOffset=30)
-# print a report of any errors that occured
-at.printAnchorErrors()
-# build the accented glyphs if you want to
-at.buildAccents()
-# print a report of any errors that occured
-at.printAccentErrors()
-"""
-#XXX! This is *very* experimental! I think it works, but you never know.
-
-from robofab.gString import lowercase_plain, accents, uppercase_plain, splitAccent, findAccentBase
-from robofab.tools.toolsAll import readGlyphConstructions
-import robofab
-from robofab.interface.all.dialogs import ProgressBar
-from robofab.world import RFWorld
-inFontLab = RFWorld().inFontLab
-
-anchorColor=125
-accentColor=75
-
-def stripSuffix(glyphName):
- """strip away unnecessary suffixes from a glyph name"""
- if glyphName.find('.') != -1:
- baseName = glyphName.split('.')[0]
- if glyphName.find('.sc') != -1:
- baseName = '.'.join([baseName, 'sc'])
- return baseName
- else:
- return glyphName
-
-def buildRelatedAccentList(font, list):
- """build a list of related glyphs suitable for use with AccentTools"""
- searchList = []
- baseGlyphs = {}
- foundList = []
- for glyphName in list:
- splitNames = splitAccent(glyphName)
- baseName = splitNames[0]
- accentNames = splitNames[1]
- if baseName not in searchList:
- searchList.append(baseName)
- if baseName not in baseGlyphs.keys():
- baseGlyphs[baseName] = [accentNames]
- else:
- baseGlyphs[baseName].append(accentNames)
- foundGlyphs = findRelatedGlyphs(font, searchList, doAccents=0)
- for baseGlyph in foundGlyphs.keys():
- for foundGlyph in foundGlyphs[baseGlyph]:
- for accentNames in baseGlyphs[baseGlyph]:
- foundList.append(makeAccentName(foundGlyph, accentNames))
- return foundList
-
-def findRelatedGlyphs(font, searchItem, doAccents=True):
- """Gather up a bunch of related glyph names. Send it either a
- single glyph name 'a', or a list of glyph names ['a', 'x'] and it
- returns a dict like: {'a': ['atilde', 'a.alt', 'a.swash']}. if doAccents
- is False it will skip accented glyph names.
- This is a relatively slow operation!"""
- relatedGlyphs = {}
- for name in font.keys():
- base = name.split('.')[0]
- if name not in relatedGlyphs.keys():
- relatedGlyphs[name] = []
- if base not in relatedGlyphs.keys():
- relatedGlyphs[base] = []
- if doAccents:
- accentBase = findAccentBase(name)
- if accentBase not in relatedGlyphs.keys():
- relatedGlyphs[accentBase] = []
- baseAccentBase = findAccentBase(base)
- if baseAccentBase not in relatedGlyphs.keys():
- relatedGlyphs[baseAccentBase] = []
- if base != name and name not in relatedGlyphs[base]:
- relatedGlyphs[base].append(name)
- if doAccents:
- if accentBase != name and name not in relatedGlyphs[accentBase]:
- relatedGlyphs[accentBase].append(name)
- if baseAccentBase != name and name not in relatedGlyphs[baseAccentBase]:
- relatedGlyphs[baseAccentBase].append(name)
- foundGlyphs = {}
- if isinstance(searchItem, str):
- searchList = [searchItem]
- else:
- searchList = searchItem
- for glyph in searchList:
- foundGlyphs[glyph] = relatedGlyphs[glyph]
- return foundGlyphs
-
-def makeAccentName(baseName, accentNames):
- """make an accented glyph name"""
- if isinstance(accentNames, str):
- accentNames = [accentNames]
- build = []
- if baseName.find('.') != -1:
- base = baseName.split('.')[0]
- suffix = baseName.split('.')[1]
- else:
- base = baseName
- suffix = ''
- build.append(base)
- for accent in accentNames:
- build.append(accent)
- buildJoin = ''.join(build)
- name = '.'.join([buildJoin, suffix])
- return name
-
-def nameBuster(glyphName, glyphConstruct):
- stripedSuffixName = stripSuffix(glyphName)
- suffix = None
- errors = []
- accentNames = []
- baseName = glyphName
- if glyphName.find('.') != -1:
- suffix = glyphName.split('.')[1]
- if glyphName.find('.sc') != -1:
- suffix = glyphName.split('.sc')[1]
- if stripedSuffixName not in glyphConstruct.keys():
- errors.append('%s: %s not in glyph construction database'%(glyphName, stripedSuffixName))
- else:
- if suffix is None:
- baseName = glyphConstruct[stripedSuffixName][0]
- else:
- if glyphName.find('.sc') != -1:
- baseName = ''.join([glyphConstruct[stripedSuffixName][0], suffix])
- else:
- baseName = '.'.join([glyphConstruct[stripedSuffixName][0], suffix])
- accentNames = glyphConstruct[stripedSuffixName][1:]
- return (baseName, stripedSuffixName, accentNames, errors)
-
-class AccentTools:
- def __init__(self, font, accentList):
- """several tools for working with anchors and building accents"""
- self.glyphConstructions = readGlyphConstructions()
- self.accentList = accentList
- self.anchorErrors = ['ANCHOR ERRORS:']
- self.accentErrors = ['ACCENT ERRORS:']
- self.font = font
-
- def clearAnchors(self, doProgress=True):
- """clear all anchors in the font"""
- tickCount = len(self.font)
- if doProgress:
- bar = ProgressBar("Cleaning all anchors...", tickCount)
- tick = 0
- for glyphName in self.accentList:
- if doProgress:
- bar.label(glyphName)
- baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions)
- existError = False
- if len(errors) > 0:
- existError = True
- if not existError:
- toClear = [baseName]
- for accent, position in accentNames:
- toClear.append(accent)
- for glyphName in toClear:
- try:
- self.font[glyphName].clearAnchors()
- except IndexError: pass
- if doProgress:
- bar.tick(tick)
- tick = tick+1
- if doProgress:
- bar.close()
-
- def buildAnchors(self, ucXOffset=0, ucYOffset=0, lcXOffset=0, lcYOffset=0, markGlyph=True, doProgress=True):
- """add the necessary anchors to the glyphs if they don't exist
- some flag definitions:
- uc/lc/X/YOffset=20 offset values for the anchors
- markGlyph=1 mark the glyph that is created
- doProgress=1 show a progress bar"""
- accentOffset = 10
- tickCount = len(self.accentList)
- if doProgress:
- bar = ProgressBar('Adding anchors...', tickCount)
- tick = 0
- for glyphName in self.accentList:
- if doProgress:
- bar.label(glyphName)
- previousPositions = {}
- baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions)
- existError = False
- if len(errors) > 0:
- existError = True
- for anchorError in errors:
- self.anchorErrors.append(anchorError)
- if not existError:
- existError = False
- try:
- self.font[baseName]
- except IndexError:
- self.anchorErrors.append(' '.join([glyphName, ':', baseName, 'does not exist.']))
- existError = True
- for accentName, accentPosition in accentNames:
- try:
- self.font[accentName]
- except IndexError:
- self.anchorErrors.append(' '.join([glyphName, ':', accentName, 'does not exist.']))
- existError = True
- if not existError:
- #glyph = self.font.newGlyph(glyphName, clear=True)
- for accentName, accentPosition in accentNames:
- if baseName.split('.')[0] in lowercase_plain:
- xOffset = lcXOffset-accentOffset
- yOffset = lcYOffset-accentOffset
- else:
- xOffset = ucXOffset-accentOffset
- yOffset = ucYOffset-accentOffset
- # should I add a cedilla and ogonek yoffset override here?
- if accentPosition not in previousPositions.keys():
- self._dropAnchor(self.font[baseName], accentPosition, xOffset, yOffset)
- if markGlyph:
- self.font[baseName].mark = anchorColor
- if inFontLab:
- self.font[baseName].update()
- else:
- self._dropAnchor(self.font[previousPositions[accentPosition]], accentPosition, xOffset, yOffset)
- self._dropAnchor(self.font[accentName], accentPosition, accentOffset, accentOffset, doAccentPosition=1)
- previousPositions[accentPosition] = accentName
- if markGlyph:
- self.font[accentName].mark = anchorColor
- if inFontLab:
- self.font[accentName].update()
- if inFontLab:
- self.font.update()
- if doProgress:
- bar.tick(tick)
- tick = tick+1
- if doProgress:
- bar.close()
-
- def printAnchorErrors(self):
- """print errors encounted during buildAnchors"""
- if len(self.anchorErrors) == 1:
- print 'No anchor errors encountered'
- else:
- for i in self.anchorErrors:
- print i
-
- def _dropAnchor(self, glyph, positionName, xOffset=0, yOffset=0, doAccentPosition=False):
- """anchor adding method. for internal use only."""
- existingAnchorNames = []
- for anchor in glyph.getAnchors():
- existingAnchorNames.append(anchor.name)
- if doAccentPosition:
- positionName = ''.join(['_', positionName])
- if positionName not in existingAnchorNames:
- glyphLeft, glyphBottom, glyphRight, glyphTop = glyph.box
- glyphXCenter = glyph.width/2
- if positionName == 'top':
- glyph.appendAnchor(positionName, (glyphXCenter, glyphTop+yOffset))
- elif positionName == 'bottom':
- glyph.appendAnchor(positionName, (glyphXCenter, glyphBottom-yOffset))
- elif positionName == 'left':
- glyph.appendAnchor(positionName, (glyphLeft-xOffset, glyphTop))
- elif positionName == 'right':
- glyph.appendAnchor(positionName, (glyphRight+xOffset, glyphTop))
- elif positionName == '_top':
- glyph.appendAnchor(positionName, (glyphXCenter, glyphBottom-yOffset))
- elif positionName == '_bottom':
- glyph.appendAnchor(positionName, (glyphXCenter, glyphTop+yOffset))
- elif positionName == '_left':
- glyph.appendAnchor(positionName, (glyphRight+xOffset, glyphTop))
- elif positionName == '_right':
- glyph.appendAnchor(positionName, (glyphLeft-xOffset, glyphTop))
- if inFontLab:
- glyph.update()
-
- def buildAccents(self, clear=True, adjustWidths=True, markGlyph=True, doProgress=True):
- """build accented glyphs. some flag definitions:
- clear=1 clear the glyphs if they already exist
- markGlyph=1 mark the glyph that is created
- doProgress=1 show a progress bar
- adjustWidths=1 will fix right and left margins when left or right accents are added"""
- tickCount = len(self.accentList)
- if doProgress:
- bar = ProgressBar('Building accented glyphs...', tickCount)
- tick = 0
- for glyphName in self.accentList:
- if doProgress:
- bar.label(glyphName)
- existError = False
- anchorError = False
-
- baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions)
- if len(errors) > 0:
- existError = True
- for accentError in errors:
- self.accentErrors.append(accentError)
-
- if not existError:
- baseAnchors = []
- try:
- self.font[baseName]
- except IndexError:
- self.accentErrors.append('%s: %s does not exist.'%(glyphName, baseName))
- existError = True
- else:
- for anchor in self.font[baseName].anchors:
- baseAnchors.append(anchor.name)
- for accentName, accentPosition in accentNames:
- accentAnchors = []
- try:
- self.font[accentName]
- except IndexError:
- self.accentErrors.append('%s: %s does not exist.'%(glyphName, accentName))
- existError = True
- else:
- for anchor in self.font[accentName].getAnchors():
- accentAnchors.append(anchor.name)
- if accentPosition not in baseAnchors:
- self.accentErrors.append('%s: %s not in %s anchors.'%(glyphName, accentPosition, baseName))
- anchorError = True
- if ''.join(['_', accentPosition]) not in accentAnchors:
- self.accentErrors.append('%s: %s not in %s anchors.'%(glyphName, ''.join(['_', accentPosition]), accentName))
- anchorError = True
- if not existError and not anchorError:
- destination = self.font.compileGlyph(glyphName, baseName, self.glyphConstructions[stripedSuffixName][1:], adjustWidths)
- if markGlyph:
- destination.mark = accentColor
- if doProgress:
- bar.tick(tick)
- tick = tick+1
- if doProgress:
- bar.close()
-
- def printAccentErrors(self):
- """print errors encounted during buildAccents"""
- if len(self.accentErrors) == 1:
- print 'No accent errors encountered'
- else:
- for i in self.accentErrors:
- print i
-
-