Back to Feed
article 3m read

PDF exporter photographing slides whether or not the fonts showed up

A deck-to-PDF exporter I wrote flattens every page into images by default, and on a reread I noticed its font and image waits always pass, so a fallback font would get frozen into pixels with nothing left to catch it.

Article DepthPractice

Flow

Checks that belong before the photo step

  1. 1Waits that report

    Each image or font comes back loaded, broken or slow, and only loaded passes.

  2. 2Fonts by name

    Each declared font is checked on its own, not through one page-wide signal.

  3. 3Print the text PDF

    Real text, links and named fonts still exist here.

  4. 4Look inside it

    List its fonts and search it for the title before anything is rasterized.

  5. 5Flatten and keep both

    Ship the image PDF for viewing and the text PDF for search and screen readers.

Pitch deck to PDF was what I needed. The deck is a web page, so I wrote a script that opens it in a hidden Chrome, switches to print styles, and saves a PDF. Then, by default, the script throws that PDF away.

That was my call. This is from reading my own script again, not from a failed export.

A hidden Chrome and a photo step

It opens the page, waits a little for the network, and flips lazy images so they load right away. Then it waits for fonts and images, each with a short timer, and prints a PDF with real text in it.

Next comes the flatten step. Each page is drawn into a big image, and the images are glued into a new PDF, while the first PDF gets deleted along with the temp folder. The last thing the script prints is the mode and the file size.

Pictures instead of text

A flattened PDF looks the same in every viewer. That's the appeal. But you can't search it, copy from it, or click its links, and screen readers get nothing. My two files came out several megabytes each.

The waits never complain

The network wait and the font and image waits give up when their timers run out, and giving up counts as success, the same as a broken image does. A slow font means Chrome prints a backup font, so lines wrap in new places. The script can't tell good from bad, so it keeps going.

In a normal PDF you could still catch that, because a font list would show the backup font and a search would still find the title. Once it's flattened, the mistake is just pixels, and nothing points at it.

Rare, but I'd never know

Probably rare. My fonts and photos are baked into the one HTML file, so there's nothing to fetch. But if it ever happens, I'd have no way to know. The same commit made the background warmer and the shadows darker. The pale ones probably looked weak in the export, but that's a guess.

Four fixes, in order

If you build something like this, the order is what matters:

  1. Make each wait report "loaded", "broken" or "slow", and stop on anything but "loaded".
  2. Check each font by name instead of trusting one page-wide signal.
  3. Before flattening, list the fonts in the PDF and search it for the title.
  4. Keep the text PDF next to the flattened one.

The first fix is small.

Now an image that is broken or too slow throws an error naming it, and only a loaded image passes.

The last one is the cheapest. The text PDF already exists for a few seconds on every run, and my script deletes it.

Keep reading

Pick up a connected idea or branch into a nearby one.

4 paths forward