Commit Graph
4115 Commits
Author SHA1 Message Date
aiongg a73d106ab4 UI: make the application bar's search field find and run commands 2026-10-11 12:47:27 +00:00
aiongg 6cf1933a13 Text: notes insert into a story whose markers lack payloads 2026-10-11 12:43:59 +00:00
aiongg 0de31ef27b Layout: a baseline shift doesn't move the Em Box Height first baseline
The line's em box top is measured at the unshifted baseline; the shift
moves only the drawn glyphs. CJK character alignment still counts. The
Ascent, Cap Height and x Height offsets keep counting a raised baseline.
2026-10-11 12:33:55 +00:00
aiongg d6309bae32 Text: copied text keeps its endnotes and editorial notes 2026-10-11 12:31:59 +00:00
aiongg d5fe4ec201 Integration: shatai glyphs in right-to-left lines always take a tagged run
8806a223 (next, for #392) drew a slanted glyph with run while a
right-to-left line span was open, so its tagged span would not nest in
the line span. pdf-rtl-text (8f30ba1c) removes the line span and its
line_span flag, so the glyph always goes through tagged_run. The
regression test keeps its export of tagged and untagged PDFs with shatai
Hebrew and checks what the branch's tests check: reading-order text,
no marked content opened inside an ActualText span, and no ActualText
wider than a word.
2026-10-11 12:28:34 +00:00
aiongg eda793e300 Merge pdf-rtl-text: PDF: right-to-left lines carry no line-wide ActualText 2026-10-11 12:24:45 +00:00
aiongg 941d8b29d5 Merge #464: Fonts: discover Linux user fonts in XDG_DATA_HOME
Conflict: crates/fonts/src/fontdb.rs: both — the PR's unix_font_dirs, then next's platform_font_files and unscanned_font_files
2026-10-11 12:24:41 +00:00
aiongg 8acb2fbdce Merge #463: Docs: explain hyphenation defaults and image fitting modes to agents
Conflict: crates/engine/src/cmd/text.rs: text.formatParagraph params doc keeps next's drop-cap fields and adds the PR's "hyphenate?: bool (default true)"
2026-10-11 12:24:26 +00:00
aiongg f25ca5cbc6 Merge #454: i18n: translate print, import and table controls
Conflict: ROADMAP.md: status line lists both changes (the PR's review date); progress log both lines, the PR's first
Conflict: crates/ui-egui/src/i18n/ja.rs (auto-merged, edited): the PR's ("All", "すべて") row dropped, next already has it
2026-10-11 12:24:17 +00:00
aiongg cde814c0df Selection tool: Alt and Shift resize around the centre and keep side-handle drags centred 2026-10-11 12:24:00 +00:00
aiongg 92b50683f6 Merge #474: Show the first parent page behind single-sided pages (#429)
Conflict: crates/doc/src/build.rs: next's parent_page_for (it calls Spread::parent_page_for_side); the PR's test kept
Conflict: crates/tools/src/snap.rs: shown_parent_page_index no longer exists (snap calls Spread::parent_page_for_side); the PR's test kept, calling parent_page_for_side on a two-page and a one-page parent
Conflict: crates/doc/src/page.rs (auto-merged, edited): parent_page_for_side picks the parent's first page for PageSide::Single, the PR's rule moved to where next makes the choice
2026-10-11 12:23:50 +00:00
aiongg de18c1833c Merge #472: Moving a sheared, rotated text frame leaves no text trails
Conflict: ROADMAP.md: both progress-log lines, the PR's first
2026-10-11 12:20:23 +00:00
aiongg 65db56a471 Integration: swatch references bump the story revision with wrapping_add
#456 makes every story revision increment wrap; next's swatch_refs.rs (added after the PR's base) still used rev += 1.
2026-10-11 12:20:13 +00:00
aiongg 9ed4aba3da Merge #456: Wrap saved story revision counters consistently
Conflict: crates/doc/src/edit.rs: next's thread_frames (append_story); every rev += 1 is rev.wrapping_add(1)
Conflict: crates/engine/src/cmd/fonts.rs: next's replace (the local-formatting pass moved out of this hunk)
Conflict: crates/engine/src/cmd/text.rs: next's format_chars (apply_char_attrs, typing format); rev += 1 is rev.wrapping_add(1)
2026-10-11 12:20:08 +00:00
aiongg d5a6eca36d Merge #427 update: Text: Optical kerning spaces pairs from their outlines
Conflict: Cargo.lock: next's (the PR's dependency is already on next)
Conflict: ROADMAP.md: next's (the PR's earlier head is already merged)
Conflict: docs/gaps.md: next's (the PR's earlier head is already merged)
Conflict: docs/typography-parity.md: next's, test count 170 -> 172 as in d0120bf6
Conflict: crates/compose/src/optical.rs: next's plus d0120bf6's kernable() dash and fullwidth exclusion and its unit test
Conflict: crates/compose/src/tests.rs: next's plus d0120bf6's optical_kerning_leaves_dash_pairs_alone
2026-10-11 12:19:35 +00:00
LosminekandClaude Opus 5.5 b3d256c817 i18n (cs): terminology review fixes
Changes from an independent review pass over the Czech catalog:

