Files

22 KiB
Raw Permalink Blame History

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): 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 paragraph text wrapped at that width), box_height (paragraph text: lines that do not fit are not shown; 0 = as tall as the text)
Shape shape (Rectangle/Ellipse/Polygon/Path), size [w, h], sides, corner_radius (one radius for all four corners, at most half the shorter side; on the Program monitor, drag one of the four small circles just inside a selected rectangle's corners), 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); paragraph text's origin is the top-left corner of its box; a shape's origin is its centre. Colours are #rrggbb (sRGB).

Point text and paragraph text

A text layer is one of two types, as in Premiere Pro (behaviour observed in Premiere Pro 26):

Point text Paragraph text
Made with the Type tool by a click a drag: the dragged rectangle is the box
Lines only where Return was typed wrap at the box's width; lines below the box's bottom are not shown, and the bottom-right handle turns into a red plus
Selection box fits the text the box, whatever it holds
New layer's anchor point the origin (left end of the first baseline) the box's top-left corner
Dragging a handle scales the layer about its anchor point: every handle scales both axes alike (Uniform Scale stays on), the font size is untouched moves that side or corner of the box to the pointer, the opposite side stays; the text re-wraps at the same size and Scale is untouched
  • Point-text scale. Only the pointer's travel along one side of the box counts: along its width for the two side handles, along its height for the corners and the top and bottom handles. Travel d away from the anchor scales by 1 + d / r, where r is the handle's distance from the anchor along that side, plus 60 points when the handle is nearer than 60 points (so a handle on the anchor does not scale without bound). A handle exactly on the anchor grows the text when dragged into the box.
  • Paragraph box. A side dragged past its opposite stops at half the font size. When the top or left side moves, the layer's origin moves with the corner, so the anchor point is renumbered to stay on the same spot of the picture and Position does not change.
  • Anchor point. Drag it with the Selection tool: the anchor moves, the layer stays (Position and Anchor Point change together). It is picked before anything under it: a shape dragged by its exact centre moves its anchor, not the shape, and the top-left handle of a new paragraph box is reached only after moving the anchor.
  • Switching type. Properties ▸ Text ▸ wrench ▸ Text Properties ▸ Text Layer Type (graphics.setTextType). To point text: the wrapped lines become real lines (also those the box hid). To paragraph text: the box is fitted to the text. Either way the text stays where it is and Position is untouched; only Anchor Point is renumbered. Vertical text is always point text.

Known differences from Premiere: the first line of paragraph text sits one font ascent below the box's top (Premiere places it higher, about one cap height below); Premiere's smallest box and the box it fits when switching to paragraph text were not measured exactly; the 60 points were measured with the Program monitor at Fit only; Text Properties has no Hindi Digits option.

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, box ([w, h]: paragraph text in a box, position is its top-left corner), clip (add to this graphic), vertical, size, font, fontStyle, seconds (5), track, time
graphics.newVerticalText New Layer ▸ Vertical Text as graphics.newText; characters stack top to bottom, paragraphs are columns right to left
graphics.newRectangle, graphics.newEllipse, graphics.newPolygon New Layer ▸ Rectangle (⌥⌘R), Ellipse (⌥⌘E), Polygon position (the shape's centre), size, clip, seconds (5), track, time; polygon sides (6)
graphics.newFromFile New Layer ▸ From file… path — imports the image or video and places it above the clips at the playhead (a separate clip; graphics have no media layers yet)
graphics.newShape (agents) shape (rectangle/ellipse/polygon/path), position (the shape's centre), size, points, clip (add to this graphic), seconds (5), track, time
graphics.setTextType Text Properties ▸ Text Layer Type clip, layer, type (point / paragraph); the text stays where it is
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, merge + begin (a drag is one undo step: send merge: true on every change and begin: true on the first change of each press)
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/group/selection), layers
graphics.alignFrame.<how> Align to Video Frame ▸ Left / Center Horizontally / Right / Top / Center Vertically / Bottom each selected layer to the frame
graphics.alignGroup.<how> Align to Video Frame as Group ▸ … the selected layers' union to the frame (2+ layers; relative positions kept)
graphics.alignSelection.<how> Align to Selection ▸ … each selected layer to the selection's union (2+ layers)
graphics.distribute Align and Transform axis (horizontal/vertical), space (equal gaps), layers (3+)
graphics.distributeVertically, …SpaceVertically, …Horizontally, …SpaceHorizontally Distribute ▸ … the selected layers (3+): equal centre spacing or equal gaps
graphics.bringToFront, graphics.bringForward, graphics.sendBackward, graphics.sendToBack Arrange ▸ … (⇧⌘], ⌘], ⌘[, ⇧⌘[) clip, layer
graphics.selectNextGraphic, graphics.selectPreviousGraphic Select ▸ Select Next / Previous Graphic selects the next / previous graphic clip in timeline order (moves the playhead onto it)
graphics.selectNextLayer, graphics.selectPreviousLayer Select ▸ Select Next / Previous Layer (⌥⌘], ⌥⌘[) cycles the selected layer
graphics.resetAllParameters Reset All Parameters layers (default: the selected layers, else all) — appearance, text formatting and transform back to defaults; text, shape and geometry kept
graphics.resetDuration Reset Duration seconds (5), limited by the next clip on the track
graphics.list (query) clip — layers with names, kinds, text, textType (point / paragraph), box, overflow (the box hides text), position, anchor, scale 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 point-text layer with a caret. Drag on empty picture: new paragraph-text layer with that box. Click a text layer: caret there. The box of the text being typed into is red. 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; only selected layers have a box, and a layer whose visibility is off has none and cannot be clicked); drag to move; drag the anchor point to move it alone; drag a handle to scale point text about its anchor, resize a paragraph-text box (see Point text and paragraph text), or change a shape's Size: the dragged side or corner follows the pointer while the opposite one and the anchor point stay, Scale is untouched, and Shift on a corner keeps the proportions (a path, which has no Size, stretches instead); double-click a text layer to edit it with all its text selected, so typing replaces it; while text is edited, Select All (Cmd/Ctrl+A or Edit ▸ Select All) selects all of that text instead of the timeline clips.
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.

Moving a layer snaps its edges or centre to the frame edges, the frame centre and the guides (View ▸ Snap in Program Monitor, on by default; hold ⌘/Ctrl to move freely). See monitors.md for rulers and guides.

Automation ids: program.layer.<clip>.<layer>, program.layer.<clip>.<layer>.handle.<n> (0–3 the corners from the top-left clockwise, 4–7 the top, right, bottom and left sides), program.layer.<clip>.<layer>.anchor, 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 and height, faux bold / faux italic / all caps / small caps / underline, kerning and ligatures; the wrench in the section's header opens Text Properties: Text Layer Type 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>, graphics.textProperties (the wrench) and in its dialog graphics.textProperties.type, .type.point, .type.paragraph, .ligatures, .ok, .cancel.

Per-character styles

Select characters with the Type tool and change font, style, size, colour, faux bold / italic, underline, tracking, baseline shift or caps in the Properties panel: the change applies to the selection only (graphics.setCharStyle). Styles are stored on the layer as runs of characters (EffectInstance::layer.runs, character offsets, sorted and non-overlapping) and follow the text when it is edited (typed characters take the style of the character before them). The text engine lays the runs out together (filmcraft_text::layout_rich): a run can change the font and size, lines grow to fit the largest run, and each run can have its own fill colour.

Command Params
graphics.setCharStyle clip, layer, start, end (characters; default the whole text), style {font, fontStyle, size, color, bold, italic, underline, tracking, baselineShift, caps}, clear (remove styles from the range)

Responsive design

Position (pins). A layer's edges can be pinned to another layer of the same graphic or to the video frame (graphics.pin {layer, to: "frame" | layer index | name | "none", edges}). Each pinned edge keeps its distance to the same edge of the target, measured when the pin is made: a box pinned on all four edges to a text layer grows with the text; a shape pinned on two opposite edges is resized, a text layer only moves. Pins resolve in dependency order (cycles are ignored). Moving a pinned layer keeps the pin at its new distance. Layers get a stable uid for this.

Time (intro / outro). graphics.setResponsiveTime {introFrames, outroFrames} protects the first and last part of a graphic: when the clip is trimmed or extended, keyframes inside the intro keep their timing from the clip start, those inside the outro from the clip end, and the middle is stretched or squeezed (graphic_design::remap_time). Trimming the head keeps the intro playing from the new start.

Rolls and crawls. graphics.setRoll {mode: off | roll | crawlLeft | crawlRight, startOffScreen, endOffScreen, prerollFrames, easeInFrames, easeOutFrames, postrollFrames} (the Roll options of Responsive Design – Time) moves the whole graphic: up for a roll, sideways for a crawl. Start Off Screen starts with the content just outside the frame (below it / right of it / left of it), otherwise where it was laid out; End Off Screen lets it leave completely, otherwise it stops when its last edge reaches the frame edge. The speed is constant between the preroll and the postroll, with linear acceleration over Ease In and deceleration over Ease Out (graphic_design::roll_progress). The offset is exact maths on the union of the layers' bounds (with background padding), at the clip-relative time.

These settings are TrackItem::graphic (GraphicMeta, schema v12).

Graphics templates (.fcgt)

FilmCraft's equivalent of motion graphics templates is its own format: a .fcgt file is documented, versioned JSON (filmcraft_project::gtemplate):

Field Meaning
format, version "filmcraft.graphicsTemplate", 1 (newer versions are refused)
id, name, category, description, author, license, tags library information
canvas, duration frame size it was designed for, default clip length (ticks)
layers the graphic's layers, exactly as in a project file, each with a uid
graphic roll / crawl and responsive time
controls editable properties: {id, name, kind: text|color|slider|checkbox|font|position, layer: uid, param, min, max}; param: "enabled" is the layer's visibility
resources.fonts optional embedded font files (base64) with their licence; registered on install

Placing a template on a sequence of another size scales and centres its layers (pin distances scale too).

FilmCraft never reads or imports Adobe .mogrt files (or any other application's template packages): Install refuses .mogrt paths without opening them, and the reader rejects ZIP archives. Built-in templates are original designs made for FilmCraft in code (no image, font or template files): lower thirds (Slab, Rule, Ticker crawl), titles (Centered, Boxed), end credits (Roll) and callouts (Pointer, Tag), with the bundled Inter font. Thumbnails are rendered by the engine at runtime.

Command Menu Params
graphics.template.list (query) query, category, source (builtin / user)
graphics.template.apply Browse tab: drag or double-click template (id, name or .fcgt path), values {control: value}, time, track
graphics.template.export Graphics and Titles ▸ Export As Motion Graphics Template… clip, name, category, description, controls [{layer, param, name, kind, min, max}], path (default: the user folder), embedFonts
file.exportGraphicsTemplate File ▸ Export ▸ Motion Graphics Template… as above
graphics.template.install Graphics and Titles ▸ Install Motion Graphics Template… path (a .fcgt)
graphics.template.remove Browse tab template (user templates)
graphics.template.set / graphics.template.controls Essential Graphics ▸ Edit clip, control, value / values
graphics.template.thumbnail (query) template, width, path (PNG)

User templates live in <data dir>/Graphics Templates/.

Essential Graphics panel. Browse lists the built-in and user templates as cards with engine-rendered thumbnails, a search field and a category filter; click selects, double-click or Apply places the template at the playhead, dragging a card onto a video track places it there, Install… picks a .fcgt, Remove deletes a user template. Edit is the graphic editor; for a graphic made from a template it starts with Template Properties (one editor per control). With no layer selected it shows Responsive Design – Time (intro / outro, Roll with its options); with a layer selected, Responsive Design – Position (Pin To and the pinned edges). With characters selected by the Type tool, the Text section's controls style just those characters. Export As Motion Graphics Template… opens a dialog (name, category, description and a checklist of properties to expose); Replace Fonts in Projects… lists the fonts in use (missing ones flagged) and replaces one. Automation ids: essentialGraphics.tab.browse|edit, gfxTemplates.search, gfxTemplates.category, gfxTemplates.item.<id>, gfxTemplates.apply|install|remove, gfxTemplates.control.<control id>, graphics.roll.*, graphics.time.intro|outro, graphics.pin.to|left|top|right|bottom, exportTemplate.*, replaceFonts.*; ui.set {"gfxTemplates": {...}, "gfxEdit": {...}} sets the panel state and the Type-tool selection.

Captions, source graphics and fonts

Command Menu Params
graphics.upgradeCaption Graphics and Titles ▸ Upgrade Caption to Graphic captions (default: the selection, else the one under the playhead): each caption becomes a graphic clip on a video track with the track style (font, size, colour, background, outline, alignment, position); <i>/<b>/<u> become character styles; one undo step
graphics.upgradeToSourceGraphic Graphics and Titles ▸ Upgrade to Source Graphic clip: the graphic gets its own project item (shown in the Project panel); every clip of that item shares its layers — editing one updates the others in the same undo step (project.source_graphics)
file.replaceFonts Graphics and Titles ▸ Replace Fonts in Projects… from (family or {family, style}), to, toStyle: graphic layers, character styles, source graphics and caption tracks
graphics.fonts.used (query) fonts in use with counts and whether they are missing

Gradient fills

Appearance › Fill Type › Linear Gradient paints the shape or the text with a ramp from Gradient Start to Gradient End. Stops are blended in linear light. The angle is degrees clockwise on screen; 0° runs left to right across the layer's own bounds, and the ramp turns with the layer. graphics.set accepts fill_kind (solid or linear gradient), gradient_start, gradient_end and gradient_angle. A per-character fill colour still paints those characters as a solid; the rest of the text keeps the ramp. A singular layer transform falls back to the solid fill colour.

Not yet

Mask-with-text, per-layer blend modes, Bézier curves in the pen tool (paths are polygons), media layers inside graphics, and template controls grouped into folders.