Files
filmcraft/docs/graphics.md
T
Brandon ThomasandClaude Opus 5.5 daaee5072c M10.2: Type tool with on-monitor text editing, shape and pen tools, layer boxes and handles, graphic editor in Properties / Essential Graphics
- Program monitor overlay for graphic clips: Type tool click creates a text layer (in the
  selected graphic under the playhead or a new clip) and edits it in place with a caret,
  selection highlight, arrows/word/line navigation, Shift-select, Cmd+A/C/X/V, Return,
  Backspace/Delete, Esc; typing is one undo step. Selection tool selects, moves and scales
  layers (bounding box, handles, anchor); double-click edits text. Rectangle/Ellipse tools
  drag out shapes; Pen tool places a closed path. Automation ids program.layer.*.
- Properties (when a graphic is selected) and Essential Graphics: Layers list, Align and
  Transform (align / distribute), Text (source text, font family + style incl. system fonts,
  size, paragraph alignment, tracking, leading, baseline shift, box width, faux bold/italic,
  caps, underline, kerning/ligatures), Shape, Appearance (fill, 2 strokes, background,
  shadow). Automation ids graphics.*.
- Headless UI test (egui_kittest) drives the whole flow through the control channel; with
  FILMCRAFT_UI_SHOTS it renders PNGs via wgpu (works with a locked screen).
- docs/graphics.md; architecture, ROADMAP, ATTRIBUTION (code-drawn glyphs) updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 01:57:18 -04:00

