月別アーカイブ: 2023年1月

XSL-FO 試行錯誤 SVG 2.0 inline-sizeのTips

2023年01月19日に『Antenna House Formatter V7.3』がリリースされました!
関連して、2023年01月31日(火)16:00-17:00 にZoomウェビナーとして『Antenna House Formatter V7.3 リリース!  新機能と利用シーン紹介』を開催します。


https://us06web.zoom.us/webinar/register/4716717860524/WN_ElB-ZrzFQzShzKGqWZMHqg

新機能紹介ということで、XSL-FOやCSSページ組版の基礎知識があることを前提としています。しかし、特に知識の無い方でも「自動組版でこんな細かいレイアウト調整が効くのか」と楽しめることを目指していますので、お時間が合いましたら是非参加登録いただければ幸いです。

ウェビナースライドはFormatter V7.3で組版しています。スライドはCSSで組んでいるのですが、話題がSVGについてなので、暫くぶりとなる「XSL-FO 試行錯誤」シリーズを題に含めました。
(前回のXSL-FO試行錯誤のカレンダー作成の続きについてはまた時間があるときにさせていただければ……)

さて、本記事ではウェビナーで割愛する部分について、先行して補足します。
ということで、見た目が地味なのであまり深く掘り下げない予定のinline-sizeによるテキストの折り返しについてです。

発表スライドの見出し部分にはSVG 2.0を使っています。

テキストを配置するとき、SVG 1.xでは折り返しを扱えませんでした。
よって、複数行のテキストを配置するときは次の手順(これ以外にもなくはないですが)です。

右揃えで3行でテキストを描画するとします。座標は適当です。

  1. 改行位置でテキストを分割し、別のtspanに分ける
  2. それぞれのtspanにx,yの座標を指定する。2行目であれば1行目から1文字分以上離れた位置にyを設定する
<!-- SVG 1.x -->
<text x="0" y="0">
<tspan text-anchor="end" x="250" y="0">Formatter V7.3</tspan>
<tpsan text-anchor="end"  x="250" y="10">リリース!</tspan>
<tspan text-anchor="end"  x="250" y="20">新機能と利用シーン</tspan>
<text>

text-anchor=”end”によって、xの位置がテキストの終端になっています。

x,yはSVG内の座標系なので、font-size:18ptのように絶対単位で指定されていると対応する高さを調整するのはちょっと手間ですね。
他にも拡大縮小の際などにこれを忘れずに変更しなければなりません。

メリット、といえるかは分かりませんが、あらかじめ分割しているので、意図しない行分割が発生するということはないでしょう。

SVG 2.0のテキスト折り返し機能を使えば、折り返しを自動化可能です。Formatter V7.3ではinline-sizeによる折り返しをサポートしています。
Scalable Vector Graphics (SVG) 2 11.4.1. The ‘inline-size’ property



<text x="0" y="0" inline-size="1000">Formatter V7.3リリース! 新機能と利用シーン</text>

inline-sizeにはテキストの行長を指定します。

  • 両端揃えができない
  • 日本語は行頭・行末禁則以外では基本的に改行可能と判断される

また、見出しのような箇所で使う場合、次のことを意識しておくとよいでしょう。

今まで手動でやっていた行分割を自動処理にする都合上、特に、本文でない箇所での行分割規則は意識しておかなければなりません。
言語処理が日本語になっていれば(xml:lang=”ja”が適用されるような箇所であれば)
意図してそうしない限り「ー」は先頭に来ませんが、「リ」はそうではないので、

Formatter V7.3 リ
リース!

となるかもしれません。

特定単語の行分割を防ぐため、その箇所のマークアップをtspanにして、分割禁止のプロパティを付けることにします。
「tspanを使うなら結局SVG 1.xとあまり変わらない?」と思われるかもしれませんが、座標の明示がなくなるので処理はかなり単純化します。
「この単語で行分割されるのは困るが、ここ以外であれば別に構わない」というケースが多いとみているのですが、どうでしょうか。

<!-- <heading>Formatter V7.3<keep>リリース!</keep><keep>新機能</keep>と<keep>利用シーン</keep></heading> -->
...
<xsl:template match="heading">
  <svg:svg viewBox="0 0 1920 1080" >
  ...
    <svg:style>
      svg|tspan.keep {
        word-break: keep-all;
      }
    </svg:style>

    <svg:text x="1800" y="100" text-anchor="end"><xsl:apply-templates mode="#current"/></svg:text>
  </svg:svg>
</xsl:template>
...

<xsl:template match="keep">
  <svg:tspan class="keep"><xsl:apply-templates mode="#current"/></svg:tspan>
</xsl:template>

上記は実際に使用したコードではないため、参考程度にお考えください。
inline-sizeが対応するalign調整はtext-anchorによるものになるため、両端揃えの自動配置はできません。

その他、SVGのテキストを使う場合の注意点として、FOのブロックやHTMLのテキストと異なり、
「viewBoxは伸長しないため、想定よりテキストが長くなると表示が見切れる」という点があります。
つまり、「ページ単位で表示領域を確保できる」など、特に高さ・テキスト長があらかじめ想定できる
範囲で使うようにするとよいでしょう。

そして、Formatter V7.3で対応したSVGフィルタ・マスク機能と組み合わせることで文字列に効果を付加できます!

SVGテキストとマスク

画像に対し、テキストをマスクとして被せたものになります。このSVGではtext-anchor=”middle”です。
実のところ、SVGマスク以外の方法もあります、ただ、SVGマスクやフィルタは汎用的ですし、追加の独自仕様無しでXSL-FOでも使えるというメリットがあります。