Python Script - Find all selected glyphs

Kannery's picture

I'm trying to write a simple python script that acts on the glyphs that the user has selected in the FontLab font window:

I'm especially interested in the glyphs (or maybe more accurately "glyph slots") that are in the encoding but are un-filled.

So far I've tried two things:


# 1 - glyph slots
selectedSlots = fl.count_selected
print "Number of selected glyph slots:", selectedSlots


# 2 - selected glyph names
selectedNames = [ fl.font.glyphs[i].name for i in range(len(fl.font.glyphs)) if fl.Selected(i) ]
print "List of selected glyph names:", selectedNames

Script number 1 reports a count of the full user selection - all selected glyph slots - filled and un-filled - perfect! Script number 2 returns a list of glyphnames but only the selected glyphs that are filled - no good. Results of running 1 and 2:


Number of selected glyph slots: 3
List of selected glyph names: ['eacute']

Can anyone suggest a technique that will list the glyphnames associated with all the selected glyph slots?

cheers
- kannery

AttachmentSize
glyph-slots.png10.43 KB
malcolm's picture

If a slot is empty, there is nothing in FontLab to read.

Kannery's picture

FontLab can read the glyphnames associated with the slots, even if they are empty:


# Generate a list of encoding glyph names
enc = fl.font.encoding
encodingNames = [ enc[i].name for i in range(len(enc)) ]
print "List of the encoding glyph names:", encodingNames


List of the encoding glyph names:
['acute', 'aacute', 'eacute', 'iacute', 'oacute', 'uacute', 'yacute', 'cacute']

And even if the slots are empty, FontLab also knows how many slots are selected (see script #1 in my first post). So possibly there is a way for FontLab to associate glyphnames with selected slots -- empty or not.

I hope. Is there a way?

cheers
-k

Michel Boyer's picture

I don't use Fontlab (I use mainly FontForge); it seems to me you are trying to list names of characters that are not in the font. What you can do is determine the unicode range of those characters that are in the font and then print the names given by the encoding. If the first and last character are in the font then the following code seems to work on my demo version of Fontlab

def encodingNames():
  gl = fl.font.glyphs
  sIndices = [ g.unicode 
     for g in gl if fl.Selected(g.index) ]
  eNames = [ enc[i].name 
     for i in range(sIndices[0],sIndices[-1]+1) ]
  return eNames
print "List of glyph names in the selected range:", encodingNames()
Kannery's picture

Thanks for your suggestion Michel, its an interesting script. But unfortunately your script would only work for me in a very rare special case: if the user happens to select a filled slot with an ID thats numerically lower than any unfilled selected slot AND, at the same time, the user also happens to select another filled slot with an ID thats numerically higher than any selected unfilled slot.

Its just too narrow of a scenario, but your script does give some inspiration for crafty workarounds, so thanks.

I guess what I'm after would be a magical method where you could probe for glyphnames like this:


fl.font.encoding.Selected(glyphname)

Where it would return TRUE if the encoding slot was selected.

cheers,
-k

malcolm's picture

No it can't. Your script is reading an encoding not the font data.

Kannery's picture

I came up with a workaround:

# Find all selected glyph slots

f = fl.font
s1 = [ g.name for g in f.glyphs if fl.Selected(g.index) ]
slots = [ e.name for e in f.encoding if e.unicode > -1 ]
empties = [ n for n in slots if not f.has_key(n) ]

# Create temporary blank glyphs in all empty glyph slots
for n in empties:
	g = Glyph()
	g.name = n
	f.glyphs.append(g)
fl.UpdateFont()

s2 = [ n for n in empties if fl.Selected(f[n].index) ]

# Remove temporary blank glyphs
for n in empties:
	del(f.glyphs[f[n].index])
fl.UpdateFont()

allSelected = s1 + s2
print "All selected slots:", allSelected

Using the example from my first post, the user has selected one full glyph slot [eacute] and two empty glyph slots [uacute, yacute] :

Running the script in this state yields the result:

All selected slots: [eacute, uacute, yacute]

A kludgy script, but it gets the job done. If anyone has a more elegant solution, please post ( Adam? Eigi? ).

cheers,
-kannery

Syndicate content Syndicate content