Compensated tuning tools
These tools help you preview and optionally apply a compensated tuning transform to outlines across masters.
This is a two-master compensated scaling workflow:
- it compares a base master and a different reference master with compatible outlines,
- it computes interpolation factors from the geometric difference between those two masters, and
- it applies those factors while scaling (
sx,sy) to preserve stroke thickness approximately.
This is not a generic "make this one master lighter/darker" tool.
review_compensated_tuningcomputes tuned outlines for one glyph (no mutation).apply_compensated_tuningapplies the same transform across many glyphs (requires confirmation).measure_stem_ratiois an optional helper that estimates the stem ratiobused for compensation.
This workflow is meant for typographers and font engineers: it is deterministic, inspectable, and safe by default (dry-run and confirm gates, no auto-save).
What the tools change (and what they don’t)
Changes (only when applied)
- Replaces paths (outlines) in the target master layer.
- Updates layer width for the target master layer.
- Optionally adds a backup layer per glyph before applying.
Does not change
- Kerning
- Components or anchors (and components are not supported for tuning)
- Any files on disk (no auto-save)
Important constraints (read this first)
-
No components
review_compensated_tuningandapply_compensated_tuningrefuse glyph layers that contain components. Decompose first, tune, then rebuild components if needed. -
Compatible outlines across masters
The tool requires the base and reference master layers to have matching path/node structure (same path count, node count, node types). -
Two different masters are required for a meaningful result If
base_master_id == ref_master_id, the current implementation has no geometric delta to interpolate from. In practice, that means the result is unchanged. -
This is a scaling workflow, not a standalone thinning workflow
keep_strokeonly matters when the tool is computing compensated interpolation from a real two-master setup. It is not a "lighten this master in place" knob. -
Safety gates
apply_compensated_tuningrefuses to mutate unless you usedry_run=trueorconfirm=true. It never auto-saves.
When to use this tool
Use it when you want to:
- scale a master horizontally and/or vertically,
- use a second master to preserve stroke behavior while scaling,
- preview or apply the same compensated transform across many compatible glyphs.
Typical example:
base_master_id = Regularref_master_id = Boldsx = 0.97to condense slightlysy = 1.00to keep height unchangedkeep_stroke = 0.9to preserve stroke thickness during that scaling
When not to use this tool
Do not use it when you want to:
- make one master slightly lighter or darker without using another master,
- thin outlines in place with
base_master_id == ref_master_id, - change weight while leaving
sx = 1andsy = 1and expectingkeep_stroketo do the work, - process component-based glyphs without decomposing them first.
If your font only has one usable master for a glyph, or if the reference master is structurally incompatible, this tool is the wrong tool for that task.
Concepts (plain language)
Base vs reference vs output
base_master_id: the master you are tuning toward (often your “current” master).ref_master_id: the master you are tuning from (often the next heavier master on the weight axis).output_master_id: where the tuned outlines are written (defaults tobase_master_id).
b, q_x, q_y
bis a stem thickness ratio (ref/base) used to compensate the interpolation.- If you don’t provide
q_x/q_y(and masters differ), the tool can estimatebautomatically viameasure_stem_ratio-style measurements. - If you do provide
q_x/q_y, those explicit values override the computed compensation. In that case,keep_strokeis no longer the control that determinesq. extrapolationcontrols what happens when computedqfalls outside[0..1]:"clamp"(default): clamp and warn"allow": allow extrapolation"error": fail fast
Why two masters are needed
The algorithm does not "invent" a lighter or heavier outline from one shape alone. It uses:
- the base-master point positions,
- the reference-master point positions,
- and the stem-thickness ratio between those two masters
to compute a compensated interpolation.
With a single master, there is no geometric difference to interpolate from, so the current implementation has nothing to work with.
Recommended workflow (safe)
Step 0) Identify masters
Use:
list_open_fonts→ pickfont_indexget_font_masters→ get master IDs
Step 1) (Optional) Measure b
If you want to inspect the measured ratio (or tune defaults), call:
{
"font_index": 0,
"base_master_id": "BASE_MASTER_ID",
"ref_master_id": "REF_MASTER_ID",
"stem_source": "auto",
"reference_glyphs": ["H", "n", "I", "o", "E"]
}
Tool: measure_stem_ratio
Look at ok, b, and warnings.
Important:
- use different base and reference masters for a meaningful ratio,
- do not use
base_master_id == ref_master_idunless you intentionally want a neutral baseline.
Step 2) Preview on one glyph (no mutation)
Tool: review_compensated_tuning
{
"font_index": 0,
"glyph_name": "A",
"base_master_id": "REGULAR_MASTER_ID",
"ref_master_id": "BOLD_MASTER_ID",
"sx": 0.97,
"sy": 1.0,
"keep_stroke": 0.9,
"extrapolation": "clamp",
"round_units": true
}
The result is set_glyph_paths-compatible (paths, width) and includes a gmcp metadata block with:
- computed
qX/qYandwarnings steminfo whenbwas measured automatically
Read the result like this:
- if
computed.qX/computed.qYdiffer from1, the transform is doing real interpolation work, - if you used the same master for base and reference, expect the result to be unchanged,
- if you supplied explicit
q_x/q_y, those values are the real driver of the transform.
Step 3) Dry-run apply across a set
Tool: apply_compensated_tuning
{
"font_index": 0,
"glyph_names": ["A", "B", "C"],
"base_master_id": "REGULAR_MASTER_ID",
"ref_master_id": "BOLD_MASTER_ID",
"output_master_id": "REGULAR_MASTER_ID",
"sx": 0.97,
"sy": 1.0,
"keep_stroke": 0.9,
"extrapolation": "clamp",
"backup": true,
"dry_run": true
}
Inspect:
dryRunsummary.okCount / skippedCount / errorCountresults[]per glyph (and why something was skipped)stemifbwas measured automatically
Before applying, confirm that:
- base and reference are different masters,
- the glyphs you selected are outline-compatible across those masters,
- the preview actually changed the geometry you care about.
Step 4) Confirm apply (writes outlines)
Re-run apply_compensated_tuning with the same args, but confirm=true (and dry_run=false).
After applying, consider doing a visual proof pass in Glyphs and optionally calling save_font to persist.
Common mistakes
-
Using the same master for both
base_master_idandref_master_idThis gives the algorithm no second shape to interpolate against. Expect no path change. -
Expecting
keep_stroketo lighten a master by itselfkeep_strokecontrols compensation within a scaling workflow. It is not a standalone weight-editing parameter. -
Supplying
q_x/q_yand then tuningkeep_strokeOnceq_x/q_yare explicit, they override the computed compensation. -
Using
measure_stem_ratiowith the same base and reference master and treating that as an active tuning setup That is only a neutral baseline.
Troubleshooting
- “Glyph layers contain components”: Decompose components; the tuning transform expects point-level outlines.
- “Incompatible outlines between masters”: Ensure the masters have matching node structure for that glyph (paths/nodes/types).
- No visible path change: Check whether you used the same base/ref master, whether your preview reported
qX = qY = 1, or whether you supplied explicitq_x/q_ythat keep the shape nearly unchanged. - Too many warnings about clamping: Try
"extrapolation":"allow"for exploration, or adjustkeep_stroke/ provide explicitq_x/q_y.
Reference
- Full tool list: Command set