Commit Graph
282 Commits
Author SHA1 Message Date
Brandon Thomas a8b8b3eb62 Merge pull request #1779 from dotCooCoo/fix/automation-roots-tests-on-windows
MCP: the several-roots tests expect Windows paths without the \\?\ prefix
2026-10-25 12:25:47 -04:00
aiongg fec0897a5d Application bar: use craft-window's shared title bar (#1811)
* UI: the application bar uses craft-window's title bar

DesignCraft's title-bar code moved to craft-libs as craft_window::title_bar.
The application bar calls it instead of its own copy, and the macOS shell
takes sync_movable from it. Differences: a drag on an in-window panel lying
over the bar no longer moves the window, full screen ignores the bar's drag
and double-click, and floating panels in their own windows keep their own
movable flag.

* UI: craft-window from craft-libs main

* UI: the application bar ignores the title bar's response
2026-10-25 12:06:36 -04:00
skylartaylor 8a6ed75d41 egui037: reconcile current DesignCraft main and qualify CI 2026-10-25 03:38:13 +01:00
skylartaylor a2db858e7d egui037: Port DesignCraft to egui 0.37
Pin the final egui, winit and shared UI revisions and reconcile current main.
Preserve document-epoch input and screenshot boundaries, host action ordering,
and Windows path regression coverage. Add click/End batch characterization.

