How to remove vertical PS hints with a Python script?

Hi there,

I've been attempting with no much success to remove only vertical PS hints with a script but I can't go further than printing them. I found the RemoveHints(integer mode) method in the old Fontlab Python reference but I can't find a way to use it.
Can anyone give a hand with it?
TIA.

from robofab.world import AllFonts

for font in AllFonts():
    for x in font:
	for n in x.naked().vhints:
	    print n
				
print 'Ready'
font.update()
 
Tagged:

Comments

  • Paul van der Laan
    Paul van der Laan Posts: 242
    edited February 2017
    The del() command is your friend here:
    from robofab.world import AllFonts
    
    for thisFont in AllFonts():
       for thisGlyph in thisFont:
          verticalPSHints = thisGlyph.naked().vhints
          for n in range(len(verticalPSHints)):
             del verticalPSHints[0]
       thisFont.update()
    
    print 'done'
    

  • Thanks, Paul!
  • Even better, do not use for..in loop with del, just use x.naked().vhints.clean() :)
  • Ramiro Espinoza
    Ramiro Espinoza Posts: 839
    edited February 2017
    Nice! So here is the final script. My aim was to remove vertical hints in non spacing diacritics for all open fonts (I was tired of doing it by hand).
    from robofab.world import AllFonts
    
    diacritics = """gravecomb acutecomb uni0302 tildecomb uni0304 uni0306 uni0307 uni0308
    uni030A uni030B uni030C uni0312 uni0313 uni0326 uni0327 uni0328 gravecomb.case acutecomb.case
    uni0302.case tildecomb.case uni0304.case uni0306.case uni0307.case uni0308.case uni030A.case
    uni030B.case uni030C.case uni0326.case uni0327.case uni0328.case gravecomb.sc acutecomb.sc
    uni0302.sc tildecomb.sc uni0304.sc uni0306.sc uni0307.sc uni0308.sc uni030A.sc uni030B.sc
    uni030C.sc uni0326.sc uni0327.sc uni0328.sc"""
    
    diacritics = diacritics.split()
    
    for font in AllFonts():
        for x in font:
            for n in diacritics:
                if x.name == n:
                    x.naked().vhints.clean()
                    print "Vertical hints removed in %s" % x.name
                    x.update()
    
    print 'Ready'
    font.update()

  • Great. A suggestion if I may - just skip that loop....
        for n in diacritics:
                if x.name == n:
                    x.naked().vhints.clean()
                    print "Vertical hints removed in %s" % x.name
                    x.update()
    
    and replace it with:
    if x.name in diacritics:
    	x.naked().vhints.clean()
    	print "Vertical hints removed in %s" % x.name
    	x.update()
    
  • Paul van der Laan
    Paul van der Laan Posts: 242
    edited February 2017
    Even better, do not use for..in loop with del, just use x.naked().vhints.clean() :)
    Neat. Is the vhints.clean() method documented somewhere?
  • @Paul van der Laan I do not seem to remember. But all of those vArray instances that Fontlab uses have .append() and .clear(). I used same method long ago to clean Guidelines. Today I made an anchor manager, and tried to use .clean() on anchor array and it worked - so a presumed that it will work on hints :)
  • attar
    attar Posts: 209
    and replace it with:

    (nitpicking but) you can do better than that: since you have the list of glyph names you care about, you don't need to loop through all glyphs in the font:

    for font in AllFonts():
        for n in diacritics:
            if n not in font: continue
            glyph = font[n]
            # do things with the glyph
  • @Adrien Tétar depends what is faster, a full enumeration or searching the glyph names (n not in font).
  • attar
    attar Posts: 209
    @Georg Seifert With defcon, if name in font is O(1) (set*) whereas with the previous solution you have to do for all names if name in diacritics which is O(n), n length of the list.

    *Actually looking at the code I noticed an unnecessary conversion to a list so I put up a PR to change that.  ;)

    (Of course this all doesn't matter very much until you have large datasets.)