Beispiel #1
0
def buildAccentedGlyphs(junk,object):
#    """Get the names of the selected glyphs in a font.
#    
#    Call the composing function for every glyph that has an entry 
#    in the dictionary."""
#    componentsByFontname(font, font.fontname)
    font_file = os.path.normpath(fontforge.activeFont().path)
    top_level = os.path.split(os.path.split(font_file)[0])[0]
    tool_path = os.path.join(top_level, "tools")

    try:
        sys.path.append(tool_path)
        from glyphcomponents import glyphComponents
    
        if type(object).__name__ == "font":
            for glyph in object.selection.byGlyphs:
                if glyph.glyphname in glyphComponents.keys():
                    composeAccented(glyph)
                else:
                    continue
        else: 
            if object.glyphname in glyphComponents.keys():
                composeAccented(object)
            else:
                logWarning('This glyph has no entry in the dictionary')
    except ImportError:
        fontforge.postError("Cannot import Python module glyphcomponents",
                "This script is made to work with the SFDs residing in top_level/SFD and the module in top_level/tools.")
Beispiel #2
0
def YOffset(percent, afont):
    '''Adjust the Y position.'''
    em = afont.ascent + afont.descent / 2
    if not percent:
        ret = fontforge.askString('Offset Percent?', 'Percent of Offset?',
                                  '64')
        if not ret:
            return
        try:
            percent = float(ret) / 100
            if percent < -1.5 or percent > 1.5:
                raise ValueError
        except ValueError:
            fontforge.postError('Wrong Percent!',
                                "Need a value abs(x) <= 150.")
            return
    if percent == 0:  # Do Nothing.
        return
    tavg, bavg = get_avg_topbtm(afont)
    if percent > 0:
        deltay = (afont.ascent - tavg) * percent
    else:
        deltay = (afont.descent - bavg) * percent
    matrix = psMat.translate(0, deltay)
    for glyph in afont.selection.byGlyphs:
        glyph.transform(matrix)
Beispiel #3
0
def excepthook (*args):
    tb = ''.join(traceback.format_exception(*args))
    message = ''.join(traceback.format_exception_only(*args[:2])).strip()

    fontforge.logWarning(tb.replace('%', '%%'))
    fontforge.postError('Unhandled exception',
                        message.replace('%','%%'))
Beispiel #4
0
def YOffset(percent, afont):
	'''Adjust the Y position.'''
	em = afont.ascent + afont.descent/2
	if not percent:
		ret = fontforge.askString('Offset Percent?',
				'Percent of Offset?', '64' )
		if not ret:
			return
		try:
			percent = float(ret)/100
			if percent < -1.5 or percent > 1.5:
				raise ValueError
		except ValueError:
			fontforge.postError('Wrong Percent!', "Need a value abs(x) <= 150.")
			return
	if percent == 0: # Do Nothing.
		return
	tavg, bavg = get_avg_topbtm(afont)
	if percent > 0:
		deltay = (afont.ascent - tavg)*percent
	else:
		deltay = (afont.descent - bavg)*percent
	matrix = psMat.translate(0, deltay)
	for glyph in afont.selection.byGlyphs:
		glyph.transform(matrix)
Beispiel #5
0
def viewPoints(junk, glyph):
    pointdict = getDict("pointdict", glyph)

    answ = ff.askString(
        "View parametrized points",
        printTbl(
            "Coordinate : value", pointdict,
            "Supported commands:\n[i]nsert [r]emove removeall [u]pdate [q]uit")
    )

    if answ == "insert" or answ == "i":
        pname = ff.askString("New parametrization",
                             "Name of coordinate to be parameterized:")
        if pname:
            if pname in pointdict:
                ff.postError(
                    "Insertion error",
                    "A coordinate with this name already exists. Choose a different name or update instead"
                )
            else:
                pval = ff.askString("New parametrization", "Coordinate value:")
                if pval:
                    pointdict[pname] = pval
    elif answ == "remove" or answ == "r":
        toremove = ff.askString(
            "Remove point parametrization",
            "Name of coordinate to be deparameterized (the point will not be removed):"
        )
        if toremove:
            del pointdict[toremove]
    elif answ == "removeall":
        pointdict = {}
    elif answ == "update" or answ == "u":
        pname = ff.askString("Update point parametrization",
                             "Name of coordinate to update:")
        if pname:
            if not pname in pointdict:
                ff.postError(
                    "Update error",
                    "A coordinate with this name does not exist. Choose an existing coordinate or parametrize existing points."
                )
            else:
                pval = ff.askString("Update coordinate",
                                    "New coordinate value:")
                if pval:
                    pointdict[pname] = pval
    elif answ == "quit" or answ == "q" or not answ:
        return

    glyph.persistent['pointdict'] = pointdict
    updatePoints(glyph)

    viewPoints(junk, glyph)
