Skip to content

M3: stroke on type, Stroke panel units, mixed values and Control bar (M3.40, M3.41) - #28

Merged
bflatastic merged 2 commits into
mainfrom
pr/m3-stroke-on-type
Oct 4, 2026
Merged

bflatastic merged 2 commits into
mainfrom
pr/m3-stroke-on-type

Conversation

@bflatastic

Copy link
Copy Markdown
Member

Part of M3 (Paint & appearance). The Stroke panel now edits the stroke of type characters, and it follows the stroke units, shows mixed values blank and reaches the Control bar.

  • M3.40: stroke on type.
    • Model: CharStyle gains stroke_cap, stroke_join, stroke_miter_limit (default 10) and stroke_dash, defaulted and only written when set. One CharStyle::appearance() builds the characters' fill and stroke, keeping the overprint flags and the stroke options.
    • stroke.set: with type selected and no item, it sets weight, cap, join, miter limit and dashes on every run; an explicit item edits an object stroke. Unknown cap or join names are now rejected.
    • Typing: text.setRangeStyle {strokeOptions} styles a range of characters, and the Stroke panel uses it while the Type tool edits text.
    • Output: character strokes and object strokes on type go through the shared stroke code on the canvas, in PDF and in SVG, so dashes, joins, profiles, opacity, blend and brushes all apply.
    • Other features: Create Outlines, the Eyedropper and graphic styles keep the options.
    • Behaviour change: character strokes now default to a miter join like object strokes, instead of always drawing round joins.
  • M3.41: Stroke panel usability.
    • Units: weight and dash fields follow Units ▸ Stroke in the Stroke panel, the Control bar and the Properties panel.
    • Mixed selections: values the selection doesn't share show blank (DocState::stroke_mixed, cached per revision).
    • Align: Inside/Outside are disabled for open paths and type.
    • Control bar: a weight spinner with presets from 0.25 to 100 pt and a profile dropdown. Its Stroke link opens the Stroke panel as an anchored popover, as does the Properties panel's "…" button.
    • Groups: stroke.set on a group skips images and symbol instances.
    • Inspect: document.inspect reports strokeOptions (cap, join, miter limit, align, dash, offset, alignment, arrowheads, profile), including for groups and layers that carry their own stroke.

docs/mcp.md has a "Strokes on type" section.

Known limits:

  • With type selected, the arrowhead and profile controls stay enabled but have no effect.
  • Mixed values aren't computed for a typed range.

Checks

Rebased onto 09778f2 (#27). cargo xtask ci passes all 7 steps on this branch: 1,550 tests, 0 failed.

  • New tests:
    • engine;
    • render (round joins without spikes, dashes, opacity);
    • SVG (an object-stroke dash) and PDF;
    • a UI typing-range test;
    • a native round-trip and loading an older file;
    • the panel checks: a 1 pt stroke shown in mm, disabled buttons, a blank mixed weight, inspect fields, presets 0.25 and 100, and skipping images and symbols in groups.
  • Checked in the running app: a dashed type stroke, the blank mixed weight, the Control bar and the anchored popover.

🤖 Generated with Claude Code

bflatastic and others added 2 commits October 5, 2026 01:09
With type selected, stroke.set (without an item) gives every run the
weight, cap, join, miter limit and dashes instead of adding an object
stroke; while the Type tool edits text, the Stroke panel styles the
selected characters through text.setRangeStyle `strokeOptions`, and the
panel reads the first run (or the selection's style).

CharStyle gains stroke_cap, stroke_join, stroke_miter_limit and
stroke_dash (defaulted, skipped when default). Character strokes and
object strokes on type now draw through the shared stroke geometry on
the canvas, in PDF and in SVG (live text writes cap/join/miter/dash and
tspans reset what the first run sets; object strokes are drawn on the
glyph outlines), so every stroke option, opacity and blend applies.
Outlines, the Eyedropper and graphic styles keep the options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and reaches the Control bar

- Weights and dash lengths show in Units > Stroke in the Stroke panel,
  the Control bar and the Properties panel (Session::stroke_unit).
- Values the selected objects don't share show blank (weight, miter
  limit, dashes) or light no button (cap, join, align), from a
  per-revision cached DocState::stroke_mixed.
- Align Stroke Inside/Outside are disabled for open paths and type.
- The Control bar weight is a preset spinner with a width profile
  dropdown, and its Stroke link (and the Properties panel's) opens the
  Stroke panel as an anchored popover instead of docking it.
- The panels show a group's first painted object's stroke, as the
  Stroke proxy does (Session::shown_stroke).
- stroke.set on a group skips images and symbol instances.
- document.inspect reports each object's strokeOptions (cap, join,
  miterLimit, align, dash, dashOffset, alignDashes, arrows, arrowAlign,
  profile) in stroke.set terms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant