Coupler
v5.13.22
No font loaded

Coupler — Reference

Coupler computes optical kerning corrections from the actual glyph contour geometry of TrueType and OpenType fonts. No manual pair editing — all values are derived mathematically from outline shapes. Available as a browser tool and as a native Glyphs plugin.

Source & documentation: github.com/jrgdrs/Coupler

What's New

v5.9.17b
Fix — Apply to Glyphs crash (definitive). Diagnostic log proved the crash occurred inside json.loads while parsing 4.7 MB of URL-encoded JSON: this creates tens of thousands of Python objects, reliably crossing the GC generation-2 threshold (gc count (0, 3, 7) vs. thresh (700, 10, 10)). GC fires mid-parse, traverses CouplerDialog.__dict__ (which holds live ObjC proxies), and crashes in visit_decref. Fix: gc.disable() at the start of couplerDispatch_, gc.enable() in finally. With a single URL (v5.9.17 IPC revert), gc.enable() fires exactly once after all ObjC work is complete — no window between chunk calls as in the earlier chunked protocol.
v5.9.10–14
AutoParam — new ⚙ AutoParam button left of the Presets dropdown. Scans all eight analysis parameters (Zones, Smooth, Blur, Glow Blur, Round, Threshold, Lazy, Min Gap) sequentially and pre-fills the fields with font-specific optimal values. Sensitivity metric: Laufweite (total text width = sum of advance widths + kerning corrections) for the 26-word test string. Selection algorithm: lower average — the candidate whose Laufweite is closest to the mean of all below-mean values, representing the converged stable state. Lite analysis processes only the ~52 glyphs and ~130 pairs in the test string (no KERNING_PAIRS lookup) — ~50–100× faster than a full analysis per scan step. Available in both browser mode and Glyphs plugin mode. During the scan the parameter panel is hidden and the log fills the full panel height. AutoParam test string added as first entry in the Preview text preset dropdown.
v5.5
Build system. Source code is now modular: HTML template, CSS, and 14 JS modules in src/. build.js assembles them into ui.html (npm run build). Jest unit test suite covers core margin measurement and kerning math (npm test). No user-visible changes to the tool.

Workflow

  1. Load font — Drop a TTF or OTF file onto the drop zone, or click to browse. In Glyphs mode, click Load & Compute to pull the active font directly from Glyphs.
  2. Set parameters — Adjust Zones, Blur, Smooth, Round module, and other settings. Use a preset as a starting point.
  3. Compute — Click ► Compute Kerning. The cadence scan pre-fills Round module automatically on first load.
  4. Review — Inspect pairs in the Preview canvas and the Coupling Table. Use Margins toggle to check zone coverage.
  5. Export / Apply — Download as CSV, copy to clipboard, or apply directly to the font in Glyphs.

Computation Pipeline

Formula: correction = base − pairMean. Negative = tighten; positive = loosen.

  1. Margin measurement — Each glyph is sliced into Zones equal horizontal bands. Per band, Bezier intersection (cubic + quadratic) finds left and right ink extents. Each margin is averaged over Blur sub-zones to suppress staircase artifacts at oblique curve crossings. In Glow mode, margins are measured from a rasterized pixel map instead of vector intersections, with ink spread controlled by Glow Blur.
  2. Smoothing — A reciprocal step-limit pass (Smooth) constrains jumps between adjacent zone margins, anchoring from the zone of maximum glyph extent outward. Diagonal strokes and open counters converge toward the dominant margin profile.
  3. Baseline — The self-pair of Base Glyph LC (default o+o) and Base Glyph UC (default O+O) sets the target spacing. Tracking offsets this baseline globally.
  4. Pair corrections — For every pair, the mean of all valid zone gaps is compared to the baseline. Corrections violating Min gap are capped ( ⚑). Corrections below Threshold are zeroed. The result is snapped to the nearest multiple of Round module.

Parameters

