背景
#53 で Python turtle との差分を整理した結果、write()(テキスト描画)が描画語彙に残る
唯一の本質的な穴であることが分かった。
このライブラリの描画コマンドは primitive なものに絞る方針で、「既存の primitive の
組み合わせで到達できるものは入れない」(組み合わせて考えるのは利用者、特に子供の仕事)
という基準で判断している。Python turtle にあってこちらに無いもののうち、
dot(size, color) の色引数、color(pen, fill)、circle(steps=) はいずれも組み合わせで
書けるので、入れないことに理由がある。
テキストだけは、どう組み合わせても到達できない。 だからこれは穴であり、primitive 側に
属する機能として検討する価値がある。
図にラベルを付ける、座標軸に数値を振る、作品にタイトルを入れる、といったことが現状
一切できない。
Python turtle の挙動(参考)
turtle.write("Hello", move=False, align="left", font=("Arial", 8, "normal"))
align: "left" / "center" / "right"
move: True なら書き終わりの位置にタートルが移動する
- テキストは常に水平で、タートルの heading には追従しない
- ペンの上下に関係なく描かれる
難しいところ
素直に入れられないので未着手になっている。論点は以下。
1. Core は Foundation のみ・Linux 対応
TortoiseCore にはプラットフォーム API が無い。フォントのメトリクス(各文字の送り幅、
ベースライン、カーニング)を解決する手段がそもそも無い。
2. 2 つのレンダラーが一致しない
TortoiseSVG の <text> は、閲覧環境にあるフォントで描画される。同じ SVG が別の
マシンで違う幅になる
TortoiseUI の Canvas は実フォントでラスタライズする
同じコマンドが 2 つのレンダラーで違う見た目になり、ゴールデンテスト
(DrawingScenarioSVGTests / DrawingScenarioCanvasTests)が構造的に一致しない。
3. ワイヤーフォーマットが 2.x で凍結されている
フォントをどう持つか(family 名の文字列? サイズだけ? 何も持たない?)を一度決めたら、
2.x の間は変更できない。フォント名を持たせると、その名前のフォントが無い環境での
挙動まで仕様になる。
4. DrawingBounds が測れない
テキストの外接矩形が分からないと ViewportMode.autoFit が壊れる。文字を含む描画で
ビューが正しくフィットしなくなる。
方針の選択肢
A. 単線ベクタフォントを Core に内蔵する(推奨)
Hershey フォントのような線分の集まりで定義された単線フォントのデータを
TortoiseCore に持ち、write を内部的にストロークの集合として展開する。
- ✅ Core 内で完結し、プラットフォーム API に依存しない → Linux OK
- ✅ 2 つのレンダラーが同じストロークを受け取るので、見た目が完全に一致する
- ✅
DrawingBounds が正確に計算できる(ただの線分なので)
- ✅ 思想に合う。 タートルが線で文字を書くのであって、文字を貼り付けるのではない。
出力が primitive(線)のままになる
- ❌ 表現は限られる(書体を選べない、日本語は現実的でない)
- ❌ フォントデータの分だけバイナリが増える
- ❌ ライセンスの確認が必要
B. プラットフォームのフォントに委ねる
- ❌ Linux で破綻する
- ❌ SVG と Canvas で見た目が変わる
- ❌ ゴールデンテストが書けない
C. Core は文字列とサイズだけ保持し、解決はレンダラーに任せる
- ❌ SVG は閲覧環境依存のまま。同じ描画が環境によって変わる、という性質が
「コマンドストリームは再現可能な記録である」という設計と衝突する
決めるべきこと
優先度について
需要が実際に出ているわけではないので急がないが、描画語彙に残る唯一の穴であり、
新しい描画コマンドの追加を検討するときは常にこれが最優先候補になる、という位置づけ。
関連
背景
#53 で Python turtle との差分を整理した結果、
write()(テキスト描画)が描画語彙に残る唯一の本質的な穴であることが分かった。
このライブラリの描画コマンドは primitive なものに絞る方針で、「既存の primitive の
組み合わせで到達できるものは入れない」(組み合わせて考えるのは利用者、特に子供の仕事)
という基準で判断している。Python turtle にあってこちらに無いもののうち、
dot(size, color)の色引数、color(pen, fill)、circle(steps=)はいずれも組み合わせで書けるので、入れないことに理由がある。
テキストだけは、どう組み合わせても到達できない。 だからこれは穴であり、primitive 側に
属する機能として検討する価値がある。
図にラベルを付ける、座標軸に数値を振る、作品にタイトルを入れる、といったことが現状
一切できない。
Python turtle の挙動(参考)
align:"left"/"center"/"right"move:Trueなら書き終わりの位置にタートルが移動する難しいところ
素直に入れられないので未着手になっている。論点は以下。
1. Core は Foundation のみ・Linux 対応
TortoiseCoreにはプラットフォーム API が無い。フォントのメトリクス(各文字の送り幅、ベースライン、カーニング)を解決する手段がそもそも無い。
2. 2 つのレンダラーが一致しない
TortoiseSVGの<text>は、閲覧環境にあるフォントで描画される。同じ SVG が別のマシンで違う幅になる
TortoiseUIのCanvasは実フォントでラスタライズする同じコマンドが 2 つのレンダラーで違う見た目になり、ゴールデンテスト
(
DrawingScenarioSVGTests/DrawingScenarioCanvasTests)が構造的に一致しない。3. ワイヤーフォーマットが 2.x で凍結されている
フォントをどう持つか(family 名の文字列? サイズだけ? 何も持たない?)を一度決めたら、
2.x の間は変更できない。フォント名を持たせると、その名前のフォントが無い環境での
挙動まで仕様になる。
4.
DrawingBoundsが測れないテキストの外接矩形が分からないと
ViewportMode.autoFitが壊れる。文字を含む描画でビューが正しくフィットしなくなる。
方針の選択肢
A. 単線ベクタフォントを Core に内蔵する(推奨)
Hershey フォントのような線分の集まりで定義された単線フォントのデータを
TortoiseCoreに持ち、writeを内部的にストロークの集合として展開する。DrawingBoundsが正確に計算できる(ただの線分なので)出力が primitive(線)のままになる
B. プラットフォームのフォントに委ねる
C. Core は文字列とサイズだけ保持し、解決はレンダラーに任せる
「コマンドストリームは再現可能な記録である」という設計と衝突する
決めるべきこと
align/moveを Python turtle に合わせるかただしタートルが線で書くなら回転するほうが自然かもしれない)
penColor/penWidthに従うのか、独立させるのか{"write":{...}}のペイロード)優先度について
需要が実際に出ているわけではないので急がないが、描画語彙に残る唯一の穴であり、
新しい描画コマンドの追加を検討するときは常にこれが最優先候補になる、という位置づけ。
関連
forward(_:widthTo:)/circle(radius:extent:widthTo:)) #50(ペン幅テーパー。primitive に絞る方針を確認したきっかけ)