Validation: all nine Linux CI stages pass (3230 tests, zero failures); Windows
CI and bounded native editing workflows pass on the same production source.
2026-10-25 00:52:21 +02:00
skylar taylor-barrick 9fc02f8f7b Merge contributor branch codex/placed-graphic-layer-overrides (PR #1647) into main
Conflict resolutions:
- crates/pdf/src/export.rs: keep main's `graphic(.., hidden)` signature from
  #1241 and report retained graphic-layer overrides that drawing cannot apply.
- docs/gaps.md: keep main's change list and add the graphic-layer entry.
2026-10-24 15:30:03 -06:00
aiongg b3be40ed08 Merge remote-tracking branch 'upstream/main' into docking-trial
# Conflicts:
#	Cargo.toml
2026-10-24 18:46:43 +00:00
dotCooCoo bab76dcd11 MCP: the several-roots CLI test keeps a share path a share path
The test removed only the \\?\ prefix from the folder it resolved, so a
temporary folder on a network share became the relative path
UNC\server\share\... . It now removes the \\?\UNC\ prefix first and
keeps the two leading backslashes, as file_access::plain does, with a
test of both forms.
2026-10-24 10:44:08 -07:00
dotCooCoo 1f613f8c66 MCP: the several-roots tests expect Windows paths without the \\?\ prefix
Four tests from #1678 fail on Windows. Each one builds its paths, or the
text it expects, from a folder resolved with `std::fs::canonicalize`,
which adds the `\\?\` prefix on Windows. `AutomationRoots::describe` and
the rejection messages show the roots without that prefix, so the
expected text does not match. Windows does not resolve `..` in a path
with the prefix, so the checks refuse every such path as one they cannot
resolve, including the ones the tests expect to pass from one root into
another. The code the tests check is unchanged.

The engine tests take the resolved folder through `file_access::plain`,
which the roots use for the text they show. The CLI test strips the
prefix the same way.
2026-10-24 08:41:44 -07:00
Brandon Thomas b724698d98 Merge remote-tracking branch 'origin/main' into pr1678
# Conflicts:
#	apps/designcraft-cli/src/main.rs
2026-10-24 10:03:25 -04:00
andeecollard 7074dc8a85 M6: preserve per-placement graphic layer options 2026-10-24 13:22:08 +01:00
Dylan M. TaylorandClaude Sonnet 5.5 8299d26400 chore: replace trivial closures with method paths (Sonar S1612) (#1714)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 04:30:43 -04:00
Daniel c2b2d260a5 Merge upstream main and preserve Linux GNOME decorations
Integrate updated DesignCraft notices, dependencies and package scripts while keeping Adwaita's MIT notice.
2026-10-24 10:25:28 +02:00
Dylan M. TaylorandDylan Taylor f90d286721 chore: resolve SonarCloud maintainability issues (#1698)
* chore: resolve SonarCloud maintainability issues

- Replace lambda closures with method references (S1612)
- Replace wildcard imports with explicit imports (S2208)
- Refactor complex functions with extracted helpers (S3776)
- Replace OR pattern with range pattern in math parser (S9047)

* style: apply rustfmt to warichu helper

* fix(compose): revert slice conversion in tests and remove unused var in warichu

* Group warichu row layout scalars to satisfy S107 parameter limit

* style: satisfy rustfmt in warichu.rs

---------

Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-24 03:54:24 -04:00
Brandon Thomas 058b369b53 Merge storytold/main into squad/pdfx-unembedded-fonts
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-23 17:30:20 -04:00
Brandon Thomas e3ac9936a6 Merge pull request #1371 from Hamza0101/fix/backend-log-says-what-happened
Graphics: the start-up log says which backend was chosen and how to change it
2026-10-23 17:28:35 -04:00
Marco Arnulfo b5342e48cd Save and export dialogs start in the document's folder, or the last one used (#1653) 2026-10-23 21:32:05 +02:00
Marco Arnulfo 7362530591 MCP: --automation-read-root and --automation-write-root may each be given more than once (#1552)
A path passes when it lies inside one of the roots of its kind. The roots'
common parent, a sibling named like a root, `..` or a link out of them and
the other kind's roots stay refused; a folder given twice counts once.
2026-10-23 20:30:07 +02:00
Dylan M. Taylor df1db1646b web: let the browser zoom the page (SonarCloud Web:S7926) (#1641)
The viewport no longer sets user-scalable=no, so people who need to zoom
the page can (WCAG 1.4.4). The canvas takes touch-action: none, so pinch
and pan gestures on it still go to the app's own zoom, as eframe's touch
handlers expect, instead of zooming the page.
2026-10-23 11:16:49 -04:00
aiongg 0409bbf9aa Merge branch 'print-color' into print-color-x1a
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	xtask/src/pdf_deps.rs
2026-10-23 08:16:07 +00:00
aiongg 7ac286e6d2 Merge branch 'keymap-adoption' into keymap-shortcuts-dialog
# Conflicts:
#	Cargo.toml
#	apps/designcraft/src/native_menu.rs
#	crates/ui-egui/src/i18n.rs
2026-10-23 05:41:18 +00:00
aiongg a30b71cd36 Merge remote-tracking branch 'upstream/main' into print-color
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	xtask/src/pdf_deps.rs
2026-10-23 05:40:13 +00:00
aiongg 3c38c84438 Merge remote-tracking branch 'upstream/main' into keymap-adoption
# Conflicts:
#	Cargo.toml
#	crates/ui-egui/src/menus.rs
#	crates/ui-egui/src/shortcut_import.rs
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-23 05:10:57 +00:00
aiongg bc1ccfa481 Merge remote-tracking branch 'upstream/main' into docking-trial
# Conflicts:
#	Cargo.toml
#	crates/ui-egui/src/i18n/fr.rs
2026-10-23 05:07:00 +00:00
aiongg 3ee11391ae CI: one integration-test binary per crate 2026-10-23 01:17:48 +00:00
KnottyDyes bba31c17b6 PDF: report visible unembedded fonts in PDF/X-4 (#909)
Track text state through graphics saves and drawn forms; exempt invisible text. Report font names and pages in export warnings and validation without embedding or outlining placed fonts.
2026-10-22 10:31:21 -06:00
aiongg 8f98f3dc8b Keyboard Shortcuts: import an InDesign shortcut set (#1296)
* #1180: import an InDesign keyboard shortcut set

Edit > Keyboard Shortcuts gets Import InDesign Set..., which reads the
.txt that InDesign's Show Set writes (window.importShortcuts {path|text}).
Matched commands take the set's Default shortcut, or lose theirs when
every occurrence says [none defined]; other commands give up keys the
set takes. The report lists changes, cleared conflicts, and the items
that could not be matched or read. Tool keys stay fixed.

* #1180: read the set file through the checked reader

* #1180: when two items want the same keys, the later one takes them
2026-10-22 09:28:11 -04:00
aiongg 2660395db5 macOS: a Language submenu in the app menu (#1541) 2026-10-22 01:31:36 -04:00
aiongg 496b1899a2 macOS menu bar: menus keep working after a language change; key equivalents follow the shortcuts (#1540)
* macOS menu bar: keep working after a rebuild; key equivalents follow the shortcuts in effect

* macOS menu bar: the shortcut test sets its key with window.setShortcut
2026-10-22 01:18:41 -04:00
Zuujis 438d7b6d79 Dedupe the 400-year-cycle UTC conversion and the EPUB package writer (#1537)
* Dedupe the 400-year-cycle UTC conversion and the EPUB package writer

SonarCloud flagged new-code duplication on main (17%): five copies of the
"move the instant into chrono's range by whole 400-year cycles" conversion
and two copies of the EPUB OPF/container/zip writer.

- designcraft-doc gains a `time` module: `date_parts(days)` and
  `utc_parts(secs, nanos)`. App logging, EPUB `iso8601`, PDF `civil`, PPTX
  `civil` and text-variable `civil` are now thin callers; each keeps its own
  format string and year clamp. The app reaches it through
  `designcraft_engine::doc`, so its direct chrono dependency is dropped.
- EPUB: `package_opf` + `write_package` shared by fixed-layout and
  reflowable export (same entry order and compression).
- Boundary tests on the helper: pre-1970, year 9999 -> 10000, i64 extremes,
  nanos past a second.

Output is unchanged: existing date tests pass, and fixed/reflowable EPUBs
(with/without cover, author, pre-1970 and i64::MAX dates) are byte-identical
to origin/main.

* time: drop the unreachable i128 clamp and match arms in utc_parts

Whole 400-year cycles times 400 stay under 2.6e16 for any i64 day count,
so the year can't overflow i64 and the i128 + saturate was dead code
(carried over from the copies this replaced). The date and time lookups
can't fail either; each keeps one unwrap_or_default instead of a match
with a fake 1970 fallback. Output and tests unchanged.
2026-10-21 21:46:38 -04:00
Dylan M. Taylor 3b985e3813 Use chrono instead of hand-rolled UTC conversion (#1479)
* Use chrono for UTC/calendar conversion instead of hand-rolled copies

Replaces the hand-rolled civil / civil_from_days / days_from_civil copies (the
146_097 / 719_468 magic numbers) across the logging timestamp, text-variable
dates, EPUB dcterms:modified, PDF metadata dates and PPTX core.xml dates with
chrono, added as a workspace dependency (default-features = false, std only, so
wasm is unaffected).

- apps/designcraft logging `timestamp` (private civil_from_days deleted).
- doc text variables: `civil` and `days_from_civil` use chrono::NaiveDate;
  `format_date` and `parse_iso_date` keep their own format/parse logic and
  still call these helpers.
- epub `iso8601`, pdf `civil`, pptx `civil`: UTC datetime via
  chrono::DateTime::from_timestamp.

Output is byte-identical and pinned by the existing date, ISO-date, EPUB,
image, EPS and logging tests. The OOXML/EPUB dcterms timestamps keep their
exact strings. Each converted helper keeps a proleptic-Gregorian fallback for
dates outside chrono's NaiveDate range (and for the serial/overflow dates
parse_iso_date can hand days_from_civil), so no input changes or panics.
AGENTS.md now says time goes through chrono.

Follow-up to storytold/cadcraft#1785

* Never panic on a clock outside chrono's range; keep 5-digit years unprefixed

logging.rs timestamp(): chrono's From<SystemTime> unwraps, so a clock past
year 262143 panicked inside the logger. Use the fallible DateTime::from_timestamp
and read such a clock, or a pre-epoch clock, as the epoch like the old saturating
code did. Years past 9999 are written with {:04} like before, because %Y adds a
'+'. Tests cover both cases.

epub iso8601(): write the year with {:04} instead of %Y, matching the old
{year:04} output, so years past 9999 are not prefixed with '+'. Test added.

AGENTS.md: the "Time goes through chrono" rule now notes the narrow fallback
for dates outside chrono::NaiveDate's range, which crates/doc/src/vars.rs
retains (Howard Hinnant's algorithm).

* Don't build an unrepresentable SystemTime in the far-future test

UNIX_EPOCH + Duration::from_secs(u64::MAX / 2) overflows Windows'
SystemTime and panicked before timestamp() ran, failing the Windows
test job. Build it with checked_add and only assert where it exists.

* Route out-of-range dates through chrono's 400-year cycle, not hand-rolled copies

doc/vars.rs kept hand-rolled Hinnant `civil_fallback`/`days_from_civil_fallback`
copies for dates outside chrono's ±262143-year range, and AGENTS.md carved a
"narrow fallback" exception for them, which left calendar arithmetic outside
chrono after all.

Replace both copies with the Gregorian 400-year cycle (146_097 days): chrono
converts the day/year within one cycle and whole cycles are added back via i128
(so i64::MIN/MAX can't overflow). `civil` is reached by the system clock through
`format_date(now(), ..)`, so it must stay exact; `days_from_civil` only ever
sees a 4-digit parsed year via `parse_iso_date`, but it uses the same cycle form
for consistency. Both reproduce the pre-chrono proleptic Gregorian result, so
outputs are unchanged (verified against the old formula over wide ranges and at
the i64 extremes).

New test pins dates past chrono's range on both sides of the epoch, through the
public `format_date` and round-tripping `days_from_civil`/`civil`, with values
from the old formula. Removed the AGENTS.md "narrow fallback" exception.

epub/pdf/pptx `civil`/`iso8601` are left as-is: the PR already dropped their
hand-rolled copies for pure chrono, and their remaining epoch (`unwrap_or_default`)
fallback only triggers for a metadata/clock timestamp past year 262143 -- the
live-clock/file-mtime case FredApps accepted, with outputs that clamp the year
anyway (pptx 0..9999, PDF DateTime). No hand-rolled copy remains there to replace.

Tested: cargo test -p designcraft-doc; fmt --check; clippy --all-targets -D warnings.

* Carry an overflowing day into the next month again in parse_iso_date

parse_iso_date accepts any day 1..=31, and the old days_from_civil
carried a day past the end of its month into the next one (2019-02-30 is
2019-03-02). from_ymd_opt rejects such a day, and unwrap_or(0) turned it
into 1970-01-01. chrono now places the 1st of the month and the day is
added on, which restores the old normalization. Tested through days_from_civil
and parse_iso_date.

* time: preserve old out-of-range date conversion (no epoch fallback)

`DateTime::from_timestamp(...).unwrap_or_default()` silently reset any
instant past chrono's year range to 1970-01-01, changing output the old
hand-rolled Howard-Hinnant code converted exactly (e.g. 10_000_000_000_000 s
was 318857-05-20 17:46:40, not the epoch). Restore the old conversion domain
with a cycle-based helper that routes the calendar through chrono (the
calendar repeats every 400 years = 146_097 days, so month/day/time come from
chrono and only the year is carried, keeping every i64 exact), then apply each
format's existing year clamp afterwards.

- apps/designcraft/src/logging.rs: `timestamp` via `utc_parts`; keep the
  pre-1970 epoch clamp; u64 secs past i64::MAX saturate, not epoch.
- crates/epub/src/lib.rs: `iso8601` via `utc_parts`.
- crates/pdf/src/export.rs: `civil` cycle-based; `date_time` keeps its
  0..=9999 year clamp.
- crates/pptx/src/package.rs: `civil` cycle-based, keeps its 0..=9999 year
  clamp on the year only (month/day/time keep the real instant).

Pinned old outputs in tests (through the public helpers):
  logging u64::MAX/2 s -> 292277026596-12-04T15:30:07.000Z (was epoch)
  epub 10_000_000_000_000 -> 318857-05-20T17:46:40Z
       -10_000_000_000_000 -> -314918-08-13T06:13:20Z
       i64::MAX -> 292277026596-12-04T15:30:07Z
       i64::MIN -> -292277022657-01-27T08:29:52Z
  pdf  civil(10_000_000_000_000) -> (318857,5,20,17,46,40)
  pptx civil(10_000_000_000_000) -> (9999,5,20,17,46,40) (year clamped)

* Don't build a year-318857 SystemTime unchecked in the logging test

Windows' SystemTime only reaches about year 30828, so
UNIX_EPOCH + Duration::from_secs(10_000_000_000_000) panicked before
timestamp() ran and failed the Windows test job. Build it with
checked_add and assert where the platform can hold it. The year-10000
case fits everywhere and stays unconditional.

* Name the 400-year range extension as the one exception to the time rule

The rule said never to hand-roll calendar math, but the range fix
(shifting by whole 400-year Gregorian cycles so dates past chrono's year
range keep their old output) is cycle arithmetic, so the rule and the code
disagreed. The rule now names that exception: the library still computes
month, day and time, and only whole cycles are carried in the year.

* Say the library computes month and day; time-of-day is plain arithmetic

Narrows the range-extension wording: the date library computes the
calendar fields, and splitting seconds into hours, minutes and seconds
is ordinary arithmetic, which is what the code does.
2026-10-21 19:36:27 -04:00
aiongg 238ca0d2a0 Shortcuts: the shared craft-keymap dialog (craft-libs#186)
Edit > Keyboard Shortcuts is craft_keymap::ui::ShortcutsDialog over the
keymap and named shortcut sets. ui.json stores the sets as shortcutSets
and still writes the active set as shortcuts plus shortcutsMore. The
InDesign importer is the dialog's second import format, with a review,
and window.importShortcuts imports as a new set. window.shortcutSets
lists and selects sets. The native macOS menu drops its key equivalents
while the dialog records.
2026-10-20 20:41:24 +00:00
aiongg c50321c852 Print color: X-1a written by craft-pdf at PDF 1.4 (craft-libs#194 d30598d)
Repin craft-pdf, craft-prepress, krilla and the hayro crates to d30598d.
flatten_document writes the X-1a file at PDF 1.4 with GTS_PDFXVersion
PDF/X-1:2003 in the Info dictionary and XMP, so DesignCraft's header
rewrite and incremental update are gone. check_pdfx1a refuses DeviceN
NChannel attributes and warns about an ICC v4 output intent profile in a
file of PDF 1.5 or lower; the export names the built-in Coated FOGRA39
(v4) when it is the intent. validate-pdf lists warnings apart from issues.
2026-10-20 16:00:38 +00:00
Hamza ba4b6d4089 Say which backend was chosen without claiming it was the first
Two corrections to the message, both reported by CodeRabbit on #1371.

switched_from being None only means this start did not switch from a
backend that never showed a frame. A backend that failed on an earlier
start is remembered in the record, and choose() then picks the first
candidate that is not in that list -- so calling it the "first choice"
misstates how it was arrived at. The line now says either "nothing has
failed before" or which backends had, so the log says what happened.

The comment claimed that reaching this line means WGPU_BACKEND is
unset. wgpu-types returns an empty mask for an empty or unrecognised
value and begin() only returns early for a non-empty one, so such a
value reaches here with the variable set. The comment says that instead.
2026-10-20 20:59:04 +05:00
aiongg 75c6084a69 Print color: PDF/X-1a export through craft-prepress's flattener
standard x1a writes the PDF/X-4 print file, flattens it with
craft_prepress::flatten::flatten_document at the flattener preset's
resolution (high 300, medium 150, low 72 ppi; default 300), then makes it
PDF/X-1a:2003: the PDF 1.4 header, GTS_PDFXVersion and GTS_PDFXConformance
in the Info dictionary and XMP. check_pdfx1a refuses transparency (soft
masks, transparency groups, CA/ca below 1, blend modes) and color outside
DeviceCMYK, DeviceGray, Separation and DeviceN; export fails when the
flattened file still has either.

The X-1a path skips DesignCraft's RGB transparency flattener. Soft drop
shadows are drawn in their swatch's inks through a coverage mask, so
craft-prepress flattens them per ink instead of an RGB image of the
object. validate-pdf takes --standard x4|x1a; the Export PDF dialog gains
the PDF/X-1a:2003 preset and standard and a Transparency Flattener preset.
2026-10-20 15:04:58 +00:00
Hamza e572a5316f Graphics: the start-up log says which backend was chosen and how to change it
`Fallback::begin` returns before the fallback runs when `WGPU_BACKEND`
is set, logging that wgpu picks the backend. So the line below it is
reached only when the variable is *not* set -- and it said
"(WGPU_BACKEND overrides)", which reads in a log as though the user's
environment had chosen the backend when nothing had.

    before: graphics: DirectX 12 (WGPU_BACKEND overrides)
    after:  graphics: DirectX 12 (first choice; set WGPU_BACKEND to choose another)

The report quotes that line as evidence of which backend a start used,
which is exactly the wrong conclusion to be led to.

Part of #1343.
2026-10-20 18:26:44 +05:00
aiongg 6c9709e11f Print color: gradient stops keep the swatch they were given
A stop can name a colour swatch (spot, process, tint, [Paper]) next to its
display colour. swatch.create {gradient}, object.gradient, the Gradient panel
and IDML StopColor keep the reference; renames follow it, swatch edits refresh
the stop's colour and a deleted swatch leaves a plain colour. The field is
optional and omitted for plain stops, so saved documents load and save as
before.
2026-10-20 13:12:29 +00:00
Daniel 7c3e60b6c4 fix(linux): enable font-free Wayland window controls 2026-10-20 03:24:52 +02:00
aiongg 4b4503d92a Merge branch '1180-import-shortcuts' into keymap-adoption
# Conflicts:
#	Cargo.lock
2026-10-19 21:03:34 +00:00
aiongg 0d6fe6bff7 Merge remote-tracking branch 'upstream/main' into docking-trial
# Conflicts:
#	crates/ui-egui/src/dock.rs
2026-10-19 20:49:04 +00:00
aiongg adcb8ee067 Merge remote-tracking branch 'upstream/main' into 1180-import-shortcuts 2026-10-19 20:47:24 +00:00
aiongg 84e4032c11 Docking trial: migrate ui.json, delete the classic dock 2026-10-19 12:24:39 +00:00
Brandon Thomas 8ce4c31bac Merge pull request #1078 from marcoarnulfo/feat/vt-forced-break
Text parameters: a vertical tab is a forced line break
2026-10-19 02:50:31 -04:00
aiongg 8383d828ad keymap: DesignCraft shortcuts on craft-keymap
The shortcut model, dispatch and storage move onto the shared craft-keymap
crate. The catalogue is built from UI_COMMANDS, the engine command specs,
the panels (window.panel {panel}) and the tools (tool.select {tool}, one
group per Tools-panel group), with menu paths from the menu tree.

- Dispatch goes through craft_keymap::egui::Dispatcher; presentation keys,
  Esc-to-selection, Clear and the native-menu skip stay app-side, and the
  clipboard events stay with the canvas.
- Panels take InDesign's default keys where DesignCraft leaves them free.
- Tool keys are editable; tools sharing a key take turns.
- ui.json keeps its shortcuts as craft-keymap Overrides; the map form older
  versions saved loads unchanged.
- window.setShortcut accepts params (panels), tool ids and steal; the
  Keyboard Shortcuts dialog lists panels and tools and moves recorded keys.
2026-10-19 04:14:59 +00:00
NetterSilverandClaude Haiku 5.5 485a964e94 Reject a non-finite or non-positive --scale in designcraft-cli run
Found while testing apps/designcraft-cli/src/main.rs:361 (`--scale` parse) and :386 (export); crates/render/src/lib.rs:422-423 (render_page)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 08:51:07 +00:00
skylar taylor-barrick 61b1a3b08d Merge pull request #150 from skylartaylor/codex/fix-relink-eps
Merges upstream/main into the branch, resolving 12 conflicted files, and reconciles where the two sides meant different things — notably the format version, where both had independently defined version 2 (EPS sources here, pinned paragraph defaults on main), so a document without EPS was being written as version 1 and re-upgraded on load.

Verified locally against main b17efb2d: cargo test --workspace --no-fail-fast 2869 passed / 0 failed, cargo fmt --check clean, cargo clippy --workspace --all-targets -D warnings clean, xtask layers and wasm ok.
2026-10-16 21:55:21 -06:00
skylar taylor-barrick 653f83b8cb Startup: keep the backend a start was on, whichever it is, and cover it
Builds on the fix in this branch, which spotted that a failed OpenGL was
being forgotten because `failed` is filtered to this platform's
candidates and OpenGL is no candidate off Windows.

Rather than spare OpenGL from the filter, run the filter before the
previous start's backend is added. A stored entry that is no candidate
here came from another machine and still says nothing, so it is dropped
as before; the backend a start was actually running on is added
afterwards and stays, whichever backend it is. That keeps the same crash
out of the next instance without naming OpenGL or the platform, and
without holding a failure recorded on someone else's machine against
this one.

Adds the regression test: on macOS, where Metal is the only candidate, a
start left on OpenGL has to keep it out of the instance, while a stored
OpenGL entry that never ran here is dropped.
2026-10-16 20:46:40 -06:00
skylar taylor-barrick 0d541deab7 Merge upstream/main into codex/fix-relink-eps
Resolve 12 conflicted files. Where both sides changed the same code:

- format: keep main's bounded-read load_zip (MAX_ENTRIES, read_entry) and
  this branch's u64 version reporting, so a version above u32::MAX is named
  as written rather than clamped. Both sides had fixed the same truncation.
- render: main's natural_size supersedes image_natural_size (it already
  reads an EPS bounding box and also handles PDF pages); callers in table
  and data merge now use it.
- images: keep the DSC-aware header scan and (atend) trailer lookup, take
  main's classic-Mac line endings, and carry its overflow guard into
  parse_box. eps_proxy draws main's simple rectangles before falling back
  to the placeholder, still over a retained EPS source.
- engine/file: take main's placement shape (add_asset, crop box geometry,
  place cursor, finite_rect, object effects) and keep this branch's
  validate_placement in both branches; edit() works on a clone and commits
  only on Ok, so validating inside it stays all-or-nothing.
- engine/links: keep building the replacement before edit() so a file that
  cannot be read leaves the document untouched, and move main's crop_pdf
  refresh into relinked_asset, which both relink and update go through.
- engine/export: EPS preview warnings join the font-embedding warnings
  rather than shadowing them.
- idml: an EPS element keeps ActualPpi (its pixels are a preview raster);
  main's PDF exclusion is unchanged.

Cargo.lock regenerated. Tests and doc strings from both sides kept.
2026-10-16 19:57:08 -06:00
aiongg 3c862cc20f #1180: import an InDesign keyboard shortcut set
Edit > Keyboard Shortcuts gets Import InDesign Set..., which reads the
.txt that InDesign's Show Set writes (window.importShortcuts {path|text}).
Matched commands take the set's Default shortcut, or lose theirs when
every occurrence says [none defined]; other commands give up keys the
set takes. The report lists changes, cleared conflicts, and the items
that could not be matched or read. Tool keys stay fixed.
2026-10-16 19:53:29 +00:00
Hamza 5316059405 Graphics: keep a failed OpenGL out of the instance (macOS)
`choose` pruned the failed list to this platform's candidates, which dropped an
OpenGL entry on macOS, where Metal is the only candidate. But OpenGL is not only
a candidate: off Windows it is the in-process fallback that `instance_backends`
adds whenever it has not failed. So a start that recorded OpenGL and never
showed a frame had the entry pruned a line later, and OpenGL went straight back
into the instance — the backend that had just failed was offered again on every
start, with nothing able to retire it.

An entry that can still be reached is kept now. A non-candidate entry still
cannot be chosen as a backend, since `pick` only looks at candidates, so which
backend starts is unchanged; it only stops a failed OpenGL being handed back to
the instance.

This is what `a_start_records_its_backend_until_a_frame_is_presented` asserts,
and that test failed on macOS: `cargo xtask ci` stopped in the `designcraft` bin
before the rest of the workspace ran, so the gate could not go green there at
all.
2026-10-16 20:23:31 +05:00
aiongg e99783c756 Integration: "&" shows in native menu labels 2026-10-16 06:40:28 +00:00