예제 #1
0
    def replaceSuffixes(self, sender):
        """ Handle replacing/appending of suffixes. """
        mode = "replace" if self.w.replace.get() == 1 else "append"
        oldSuffix = self.w.oldSuffix.getItems()[self.w.oldSuffix.get()]
        enteredSuffix = self.w.newSuffix.get()
        suffixes_in = [oldSuffix, enteredSuffix]

        suffixes = []  # build proper suffixes list
        for s in suffixes_in:
            if s is not None and len(s) > 0:
                if s[0] == ".":
                    s = s[1:]  # handle suffixes without periods
            suffixes.append(s)

        if mode == "replace" and suffixes[0] == suffixes[1]:
            Message(
                u"Cannot replace a suffix with itself.\nI mean I could, but there seems to be little point :)"
            )
        elif mode == "append" and suffixes[1] == "":
            Message(
                u"Cannot append an empty suffix.\n(Or you could just pretend I've already done it.)"
            )

        else:
            scope = self.f.keys() if self.w.scope.get(
            ) == 1 else self.f.selection

            if mode == "replace":
                for gname in scope:
                    if gname.endswith(suffixes[0]):
                        sufLen = len(suffixes[0])
                        if len(suffixes[1]) > 0:
                            newName = gname[:-sufLen] + suffixes[1]
                        else:
                            sufLenWithPeriod = sufLen + 1
                            newName = gname[:-sufLenWithPeriod]
                        self._changeGlyphname(gname, newName)

            elif mode == "append":
                for gname in scope:
                    newName = gname + "." + suffixes[1]
                    self._changeGlyphname(gname, newName)

            self.f.update()

            # store new values as defaults
            savedPresets = getExtensionDefault(
                "nl.typologic.suffixer.presetSuffixes")
            if enteredSuffix != "" and enteredSuffix not in savedPresets:
                savedPresetsList = savedPresets.split()
                savedPresetsList.append(enteredSuffix)
                savedPresetsList.sort()
                newPresets = " ".join(savedPresetsList)
                setExtensionDefault("nl.typologic.suffixer.presetSuffixes",
                                    newPresets)

            self.w.close()
예제 #2
0
def dump(font):
	filePath = checkPath(font.path[:-4] + ".txt")

	if filePath is not None:
		tickCount = len(font)
		bar = ProgressBar('Writing dump file', tickCount)
		tick = 0
		outList = []
		for glyph in font:
			bar.tick(tick)
			tick = tick+1
			if len(glyph.components) != 0:
				output = glyph.name + ';' + str(glyph.width)
				componentNumber = 0
				while componentNumber < len(glyph.components):
					x, y = glyph.components[componentNumber].offset
					output = output + ';' + glyph.components[componentNumber].baseGlyph + ';' + str(x) + ';' + str(y)
					componentNumber = componentNumber + 1
				output = output + '\n'
				outList.append((glyph.index, output))

		# Create a dictionary for sorting the glyphs by GID
		outDictionary = dict(outList)
		outKeys = outDictionary.keys()
		outKeys.sort()
		
		# Write out the file
		file = open(filePath, 'w')
		keyCount = 0
		while keyCount < len(outKeys):
			file.write(outDictionary[outKeys[keyCount]])
			keyCount = keyCount + 1
		file.close()
		bar.close()
		Message('Dump file written')
예제 #3
0
    def startDialog(self):

        # Welcome message!
        Message("Hi! My name is typeStats.")

        # Mode
        verboso = AskYesNoCancel("Do you prefer the verbose mode?",
                                 title='typeStats',
                                 default=0)

        # Search path
        folder = GetFolder("Choose the directory to analyze")

        return folder, verboso
예제 #4
0
def fuse(font):
	readGlyphList = getDataFile(font.path, 'Choose a dump file')
	if readGlyphList is not None:
		# Check to make sure that all compontents are present in the font
		checkedGlyphList = checkGlyphs(font, readGlyphList)
		if len(checkedGlyphList) == 0:
			mark = AskYesNoCancel('Do you wish to mark changed glyphs?')
			if mark != -1:
				saveBackup = AskYesNoCancel('Do you want a backup of changed glyphs?')
				if saveBackup != -1:
					makeGlyph(readGlyphList, font, 'Updating glyphs', mark, saveBackup)
					font.update()
					Message('Done updating glyphs')
		else:
			# Gives a list of the components missing from the VFB
			OneList(checkedGlyphList, 'Sorry, your VFB is missing:')