Presets ↻
Loads a named parameter set tuned for common font styles: Default, Serif Regular/Italic/Bold/Bold Italic, Sans Light/Regular/Bold, Slab Light/Regular/Bold. Overrides all parameter fields at once.
Zones default 16 · range 1–64
Number of equal-height horizontal slices across the full em (ascender to descender). More zones capture finer vertical contour detail at the cost of speed. Recommended: 9–16 for most text fonts.
Smooth default 50 · range 0–99
Reciprocal smoothing strength. 0 = disabled; 99 = maximum (step limit of 1 % of zone height per adjacent zone). Tames diagonal strokes and open counters by constraining margin jumps between zones.
Min gap % default 4 · range 0–100
Minimum ink distance between adjacent glyphs as a percentage of UPM, measured on the raw geometric outline (independent of Smooth or Glow). Covers any part of a glyph that extends beyond its body — including negative sidebearings and descending strokes. Corrections that would bring actual ink closer than this floor are raised to maintain the gap, and marked ⚑. Set to 0 to disable.
Blur default 1 · range 1–50
Number of sub-zones computed per zone for margin averaging. Higher values suppress quantization artifacts where curves cross zone boundaries at oblique angles, at the cost of speed. 1 = single geometric sample per zone.
Glow default on
Switches margin measurement from vector Bezier intersection to a rasterized pixel-scan method. Ink is spread by Glow Blur before the margin edge is detected, simulating optical ink spread and producing softer, optically weighted margins. The Min gap check always uses the raw geometric outline regardless of this setting.
Glow Blur default 20 · range 0–200 font units
Spread radius for the Glow rasterizer. Each pixel's ink influence extends this many font units outward before the margin edge is sampled. 0 = hard pixel edges only.
Round module default 20 · min 1
Snaps all correction values to the nearest multiple of N. Example: module 20 produces values −40, −20, 0, +20, +40. Use 1 for plain integer rounding. Pre-filled automatically from the Cadence scan on first font load; the raw cadence value is adjusted so it falls in the range 20–40 (halved if >40, doubled if <20).
Threshold default 0 · min 0
Corrections with absolute value below this number are set to zero. Eliminates imperceptible micro-corrections that would bloat the kerning table. The threshold is not applied to corrections forced by Min gap.
Lazy % default 20 · range 0–99
Reduces all computed corrections by this percentage before output, then re-snaps to the Round module. Produces softer, less aggressive kerning — useful when the full optical correction feels too tight in print. Example: Lazy = 20, computed = 110 → 110 × 0.8 = 88 → snapped to 80 (module 20). Min gap is enforced after the reduction.
Base Glyph LC default o
Reference glyph for lowercase baseline spacing. The self-pair (o+o by default) is measured and its average zone gap becomes the LC target spacing. Change to 'n' for very square-sided sans-serifs.
Base Glyph UC default O
Reference glyph for uppercase and lining-figure baseline spacing. Analogous to Base Glyph LC for the UC range.
Tracking default 0
Constant offset added to the effective base value before corrections are computed. Negative tightens all spacing; positive loosens. Does not affect the base glyph measurement itself.
Pair limit default 0 (all pairs)
Restricts output to the N most common pairs by real-world text frequency (Andre Fuchs corpus). Set to 0 to include every pair in the font — this is the default. A limit such as 2000 dramatically reduces computation time for large fonts without sacrificing the most typographically relevant pairs.

Results Summary

Displayed in the left panel after each computation.

Glyphs / Pairs
Total glyphs analyzed and kerning pairs produced.
Base LC / Base UC
Measured mean gap of the LC and UC reference self-pairs in font units. All corrections are relative to these values.
Total LC / UC (zones)
Summed zone-margin area across all LC or UC glyphs. Useful for comparing fonts with different proportions at the same UPM.
Margin / Counter / Print LC · UC %
Each glyph's zone area is classified as Margin (side whitespace), Counter (enclosed voids), or Print (ink coverage). These percentages describe the spatial character of the font. All three sum to 100 %.
n / O / o inner fu²
Measured counter area of the three reference glyphs in font units squared. Captures the openness of each counter space.
n / O / o ctr/marg
Counter area divided by (base margin × glyph height). A dimensionless ratio describing counter size relative to margin width — useful for comparing fonts across different UPM values.

Preview Panel

Renders text on a canvas at any size. Kerning corrections are applied as advance-width offsets per pair.

