Commit Graph
2864 Commits
Author SHA1 Message Date
aiongg d36e5fb63f Merge pull request #1927 from Silvertree2010/perf/export-speed
PDF export: ask the composition cache once per story and page
2026-10-27 13:41:05 -04:00
NetterSilverandClaude Opus 5.5 1db1635a88 Ask the composition cache once per story and page in PDF export
The PDF exporter called Cache::get twice for every text frame it drew.
Each call rebuilds the cache signature of the whole story, which looks up
every frame of the story with Document::find (a linear walk over all
spreads), and the anchored-frame placements walk them again. For a story
threaded through many frames this is O(frames^2 x items) per export.

The document doesn't change during an export, so the exporter now keeps
the composition it got for each (story, page) and reuses it. The cache
still decides what to compose; the output is byte-identical.

Add examples/pdf_export.rs to designcraft-cli: File > Export PDF through
a headless session on the `designcraft-cli perf` stress document (200
pages, 1M characters in 40 threaded stories, 500 placed images). The
stress document generator moves unchanged from src/perf.rs to a small
library module (src/stress.rs) that the binary and the example share.

Ryzen 16 threads, Linux, 12 runs each, interleaved:
  main     median 3485 ms, min 3427 ms
  patched  median 2016 ms, min 1656 ms  (-42 % median, -52 % min)