예제 #5
0
    def checkFont(self, useSelection=False, excludeZeroWidth=True):
        f = CurrentFont()
        if f is not None:
            # initialize things
            self.w.options.progress.start()
            time0 = time.time()
            self.excludeZeroWidth = excludeZeroWidth
            self.f = f

            glyphNames = f.selection if useSelection else f.keys()
            glyphList = [f[x] for x in glyphNames]
            glyphList = self._trimGlyphList(glyphList)

            self.touchingPairs = Touche(f).findTouchingPairs(glyphList)

            # display output
            self.w.results.stats.set("%d glyphs checked" % len(glyphList))
            self.w.results.result.set("%d touching pairs found" %
                                      len(self.touchingPairs))
            self.w.results.show(True)

            outputList = [{
                "left glyph": g1,
                "right glyph": g2
            } for (g1, g2) in self.touchingPairs]
            self.w.outputList.set(outputList)
            if len(self.touchingPairs) > 0:
                self.w.outputList.setSelection([0])
            else:
                self.w.preview.set("")

            outputButtons = [
                self.w.results.spaceView, self.w.results.exportTxt
            ]
            for b in outputButtons:
                b.enable(False) if len(
                    self.touchingPairs) == 0 else b.enable(True)
            self.w.preview.setFont(f)
            self.w.options.progress.stop()
            self._resizeWindow(enlarge=True)

            time1 = time.time()
            print u'Touché: finished checking %d glyphs in %.2f seconds' % (
                len(glyphList), time1 - time0)

        else:
            Message(u'Touché: Can’t find a font to check')
예제 #6
0
def OpenFont(path=None, note=None):
    """Open a font from a path. If path is not given, present the user with a dialog."""
    if not note:
        note = 'select a .ufo directory'
    if not path:
        from robofab.interface.all.dialogs import GetFolder
        path = GetFolder(note)
    if path:
        try:
            return RFont(path)
        except OSError:
            from robofab.interface.all.dialogs import Message
            Message(
                "%s is not a valid .UFO font. But considering it's all XML, why don't  you have a look inside with a simple text editor."
                % (path))
    else:
        return None
예제 #7
0
    def checkFont(self, useSelection=False, excludeZeroWidth=True):
        f = CurrentFont()
        if f is not None:
            # initialize things
            self.w.options.progress.start()
            time0 = time.time()
            self.excludeZeroWidth = excludeZeroWidth
            self.f = f
    
            glyphNames = f.selection if useSelection else f.keys()
            glyphList = [f[x] for x in glyphNames]
            glyphList = self._trimGlyphList(glyphList)
            
            self.touchingPairs = Touche(f).findTouchingPairs(glyphList)
        
            # display output
            self.w.results.stats.set("%d glyphs checked" % len(glyphList))
            self.w.results.result.set("%d touching pairs found" % len(self.touchingPairs))
            self.w.results.show(True)
            
            outputList = [{"left glyph": g1, "right glyph": g2} for (g1, g2) in self.touchingPairs]

            outputStringList = [ "/%s/%s  " % (g1, g2) for (g1, g2) in self.touchingPairs ]
            outputStringMetalist = [outputStringList[i:i + 400] for i in range(0, len(outputStringList), 400)]

            ActiveFont = self.f._font
            ActiveFont.disableUpdateInterface()
            for eachList in outputStringMetalist:
                outputString = "".join(eachList)
                ActiveFont.newTab(outputString)

            self.w.outputList.set(outputList)
            if len(self.touchingPairs) > 0:
                self.w.outputList.setSelection([0])
            ActiveFont.enableUpdateInterface()
            
            #self.w.preview.setFont(f)
            self.w.options.progress.stop()
            self._resizeWindow(enlarge=True)
        
            time1 = time.time()
            print u'Touché: finished checking %d glyphs in %.2f seconds' % (len(glyphList), time1-time0)
            
        else:
            Message(u'Touché: Can’t find a font to check')
예제 #8
0
#MenuTitle: Swap Glyphs

# ###################################################################
#
# Swaps 2 Characters (basically just renaming each other)
#
# --> let me know if you have ideas for improving
# --> Mark Froemberg aka DeutschMark @ GitHub <--
#
# ToDo: -
#
# ###################################################################

