IntegerStemFinder

Michael Rafailyk
Michael Rafailyk Posts: 168
edited February 26 in Type Design Software

Another stem interpolation (and extrapolation) calculator with the ability to adjust instances after interpolation and easily find the closest integer (or closest to integer) stem or sidebearing.


Links

Online version:
michaelrafailyk.github.io/IntegerStemFinder

Video demonstration:
youtube.com/watch?v=ei9jeOwSu30

Project page on GitHub:
github.com/michaelrafailyk/IntegerStemFinder

Sources

The idea of editable instances is inspired by a comment of Abraham Lee. The idea of finding the closest integer stem or sidebearing is inspired by a comment of George Thomas. The progression formulas are taken from a comment of Linus Romer and from a comment of Abraham Lee. Interpolation of nonlinear progression with intermediate masters uses the second method from a comment of John Hudson.

Features

  • Interpolate linearly (multiple masters setup supported).
  • Interpolate with equal steps for all weights.
  • Interpolate with a progression (multiple masters setup supported).
  • Extrapolate linearly (multiple masters setup supported).
  • Switch any weight to master.
  • Hide any weight from axis.
  • Drag the weight by the handle/line to change its position.
  • Adjust instance after interpolation.
  • Find a closest integer stem or sidebearing.
  • Switch between accurate and rounded stems and sidebearings.
  • See a visualization of stems and sidebearings.
  • See a graph of stem growth curve.
  • Compare interpolation strategies using sets.

A complete list of features:
github.com/michaelrafailyk/IntegerStemFinder?tab=readme-ov-file#features

Colors

Black – master.
Green – instance.
Blue – adjusted instance.
Gray – hidden weight.

Defaults

Default weights and their parameters could be predefined in an array in a JavaScript file. Here you can set default axis configuration, such as: amount of weights; weight position (axis range is from 0 to 1000) and name; weight is master, instance, or hidden; stem and sidebearing values for masters.

defaults: [
	{position: 0, name: 'Hairline', hidden: true},
	{position: 100, name: 'Thin', master: true, stem: 20, sidebearing: 82},
	{position: 200, name: 'Extra Light'},
	{position: 300, name: 'Light'},
	{position: 400, name: 'Regular'},
	{position: 500, name: 'Medium'},
	{position: 600, name: 'Semi Bold'},
	{position: 700, name: 'Bold'},
	{position: 800, name: 'Extra Bold'},
	{position: 900, name: 'Black', master: true, stem: 220, sidebearing: 50}
]

Implementation

Implemented using HTML + CSS + JavaScript. I'm not very familiar with Java, but I know JavaScript a little better, and also I like an idea that it could be accessed from any device connected to internet. To run it offline, download all three files, place it in one directory, and open the index.html file in any browser. However, I recommend using the online version as it will receive updates if any errors are found.

License

MIT License. You are free to fork / copy / download / modify this tool without any permission. In the case of modifications, all the functions and actions are commented and explained inside the JavaScript file.

