PDF jumper diagrams with a simple Perl script
2 Jan 2020
I recently needed to generate documentation in TeX for a board which was configured via jumpers placed on header pins. I wrote the Perl script shown here to quickly generate high-quality PDF images of different jumper settings for inclusion in the documentation. The script is approximately 200 lines, has no dependencies aside from the Perl interpreter itself, and can easily be modified to draw other kinds of diagrams.
To use it, specify a template consisting of a string of one of more of the following characters:
O: a jumper post.
o: a greyed-out jumper post.
I: a jumper looped over the following two jumper posts.
For example, invoking as:
./jd.pl OIOOoo > example.pdf
Gives the following output:
The script and the above example output can be downloaded here:
The script itself is broken into three packages. The first package,
called PDF, handles low-level PDF operations. It contains
output functions which keep track of the current position, and
facilities for allocating PDF objects and emitting a final xref
table.
The second package is called PDFDrawing and is
higher-level. It provides a function for adding graphics commands to a
single content-stream. Finally, PDFDrawing::finish is
called, which uses the PDF package to build a PDF file
containing a single page, cropped to the specified size and containing
the given content. The PDFDrawing package also contains a
helper function to approximate circles using Bezier splines.
Finally, the main package parses the template and calls
functions in PDFDrawing to emit primitives. The package is
shown here in its entirety:
my $tmpl = shift // die "Specify a template";
my $size = 10;
my $n = 0;
for my $c (split //, $tmpl) {
if (($c eq 'o') or ($c eq 'O')) {
PDFDrawing::put "q 0.75 G" if $c eq 'o';
PDFDrawing::bz_circle $n * $size + $size / 2, $size / 2, $size / 4;
PDFDrawing::put "S";
PDFDrawing::put "Q" if $c eq 'o';
$n++;
} elsif ($c eq 'I') {
my $x1 = $n * $size + $size / 8;
my $y1 = $size / 8;
my $y2 = $size * 7 / 8;
my $x2 = ($n + 2) * $size - $size / 8;
PDFDrawing::put "$x1 $y1 m";
PDFDrawing::put "$x2 $y1 l";
PDFDrawing::put "$x2 $y2 l";
PDFDrawing::put "$x1 $y2 l";
PDFDrawing::put "h S";
}
}
PDFDrawing::finish $size * $n, $size;
By replacing the main package, this script can be easily
repurposed. For a reference on PDF graphics commands, see section 8
(“Graphics”) of the PDF
specification.