kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

CSS組版 Vivliostyle ユーザーと開発者の集い 2022秋 に参加した (1)

転職して書籍制作に直接たずさわることはなくなったものの、自動組版技術は趣味として追い続けたいテーマ。HTML+CSSと変換エンジンを使って紙面PDFを生成する「CSS組版」についても、InDesignTeXとこれまで利用してきた制作手法にプラスできないかという期待が大きかった。

日本語対応のCSS組版として、VersaType Converter・Antenna House Formatter・Vivliostyle.jsと業務でチャレンジしてきたものの、課題がいろいろあって残念ながら在籍時には商業刊行品質につなげるようなモノにはできなかった(Antenna House Formatterはそれ自体はかなり要求に応えられそうではあったのだが、合いそうなものがInDesign指定だったりして投入できず)。

VivliostyleはOSSコミュニティで開発されているプロジェクトで、WebブラウザをエンジンとしてHTML(またはVFM; Vivliostyle Flavored Markdown)とCSSからコンテンツをページドなものに整形し、画面表示またはPDFの出力を行うという仕組みを開発・提供している。 vivliostyle.org

  • CSSには紙の組版にインスピレーションされた「仕様」はさまざまあるのだが、それがモダンWebブラウザで実装されているか?というとまた別問題。そこで、VivliostyleではプリプロセスやJavaScriptを使って代替的に仕様の表現を実現したり、固有のCSSを提供したりといったハックが行われている
  • HTMLとCSSを評価・加工するJavaScriptライブラリのVivliostyle.js、CUI上でデータの入力・変換・出力を担うVivliostyle CLIWebブラウザ上でページドな形で表示するVivliostyle Viewer、Markdown処理のVFMモジュールが主な要素となっている

昨日、オンラインの「CSS組版 Vivliostyle ユーザーと開発者の集い 2022秋」が開催され、特に興味があるトピックが多かったので、聴講参加した。 vivliostyle.connpass.com

Vivliostyle.jsの先行実装から考えるCSS text-spacingプロパティ

speakerdeck.com

  • FONT WORKSの鈴木丈さん。Webページでのタイプセット理論を扱った『ウェブタイポグラフィ』(ボーンデジタル)の監訳もされている
  • 扱ったトピックとしてはCSS Text Module Level 4(Level 3にあったらしいが先送りされた)のtext-spacingプロパティ。https://drafts.csswg.org/css-text-4/#text-spacing
  • 文字クラス間の空きスペースを指定するもので、日本語組版だと具体的には和欧混植の組版において、和欧の間とか、和・数字とか、連続約物とかの空きを設定できる
  • 和欧間スペースは、紙組版では1/4emが基本、本によっては1/3em〜1/8em程度(※kmutoの業務経験でも1/4、1/6、1/8あたりだった)。欧文組版だと単語間は1/4em、組み方や文字サイズなどにより1/3em〜1/5em。ということで、和欧どちらもだいたい1/4emが基本と言えそう
    • text-spacingの値の例として、ideograph-alpha(CJK/非CJKな文字のアキ)、ideograph-numeric(CJK/非CJKな数字のアキ)というのがある
    • Vivliostyle.jsでのHTML変換結果を外形的に見たところでは、アキを作るのに content: " " のU+20のスペースを作成し、Timesフォント指定している。TimesフォントはU+20スペースで1/4emが保証されるので、あとはこれをfont-sizeでスケールし、希望のemに合わせる(66.6%で1/6em)
    • marginではなくcontentにすることで、justifyな段落組で行末尾になったときは吸収されてアキはできないというテクニック
      • 開発からの追加として、UnicodeのU+20以外のスペース(EMやENなど)では行末尾になっても吸収されない(!)
    • macOS/iOSでは、iOS 14以降で、アプリケーションによっては、和欧間に1/8em程度のアキが入る模様
    • 今後モダンWebブラウザがtext-spacingを実装した場合に、デフォルトのアキはどの程度がよいのかの鈴木さんの私見としては、もともとWebブラウザで和欧アキはなかったこと、Webテキストは文中に欧文が登場する頻度高いこと、横組みであること、から、これまで紙組版で標準としていた1/4emはアキすぎで不自然と思われる。1/6emか1/8emの控えめなほうがよいのでは、とのこと
  • カッコ、句点、中点などの連続約物。」」「 など)は、紙の組版では組み合わせに応じてアキ調整をしている
    • OpenType Featureのchwsやvchwを使うのが望ましい。font-feature-settings: "chws" 1; でOTF側がこのFeatureを持っていればそれが使われる
      • しかしOSバンドルフォントでは対応してなさげ
      • 約物専用フォントを使う、chws_toolで手元のフォントにchws, vchwを埋め込むという方法も一応ある
    • OTFにFeatureがない場合、CSSで対処。space-adjacent(約物間を詰めず全角取り)、trim-adjacent(特定の組み合わせで約物間を詰め)というのがある。ただし実装ブラウザはないので、Vivliostyle.jsが該当並び順のときに margin-inline-start: -0.5em になるようなHTML+CSSにしている
      • 開発からの追加として、chws/vchw実装しているOTFの場合は不要なので、詰めすぎないよう判定実装しているとのこと
      • コンデンスド書体でも処理が働いて詰めすぎないようになっている。全角かどうかでの判断
  • 行頭・行末の約物(行頭の始め括弧類、行末の終わり括弧類・句読点・中点など)はchws/vchwでも対処できない。これらは文中用を目的としているので、行頭・行末はコントロール不能。Vivliostyle.jsでは処理を実装しており、必要なら margin-inline-start: -0.5em を入れるようになっている
  • 開発からの反応。あくまでもこれらはVivliostyle.jsのHTMLプリプロセスで行われ、人が見たり書いたりする必要はない
    • Timesは苦しまぎれで、スペースだけのフォントを持つか?というアイデアもある
    • アキを visibility: hidden にしているのは、ビューアからコピペしたときにアキのスペースが含まれないようにするため

Vivliostyle.jsにおけるWeb標準CSSサポートの大改善

vivliostyle.org

  • Vivliostyle代表の村上さん
  • レイアウトの多くはWebブラウザCSS機能を使い、未実装のCSS仕様や固有の組版機能を追加実装するポリシーで開発
  • …が建前なのだが、もともとAdaptive LayoutベースでCSS解析を自前で行っているところがあり、最新のCSS機能が使えない箇所があった
  • 設計を見直し、v2.17からWebブラウザで使えるCSSプロパティ・値は基本的にすべて利用可
    • Vivliostyle.jsで定義していなくてもWebブラウザでサポートされているものであれば有効になるはず。なっていなかったらVivliostyle.jsのバグ
  • ということで、CSS Grid LayoutがVivliostyle.jsモデルでも利用できる!
  • CSS変数も利用できるようになり、パラメータをまとめやすくなった
:root {
  --page-width: 148mm;
  --page-height: 210mm;
}

@page {
  size: var(--page-width) var(--page-height)
 ...
}
  • v2.19で擬似セレクタを強化。:has():is():not():where()。特に :has() は強力。子要素や後に続く要素に基づいて選択できる
    • section:has(section) sectionを持つsection
    • h1:has(+ p) 段落pが後に続く見出しh1のスタイル
    • これは滅茶苦茶便利だな。EPUBビューアに実装してほしかった…
  • 実装予定のもの。::marker 箇条書きのマークを指定(これもEPUBでほしかったな…)、@counter-style 箇条書きのカウンタを指定、@layer カスケーディングレイヤー、@container コンテナクエリ。いずれもWebブラウザには実装がないので独自実装が必要
  • これから標準になるので普通に使えるようになりそうなもの
    • CSS Nesting(SCSS的な書き方ができる。最近話題になってたね)
    • 単位lhとrlh(lhは行高を基準にした長さ単位、rlhはルート要素のline-height基準)。 margin-block: 1lh(1行ぶんアキ)、block-size: 3rlh(3行取り)←block-sizeとな…? (←widthまたはheightのロジカルプロパティとのこと)
  • これまで実装してきたもの
    • CSS Text Level4: hanging-punctuation, text-spacing
    • CSS Paged Media Level3: ページメディア用の基本仕様
    • CSS Generated Content for Paged Media
    • CSS Fragmentation Level3
    • CSS Page Floats: みんな大好きな、ページに天つき地つきで配置できるやつ
  • まだできてないもの
    • ページメディア仕様で記載されているが… margin-break マージンがページ先頭かどうかで保持か破棄かを指定できる(keepはマージン保持、discardはマージンを破棄)
    • Running Elements: 柱。単純な文字列だけならNamed Stringsでできるが、より複雑なのには必要(実際商業書籍だと柱もデザイナーの腕の見せどころなので、これはぜひ強化してほしいね)
    • @footnote: 脚注スタイル
    • leader(): 目次や索引のドットリーダとかを表現するやつ
  • 組版課題
    • Mac以外だとハイフネーションが無効になってしまう(Windows/Linux/DockerでのCLI。エンジンのChromiumの問題)
    • https://print-css.rocks/lessons (Beta版)で、CSS組版の比較的最新の機能比較ができる(Linuxで検証されている)
    • OSSのものはVivliostyle.jsとPagedJS(エンジンはWebブラウザ)、Weasy-print(エンジンは自前)。Vivliostyle.jsの欠点とされているのはハイフネーション不備、柱の機能不足、CMYK非対応、PDF機能の不足
    • Vivliostyle.jsだとJavaScriptをその上で利用できるため、JavaScriptで処理される図版も出力できる
    • MathMLの対応がChromeで強化されている
      • しかしMathMLは人間が書くものではないんだよな。TeXかAsciiMathからのまともに動く変換ツールが内包されるならなんとか?(なお、MathJaxのMathMLも、RubyのMathMLライブラリはだいぶ不足だった)

後半戦メモは後日。