- meaning: "Fit Text" resizes the frame to the text, not the text; the nested
  style "New Line Style" is a style for lines of text, not for strokes;
  "Liquid Settings", "Nonbreaking Space/Hyphen" and "Discretionary Hyphen" use
  the common Czech terms
- consistency: a story is "text" and an article is "clanek" (they were both
  "clanek"); "Tags" matches "Novy tag"/"Odebrat tag"; "Float Panel" matches
  "Float panel"; Image = "Obrazek" like the other image labels; Remove =
  "Odebrat"; one name for the Utilities menu that no longer clashes with Tools
- grammar and shape: command-like labels (Essentials, Wavy, Metrics, Optical,
  Both, Restart Numbering, Output All Blacks...) and a stray "(" fixed

Strings that need a code change to be right in every place (digit set names
that share keys with languages, nested-style units after a number, the
Crop/Trim/Media combo) are left as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:11:32 +02:00
MarekSpodBiedry 233aef8986 Fix needless horizontal scrollbar in the app bar at 115% scale (#481) 2026-10-11 13:51:42 +02:00
LosminekandClaude Opus 5.5 332723a58e i18n: tests for the Czech catalog, plural counts and language switch
- Every Czech row is looked up through the cached tr(), and an unknown
  label passes through unchanged.
- No duplicate or empty rows; placeholders, trailing ellipses and colons
  and padded captions match the English key. Only stale rows fail: keys
  that no catalog, command label, menu name or UI command knows any
  more. A new English string falls back to English, as in #294.
- count_label("cs", ..) gives the one / few / other form for 0, 1, 2,
  4, 5, 11 and 22, and the Group selection title uses its context row.
- Czech is selectable from the menu, persisted in UiState and leaves
  document data untouched; it joins the language switch geometry test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:50:24 +02:00
LosminekandClaude Opus 5.5 8178e15ddd i18n: Czech in Edit > Interface Language, with plural count captions
Register "Čeština" (cs) in LANGUAGES, the Interface Language menu and
the app.language parameter doc, and look it up in tr() like the other
single-language tables. tr_context() uses the Czech CONTEXT rows.

count_label() picks the Czech plural form for the number (1 chyba,
3 chyby, 5 chyb; 1 stránka, 3 stránky, 5 stránek), so the info panel,
the Preflight panel and the status bar read grammatically for every
count. Nouns without plural forms keep the existing "{count} {noun}"
caption; other languages are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:50:13 +02:00
LosminekandClaude Opus 5.5 23ae46dbee i18n: Czech interface catalog (1,722 strings)
Add crates/ui-egui/src/i18n/cs.rs in the shape of ar.rs, it.rs, ja.rs and
uk.rs. It has a row for every key of the shared table and of the Arabic,
Brazilian Portuguese, Italian, Japanese and Ukrainian tables (1,697
strings), plus 25 labels the code passes to tr() that no catalog had yet
(data merge and composite font commands, panel docking, the unsaved
changes dialog, W:/H: in the control bar).

Translated from the meaning of the English strings with ordinary Czech
desktop-publishing vocabulary; no other product's localization was used.
Phrases that the MIT OR Apache-2.0 Czech catalogs of VectorCraft and
PhotoCraft already use are kept identical for consistency across
ArtCraft and credited in ASSETS.md.

The file also holds PLURALS (one / few / other forms for the count
captions) and CONTEXT (the Properties panel title "Group" is a noun,
the menu command is a verb). The next commit wires them in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:49:17 +02:00
noah1400 0a9bfa5735 UI: Alt + wheel zooms the view at the pointer (#470)
The wheel turned over a document view with Alt (Option) held scrolled
the view like the plain wheel. It now zooms at the pointer, exactly as
Ctrl/Cmd + wheel does. As with that zoom, a wheel motion keeps its key
to its end: letting Alt go while a trackpad swipe coasts on does not
turn the rest into scrolling.
2026-10-11 13:41:07 +02:00
Abdelrehman Fouad d0120bf6a6 Text: Optical kerning leaves dashes and fullwidth forms alone
Two dashes end to end have no ink gap to measure, so -- and the double
em dash opened up by the loosen cap; Chinese sets —— as one continuous
rule. Fullwidth Latin (U+FF21–FF5A) was kernable through its Latin
script and moved CJK text off its em grid. Both are now excluded from
kernable(), with a unit test and a compose test that failed before.
2026-10-11 11:45:29 +02:00
MarekSpodBiedry 30cbd67e3d Honor IDML SameParaStyleSpacing between same-style paragraphs (#449) 2026-10-11 11:43:38 +02:00
MarekSpodBiedry 5ab84500fe Show the first parent page behind single-sided pages (#429) 2026-10-11 11:40:56 +02:00
moppeeerandClaude Opus 5.5 3943e4c8b7 Repaint a moved text frame's whole text box
Text is composed in the box around a frame's path in the frame's own
coordinates. A sheared then rotated frame turns that box past its path's
bounds, which was all a move repainted, so its text left trails behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:39:41 +02:00
Abdelrehman Fouad d02a220b4e 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 11:39:20 +02:00
Middle DiscandClaude Haiku 5.5 2b55f2ed0d Layout: parent-page margins and guides, Create Guides on the current page, ruler-unit-aware Margins and Columns
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRYQ5eieuUrtxhdbh6goq
2026-10-11 12:16:18 +03:30
KnottyDyes 97b753619a Docs: explain hyphenation defaults and image fitting modes to agents
Command descriptions left the new-text hyphenation default and image fitting outcomes implicit. State the default and each fitting mode's semantics, and add an MCP example that disables hyphenation. No behavior changes.
2026-10-11 01:26:26 -06:00
sanyamsingh001andCodex f58c212289 QA1: wrap saved story revisions consistently
Co-Authored-By: Codex <codex@openai.com>
2026-10-11 16:30:58 +10:00
Ikki Nishihara 8143cb2a7d i18n: translate print, import and table controls
Route visible labels through the existing translation and RTL helpers.
Keep document commands, stored options and user-defined style names intact.
Update the localization status and roadmap progress log.
2026-10-11 14:44:39 +09:00
aiongg 7eb3b2ac5a Integration: the Tabs panel floats outside the docking layout
atomic-say brings upstream's shared panel docking (#409), which sends
float_panel and dock_panel through the docking registry; next's Tabs panel
is float-only and not registered there, so Type > Tabs failed with "panel
must name a registered panel". Float-only panels keep the legacy floating
list: they float and close without the registry, a customized layout
keeps them in that list, and dock::floating still draws them then.
2026-10-11 05:35:53 +00:00
aiongg 8f30ba1c55 PDF: right-to-left lines carry no line-wide ActualText
poppler positions an ActualText with the transform in force where its
span ends; a line span closes outside the runs' transforms, so pdftotext
placed the line text off the page and dropped it. An ActualText per run
fares no better: poppler reverses its characters in a right-to-left
line. Without them, poppler orders the glyphs of right-to-left lines
itself and extracts whole lines in reading order, and the content stream
keeps listing them in reading order. With no line span left, glyphs in
it no longer need to avoid krilla's cluster spans, so that workaround
goes too. The tests that read the line span's ActualText now check that
ActualText never spans more than a cluster.
2026-10-11 05:33:12 +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 924a78a2dd Merge feat/layout-parity: Layout: only CJK fonts take the em box top from a one-em typo box
Conflict: crates/compose/src/tests.rs: next's baseline-fit and keep tests, then the branch's OS/2 offset doc and code-page constant
Conflict: crates/fonts/src/tests_vertical.rs: testing imports from both (with_base, with_code_pages)
2026-10-11 05:19:16 +00:00
aiongg c94d7ce8c8 Merge mojikumi-base: CJK: mojikumi tables based on Nothing and the one-em line-end set apply their rules
Conflict: crates/compose/src/tests.rs: next's tests, plus the branch's one-em line-end test after its neighbour
2026-10-11 05:18:58 +00:00
aiongg b77ed8c300 Merge fix/idml-interchange: PDF: Bounding Box crops are measured from the page's drawing, not a render 2026-10-11 05:18:36 +00:00
aiongg 0d05035e65 Integration: thread cursors have system cursors in the tool cursor table
tool-cursors moves the cursor-to-system-icon table into cursors.rs; next's
text threading adds Cursor::ThreadLink and Cursor::Unthread. They keep the
icons next gave them (alias, no-drop) under the loaded-text badge.
2026-10-11 05:18:36 +00:00
aiongg 7c6bb39656 Integration: close the live-corner test before the pen cursor tests
The tool-cursors merge (ba6fcbe2) appended the branch's pen cursor tests
after next's live_corner_diamonds_follow_a_rotated_frame without that
test's closing brace.
2026-10-11 05:18:07 +00:00
aiongg ba6fcbe26a Merge tool-cursors: Canvas: tools show their own cursors (Direct Selection, Pen states)
Conflict: crates/tools/src/tests.rs: both sides' tests (thread ports, pen add/delete)
Conflict: crates/ui-egui/src/canvas.rs: the branch's cursors::show for the icon, then next's loaded-text/thread badge; next's cursor_icon dropped for cursors::system
Conflict: crates/ui-egui/src/lib.rs: DesignApp fields from both sides
2026-10-11 05:17:24 +00:00
aiongg 2352a58b7d Merge tool-icons-swap: Tools panel: Selection is the filled arrow, Direct Selection the hollow one 2026-10-11 05:16:40 +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 0437ab27f5 PDF: Bounding Box crops are measured from the page's drawing, not a render
Finding a placed PDF's Bounding Box crop rendered its page at 2048
pixels and took the bounds of the painted pixels. PDF export measures
every such crop that import left unmeasured, so exporting a 17-page
document that places one complex illustration took about 4 s longer
than before crops were supported. The box is now the union of the
page's painted paths (strokes included), glyphs and images, each cut
to its clip, collected by interpreting the page without rasterizing
it: the same box, exact instead of to the nearest pixel, in
milliseconds.

Test: content_crop_box_is_measured_without_rendering_the_page.
2026-10-11 04:56:32 +00:00
aiongg a81fb0be62 PDF: glyphs in a right-to-left line's span open no ActualText span of their own
krilla wraps a mark cluster that maps to several glyphs, and a glyph drawn
with other text than its font already maps it to, in an ActualText span.
Inside a line's ActualText span that nested the spans, and poppler drops
the text before a nested span. Inside a line span each glyph now gets the
text its font maps it to (the exporter keeps a copy of krilla's mappings),
a cluster's text goes to its first glyph, and a run splits into separate
draw calls where two glyphs in a row would share an empty range. A run
drawn through tagged_run inside a line span takes the span as its tag.
Test: mark_clusters_in_right_to_left_lines_open_no_span_of_their_own
(5 nested spans before).
2026-10-11 04:45:20 +00:00
aiongg 45032b527f CJK: mojikumi tables based on Nothing and the one-em line-end set apply their rules 2026-10-11 04:38:04 +00:00
aiongg 58f0e8c9b7 Layout: only CJK fonts take the em box top from a one-em typo box
A font's em box is its BASE em box; else, for a CJK font (its font
menu group isn't Western: meta or name languages, CJK code pages, else
kana, Hangul or ideograph coverage), the OS/2 typo ascender when the
typo ascender and descender span exactly one em; else 0.5 em + cap
height / 2; else 0.88 em. Latin fonts with a one-em typo box, such as
DejaVu Serif, centre on the cap height.
2026-10-11 04:28:46 +00:00
aiongg 56c8ed9667 Canvas: tools show their own cursors (Direct Selection, Pen states)
Tool cursors are glyphs drawn in code (black ink, white halo): the filled
arrow for Selection, the hollow arrow for Direct Selection, the pen nib
with an add, delete, close or convert badge, and a curved double arrow
for rotating. Linux and Windows show them as OS cursor bitmaps,
rasterized per pixels-per-point and cached; macOS paints them at the
pointer, since it sizes cursor bitmaps in points; the web build keeps
the system cursors. Text, hand, zoom and resize cursors stay system
cursors.

The Pen tool reports what a click does: over the first anchor of the
path being drawn it closes the path, and between paths a click on a
selected path's anchor deletes it and a click on its outline adds one.
The Add, Delete and Convert Direction Point tools show the matching pen
badges.

The glyph geometry and the rasterizer are adapted from VectorCraft's
code-drawn tool cursors (same organisation, original work).

Fixes #438
2026-10-11 04:12:43 +00:00
aiongg 1a8df25fdd MCP: exported files replace the target atomically (#436) 2026-10-11 04:12:32 +00:00
aiongg 11f34a07f3 Files: saves and exports replace the file atomically
Documents, books, libraries, snippets, swatches and every export are
written to a temporary file beside the target, flushed, renamed over it
and the folder flushed, so a crash, kill or full disk mid-write leaves
the old file intact. Replaced files keep their permissions, symbolic
links keep pointing at their file, and Windows retries a rename that a
scanner briefly blocks.

Fixes #436
2026-10-11 04:01:22 +00:00
aiongg 63375bc84d Tools panel: Selection is the filled arrow, Direct Selection the hollow one
Fixes #437
2026-10-11 03:54:51 +00:00
Wladmir Júnior b522a0a3e8 pt-BR: complete the interface translation 2026-10-11 00:44:04 -03:00