Size slider / number field
Font size in pixels (20–600 px). Both controls are linked and update the canvas immediately.
Text field
Type any string to preview. The preset dropdown offers ready-made test strings: cap pairs, diagonal stress, full LC/UC, Small Caps, Oldstyle Figures, and more.
↔ Kerning ON/OFF
Toggles Coupler kerning on and off. When off, glyphs render in dim blue so the difference is immediately visible.
Margins
Overlays the computed left (amber) and right (green) margin zone bands on each glyph. Zone boundaries are marked with faint white lines, enabling direct inspection of zone coverage and smoothing quality.
Glow
When the last analysis used Glow mode, this overlay adds an amber luminous halo representing the ink spread zone around each glyph's outline. Only active when Glow analysis was used.
Baseline
Shows the typographic baseline as an amber line with label.
x-Height
Shows the x-height as a blue line with label. Requires the font to carry the sxHeight metric in the OS/2 table.
Small Caps
Switches the preview text to the .sc / .smcp glyph variants where the font provides them.
OSF
Switches digit characters to Oldstyle Figure variants (.osf or PUA U+F730–F739) where available.
⊙ Pair
Activates Pair Preview mode. The selected table row is rendered as oLRo nLRn OLRo HLRH — the pair in four representative spacing contexts. Navigate rows with ↑↓ keys. Press Escape or click ⊙ Pair again to exit.

Coupling Table

Lists all computed kerning pairs. Click any column header to sort. Click any row to enter Pair Preview mode.

Left / Right
Glyph names forming the pair.
Correction
Final kerning value in font units after rounding and threshold filtering. Negative = tighten spacing; positive = loosen.
Pair Mean
Average of (right margin of left glyph + left margin of right glyph) across all zones where both glyphs have ink.
Base
The target spacing used for this pair — the LC or UC base value adjusted by Tracking.
Class
Pair classification: LC (both lowercase), UC (both uppercase or lining figures), mixed (one of each, uses LC base). Determines which baseline applies.
Zones
Per-zone gap values shown abbreviated in the cell. Hover the cell for the full zone breakdown. Capped pairs are marked ⚑.
Filter field
Filters the table by glyph name. Single term = exact match on either side. Two space-separated terms = exact left+right pair match. Toggle .* to use a full JavaScript regular expression against glyph names.
↓ Export
Downloads all pairs as a semicolon-delimited CSV including a parameter header. Format per line: Left;Right;Correction (Class zones) [cap]

Spacing Corrections Tab

Analyzes self-pairs (A+A, n+n…) to detect sidebearing imbalances and suggests advance-width and sidebearing corrections that would bring each self-kern to zero.

Histogram
Groups glyphs by their proposed new advance width. Bar width represents relative group count. The bar label shows the glyphs in that group; hover the row for the complete list. The number on the left is the advance width in font units; the number on the right is the group count.
Glyph / Cls
Glyph name and classification (LC or UC).
Old AW
Current advance width in the source font.
New AW
Proposed advance width rounded to the Round module that would make the self-kern approach zero.
Δ AW
Net advance-width change (New AW − Old AW). Red = tighten; green = widen.
Δ Left / Δ Right
Suggested sidebearing adjustments — how much to shift the left or right margin to re-balance the glyph symmetrically within its bounding box.
New L / New R
Resulting left and right margin values after the suggested adjustment is applied.
⊙ Apply Spacing Glyphs mode only
Writes the suggested advance-width and sidebearing corrections directly into the active Glyphs document.

Cadence Tab

Measures the stem rhythm of the lowercase 'n' to derive a natural Round module. The scan runs automatically on font load and pre-fills the Round module field.

