4DのSVGレンダリングエンジンの縦書きサポートに関する考察です。
Specification
4DのSVGレンダリングエンジンは,Scalable Vector Graphics (SVG) 1.1 (Second Edition)をベースに設計されており,基本的な要素や属性がサポートされています(つまり,すべてが利用できるわけではありません)。加えて,Scalable Vector Graphics (SVG) Tiny 1.2 Specificationの要素や属性も一部がサポートされています。
text or textArea
textAreaは,四角形の内部にテキストをレンダリングするものです。折り返しや禁則処理を自前で実装する必要がなく,レイアウトが簡単にデザインできるので,とても便利です。ただし,2019年の時点で,主要なユーザーエージェントはtextAreaをサポートしていないので,外部アプリケーションで表示するような用途には不向きとなっています。
レイアウト関連では,下記のCSSスタイル属性がサポートされています。
text-alignテキスト進行方向の揃え [start, end. center, justify]display-alignブロック進行方向の揃え [auto, before, after, center]letter-spacingテキスト進行方向の文字間隔
縦書きスクリプトがサポートされているので,水平揃え・垂直揃えという表現はしない点に留意してください。
下記のCSSスタイル属性はサポートされていません。
line-incrementword-spacingglyph-orientation-horizontalglyph-orientation-verticaldominant-baseline
textAreaは,指定した領域に収まるよう,テキストを描画するのに適しています。ただし,行間をコントロールすることができないので,レイアウトのデザインに限界があります。

textは,どのユーザーエージェントでもサポートされている基本の要素です。テキストが複数行にわたる場合,textAreaのようにtbreak要素で改行したり,レンダリングエンジンに折り返しの処理を任せたりするようなことはせず,行毎にtextを使用します。手間はかかりますが,行間を自由に制御することができるというメリットがあります。

この例では,本文にtext,ルビにtextAreaを使用しています。座標とフォントサイズの単位にpc(パイカ)およびin(インチ)を使用しているため,比較的シンプルにレイアウトを決めることができました。
textまたはtextAreaを縦書きにする場合,要素のwriting-mode属性を指定します。CSSスタイルで指定することはできないので,注意してください。
Download
https://github.com/miyako/4d-tips-svg-writing-mode
Convert to PDF (fail)
SVGをPDFに変換するrsvg-convertというプログラムがあります。
カスタマイズ版: miyako/console-rsvg-convert
上記の方法で作成したSVGを処理させたところ,下記のようなエラーが返されました。
Pango-WARNING **: couldn't load font "Times New Roman, Rotated-Left 12", modified variant/weight/stretch as fallback, expect ugly output.
Pango-ERROR **: Could not load fallback font, bailing out.
日本語のwriting-mode:tb-rlでエラーになるようです。英語の縦書きでは問題ありませんでした。いずれにしてもtextAreaは出力されません。
Convert to PDF (success)
4Dの印刷コマンドでPDFを作成することができます。
まず,印刷は同時に複数のプロセスで実行できないので,Storageでコードブロックを保護します。従来のようにSemaphoreを使用しても構いません。
If (Storage.mutex=Null)
Use (Storage)
Storage.mutex:=New shared object
End use
End if
If (Storage.mutex.printing=Null)
Use (Storage.mutex)
Storage.mutex.printing:=New shared object
End use
End if
Use (Storage.mutex.printing)
//...
End use
カレントの印刷設定をオブジェクト型に保存します。
C_OBJECT($currentPrintSettings)
C_REAL($left;$top;$right;$bottom)
GET PRINTABLE MARGIN($left;$top;$right;$bottom)
C_LONGINT($destination)
GET PRINT OPTION(Destination option;$destination)
$currentPrintSettings:=New object(\
"name";Get current printer;\
"destination";$destination;\
"margin";New object(\
"left";$left;\
"top";$top;\
"right";$right;\
"bottom";$bottom)\
)
PDFファイルの保存パスを設定します。WindowsではDestination optionが2,Macでは3となる点に注意してください。
If (Is Windows)
SET CURRENT PRINTER(Generic PDF driver)
SET PRINT OPTION(Destination option;2;$pdfPath)
Else
SET PRINT OPTION(Destination option;3;$pdfPath)
End if
SVGは,用紙サイズぴったりのピクチャオブジェクトに転写して印刷します。フォームエディターで個別に用意することもできますが,JSONフォームであれば,オンザフライでフォームが作成できるので便利です。
C_OBJECT($form)
$form:=New object(\
"destination";"detailScreen";\
"rightMargin";0;\
"bottomMargin";0;\
"markerHeader";0;\
"markerBody";0;\
"markerBreak";0;\
"markerFooter";0;"events";New collection("onLoad";"onUnload");\
"pages";New collection(Null;New object("objects";New object)))
$form.pages[1].objects.img:=New object(\
"type";"input";\
"top";0;\
"left";0;\
"width";$width;\
"height";$height;\
"dataSourceTypeHint";"picture";\
"focusable";False;\
"enterable";False;\
"contextMenu";"none";\
"dragging";"none")
印刷ジョブを開始し,フォームの代わりにオブジェクト型をメモリにロードします。
OPEN PRINTING JOB
FORM LOAD($form)
$img:=OBJECT Get pointer(Object named;"img")
ピクチャをメモリ上の仮想フォームオブジェクトに代入します。
$img->:=$svg
$printed:=Print object(*;"img")
仮想フォームをアンロードし,印刷ジョブを終了します。
FORM UNLOAD
CLOSE PRINTING JOB
印刷コマンド終了後,印刷設定を復元します。
SET CURRENT PRINTER($currentPrintSettings.name)
SET PRINT OPTION(Destination option;$currentPrintSettings.destination)
SET PRINTABLE MARGIN(\
$currentPrintSettings.margin.left;\
$currentPrintSettings.margin.top;\
$currentPrintSettings.margin.right;\
$currentPrintSettings.margin.bottom)