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>
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>
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>
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>
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
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>
.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)
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
Save and Save a Copy put a picture of the first page in the .designcraft
zip as preview.png (320 px on the longer side). The start screen reads
only that entry and shows the last eight recent files as cards with the
picture and the name, below the community card. Files saved before have
a blank page until they are saved again.
The package fallback-font test writes its fixture without Save's preview:
drawing it before the document's fonts load pulled in a system font that
covers the test's characters (Unifont CSUR) ahead of the document's own.
InDesign draws a radial gradient in the object's bounding box: on a
non-square frame it's an ellipse reaching the frame's sides, and a
Gradient Swatch tool drag keeps those proportions. LYH Studio episode 6
(3:16) gives the left page's background a radial gradient: magenta in
the middle, cyan out to every edge. DesignCraft drew a circle reaching
only the longer side, so a portrait page stayed purple at its sides.
- doc: `Fill::radial_ellipse(bounds)`: centre and radii (default: the
box's centre and half its width and height; with a tool vector, its
start, and its length measured with the box made square).
- render: the radial paint is that circle, stretched by the paint
transform; PDF: the shading's transform does the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Swatches panel New Swatch takes what is current: a gradient
built in the Gradient panel becomes "New Gradient Swatch" (applied, and
listed), an unnamed colour a listed swatch, a selected named swatch a
"… copy". DesignCraft's button always added the same orange swatch, and
gradient swatches could not be created at all (LYH Studio episode 6,
2:12: "this is our Swatch … create a new swatch for it").
- engine: `swatch.new {swatch?, target?}` does the above for the
selection's fill (or stroke) or a named swatch; `swatch.create` also
takes `gradient: {kind?, stops: [{location, swatch | color, opacity?,
midpoint?}]}`, its stops taking colour swatches by name, as swatches
dragged onto the Gradient panel's stops.
- Swatches panel: New Swatch runs `swatch.new`, and with nothing
selected still adds a colour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening or saving a document moves it to the front of File › Open Recent
(no duplicates; Save a Copy and exports don't count). The submenu lists the
files by name with the full path as tooltip, then Clear Recent Files; the
start screen shows the last eight with their folders. A file that is gone is
dimmed and, when chosen, says so in an alert and stays listed (a disk that
isn't connected comes back). Preferences › File Handling sets how many are
kept (default 20, 0–100).
Engine: Prefs.recent_files / recent_files_max (saved in prefs.json),
file.openRecent {index}, file.recentFiles, file.clearRecent. UI:
app.openRecent; the macOS menu bar rebuilds the submenu when the list
changes.
- designcraft-color: ICC profiles (built-in RGB working spaces, user .icc files) go through
craft-cms from storytold/craft-libs. The default CMYK working space is craft-cms's Coated
FOGRA39; CMYK swatches show relative colorimetric with the settings' black point
compensation. Generic CMYK and Device CMYK stay selectable. A CMYK profile name resolves
through Builtin::stand_in_for; a name with no stand-in is an UnknownProfile error.
ColorSettings::with_known_profiles replaces unavailable saved names with the defaults; the UI
uses it when it restores saved settings at startup. Lab, gamut error and proofing of ICC CMYK
spaces use craft-cms transforms. The Generic CMYK output profile is encoded by craft-cms.
- designcraft-pdf: the PDF/X output intent is the working CMYK space's profile: the FOGRA39
built-in with identifier FOGRA39, user profiles as loaded, Generic CMYK otherwise.
- moxcms is no longer a direct dependency of designcraft-color.
- Open a file: missing IDML parts now open with an Import Warnings
alert in the release; drop the "not in a release yet" note.
- Place: an image placed into a frame leaves Auto-Fit off (0.7.0).
- Install, supported systems: add the 32-bit Windows x86 builds and
the RISC-V .deb and .rpm; example version 0.7.1.
- Set verified: 0.7.1 on every checked page.
- docs/user/CLAUDE.md: a regular file pointing to AGENTS.md instead of
a symlink.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The engine's atomic module keeps its functions and signatures and delegates to craft-libs/craft-atomic (pinned to e9546e19), so every save and export caller is unchanged. write_atomic_with also turns a panicking writer into an error, so its temporary file is removed. Recovery checkpoints and package output keep their own writers, which replace links instead of following them.
On Unix, new files follow the umask and replaced files keep their permissions.
Separable blend formulas work channel by channel, so the spread is drawn
twice through the ordinary renderer: C, M and Y complements into RGB, K
into a second raster, with the existing transparency groups, masks,
effects and parent-page placement. The inks are converted to sRGB once and
put over the paper. Two passes regardless of how many objects blend;
parent items, nested blends and effect blends (Multiply satin, shadows)
blend in CMYK too, and the pass covers the whole view, so blending
continues past the trim. An unchanged view is reused from a one-frame
cache (64 MiB cap). Spreads with Hue, Saturation, Color or Luminosity keep
the RGB-then-proof approximation. Effect blend layers sit outside their
clips and offscreen filters, so they see the object's backdrop (RGB too).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Preview checkbox beside Close and Create shows a document with the
window's settings in the workspace and rebuilds it as they change: size,
orientation, pages, facing pages, margins, columns, gutter, bleed and slug.
It is off by default and kept for the session. Fields that don't hold a
value yet, and sizes file.new refuses, keep the last preview.
The engine keeps the preview document (Session::preview_new_document,
end_new_document_preview): it replaces itself in its tab, takes no
Untitled number and is never written as recovery data. Create removes it
and makes the document with file.new, so it starts with a clean undo
history. Close, Escape, ui.dialog.cancel, turning Preview off or another
dialog replacing the window remove it and show the previously active
document again, unchanged.