Equator
The y-coordinate (font units) at which 'n' is scanned for ink runs. Default: half x-height. Editing this value re-triggers the full cadence scan.
Left / Right read-only
Detected x-positions of the left and right ink-run edges at the equator scan line.
Stem
Width of the first stem in font units (right edge minus left edge of the first ink run). Editable for manual override.
Interval
Distance from the start of the first stem to the start of the second stem — one complete stem+counter cycle.
Divider
Number of sub-steps per stem. Controls the resolution of the dashed divider grid overlay in the canvas. Default: 4.
Step read-only
Interval ÷ Divider. The base grid step of the cadence.
Cadence read-only
Computed Round module candidate: Interval ÷ Divider, rounded. Pre-filled into Round module on first font load. The raw value is adjusted to fall in the range 20–40: if it exceeds 40 it is halved; if it is below 20 it is doubled. This keeps the rounding grid in a practical range regardless of font size or stem density.
⊙ Assign to Round module
Manually copies the current Cadence value (with the same >40/<20 adjustment) into the Round module parameter field and highlights the field briefly.
Canvas
Visualizes the 'n' glyph (28 % opacity) with amber baseline and x-height lines, a white equator scan line, white vertical lines at stem edges, and a gray dashed divider grid. Numeric labels on the right show font-unit positions and the x-height factor relative to the cadence.

Compact Panel

Double-click the Coupler logo to toggle between compact and full panel. In Glyphs mode the compact panel is the default starting view; in the browser the full panel opens by default. The compact panel shows only the essential controls in a narrow window — designed for production use alongside Glyphs.

Load & Compute Glyphs mode
Fetches the active font from Glyphs and runs the full analysis. Always resets and pre-fills the Round module from the cadence scan (adjusted to the 20–40 range).
n Cadence canvas
Compact cadence visualization — same overlay as the Cadence tab but without labels, scaled to the panel width.
Round module
Pre-filled from the cadence scan on first load. Edit freely; Recompute always uses the current field value without overwriting it.
Threshold / Lazy % / Pair limit
As per the full panel. Threshold suppresses noise; Lazy % softens the overall correction magnitude; Pair limit caps the number of pairs generated.
↻ Recompute
Re-runs the analysis with current field values. Enabled only after the first Load & Compute. Does not reset Round module.
⊘ Kerning to Clipboard browser mode
Copies all kerning pairs to the system clipboard in the same semicolon-delimited format as the CSV export, including the parameter header lines.
↓ Export CSV  /  ⊙ Apply to Font
Browser mode: downloads the kerning CSV. Glyphs mode: writes kerning pairs from the last computation directly into the active Glyphs document.

Testpage

Opens an A4 landscape print window with six text blocks at sizes 9–16 pt, using European-language sample texts. Coupler kerning is embedded. Use Cmd+P / Ctrl+P to print or export as PDF.

Log

The log box at the bottom of the left panel records computation steps, timing, and errors in real time. Green = success, amber = info, red = error. The divider above it can be dragged to resize the log area.

Glossary

UPM
Units Per Em — the internal coordinate grid of a font. All distances (margins, corrections, gap floors) are in UPM units.
Advance Width
Total horizontal cursor advance after placing a glyph, including both sidebearings.
Margin
Gap between the outermost ink edge and the advance-width boundary, measured per zone on the left and right side.
Zone
One equal-height horizontal slice of the em. More zones = finer vertical detail; higher computation cost.
Pair Mean
Average of (right margin of left glyph + left margin of right glyph) across all zones where both glyphs have ink.
Base Value
Target pair mean from the reference glyph self-pair. All corrections are measured relative to this.
LC / UC / Mixed
Pair classification. LC = both lowercase; UC = both uppercase or lining figures; Mixed = one of each (LC base applies).
Capped ⚑
Correction was reduced to avoid violating the Min Gap floor. The cell in the table is marked with ⚑.
Self-Kern
Kerning correction of a glyph paired with itself (A+A). Non-zero indicates sidebearing imbalance in the source font.
Counter
Enclosed interior void of a glyph (e.g. the hole in 'o' or 'p'). Measured by pixel scan on an off-screen canvas.
Print Area
Total ink coverage of a glyph in font-unit² (sum of ink-covered pixels in the zone raster).
Cadence
The natural stem-rhythm interval of the 'n', used as the Round module grid. Derived as Interval ÷ Divider.
Glow mode
Pixel-based margin computation with configurable ink spread radius. Produces optically weighted margins for high-contrast and ink-trap designs.
Small Caps (SC)
Glyph variants with names ending in .sc or .smcp.
OSF
Oldstyle Figures — non-lining numerals with names ending in .osf or PUA code points U+F730–U+F739.
Pair Limit
Maximum pairs to compute, ranked by real-world text frequency (Andre Fuchs corpus). Set 0 for all pairs.
Laufweite
Running width — the total horizontal extent of a text string: sum of all glyph advance widths plus all kerning corrections for consecutive pairs. Used by AutoParam as the sensitivity metric: a parameter change that shifts Laufweite by ≥10 font units is considered significant.
Lower average (Laufweite)
The mean of all Laufweite values (across AutoParam candidates) that are at or below the overall mean. This represents the converged stable state of accurate kerning — free from the over-loosening caused by too-coarse parameter values. AutoParam selects the candidate whose Laufweite is closest to this value.
Parameter variance
Spread of Laufweite values measured across AutoParam candidates for a single parameter. High variance indicates the parameter has a strong effect on kerning quality for this font; low variance indicates the parameter is less critical. The lower average identifies the stable low-Laufweite region of the distribution.

