Zero-Width Characters for Complex Scripts in FontForge
Configuring zero-width characters in FontForge is essential for designing complex scripts such as Arabic, Devanagari, and Thai, where combining marks, diacritics, and control characters dictate proper text shaping. This guide covers how to accurately assign Unicode values, set advance metrics to zero, configure OpenType Glyph Definition (GDEF) tables, and establish anchor positioning for seamless script rendering in modern text shaping engines.
1. Create the Glyph and Assign the Unicode Codepoint
- Open your font project in FontForge.
- Navigate to View > Go to and enter the specific
hex codepoint for your character. For invisible control characters, use
standard codes such as
U+200C(Zero-Width Non-Joiner / ZWNJ) orU+200D(Zero-Width Joiner / ZWJ). For combining marks or vowel signs (matras), locate the script-specific Unicode slot (e.g.,U+094Dfor Devanagari Virama). - If the slot is empty, double-click to open the glyph canvas, or right-click and select Glyph Info to confirm the correct name and Unicode mapping.
2. Set the Advance Width to Zero
A zero-width character must not advance the text cursor horizontally when rendered.
- Select the glyph in the font matrix or open it in the glyph editor window.
- Go to Metrics > Set Width... from the top menu.
- In the dialog box, enter
0and click OK. - Alternatively, open the Metrics Window
(Metrics > New Metrics Window), type the character,
and manually drag the right side bearing (RSB) line until the width
displays as
0.
Note for invisible control characters (ZWJ/ZWNJ): The glyph
should contain no outlines or contours—only a width of
0.
Note for combining marks: The glyph should contain your
drawn outline. The advance width remains 0, while the
visual contours will sit outside the zero-width boundary (often
requiring negative left side bearings) so they overlap correctly with
the base glyph.
3. Classify the Glyph in the GDEF Table
Complex text shapers (such as HarfBuzz and DirectWrite) rely on OpenType Glyph Definition (GDEF) tables to determine whether a glyph is a base, a mark, or a ligature.
- Go to Element > Font Info.
- Select Lookups from the left-hand panel, then switch to the GDEF tab.
- Under Glyph Class Def, ensure your zero-width combining marks are categorized as Mark.
- If using a mark attachment class, assign the glyphs to their respective mark sets so the shaping engine correctly skips or includes them during contextual lookups.
4. Implement Anchor Points for Mark Positioning (GPOS)
For visible zero-width marks, you must define anchor points to position them relative to base consonants:
- In Element > Font Info > Lookups, navigate to the GPOS tab.
- Click Add Lookup, choose Mark-to-Base
Positioning (
mark), and add a subtable. - Open the base glyph canvas and place an anchor point via
Point > Add Anchor, designating it as a "Base" point
(e.g.,
top). - Open the zero-width mark canvas, add an anchor point with the
matching name (
top), and set its type to "Mark". - Align the mark anchor to the exact connection coordinate relative to
the base glyph. Repeat this process for Mark-to-Mark
(
mkmk) lookups if diacritics stack vertically.
5. Configure Contextual Substitutions for ZWJ/ZWNJ (GSUB)
If the zero-width character is an invisible joiner used to force or suppress ligatures:
- Go to Element > Font Info > Lookups > GSUB.
- Create a Chaining Contextual Substitution or a
standard Ligature lookup under features like
akhn(Akhand),half(Half Forms), orccmp(Glyph Composition/Decomposition). - Define lookup rules where the presence of
U+200Dsubstitutes a base character with its half-form or explicit conjunct, and rules whereU+200Cblocks standard script ligation.
6. Verify and Export
- Open Metrics > New Metrics Window to test the character sequences.
- Input combinations of base characters, joiners, and zero-width marks to ensure the cursor does not advance unnecessarily and that attachments snap to the defined anchor points.
- Export the font as OpenType (
.otfor.ttf) via File > Generate Fonts, and validate the compiled OpenType layout using external shaper tools such ashb-vieworhb-shape.