How can I draw a circle int the glyphs of the font use the script?

How can I draw a circle path int the glyphs of the font use the script,I didn’t find the interface in the API document

Do you like to add a circle path to the glyph or draw a circle (on screen or a PDF)?

Sorry,my English is poor.A large paragraph is written below, which may be inaccurate, please forgive me:smile:.
Yes,I want to check all glyphs datas in the font,and marking error with a circle on the wrong place. So I want save a PDF with my marked circle.
At first ,I try add annotation by GSAnnotation,but it cann’t save to PDF,and you tell me use Drawbot plug-in ,but I didn’t be used well,so I thought that ,is it possible to realize by directly draw a circle path maked the wrong place in the glyphs ?Because the path can save PDF .

You should try to get up to speed with drawbot. Here is a script I found (https://github.com/AlphabetType/DrawBot-Scripts/blob/master/createGlyphsPDF.py) and adapted to work in Glyphs:
It is a bit more complicated as it should be but you should get an idea on how it works.

from fontTools.pens.cocoaPen import CocoaPen
from GlyphsApp import Glyphs
# Some configuration
page_format = 'A4' # See http://drawbot.readthedocs.org/content/canvas/pages.html#size for other size-values

pdf_filepath = '~/Desktop/AllMyGlyphs.pdf'

# Init
font = Glyphs.font
my_selection =  font.selectedLayers #() # May also be CurrentFont.selection or else
size(page_format)
page_width = width()
page_height = height()

# Drawbox Settings
drawbox = {}
drawbox['left_margin'] = 50
drawbox['top_margin'] = 50
drawbox['right_margin'] = 50
drawbox['bottom_margin'] = 50
drawbox['xMin'] = drawbox['left_margin']
drawbox['yMin'] = drawbox['bottom_margin']
drawbox['xMax'] = page_width - drawbox['right_margin']
drawbox['yMax'] = page_width - drawbox['top_margin']
drawbox['width'] = page_width - drawbox['left_margin'] - drawbox['right_margin']
drawbox['height'] = page_height - drawbox['bottom_margin'] - drawbox['top_margin']


def showPageMargins():
    fill(None)
    stroke(0, 0, 1, .1)
    rect(drawbox['xMin'], drawbox['yMin'], drawbox['width'], drawbox['height'])



class RegisterGlyph(object):
    
    def __init__(self, glyph):
        self.glyph = glyph
        #print 'Registered glyph:', self.glyph.name
        
        self.getGlyphSizeData()
    
    def getGlyphSizeData(self):
        bounds = self.glyph.bounds
        self.xMin = bounds.origin.x
        self.yMin = bounds.origin.y
        self.xMax = bounds.origin.x + bounds.size.width
        self.yMax = bounds.origin.y + bounds.size.height

        self.w = bounds.size.width
        self.h = bounds.size.height
        self.xHeight_pos = xHeight + abs(descender)
        self.capHeight_pos = capHeight + abs(descender)
        self.x_pos = self.glyph.LSB + drawbox['xMin']
        
        #print self.xMin, self.yMin, self.xMax, self.yMax
    
    def getScale(self):
        if self.w > self.h:
            return drawbox['width']/self.w
        else:
            return 1
            #return drawbox['height']/self.h
    
    def drawBoundingBox(self):
        stroke(255,0,0)
        fill(None)
        rect(drawbox['xMin'], drawbox['yMin'], self.glyph.width*sc, UPM*sc)
    
    def drawXHeight(self):
        stroke(255, 0,0)
        line((drawbox['xMin'], drawbox['yMin'] + self.xHeight_pos*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + self.xHeight_pos*sc))
    
    def drawCapHeight(self):
        stroke(255,0,0)
        line((drawbox['xMin'], drawbox['yMin'] + self.capHeight_pos*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + self.capHeight_pos*sc))
    
    def drawBaseline(self):
        stroke(255, 0, 0)
        line((drawbox['xMin'], drawbox['yMin'] + abs(descender)*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + abs(descender)*sc))
    
    def drawLeftMargin(self):
        stroke(None)
        fill(255,0,0,0.5)
        rect(drawbox['xMin'], drawbox['yMin'], self.glyph.LSB*sc, UPM*sc)
    
    def drawRightMargin(self):
        stroke(None)
        fill(255,0,0,0.5)
        rect(drawbox['xMin'] + (self.glyph.width - self.glyph.RSB)*sc, drawbox['yMin'], self.glyph.RSB*sc, UPM*sc)
        #rect((drawbox['xMax'] - self.glyph.RSB)*sc, drawbox['yMin'], self.glyph.width*sc, UPM*sc)
        

                
    def addNewPage(self):
        newPage()
        showPageMargins()
    
    def drawGlyph(self):
        save()
        stroke(None)
        fill(0)
        translate(drawbox['xMin'], 0)
        translate(0, drawbox['yMin'] + abs(descender)*sc)
        scale(sc)        
        
        self._drawGlyph()
        restore()
    
    def center(self, horizontal=True, vertical=True):
        offset_x = 0
        offset_y = 0
        if horizontal:
            offset_x = (drawbox['width'] - self.glyph.width*sc)/2
        
        if vertical:
            offset_y = (drawbox['height'] - UPM*sc)/2
        
        translate(offset_x, offset_y)
        
        
    
    def _drawGlyph(self):
        pen = CocoaPen(self.glyph.font())
        self.glyph.draw(pen)
        drawPath(pen.path)



def getMaxWidth():
    max_width = 0
    for g in my_selection:
        if g.width > max_width:
            max_width = g.width

    return max_width

max_width = getMaxWidth()

def getScale():
    # The glyphs should be displayed as big as possible.
    # So the most wide glyph will be the base for the scaling.
    sc = drawbox['width']/max_width
    return sc

    
        

sc = getScale()
UPM = font.unitsPerEm()
xHeight = font.masters[0].xHeight
capHeight = font.masters[0].capHeight
ascender = font.masters[0].ascender
descender = font.masters[0].descender

for g in my_selection: 
    if True: #len(g) > 0: # Ignore whitespace glyphs
        glyph = RegisterGlyph(g)
        glyph.addNewPage()
        # Just uncomment any of the following methods if you don't want them to be drawn
        glyph.center(True, True)
        glyph.drawLeftMargin()
        glyph.drawRightMargin()
        glyph.drawGlyph()
        glyph.drawBoundingBox()
        glyph.drawBaseline()
        glyph.drawXHeight()
        glyph.drawCapHeight()
        
        

_drawGlyph will fail its job if a glyph has components. Since there is no error handling, the entire script will break. Just a little observation in case it doesn’t run for some people.

Thank first, when I run the code ,it‘s successful,but when I export( File -> Export),it show that like the picture.QQ20181017-0

I have fixed the crash, so please get the latest version of the drawbot plugin by opening the Plugin Manager and restarting Glyphs.
I changed Glyphs that it can handle the original script, but I need some time to prepare an update.

for now, I changed the script a bit that it can handle components:

from GlyphsApp import Glyphs
# Some configuration
page_format = 'A4' # See http://drawbot.readthedocs.org/content/canvas/pages.html#size for other size-values

# Init
font = Glyphs.font
my_selection =  font.selectedLayers
size(page_format)
page_width = width()
page_height = height()

# Drawbox Settings
drawbox = {}
drawbox['left_margin'] = 50
drawbox['top_margin'] = 50
drawbox['right_margin'] = 50
drawbox['bottom_margin'] = 50
drawbox['xMin'] = drawbox['left_margin']
drawbox['yMin'] = drawbox['bottom_margin']
drawbox['xMax'] = page_width - drawbox['right_margin']
drawbox['yMax'] = page_width - drawbox['top_margin']
drawbox['width'] = page_width - drawbox['left_margin'] - drawbox['right_margin']
drawbox['height'] = page_height - drawbox['bottom_margin'] - drawbox['top_margin']


def showPageMargins():
    fill(None)
    stroke(0, 0, 1, .1)
    rect(drawbox['xMin'], drawbox['yMin'], drawbox['width'], drawbox['height'])


class RegisterGlyph(object):

    def __init__(self, glyph):
        self.glyph = glyph
        #print 'Registered glyph:', self.glyph.name

        self.getGlyphSizeData()

    def getGlyphSizeData(self):
        bounds = self.glyph.bounds
        self.xMin = bounds.origin.x
        self.yMin = bounds.origin.y
        self.xMax = bounds.origin.x + bounds.size.width
        self.yMax = bounds.origin.y + bounds.size.height

        self.w = bounds.size.width
        self.h = bounds.size.height
        self.xHeight_pos = xHeight + abs(descender)
        self.capHeight_pos = capHeight + abs(descender)
        self.x_pos = self.glyph.LSB + drawbox['xMin']

        #print self.xMin, self.yMin, self.xMax, self.yMax

    def getScale(self):
        if self.w > self.h:
            return drawbox['width']/self.w
        else:
            return 1
            #return drawbox['height']/self.h

    def drawBoundingBox(self):
        stroke(255,0,0)
        fill(None)
        rect(drawbox['xMin'], drawbox['yMin'], self.glyph.width*sc, UPM*sc)

    def drawXHeight(self):
        stroke(255, 0,0)
        line((drawbox['xMin'], drawbox['yMin'] + self.xHeight_pos*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + self.xHeight_pos*sc))

    def drawCapHeight(self):
        stroke(255,0,0)
        line((drawbox['xMin'], drawbox['yMin'] + self.capHeight_pos*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + self.capHeight_pos*sc))

    def drawBaseline(self):
        stroke(255, 0, 0)
        line((drawbox['xMin'], drawbox['yMin'] + abs(descender)*sc), (drawbox['xMin'] + self.glyph.width*sc, drawbox['yMin'] + abs(descender)*sc))

    def drawLeftMargin(self):
        stroke(None)
        fill(255,0,0,0.5)
        rect(drawbox['xMin'], drawbox['yMin'], self.glyph.LSB*sc, UPM*sc)

    def drawRightMargin(self):
        stroke(None)
        fill(255,0,0,0.5)
        rect(drawbox['xMin'] + (self.glyph.width - self.glyph.RSB)*sc, drawbox['yMin'], self.glyph.RSB*sc, UPM*sc)
        #rect((drawbox['xMax'] - self.glyph.RSB)*sc, drawbox['yMin'], self.glyph.width*sc, UPM*sc)


    def addNewPage(self):
        newPage()
        showPageMargins()

    def drawGlyph(self):
        save()
        stroke(None)
        fill(0)
        translate(drawbox['xMin'], 0)
        translate(0, drawbox['yMin'] + abs(descender)*sc)
        scale(sc)

        self._drawGlyph()
        restore()

    def center(self, horizontal=True, vertical=True):
        offset_x = 0
        offset_y = 0
        if horizontal:
            offset_x = (drawbox['width'] - self.glyph.width*sc)/2

        if vertical:
            offset_y = (drawbox['height'] - UPM*sc)/2

        translate(offset_x, offset_y)


    def _drawGlyph(self):
        drawPath(self.glyph.drawBezierPath)


def getMaxWidth():
    max_width = 0
    for g in my_selection:
        if g.width > max_width:
            max_width = g.width

    return max_width

max_width = getMaxWidth()

def getScale():
    # The glyphs should be displayed as big as possible.
    # So the most wide glyph will be the base for the scaling.
    sc = drawbox['width']/max_width
    return sc


sc = getScale()
UPM = font.unitsPerEm()
xHeight = font.masters[0].xHeight
capHeight = font.masters[0].capHeight
ascender = font.masters[0].ascender
descender = font.masters[0].descender

for g in my_selection: 
    if True: #len(g) > 0: # Ignore whitespace glyphs
        glyph = RegisterGlyph(g)
        glyph.addNewPage()
        # Just uncomment any of the following methods if you don't want them to be drawn
        glyph.center(True, True)
        glyph.drawLeftMargin()
        glyph.drawRightMargin()
        glyph.drawGlyph()
        glyph.drawBoundingBox()
        glyph.drawBaseline()
        glyph.drawXHeight()
        glyph.drawCapHeight()

Thanks very much,I will try to modify it realize my ideas:+1:t2: