Commit Graph
520 Commits
Author SHA1 Message Date
aiongg 1c1449c207 Merge #867: Liquid Layout panel (Auto-Fit, Object Constraints); Create Alternate Layout in the Layout menu
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/interactive.rs
2026-10-14 01:41:00 +00:00
aiongg a4b8ee994f Merge #866: Page tool: liquid pins and resize locks on the canvas for object-based pages
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/i18n.rs
#	docs/target-app-parity.md
2026-10-14 01:40:21 +00:00
aiongg 47b51d6377 Integration: #864 drops the Controlled by Parent rule from the menus and the Objects Move with Page checkbox (neither has an effect yet) 2026-10-14 01:39:08 +00:00
aiongg d0035c0722 Merge #864: Control panel for the Page tool (W/H, preset, orientation, Liquid Page Rule); Controlled by Parent; Show Parent Page Overlay
# Conflicts:
#	crates/idml/src/import.rs
#	crates/ui-egui/src/chrome.rs
#	crates/ui-egui/src/i18n.rs
2026-10-14 01:37:34 +00:00
aiongg f1f8aaa9f7 Merge #862: Page tool: click selects a page; its handles preview the liquid rule, Alt-drag resizes, Shift keeps proportions
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
#	crates/tools/src/lib.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/i18n.rs
2026-10-14 01:36:53 +00:00
aiongg fa511f80cd Merge #868: Page tool draws liquid guides from the rulers (dashed)
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/guides.rs
#	crates/ui-egui/src/canvas.rs
2026-10-14 01:33:37 +00:00
aiongg 063856cc4c Merge t14-b: #836 #840 #846 #854, Find/Change first:true
# Conflicts:
#	ROADMAP.md
2026-10-14 00:09:13 +00:00
moppeeerandClaude Opus 5.5 db19963bad feat(ui): the Page tool draws liquid guides from the rulers
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (11:00–
13:30) drags guides out of the rulers with the Page tool on a
guide-based page: "these guides are a little bit different... they are a
dashed line, a cyan dashed line" - liquid guides, which let the objects
they cross stretch with the page. DesignCraft drew liquid guides dashed
and applied them, but a guide could only become liquid through the
Liquid Layout panel's list: ruler drags always made ruler guides.

- canvas: with the Page tool, a page guide dragged from a ruler is a
  liquid guide; its preview is dashed while it's dragged.
- engine: guide.add takes `liquid`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:37:30 +02:00
moppeeerandClaude Opus 5.5 9da44a042f feat(ui): Liquid Layout panel in InDesign's layout; Create Alternate Layout in the Layout menu
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (2:47,
7:24) uses the Liquid Layout panel: "Liquid Page Rule:" with "Page: n",
Content › Auto-Fit, and Object Constraints › Resize with Page (Height,
Width) and Pin (Top, Left, Bottom, Right), greyed until an object on an
object-based page is selected. DesignCraft's panel had a "Page 1" label,
the rule, six wrapped checkboxes ("Resize width", "Pin top"…) only once
an object was selected, and a Create Alternate Layout form.

- Liquid Layout panel: InDesign's layout and labels; the page is the one
  the Page tool selected (else the page in view); Auto-Fit (graphic
  frames) runs object.fittingOptions; the constraints apply on
  object-based pages (also through Controlled by Parent) and stay
  greyed otherwise. The page's liquid guides stay listed below for now.
- Layout menu: Create Alternate Layout… (as in InDesign).
- Translations for the new labels.

