CSS組版の光と闇

このエントリーは、技術同人誌 その2 Advent Calendar 2018 の10日目エントリーです。

adventar.org

2018/12/4に開催された技術同人誌再販Night★#3 #技術書典 の技術書が集合&LT でLTした内容です。当日のスライドはこちらです。

CSS組版とは

書籍を出版する上でのレイアウトを、htmlとCSSを使って実現するものです。

詳しくはこちらを。

pentapod.booth.pm

github.com

speakerdeck.com

Vivliostyle Foundationオープンソース(AGPL)で提供するVivliostyleCSS組版の分野をリードしています。著者もこのライブラリーを使用してCSS組版を行っています。

CSS組版のフロー

自分は以前からMarkdownで書いた原稿をPandocでPDFに変換するフローで執筆を行っていたので、 Markdownからhtmlへの変換もPandocで行っています。

まず、原稿はMarkdownで記述します。

次に、Pandocが変換するhtmlにあわせてCSSを記述します。(抜粋)

@page {
    size: B5;
    @bottom-center {
        content: counter(page);
    }
}
div#TOC {
    break-before:  page;
}
h1 {
    break-before: page;
}
/* 本文 */
h1,h2,h3 {
    font-family: "Source Han Code JP N";
}
h1 {
    font-size: 18pt;
}
h2 {
    font-size: 16pt;
}
p {
    font-family: "Source Han Serif";
    font-size: 12px;
}
li {
    font-family: "Source Han Serif";
    font-size: 12px;
}

PandocでMarkdownをhtmlに変換します、

pandoc  \
  -s -f markdown+raw_tex+citations+yaml_metadata_block+fenced_code_blocks \
  -c book.css --filter pandoc-crossref \
  -M "crossrefYaml=${PWD}/../crossref_config.yaml" \
  --filter pandoc-citeproc -o ../target/${OUTPUT}.html \
  --toc --toc-depth=2 --reference-location=block \
  -B cover.html -A imprint.html \
  -S tmp.md  --verbose

f:id:setoazusa:20181210141252p:plain

npm run serveコマンドでWebサーバーを立ち上げた上で生成したhtmlとCSSをVivliostyleのViewrにかまして、レイアウトします。下記はpackage.jsonの抜粋です。

{
(略)
  "scripts": {
    "serve": "live-server --port=8989 --browser=chrome --open=vivliostyle-js-2018.8.100/viewer/vivliostyle-viewer.html#x=../../target/sweetmusic-vol6.html --cors --verbose"
  },
  "dependencies": {
    "http-server": "^0.11.1"
  },
  "devDependencies": {
    "live-server": "^1.2.0",
    "vivliostyle": "^2017.6.0"
  }
}

f:id:setoazusa:20181210141402p:plain

最後に、Chrome印刷機能を使って、PDFを出力します。

f:id:setoazusa:20181210141429p:plain

CSS組版の光

CSS組版には以下のようなメリットがあります。

以下、エンジニア観点でCSS組版でうれしいことについて述べます。

ソースコード中の全角半角をそろえる

LaTexのレイアウトにはいわゆる「全角・半角」という考え方がないため、 コード例などで、コメント等でいわゆる全角文字を半角文字2文字分に揃えたレイアウトが非常に困難ですが、CSS組版だとフォント指定のみで可能です。

f:id:setoazusa:20181210141551p:plain

均等割り付け

似たような理由で均等割り付けもLaTexだとガリガリ書く必要がありますが、 CSS組版だと比較的楽です。

f:id:setoazusa:20181210141739p:plain

URL

紙のレイアウトの際にURLを識別しやすくするのもCSSだと楽ですね。

f:id:setoazusa:20181210141807p:plain

光があれば闇もあります。以下ざっと。

目次のレンダリングに時間がかかる

目次のページ番号の表記は、CSS Paged Mediatarget-counterを使って行うのですが、32ページ程度の書籍でも目次のレンダリングが終わるまで結構かかります。

環境依存のレイアウト乱れ

