Re-Interpolate with specific masters

Is the possible to specify the exact set of masters that are used for Re-Interpolating via scripting?

There is internal API that can be accessed by a script. I’ll put something together, soon.

2 Likes

@GeorgSeifert any update on how to access this?

You can peek into the KinkFinder and Interpolate two paths scripts. Or the Variation Interpolator.

Those scripts were helpful. Got to this point and am running into some questions. Simple/messy version of the script so far:

tempGlyph = GSGlyph()
thisGlyph = Font.glyphs['A']
#SOURCE: Regular
layerA = thisGlyph.layers[Font.masters[0].id].copy()
#SOURCE: Bold
layerB = thisGlyph.layers[Font.masters[2].id].copy()
#DESTINATION: Medium
layerC = thisGlyph.layers[Font.masters[1].id]

tempGlyph.layers = [layerA, layerB]

interpolationFactor = .92
#interpolationFactor = .5

tempLayer = tempGlyph._interpolateLayers_interpolation_masters_decompose_font_error_(
	[layerA, layerB], 
	{
		layerA.layerId:interpolationFactor,
		layerB.layerId:1-interpolationFactor,
	}, 
	None, False, Font, None)

for i in range(len(layerC.shapes)-1,-1,-1):
	del layerC.shapes[i]
	print (layerC.shapes)
	layerC.shapes.append(tempLayer.paths[i])
for i in range(len(layerC.anchors)-1,-1,-1):
	del layerC.anchors[i]
	layerC.anchors.append(tempLayer.anchors[i].__copy__())
	
l = thisGlyph.layers[Font.masters[1].id]
l.roundCoordinates()

Questions:

  1. How to calculate the interpolation factor based on the selected source and destination masters?
  2. When the interpolated paths are appended, the shape order changes…how can I keep the original shape order?
  3. Should roundCoordinates() be used like this?

Grateful for any help clean up and consolidating the code, and any additions for things that may be overlooked.

I don’t understand Q 1. I thought you wanted to define a certain interpolation factor yourself…?

2: just set the shapes of the destination layer to (copies of) the shapes of the interpolated layer. The whole collection at one. Don’t need to go one by one.

3: I would think so. Does it not work?

  1. For the interpolation factor, for one part I was trying to figure out the same way as a Medium instance is interpolated from a Regular and Bold through the Exports tab. How is that factor calculated?

  2. Do you mean basically setting it like this?
    layerC.shapes = tempLayer.shapes
    It wasn’t including the anchors so should I add this separately?
    layerC.anchors = tempLayer.anchors

One issue I am running into now with adding the looping-through-masters part is that glyphs with corner components lose their components. This might be due to something else but from a glance, are there any obvious mistakes?

for masterIndex, thisMaster in enumerate(Font.masters):
    tempGlyph = GSGlyph()
		layerC = Font.glyphs[glyph.name].layers[dest]
    if  nameLayerA == thisMaster.name:
        layerA = glyph.layers[thisMaster.id].copy()
        layerA.layerId = "layerIDA%05i" % masterIndex
        continue
					
    if nameLayerB == thisMaster.name:
        layerB = glyph.layers[thisMaster.id].copy()
        layerB.layerId = "layerIDB%05i" % masterIndex
        continue
					
    tempGlyph.layers = [layerA, layerB]

    interpolationFactor = .92
    tempLayer = tempGlyph._interpolateLayers_interpolation_masters_decompose_font_error_(
        [layerA, layerB], 
        {
            layerA.layerId:interpolationFactor,
            layerB.layerId:1-interpolationFactor,
        }, 
        None, False, Font, None)
				
        layerC.shapes = tempLayer.shapes
        layerC.anchors = tempLayer.anchors
  1. You don’t need a script for that. You can simply reinterpolate. Exactly in the middle is 0.5/0.5, but where a good place for the Medium is depends on the design of the masters of course. YMMV.
  2. Yes. Perhaps you need to from copy import copy as copy and then copy(tempLayer.shapes)

Apart from the over-indent of the last two lines, it looks good.

The interpolation factor is simply the percentage of where between the two interpolation sources (a, b) the interpolation destination (c) is.
factor = (c - a)/(b - a)

1 Like

Then set like this?
layerC.shapes = copy(tempLayer.shapes)

This still isn’t copying the corner components.

Then you also need to copy the layer.hints

Looks like that did it!
Thanks for the help.

Running into one more issue/bug with the sidebearing values not updating correctly after interpolation.

If I move a node or manually make an adjustment, it updates. It will also updates after closing and opening the file.

Is this a bug or is there something I need to add to the script?

metrics_not_updating

3.1 (3133)

Not sure I understand what exactly is the issue. The interpolation gives you a wrong or unexpected sidebearing?

If I distort the outline of the shape-to-be-interpolated, the LSB changes to 637.

After running the script, the interpolation is correct but the reading of the LSB still remains the 637 instead of updating to be 1136.

I see; you may need to force an update of the edit view. I’ll post some sample code later. Or ignore it because it is only temporary and UI-cosmetic.

An update edit view sample code would be great.

I don’t think I can ignore because there are metric keys set to that glyph and once it has that incorrect sidebearing other glyphs reference that and end up setting to those units.

To update the view, simply run tab.forceRedraw().

Getting NameError: name 'tab' is not defined

Tried this to define the current tab:

currentEditViewController = Glyphs.currentDocument.windowController().activeEditViewController()
currentTab = currentEditViewController.graphicView()
currentTab.forceRedraw()

Get this error:
AttributeError: 'NSKVONotifying_GSGlyphEditView' object has no attribute 'forceRedraw'

Also tried:
Font.currentTab.forceRedraw()
No errors but it doesn’t seem to do anything

Try the Method Reporter script for finding the correct method.