Doc = Glyphs.currentDocument
Font = Glyphs.font
Selection = Font.selectedLayers

listOfGlyphNames = [x.parent.name for x in Selection]

if len(listOfGlyphNames) == 2:
    Selection[1].parent.name = "Temp"

    print listOfGlyphNames
    Selection[0].parent.name = listOfGlyphNames[1]
    Selection[1].parent.name = listOfGlyphNames[0]
else:
    #pass
    from robofab.interface.all.dialogs import Message
    Message("Select only TWO glyphs")
예제 #9
0
        return True


def getLayer(nakedFont, message):
    numberOfLayers = nakedFont[0].layers_number - 1
    layers = []
    while numberOfLayers >= 0:
        layers.append(numberOfLayers)
        numberOfLayers = numberOfLayers - 1
    whichLayer = OneList(layers, message)
    return int(whichLayer)


fontToChange = CurrentFont()
if not hasMM(fontToChange.naked()):
    Message('Font needs to be MM')
else:
    orignalMetricsFont = OpenFont(None,
                                  "Which font's sidebearings do you want?")
    orignalMetrics = {}
    tickCount = len(orignalMetricsFont)
    bar = ProgressBar('Getting metrics', tickCount)
    tick = 0

    if hasMM(orignalMetricsFont.naked()):
        layer = getLayer(orignalMetricsFont.naked(),
                         'Which layer do you want?')
        for glyph in orignalMetricsFont:
            advanceWidth = int(glyph.naked().GetMetrics(layer).x)
            glyphWidth = int(glyph.naked().GetBoundingRect(layer).width)
            glyphLeft = int(glyph.naked().GetBoundingRect(layer).x)
예제 #10
0
print "selection", todo
if g is not None:
	todo.append(g.name)
		
for f in AllFonts():
	ufoPath = None
	print "f.path", f, f.path
	if f.path is None:
		# huh, in case there is a ghost font.
		print "skipping", f
		continue
	ufoPath = f.path.replace(".vfb", ".ufo")
	if not os.path.exists(ufoPath):
		ufoPath = GetFolder("Select a UFO to save the GLIF in:")
		if ufoPath.find(".ufo") == -1:
			Message("You need to select an UFO. Quitting.")
			ufoPath = None
	if ufoPath is None:
		continue
	for c in todo:
		if c not in f:
			print "font is missing", c
			continue
		g = f[c]
		path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs")
		print "saving glyph %s in %s"%(g.name, path)
		gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName)
		gs.writeGlyph(g.name, g, g.drawPoints)
		gs.writeContents()

print 'done'
예제 #11
0
if buildSmallCap == 1:
    buildAccents(font, smallCapList, 'Building small cap accents', overwrite)

#Build a couple of accents that would be missed
#font.newGlyph('uni021B', clear=True)
#font.newGlyph('uni021A', clear=True)
#font.newGlyph('Dotlessi.sc', clear=True)
#dotlessisc = font['I.sc'].copy()
#duplicatetcommaaccent = font['tcommaaccent'].copy()
#duplicateTcommaaccent = font['Tcommaaccent'].copy()
#font['Dotlessi.sc'].appendGlyph(dotlessisc)
#font['uni021B'].appendGlyph(duplicatetcommaaccent)
#font['uni021A'].appendGlyph(duplicateTcommaaccent)
#font['uni021B'].width = duplicatetcommaaccent.width
#font['uni021B'].leftMargin = duplicatetcommaaccent.leftMargin
#font['uni021B'].rightMargin = duplicatetcommaaccent.rightMargin
#font['uni021B'].mark = 200
#font['uni021A'].width = duplicateTcommaaccent.width
#font['uni021A'].leftMargin = duplicateTcommaaccent.leftMargin
#font['uni021A'].rightMargin = duplicateTcommaaccent.rightMargin
#font['uni021A'].mark = 200
#font['Dotlessi.sc'].width = dotlessisc.width
#font['Dotlessi.sc'].leftMargin = dotlessisc.leftMargin
#font['Dotlessi.sc'].rightMargin = dotlessisc.rightMargin
#font['Dotlessi.sc'].mark = 200

font.update()

Message('Listo!')
예제 #12
0
#
#
#	demo of the RoboFab glyph object
#
#