Comments

  • John Hudson
    John Hudson Posts: 3,350
    Very nice.

    Is Abraham’s progression documented somewhere? I’ve never used it, and am struck by how different it is from all the others.
  • I'm not sure what the initial source of Abraham formula is, but I saw it implemented in steminterpolation by Linus Romer, and in Insert Instances by Rainer Erich.
  • George Thomas
    George Thomas Posts: 652
    edited February 19
  • John Hudson
    John Hudson Posts: 3,350
    Thanks, George. I understand the difference now: Abraham is approaching weight progression in terms of significant distinction between neighboouring weights, versus the others looking at proportional progresssion across the weight range.
  • AbrahamLee
    AbrahamLee Posts: 263
    Very nice.

    Is Abraham’s progression documented somewhere? I’ve never used it, and am struck by how different it is from all the others.
    The progression I came up with is based on two observations:
    1. The instances are noticeably different on the "light" end of a linear/equal progression
    2. The instances are noticeably different on the "heavy" end of an exponential progression

    So, the progression I came up with starts linear and ends up exponential. One consequence of this is that the middle of the range tends to be slightly less different from its neighbor. If one reverses this blend, which is what the "Impallari" progression is, going from exponential to linear, then the the extremes are less different and the middle is more different. There's no clear winner here as each has its trade-offs.

    One example I have found in the wild (and I haven't really looked much) which follows a similar progression as I proposed is the font family "Traction" published by Schriftlabor, which was released around the same time as I came up with the mathematical form of the progression, though I have no idea if there was any influence, or just coincidence.
  • I have a typeface close to release, that follows closer to the Abraham Lee proportions than anything else.

    But in this case, it is the result of wanting something else, but needing to anchor the regular to a “historical regular,” which is heavier than one might otherwise get, given the number of steps and the weights of the extremes. So the progression is what I would consider unusual, or less optimal, as a result.
  • John Hudson
    John Hudson Posts: 3,350
    needing to anchor the regular to a “historical regular”
    I have been in this situation a couple of times, but approached it slightly differently: I did a Luc(as) progression across the whole weight range, and then scaled the progression on either side to relocate the calculated regular to the location of the historical regular.
  • Kent Lew
    Kent Lew Posts: 974
    Question: Why is it that when I view the online tool, the line connecting the instances remains level in all views, rather than showing a curve as in your video demo? I checked in three different browsers and twiddled various parameters, but the line remains flat. (The distribution changes as expected, just not the slope of the line.) What am I missing?

  • John Hudson
    John Hudson Posts: 3,350
    One of the things I like most about this tool is the visualisation of the stem weights and their distances to each other, along the bottom. I have almost always used Luc(as)’s equation, but looking at this visualisation the virtues of the Schneider progression are much more obvious to me than they have been in more abstract calculation tools and graphs.
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited February 21
    Kent Lew said:
    Question: Why is it that when I view the online tool, the line connecting the instances remains level in all views, rather than showing a curve as in your video demo? I checked in three different browsers and twiddled various parameters, but the line remains flat.
    Hi Kent. Sorry for the confusion, that's not a browser support issue, that's a functionality that is temporarily disabled. Originally, that graph displayed the relation between design coordinates and user coordinates (something like in an axis setup graph in FontLab), so that was about position, not stem. The problem is that most people (who tested it) thought that the graph displayed the stem thickness curve, like in other stem calculators. So it was a bit confusing what people were actually seeing, and I temporarily disabled that feature. I'm currently looking for a way to display the stem thickness curve graph (which people expecting to see). It requires a bit more advanced calculation and implementation, and something is works in my tests, just need more time to make it properly. If (or when) I do, I'll bring this (updated) functionality back. If I don't, then I'll probably update all the preview pictures and videos so as not to confuse people.
  • Kent Lew
    Kent Lew Posts: 974
    Ah, thanks for the clarification. I agree that what I would have expected to be seeing is a stem-thickness curve, so if that’s not what was being mapped in your demo, then it makes sense that you disabled it. 
    I might suggest you update the preview pics & videos now, unless you think you can implement a stem curve in the near future. The current mismatch really does make it seem like the tool isn’t fully working. I’m sure I wasn’t the only one trying to figure it out.
    That said, thanks very much for sharing your work.
  • Agree, I updated the preview and video. Thanks for the feedback!
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited February 27
    I finally figured out how to correctly display the stem growth curve for a progressions. So the graph functionality is back. I updated all the files, and also updated the preview and video link.

    When the graph is standalone, this is easy to draw the curve. But in my case (where graph is integrated right into interface), the solution is to compare the equal-step stems to actual (interpolated) stems for each weight, and then correct each point of graph curve for that difference (between equal and actual).
  • John Hudson
    John Hudson Posts: 3,350
    I am wondering if there is a way to add an option to scale the positions of interpolated instances if an instance is manually shifted. I have projects in which there is an inherited intermediate master (most often Regular), whose position is somewhat off from the calculated location of that instance. I would like to be able to apply a progression equation in the tool, then manually set the location of the inherited master, and have the locations of the calculated instances on either side of it scale relative to the new distance between the intermediate master and the extremes. [In theory, any manually set intermediate location can be considered a master, and floating locations between any masters should be scaled relative to those masters.]
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited February 24
    John, if I understood correctly, you want to turn intermediate instance (like Regular weight) to master (which become the 3rd master), and have all instances between masters interpolated?

    Currently it is possible for linear interpolation only (with equal steps between masters). To switch the instance to master, click on the "Instance" button below the weight name. It will be marked as Master and the color will be black. When you set up 3 or more masters, "Segments" button will be highlighted on the left side.

    But if you need it for non-linear progression, like Luk(as) one – not yet, but it will be possible soon. It is already in work, just requires more time for polishing and testing. I'll be back and message here when this functionality will be added.
  • John Hudson
    John Hudson Posts: 3,350
    Thanks, Michael.

    Thinking about this, there seem two possible ways this can be done:

    1) treat each segment between masters as a distinct progresssion with its own interpolation with a limited number of steps; or
    2) treat the overall weight range as a progression, but with portions of it scaled between adjusted master locations.

    I think these methods produce different results. The second method is the one in which I am interested (in part because I already have tools that I can use to the calculate the first method).
  • I made some calculations, and confirm that these two methods produce different results for intermediate instances. In the following test I used Luc(as) progression applied to 8 weights, where Thin and Black are extreme masters, and Extra Light is the second weight. So I observed the percentage of Extra Light relative to segment of Thin (0%) — Regular (100%).

    1. Default
    Interpolation: Thin-Black
    Thin (master): 20 (stem)
    Extra Light (instance): 28.25 = 22.92%
    Regular (instance): 56
    Black (master): 220

    2. First method
    Interpolation: Thin–Regular + Regular–Black

    Thin (master): 20 (stem)
    Extra Light (instance): 28.25 = 22.92%
    Regular (master): 56
    Black (master): 220

    3. First method (Regular stem is changed)
    Interpolation: Thin–Regular + Regular–Black
    Thin (master): 20
    Extra Light (instance): 33.13 = 18.75% (percentage is shifted closer to Thin)
    Regular (master): 90
    Black (master): 220

    4. Second method (Regular stem is changed)
    Interpolation: Thin-Black
    Adjustment: between Thin and Regular, and between Regular and Black

    Thin (master): 20 (stem)
    Extra Light (instance): 36.04 = 22.92%
    Regular (master): 90
    Black (master): 220


    So, the first method (test 2) produce the same result for intermediate instances until Regular stem is unchanged compared to default (test 1) interpolation. But a difference of the first method could be seen in test 3. The second method (test 4) preserves percentage relation for instances between masters regardless of what the stem is set for intermediate (Regular) master. Looks like it make sense.

    @John Hudson, do you think that the second method is better and why do you prefer it? Or are they both considered correct methods? I mean, implementing it is not a problem. The problem is to let the people know what the results they get.
  • Thomas Phinney
    Thomas Phinney Posts: 2,955
    edited February 24
    In principle, I prefer the second method, to the extent that I care. Both are reasonable methods. I do not think one can find a likely case in which they will produce radically different results. Just so long as you have an accommodation for this, that is lovely.

    (As I am not 100% commited to a single interpolation scheme in the first place, so a small detail in how we patch the schemes when we have to anchor a specific intermediate designed master at specific values is just… not a big deal to me.)

    You could theoretically support both! But I can see how that might seem like overkill.
  • You could theoretically support both! But I can see how that might seem like overkill.
    Yeah, that's what I mean. I don't want to add both of them, I want just one which make more sense. And I also prefer the second method.
  • John Hudson
    John Hudson Posts: 3,350
    I have used the first method in the past, but realised that it effectively creates two separate progressions on either side of a pivot master, so you lose the sense of an overall progression between the extremes. What I like about the second method is that you retain the sense of an overall progression. Of course, the proof is in the outcomes when applied to a design.
  • Kent Lew
    Kent Lew Posts: 974
    Thanks for updating the graph, Michael!
    I tend to agree with John’s take on the manual adjustment within a progression. There are tools to create two progressions on either side of a fixed master; but one that adjusts the entire progression to incorporate a fixed point while adjusting the overall curve on both sides to redistribute the designated progression across the whole curve would be value added.
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited February 26
    John, Thomas, Kent, big thanks for sharing your thoughts and proposing ideas.

    I implemented the second method, and now you can add intermediate masters for progressions – one, two, or as many as you need.



    I added the additional check. Intermediate master stem should be inside the range between first and last masters stems. If you set the stem that is out of range, or set empty value, this intermediate master will be turned to instance.

    Another change: "Segments" button is now renamed to "Linear". I suppose that make more sense now. That button is highlighted for linear interpolation between every pair of masters, and also for extrapolation.
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited February 26
     
  • Michael Rafailyk
    Michael Rafailyk Posts: 168
    edited March 1
    A small visual fix. Now, when you add intermediate master for a non-linear progression (and stem value and weight position are the same as interpolated), the handle (of stems curve graph) no longer jumps (like in Linear interpolation), but continues to display a consistent stem growth curve. So now the graph of stems curve looks more organic. This improvement doesn't affect any numbers and it is only about visual.