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()
        
        
1 Like

_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()
1 Like

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