Commit Graph
1214 Commits
Author SHA1 Message Date
aiongg 8d3b2b78da Merge upstream main f70f93de
Main's squashes of #510, #528, #420, #538 and #356 equal their PR heads; next has
all of them except the two maintainer merge commits a01bfcde (#538, ROADMAP only)
and 139e7c2e (#356: import-warning alert, malformed-URI assertion).

Conflict: ROADMAP.md: next's log lines (main's #538 line already in next)
Conflict: crates/doc/src/assets.rs: next's side (later same_file comment, Asset fields)
Conflict: crates/engine/src/cmd/datamerge/fill.rs: next's side (Asset with pdf_crop)
Conflict: crates/engine/src/cmd/file.rs: next's side (INDD description, Asset ..Default, crop box sizes)
Conflict: crates/engine/src/cmd/interchange.rs: next's side (INDD conversion warnings, resolve_pdf_crops, grep_style_warnings)
Conflict: crates/engine/src/cmd/links.rs: next's side (Asset ..Default)
Conflict: crates/engine/src/cmd/mathexpr.rs: next's side (Asset ..Default)
Conflict: crates/engine/src/cmd/media.rs: next's side (Asset ..Default)
Conflict: crates/engine/src/cmd/style.rs: next's side
Conflict: crates/engine/src/cmd/table.rs: next's side (Asset ..Default)
Conflict: crates/format/src/lib.rs: next's side (pdf_crop fields and tests)
Conflict: crates/idml/src/import.rs: next's side (linked_assets keyed by path, page and crop; CJK settings)
Conflict: crates/idml/src/tests.rs: both (main's file:/a%bé assertion added)
2026-10-12 01:57:47 +00:00
aionggandskylartaylor f70f93de44 fix(idml): report missing parts and show import warnings
Match IDML part names leniently, report missing parts, and show import warnings when opening a file. Cover the malformed URI crash with a regression test.

Validation: all six cargo xtask ci gates passed on the current main merge candidate; 1,176 native tests passed and all 15 WASM packages checked.
Hosted FreeBSD tests and Windows ARM64 packaging and install/run checks passed.

Task: #356

Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-11 19:39:34 -06:00
moppeeerandskylartaylor 95c8c9cc5b fix(hyphenation): honor capitalized-word settings for uppercase words
Honor the capitalized-word hyphenation setting for uppercase words and retain the current roadmap entries.

Validation: all six cargo xtask ci gates passed on the current main merge candidate; 1,170 native tests passed and all 15 WASM packages checked.

Task: #538

Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-11 19:32:49 -06:00
aiongg 223dedfe5a feat(assets): deduplicate files and omit unused assets on save
Share duplicate file data while keeping distinct link paths independent, and leave unused assets out of saved documents.

Validation: all six cargo xtask ci gates passed on the merge candidate; 1,170 native tests passed and all 15 WASM packages checked. Independent regression checks cover updates, relinking, embedding, undo and save/reopen.

Task: #420
2026-10-11 19:23:58 -06:00
aiongg ca1a8a12bc Place: an image placed into a frame leaves Auto-Fit off (#528)
* Place: an image placed into a frame fills it once and leaves Auto-Fit off

* Place: the fitting test names its fitting, since a placed image no longer auto-fits
2026-10-11 18:49:56 -06:00
japbcoelhoandClaude Opus 5.5 597f0e649f Color parsing: one scale per colour, not per component (#510)
A CMYK component of 1 or less was read as a fraction even when the other
components were percentages, so {"c": 0.7, "m": 0, "y": 12.2, "k": 0}
(a pale cream) became C 70 % Y 12.2 % and exported as
`0.7019608 0 0.12156863 0 k`. The same applied to RGB arrays.

Now a colour is read as percentages (0..100, or 0..255 for RGB) when any
component is above 1, and as fractions only when every component is
within 0..1.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:49:46 -06:00
aiongg cf22cbe081 Integration: Czech, German and Russian for Quit DesignCraft (#544 × cs/de/ru catalogs)
The catalogs that #544's branch doesn't have get the new menu label (machine-translated).
2026-10-12 00:39:55 +00:00
aiongg c0b28a4478 Merge quit-unsaved: quitting asks to save documents with unsaved changes (#544)
Conflict: apps/designcraft/src/native_menu.rs: next's MAC_APP_MENU loop without the Quit arm; menus.rs MAC_APP_MENU ends with a dc-quit Cmd row running app.quit (AppMenuItem::Quit removed)
Conflict: crates/ui-egui/src/lib.rs: DesignApp fields, initialisers and tests keep both sides
2026-10-12 00:38:50 +00:00
aiongg e3e8c44bd4 Merge upstream main 65ef027f 2026-10-12 00:38:22 +00:00
aiongg 6aada5b74a UI: quitting asks to save documents with unsaved changes (#544)
Closing the window or Quit (Cmd+Q, now a menu command instead of the predefined
terminate item) asks about each unsaved document: Save, Don't Save or Cancel.
The control channel's app.quit still quits without asking.
2026-10-12 00:37:32 +00:00
aiongg edaea097e8 Merge asset-dedupe: files with different paths stay separate assets (#420)
Conflict: crates/doc/src/assets.rs: same_file doc comment names both the PDF crop box (next) and the link (asset-dedupe)
2026-10-12 00:32:16 +00:00
aiongg 10546a6e66 Assets: files with different paths stay separate assets
Two linked files with identical bytes were merged into one asset, so updating, relinking or embedding one changed both placements and saves dropped one path. Assets now match only with the same link; identical bytes still share one buffer in memory.
2026-10-12 00:22:34 +00:00
aiongg 49d8d67ae0 Integration: format
rustfmt orders the fonts crate's modules after #536 (mod kind) joined next's mod mac_fonts.
2026-10-12 00:21:40 +00:00
aiongg 978a9b9b98 Merge #452: M6: Adopt craft-print and support Windows PDF printing
Conflict: crates/engine/src/cmd/print.rs: the PR's print_with/craft_print::submit; print_with and the test's expected bytes export through next's interchange::with_pdf_boxes
Conflict: Cargo.lock: next's lock plus only craft-print (the auto-merge had moved windows-sys back to 0.59/0.60 for several crates)
Conflict: Cargo.toml: craft-print entry moved beside craft-ui with a comment
Conflict: ROADMAP.md: status Change texts combined; both progress-log lines (the PR's 2026-10-11 line under the 2026-10-12 ones)
Conflict: docs/gaps.md: status Change texts combined
Conflict: docs/hardware-parity.md: status Change texts combined
2026-10-12 00:21:22 +00:00
aiongg fd21bc4f04 Integration: Properties › Transform rotate and flip buttons use the Control panel's icons (#541)
#541 adds rotate-cw, rotate-ccw, flip-h and flip-v icons for its Properties › Transform buttons; next's Control panel already draws the same actions with rotate-clockwise, tool-rotate, flip-horizontal and flip-vertical. The Properties buttons use those, and the PR's duplicate icon arms are removed so both panels show the same icons.
2026-10-12 00:19:29 +00:00
aiongg 30354c0a88 Merge #541: Rotation, shear, scale, rotate and flip in Properties › Transform
Conflict: ROADMAP.md: both progress-log lines
Conflict: crates/ui-egui/src/panels/properties.rs: tests keep next's panel(app) helper and Pathfinder test; the PR's transform test builds its harness through panel(app)
2026-10-12 00:18:50 +00:00
aiongg 6c8ba2d75d Merge #539: One underline bar per stretch of text, no seams between letters
Conflict: ROADMAP.md: both progress-log lines
2026-10-12 00:18:21 +00:00
aiongg d50f1b36d9 Merge #538: Words in capitals hyphenate like capitalized words
Conflict: ROADMAP.md: both progress-log lines
2026-10-12 00:17:58 +00:00
aiongg bbd6a6c277 Merge #537: Engine: report the selected text; remember recently used fonts
Conflict: crates/engine/src/cmd/text.rs: next's selection_attrs (mixed, typing format, mixed_para_attrs, link_style) with the PR's selectedText added to its output; both parameter descriptions
2026-10-12 00:17:43 +00:00
aiongg d83de14b7f Merge #536: Fonts: format, classification and PANOSE of each face, read without keeping fonts loaded
Conflict: crates/fonts/src/fontdb.rs: FontFace keeps next's family/style alias fields and the PR's kind
Conflict: crates/fonts/src/lib.rs: both mod mac_fonts (macOS) and mod kind
2026-10-12 00:16:58 +00:00
aiongg e8d568af98 Integration: Czech, German and Russian View submenu paths for the View menu (#527)
#527 moves Proof Setup, Rotate Spread and Separations Preview from Type to View and adds Screen Mode, Extras and Structure submenus; ja.rs follows it in the PR. cs.rs, de.rs and ru.rs (added on next) still had the Type/... keys, which the catalog tests report as stale. Their View/... rows join each catalog's existing translations of View and of the submenu names (machine-made, not reviewed by native speakers).
2026-10-12 00:16:31 +00:00
aiongg edf30ac0ff Merge #527: View items in the View menu, laid out like InDesign's
Conflict: ROADMAP.md: both progress-log lines
Conflict: crates/ui-egui/src/i18n.rs: both sets of rows
Conflict: crates/ui-egui/src/i18n/it.rs: both sets of rows (Presentation with next's)
Conflict: crates/ui-egui/src/menus.rs: the PR's View list (Rotate Spread, Screen Mode); next's Overprint Preview is already in it
2026-10-12 00:15:48 +00:00
aiongg 52d42ebdd0 Merge #525: Tint and Apply To in the Properties Fill and Stroke menus
Conflict: ROADMAP.md: both progress-log lines
Conflict: crates/engine/src/cmd/object.rs: object.fill takes the PR's swatch?/tint? form with next's known_swatch check (#520) on a given swatch; params doc names the swatch format; both test modules
Conflict: crates/ui-egui/src/i18n/it.rs: both sets of rows
Conflict: crates/ui-egui/src/panels/properties.rs: swatch_menu keeps the PR's popup (Apply To, Tint) with next's swatch_list for the swatches (its own width); tests keep next's Pathfinder test and the PR's three
2026-10-12 00:15:19 +00:00
aiongg d11ccad30a Merge #523: Parent-page items are composed for their page by index, not page name
Conflict: crates/pdf/src/export.rs: next's cycle guard (item -> item_guarded) and frame_objects (notes and cells) with the PR's page: Option<usize>; the PR's anchored-object loop dropped (frame_objects covers it)
Conflict: crates/render/src/lib.rs: stories keyed by (StoryId, Option<usize>) plus next's drawing_items; next's draw_item -> draw_item_inner guard with page: Option<usize>
2026-10-12 00:14:33 +00:00
aiongg 117420a829 Merge #522: Every command that writes story text reads CR as a paragraph return
Conflict: ROADMAP.md: both progress-log lines
Conflict: crates/engine/src/cmd/table.rs: next's setCell (StrokeEdit/EdgeSel, edit_table with ID) with the PR's text_param for the cell text
2026-10-12 00:12:48 +00:00
skylar taylor-barrick 65ef027f9f Merge pull request #452 from storytold/codex/craft-print
M6: Adopt craft-print and support Windows PDF printing
2026-10-11 18:12:43 -06:00
aiongg 059f9a40ef Merge #519: Corner Options keep curves and round every corner point
Conflict: ROADMAP.md: both progress-log lines
Conflict: crates/geom/src/corners.rs: tests keep next's radius_is_clamped_to_half_the_shorter_side and box_outline_rounds_only_closed_corners plus the PR's nearest, quarter_disc and three tests
2026-10-12 00:12:34 +00:00
aiongg aee3748be2 Merge #411: Undo: a command that runs another is one undo step
Conflict: crates/engine/src/guard.rs: next's snapshot tuple without revision (bump_revision on restore) + the PR's saved in_undo_step
2026-10-12 00:12:13 +00:00
aiongg 461598a149 Merge upstream main 66860bd1
Conflict: crates/engine/src/cmd/file.rs: next's pdfCrop/PdfCrop placement and trim-box test (next already has #511 with later work)
Conflict: crates/ui-egui/src/panels/mod.rs: next's Find/Replace Font row and swatch_list_tests (next already has #447)
2026-10-12 00:12:05 +00:00
aiongg 66860bd1de UI: Return and Escape in the font menu stay in the menu, never reach the dialog under it (#447)
Every font field's menu (Control bar, Contextual Task Bar, Properties > Character,
Character and Glyphs panels, Paragraph/Character Style Options, Find/Replace Font)
keeps its search focused and open on a click and filters as you type. In a dialog,
Return picked the highlighted family and also pressed OK, and Escape closed the
menu and cancelled the dialog: the menu now consumes the keys it uses. The
drawn font fields report themselves as combo boxes to screen readers.
2026-10-11 17:40:06 -06:00
japbcoelhoandClaude Opus 5.5 2b46ca664c Hyphenation: Portuguese text is hyphenated with hyph-utf8's Portuguese patterns (#512)
Text set in Portuguese ("Portuguese: Brazilian", "Portuguese", pt_BR) got
no hyphenation, so justified Portuguese columns could only stretch their
word spaces (up to 335 % of the normal space in a 56 mm column of 10 pt
Times).

Turn on hypher's "portuguese" feature, beside Spanish: hyph-pt.tex 1.4
(2024-07-13) from hyph-utf8, BSD-3-Clause, credited in NOTICE.
Lang::for_language already maps the Portuguese names and locale codes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:39:53 -06:00
japbcoelhoandClaude Opus 5.5 3dc0a1563a Place: PDF pages and SVGs keep their exact size (#511)
file.place sized a placed PDF page (and SVG) from its size rounded to
whole points, while the export draws the page into that size: a page of
91.774 x 613.276 pt became 92 x 613 and was drawn 0.25 % wider and
0.3 % shorter, so pieces laid edge to edge left gaps of up to 1.9 pt.
A 100.4 x 50.4 pt page placed 100.4 pt wide came out 50.2 pt tall:
`Rect { x0: 0.0, y0: 0.0, x1: 100.4, y1: 50.2 }`.

The graphic's natural size is now the exact page (crop box) or SVG size;
the rounded pixel size stays for display and preflight. place.load (the
place cursor) gets the same exact size.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:39:40 -06:00
skylar taylor-barrick 957890223a M6: Pin craft-print with native driver capability validation 2026-10-12 01:20:53 +02:00
moppeeerandClaude Opus 5.5 65ddf1f119 feat(ui): Rotation, shear, scale, rotate and flip in Properties › Transform
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>
2026-10-12 00:34:51 +02:00
moppeeerandClaude Opus 5.5 1e34026a79 fix(render): One underline bar per stretch of text, no seams
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>
2026-10-12 00:29:17 +02:00
moppeeerandClaude Opus 5.5 d6ddf749fe fix(compose): Words in capitals hyphenate like capitalized words
A word typed in capitals was never hyphenated, so a heading such as
FERRUM COMMODI UNTI moved the whole word to the next line where InDesign
breaks it (COM-MODI). Capital words now follow Hyphenate Capitalized
Words like words with a capital first letter: on by default, and turning
it off keeps both, acronyms included, whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 00:24:48 +02:00
moppeeerandClaude Opus 5.5 83584feb03 feat(engine): Report the selected text; remember recently used fonts
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>
2026-10-12 00:14:13 +02:00
moppeeerandClaude Opus 5.5 1009d59d26 feat(fonts): A family's kind without keeping it loaded
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>
2026-10-12 00:14:12 +02:00
moppeeerandClaude Opus 5.5 1ff2cda02b feat(fonts): Font format, classification and PANOSE for the font menus
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>
2026-10-12 00:14:12 +02:00
moppeeerandClaude Opus 5.5 15d2b998f0 fix(ui): Screen Mode checks the current mode; Japanese View submenu paths
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>
2026-10-12 00:09:46 +02:00
moppeeerandClaude Opus 5.5 60bf43b9e8 fix(ui): A tint keeps each object's swatch, and no stroke stays none
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>
2026-10-12 00:06:18 +02:00
moppeeerandClaude Opus 5.5 95a5317b0b fix(engine): note.edit reads CR as a paragraph return too
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>
2026-10-12 00:00:30 +02:00
moppeeerandClaude Opus 5.5 c6d2856688 fix(geom): Trim straight sides exactly for Corner Options
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>
2026-10-11 23:57:34 +02:00
Sean HammondandClaude Opus 5.5 5898c084b6 Parent-page composition: the page's name is part of the cache signature
Keying parent-page compositions by page index (previous commit) dropped the
page name from the cache key, and the signature only counts sections, so a
page-number marker on a parent page kept its old text after a section's
start number, style or prefix changed (renaming the page without changing
its index). The page's name is now hashed into the signature whenever a page
is given, so renumbering recomposes it as it did before, while two pages that
share a name stay separate.

Test: parent_page_number_follows_section_renumbering (marker on a parent
page, composed for page 3; the first section restarted at 100) fails before
(still "3", 1 glyph) and passes after ("102").

Reported by aiongg on #523.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
2026-10-11 21:17:42 +00:00
aiongg bfe6cf8518 Integration: format the Paragraph Style Options justification check (#531 × paragraph style sections)
The merge of #531 moved its style-dialog justification check into next's confirm_paragraph_style_options (from our paragraph style sections work); rustfmt wraps the moved line.
2026-10-11 20:51:10 +00:00
aiongg f5ee268962 Merge justification-dialog: a Justification dialog for the selected paragraphs (#531)
Conflict: ROADMAP.md: both progress-log entries, #531's above next's 2026-10-11 lines.
Conflict: docs/typography-parity.md: status line lists next's changes and the Justification dialog.
Conflict: crates/engine/src/cmd/text.rs: selection_attrs keeps next's typing-format chars and adds paraMixed for {mixed: true}; mixed_para_attrs sits beside next's apply_typing_format and link_style.
Conflict: crates/ui-egui/src/dialogs.rs: titles, draw and confirm arms for both paragraphLocal and justification; the style dialog's justify arm calls the shared justification(), which uses next's composer_choice (Japanese composers) and selects neither composer when mixed; the style dialog's justification check moved into next's confirm_paragraph_style_options (section set to justify, reason in next's status line); tests from both sides.
Conflict: crates/ui-egui/src/i18n/ja.rs: union of rows.
Conflict: crates/ui-egui/src/i18n/uk.rs: union of rows.
Conflict: crates/ui-egui/src/menus.rs: UI_COMMANDS, run_ui arms and Type menu keep next's Paragraph Borders and Shading, Span Columns and Bullets and Numbering plus Justification… (Cmd+Alt+Shift+J, free on next) right after Paragraph Rules…; menu_enabled keeps next's IME check before the type.para check.
Auto-merged crates/ui-egui/src/panels/properties.rs: Justification… joins the Paragraph panel menu list after Paragraph Rules….
2026-10-11 20:49:57 +00:00
aiongg 1a9499b465 Merge document-grid: View draws the document grid (#530)
ROADMAP.md: both progress-log lines
docs/target-app-parity.md: next's lines plus the document grid
2026-10-11 20:47:12 +00:00
aiongg 3f752312d6 Type: Justification dialog for the selected paragraphs (#531)
Type > Justification... and the Paragraph panel menu (Cmd+Alt+Shift+J) open
the Justification controls of Paragraph Style Options for the selected
paragraphs: word and letter spacing, glyph scaling, composer, kashidas and
Korean line breaks. Values that differ across the selection show empty, and
OK applies only the edited fields through type.para as one undo step.
Spacing values outside their range or out of minimum/desired/maximum order
keep the dialog open with the reason, in both dialogs.

type.selectionAttrs takes {mixed: true} and lists the paragraph attributes
that differ across the selected paragraphs as paraMixed.
2026-10-11 20:46:38 +00:00
aiongg 61504dae48 View: draw the document grid (#530)
Show/Hide Document Grid (View > Grids & Guides, Cmd+') draws the grid
on the positions Snap to Document Grid uses: subdivision and major
lines from each page's top-left corner, across the spread's band of the
pasteboard, behind or in front of page items as the grid settings say.
Dense lines are left out at low zoom. The Properties toggle runs the
command.
2026-10-11 20:46:38 +00:00
skylar taylor-barrick 3ec5cef6a2 M6: Adopt merged craft-print with scaling and queue duplex defaults 2026-10-11 22:14:24 +02:00