def simplepolateFonts(registerobject, font):
    # Ask user how many children to create, default is 5
    amount = 5
    s = fontforge.askString("Simple Font Interpolation", "How many children?",
                            str(amount))
    try:
        amount = int(s)
    except:
        fontforge.postError("Bad value", "Expected whole number")

    # figure out the interpolation amount floats based on how many children the user requested
    interpolationamount = [0.0]
    calcamount = amount + 1
    x = 1.0 / calcamount
    for y in range(1, calcamount):
        interpolationamount.append(x * y)
    interpolationamount.append(1.0)

    # TODO: This should ask the user to choose which is source1 and source2
    # get the souce fonts from the 2 currently open (check for only 2 open is in shouldWeAppear())
    fonts = fontforge.fonts()
    source1 = fonts[0]
    source2 = fonts[1]

    # get a name for the children - font-name-generator.py supplies gibberish() so if we have that available, lets use it
    name = source1.familyname + " Simp"
    newName = fontforge.askString("Simplepolate Fonts", "Base family name?",
                                  str(name))

    # create all the children
    for x in range(amount + 2):
        # TODO I thought this would work but it doesn't
        # newFont = source1.interpolateFonts(interpolationamount[x],source2.path)
        # TODO and I thought this would work because it does on its own, but if its even just repeated twice right next to each other, it doesn't work!! :(
        source1.interpolateFonts(interpolationamount[x], source2.path)
        newFontName = newName + ' ' + str(int(
            interpolationamount[x] * 100)).zfill(3)
        newFont = fontforge.activeFont()
        # Set PostScript Style Name (FamilyName-Style)
        newFont.weight = "Regular"
        newFont.fontname = newFontName.replace(' ', '') + '-' + newFont.weight
        # Set PostScript Family Name (Family Name)
        newFont.familyname = newFontName
        # Set PostScript Full Name (Family Name Style)
        newFont.fullname = newFontName + ' ' + font.weight
        # let folks know what we did
        message = "Simplepolated %s: %s%%/%s%% %s/%s" % (
            newFont.fullname, int(100 - interpolationamount[x] * 100),
            int(interpolationamount[x] * 100), source1.fontname,
            source2.fontname)
        note(message)
 def fit_selected_segments (registerobject, glyph):
     l = glyph.layers[glyph.activeLayer]
     selection = map (selected_segments, l) 
     try:
         v = ask_user_fit ()
     except:
         fontforge.postError("Bad Value", "Input was not a number")
         return
     if v == None: return
     for contour in selection:
         for s in filter (is_curve_seg, contour):
             fit_segment (s, v)
     glyph.layers[glyph.activeLayer] = l
     print 'done'
