Home / Alt manpages / ppmdcfont(1)

  • ppmdcfont(1)
  • User command
  • linux

Turn a Ppmdfont File into a Non-Conflicting Netpbm Font

You will finish with a C source file generated from a Netpbm Ppmdfont file, plus a checked name for the font object before you hand it to a build. The examples use Netpbm package version 2:11.05.02-1.1build1, as installed on this machine.

Allow about fifteen minutes. You need a shell, the ppmdcfont and ppmdmkfont commands, and a writable working directory. No step needs sudo. This guide generates files in your working directory but does not install a font or change the system library.

1. Check the installed contract

ppmdcfont has no options or positional arguments. It reads one Ppmdfont file from standard input and writes C source to standard output. Confirm the binary and package version first:

$ command -v ppmdcfont
/usr/bin/ppmdcfont
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ man ppmdcfont

Checkpoint: if command -v finds nothing, stop and install Netpbm through your normal package-management process. Do not invent an option such as --input: this program's interface is the standard-input and standard-output pipeline shown above.

2. Produce or choose a Ppmdfont input

For a reproducible smoke test, use ppmdmkfont. It creates the standard Ppmdfont on standard output and accepts no input. The standard font is already built into libnetpbm, so this file is an example input, not a new system font.

$ workdir="$PWD/ppmdcfont-work"
$ mkdir -p "$workdir"
$ ppmdmkfont > "$workdir/example.ppmdfont"
$ file "$workdir/example.ppmdfont"
$ od -An -t x1 -N 8 "$workdir/example.ppmdfont"
 70 70 6d 64 66 6f 6e 74

The first eight bytes spell ppmdfont. A font made by another tool should have the same format. The file name commonly ends in .ppmdfont, but the suffix is a convention, not what makes the input valid.

Checkpoint: inspect an input you did not create before converting it. This diagnostic writes its description to standard error, so redirect that stream to a review file:

$ ppmddumpfont < "$workdir/example.ppmdfont" 2> "$workdir/font-report.txt"
$ sed -n '1,8p' "$workdir/font-report.txt"
ppmddumpfont: Font has 95 characters
ppmddumpfont: Font has code points 32 through 126
ppmddumpfont: Code point 32:
ppmddumpfont:   skip before: 0 pixels; skip after: 21 pixels; 0 commands:

Your report can contain different counts for a custom font. A non-zero status or a report that stops with a parse error means the input is not ready for conversion.

3. Generate the C source

Use input redirection for the Ppmdfont and output redirection for the generated source. Choose a new destination while testing. Shell redirection truncates an existing file before the program runs, so do not point it at a source file you need to preserve.

$ ppmdcfont < "$workdir/example.ppmdfont" > "$workdir/example-font.c"
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ sed -n '1,12p' "$workdir/example-font.c"
/* THIS FILE WAS GENERATED BY 'ppmdcfont' from a ppmdfont file. */

#include "ppmdfont.h"

struct ppmd_glyphCommand const ppmd_standardfont_glyphTable_cmd_33[8] = {

The exact number of generated lines depends on the input. The useful checks are a zero exit status, the generated-file header, and an include of ppmdfont.h. An empty output file is not a successful font conversion even if a later shell command hid the original status.

4. Rename the generated object before linking

This is the most easily missed part. The generated C source calls the font object ppmd_standardfont. That is also the name used by the font built into libnetpbm. Leaving the name unchanged can cause a duplicate symbol at link time and makes it unclear which font a program is using.

Make a copy, then replace the generated identifier consistently. Use a name that is a valid C identifier and specific to your font:

$ cp -- "$workdir/example-font.c" "$workdir/acme_font.c"
$ sed -i 's/ppmd_standardfont/acme_font/g' "$workdir/acme_font.c"
$ rg -n 'ppmd_standardfont|acme_font' "$workdir/acme_font.c"
3168:struct ppmd_font const acme_font = {
3176:  /* .glyphTable: */ acme_font_glyphTable

Your line numbers will differ. The important result is that the old identifier is absent and the replacement appears in the font object and its generated glyph-table names. Do not perform a broad search-and-replace on unrelated source files.

Checkpoint: verify the old name explicitly:

$ if rg -n 'ppmd_standardfont' "$workdir/acme_font.c"; then
>     echo 'old font identifier remains' >&2
>     exit 1
> fi
$ test -s "$workdir/acme_font.c" && echo 'renamed C source is non-empty'
renamed C source is non-empty

5. Hand the source to the matching Netpbm build

ppmdcfont generates declarations that depend on Netpbm's ppmdfont.h and the corresponding library interfaces. Compile the renamed file only in the project that provides the matching Netpbm development headers and library. This machine has the runtime command and library package, but a missing development header is a build-environment problem, not a reason to edit the generated C.

Before adding the file to a real build, inspect the generated include and locate the header through the development package's documented include path:

$ rg -n '^#include "ppmdfont.h"' "$workdir/acme_font.c"
3:#include "ppmdfont.h"
$ find /usr/include -name ppmdfont.h -print

If the final command prints nothing, stop and install or expose the appropriate Netpbm development files through your normal build setup. Do not copy headers from an unrelated Netpbm release. Compile in a disposable build directory first, then link the font into the program or library that will use it.

There is no service restart or privileged installation in this workflow. To undo the generated artefacts, remove only the named working directory after checking that no build refers to it:

$ rm -rf -- "$workdir"

That removal is irreversible. If you need to keep the generated source, leave the directory in place or archive it before cleaning up.

6. Diagnose the common traps

  • "No arguments" means no file operand. Use ppmdcfont < font.ppmdfont > font.c, not ppmdcfont font.ppmdfont. The latter does not match the documented interface.
  • Do not confuse a report with generated C. ppmddumpfont writes its human-readable report to standard error. ppmdcfont writes C to standard output. Keep the streams separate.
  • A zero status does not resolve a symbol conflict. Search for ppmd_standardfont and rename it before linking a second font.
  • Keep the input. The converter does not modify the Ppmdfont stream, so retain the original while reviewing and compiling the C output.
  • Do not run as root. Reading a font and writing a project file should be unprivileged. Elevated access would not repair a malformed font or missing development header.

Done means

  • The installed Netpbm version and ppmdcfont path are known.
  • The input is a readable Ppmdfont stream and passes a diagnostic check when needed.
  • The command completed with status 0 and produced non-empty C source.
  • The generated ppmd_standardfont identifier was renamed consistently before linking.
  • The matching Netpbm development header and library are available to the intended build.
  • No system library, service or persistent configuration was changed.