AutoParam

AutoParam automatically detects font-specific optimal values for all eight analysis parameters. It measures how each parameter affects the Laufweite (running width) of a standard test string and pre-fills the parameter fields with the found values.

Available in both browser mode and Glyphs mode (requires font data loaded via Load & Compute). Click ⚙ AutoParam left of the Presets dropdown. During the scan the parameter panel is hidden and the log fills the left panel; parameters are restored when the scan completes.

Test string
Arrowroot Barley Chervil Dumpling Endive Flaxseed Garbanzo Hijiki Ishtu Jicama Kale Lychee Marjoram Nectarine Oxtail Pizza Quinoa Roquefort Squash Tofu Uppuma Vanilla Wheat Xergis Yogurt Zweiback — 26 words covering all uppercase initials, mixed lowercase, and a broad range of letter shapes (round, diagonal, straight, narrow, wide).
Algorithm
Each parameter is scanned independently across a set of candidates (e.g. Zones: 3, 9, 18, 36, 48, 96). For each candidate the full kerning analysis is run with all other parameters at their current or accumulated optimal values. All Laufweite values are collected; the lower average (mean of values at or below the overall mean) is computed. The optimal candidate is the one whose Laufweite is closest to this lower average — the converged stable state that characterises accurate kerning for the given font.
Parameter scan order
Zones → Smooth → Blur → Glow Blur → Round → Threshold → Lazy → Min gap. Each scan uses the optimal values already found for earlier parameters, so later scans reflect realistic combined conditions.
Result
All eight parameters are pre-filled with the detected optimal values and a final analysis is run automatically. The result represents a font-specific starting point — further manual adjustment is always possible.
Duration
Each scan step uses a lightweight analysis that processes only the ~52 glyphs and ~130 pairs needed for the test string — no KERNING_PAIRS lookup, no UI updates. Total: up to 6+5+5+6+5+5+5+6 = 43 lite passes, plus one full analysis at the end. Typical runtime: a few seconds for most fonts.

Source code & documentation: github.com/jrgdrs/Coupler

Drop TTF / OTF font here
or click to browse
Parameters
Zones (subtlety)--zones · height divisions
Smooth (diagonals and counter)--smooth · 0=off, 99=max smooth
Min gap % (no touch)--mingap · % of UPM floor
Blur (less details)--blur · sub-zones per zone
Glow (pixel-based)--glow · rasterized margins
Glow Blur (ink spread)--glowblur · radius in font units
Round module (cadence)--round · kern snap value
Threshold (suppress noise)--threshold · min abs correction
Lazy % (soften output)--lazy · reduce corrections by %
Base Glyph LC (reference char)--base-lc · char+char pair
Base Glyph UC (reference char)--base-uc · char+char pair
Tracking (global offset)--tracking · offset on base values
Pair limit (top N by frequency)--pairs · 0 = all pairs
Results
Glyphs
Pairs
Base LC
Base UC
Total LC (zones)
Total UC (zones)
Margin LC %
Counter LC %
Print LC %
Margin UC %
Counter UC %
Print UC %
n inner fu²
n ctr/marg
O inner fu²
O ctr/marg
o inner fu²
o ctr/marg
n Cadence
Preview
Load a font to get started