mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-26 11:06:58 -06:00
- 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>
93 lines
6.7 KiB
Markdown
93 lines
6.7 KiB
Markdown
# 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).
|