Add per-character text outline/stroke for text clips#190
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b8d298a. Configure here.
| debounceKey: "outlineColor", | ||
| setEnabled: { $0.outline.enabled = $1 }, | ||
| setColor: { $0.outline.color = $1 } | ||
| ) |
There was a problem hiding this comment.
Outline enable skips bbox refit
Medium Severity
Turning on outline (inspector toggle or set_clip_properties with only outlineColor) does not run fitTextClipToContent, unlike outline width changes. The clip box stays sized for fill-only text while outline mode rasterizes into that fixed CATextLayer bounds, so the stroke can be clipped in preview and export.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit b8d298a. Configure here.


Summary
Adds a per-character text outline (stroke) to text clips — the classic TikTok/YouTube Shorts caption style with colored borders around each letter.
Changes
Model (
TextStyle.swift,TextLayout.swift)TextStyle.Outlinestruct:enabled,color(RGBA, default black),width(canvas points, default 3).palmierfilesTextLayout.naturalSizeaccounts for outline width in bounding-box paddingNSAttributedString.Key.strokeColor+.strokeWidth(negative = fill + stroke)Rendering (
TextLayerController.swift)CGImageviaNSAttributedString.draw(in:)→CGContext.makeImage()CATextLayer's native text rendering soAVVideoCompositionCoreAnimationToolcomposites stroke correctly during exportInspector UI (
TextTab.swift)MCP / Agent Tools
add_texts:outlineColor(hex),outlineWidth(canvas points) — setting either auto-enables outlineset_clip_properties: same params (text clips only)add_captions: same params — captions can have outline toooutlineWidthparsed viadict.double()to handle MCP JSON integer/float coercionTesting
swift buildpasses with zero new warningsNote
Low Risk
Localized text styling and rendering changes with tolerant project decode; export path adds a CGContext rasterization branch only when outline is enabled.
Overview
Adds per-character text outline/stroke on text clips (caption-style colored letter borders), wired through the model, preview/export, inspector, and agent tools.
TextStylegains anOutline(enabled, color, width in canvas points) with backward-compatible decode. Stroke usesNSAttributedStringstroke attributes;TextLayout.naturalSizepads the bbox when outline is on.TextLayerControllerrasterizes outlined text to aCGImagewhen enabled so export compositing matches preview (instead of relying onCATextLayeralone).Inspector (
TextTab) adds outline toggle/color and a width scrubber (0.5–20 pt) that refits the clip box.Agent/MCP:
outlineColorandoutlineWidthonadd_texts,set_clip_properties(text-only), andadd_captions; either param enables outline.set_clip_propertiestreatsoutlineWidth-only updates as valid and refits on width changes.Reviewed by Cursor Bugbot for commit b8d298a. Bugbot is set up for automated code reviews on this repo. Configure here.