⬆️ upstream そのまま —
packages/scratch-svg-renderer/は upstream Scratch Foundation の実装をそのまま利用。Smalruby 独自の改変はパッケージスコープ (@smalruby/scratch-svg-renderer) のリブランドのみ。
packages/scratch-svg-renderer/ は SVG コスチュームの前処理パッケージ。SVG を WebGL レンダラーに渡せる形 (Canvas / Bitmap) に変換するために、サニタイズ・正規化・フォントインライン化・ラスタ化を行う。
- セキュリティ重要: ユーザーがアップロードする SVG に悪意あるコンテンツ (script, 外部 URL など) が含まれる可能性 → 独立した sanitization 層
- 重い依存 (DOMPurify, css-tree): WebGL レンダラーから切り離すことで、SVG 不使用のシナリオでロードしない
- 再利用性: scratch-paint (ペイントエディタ)、コスチュームインポーターなど、レンダラー以外からも使う
- Vector → Raster ブリッジ: WebGL は SVG をネイティブ描画できないため、Canvas 経由でラスタ化する必要がある
- SVG コスチューム関連のバグを調査する人
- Scratch 2.0 由来の SVG quirks に対応した何かを追加・修正する人
- フォント処理を理解したい人
| 項目 | 値 |
|---|---|
| バージョン | 13.0.0 (upstream 同期) |
| Entry | packages/scratch-svg-renderer/src/index.js (関数群を export) |
| 主要依存 | css-tree (CSS パース), isomorphic-dompurify (SVG サニタイズ), transformation-matrix (2D 行列), base64-js |
{
SVGRenderer, // (deprecated) quirks-mode renderer クラス
loadSvgString, // SVG 文字列をパース・検証して DOM tree を返す
serializeSvgToString, // DOM tree を文字列化
sanitizeSvg, // 危険なコンテンツを除去
convertFonts, // フォント形式変換 (WOFF ↔ TTF)
inlineSvgFonts, // フォント定義を <defs> に埋め込む
BitmapAdapter // SVG を Canvas にラスタ化
}クラスではなく関数群として提供される。
SVG 文字列の取り込みのメインフロー:
- XML パース (DOMParser またはサーバ環境では xmldom)
- Scratch 2.0 quirks 修正:
- 誤った viewBox の補正
- width/height 欠落の補完
- 古い style 属性の正規化
- 境界計測 (実際の表示サイズの計算)
- DOM tree + メタデータ を返す
セキュリティの要。isomorphic-dompurify で以下を除去・無害化:
- 外部 URL 参照 (
xlink:hrefで http:// / https:// を指すもの) url()参照で外部リソース (フォント、画像) を指すもの- スクリプト (
<script>, イベントハンドラ属性) data:URL (例外: 安全なdata:image/...のみ許可)- 不正な構造の修正
→ ユーザーアップロード SVG の XSS 攻撃を防ぐ。
Canvas での描画は HTML カスタムフォントをリンクできないため、SVG 内のフォント定義を base64 エンコードしたフォントデータとして <defs> に埋め込む 必要がある:
- SVG 内の
font-family属性をスキャン scratch-render-fontsパッケージから対応するフォントデータ (WOFF / TTF) を取得<style>@font-face { ... }</style>を SVG の<defs>に注入- これで Canvas 描画時に正しいフォントで描画される
SVG → Canvas ラスタ化の本体:
1. SVG bounds を計測
2. Canvas を bounds に合わせてリサイズ
3. ctx.drawImage() で SVG をデータ URL 経由で描画
4. ctx.getImageData() で ImageData (pixel array) を取得
5. 回転中心情報 + bitmap を返す
これが scratch-render の SVGSkin が WebGL テクスチャをアップロードするときの入力。
SVG の transform="" 属性 (translate / rotate / scale / skew / matrix) をパースして 2D 行列として適用するユーティリティ。
旧 quirks-mode の SVGRenderer クラス。新規コードでは使わない。後方互換のため残置。
SVG コスチューム (string)
↓
scratch-svg-renderer:
loadSvgString → sanitizeSvg → inlineSvgFonts → DOM tree
↓
scratch-render の SVGSkin:
BitmapAdapter で Canvas にラスタ化
↓
WebGL texture upload
ゼロ (パッケージスコープのリブランドのみ):
package.jsonの"name": "@smalruby/scratch-svg-renderer"- 内部実装は upstream 同期
upstream マージ時の競合は基本的に発生しない。
scratch-render/README.md— WebGL レンダラー (本パッケージの主要利用者)- 上流: scratch-svg-renderer GitHub
特になし (upstream 同期で進化)。