import robofab
from robofab.world import CurrentFont, CurrentGlyph
from robofab.interface.all.dialogs import Message

# (make sure you have a font opened in FontLab)

# this code starts out the same as intro_FontObject
f = CurrentFont()
if f == None:
    Message("You should open a font first, there's nothing to look at now!")
else:
    for g in f:
        print "glyphname:", g.name, ", glyph width:", g.width
        # so now g is a RoboFab Glyph object
        print "this glyph has %d contours" % len(g.contours)
        print "this glyph has %d components" % len(g.components)
        print "this glyph has %d anchors" % len(g.anchors)
        print

# easy huh?
# There are many more attributes and methods.
# Most of these can be used to edit the font data.
# Which makes them not suited for a simple intro as this
# because we don't want to mess up your font.
예제 #13
0
font = CurrentFont()
filePath = PutFile()
file = open(filePath, 'w')
tickCount = len(font)
bar = ProgressBar('Writing dump file', tickCount)
tick = 0
outList = []
for glyph in font:
	bar.tick(tick)
	tick = tick+1
	if len(glyph.components) != 0:
		output = glyph.name + ';' + str(glyph.width)
		componentNumber = 0
		while componentNumber < len(glyph.components):
			x, y = glyph.components[componentNumber].offset
			output = output + ';' + glyph.components[componentNumber].baseGlyph + ';' + str(x) + ';' + str(y)
			componentNumber = componentNumber + 1
		output = output + '\n'
		outList.append((glyph.index, output))
outDictionary = dict(outList)
outKeys = outDictionary.keys()
outKeys.sort()
keyCount = 0
while keyCount < len(outKeys):
	file.write(outDictionary[outKeys[keyCount]])
	keyCount = keyCount + 1

bar.close()
file.close()
Message('Dump file written')
예제 #14
0
# or Glyph object respectively. It will be the
# front most font or the front most glyph.
from robofab.world import CurrentFont, CurrentGlyph

# This is a brief intro into Robofabs all singing and
# dancing dialog class. It will produce simple
# dialogs in almost any environment, FontLab, Python IDE, W.
from robofab.interface.all.dialogs import Message

# (make sure you have a font opened in FontLab)

f = CurrentFont()
# so now f is the name of a font object for the current font.

if f == None:
    # let's see what dialog can do, a warning
    Message("You should open a font first, there's nothing to look at now!")
else:
    # and another dialog.
    Message("The current font is %s" % (f.info.postscriptFullName))

    # let's have a look at some of the attributes a RoboFab Font object has
    print "the number of glyphs:", len(f)

    # some of the attributes map straight to the FontLab Font class
    # We just straightened the camelCase here and there
    print "full name of this font:", f.info.postscriptFullName
    print "list of glyph names:", f.keys()
    print 'ascender:', f.info.ascender
    print 'descender:', f.info.descender