Beispiel #8
0
def viewParameters(junk, fontOrGlyph):
    font = getFont(fontOrGlyph)
    paramdict = getDict("paramdict", font)

    answ = ff.askString(
        "View parameters",
        printTbl(
            "Parameter : value", paramdict,
            "Supported commands:\n[i]nsert [r]emove removeall [u]pdate [q]uit")
    )

    if answ == "insert" or answ == "i":
        pname = ff.askString("New parameter", "Parameter name:")
        if pname:
            if pname in paramdict:
                ff.postError(
                    "Insertion error",
                    "A parameter with this name already exists. Choose a different name or update instead"
                )
            else:
                pval = ff.askString("New parameter", "Parameter value:")
                if pval:
                    paramdict[pname] = pval
    elif answ == "remove" or answ == "r":
        toremove = ff.askString("Remove parameter",
                                "Name of parameter to remove:")
        if toremove:
            del paramdict[toremove]
    elif answ == "removeall":
        paramdict = {}
    elif answ == "update" or answ == "u":
        pname = ff.askString("Update parameter", "Parameter name:")
        if pname:
            if not pname in paramdict:
                ff.postError(
                    "Update error",
                    "A parameter with this name does not exist. Choose an existing parameter or insert instead"
                )
            else:
                pval = ff.askString("Update parameter", "Parameter value:")
                if pval:
                    paramdict[pname] = pval
    elif answ == "quit" or answ == "q" or not answ:
        return

    font.persistent['paramdict'] = paramdict
    updateAllGlyphs(junk, font)

    viewParameters(junk, font)
Beispiel #9
0
def GetSelectedBound(junk, afont):
	'''Show max height and width of the selected glyphs.'''
	wmax, hmax, wpct, hpct = get_max_size(afont)
	wavg, havg = get_avg_size(afont)
	em = afont.ascent + afont.descent
	msg = ('The max width and height of the selected glyphs are:\n'
			'Points:\t%d\t%d\nScale Factor to 100%%:\t%.3f\t  %.3f%%')
	msg = msg % (wmax, hmax, wpct, hpct)
	msg += "\nEm:\t%d" % em
	msg += '\nThe average width and height of the selected glyphs are:\n'
	msg += 'Points:'
	msg += str(wavg)
	msg += '\t'
	msg += str(havg)
	fontforge.postError('Max Demension', msg)
Beispiel #10
0
def GetSelectedBound(junk, afont):
    '''Show max height and width of the selected glyphs.'''
    wmax, hmax, wpct, hpct = get_max_size(afont)
    wavg, havg = get_avg_size(afont)
    em = afont.ascent + afont.descent
    msg = ('The max width and height of the selected glyphs are:\n'
           'Points:\t%d\t%d\nScale Factor to 100%%:\t%.3f\t  %.3f%%')
    msg = msg % (wmax, hmax, wpct, hpct)
    msg += "\nEm:\t%d" % em
    msg += '\nThe average width and height of the selected glyphs are:\n'
    msg += 'Points:'
    msg += str(wavg)
    msg += '\t'
    msg += str(havg)
    fontforge.postError('Max Demension', msg)
Beispiel #11
0
def ScaleToSquare(percent, afont):
    '''Scale a font to nearly fit a square.'''
    if not percent:
        ret = fontforge.askString('Scale Percent?', 'Percent of Scale?', '20')
        if not ret:
            return
        try:
            percent = float(ret) / 100
            if percent <= 0 or percent > 1:
                raise ValueError
        except ValueError:
            fontforge.postError('Wrong Percent!', "Need a value <= 100.")
            return
    for glyph in afont.selection.byGlyphs:
        fit_glyph_box(glyph, percent)
Beispiel #12
0
def ScaleToSquare(percent, afont):
	'''Scale a font to nearly fit a square.'''
	if not percent:
		ret = fontforge.askString('Scale Percent?',
				'Percent of Scale?', '20' )
		if not ret:
			return
		try:
			percent = float(ret)/100
			if percent <= 0 or percent > 1:
				raise ValueError
		except ValueError:
			fontforge.postError('Wrong Percent!', "Need a value <= 100.")
			return
	for glyph in afont.selection.byGlyphs:
		fit_glyph_box(glyph, percent)
Beispiel #13
0
def BoundToSquare(percent, afont):
    '''Scale a font to nearly fit the average width.'''
    em = afont.ascent + afont.descent
    if not percent:
        ret = fontforge.askString('Scale Percent?', 'Percent of Scale?', '36')
        if not ret:
            return
        try:
            percent = float(ret) / 100
            if percent <= 0 or percent > 1:
                raise ValueError
        except ValueError:
            fontforge.postError('Wrong Percent!', "Need a value <= 100.")
            return
    wavg, havg = get_avg_size(afont)
    for glyph in afont.selection.byGlyphs:
        box_fit_square(glyph, em, percent, wavg, havg)
