Home / Alt manpages / ppmdcfont(1)

  • ppmdcfont(1)
  • User command
  • linux

Turn a Ppmdfont File into a Netpbm C Font with ppmdcfont

ppmdcfont converts a Netpbm Ppmdfont file into C source, but the generated font shares its name with the one built into libnetpbm.

This guide gets you a checked C file and a safe renamed identifier before you hand it to a build. Allow about fifteen minutes.

You need a shell, the ppmdcfont and ppmdmkfont commands, and a writable working directory. No step needs sudo. The examples use Netpbm package version 2:11.05.02-1.1build1, as installed on this machine. 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 part most people miss. The generated C source names the font object ppmd_standardfont, which is also the name of the font built into libnetpbm. The manual says as much: there is no option to choose this name, so leaving it unchanged can cause a duplicate symbol at link time and makes it unclear which font a program is actually 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 run 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"

Warning

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

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

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