Home / Blog Menu ↓

Blog: #pagedjs

A short followup to what I wrote last year about Press, my abandoned typesetting engine project: I’m now fully convinced that the web platform is where I want to do typesetting. It’s open, programmatic, and capable. Source files are plain text, easy to version control, and fairly future-proof. And even though it’s not WYSIWYG — at least not the way I’m using it — it’s much more comfortable for me as a working environment.

For non-book work (charts, some kinds of documents), I’ve found that browsers already support everything I need (like @page). That’s how I’ve done all my recent genealogy design work, and it’s how I’ll do any language charts I make going forward. And for things like books where browser support isn’t quite there yet, Paged.js works well (and will presumably be phased out once browser support gets better).

Not to mention how nice it is for both print and digital workflows (EPUB, web) to all use the same technologies. I also love that the web is cross-platform. Something I ran into when I was making charts with PlotDevice (which is Mac-only) was that people on Windows couldn’t modify the charts even when I gave them the source. That’s not a problem with the web.

I’ve even started using the web platform for less webby things like making wallpaper for my phone:

Dark cloudy background with the text of Matthew 11:28 at the center.

Here’s the HTML (the 375×812px size is the CSS resolution of my iPhone 12 Mini — RIP — and also keep in mind that this was for a one-off never to see the light of day, so I took the liberty of cutting a few corners):

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div class="background">
    <svg id="darknoise" viewBox="0 0 375 812" xmlns="http://www.w3.org/2000/svg">
      <filter id="noiseFilter">
        <feTurbulence baseFrequency="0.5" numOctaves="8" />
      </filter>
      <rect width="100%" height="100%" filter="url(#noiseFilter)" />
    </svg>

    <svg id="lightnoise" viewBox="0 0 375 812" xmlns="http://www.w3.org/2000/svg">
      <filter id="noiseFilter2">
        <feTurbulence seed="485" baseFrequency="0.005" numOctaves="12" />
      </filter>
      <rect width="100%" height="100%" filter="url(#noiseFilter2)" />
    </svg>
  </div>

  <div class="quote">Come unto me, all ye that labour and are heavy laden, and I will give you rest.</div>

  <div class="reference">Matthew 11:28</div>
</body>
</html>

The CSS (with the font purchased from FontShop):

* {
  box-sizing: border-box;
  font-family: Clifford Pro;
}

html {
  height: 100%;
}

body {
  color: #777;
  font-size: 1.6rem;
  margin: 0;
  text-align: center;
}

.background {
  background: radial-gradient(circle at 50% 90%, #222, #111);
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: -1;
}

.background svg#darknoise {
  bottom: 0;
  filter: saturate(0);
  left: 0;
  mix-blend-mode: multiply;
  opacity: 0.9;
  position: absolute;
  right: 0;
  top: 0;
}

.background svg#lightnoise {
  bottom: 0;
  filter: saturate(0);
  left: 0;
  mix-blend-mode: soft-light;
  opacity: 0.4;
  position: absolute;
  right: 0;
  top: 0;
}

.quote {
  line-height: 1.4;
  margin: 25rem 1.5rem 0;
}

.reference {
  color: hsl(0 40% 32%);
  font-size: 1.3rem;
  font-style: italic;
  margin-top: 1rem;
}

I then used headless Chrome to export the PNG (Firefox would probably have worked as well, though I haven’t yet tested it for this):

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --disable-gpu --screenshot --window-size=375x812 index.html

It’s not the world’s most amazing wallpaper or anything, but I’m still pleased that I was able to make something I’m reasonably happy with using technologies I love. (I could have also used WebGL shaders or Canvas. Lots of options!)

Here’s to the open web.


Reply via email or office hours

Historia Calamitatum

Book cover for Historia Calamitatum by Peter Abelard, white text over small circles fading vertically from white at top through red in the middle down to black at the bottom

After what feels like a long absence from bookmaking, I’ve gotten back into it and have a new release: Historia Calamitatum, available as a PDF.

The book is a medieval autobiography by Peter Abélard, a Catholic philosopher who lived in the eleventh and twelfth centuries in France.

