[metapost] Trying to use MT1 to make outline fonts... (again)

mskala at ansuz.sooke.bc.ca mskala at ansuz.sooke.bc.ca
Tue Jun 19 19:32:45 CEST 2012

On Tue, 19 Jun 2012, Shriramana Sharma wrote:
> To produce outlines suitable for Type 1 fonts,
> all envelope overlapping should be removed. The
> result of this operation is shown in figure 6.</quote>
> If it is thus possible to obtain the actual METAFONT envelopes, why
> does MT1 (or any other program attempting to convert MF to outlines)
> not just use these envelopes (and remove overlapping using FontForge
> or such)?

I use a FontForge script to remove overlaps.  There are macros in
METATYPE1 that attempt to do it, but they don't seem to work reliably on
the more difficult cases, and FontForge is faster.  I imagine that some
authors hoped to do it all in METAFONT-language code without needing an
external tool.

Note that I think the "envelopes" in question were calcuated by the
METATYPE1 pen_stroke() macro, i.e. they are *paths* in the METAFONT
language.  They are not the bitmapped results of the METAFONT-native
pen-stroking operation.

FontForge is itself a bit unreliable.  It tends to die when, for instance,
there are many paths all intersecting at or near a single point.  I simply
design my glyphs to avoid creating the situations that I've found to be

> <quote>Note
> that the resulting outlines contain too many con-
> secutive lines and curves split into many pieces. To
> obtain outlines free from such defects, I have made
> some geometrical optimization.
> </quote>
> Does anyone know whether he (or is he on this list?) published the
> nature of these optimizations? Are there generic scripts that do this
> or is it manual?

I don't know exactly what he means there, but I have noticed that the
outlines sometimes contain very short segments that cause Metapost to
throw an error about "degenerate" paths.  I use a macro of my own called
"regenerate" to remove such segments.  Here is its source, which I release
to the public domain (also in mp/intro.mp in the Tsukurimashou distribution):

def regenerate(expr p) =
    save q;
    path q;
    for t=1 step 1 until length p:
      if abs((point t of p)-(point (t-1) of p))>3:
        if unknown q:
          q:=subpath (t-1,t) of p;
        elseif length(q)=1:
          q:=(point 0 of q)..
              controls (postcontrol 0 of q) and (precontrol 1 of q)..
            (0.5[point 1 of q,point t-1 of p])..
              controls (postcontrol t-1 of p) and (precontrol t of p)..
            (point t of p);
          q:=(subpath (0,length(q)-1) of q)..
              controls (postcontrol length(q)-1 of q)
                and (precontrol length(q) of q)..
            (0.5[point length(q) of q,point t-1 of p])..
              controls (postcontrol t-1 of p) and (precontrol t of p)..
            (point t of p);
    if cycle p:
      q:=subpath (0,length(q)-1) of q..
           controls (postcontrol length(q)-1 of q)
             and (precontrol length(q) of q)..

Running it through FontForge can also clean up things like unnecessary
extra points in the middle of simple lines and curves.  However, it's
necessary for the path to be clean enough not to kill the Metapost
interpreter, before we can even start working on it with a FontForge
Matthew Skala
mskala at ansuz.sooke.bc.ca                 People before principles.

More information about the metapost mailing list