def simplepolateFonts(registerobject, font):
	# Ask user how many children to create, default is 5
	amount = 5
	s = fontforge.askString("Simple Font Interpolation", "How many children?", str(amount))
	try:
		amount = int(s)
	except:
		fontforge.postError("Bad value", "Expected whole number")

	# figure out the interpolation amount floats based on how many children the user requested
	interpolationamount = [0.0]
	calcamount = amount +1
	x = 1.0 / calcamount
	for y in range(1, calcamount):
		interpolationamount.append(x*y)
	interpolationamount.append(1.0)

        # TODO: This should ask the user to choose which is source1 and source2
	# get the souce fonts from the 2 currently open (check for only 2 open is in shouldWeAppear())
	fonts = fontforge.fonts()
        source1 = fonts[0]
	source2 = fonts[1]

	# get a name for the children - font-name-generator.py supplies gibberish() so if we have that available, lets use it
	name = source1.familyname + " Simp"
	newName = fontforge.askString("Simplepolate Fonts", "Base family name?", str(name))
        
        # create all the children
	for x in range(amount+2):
	        # TODO I thought this would work but it doesn't
		# newFont = source1.interpolateFonts(interpolationamount[x],source2.path)
		# TODO and I thought this would work because it does on its own, but if its even just repeated twice right next to each other, it doesn't work!! :(
                source1.interpolateFonts(interpolationamount[x],source2.path)
                newFontName = newName + ' ' + str(int(interpolationamount[x]*100)).zfill(3)
                newFont = fontforge.activeFont()
                # Set PostScript Style Name (FamilyName-Style)
		newFont.weight = "Regular"
		newFont.fontname = newFontName.replace(' ', '') + '-' + newFont.weight
		# Set PostScript Family Name (Family Name)
		newFont.familyname = newFontName
		# Set PostScript Full Name (Family Name Style)
		newFont.fullname = newFontName + ' ' + font.weight
		# let folks know what we did
                message = "Simplepolated %s: %s%%/%s%% %s/%s" % (newFont.fullname, int(100-interpolationamount[x]*100), int(interpolationamount[x]*100), source1.fontname, source2.fontname)
		note(message)
def simplepolate(registerobject, font):
	# Ask user how many children to create, default is 5
	amount = 5
	s = fontforge.askString("Simple Glyph Interpolation", "How many children?", str(amount))
	try:
		amount = int(s)
	except:
		fontforge.postError("Bad value", "Expected whole number")

	# figure out the interpolation amount floats based on how many children the user requested
	interpolationamount = [0.0]
	calcamount = amount +1
	x = 1.0 / calcamount
	for y in range(1, calcamount):
		interpolationamount.append(x*y)
	interpolationamount.append(1.0)

	# get the souce glyphs from the selection -- this should be simpler...
	glyphs = []
	for g in font.selection.byGlyphs:
		glyphs.append(g)
	source1 = glyphs[0]
	source2 = glyphs[1]

	# get a name for the children - font-name-generator.py supplies gibberish() so if we have that available, lets use it
	if gibberish: 
		name = gibberish(1)
	else:
		name = "simplepolation"
	name = fontforge.askString("Simple Glyph Interpolation", "Children names?", str(name))

	# create all the children
	for x in range(amount+2):
		glyphname = str(name) + '.'+ str(x+1)
		g = font.createChar(-1, glyphname)
		g.preserveLayerAsUndo(1)
		# interpolate the top layer
		g.layers[1] = source1.layers[1].interpolateNewLayer(source2.layers[1], interpolationamount[x])
		# interpolate the width
		g.width = source1.width + (source2.width - source1.width)*interpolationamount[x]
		# interpolate the vwidth
		g.vwidth = source1.vwidth + (source2.vwidth - source1.vwidth)*interpolationamount[x]
		# let folks know what we did
		message = "Simplepolator created '%s' that is %s%% '%s' and %s%% '%s'" % (glyphname, int(100-interpolationamount[x]*100), source1.glyphname, int(interpolationamount[x]*100), source2.glyphname)
		note(message)
