Layout > Numbering & Section Options now opens its own window instead of
the generated command form, on the section of the page in view: Start
Section (always on for page 1), Automatic Page Numbering or Start Page
Numbering at, and a Page Numbering group with Section Prefix, Style,
Section Marker and Include Prefix when Numbering Pages; then Document
Chapter Numbering with its style, Automatic Chapter Numbering, Start
Chapter Numbering at, Same as Previous Document in the Book (only in a
book) and the book's name. OK and Cancel sit beside the options, out of
the scrolling body.
OK runs layout.section and layout.chapterNumbering; a refused value
(a prefix over eight characters or with + or a comma, a start number
below 1) keeps the window open and changes nothing. Opening the window
reads the chapter numbering without running a command, so it doesn't
stop a Data Merge preview. New strings are translated (German, French,
Spanish, Japanese, Chinese, Italian).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A paragraph range inside a tracked change takes the change into its character
attributes, so the mark holds for its character ranges however their format is
built.
A column, frame or page break character that tracked changes delete, or a
hidden condition hides, no longer sends the next paragraph on. Deleted
paragraphs between a live break and the next paragraph don't stop the break.
Tests cover a deleted paragraph range inside a change, a deleted frame break in
both nestings, and a live break before a deleted paragraph.
Put the compact object groups inside the Control bar's existing sideways
scroll area, and give the painted captions (X:/Y:/W:/H:, icon captions,
Columns) and the Fill/Stroke chips accessible labels so tests and screen
readers find them. The Fill and Stroke chips open with nothing selected,
as before, so a popup opens at a scrolled control.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebased on the progress-docs restructure (#355): the ROADMAP bullets this
PR added moved to the inventory in docs/target-app-parity.md, and the
ROADMAP progress log gets a line for it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-up. Enter in the Save Document Preset popup created the
document and Escape closed the whole dialog: the dialog footer took
both keys while a popup was open. The dialog now leaves Enter and
Escape to an open popup (read before it draws, as egui closes a popup
on Escape that frame): Enter in the preset name saves the preset,
Escape closes only the popup. Clicking the name field no longer closes
the popup either (menus close on any click; this one only outside), and
the field takes focus when the popup opens.
Saved presets lived only in the UI state, so `file.new {preset: name}`
refused them. They are now engine preferences (saved with prefs.json):
`file.savePreset {name, …the file.new settings}` replaces a preset of
that name and refuses built-in names, `file.deletePreset {name}` removes
one, `file.presets` lists them after the built-in ones (`saved: true`),
and `file.new {preset}` makes documents from them by name. The Saved tab
reads and writes them through those commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File > New > Document now shows Recent, Saved, Print, Web and Mobile
tabs of page cards (drawn to the preset's proportions; double-click
creates) beside the preset's details: document name, width and height
with arrows, units, orientation, pages, start page #, facing pages,
primary text frame, columns and gutter, and collapsible margins and
bleed and slug per edge with link toggles. Save Document Preset keeps
presets by name; documents made are remembered for the Recent tab.
Small windows stack the details above the presets and scroll; the
layout mirrors for right-to-left languages. New strings go through the
translation tables (Italian, German, French, Spanish, Japanese, Chinese).
file.new takes intent, units, startPage and per-edge bleed and slug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebased on the progress-docs restructure: the ROADMAP bullet moved to the
inventory in docs/target-app-parity.md (Books), with a progress-log line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A section prefix is at most eight characters and contains no plus or
comma (page references and ranges use them); `layout.section` refuses
others and leaves the section unchanged. Symbols, a footnote style,
no longer number pages. The parameter documentation lists the 01, 001
and 0001 styles, and a test pins the fields the generated dialogs read
from both numbering commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A document's chapter number now has a style (1, I, i, A, a, 01, 001,
0001) and a source, as in Numbering & Section Options > Document
Chapter Numbering: Automatic Chapter Numbering (one more than the
previous document in the book; 1 first), Start Chapter Numbering at,
or Same as Previous Document in the Book.
`layout.chapterNumbering {style?, start?, source?}` sets them (undoable)
and, with no parameters, reports them with the open book that holds the
document. The book's Update Numbering (`book.paginate`) resolves chapter
numbers in book order and reports them. Chapter Number variables and
cross-reference chapter numbers use the style.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Straight sides were trimmed through inv_arclen at 1e-3 accuracy, so a
rectangle's corner points landed up to about 1e-4 pt off. Lines are now
measured and trimmed along the chord, exactly; curves still use arc length.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Corners were applied only where two straight segments meet, and every
other segment was redrawn as a straight line: a Pathfinder quarter
circle with rounded corners rendered as a triangle with one round
corner. Corner points are now where the path turns; the sides next to a
corner are trimmed along their length, curves included, and stay
curves. Smooth points are left alone; rectangles are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With several objects selected, InDesign's Properties panel shows
Pathfinder: Add, Subtract, Intersect, Exclude Overlap and Minus Back.
DesignCraft had them only in Object › Pathfinder and the Pathfinder
panel. The section sits after Align, with code-drawn icons.
Section titles and icon buttons in Properties now have accessible names
(the title; the button's tooltip), so screen readers can tell them apart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changing the Tint in the Fill menu sent the first object's swatch with
it, so with several objects selected every fill became that swatch; and
a Stroke tint on a frame without a stroke gave it the default 1 pt black
stroke.
object.fill now takes a tint alone and keeps each object's swatch, and
object.stroke with only a tint leaves a [None] stroke alone; the menu
sends just the tint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Fill and Stroke menus in Properties › Appearance have a Tint
field and, for a text frame, Apply To: Frame or Text. DesignCraft's
listed only the swatches, so a tint needed the Swatches panel and a
text frame's text colour needed a text selection.
The menus now have both: the tint applies to the fill or stroke of the
frame (object.fill / object.stroke) or of its text (type.char fillTint /
strokeTint); Apply To: Text colours the whole story. With text selected
the menu applies to the selected text, with its tint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
View › Screen Mode showed no check mark (checked() had no view.screenMode
arm), so with the Normal/Preview row gone nothing showed the current
mode. ja.rs still translated the old Type/Proof Setup, Type/Rotate Spread
and Type/Separations Preview paths; it now has the View/… paths,
Screen Mode, Extras and Structure included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rotate Spread, Proof Setup, Proof Colors, Flattener Preview, Show Tag
Markers, Separations Preview and Show/Hide Tagged Frames were at the end
of the Type menu. They are in View now, which follows InDesign's order:
Overprint Preview and proofing, zoom, Rotate Spread, Screen Mode,
Display Performance, rulers, Extras (frame edges, text threads), Grids &
Guides and Structure (tagged frames, tag markers). Show Hidden
Characters stays in Type, as in InDesign; W still toggles Preview.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The canvas drew an underline (and a strikethrough) as one rectangle per
glyph; where two anti-aliased edges met at a fractional pixel they left
a lighter seam between the letters. Contiguous bars of the same colour
and position are merged into one, as the PDF export already does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Properties › Transform shows, under X/Y/W/H, the rotation
and shear angles beside the X and Y scale, then buttons to rotate a
quarter turn either way and to flip horizontally or vertically.
DesignCraft's showed only X/Y/W/H; the rest was in the Control bar
and Object › Transform. The fields set totals through transform.set
around the reference point; the buttons run transform.rotate and
transform.flip. Rotate and flip icons are original drawings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In InDesign a double-click on the Tools panel's Fill or Stroke box opens
the Color Picker; DesignCraft opened the Swatches panel. It now opens
the Color Picker for that box, with the selection's colour (the selected
text's when text is selected). The Stroke box also reports its name to
screen readers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit > Step and Repeat opened the generic command form (Count 1..1000, Dx, Dy, Rows, Columns, Ids). It now has InDesign's dialog: Repeat (Count, or Rows and Columns when Create as a grid is on), Offset (Vertical, Horizontal, in the document's ruler units or any unit typed) and Preview, which shows the copies on the page while the dialog is open. Cancel, Esc and ui.dialog.cancel take the preview away; OK makes the copies once, as one undo step. A value that isn't a number keeps the dialog open and says so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Hyphenation Zone ("the white space allowed at the end of a
line of unjustified text before hyphenation begins") applies only with the
Single-line Composer. The Paragraph Composer, the default, weighs every
break of the paragraph instead. DesignCraft applied the default 3p0 zone
to both, so ragged paragraphs under the Paragraph Composer refused
hyphens InDesign makes. In LYH Studio's poster tutorial the placeholder
text breaks "aper-natem" and "mosticsia-tur"; ours ran a line longer.
The breaker now gets the zone only for unjustified Single-line Composer
paragraphs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
note.edit was the one story-text command still reading `text` without
text_param. The progress-log line held real CR and CRLF characters where
it meant to show the escapes; it reads `\r` and `\r\n` now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frame.create and text.insert turned \r and \r\n into paragraph returns,
but story.replaceRange, story.setText, note.new, footnote and endnote
text, type on a path and table cells kept the CR in the text, where it
drew as a missing glyph and joined the paragraphs. They all use
text_param now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Previews were kept in the context's data for each sample text, size
and colour, and never let go: every new text selection loaded textures
for every visible row. They now live in a cache of at most 256 that
drops the least recently used.
- A family the background read didn't list (installed since) was read
from disk on the UI thread every frame and never kept; it is now read
once and stored with the others.
- Return and Escape in a dialog's font menu are covered by #447's test
on main; this branch's duplicate is dropped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The class, Recently Added and Show Similar Fonts filters read every
family's kind through face(), which loads the family and keeps its bytes
for the session (with no size cap). They use family_kind now, which
reads each file and lets it go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Return, Escape and the arrows are consumed by the menu (Escape closes
it), so a dialog under the menu never confirms or cancels (#447).
- The class and Recently Added filters and Show Similar Fonts read every
family's kind on a background thread, once per document font scope;
the menu says Loading fonts... meanwhile. The web reads its few bundled
fonts inline.
- The colour font badge uses theme tokens instead of fixed colours.
- Every font field, the hand-drawn ones included, reports as a combo box
with the current family as its value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With few fonts installed the font's own row in the main list is on screen
too, so the label matched twice (FreeBSD CI).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The font menu (Control bar, Character panel, Properties, task bar, style
dialogs, Find Font, Glyphs) now has InDesign's layout:
- a search field with a clear button, and a Filters row: classification
(All Classes, serif, slab serif, sans serif, script, monospaced,
decorative, symbol), Show Favorites Only, Show Recently Added (fonts
added in the last 30 days);
- the sample text (Selected Text, Sample, Aa Bb Cc, a pangram, digits)
in three sizes, remembered with the UI state;
- Recently Used fonts at the top, then every family;
- a family of several styles shows how many and opens to list them, each
previewed in its own face; picking a style applies it as it is;
- each family's format after its sample, and Show Similar Fonts (≈) to
list the families of the same class nearest by PANOSE.
Find More and the activated-fonts filter are Adobe Fonts services and
are left out. The font combo is a field and a plain popup now: egui's
combo box kept its menu at the size it last had, so a family opening or
a filter clearing didn't show. The ≈ button stays while the pointer is
on it (the row under it no longer counts as hovered there). New strings
are translated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
type.selectionAttrs copied the whole selection to a string before taking
the first 60 characters, so selecting a long story copied all of it on
every query. It now skips leading blanks and stops after 60 characters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
type.selectionAttrs reports the start of the selected text on one line
(`selectedText`, up to 60 characters), for previews such as the font
menu's Selected Text sample. The preferences keep `recentFonts`, the
fonts last picked in the font menus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
type.selectionAttrs copied the whole selection to a string before taking
the first 60 characters, so selecting a long story copied all of it on
every query. It now skips leading blanks and stops after 60 characters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
type.selectionAttrs reports the start of the selected text on one line
(`selectedText`, up to 60 characters), for previews such as the font
menu's Selected Text sample. The preferences keep `recentFonts`, the
fonts last picked in the font menus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ScopedFonts::family_kind reads a family's format, class, PANOSE and file
date from its Regular face. A loaded face is asked; an installed family
that isn't loaded is read from its file, which is let go afterwards,
instead of loading every family the font menu's filters look at for the
rest of the session. Files over MAX_DOCUMENT_FONT_BYTES are skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each face reports what InDesign's font menu shows and filters by, read
once from its tables: its format (TrueType, OpenType/CFF, variable,
colour), its class (serif, slab serif, sans serif, script, monospaced,
decorative, symbol) from PANOSE, else the OS/2 IBM family class, else
the family name, else the shape of its "l" (serifs widen the foot), its
PANOSE numbers (with a distance for similar fonts) and when its file
was added.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paste Into gives a frame nested content, but it isn't a group: the Effects
panel showed "Group:" and enabled Isolate Blending and Knockout Group for
it. It now asks Item::is_group, so such a frame shows "Object:" with the
group options disabled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Effects panel had the blend mode, opacity and Drop Shadow only. Like InDesign's it now names the level the settings apply to with its blend mode and opacity (Group: Color Dodge 100%, Object: Normal 100%), and has Isolate Blending and Knockout Group, enabled for a selected group, through object.transparencyGroup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Probe reused connections before writing so an app restart does not lose the next call. Report connection failures as not reachable with nothing sent, while retaining uncertain outcomes and no replay after sending begins.
Add same-port restart and unavailable-app loopback regressions, and retain the lost-reply guard.
Validate caller-supplied character fills before merging selection attributes.
Deleted swatch names already retained in text no longer block New Style from
Selection; explicit unknown fills still fail without changing state.
Cover swatch creation, text formatting, deletion and style capture, including
non-fill overrides and explicit-fill rejection with fromSelection.
The DestIn mask now covers the whole render target (and the PDF's
exported area), with the gradient kept in item space through the paint
transform, since past the gradient's ends the end opacity carries on: a
child's long drop shadow or thick stroke is faded, not cut off at a box.
feather_bounds counts only shown children and active states, walking
nested groups without recursion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A gradient feather on a group (Gradient Feather tool over grouped text, as
in LYH Studio's poster tutorial) did nothing on screen: groups never went
through the effects path. In PDF the group's mask was the group's own path
bounds, and a group has no path, so the mask covered a box of zero size and
hid the group.
- Item::feather_bounds: the box the feather spans, the objects' bounds for
a group.
- Render: a feathered group draws its objects in one layer, then fades it
with the same mask as other objects (fx::gradient_feather_mask).
- PDF: the group's mask spans its objects.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A placed PDF, EPS or SVG under the Eyedropper matches attributes again,
as before, instead of failing with "no placed image under the point"
(Asset::is_raster, shared by the tool and color.sample). color.sample
hands its colour to object.color, which now colours selected text, the
text of selected frames ({text: true}), or the typing colour of an empty
story; a caret in existing text is refused before a swatch or undo step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Eyedropper on a placed image now does what InDesign does: with text
selected, clicking the photo colours the text with the image's colour under
the pointer; with objects selected, it fills them. The colour is an unnamed
colour (reused when the same colour is sampled again). Images on locked
layers can be sampled, and unfilled frames over the image let it show through.
- color.sample {at, spread?, target?: fill|stroke, ids?} samples the frontmost
visible raster image at a spread point; one undo step; a caret or a point
with no image is refused without an edit.
- object.color shares its swatch lookup with it.
- The Eyedropper tool sends color.sample over an image, matchAttributes
elsewhere as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The canvas reports a double-click on release (after the second Up), so the
handle double-click now fires from the mouse. Side handles map to the frame's
local axis through spread and frame rotation. Graphic frames honour the axis.
Locked frames and frames on locked layers are left alone. Text frames fit by
searching the frame height with its own columns and vertical justification,
so two columns stay two columns and Bottom/Center/Justify don't inflate it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>