Epicycles: poster-making


So, as I prepare to inflict PDF::Cairo on the world, I’ve been sensibilizing the documentation and adding example code. My latest effort was dusting off my 15-year-old Traveller sector map generator and cleaning up the hex-grid calculations to use my Box library and the regular-polygon method I recently added. Works great.

Then I had an idea for Yet Another Epicycle: tiling a large image across multiple pages. I did this by hand in the original sec2pdf script, splitting sector maps across 4 or 16 pages, but it would be cool to render the entire sector once and then simply ‘cut out’ the pieces I need for each page. It would also get rid of a lot of special-case code for handling things that are partially outside of the current page.

I tried it out by hand, and it worked great. I drew a big box on a recording surface that was 17x22, and replayed it four times onto 8.5x11 pages with different offsets. Not lightning fast, since you end up rendering the entire drawing N+1 times, but it worked.

For that very simple example.

Unfortunately, it looks like there’s internal state that doesn’t get reset completely, so that when I integrated it into the module and told it to make a really big hex grid, only the first replay was 100% successful. The rest were incomplete (one row/column of hexes, with no text labels). It didn’t matter what order I replayed them in.

Cairo apparently has scripting surfaces and proxy surfaces in recent versions, but no one has updated the Perl module to expose those, and I’m not sure they’d help (scripting surfaces are basically a debugging tool that writes to disk and gets replayed with a standalone CLI tool).

I still want to do it, so I may simply add a simple-minded recording of my API calls and do a high-level replay. Even more overhead than using a recording surface (especially for things like loading fonts and images), but then I’ll know it can be replayed more than once.

Meanwhile, the recording()/replay() methods work at least once, so I’m leaving them in for now.

Update!

Wow, that was an easy fix. After walking away for a few hours, I went back and added a single cairo_surface_flush() right before each set_source_surface() call. Renders perfectly, as many times as I want. See?; I just need to tweak the clipping regions a bit, to capture the overlap between pages.

Performance is actually pretty good, now that I have something to measure: it took only 28% longer to generate the drawing and replay it four times on different pages. Output size was 146% larger than generating the same drawing on a single large sheet, but that’s a small price to pay for the convenience.

If I were really going to revive sec2pdf (and I might, but not this weekend!), what I’d do to get the most efficient output is use a recording to draw all of the sector-wide elements (regional borders, X-boat routes, etc) and replay them onto the individual pages, after drawing each page’s grid but before adding text and system data. That would significantly reduce the amount of wasted drawing outside each page’s boundaries, and only repeat the elements that might appear on multiple pages.


Comments via Isso

Markdown formatting and simple HTML accepted.

Sometimes you have to double-click to enter text in the form (interaction between Isso and Bootstrap?). Tab is more reliable.