Some notes on the making, for those who like that sort of thing:

  • I used paged.js for the typesetting, so I was editing HTML and CSS files instead of wrangling InDesign or Affinity Publisher or LaTeX. It’s a different workflow, to be sure (lots of reloading in Chrome and then finding my spot again), but overall I love having the source files be plain text.
  • The line-breaking algorithm isn’t as nice as InDesign’s. Had to finagle the word-spacing and letter-spacing properties a bit to fix some more egregious spots. (At the same time, I wasn’t fixated on making the spacing perfect. Nor did I fix the hyphenation stacks, because they don’t bother me. I’m clearly becoming a bit more relaxed about typesetting rules as I get older.)
  • For the typeface I went with IM Fell DW Pica, which is no doubt anachronistic but I like the feeling it gives the book.
  • I proofed the PDFs in the Documents app on my iPad. Much nicer than printing the whole thing out (which I used to do, years ago).
  • I made the cover using Cirque with textures applied in Affinity Photo.

Reply via email or office hours

Update on Press (the PDF compiler). I haven’t worked on it at all lately, but I wanted to document its current state for history’s sake, and as part of working in public. (I’ve also been sitting on this post for over a year.)

Back in 2017 I did end up re-architecting Press to use Low Ink as an intermediate page description language. In the process, Low Ink changed from a JSON-based idea to this:

:page 11x8.5in
:bleedbox x=0.125in y=0.125in w=5.75in h=8.75in
:fontmap family=helv weight=regular style=normal standard=Helvetica
:yinvert
:push
:translate x=72 y=72

# ascender
:push
:translate x=0 y=1040
:strokecolor hex=#999
:linewidth 0.25pt
:line x1=0 y1=0 x2=1080 y2=0
:stroke
:push
:fillcolor hex=#999
:font family=helv size=14pt
:text x=1085 y=-3 text="ascender"
:pop
:pop

# filled glyph
:push
:translate x=1320 y=240
:fillcolor hex=#000
:moveto x=0 y=0
:pathto x=400 y=300 cx1=120 cy1=300 cx2=140 cy2=300
:pathto x=320 y=200 cx1=540 cy1=300 cx2=320 cy2=180
:lineto x=350 y=350
:lineto x=450 y=250
:lineto x=150 y=0
:moveto x=200 y=200
:lineto x=200 y=250
:lineto x=250 y=250
:lineto x=250 y=200
:lineto x=200 y=200
:fill
:pop

It was intended to be a fairly low-level wrapper on the PDF format, with the idea being that other libraries/apps would provide more ergonomic abstractions on top of it.

I initially used Python because Press started out as a library, but with the pivot to a compiler model, I think Go or Rust would probably end up being a better choice (Rust would make integrating HarfBuzz a bit easier, at any rate).

Potential improvements

To my 2021 eyes, the language design isn’t particularly elegant. I like that the parameters are named (clarity), but for most of the commands there aren’t actually that many parameters, because many of the settings that would normally be parameters are separate commands. For parameters that are clearly unambiguous, the names hamper readability. For example, I think something like this might be better:

:line 0,0 to 1080,0
:fillcolor #345

I’ve also thought that push and pop could potentially be clearer as curly braces, and that the initial colons aren’t really necessary:

{
  translate 0,1040
  strokecolor #999
  linewidth 0.25pt
  line 0,0 to 1080,0
  stroke

  {
    fillcolor #999
    font 14pt helv
    text 1085,-3 "ascender"
  }
}

The future

My initial reason for building Press was to have an easy, programmable cross-platform way to create language chart PDFs (so I could move away from PlotDevice/DrawBot), and what I’ve realized (acknowledging that I haven’t really been making language charts in recent years) is that there are some other, better options now.

One that seems decent is SVG, converted to PDF by way of Inkscape. Initial tests here seem like it would probably work fine.

Another promising option that I admittedly haven’t looked into very much yet is Paged.js. HTML and CSS are already great for declarative typesetting, and the more I’ve thought about programmatic typesetting, the more this model seems to be the future I’d want to work with (and not just because of parity with web, though that makes it much more compelling).

tl;dr I don’t see myself continuing on with Press, so we may as well call a mortem on it.


Reply via email or office hours