Builds on #864 (rule list, Controlled by Parent) and #862.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:29:44 +02:00
moppeeerandClaude Opus 5.5 8f71219533 feat(tools): Page tool pins and locks objects on object-based pages, on the canvas
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (6:32–
9:58) clicks an object with the Page tool on an object-based page and
gets InDesign's on-canvas liquid controls: a pin outside each edge
("Object is pinned relative to the page edge. Click to release.") and a
padlock on the width and height lines ("The object's width is locked.
Click to let the object change width as the page changes width."). The
pins and resize settings existed (liquid.object, the Liquid Layout
panel) but the canvas showed none of it.

- tools: on an object-based page a Page tool click selects the object
  with its page (layout.selectPage takes `ids`); its pins (14 px outside
  each edge's middle) and width/height locks (beside the centre) toggle
  liquid.object on click, show InDesign's tooltips on hover and a hand
  cursor.
- canvas: LiquidPins (orange dashed width/height lines with padlocks,
  open when the object follows the page; hollow pins, or a line to the
  page edge when pinned) and Tip overlays; tooltip translations.

Builds on the Page tool PR (#862).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:21:51 +02:00
aiongg 6692e061d6 Merge t14-c: #839 #843
# Conflicts:
#	ROADMAP.md
2026-10-13 22:51:48 +00:00
moppeeerandClaude Opus 5.5 59b6125af1 feat(ui): Control panel for the Page tool; Controlled by Parent; Show Parent Page Overlay
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (1:02–
2:06, 13:47) sizes pages from the Control panel with the Page tool
selected: X/Y, W/H, the page-size preset ("US Business Card"),
orientation, Liquid Page Rule ("Controlled by Parent"), Objects Move with
Page and Show Parent Page Overlay. DesignCraft's Control panel showed the
(empty) object controls.

- ui: with the Page tool, the Control panel shows the selected page (or
  the page in view): the reference point (W/H, preset and orientation
  keep it in place via layout.pageSize's anchor), X/Y (read-only),
  W/H, the preset dropdown, portrait/landscape, Liquid Page Rule, Objects
  Move with Page (always on: pages don't move within spreads yet) and
  Show Parent Page Overlay.
- doc: LiquidRule::ControlledByParent (the parent page's rule, Off
  without one; resolved by liquid::effective_rule); Page.show_parent_overlay.
- engine: layout.pageOptions {pages, showParentOverlay}; liquid.pageRule
  takes controlledByParent.
- canvas: the parent page's size over a page with the overlay on.
- Liquid Layout panel and Control panel share InDesign's rule list
  (Off, Scale, Re-center, Object-based, Guide-based, Controlled by
  Parent); "US Business Card" preset; translations.

Builds on the Page tool PR (#862) for the selected page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:51:47 +02:00
aiongg b9cbfca8cf Merge #843: Placed PDFs: render with pdfcraft's patched hayro crates
# Conflicts:
#	Cargo.toml
#	ROADMAP.md
#	crates/render/src/lib.rs
2026-10-13 22:38:19 +00:00
aiongg 450bee203a Merge #859: Control: bound click and drag input before queuing events 2026-10-13 22:36:03 +00:00
aiongg b98d1521df Merge #855: fix: repaint canvas when entering and leaving parent editing 2026-10-13 22:35:26 +00:00
aiongg 9ceb7011a5 Merge #840: Object > Fitting with the reference shortcuts
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/menus.rs
2026-10-13 22:34:54 +00:00
aiongg dc2dda7717 Merge #836: gradients between process colours blend as inks
# Conflicts:
#	ROADMAP.md
2026-10-13 22:31:16 +00:00
moppeeerandClaude Opus 5.5 cc13e80c9d feat(tools): Page tool selects pages; handles preview the liquid rule, Alt-drag resizes
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (0:42–
2:06) selects a page with the Page tool, gets its bounding box with
handles, drags a handle (the page springs back: a liquid-rule preview),
holds Option to really resize it, Shift for proportions, and reads the
size in a tooltip by the cursor. DesignCraft's Page tool only opened a
generic Page Size dialog on click.

- tools: the Page tool selects the page under a click (none on the
  pasteboard); the selected page shows its outline, eight handles and
  its liquid page rule ("Scale", "Object-Based"…) above it. Dragging a
  handle previews layout.pageSize (the liquid rule re-flows the
  objects) and springs back on release; Alt resizes, Shift keeps the
  proportions; a W/H readout follows the pointer; resize cursors on the
  handles. Double-click a page for the Page Size dialog.
- doc: Selection.page (the Page tool's page); engine: layout.selectPage
  (no undo step).
- layout.pageSize `anchor` (0-8): the page grows away from the
  reference point and its objects and guides keep their place relative
  to it (a handle drag anchors the opposite edge); liquid rules work
  from that.
- canvas: PageHandles and Tag overlays; translations for the tags and
  the Resize Page undo label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:29:55 +02:00
Andreas Haraminac 5024ed8870 #732: bound control-channel click and drag event queues 2026-10-13 21:55:44 +00:00
harrisonoconnorhover 2d07bc5295 fix: refresh canvas when switching parent editing 2026-10-13 17:28:38 -04:00
aiongg e19b6b1fd9 Merge toc-dialog: Table of Contents dialog, entry options and IDML TOC styles (#755)
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests_idml.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/dialogs.rs
2026-10-13 20:44:30 +00:00
aiongg 129adfa429 Layout: Table of Contents dialog with entry styles, page number position and IDML TOC styles (#755) 2026-10-13 20:41:56 +00:00
aiongg d5c26cc781 Merge t13-commands: #764 #757 #802 #803
# Conflicts:
#	crates/engine/src/cmd/object.rs
2026-10-13 20:28:49 +00:00
aiongg b9060d0350 Merge #803: Refuse command params the description doesn't name
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/file.rs
#	crates/engine/src/cmd/mod.rs
#	crates/engine/src/cmd/object.rs
#	crates/engine/src/cmd/prefs.rs
#	crates/engine/src/cmd/table.rs
#	crates/engine/src/lib.rs
2026-10-13 20:13:51 +00:00
aiongg 16c2ac46c6 Merge #829: Polish UI language
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/chrome.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
#	docs/localization-parity.md
#	docs/target-app-parity.md
2026-10-13 20:06:53 +00:00
aiongg c6921a77cb Merge #802: File › Open Recent: recent documents in the menu and on the start screen
# Conflicts:
#	ROADMAP.md
#	apps/designcraft/src/native_menu.rs
#	crates/engine/src/cmd/file.rs
#	crates/engine/src/cmd/mod.rs
#	crates/engine/src/cmd/prefs.rs
#	crates/engine/src/lib.rs
#	crates/format/src/lib.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/menus.rs
#	docs/target-app-parity.md
2026-10-13 20:06:29 +00:00
aiongg 7f0d7f1f32 Merge t13-moppeeer: #253 #832 #753 #754 (a3b97165) #588
# Conflicts:
#	ROADMAP.md
#	crates/idml/src/tests.rs
2026-10-13 19:57:37 +00:00
aiongg 6ec31fde95 Merge #764: Swatches: dropping an .ase file on the window loads its swatches
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/lib.rs
2026-10-13 19:56:32 +00:00
dotCooCoo 7a89954937 Placed PDFs: render with pdfcraft's patched hayro crates
Placed PDFs rendered through hayro 0.7 from crates.io, whose
hayro-interpret divides integers in calculator functions without a
check, does not limit how deep functions nest and samples each mesh
triangle over its whole bounding box. A placed PDF whose calculator
function runs `1 0 idiv` or `-2147483648 -1 idiv` panicked the render.
A chain of 100,000 functions, each stitching function naming the next,
overflowed the stack and aborted the process. Mesh shadings with points
far off the page, ten thousand overlapping triangles or forty thousand
patches ran for over a minute or passed 2 GiB of memory.

[patch.crates-io] now takes hayro, hayro-interpret, hayro-syntax and
hayro-jbig2 from pdfcraft's vendor/ directory at b5467d93, with the
patches its vendor/README.md lists. The crate versions do not change.
The patched hayro-syntax sizes a page with a /UserUnit in points, and
pdf_page_box scales the page's boxes by the same unit, so with Crop to
the frame still shows the chosen box. NOTICE names the new source and
the licenses. The function and mesh tests in
crates/render/tests/placed_pdf.rs follow pdfcraft's tests in
crates/render/src/raster.rs.
2026-10-13 12:52:10 -07:00
aiongg 6039be0526 Merge #588: CMYK blend space: blend modes blend in CMYK on screen
# Conflicts:
#	ROADMAP.md
#	crates/render/src/fx.rs
#	crates/render/src/lib.rs
2026-10-13 19:37:18 +00:00
moppeeer 58b9950fb6 feat(effects): Inner Glow mode and technique; Basic Feather choke and corners
InDesign's Effects dialog sets an Inner Glow's blend Mode (Screen by
default) and Technique (Softer or Precise), and a Basic Feather's Choke
and Corners (Sharp, Rounded, Diffused). LYH Studio episode 14 shows them
at 12:05–12:20 (Screen 75 %, Softer, 0.25 in; 0.0625 in, Diffused).

- doc: InnerGlow.mode and .technique (GlowTechnique), Effects.
  feather_options (FeatherOptions: choke %, FeatherCorners), with
  InDesign's defaults; old documents read as before.
- render: the glow uses its mode; Precise keeps it nearer the edge; the
  feather's choke shortens the fade, Sharp and Rounded corners follow
  the shape more tightly or softly than Diffused (unchanged, so the
  goldens stay).
- render fix: an inner glow's (and a bevel's) blend mode was applied
  inside the clip layer, against its empty backdrop, so Screen and
  Multiply acted as Normal; the blend layer now wraps the finished edge
  and mixes with the object below.
- engine: choke clamped to 0–100; the params documented.
- Effects dialog: Mode and Technique on Inner Glow; Choke and Corners on
  Basic Feather; strings translated.

Builds on #643 (the Effects dialog).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit a3b971654f)
2026-10-13 19:33:40 +00:00
aiongg 1907d14699 Merge #753: Text Frame Options laid out as InDesign's: columns type and width, inset link, Ignore Text Wrap, Baseline Options 2026-10-13 19:31:44 +00:00
aiongg 1847b8cef5 Merge #825: Gradient swatches on text, laid across the text frame
# Conflicts:
#	ROADMAP.md
#	crates/pdf/src/export.rs
#	crates/pdf/src/text.rs
#	crates/render/src/text.rs
#	docs/target-app-parity.md
2026-10-13 19:30:47 +00:00
aiongg 42f000e95a Merge #832: Window menu in InDesign's order; Window > Workspace with Essentials Classic
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/chrome.rs
#	crates/ui-egui/src/dock.rs
#	crates/ui-egui/src/menus.rs
2026-10-13 19:28:59 +00:00
aiongg f60eb24656 Merge #823: Gradient strokes: on screen, in PDF, in IDML and the Gradient panel
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/object.rs
#	crates/engine/src/cmd/style.rs
#	crates/idml/src/tests.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/uk.rs
#	crates/ui-egui/src/panels/swatches.rs
#	docs/target-app-parity.md
2026-10-13 19:28:11 +00:00
aiongg da8aaa9cdc Merge #826: Gradient panel layout; drop swatches from the Swatches panel onto its stops
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/panels/swatches.rs
#	docs/target-app-parity.md
2026-10-13 19:25:12 +00:00
aiongg fce28331ec Merge #763: New Swatch names a gradient "New Gradient Swatch"; gradient swatches from colour swatches
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/style.rs
#	docs/target-app-parity.md
2026-10-13 19:23:33 +00:00
aiongg 9d5d341a7d Merge #765: Radial gradients stretch with the object's box (an ellipse) 2026-10-13 19:21:58 +00:00
moppeeerandClaude Opus 5.5 08386d03b1 feat(ui): Object > Fitting with InDesign's shortcuts
LYH Studio episode 6 (7:00) fills its photo frames with the caption
"Fit Content to Frame (Ctrl + Shift + Alt + C)", InDesign's shortcut for
Fill Frame Proportionally. DesignCraft's Fitting items were object.fit
variants without shortcuts (a menu shortcut belongs to a command id, and
the five modes share one).

- Five UI commands, one per mode, with InDesign's keys:
  fit.fillFrameProportionally Cmd+Alt+Shift+C,
  fit.contentProportionally Cmd+Alt+Shift+E, fit.frameToContent
  Cmd+Alt+C, fit.contentToFrame Cmd+Alt+E, fit.centerContent
  Cmd+Shift+E (Ctrl on Windows and Linux); each runs object.fit.
- Object > Fitting lists them (with their shortcuts), enabled as
  object.fit is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:15:35 +02:00
aiongg b4f7286482 Merge text-autosize: opening a file keeps its auto-size frame sizes (#632)
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/interchange.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-13 18:40:15 +00:00
aiongg 935741d47c Text frames: opening a file keeps its auto-size frame sizes 2026-10-13 18:40:01 +00:00
moppeeerandClaude Opus 5.5 dc712baeca fix(color): gradients between process colours blend as inks, as InDesign shows them
LYH Studio episode 6 builds every gradient from C=0 M=100 Y=0 K=0 to
C=100 M=0 Y=0 K=0. InDesign blends a gradient's process stops as inks:
halfway is C 50 M 50, a light lilac. DesignCraft converted both ends to
RGB and blended there, so the middle came out a darker violet (117, 88,
189 instead of 135, 119, 181), and every Episode 6 gradient looked
different. A midpoint between CMYK stops also became an RGB colour, so
the PDF shading turned RGB with a conversion warning.

- color: `Color::lerp` blends CMYK with CMYK (or grey), and grey with
  grey, in ink space; anything with RGB still blends in RGB.
- `Gradient::display_stops`: the expanded stops plus samples through
  each span that isn't RGB at both ends, for renderers that interpolate
  in RGB; the screen renderer uses it.
- pdf: a midpoint's expanded stop now keeps the stops' space; the
  colour-space test expects no conversion for CMYK or grey midpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:38:38 +02:00
moppeeerandClaude Opus 5.5 0a34316b82 feat(ui): Window menu in InDesign's order; Window > Workspace with Essentials Classic
LYH Studio episode 6 starts with "Window > Workspace > Essential
Classic" and opens panels with "Window > Color > Gradient & Swatches".
DesignCraft's Window menu had no Workspace or Color submenu (panels sat
in one "Panels" list) and no Essentials Classic workspace.

- Window menu: Arrange, Workspace, then the panels alphabetically with
  InDesign's groups (Color: Color, Gradient, Swatches; Editorial;
  Interactive; Object & Layout; Output; Styles; Type & Tables;
  Utilities). Every panel stays reachable; Next/Previous Document moved
  into Arrange.
- Window > Workspace: the built-in workspaces as "[Essentials]", the
  current one checked, Reset <current>, New Workspace. The app bar's
  switcher uses the same list and order.
- Essentials Classic: the Control panel, no Properties stack, and an
  icon column of named panel groups ([Pages, Layers, Links] [Stroke,
  Color] [Swatches] [Effects] [Paragraph] [Text Wrap] [Character
  Styles, Paragraph Styles] [Gradient]); Window > Pages opens Pages
  from its group. Saved workspaces keep the groups.
- Flyouts and floating panels name Pages, Layers and Properties.
- Translations for Editorial, Object & Layout, Styles and Essentials
  Classic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:16:51 +02:00
moppeeerandClaude Opus 5.5 bdf66d7749 feat(ui): Gradient panel in InDesign's layout; swatches drop onto its stops
LYH Studio episode 6 (1:36-2:05) builds its gradient in the Gradient
panel: it drags C=0 M=100 Y=0 K=0 from the Swatches panel onto the left
stop, drops C=100 M=0 Y=0 K=0 on the ramp (a new stop at 68.636 %), then
drags the black stop off. DesignCraft's Gradient panel took no swatches,
showed only a hint until the fill was a gradient, and laid out its
fields differently.

- Gradient panel: InDesign's layout (thumbnail; Type; Location % and
  Angle; Reverse; the ramp with midpoint diamonds above and stops below).
  Until the fill is a gradient it shows the default White -> Black ramp;
  clicking the thumbnail or using the ramp starts one. Midpoints drag
  and take a Location. A stop's colour picker moved to its right-click
  menu, so selecting a stop no longer grows the panel.
- Swatches panel rows are drag sources (the chip follows the pointer):
  dropped on a stop a swatch colours it, elsewhere on the ramp it adds
  a stop there.
- Stops keep their colour model through panel edits (CMYK used to turn
  into hex RGB whenever a stop moved).
- engine: `object.gradient` stops accept `swatch` (its colour; gradient
  swatches and [None] are refused) and colours accept `{gray}`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:02:45 +02:00
moppeeerandClaude Opus 5.5 ac54c8faf7 feat(text): gradient swatches on text, laid across the frame as in InDesign
LYH Studio episode 6 (8:28) gives the "1969" headline the "New Gradient
Swatch" (magenta → cyan) from the Swatches panel. InDesign runs a gradient
on text across its text frame's box. DesignCraft resolved a character
fill to one solid colour, so a gradient swatch drew no text at all.

- render: a character fill or stroke that names a gradient swatch is
  painted with that gradient over the frame's box in text space (type on
  a path: the path's box).
- pdf: text runs take a gradient paint: the shading is laid out in the
  frame's text space and mapped into each run's origin, so skew and
  horizontal scale don't bend it; outlined runs and type on a path too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:30:55 +02:00
Tomasz LewandowskiandClaude Opus 5.5 226991cb28 i18n: add Polish interface language
Adds a Polish catalog (i18n/pl.rs, 1,698 strings), registers Polski in
Edit › Interface Language, uses category-first count captions for Polish
(as for Ukrainian) and adds catalog and language-switch tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DukHNvUY45rjRnvtz91x33
2026-10-13 19:16:32 +02:00
moppeeerandClaude Opus 5.5 370dca2ca2 feat(render): gradient strokes, on screen, in PDF and in the Gradient panel
A gradient swatch on a stroke drew nothing: strokes were painted with a
single resolved colour. LYH Studio episode 6 gives the loop on the right
page (9:13) and, at first by accident, the circle (1:19, "right now it
is on the stroke") a gradient stroke.

- doc: Stroke::gradient_angle / gradient_vector (as Fill's) and
  Stroke::as_fill(), the stroke's paint as a fill.
- render and PDF: a gradient stroke is painted like a gradient fill,
  across the path's box (dash gaps and arrowheads keep their paints).
- engine: object.gradient {target: stroke} edits the stroke's
  gradient (kind, stops, angle, the Gradient Swatch tool's from/to);
  scaling moves the stroke's vector with the shape.
- IDML: GradientStrokeStart/Length/Angle round-trip.
- Gradient panel: acts on the stroke when the toolbox's Stroke box is
  in front, as InDesign's follows the Fill/Stroke proxy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:11:58 +02:00
aiongg 7ad3d12883 Merge indd-import: open .indd and .indt files through indd-utils 2026-10-13 16:18:53 +00:00
aiongg a7c3e330ec INDD: open .indd and .indt files through indd-utils (#21, #114)
.indd and .indt documents open through File › Open, drop, the web inbox,
file.open, file.openBytes, file.openIdml and the CLI. The engine converts
them to IDML in memory with storytold/indd-utils (pinned by rev, MIT OR
Apache-2.0, no dependencies, builds for wasm) and imports the result
through the existing IDML path. The converter's warnings come first in the
open result's `warnings`, before the IDML importer's and the font
warnings. A file the converter can't read is an open error, shown in the
Can't Open the File alert.

Routing: a path or name ending in .indd/.indt, or bytes starting with the
INDD signature (the web inbox passes the name without its extension).
opens_as_document and the desktop and web Open dialogs list indd/indt.

Tests use synthetic bytes only: signature-bearing junk, a zero-filled
.indd and a short .indt all fail as open errors with no document added;
a dropped unreadable .indd raises the open alert.

(cherry picked from commit bb8a6a23fa)
2026-10-13 16:15:15 +00:00
Gert Pellin 68596ea696 Refuse command params the description doesn't name
Callers from outside the app now get a parameter error for a key a
command's params description doesn't name, instead of the command
running with its defaults: `text.select {story, start, end}` and
`style.list {bogus: 1}` are refused with "unknown parameter `…`" and the
nearest or the accepted keys.

- engine: `cmd::params` (ported from VectorCraft #1442) reads the keys
  from each params description; `check_params` / `check_keys`.
  `Session::execute` itself stays lenient so old journals replay; in the
  engine's own tests it checks too, as the audit of the descriptions.
- MCP: tools/call answers -32602 for an argument a tool doesn't take and
  for params a command doesn't take (`execute`, every `batch` step before
  the first runs); the headless backend checks as well.
- Control channel (`engine.execute`) and `designcraft-cli run --cmd`.
- Descriptions now name every key their commands read (table target
  cells, anchored objects, gap.move, file.place, data merge, prefs.set,
  …); type.char / type.para stay unchecked (their attributes may be the
  params object itself; the setters refuse unknown attributes).
- Tests that passed keys the commands never read are fixed, and the pen
  tool no longer sends the unread `notifyPen`.

Fixes #776
2026-10-13 17:25:27 +02:00