Beispiel #16
0
def	importIcon(junk, font):
	iconbase = 0xe000
	while iconbase in font and font[iconbase].isWorthOutputting():
		iconbase += 1
	svgfile = fontforge.openFilename("Select SVG file", "", "*.svg")
	if svgfile:
		newglyph = font.createChar(iconbase)
		try:
			newglyph.importOutlines(svgfile)
			newglyph.right_side_bearing = 0
			newglyph.left_side_bearing = 0

			boundingbox = newglyph.boundingBox()
			if boundingbox[3]-boundingbox[1] > 1000:
				print("bigger than 1000")
				while boundingbox[3]-boundingbox[1] > 1000:
					newglyph.transform(scaledown)
					boundingbox = newglyph.boundingBox()
			elif boundingbox[3]-boundingbox[1] < 1000:
				print("smaller than 1000")
				while boundingbox[3]-boundingbox[1] < 1000:
					newglyph.transform(scaleup)
					boundingbox = newglyph.boundingBox()

			boundingbox = newglyph.boundingBox()
			#fontforge.postNotice("Info", "y1 = %f, y2 = %f" % (boundingbox[1], boundingbox[3]))
			print("y1 = %f, y2 = %f" % (boundingbox[1], boundingbox[3]))
			if min(boundingbox[1], boundingbox[3]) > -200:
				print("need to move down")
				while min(boundingbox[1], boundingbox[3]) > -200:
					newglyph.transform(translatedown)
					boundingbox = newglyph.boundingBox()
			elif max(boundingbox[1], boundingbox[3]) > 1000:
				while max(boundingbox[1], boundingbox[3]) > 1000:
					print("need to move up")
					newglyph.transform(translateup)
					boundingbox = newglyph.boundingBox()

			newglyph.right_side_bearing = 0
			newglyph.left_side_bearing = 0

		except Exception as e:
			fontforge.postError("Error", "Something went wrong!\n\n"+str(e))
			#newglyph.clear()
			font.removeGlyph(iconbase)
Beispiel #17
0
def BoundToSquare(percent, afont):
	'''Scale a font to nearly fit the average width.'''
	em = afont.ascent + afont.descent
	if not percent:
		ret = fontforge.askString('Scale Percent?',
				'Percent of Scale?', '36' )
		if not ret:
			return
		try:
			percent = float(ret)/100
			if percent <= 0 or percent > 1:
				raise ValueError
		except ValueError:
			fontforge.postError('Wrong Percent!', "Need a value <= 100.")
			return
	wavg, havg = get_avg_size(afont)
	for glyph in afont.selection.byGlyphs:
		box_fit_square(glyph, em, percent, wavg, havg)
Beispiel #18
0
def buildAccentedGlyphs(junk, object):
    #    """Get the names of the selected glyphs in a font.
    #
    #    Call the composing function for every glyph that has an entry
    #    in the dictionary."""
    #    componentsByFontname(font, font.fontname)

    font = object if type(object).__name__ == "font" else object.font
    font_file = os.path.normpath(font.path)
    top_level = os.path.split(os.path.split(font_file)[0])[0]
    tool_path = os.path.join(top_level, "tools")
    if tool_path not in sys.path:
        sys.path.append(tool_path)

    import_successful = True
    try:
        glyphcomponents = importlib.import_module("glyphcomponents")
    except:
        import_successful = False
        fontforge.postError(
            "Cannot import Python module glyphcomponents",
            "This script is made to work with the SFDs residing in top_level/SFD and the module in top_level/tools."
        )

    if import_successful:
        try:
            reload(glyphcomponents)
            glyphComponents = glyphcomponents.glyphComponents

            if type(object).__name__ == "font":
                for glyph in object.selection.byGlyphs:
                    if glyph.glyphname in glyphComponents.keys():
                        composeAccented(glyph, glyphComponents)
                    else:
                        continue
            else:
                if object.glyphname in glyphComponents.keys():
                    composeAccented(object, glyphComponents)
                else:
                    logWarning('This glyph has no entry in the dictionary')

        except BaseException as e:
            fontforge.postError("Building glyphs failed", str(e))
Beispiel #19
0
def ScaleToEm(percent, afont):
    '''Scale a font to fit 5% less than the em.'''
    #em = afont.ascent + afont.descent
    em = afont.ascent + afont.descent / 2
    center = (afont.ascent - afont.descent / 2) / 2
    lbearing = int(em * 0.05)
    if not percent:
        ret = fontforge.askString('Scale Percent?',
                                  'Percent of Line Height (em)?', '95')
        if not ret:
            return
        try:
            percent = float(ret) / 100
            if percent <= 0 or percent > 1.5:
                raise ValueError
        except ValueError:
            fontforge.postError('Wrong Percent!', "Need a value <= 150.")
            return
    wavg, havg = get_avg_size(afont)
    for glyph in afont.selection.byGlyphs:
        #fit_glyph(glyph, em, percent)
        fit_glyph_plus(glyph, em, percent, wavg, havg)
        #center_glyph(glyph, center, lbearing) # Maybe not move glyph?
        center_glyph_height(glyph, center)
Beispiel #20
0
def ScaleToEm(percent, afont):
	'''Scale a font to fit 5% less than the em.'''
	#em = afont.ascent + afont.descent
	em = afont.ascent + afont.descent/2
	center = (afont.ascent - afont.descent/2)/2
	lbearing = int(em*0.05)
	if not percent:
		ret = fontforge.askString('Scale Percent?',
				'Percent of Line Height (em)?', '95' )
		if not ret:
			return
		try:
			percent = float(ret)/100
			if percent <= 0 or percent > 1.5:
				raise ValueError
		except ValueError:
			fontforge.postError('Wrong Percent!', "Need a value <= 150.")
			return
	wavg, havg = get_avg_size(afont)
	for glyph in afont.selection.byGlyphs:
		#fit_glyph(glyph, em, percent)
		fit_glyph_plus(glyph, em, percent, wavg, havg)
		#center_glyph(glyph, center, lbearing) # Maybe not move glyph?
		center_glyph_height(glyph, center) 
def simplepolate(registerobject, font):
    # Ask user how many children to create, default is 5
    amount = 5
    s = fontforge.askString("Simplepolate", "How many children? (1-8)",
                            str(amount))
    try:
        amount = int(s)
    except:
        fontforge.postError("Bad value", "Expected whole number")
        return
    if 1 <= amount >= 9:
        fontforge.postError("Bad value", "1 to 9, please")
        return

    # figure out the interpolation amount floats based on how many children the user requested
    interpolationamount = []
    calcamount = amount + 1
    x = 1.0 / calcamount
    for y in range(1, calcamount):
        interpolationamount.append(x * y)
    interpolationamount.append(1.0)

    # get the souce glyphs from the selection -- this would be simpler in robofab :)
    glyphs = []
    for g in font.selection.byGlyphs:
        glyphs.append(g)
    source1 = glyphs[0]
    source2 = glyphs[1]

    name = source1.glyphname
    print "Adding %s Style Sets to %s" % (amount, name)

    # create all the children
    for x in range(amount + 1):
        # create the style set name
        ss = 'ss' + str(x + 1).zfill(2)
        glyphname = str(name) + '.' + ss
        # create a char slot
        g = font.createChar(-1, glyphname)
        # make this undoable
        g.preserveLayerAsUndo(1)
        # interpolate the top layer
        g.layers[1] = source1.layers[1].interpolateNewLayer(
            source2.layers[1], interpolationamount[x])
        # interpolate the width
        g.width = source1.width + (source2.width -
                                   source1.width) * interpolationamount[x]
        # interpolate the vwidth
        g.vwidth = source1.vwidth + (source2.vwidth -
                                     source1.vwidth) * interpolationamount[x]

        # add lookup for each ss, eg ss01, if it doesn't already exist
        lookup = str(ss)
        if lookup not in font.gsub_lookups:
            flags = ("", "")
            featureScriptLangTuple = ((lookup, (("latn", ("dflt")), )), )
            # featureScriptLangTuple = (('ss07', (('latn', 'dflt'),)),)
            font.addLookup(lookup, "gsub_single", (), featureScriptLangTuple)

        # check for existing subtables
        if len(font.getLookupSubtables(lookup)) == 0:
            subtable = lookup + '-0'
            font.addLookupSubtable(lookup, subtable)
        else:
            subtable = font.getLookupSubtables(lookup)[0]
        # add the substitution
        source1.addPosSub(subtable, glyphname)

        # merge the subtables (thanks to khaled hosney for this!)
        for lookup in font.gsub_lookups:
            while 1 < len(font.getLookupSubtables(lookup)):
                font.mergeLookupSubtables(
                    font.getLookupSubtables(lookup)[1],
                    font.getLookupSubtables(lookup)[0])

        # let folks know what we did
        message = "  Created %s %s%%/%s%% %s/%s (%s:%s)" % (
            glyphname, int(100 - interpolationamount[x] * 100),
            int(interpolationamount[x] * 100), source1.glyphname,
            source2.glyphname, lookup, subtable)
        note(message)