CSS組版は、ブラウザーレンダリングした結果をPDFとして出力するものです。 前述のCSS Paged Mediaは、html/CSSによるレイアウトを拡張してページレイアウトをCSSで実現することを目指していますが、そもそもhtmlというものは、文書構造をマークアップするものであって、物理レイアウトを規定するものではないです。

結果として、現状のCSS組版では、画面の解像度やdpiなど、ハードウェアの要因によって、出力されるレイアウトに差異が生じます。

また、レイアウトする際の微妙な差異の累積によって、出力されるページ数もかわってきます。

下記は比較的解像度が低いモニターで出力した際のレイアウトずれの例です。

f:id:setoazusa:20181210141947p:plain

このようなレイアウトずれは、多様なデバイスの存在を前提としたhtmlとWebブラウザーの世界では起きて当然なのですが、出版物の組版の環境としては見逃すことができない問題です。

このため、現状のCSS組版では、入稿するPDFをビルドするマシン環境を作ったら、その環境は死守する必要があります。

見出しの配置

以下のような、ページの一番下に見出しが来てしまう現象は、LaTexだといい感じにレイアウトを調整してくれるのですが、CSS組版でこれを回避したい場合は、実装する側で調整を行う必要があります。

f:id:setoazusa:20181210142019p:plain

フォント埋め込み

上記のような難関を越えていったとして、最後に残るのがフォント埋め込みの問題です。

CSS組版で出力したPDFをAdobe Acrobatで見ると、以下のようにフォントの種類が「Type3」と表示されています。

f:id:setoazusa:20181210142043p:plain

これはChromeでhtmlをPDF出力する際の仕様で、Type3と表示されていますが実際の端末での表示上はまず問題になりません*1

ですが、印刷所で入稿する際はAcrobatの文章のプロパティでフォントが埋め込まれているかを判断しているので、この状態のPDFを受け付けてくれない場合があります。

CSS組版のフォント埋め込みについては、@vvakameさんの「Re:VIEW+CSS組版やっていき」に、次のような記述があります。

印刷所に入稿するデータはPDF形式であり、そこにはフォントデータを埋め込まなければなりません。しかし、現時点ではChrome印刷機能でPDFを生成する時に、フォントデータを埋め込む方法が分かっていません。

pentapodさんの本によると、Adobe Acrobatに課金してフォントデータを後乗せで埋め込むという手法が選択肢としてあるそうです。羊にこの手法を試してもらいましたが、上手くいきませんでした。

よって、今回の印刷ではフォントデータが欠損していても無視して無理やり印刷します。 現状の到達点だから…!仕方ないから…!

著者もこの問題に多いにはまり、その結果としてわかったことを以下に記します。

(Windowsの)Acrobat Pro*2には、システムにインストールされているフォントでないとフォントの埋め込み・アウトライン化ができないという仕様があります。

なので、Webフォントの埋め込みはAcrobatではできない、ということになります。

では、ローカルで動かすフォントをCSSで直接指定すればいいのかというと、WindowsってCSSで指定するフォント名と、アプリケーションが認識するフォント名が一致しないフォントがあるっていう落とし罠があるんですね。下記のQiitaエントリーを見てこの現象に思い至りました。

qiita.com

上の画像はSource Han Code JP(源ノ角ゴシック)をCSSで指定するときの記述、下はAcrobatでSource Han Code JPを指定するときの表示です。表示名違うでしょ?

f:id:setoazusa:20181210142404p:plain

で、入稿前日に悪戦苦闘したのですが、これはどうやってもAcrobatでは埋め込みできない、ということになりました。回避先としては、Macのプレビュー.appだと強制的にアウトライン化してくれるので、これだと入稿OKなPDFになります。

f:id:setoazusa:20181210142537p:plain

著者の環境はWindowsなので、入稿当日にキンコーズMacを借りて、入稿用のPDFを作成しました。

以上のような悪戦苦闘を経て、できあがったものがこちらになります。

fieldnotes.booth.pm

最後に

終わった後で振り返ってみると楽しくも思えますが、入稿前日の夜*3にこういう問題にはまるのは正直地獄です。組版環境を入稿直前にいじるのはほどほどにしましょう。

*1:らしい

*2:以下Acrobat

*3:正確には、一度入稿でNGになって一日延ばしてもらった日の夜