Commit Graph
2702 Commits
Author SHA1 Message Date
aiongg e3bf0e745c Merge #413: Fonts: a pan-CJK font's family name decides its font menu group 2026-10-11 01:02:11 +00:00
aiongg f9985611bc Merge #411: Undo: a command that runs another is one undo step 2026-10-11 01:02:10 +00:00
con3codeandClaude Opus 5.5 65f0b37920 Fonts: system_fonts_cataloged builds on wasm
`cfg!` doesn't remove the expression, and `cataloged` only exists off
wasm, so `cargo xtask wasm` failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 10:00:17 +09:00
aiongg ef65f39b93 Integration: FontDb::system_fonts_cataloged builds on wasm (#394) 2026-10-11 00:53:49 +00:00
skylar taylor-barrick 2bdb0ea01d UI.9: recover saved docking metadata and declare frontend MSRV 2026-10-10 18:52:20 -06:00
con3codeandClaude Opus 5.5 52ffb3c68a Fonts: a pan-CJK font's family name decides its font menu group
A font of a pan-CJK family lists the code pages of every language it
covers. With no `meta` languages and no CJK family name, the first group
in menu order won, so a Simplified Chinese face such as "… Noto Sans CJK
SC" was listed under Japanese.

When a font lists several CJK code pages, the region tag in its family
name (JP; SC, CN, GB; TC, HK, TW, MO, HC; KR — a whole word in capitals)
now decides, if the font lists that language. Fonts with one CJK code
page, or none, are grouped as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 09:50:51 +09:00
aiongg 54b9a4d314 Merge mojikumi-base: CJK: custom mojikumi tables without a base set apply their rules
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-11 00:47:10 +00:00
aiongg 11631cde12 CJK: custom mojikumi tables without a base set apply their rules 2026-10-11 00:42:47 +00:00
aiongg 12ea53f10e Merge #404: SVG: a font family named in any case finds the installed font 2026-10-11 00:40:54 +00:00
sanyamsingh001andCodex 79601ed48d docs: avoid unrelated roadmap changes
Co-Authored-By: Codex <codex@openai.com>
2026-10-11 10:35:11 +10:00
aiongg f1b4b0cf49 Merge #394 update: UI: CJK interface text from installed fonts, on the Latin baseline
# Conflicts:
#	crates/ui-egui/src/theme.rs
2026-10-11 00:35:02 +00:00
noah1400andClaude Opus 5.5 ad173006f7 Undo: a command that runs another is one undo step (#406)
Cut, Duplicate, Paste in Place, the Arrange commands and pasting text
run a second command inside themselves, and both recorded an undo
step: the second Undo did nothing. Only the outer command records now.
A command that fails after changing the document records its step
too; a script that stopped at a bad step left changes that could not
be undone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:34:43 +02:00
aiongg d666f0e312 Merge #393 update: UI: no crash on textures past the GPU limit
# Conflicts:
#	crates/ui-egui/src/canvas.rs
2026-10-11 00:32:52 +00:00
aiongg ee0b462446 Merge #309 update: Snap: smart guides beat the baseline grid; a box centres between two others 2026-10-11 00:32:23 +00:00
aiongg 0946f5931d Merge #305 update: Preserve explicit nullable text defaults when reopening documents
# Conflicts:
#	ROADMAP.md
2026-10-11 00:32:22 +00: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
aiongg ecdb9b2dc2 Integration: rustfmt after merging #389-#392, indd 8 and 9 2026-10-10 23:52:24 +00:00
aiongg 9d717ea417 Merge cjk-run-baseline: CJK: smaller runs align to the line's em box centre
Conflicts:
- crates/fonts/src/fontdb.rs, vertical.rs: next's em cache
  ((top, bottom), declared) with FontFace::declared_em_box and the ICF
  cache/icf_box kept; the branch's base_em_box accessor dropped (same
  value). em_box's fallback chain takes the branch's let em form.
- crates/compose/src/lib.rs: next's cjk_icf_box and the branch's
  alignment_em_box, which reads declared_em_box.
- crates/compose/src/tests.rs: both tests. next applies character
  alignment only under the Japanese composers (5dc8383a), so the branch's
  smaller_cjk_run_aligns_to_the_line_em_box_centre runs under japanese();
  next's cjk_em_center_alignment_moves_small_characters measures centres
  on the alignment em box (declared, else 0.88/-0.12 em).
2026-10-10 23:49:04 +00:00
aiongg 778a270f48 Merge smallcap-tounicode: PDF: small caps and substituted figures keep their text
Conflicts:
- crates/pdf/src/text.rs run_text: the branch's two generated_text
  branches first, then #392's kashida branch (no text), then the cmap
  fallback for other inserted glyphs.
- crates/compose/src/lib.rs: next's kashida PlacedGlyph (with dx) gets
  generated_text: None.
- crates/compose/src/shape.rs hyphen_after: next's rendered_char/moji
  resets and generated_text = None.
- crates/compose/src/ruby.rs: next's ruby module (#363); the branch's
  edit to the old ruby set() has nothing to apply to.
- crates/pdf/src/tests.rs: tests from both.

Also, so the merge compiles: next's ruby (ruby.rs annotate) and kenten
(kenten.rs shape_mark) PlacedGlyph literals take generated_text: None;
they map back through the font like other inserted glyphs. Kanji page
numbers, composite-font note numbers and fallback-face label segments
go through shape_segment's replacement and list labels through
prepend_label, so they carry their generated text.
2026-10-10 23:47:37 +00:00
aiongg 8806a223fa Integration: shatai glyphs in right-to-left lines draw inside the line span (#392)
next's shatai path draws a slanted glyph on its own through tagged_run,
which opens a Span; inside #392's right-to-left line span that nested
marked content and krilla panicked ("can't start marked content twice")
in tagged exports. While a line span is open, the glyph is drawn with
run like the line's other runs. Test:
shatai_glyphs_in_right_to_left_lines_stay_in_the_line_span (panicked
before).
2026-10-10 23:46:28 +00:00
aiongg 93924a00b3 Merge pdf-rtl-text: PDF: right-to-left text extracts in reading order
No conflicts.
2026-10-10 23:45:02 +00:00
aiongg a386c73d82 Integration: PDF crop box is part of an asset's identity; clippings keep anchored graphics (#391)
Asset::same_file compares pdf_crop (#362) with type, page and bytes: one
PDF page shown with two crop boxes keeps two assets, so add_asset,
adopt_asset, insert_asset (IDML/INDD import) and the load/save merge
never point a placement at another crop. Test in
identical_files_share_one_asset.

The copy clipping (edit.rs clip_doc) keeps the assets used_assets finds
in it, so graphics anchored in copied text, graphic table cells (#379),
notes and media posters keep their files; it collected only graphics on
the copied items before. Test:
copied_text_frames_keep_the_graphics_anchored_in_their_text.
2026-10-10 23:44:15 +00:00
aiongg cfd57cb3ca Merge asset-dedupe: Assets: one asset per image, and saves leave out unused ones
Conflicts:
- crates/engine/src/cmd/{datamerge/fill.rs, file.rs, mathexpr.rs,
  media.rs, table.rs}: the branch's add_asset calls, with next's Asset
  fields (pdf_crop, pdf_box) through ..Default::default(); file.place
  keeps next's PdfCrop-aware asset (crop_pdf) and adds it with add_asset;
  the data merge graphic keeps next's wrap field.
- crates/format/src/lib.rs: load runs next's upgrade(doc, version), then
  merge_duplicate_assets (zip and legacy JSON); tests from both, with the
  round-trip test placing its asset (saves drop unused ones).
- crates/idml/src/import.rs graphic(): the branch's linked_assets reuse and
  insert_asset, with next's PDF page and PdfCrop on the asset and the
  graphic's text wrap (#389 integration) in the shared graphic closure.
  linked_assets is keyed by (path, page, crop), so placements of one PDF
  showing different pages or crop boxes keep separate assets.

Also, so the merge compiles: Asset/Graphic literals in the branch's tests
(crates/doc/src/assets.rs, format, engine links.rs) take next's pdf_crop,
pdf_box and wrap fields.
2026-10-10 23:41:30 +00:00
aiongg 27312c1cf9 Integration: feathers inherit from object styles; merge closes its functions (#390)
The merge of idml-feathers left overlay() in crates/idml/src/import.rs and
imports_and_round_trips_text_wrap_side_and_contour_type in tests.rs
without their closing braces (both sides added code at the same place);
this closes them.

Test: feathers_come_from_the_object_style_unless_its_category_turns_them_off
(gradient and directional feathers come from the style through
with_style; EnableGradientFeather="false" in
ObjectStyleObjectEffectsCategorySettings drops the style's gradient
feather; the item's own Applied="false" wins).
2026-10-10 23:38:21 +00:00
aiongg 15bcbae754 Merge idml-feathers: IDML: gradient and directional feathers import and export
Conflicts:
- crates/idml/src/import.rs, free functions: next's effect_flag/overlay
  (#389) and the branch's finite/gradient_feather_in both kept. The
  feather reads sit inside the TransparencySetting block, which next reads
  through with_style, so object style feathers are inherited and their
  EnableGradientFeather/EnableDirectionalFeather category flags apply.
- crates/idml/src/tests.rs: tests from both.
2026-10-10 23:37:23 +00:00
aiongg 75ce3f88e0 Integration: placed graphics take text wrap from their object style (#389)
A graphic element that names an AppliedObjectStyle reads its
TextWrapPreference through with_style, so mode, side, offsets and
ContourOption come from the style where the graphic sets none. Test:
text_wrap_side_and_contour_come_from_the_style_for_frames_and_placed_graphics.

Also: swatch_ref's doc comment sits on swatch_ref again.
2026-10-10 23:37:01 +00:00
aiongg 06baf887fb Merge idml-style-effects: IDML: frames take corners, effects and text wrap from their object style
Conflicts:
- crates/idml/src/import.rs, style chain helper: next's object_style_chain
  (trims BasedOn, ends with [None], cycle-safe) kept; the branch's
  style_chain dropped. with_style and attr_or_style use object_style_chain.
- import.rs corners: next's corner import over the object style chain kept
  (per-corner then all-corners at each level, InDesign default radius);
  the branch's second corner pass dropped, so corners are read once.
- import.rs text wrap: with_style(e, "TextWrapPreference") feeds next's
  shared text_wrap() reader (side, ContourOption, offsets) instead of the
  branch's inline TextWrap build.
- import.rs TextFramePreference: next's chain-aware text_frame_options
  with column rule colour kept; BaselineFrameGridOption read through
  with_style.
- crates/idml/src/tests.rs: test modules from both.
2026-10-10 23:37:01 +00: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>
v0.6.0
2026-10-10 19:33:30 -04:00
con3codeandClaude Opus 5.5 70cfd2d4fa UI: installed CJK faces are read once, without waiting for the font scan
- install_fonts no longer waits for the system font catalog on the first
  frame: the built-in faces are installed at once, the scan runs in the
  background, and the installed CJK faces are added when it is done.
- The installed faces are read once and shared: changing the interface
  language reorders them without copying the font files into egui again.
- fonts: line_metrics no longer sits between feature's doc comment and
  feature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 08:30:39 +09:00
aiongg 6b3d7c4ba8 Integration: installed CJK UI faces are read once per process (#394)
install_fonts caches system_ui_fonts in a OnceLock; the face bytes are
leaked once and borrowed (Cow::Borrowed) by each FontData, so a language
change reorders the faces without re-reading font files or copying them.
SystemFont.bytes is a Cow<'static, [u8]>.

Also: line_metrics no longer sits between feature's doc comment and
feature (crates/fonts), and the canvas texture test's frame closure
drops an unneeded mut.
2026-10-10 23:30:09 +00:00
aiongg 2b96dffda1 PDF: right-to-left text extracts in reading order
Lines with right-to-left text are wrapped in a marked span whose
ActualText is the line's text in reading order, so viewers that order
text by position (Preview, PDFKit) no longer return it reversed.

A base letter and its marks (Hebrew points) map glyph by glyph when
each glyph stands for one of the cluster's characters, and are drawn in
text order, so ToUnicode-only extraction reads each letter once with
its points after it. Marks stay in their run, placed by glyph offsets
(compensated for skew), instead of starting runs of their own.
Kashidas inserted by justification carry no text.

Fixes #392.
2026-10-10 23:29:46 +00:00
aiongg fbfc4eecf9 Merge #394: CJK interface text from installed fonts, on the Latin baseline
Conflict: crates/ui-egui/src/theme.rs install_fonts: the PR's
system_ui_fonts/add_system_fallbacks replace next's #126 system-font loop
(fallback_for per CJK sample char into system-ui-{id} faces when
CRAFT_FONTS is empty), so installed faces are not loaded twice. No #126
helper in theme.rs is left unused; FontDb::fallback_for stays (compose,
images use it).
2026-10-10 23:29:09 +00:00
sanyamsingh001andCodex 21fa11780c docs: avoid unrelated roadmap changes
Co-Authored-By: Codex <codex@openai.com>
2026-10-11 09:28:45 +10:00
aiongg daf1a0ccb3 Assets: one asset per image, and saves leave out unused ones
Placing a file that the document already holds reuses its asset (same
bytes, type and PDF page), in file.place, place.load, media and poster
placement, graphic table cells, math, data merge image fields, IDML
import (a linked file is read once) and paste/duplicate between
documents (which also maps ids that collide in the target).

Saving merges identical assets into the first and leaves out assets
nothing references; the open document keeps them for undo. Opening a
file saved with one copy per placement shares the identical bytes as
they are read and merges the assets. Package and Copy Links write only
used files, and links.list lists only used assets.

Refs #391
2026-10-10 23:28:24 +00:00
aiongg ea69df5bff Integration: canvas edits patch only a full-resolution texture (#393)
patch_texture writes full-resolution dirty rects with set_partial; when
upload() has shrunk the canvas texture to max_texture_side (a viewport
wider than the GPU limit), the edit takes a full render instead of a
partial write past the texture's bounds (a wgpu validation error). Test:
edits_patch_the_canvas_only_at_full_resolution.

The content ghost proxy goes through widgets::fit_texture (capped at 4096)
instead of skipping graphics larger than the limit.
2026-10-10 23:28:09 +00:00
con3codeandClaude Opus 5.5 cc836fe4df UI: an edit repaints a sampled-down canvas texture whole
patch_texture computed the damaged region in view pixels and wrote it
with set_partial into the canvas texture upload() had sampled down to
the GPU limit: a viewport wider than max_texture_side put the region in
the wrong place or outside the texture (a wgpu validation error on the
first edit). Such a texture is now rendered whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 08:25:43 +09:00
aiongg 9ba7e9e8c7 Merge #393: no crash on textures past the GPU limit
No conflicts.
2026-10-10 23:25:09 +00:00
aiongg 0c1d021dfd Integration: macOS menu bar rebuilds when Show CJK Features changes (#397, #336)
NativeMenu keys its rebuild on (language, cjk_features(app)), so the
CJK commands that menus::shown filters appear or disappear at once.
2026-10-10 23:24:57 +00:00
aiongg 3667fcc3a3 Merge #397: macOS menu bar follows the interface language at once
No conflicts.
2026-10-10 23:24:36 +00:00
aiongg 62fe6eb23b Merge #396: the welcome screen's Discord button clears the text beside it
No conflicts.
2026-10-10 23:24:27 +00:00
aiongg 153fa60054 Merge #388: Show the Pencil stroke while drawing
Conflict: crates/ui-egui/src/canvas.rs draw_tool_overlays: the PR's
Overlay::Path arm (draw_path_overlay) and next's Overlay::ContentGhost
arm both kept; draw_path_overlay sits before draw_content_ghost.
2026-10-10 23:23:48 +00:00
aiongg 0430763918 Merge #325 update: New Document in the progress docs
The PR was rebased onto upstream main; its code commits are unchanged
(range-diff shows only ROADMAP lines moved into the new docs commit), so
next already carries them.

Conflicts: crates/ui-egui/src/{dialogs.rs,i18n.rs,i18n/it.rs,lib.rs}:
next's versions (the old PR code plus next's own dialogs, findFont and
numberingSection work). ROADMAP.md and docs/target-app-parity.md take the
PR's New Document entries.
2026-10-10 23:22:41 +00:00
aiongg 505e748aac IDML: gradient and directional feathers import and export
Import reads GradientFeatherSetting (Applied, Type, Angle, Length,
GradientStart, first and last OpacityGradientStop) and
DirectionalFeatherSetting (Applied and the four widths) on page items.
Export writes both when the effect is on.
2026-10-10 23:21:17 +00: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 5d872fbf1e IDML: frames take corners, effects and text wrap from their object style
A page item takes every value it lacks from its applied object style and
the styles that one is based on, attribute by attribute: corner shapes and
radii, TransparencySetting (blending, drop shadow, feather), text wrap,
text frame options, the baseline frame grid and frame fitting. Nested
elements merge level by level. Effects whose category the applied style
turns off come from the item alone.

Export writes the column rule attributes on every frame, so a frame keeps
its own rule settings over those of its object style on import.

Fixes #389.
2026-10-10 23:21:08 +00:00
aiongg 279309ad12 PDF: small caps and substituted figures keep their text
Generated glyphs (page numbers, section markers, list labels) carry the
text they were shaped from, so a figure the font substitutes under small
caps or other OpenType features extracts as the digit instead of U+FFFD.
2026-10-10 23:19:21 +00:00
aiongg 351ccebe86 CJK: smaller runs align to the line's em box centre
Character alignment (em box top, centre, bottom) measured each glyph's em
box from its font's ascender/descender proportions, which puts a Latin
font's em box centre too low, so a smaller CJK run in a Latin line sat
below the line's em box centre. Alignment now uses the font's BASE em box,
else 0.88 em above and 0.12 em below the baseline.
2026-10-10 23:17:09 +00:00
con3codeandClaude Opus 5.5 6252dc3737 UI: the welcome screen's Discord button clears the text beside it
The community card is wider and its text wraps before the button's
space, so a longer translation of the line under the title no longer
runs under the button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 07:49:49 +09:00
con3codeandClaude Opus 5.5 cc12ea576f macOS: the menu bar follows the interface language at once
The system menu bar was built once at launch, so Edit › Interface
Language changed the panels but left the menus in the old language
until the next launch. It is rebuilt when the language changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
2026-10-11 07:49:21 +09:00