def simplepolate(registerobject, font):
    # Ask user how many children to create, default is 5
    amount = 5
    s = fontforge.askString("Simplepolate", "How many children? (1-8)", str(amount))
    try:
        amount = int(s)
    except:
        fontforge.postError("Bad value", "Expected whole number")
        return
    if 1 <= amount >= 9:
            fontforge.postError("Bad value", "1 to 9, please")
            return

    # figure out the interpolation amount floats based on how many children the user requested
    interpolationamount = []
    calcamount = amount +1
    x = 1.0 / calcamount
    for y in range(1, calcamount):
        interpolationamount.append(x*y)
    interpolationamount.append(1.0)

    # get the souce glyphs from the selection -- this would be simpler in robofab :)
    glyphs = []
    for g in font.selection.byGlyphs:
        glyphs.append(g)
    source1 = glyphs[0]
    source2 = glyphs[1]

    name = source1.glyphname
    print "Adding %s Style Sets to %s" % (amount, name)

    # create all the children
    for x in range(amount+1):
        # create the style set name
        ss = 'ss'+ str(x+1).zfill(2)
        glyphname = str(name) + '.' + ss
        # create a char slot
        g = font.createChar(-1, glyphname)
        # make this undoable
        g.preserveLayerAsUndo(1)
        # interpolate the top layer
        g.layers[1] = source1.layers[1].interpolateNewLayer(source2.layers[1], interpolationamount[x])
        # interpolate the width
        g.width = source1.width + (source2.width - source1.width)*interpolationamount[x]
        # interpolate the vwidth
        g.vwidth = source1.vwidth + (source2.vwidth - source1.vwidth)*interpolationamount[x]        

        # add lookup for each ss, eg ss01, if it doesn't already exist
        lookup = str(ss)
        if lookup not in font.gsub_lookups:
            flags = ("","")
            featureScriptLangTuple = ((lookup,(("latn",("dflt")),)),)
            # featureScriptLangTuple = (('ss07', (('latn', 'dflt'),)),)
            font.addLookup(lookup, "gsub_single",   (), featureScriptLangTuple)

        # check for existing subtables
        if len(font.getLookupSubtables(lookup)) == 0:
            subtable = lookup + '-0'
            font.addLookupSubtable(lookup, subtable)
        else:
            subtable = font.getLookupSubtables(lookup)[0]
        # add the substitution
        source1.addPosSub(subtable,glyphname)

        # merge the subtables (thanks to khaled hosney for this!)
        for lookup in font.gsub_lookups:
            while 1 < len(font.getLookupSubtables(lookup)):
                font.mergeLookupSubtables(font.getLookupSubtables(lookup)[1], font.getLookupSubtables(lookup)[0])
        
        # let folks know what we did
        message = "  Created %s %s%%/%s%% %s/%s (%s:%s)" % (glyphname, int(100-interpolationamount[x]*100), int(interpolationamount[x]*100), source1.glyphname, source2.glyphname, lookup, subtable)
        note(message)