The exported PDF is byte-identical (12,075,744 bytes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:47:25 +01:00
aiongg d77fdf2d4c fix(ui): dropdown menus grow back after a search with no matches (#1917)
* fix(ui): font menus grow back after a search with no matches

Every combo box is craft_ui::ComboBox (craft-libs pinned at 62bb0e1d), whose
menu follows its contents' height while open (egui#5225); clippy.toml bans
egui::ComboBox.

The Font menu splits into a header (search field, filters) and a list
(font_menu_header, font_menu_list). Font fields show it in a
craft_ui::combo::Menu and the style dialogs' Font Family combo boxes in
ComboBox::show_ui_with_header, so only the rows scroll and the search field
stays in place. The blank and Parent's Font rows sit in the header, above
the search.

* chore(deps): craft-libs 60d60d48 (dropdown fixes)

* chore(deps): craft-libs 4d7b82f7 (dropdown fixes)

* chore(deps): craft-libs 92d392cf (#387 merged)

* chore(xtask): pdf-deps expects craft-libs 92d392cf
2026-10-27 10:27:32 -04:00
aiongg 50650f74d7 Iconic panel flyouts stay open while the canvas is in use (#1902)
Auto-Collapse Iconic Panels is off by default, so a flyout closes only from its icon or
another icon. The setting is saved under a new key, so preferences saved with the old
default start with it off, and Preferences > Interface > Panels shows it.
2026-10-27 01:54:50 -04:00
aiongg 42993ae680 test(engine): read only test cfgs and any pub(…) mod as test modules in the file guard
Split files share test helpers through pub(super)/pub(crate) test modules. The guard read only `mod` and `pub mod` as a test module, so it scanned their fixtures as production code. `attr.contains("test")` also matched `#[cfg(not(test))]`, so such a module was skipped; it is scanned now.
2026-10-26 23:06:07 +00:00
aiongg bbb495111e refactor(epub): split lib.rs into modules 2026-10-26 23:05:57 +00:00
aiongg 27e21ba19a refactor(render): split lib.rs into modules 2026-10-26 23:05:57 +00:00
aiongg 08f633ae48 refactor(fonts): split fontdb.rs into fontdb/ 2026-10-26 23:05:57 +00:00
aiongg f553e17406 refactor(doc): move the CharAttrs and ParaAttrs sets to attrs/char_attrs.rs and attrs/para_attrs.rs 2026-10-26 21:00:23 +00:00
aiongg f15fe7aef0 refactor(ui-egui): split i18n.rs into i18n/table.rs 2026-10-26 21:00:23 +00:00
aiongg 2bca3285bf refactor(ui-egui): split app.rs into app/ 2026-10-26 21:00:23 +00:00
aiongg 02f595fe92 refactor(ui-egui): split lib.rs into app, state, services, clock and key_names 2026-10-26 21:00:23 +00:00
aiongg 2dd87273a2 refactor(doc): split attrs.rs into attrs/ 2026-10-26 21:00:23 +00:00
aiongg bc345384f6 refactor(doc): split table.rs into table/ 2026-10-26 21:00:23 +00:00
aiongg a24e9dffd1 refactor(doc): split item.rs into item/ 2026-10-26 21:00:23 +00:00
aiongg f70c3efa3c refactor(ui-egui): split chrome.rs into chrome/ 2026-10-26 21:00:23 +00:00
aiongg 8f601148b6 refactor(engine): split cmd/layout.rs into cmd/layout/ 2026-10-26 21:00:23 +00:00
aiongg f33de8f4aa refactor(pdf): split export.rs into export/ 2026-10-26 21:00:23 +00:00
aiongg bec8800b62 refactor(idml): split export.rs into export/ 2026-10-26 21:00:23 +00:00
aiongg 2c0882c6e0 refactor(idml): split import.rs into import/ 2026-10-26 21:00:23 +00:00
aiongg a1ec465207 refactor(engine): split cmd/style.rs into cmd/style/ 2026-10-26 21:00:23 +00:00
aiongg 7afc1af676 refactor(engine): split cmd/text.rs into cmd/text/ 2026-10-26 21:00:23 +00:00
aiongg 2f7e956e8e refactor(ui-egui): split panels/properties.rs into panels/properties/ 2026-10-26 21:00:23 +00:00
aiongg d93acf7120 refactor(engine): split cmd/export.rs into cmd/export/ 2026-10-26 21:00:23 +00:00
aiongg b2f1ad1867 refactor(engine): split cmd/file.rs into cmd/file/ 2026-10-26 21:00:23 +00:00
aiongg 18e03a3035 refactor(engine): split cmd/table.rs into cmd/table/ 2026-10-26 21:00:23 +00:00
aiongg 96295e3f58 refactor(ui-egui): split menus.rs into menus/ 2026-10-26 21:00:23 +00:00
aiongg 9d5dbb4b8c refactor(ui-egui): split canvas.rs into canvas/ 2026-10-26 19:02:05 +00:00
aiongg 5f53d41387 docs(engine): name the file guard test's new path 2026-10-26 19:02:05 +00:00
aiongg bec8b28cbc refactor(ui-egui): move panel_docking_tests.rs to panel_docking/tests.rs 2026-10-26 19:02:05 +00:00
aiongg 09688b34d6 refactor(fonts): move the fontdb tests_*.rs files to fontdb/tests/ 2026-10-26 19:02:05 +00:00
aiongg b0dc1578b5 refactor(engine): move the loose tests_*.rs files to tests/ 2026-10-26 18:18:14 +00:00
aiongg 42071abc5c refactor(ui-egui): move the font_menu_ui_tests module of panels.rs to panels/font_menu_ui_tests.rs 2026-10-26 18:18:14 +00:00
aiongg 2e52c9fcd0 refactor(engine): move the tests module of cmd/place_text.rs to cmd/place_text/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 63dff1e6b5 refactor(ui-egui): move the tests module of prefs.rs to prefs/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 256426ae99 refactor(doc): move the tests module of attrs.rs to attrs/tests.rs 2026-10-26 18:18:14 +00:00
aiongg d4bd716ebf refactor(engine): move the text_clipboard_tests module of cmd/edit.rs to cmd/edit/text_clipboard_tests.rs 2026-10-26 18:18:14 +00:00
aiongg 8d36acd1c0 refactor(engine): move the tests module of cmd/load_styles.rs to cmd/load_styles/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 8ba7fd46b9 refactor(engine): move the tests module of cmd/variables.rs to cmd/variables/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 16b3594f31 refactor(ui-egui): move the tests module of i18n.rs to i18n/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 8d4a32667f refactor(ui-egui): move the tests module of panels/pages.rs to panels/pages/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 3b0e299180 refactor(engine): move the tests module of cmd/links.rs to cmd/links/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 10829d414e refactor(ui-egui): move the tests module of toolbar.rs to toolbar/tests.rs 2026-10-26 18:18:14 +00:00
aiongg d9fb8cfbfa refactor(engine): move the text_tests module of cmd/export.rs to cmd/export/text_tests.rs 2026-10-26 18:18:14 +00:00
aiongg 7248f3afd1 refactor(ui-egui): move the tests module of new_document.rs to new_document/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 98fb372245 refactor(images): move the tests module of lib.rs to tests.rs 2026-10-26 18:18:14 +00:00
aiongg 504d0e9979 refactor(pdf): move the tests module of pdfx.rs to pdfx/tests.rs 2026-10-26 18:18:14 +00:00
aiongg f07d0900b3 refactor(engine): move the tests module of cmd/package.rs to cmd/package/tests.rs 2026-10-26 18:18:14 +00:00
aiongg 0982b3da03 refactor(compose): move the border_tests module of table.rs to table/border_tests.rs 2026-10-26 18:18:14 +00:00
aiongg 4e40f85f9b refactor(engine): move the tests module of math.rs to math/tests.rs 2026-10-26 18:18:14 +00:00