예제 #15
0
def exportUFO(font,
              newFile=True,
              doInfo=True,
              doKerning=True,
              doGroups=True,
              doLib=True,
              doFeatures=True,
              doHints=False,
              doMarks=True,
              doMasks=True,
              glyphs=None,
              formatVersion=2):
    # get the UFO path
    ufoPath = os.path.splitext(font.path)[0] + ".ufo"
    if not newFile:
        if not os.path.exists(ufoPath):
            Message("Could not find the UFO file \"%s\"." %
                    os.path.basename(ufoPath))
            return
    else:
        if os.path.exists(ufoPath):
            ufoPath = _findAvailablePathName(ufoPath)
    # make sure no bogus glyph names are coming in
    if glyphs is not None:
        glyphs = [glyphName for glyphName in glyphs if font.has_key(glyphName)]
    # make the font the top font in FL
    fl.ifont = font.fontIndex
    # add the masks and marks to the glyph.lib
    if doMasks or doMarks:
        if glyphs is None:
            glyphNames = font.keys()
        else:
            glyphNames = glyphs
        for glyphName in glyphNames:
            glyph = font[glyphName]
            if doMarks:
                mark = glyph.mark
                glyph.lib[MARK_LIB_KEY] = mark
            if doMasks:
                # open a glyph window
                fl.EditGlyph(glyph.index)
                # switch to the mask layer
                fl.CallCommand(fl_cmd.ViewEditMask)
                # if the mask is empty, skip this step
                if not len(glyph):
                    # switch back to the edit layer
                    fl.CallCommand(fl_cmd.ViewEditMask)
                    continue
                # get the mask data
                pen = InstructionPointPen()
                glyph.drawPoints(pen)
                # switch back to the edit layer
                fl.CallCommand(fl_cmd.ViewEditMask)
                # write the mask data to the glyph lib
                instructions = pen.getInstructions()
                if instructions:
                    glyph.lib[MASK_LIB_KEY] = instructions
        # close all glyph windows. sometimes this actually works.
        fl.CallCommand(fl_cmd.WindowCloseAllGlyphWindows)
    # remove WWS names from the lib
    wwsStorage = {}
    if "openTypeNameWWSFamilyName" in font.lib:
        wwsStorage["openTypeNameWWSFamilyName"] = font.lib.pop(WWS_FAMILY_KEY)
    if "openTypeNameWWSSubfamilyName" in font.lib:
        wwsStorage["openTypeNameWWSSubfamilyName"] = font.lib.pop(
            WWS_SUBFAMILY_KEY)
    # write the UFO
    font.writeUFO(path=ufoPath,
                  doHints=doHints,
                  doInfo=doInfo,
                  doKerning=doKerning,
                  doGroups=doGroups,
                  doLib=doLib,
                  doFeatures=doFeatures,
                  glyphs=glyphs,
                  formatVersion=formatVersion)
    # add the WWS names to the info
    if doInfo:
        infoPath = os.path.join(ufoPath, "fontinfo.plist")
        info = readPlist(infoPath)
        newInfo = deepcopy(info)
        newInfo.update(wwsStorage)
        if info != newInfo:
            writePlist(newInfo, infoPath)
    # put the WWS names back in the lib
    font.lib.update(wwsStorage)
    # remove the masks and marks from the glyph.lib
    if doMasks or doMarks:
        if glyphs is None:
            glyphNames = font.keys()
        else:
            glyphNames = glyphs
        for glyphName in glyphNames:
            glyph = font[glyphName]
            lib = glyph.lib
            if lib.has_key(MASK_LIB_KEY):
                del lib[MASK_LIB_KEY]
            if lib.has_key(MARK_LIB_KEY):
                del lib[MARK_LIB_KEY]
예제 #16
0
def importUFO(ufoPath,
              newFile=True,
              saveFile=True,
              closeFile=True,
              doInfo=True,
              doKerning=True,
              doGroups=True,
              doLib=True,
              doFeatures=True,
              doHints=False,
              doMarks=True,
              doMasks=True,
              glyphs=None):
    # get the VFB path
    vfbPath = os.path.splitext(ufoPath)[0] + ".vfb"
    if not newFile:
        font = None
        for font in AllFonts():
            if font.path == vfbPath:
                break
        if font is None:
            if not os.path.exists(vfbPath):
                Message("Could not find the FontLab file \"%s\"." %
                        os.path.basename(vfbPath))
                return
            font = OpenFont(vfbPath)
    else:
        if saveFile:
            if os.path.exists(vfbPath):
                vfbPath = _findAvailablePathName(vfbPath)
        font = NewFont()
    # make the font the top font in FL
    fl.ifont = font.fontIndex
    # read the UFO
    font.readUFO(ufoPath,
                 doHints=doHints,
                 doInfo=doInfo,
                 doKerning=doKerning,
                 doGroups=doGroups,
                 doLib=doLib,
                 doFeatures=doFeatures,
                 glyphs=glyphs)
    # load the masks and marks
    if doMasks or doMarks:
        for glyph in font:
            lib = glyph.lib
            if doMarks:
                if lib.has_key(MARK_LIB_KEY):
                    glyph.mark = lib[MARK_LIB_KEY]
                    del lib[MARK_LIB_KEY]
            if doMasks:
                if lib.has_key(MASK_LIB_KEY):
                    # open a glyph window
                    fl.EditGlyph(glyph.index)
                    # switch to the mask layer
                    fl.CallCommand(fl_cmd.ViewEditMask)
                    # add the mask data
                    instructions = lib[MASK_LIB_KEY]
                    pen = glyph.getPointPen()
                    instructionsDrawPoints(instructions, pen)
                    # switch back to the edit layer
                    fl.CallCommand(fl_cmd.ViewEditMask)
                    # clear the mask data from the glyph lib
                    del lib[MASK_LIB_KEY]
        # close all glyph windows. sometimes this actually works.
        fl.CallCommand(fl_cmd.WindowCloseAllGlyphWindows)
    # load the WWS names
    if doInfo:
        info = readPlist(os.path.join(ufoPath, "fontInfo.plist"))
        if "openTypeNameWWSFamilyName" in info:
            font.lib[WWS_FAMILY_KEY] = info["openTypeNameWWSFamilyName"]
        elif "openTypeNameWWSFamilyName" in font.lib:
            del font.lib[WWS_FAMILY_KEY]
        if "openTypeNameWWSSubfamilyName" in info:
            font.lib[WWS_SUBFAMILY_KEY] = info["openTypeNameWWSSubfamilyName"]
        elif "openTypeNameWWSSubfamilyName" in font.lib:
            del font.lib[WWS_SUBFAMILY_KEY]
    # update the font
    font.update()
    # save and close
    if saveFile:
        font.save(vfbPath)
        if closeFile:
            font.close()
