I'm programmatically converting (in perl with Font::TTF) a proportional font to "fixed-width" and wrestling with nested composite glyphs. Straightforward approach seems horrendously complex, and I'm wondering if there is a simpler approach that I am missing ...
Adjusting of simple glyphs is straightforward: reset AdvanceWidth and, if needed, shift glyph points in the X axis. However ...
If a simple glyph is a component in another composite glyph, the attachment points are now incorrect since the component may be X-shifted. The attachment points have to be adjusted to account for the X-shift.
Furthermore, composite glyphs can be arbitrarily nested, so some kind of iterative strategy seems to be needed. No composite glyph can be processed until all it's components have been processed ... i.e. starting with all simple glyphs then composite glyphs that only have simple glyphs as components, then working your way up the dependency tree of composite glyphs. At each stage, a structure is needed to remember how much each component has been re-positioned.
Things get (much) more thorny if I want to scale some wider glyphs in the X direction to fit the fixed-width bounding box, such as is done by the Python-based monospacifier tool (
https://github.com/cpitclaudel/monospacifier ... which I can't actually run)
Is there a simpler strategy to what I'm trying to do?
I could (groan) flatten composites into simple glyphs, but that seems heavy-handed.
FYI, I can't just set the OS2.isFixedPitch and let (hope) the rendering engine forces everything to monospace, since the font does use 3 widths: 1× wide (eg. Latin), 2× wide for most Asian 'fullwidth', and 0 wide for appopriate code points, so not strictly monospaced.
Any thoughts / ideas appreciated!
Comments
And, BTW, scaling is a nightmare, because component glyphs need to scale differently depending on the total size of the parent composite, which implies duplicating component simple glyphs to serve different parent composite glyphs. Sigh.
I'm doing this in a hybrid Perl / Python / Excel / OtherBitsAndPieces pipeline, so all this FixedWidth-ifier needs to be programmatic ...
** "glyph-compatible" is my term ... I have not seen a better one in use. I say that a license, A, is “glyph-compatible” with license B if both licenses allow code and data (typically glyph data) to be extracted from a font released under A and incorporated into a font released under B.
I disagree that converting to an actual stroke-based format is the necessary/only route to do this.
That said, in any case, the interest in automating such a process has been around for decades, and experienced programmers who also know fonts have not yet done it. There have been ways it could have been done... for example, the folks who made FontChameleon could easily have extended it to do this. But understand that said system required a human to manually turn a font into a "Chameleon" font descriptor, prior to doing any such thing. I am just saying that given the tech as it existed, they could have added an instant-monospace feature in a day, and it would have worked with all their existing font descriptors.
But not with a bunch of arbitrary, existing open source fonts. That capability we do not have, and can’t be reasonably programmed in a day, a week, or a month. Nor probably even a year.
You could write a program to take a variable font with a width axis and spit out a monospaced font, though. That would be cool, and totally plausible. Somebody should do that. But it wouldn’t work with non–variable-font sources.
That would be fine for cases where the glyph doesn't get wide enough. What you want the app to do when the glyph doesn't get narrow enough (let's say, cap M for example) is more... interesting. Sidebearings can only do so much. So in that case, you probably say that you can't get rid of more than half of each sidebearing.
Then what? Either:
At the end of the day, would still benefit from human intervention, but automation could get you most of the way there. IF you already have a weight axis, which is... not entirely trivial.