93 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Graphics
FilmCraft's graphics work like Premiere's Essential Graphics: a **graphic clip** on a video track
holds **text** and **shape** layers. Text is set by the text engine in `crates/text`
([README](../crates/text/README.md)): bundled OFL fonts plus system fonts, OpenType shaping with
kerning and ligatures, bidi, line breaking, all drawn as vectors in linear light.
## Model
- A graphic clip's project item is an `ItemKind::Graphic { width, height, rate }`: a transparent
canvas the size of the sequence frame, with unlimited duration. These items are internal and do
not appear in the Project panel.
- Its **layers** are effect instances `graphic_text` / `graphic_shape` in the clip's effect list,
in paint order (first = back). They are hidden from the Effects panel. Because they are effect
instances they save with the project, take keyframes on every animatable property (Source Text
keyframes hold), appear in Effect Controls and copy with the clip. Standard effects on a graphic
clip apply to the composed graphic; Motion and Opacity apply last.
- `filmcraft_project::graphic::eval_layer` evaluates a layer at a time into a `LayerSpec`.
- Projects with graphics need no schema migration: everything is additive (new item kind, new
effect ids). Builds older than this one refuse such files with a parse error.
### Layer properties
| Group | Properties (parameter ids) |
|---|---|
| Text | `text` (Source Text), `font`, `font_style`, `size` (px), `align` (Left/Center/Right/Justify), `tracking` (1/1000 em), `kerning`, `ligatures`, `leading` (px added to the natural line height), `baseline_shift`, `faux_bold`, `faux_italic`, `caps` (Normal/All Caps/Small Caps), `underline`, `box_width` (0 = point text, else area text wrapped at that width) |
| Shape | `shape` (Rectangle/Ellipse/Polygon/Path), `size` [w, h], `sides`, `corner_radius`, `points` (path vertices relative to the layer origin) |
| Appearance | `fill`, `fill_color`; `stroke`, `stroke_color`, `stroke_width`, `stroke_type` (Outer/Center/Inner) and the same for `stroke2`; `background`, `background_color`, `background_opacity`, `background_size` (padding), `background_radius`; `shadow`, `shadow_color`, `shadow_opacity`, `shadow_angle` (135° = down-right), `shadow_distance`, `shadow_size`, `shadow_blur` |
| Transform | `position` (graphic canvas px), `anchor` (layer px), `scale`, `scale_width`, `uniform_scale`, `rotation`, `opacity` |
Point text's origin is its alignment point on the first baseline (the click point of the Type
tool); a shape's origin is its centre. Colours are `#rrggbb` (sRGB).
## Rendering
`crates/render/src/graphic_clip.rs` rasterises each layer straight to the output transform
(sequence Motion × layer transform), so text stays sharp at any scale or rotation. Fill coverage
comes from the text engine; strokes come from a Euclidean distance transform of that coverage
(outer strokes sit under the fill, centre and inner strokes over it); the shadow is the union of
all parts, spread by Size, offset and blurred. Each layer's raster is cached while it stays the same.
The GPU plan receives one tight image per graphic clip and places it with a translation. The
Timecode and Clip Name effects also draw with the text engine.
## Commands
| Command | Menu / shortcut | Params |
|---|---|---|
| `graphics.newText` | Graphics and Titles ▸ New Layer ▸ Text (⌘T) | `text`, `position`, `clip` (add to this graphic), `size`, `font`, `fontStyle`, `seconds` (5), `track`, `time` |
| `graphics.newShape` | Graphics and Titles ▸ New Layer ▸ Shape | `shape` (rectangle/ellipse/polygon/path), `position`, `size`, `points`, `clip` |
| `graphics.setText` | typing on the monitor | `clip`, `layer`, `text`, `merge` (coalesce one typing session into one undo step) |
| `graphics.set` | Properties panel | `clip`, `layer`, `props` {parameter id or camelCase alias: value; choices by index or name}, `time` |
| `graphics.selectLayer` | layer list / monitor click | `clip`, `layers` |
| `graphics.deleteLayer`, `graphics.arrangeLayer` | layer list | `clip`, `layer`, `to` (front/back/forward/backward/index) |
| `graphics.align` | Align and Transform | `align` (left/hcenter/right/top/vcenter/bottom), `to` (frame/selection), `layers` |
| `graphics.distribute` | Align and Transform | `axis` (horizontal/vertical), `layers` (3+) |
| `graphics.list` | (query) | `clip` — layers with names, kinds, text, position and on-canvas quads |
| `fonts.list` | (query) | `system` (scan system font folders, default true) — families and styles |
Without `clip`, commands use the selected graphic clip, else the topmost graphic clip under the
playhead. Without `layer`, they use the selected layer, else the front one. New graphic clips are
placed at the playhead on the first video track above the clips there that is free for the
duration (a track is added if needed).
## Program monitor
| Tool | On the Program monitor |
|---|---|
| Type (T) | Click empty picture: new text layer with a caret. Click a text layer: caret there. Type; ←/→ (⌥ word, ⌘ line), ↑/↓, Home/End, Shift to select, ⌘A, ⌘C/⌘X/⌘V, Return = new line, Backspace/Delete, Esc = stop editing. Drag inside the edited text to select. |
| Selection (V) | Click a layer to select it (box with handles and anchor point); drag to move; drag a corner handle to scale; double-click a text layer to edit it. |
| Rectangle / Ellipse | Drag to draw a shape layer. |
| Pen (P) | Click to place points; click the first point (or Return) to close the path; Esc cancels. |
Automation ids: `program.layer.<clip>.<layer>`, `program.layer.<clip>.<layer>.handle.<n>`,
`program.textEdit` (while editing).
## Properties / Essential Graphics panels
With a graphic clip selected, the Properties panel (and Essential Graphics) shows: **Layers**
(front first; new text / rectangle / ellipse, bring forward / send backward, delete, visibility),
**Align and Transform** (six align buttons, two distribute buttons, position, anchor, scale,
rotation, opacity), **Text** (Source Text field, font family and style, size, paragraph alignment,
tracking, leading, baseline shift, box width, faux bold / faux italic / all caps / small caps /
underline, kerning and ligatures), **Shape**, and **Appearance** (fill, two strokes, background,
shadow). Automation ids: `graphics.layers.<n>`, `graphics.prop.<parameter id>`,
`graphics.align.<how>`, `graphics.distribute.<axis>`, `graphics.sourceText`, `graphics.NewTextLayer`,
`graphics.NewRectangle`, `graphics.NewEllipse`, `graphics.deleteLayer`, `graphics.section.<name>`.
## Not yet
Per-character styling inside one text layer, responsive design pins and rolls/crawls (M10.3),
motion graphics templates, the Browse tab, mask-with-text, gradient fills, per-layer blend modes, and
Bézier curves in the pen tool (paths are polygons).