page_width = page_format[0]
page_height = page_format[1]
page_num = 0
scale_round = 0

#Chooing Fonts
current_font = Glyphs.font
#print(current_font)
#print current_font.familyName
current_font_filepath = current_font.filepath

#fontname = current_font.info.postscriptFullName #postscript name as string
#if fontname is None:
#Message("No postscript name given!") #alert if font info is not complete
if current_font is None:
    Message("Open fonts you want to test first."
            )  #gives error message if no font is currently open


#First Page
def firstPage():
    newPage(page_format[0], page_format[1])  #General Info Page
    fontSize(50)
    font("System Font Regular")  #font used to display info
    text("Font Family:", (75, 420))
    text(current_font.familyName, (75, 360))


def MasterInfo():
    for i in range(0, 30):
        try:
            print "Name" + ":" + " " + current_font.masters[i].name
예제 #18
0
from robofab.interface.all.dialogs import AskString, Message
font = CurrentFont()

text = AskString("A height")
try:
    height = int(text)
except:
    Message("Hey! A number please!")

for name in font.selection:
    glyph = font[name]
    center = glyph.width/2
    glyph.appendAnchor('_top', (center,height))
    
예제 #19
0
from robofab.interface.all.dialogs import AskString, Message
font = CurrentFont()

change = AskString("How much?")
try:
    change = int(change)
except:
    Message("Number Please!")

for name in font.selection:
    glyph = font[name]
    for c in glyph:
        for p in c.bPoints:
            y = p.anchor[1]
            if y < -15:
                p.move((0, -change))
    glyph.update()
예제 #20
0
# Select tolerance level in the variable below

# Credits:
# Pablo Impallari
# http://www.impallari.com

tolerancia = 30;

from robofab.world import CurrentFont
from robofab.interface.all.dialogs import Message
f = CurrentFont()
glyphs = f.glyphs

# Se fija que haya 1 solo seleccionado y toma el ancho del mismo
if fl.count_selected != 1:
	Message("Select 1 Glyph")	
else:	
	source = f.selection[0]

ancho = f[source].width

# Limpia todos los colores
for g in glyphs:
	g.mark = 0

# pinta todos los glyphs
for g in glyphs:
	este = int(g.width)
	
	#Iguales
	if este == ancho:
예제 #21
0
from robofab.interface.all.dialogs import SearchList, AskString, Message

#asks for a number. if allowZeroOrLess is 0 it will not allow a number that is zero or less
def getNumber(message, allowZeroOrLess):
	userInput = AskString(message)
	if userInput is not None:
		try:
			int(userInput)
		except ValueError:
			userInput = getNumber('Please enter a number', allowZeroOrLess)
		if (userInput <= 0) and (allowZeroOrLess == 0):
			userInput = getNumber('Please enter a number greater than 0', 0)
		return int(userInput)

def getGlyphWidth(glyph):
	box = glyph.box
	width = box[2] - box[0]
	return width

#Program
font = CurrentFont()
glyphs = font.selection
y = getNumber('Vertical Position?', 1)
name = AskString('Name of anchors')
for glyph in glyphs:
	x = int(getGlyphWidth(font[glyph])/2) + font[glyph].leftMargin
	font[glyph].appendAnchor(name, (x,y))
font.update()
Message('All done!')