Commit Graph
112 Commits
Author SHA1 Message Date
aiongg 3ac3bc90de Merge main (0.7.1): atomic saves, recovery per instance, quit keeps documents when cancelled
Conflict: crates/engine/src/atomic.rs: main's side (the reviewed #485 code supersedes the PR head on next)
Conflict: crates/engine/src/recovery.rs: main's #506 code, with next's write_entry helper kept
Conflict: apps/designcraft/src/profile.rs: main's own_run returning Option (and_then), with next's portable root_with argument
Conflict: crates/ui-egui/src/lib.rs: main's QuitState quit flow (d020b4e8) over the #545 head; next's Find Font alert guard; one import_warning_tests module (next's, with the Find Font test)
Conflict: apps/designcraft/src/native_menu.rs: next's MAC_APP_MENU layout, which already has the dc-quit item running app.quit
Conflict: ROADMAP.md: next's header with the quit change added; next's log entries then main's three
Conflict: docs/target-app-parity.md: main's atomic save, recovery and quit lines
2026-10-12 17:14:07 +00:00
Brandon ThomasandClaude Opus 5.5 3624f48819 Release 0.7.1: rebuild with the fixed shared release workflow
The previous release build failed in craft-common-actions, not in this
repo: riscv64 packaging got --formats deb,rpm,tar (fixed in
craft-common-actions#3), Linux jobs lacked the ALSA headers
(craft-common-actions#5), and Windows signing needed the AZURE_* secrets
listed in the caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:11:06 -04:00
aiongg 40e7b1fed7 Merge upstream main 33842244 2026-10-12 12:23:26 +00:00
Brandon ThomasandClaude Opus 5.5 3384224419 Release prep: 0.7.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:44:24 -04:00
aiongg 89abf6b6c9 Merge #84 (update): Text editing, snapping and text threading (#23)
Review fixes for text editing, paste and threading (fix84-text,
fix84-thread), the Italian/Japanese/Portuguese/Ukrainian Swatches hint
and #83's update merged into the PR branch.

Conflict: ROADMAP.md: header combines #84's threading change with next's 2026-10-11 changes; progress lines and change-log rows both (#84's 2026-10-12 first); stage line #84's (alpha ~5–7 h away)
Conflict: docs/gaps.md: #84's header text plus next's kerning/fonts/print changes
Conflict: docs/roadmap.md: next's M1 row (#186 done), #84's M2 row
Conflict: crates/engine/src/cmd/style.rs: next's side; add_to_swatches calls next's Document::rename_swatch_refs, #84's rename_in_story/rename_in dropped (next's covers text, tables, cells, notes and items); #84's test kept
Conflict: crates/idml/src/tests.rs: next's side (#84 carries #83's tests.rs, already merged in 9196a164)
Conflict: crates/tools/src/select.rs: overlays keeps next's content-move ghosts and live corners, plus #84's snapped loaded-cursor drag frame; a Place click without a drag shows nothing
Conflict: crates/ui-egui/src/i18n/it.rs: next's side (the Swatches hint entry is already further down)
2026-10-12 04:20:34 +00:00
aiongg 7b803f1ddc Text: double-click word selection keeps grapheme clusters whole 2026-10-12 03:58:28 +00:00
aiongg 0fae2e4b5a Merge #83 into feat/text-editing-and-frames
Conflict: ROADMAP.md: took #83's (main's restructured roadmap); the Threading inventory line goes into docs/target-app-parity.md
Conflict: crates/compose/src/lib.rs: kept this branch's undrawn trailing spaces after warichu; comment covers both the spaces and the drop cap
Conflict: crates/idml/src/tests.rs: took #83's (drop cap style as a Dropcap nested style, table style fills through the cascade); this branch has no changes of its own there
2026-10-12 03:31:39 +00:00
aiongg 0032d57525 Merge upstream main into feat/layout-parity
Conflict: ROADMAP.md: took main's restructured roadmap; this branch's inventory changes (Keep Lines Together default, IDML defaults, drop caps, IDML Kashidas) go into docs/target-app-parity.md, where the inventory lives now
Conflict: crates/format/src/lib.rs: load runs the format upgrade, then merges duplicate assets; kept both sets of tests
2026-10-12 03:24:27 +00:00
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
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
skylar taylor-barrick 957890223a M6: Pin craft-print with native driver capability validation 2026-10-12 01:20:53 +02:00
skylar taylor-barrick 3ec5cef6a2 M6: Adopt merged craft-print with scaling and queue duplex defaults 2026-10-11 22:14:24 +02:00
aiongg a5326169f5 Integration: indd-utils 867c967a 2026-10-11 18:03:53 +00:00
aiongg 68974c0d7d Integration: indd-utils bff0fd4d 2026-10-11 16:37:23 +00:00
aiongg b6cc59d349 Merge wrap-boundary: IDML: import and wrap around custom text-wrap boundaries
Conflict: crates/compose/src/lib.rs: the custom boundary goes into next's shared wrap_exclusion(); free_slots keeps next's JumpObject handling outside it and takes the branch's combined BoundingBox/Contour arm
Conflict: crates/engine/src/cmd/object.rs: params doc has next's content flag and the branch's custom-boundary note
Conflict: crates/engine/src/tests.rs: both tests
Conflict: crates/idml/src/export.rs: the boundary goes into next's text_wrap_pref()
Conflict: crates/idml/src/import.rs: next's object-style-aware text_wrap() plus the branch's boundary parsing for the item's own wrap; pdf_page_in and wrap_path_of both kept
Conflict: crates/idml/src/tests.rs: both sides' tests
2026-10-11 13:08:12 +00:00
aiongg 47d17ca6f5 IDML: import and wrap around custom text-wrap boundaries 2026-10-11 12:53:50 +00:00
skylar taylor-barrick 9f7da3f6ab M6: Adopt craft-print for CUPS and Windows PDF printing 2026-10-11 07:29:54 +02:00
aiongg e828cd6c13 Integration: indd-utils at 08c6b78b 2026-10-11 05:19:21 +00:00
aiongg 2fae23fcc6 Merge atomic-save: MCP: exported files replace the target atomically (#436)
Conflict: ROADMAP.md: both progress-log entries, next's newer ones first
Conflict: apps/designcraft/src/gpu.rs: next's side; the branch's test fix targets the startup record tests next replaced
Conflict: apps/designcraft/src/main.rs: next's gpu startup and macOS IME helper; config_dir() dropped for the branch's profile::config_dir(), recovery_dir from profile::recovery_dir()
Conflict: crates/ui-egui/src/canvas.rs: next's guard (menu_open, keyboard_pane already limits keys to the focused pane)
Conflict: crates/ui-egui/src/lib.rs: modules from both sides
2026-10-11 05:16:10 +00:00
aiongg ff34ad3d14 Integration: INDD import follows indd-utils main
The indd dependency tracks indd-utils' main branch; Cargo.lock pins 68308f6f021a58901e82db4659705b8b96939b3b (was 9cf456d9). The API is unchanged: designcraft-engine builds as it was.
2026-10-11 02:33:11 +00:00
aiongg f12b3443a0 Merge #427: Text: Optical kerning spaces pairs from their outlines
Conflicts:
- Cargo.lock: designcraft-compose depends on both unicode-script (#427)
  and unicode-segmentation (next).
- ROADMAP.md: the optical kerning progress-log line goes above next's two
  2026-10-11 lines. Status line keeps next's Last reviewed date and names
  both changes.
- docs/gaps.md, docs/typography-parity.md: same status-line merge.
2026-10-11 02:30:53 +00:00
aiongg 5e51392ac4 Merge mac-font-activation: macOS fonts that font services and managers activate are listed (#261, #327)
Conflict in ROADMAP.md: kept both 2026-10-11 progress-log lines (New
Document from next, then the font activation line).
2026-10-11 02:20:28 +00:00
aiongg 833c0ec8d6 Fonts: macOS fonts that font services and managers activate are listed
The system font scan also reads the font files CoreText has available
(core-text's collection of all available fonts, safe API), so fonts that
Adobe Fonts, RightFont and other font managers register from their own
folders are cataloged. Files the font folders already hold are read once;
paths that lead to no file are skipped. FontDb::global serves the desktop
app and designcraft-cli alike; the scan stays in the background.

Fixes #261, #327.
2026-10-11 01:50:32 +00:00
Abdelrehman Fouad 62faa8eee2 Text: Optical kerning spaces pairs from their outlines
Optical kerning was treated exactly like Metrics: the font's kern pairs
and nothing else, so text set with Optical in InDesign came out wider,
rewrapped and went overset in tightly fitted frames.

Now the font's pairs are turned off for Optical text and each pair is
spaced from its outlines (crates/compose/src/optical.rs): every glyph's
ink is sampled into 28 bands across the em, the pair's mean and smallest
ink gap over the bands both glyphs ink are compared with the font's
stem-to-stem gap (the pair nn, or HH then oo), and the pair moves 60% of
the way towards it, keeping 30% of that gap and moving at most -0.12 or
+0.06 em. Latin, Greek and Cyrillic letters, digits and Western
punctuation take part; spaces, marks, missing glyphs, right-to-left
runs, upright and tate-chu-yoko glyphs and pairs across a fallback font
keep their font spacing. Profiles and references are cached, bounded.

Tests: AV, To and r. close up and nn stays; HH closes up under Optical
but not Metrics (fails on main); every change on a pangram stays within
the bounds and spaces keep their width; profile, gap, adjustment and
character-class unit tests.

Docs: typography parity Kerning row and remaining effort, gap 4,
ROADMAP milestone 6 and progress log.

Fixes #181.
2026-10-11 03:25:01 +02:00
aiongg ce144a614a Merge remote-tracking branch 'upstream/main' into next
# Conflicts:
#	ROADMAP.md
2026-10-11 00:30:35 +00:00
skylar taylor-barrick a77bf8bff5 UI.9: reconcile upstream before shared UI landing 2026-10-10 18:00:07 -06:00
Brandon ThomasandClaude Opus 5.5 a9124a0517 Release prep: version 0.6.0; Linux riscv64 tar.gz in releases (#398)
- release.yml: new linux-riscv64 job (cross-compiled on ubuntu-24.04 against
  ports.ubuntu.com riscv64 libs, tar.gz only, CLI smoke-tested under QEMU),
  ported from GridCraft; the draft release job needs it, so SHA256SUMS covers it.
- packaging/linux/package.sh: CROSS_ARCH/CROSS_TARGET/CROSS_COMPILE/EMULATOR
  support, as in GridCraft.
- cargo xtask version set 0.6.0; README, hardware parity and ROADMAP log note
  the new platform.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:33:30 -04:00
aiongg 62df5e764a Merge file-open-os: Save adds .designcraft, and the OS opens DesignCraft and IDML files
- apps/designcraft/Cargo.toml: the macOS target keeps objc2 0.6 / objc2-app-kit 0.3 (IME) and
  adds fmv-macos-events =0.1.0, which uses the same objc2 and objc2-app-kit versions.
- apps/designcraft/src/main.rs: the shared Arc<gpu::Startup>, catch_unwind and restart flow
  stay; the Apple-event handlers are installed before run_native (outside catch_unwind, held
  until the window ends), the app drains the inbox each frame, and documents that arrived are
  noted on the Startup. The open dialog keeps the INDD/INDT filter and ends with All files.
  The open-filter test checks both; the save-dialog test is added.
- apps/designcraft/src/gpu.rs: Startup::opening records the documents the OS handed this run;
  a start again after a graphics failure (both finish and the first-frame watch) passes them
  as file arguments, since Finder doesn't send them twice.
- apps/designcraft/src/apple_events.rs: poll returns the documents it handed the app, and
  queued() returns those still in the inbox when the window ends.
- crates/engine/src/cmd/file.rs: file.open decides by content first (IDML by its mimetype
  entry, then a DesignCraft package or JSON), then an InDesign file by its signature or
  .indd/.indt extension, then a .idml or .designcraft extension for the reader's own error;
  anything else is "not a DesignCraft or IDML file". INDD stays in file.openBytes. Save
  commands add .designcraft as on file-open-os; the params docs describe all of it.
- crates/engine/src/cmd/mod.rs: re-exports from both sides (is_document,
  with_document_extension and layout::chapter_numbering).
2026-10-10 23:21:12 +00:00
aiongg 11532d961e Documents: Save adds .designcraft, and the OS opens DesignCraft and IDML files
- file.save / file.saveAs / file.saveACopy add the .designcraft extension to a
  given path that lacks it and report the path written; saving back to the
  document's own file keeps its name.
- file.open tells DesignCraft and IDML packages apart by content, so files
  without an extension open; anything else is "not a DesignCraft or IDML file".
- Dropped or web-picked files without an extension open as documents when their
  content is one.
- Desktop save dialogs filter on the suggested extension and add it to a name
  typed without it, asking before replacing an existing file; the open dialog
  gains "All files".
- macOS: open-documents Apple events (Finder, Dock, Open With) through
  fmv-macos-events, queued until the window is ready; Info.plist declares the
  .designcraft type and an imported .idml type with CFBundleDocumentTypes.
- Windows MSI: .designcraft ProgId with an Open verb, IDML under Open with.
- Linux: shared-mime-info for both types and MimeType in the .desktop file.

Fixes #158, #211, #375
2026-10-10 22:40:06 +00:00
skylar taylor-barrick c62866443c UI.9: integrate shared panel docking and preserve workspace behavior 2026-10-10 14:42:40 -06:00
aiongg 16bb39e531 Merge gpu-startup: pick the GPU that drives the display, fall back across adapters and backends, and log startup errors (#273, #334) 2026-10-10 20:30:59 +00:00
aiongg 279336c445 Startup: pick the GPU that drives the display, restart on the next adapter or backend, and log startup errors
Ported from VectorCraft's start-up fixes (#502, #545, #651, the display-GPU
choice, #806, #964) and reconciled with the backend fallback of #297:

- The app picks the window's adapter itself (eframe's native_adapter_selector,
  apps/designcraft/src/gpu.rs): adapters that can't present never, then
  WGPU_ADAPTER_NAME, hardware before software, native backends before OpenGL,
  the GPU that drives the primary display (Windows EnumDisplayDevices through
  winsafe, Linux /sys/class/drm), the power preference (WGPU_POWER_PREF;
  otherwise power saving on Windows and macOS, the system's order elsewhere),
  then DX12 before Vulkan. Every adapter and the choice are logged.
- wgpu's indirect-call validation is off (WGPU_VALIDATION_INDIRECT_CALL=1 turns
  it back on): its compute shader failed to compile on an Intel Mac and lost
  the Metal device (#334, first error).
- run_native runs under catch_unwind. A wgpu error or a panic in wgpu,
  egui-wgpu or naga during the first frames, or a first frame that doesn't
  reach the screen in 20 s, starts the app again without that adapter
  (DESIGNCRAFT_GPU_SKIP; exec on Unix, a new process on Windows). When no
  adapter of the start's backends is left, it starts again with the next
  backend. Each restart leaves out one more adapter or backend, so they end.
  Adapters without PCI ids (Metal) are keyed by name.
- The backend fallback (gpu/backend.rs, gpu.json) stays for driver faults that
  take the process down. Windows tries DirectX 12, then OpenGL, then Vulkan,
  each in its own instance: Vulkan last because creating its instance loads
  every installed Vulkan driver, and OpenGL kept out of the DX12 instance
  because creating it crashed in AMD's atio6axx.dll (#167).
- main returns an ExitCode and logs why the app stopped to standard error and
  the log file, which is all a Windows start without a console leaves (#273).

README, architecture, gaps, hardware and target-app parity docs and ROADMAP
describe the choice, the restarts and the variables.
2026-10-10 20:26:06 +00:00
aiongg 23b6ce4cc1 Merge feat/ime: IME composition (#322)
Conflict: crates/ui-egui/src/lib.rs: next's missing-fonts test; the branch's side repeated control_bar_shows_its_second_row (next's newer copy stays) and key_names_sent_as_text_are_dropped, whose IME version replaces next's copy in place
2026-10-10 16:30:09 +00:00
aiongg 1276181cde Text: IME composition in place, commit as one step (#322)
The Type tool shows an input method's marked text in the story as a
preview of text.insert, underlined (the converting clause twice), with
the candidate window at the caret. The commit is one text.insert and one
undo step; a cancelled composition leaves the document as it was. Keys,
shortcuts, the clipboard and Undo wait while the IME composes; a click,
a tool or document switch, or any journaled command keeps the marked
text as typed. On macOS the app tells the input context to drop marked
text the tool kept.

With a split window, only the pane last clicked takes keyboard events
(both panes saw them, so typing went in twice).

The web build drops only real key names from text events, and nothing
while its text input has the keyboard, so autocompleted words survive.

The control channel's ui.ime, the headless MCP backend's ui.ime and the
MCP ime tool send IME events.
2026-10-10 16:05:36 +00:00
aiongg 5551cf9a25 Merge upstream main into feat/text-editing-and-frames
The layout-parity files (ROADMAP, compose lib/tests, engine text, fonts fontdb, idml import/tests, canvas) resolve as in the merge of main into feat/layout-parity.
Conflict: ROADMAP.md: as feat/layout-parity's merge
Conflict: crates/compose/src/lib.rs: as feat/layout-parity's merge; this branch's trimmed trailing spaces follow main's warichu::place and come before the drop cap splice
Conflict: crates/compose/src/tests.rs: both sides' tests
Conflict: crates/engine/src/cmd/text.rs: as feat/layout-parity's merge; this branch's TypingFormat/typing_format and main's warichu_cmd
Conflict: crates/fonts/src/fontdb.rs: this branch's styles/traits_of/linked_style over style_traits; style_traits falls back to the family without main's format suffix (exact_style_traits)
Conflict: crates/idml/src/import.rs, crates/idml/src/tests.rs, crates/ui-egui/src/canvas.rs: as feat/layout-parity's merge
Conflict: crates/ui-egui/src/control.rs: main's page_index and automation_contract_tests, then this branch's tests module
Conflict: crates/ui-egui/src/lib.rs: this branch's ClipboardFn and main's Inbox of ImportedFile
Conflict: crates/ui-egui/src/menus.rs: main's Quick Apply tests, then this branch's copy and paste keys test
2026-10-10 15:36:43 +00:00
aiongg 7f23a5e05b Merge upstream main into feat/layout-parity
Conflict: ROADMAP.md: this branch's Text engine, IDML interchange and Right-to-left lines; main's FID2, PDF export and Interface language lines
Conflict: crates/compose/src/lib.rs: list labels as main's number_label/bullet_label/empty-paragraph arms, kept in this branch's list_label form that marks label glyphs; main's layout_line call (ends_para, forced_mid) and warichu::place, then the drop cap splice; rule above uses main's first-line column/end_x span with this branch's rule_color; caret(): drop-cap branch, then main's stacked-row metrics
Conflict: crates/compose/src/tests.rs: both sides' tests
Conflict: crates/engine/src/cmd/text.rs: type.para doc lists the drop cap fields and main's rule fields
Conflict: crates/fonts/src/fontdb.rs: both (plausible/measured_top/typo_ascent and without_format_suffix)
Conflict: crates/idml/src/import.rs: main's table style regions, borders and alternating fill/stroke attrs (this branch's alt_fills helper dropped, unused); underline/strikethrough colour from main with this branch's tint(); frame_options takes the object-style chain's TextFramePreference elements, the frame's column rule colour resolved after it
Conflict: crates/idml/src/tests.rs: main's tests, plus this branch's added tests and helpers
Conflict: crates/ui-egui/src/canvas.rs: main's compose::highlight_quads, then this branch's drop-cap highlight
2026-10-10 15:34:23 +00:00
aiongg d86bbd8d6c Merge #316: GREP: the dialect's classes and metacharacters (\l \u \h, ~ codes, lookaround) in GREP styles and Find/Change
Conflict: crates/compose/src/tests.rs: tests only, both (#310's tight word spacing test, #316's GREP style test)
#316's overlay test calls overlays() with the drop_end argument next added (#83).
2026-10-10 10:12:34 +00:00
aiongg f4c0b9f378 GREP: dialect classes and metacharacters (\l \u \h, ~ codes) in GREP styles and Find/Change
One shared compiler (designcraft_compose::grep) translates the GREP dialect
documents and users write: \l \u \L \U letter classes, \h \H \v \V \R \N,
\r paragraph end and \n forced line break, ~ special-character codes,
Unicode-aware POSIX classes, and literal [ & -- inside character classes.
It compiles with fancy-regex, so lookahead, lookbehind, atomic groups,
possessive quantifiers, backreferences and \K work; a backtrack limit stops
pathological patterns with an error.

GREP styles skip a pattern that fails to compile or gives up on a search,
with one log warning. Find/Change returns the error. The paragraph style
dialog validates with the same compiler. Fixes en dash (~=) mapping to an
em dash in Find/Change.
2026-10-10 09:58:12 +00:00
aiongg 11eac68fda Merge upstream main 92649ff (#155) into next 2026-10-10 09:15:04 +00:00
92649ffdb0 Security: validate engine inputs and package paths (#155)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 04:50:26 -04:00
aiongg aadd54a926 Merge upstream main 736acff into next
Upstream main moved 9e4f694 -> 736acff by 10 squashes: #258, #285, #153, #280, #288, #281,
#176, #299, #298, #297. New to next: #258 (datamerge test), #153 (temporary files and release
inputs), #280 (warichu), #176 (PDF image conversion cache), #297 (graphics backend before the
window). Already on next: #285, #288, #281, #299, #298.

Conflict: ROADMAP.md: next's lines; CJK1 takes main's wording (ruby unfinished, warichu set after the line is broken)
Conflict: crates/compose/src/lib.rs: list labels (#298): next's list_label structure; paragraph start / break moves: next's `go` (with #295's sub-columns) under the maintainer's #285 comment; Cursor: next's start/next_page/next_baseline with tops; line placement: #280's warichu::place right after layout_line, before next's trimmed trailing spaces and the drop cap splice (so neither is stacked and the spaces follow the closed-up end_x); caret(): next's drop-cap branch first, then #280's stacked-row metrics
Conflict: crates/compose/src/tests.rs: next's tests kept; #280's tests auto-merged
Conflict: crates/engine/src/cmd/text.rs: both (next's TypingFormat/typing_format, #280's warichu_cmd)
Conflict: crates/idml/src/tests.rs: next's side; #280's warichu round-trip test auto-merged
Conflict: crates/pdf/src/export.rs: #176's content cache and test counter with next's RasterMode (no Exporter `interpolate` field on next, so the maintainer's `mode.interpolate &= self.interpolate` is not carried); test exporter gets next's drawing_items field
Conflict: crates/ui-egui/src/canvas.rs: #280's compose::highlight_quads (its RTL branch equals next's mixed-direction spans) followed by next's drop-cap highlight
Conflict: crates/ui-egui/src/menus.rs: next's formatting_affects_text test kept

Auto-merge duplicates removed: #288's table-style tests and #298's list test in idml tests.rs,
#288's tests in doc styles.rs and #285's docx test (both files equal next's), #281's dialog
tests in dialogs.rs (equals next's) and its menu_button/menu_max_height/clipped_submenu in
menus.rs. contributors/people.toml takes main's (next had a duplicated
[people.emanuelebonaventura] table from the 9e4f694 merge, which broke the ui-egui build
script's TOML parse).

Maintainer edits carried over: #285 break characters and Next Column through one closure
(next's `go`, comment added); #281 viewport-aware menu_button in the app bar and the Paragraph
menu, per-dialog widths clamped to the window (all already on next); #280 warichu after the
last-line rules (layout_line with ends_para/forced_mid) and rules at each warichu row's
baseline (rule_baseline in render and pdf text_rules); #176 CMYK fallback through
lossless(.., mode) and its updated contract tests; #258 test fixes; #153 and #297 as landed.
2026-10-10 08:20:36 +00:00
736acffe5f Desktop: pick the graphics backend before the window exists; DirectX 12 on Windows (#297)
* Desktop: pick the graphics backend before the window exists; DirectX 12 on Windows

On an AMD hybrid-graphics laptop (Radeon RX 6800M beside an integrated
Radeon, with two versions of amdvlk64.dll loaded into one process) the
app died a few seconds after launch with an access violation inside
AMD's Vulkan driver at the first swapchain present. Nothing reached the
log: a fault inside a driver is a native crash the engine's panic guard
never sees. wgpu's default backend set (PRIMARY | GL) enumerates Vulkan
first, so every start on that machine went down the same path, while
WGPU_BACKEND=dx12 and WGPU_BACKEND=gl ran fine and the headless CPU
renderer was never affected.

The desktop app now chooses the backend before creating the window
(apps/designcraft/src/gpu.rs): DirectX 12 first on Windows, then Vulkan,
then OpenGL; Vulkan then OpenGL on Linux; Metal on macOS. OpenGL stays
in the set as the in-process fallback when the chosen backend has no
adapter. WGPU_BACKEND still overrides everything and turns the fallback
off.

Start-up fallback: gpu.json in the settings directory records the
backend being tried until the third frame begins (the first has been
presented by then) or the app exits normally. A record left behind means
that backend never showed a frame, so the next start skips it, tries the
next candidate and says so in the status bar. The list starts over when
every candidate has failed or the app version changes;
DESIGNCRAFT_NO_PREFS records nothing. The adapter, backend and driver
version are logged at start-up for bug reports.

Verified on the affected machine: a default start runs on DirectX 12; a
simulated crashed DX12 start moved to Vulkan, which faulted for real,
and the start after that came up on OpenGL with the status line. Nine
unit tests cover the chooser and the record; cargo xtask ci passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Merge origin/main; on Windows OpenGL isn't added to the DX12 or Vulkan instance (#167)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-10 04:11:47 -04:00
74a81f9fb0 Harden temporary files and release inputs (#153)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:46:19 -04:00
8146737e97 Text: a column, frame or page break ends its paragraph (#285)
A break character is stored as the last character of the paragraph it
ends, followed by the usual '\n' separator. The story model, paragraph
ranges, styles, editing and every exporter keep splitting paragraphs on
'\n' only, so the change stays in the places that create, lay out or
write break characters:

- IDML import writes the break and ends the paragraph, so the range that
  follows keeps its own paragraph style. NextOddPage and NextEvenPage map
  to new odd and even page break characters; IDML export writes a
  paragraph that ends in a break as that one Br with its
  ParagraphBreakType, so export and re-import give the same story.
- Word and RTF import, Type > Insert Break Character (with odd and even
  page breaks added) and typing end the paragraph after a break. Typing
  between a break and its return goes to the next paragraph; deleting
  either deletes both.
- Layout: a break that ends a paragraph leaves no empty line; the next
  paragraph starts in the next column, frame or page, as a paragraph start
  option would. Page breaks and Next Page start options move to the next
  frame on a later page; odd and even ones to the next page with that
  page number parity (no such frame: overset). A break inside a paragraph
  from an older document still moves the rest of that paragraph on.

Storing the break as a paragraph separator of its own would have changed
every place that counts or splits paragraphs on '\n'.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:36:47 -04:00
aiongg 7e0afa24e8 Merge upstream main 464a442 (7 PRs landed) into next
Landed: #119 #294 #144 #199 #248 #222 #223. #119 #144 #199 #248 #223 were
already on next; #222 (Spanish hyphenation) and #294 (Ukrainian catalog
test) are new here and come in whole. Each squash equals its landed PR
head (fetched to refs/remotes/pr-landed/N).

Conflict: contributors/people.toml: next's side (keeps emanuelebonaventura between moppeeer and thaynej)
Conflict: crates/doc/src/styles.rs: next's side (next's cell/table style tests)
Conflict: crates/pdf/src/export.rs: next's side in both hunks (no Exporter `interpolate` field on next; `let i = mode.interpolate` kept once)
Conflict: crates/ui-egui/src/dialogs.rs: confirm: next's `paragraphRules` arm; basic_character_formats: upstream's side (maintainer's font menu, see below)
Conflict: crates/ui-egui/src/i18n.rs: next's translated "Tint:" row
Conflict: crates/ui-egui/src/lib.rs: next's side (keeps ClipboardFn)
Conflict: crates/ui-egui/src/widgets.rs: next's side (next's numeric field grid test)

Maintainer edits in the landed PR heads:
- #119 (bfe02c9): inbox and PDF page dialog imports go through open_file; import_file uses opens_as_document. Already on next.
- #144 (fa5b942): paragraph_style_options reads a cloned doc; already on next. Basic Character Formats' Font Family is a ComboBox over font_menu_body (blank row clears a sparse family, "—" when unset). Taken from upstream in place of next's font_combo + "×" button.
- #199 (7afa9b7): one Properties test module with both tests. Already on next.
- #248 (856a432): people.toml keeps moppeeer and thaynej. Already on next.
- #222 (ac9b68d): ROADMAP Language line combines #199's "Properties ▸ Character" with #222's Spanish hyphenation note. Comes in with #222.
- #223 (c3d8a07): `mode.interpolate &= self.interpolate` and the decode check in lossless. The decode check is on next; the interpolate line is not, because next has no Exporter `interpolate` field and RasterMode::for_standard already turns interpolation off for every standard, PDF/A included.
2026-10-10 06:36:48 +00:00
e161878e4c Hyphenation: Spanish text is hyphenated with Javier Bezos's patterns (#222)
Text set in Spanish was not hyphenated at all. It now uses Javier
Bezos's Liang patterns, hyph-es.tex 5.0 from hyph-utf8 under MIT,
through the hypher crate 0.1.8 with only its alloc and spanish
features. The full feature, which embeds 48 languages under several
licences, stays off.

- hyphen::Lang names the hyphenator for a run: English, or a hypher
  language. Lang::for_language maps a language name or locale code.
- word_breaks_in and hyphen_points_in take the language. word_breaks
  and hyphen_points stay as the English entry points.
- Composition hyphenates a non-English run whose language has
  patterns and skips the rest. The word cache key includes the
  language.
- NOTICE carries the Bezos copyright line and the MIT text.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-10 02:21:25 -04:00
e585f9495d Preserve browser import intent and document targets (#119)
* #89: preserve browser import context and PDF options

* #91: reject PDF pages before narrowing on Wasm

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 02:02:57 -04:00
skylar taylor-barrick 4c6aa4cd4b browser-correctness: fix print, startup flags, and document MIME (#117) 2026-10-10 01:13:23 -04:00
aiongg 2a80cfe54c Merge #285: Text: a column, frame or page break ends its paragraph; odd and even page breaks
Conflict: crates/compose/src/lib.rs: start options, the break after the previous paragraph and a break inside a paragraph go through a local `go` that sends NextColumn to next's span-aware next_column (#276) and the rest to #285's Cursor::start; the in-paragraph break takes #283's `brk` (the line's last glyph); #283's ends_para uses is_break_char; Cursor keeps next's resume() and adds #285's start/next_page (#285's old next_baseline header dropped, next's is kept); the table branch is #285's
Conflict: crates/idml/src/tests.rs: tests only; kept both
Conflict: crates/textimport/src/docx.rs: tests only; kept both
2026-10-10 03:51:42 +00:00