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.