Commit Graph
123 Commits
Author SHA1 Message Date
Brandon Thomas 6ac858602f Merge PR #372 2026-10-15 00:35:27 -04:00
Brandon Thomas 7acf0f95bc Merge PR #317 2026-10-15 00:35:27 -04:00
Brandon Thomas bdda458b5b Merge PR #302 2026-10-15 00:35:26 -04:00
Brandon Thomas 2aeeea345a Merge PR #918
# Conflicts:
#	crates/compose/src/notes.rs
2026-10-14 23:05:24 -04:00
Brandon Thomas 7ed56979c7 Merge PR #977
# Conflicts:
#	crates/compose/src/tests.rs
2026-10-14 22:33:58 -04:00
Brandon Thomas f9b4660ca2 Merge PR #976
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 22:33:58 -04:00
Brandon Thomas 3bf5cb58a6 Merge PR #828
# Conflicts:
#	crates/compose/src/tests.rs
2026-10-14 22:33:54 -04:00
Brandon Thomas e6d6affb37 Merge PR #796 2026-10-14 22:33:52 -04:00
Brandon ThomasandClaude Opus 5.5 edfc98ffd7 fix: integrate batched community PRs (main's new tests with #559's FrameSpec.section_marker and #604's load_document_fonts guard)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:05:13 -04:00
Brandon Thomas 6c2064ae48 Merge PR #949 2026-10-14 22:05:12 -04:00
Brandon Thomas 3cdda36680 Merge PR #657 2026-10-14 22:05:11 -04:00
Brandon Thomas 0e63dcad11 Merge PR #604 2026-10-14 22:05:10 -04:00
Brandon Thomas 1495575c19 Merge PR #589 2026-10-14 22:05:10 -04:00
Brandon Thomas 54400d8d91 Merge PR #584 2026-10-14 22:05:10 -04:00
Brandon Thomas 71cf3671f1 Merge PR #565 2026-10-14 22:05:10 -04:00
Brandon Thomas f268e17986 Merge PR #559 2026-10-14 22:05:10 -04:00
moppeeerandClaude Opus 5.5 ccf4f4aee4 An empty last paragraph isn't overset text, as in InDesign
A story that ends with a paragraph return has an empty last paragraph. When
it didn't fit, DesignCraft marked the story overset at the end of its text
(Preflight: "Overset text: 0 characters"; the out port turned red).
InDesign doesn't: Montilla Design's Flex Layout file has a caption ending
with a return, fitted to its three lines, and InDesign reports no errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:40:50 +02:00
moppeeerandClaude Opus 5.5 d52ef6b6b9 A line is set when its baseline fits in the frame, as in InDesign
InDesign sets a text line when its baseline fits in the frame; the
descenders may hang below the frame's bottom. DesignCraft required the
baseline plus the descent to fit, so a frame sized to a heading's caps
oversets: Zero2Graphic's magazine tutorial draws 2.7682 cm frames for
103 pt headings (control bar, 4:12–5:44), and all three were overset.

The keep-lines IDML fixture's frames are now 236 pt tall, so they hold the
same 19 lines under either rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:18:55 +02:00
zydvc26s67-webandCopilot App 4516989e51 Type: let a blank line's hidden paragraph mark take leading immediately
Selecting an empty paragraph (a blank line) puts a collapsed caret on its
hidden paragraph mark, the only character on that line. Previously
type.char either deferred the formatting to the next typed character (in
a non-empty story) or dropped it on the floor for composition, so there
was no way to change a blank line's height — matching InDesign's ability
to select the pilcrow and adjust leading.

- engine/cmd/text.rs: recognize an empty paragraph's own caret position
  (empty_para_mark) and apply character attributes straight to that
  byte's run instead of deferring to typing format.
- compose/lib.rs: an empty paragraph has no glyphs of its own, so resolve
  the hidden mark's run (if overridden) for the paragraph's base leading
  instead of always falling back to the paragraph's plain default.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-14 12:05:35 -07:00
Claude 23105a6df9 Merge upstream main (0.8.0) into small-frame-wrap
Conflict: crates/compose/src/tests.rs, both sides added tests at the same place (upstream's #83 Jump Object tests, our tombstone tests); kept both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
2026-10-14 15:50:20 +00:00
Marco Arnulfo 8ce1292d0e Footnotes: Span Footnotes Across Columns sets notes across the frame (fixes #915) 2026-10-14 17:04:51 +02:00
Brandon Thomas c1ce6f77bf Merge PR #860 2026-10-14 01:54:39 -04:00
Brandon Thomas d34384574c Merge PR #853 2026-10-14 01:54:37 -04:00
0f4f382b0e feat(text): improve editing, snapping, and threading
Add multi-click text selection, pending caret formatting and clipboard support, text-aware colour controls, guide/grid snapping, and frame threading with loaded-port interactions.

Include the layout, drop-cap and IDML updates carried from #83, with safeguards for generated and linked stories, external text references, local IDs, locked frames and atomic colour edits.

Fixes #23.

Co-authored-by: Sean Hammond <sean.hammond@und.edu>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:41:46 -06:00
Seon-Jin YoonandClaude Opus 5.5 0aaaa9600d fix(compose): odd/even page starts keep their parity at the top of a frame
Start options were skipped for a paragraph at the top of a frame. That is
right for Next Page, Next Frame and Next Column (there is nothing to break
away from), but a Next Odd Page paragraph that lands at the top of an even
page stayed there, as did Next Even Page at the top of an odd page, and the
same went for odd and even page break characters. A part or chapter opener
whose previous section ended exactly at the bottom of an odd page therefore
opened on a left-hand page.

Cursor::start_at_top now moves such a paragraph to the next page of the
asked parity, for paragraphs, tables and break characters alike. Other
start options at the top of a frame are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 07:12:08 +09:00
noah1400 1bddba0e75 Compose: cross-reference index no longer rebuilds itself (#851)
The cross-reference index composed its destination stories through
the cache. One with a running header asked for the running-header
index, which composed the story holding the cross-reference, which
asked for the cross-reference index again: the stack overflowed and
the app aborted. Destination stories with a running header are now
composed without it, like those with cross-references already were.
2026-10-13 23:07:21 +02:00
Govinda RoyandClaude Opus 5.5 7e344e85f1 Compose: spaces at the end of a paragraph take no room on the line
The paragraph composer counted a trailing space (or several) before the
paragraph end or a forced line break in the line's width, so "2 VOOR " in a
frame exactly as wide as "2 VOOR" broke before "VOOR" and the frame went
overset. InDesign lets those spaces hang past the edge. They now add no
width; the line's visible range already left them out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:16:42 +06:00
aiongg d6f4c0133a fix(compose): text recomposes when the baseline grid, a wrap layer's visibility or section numbering changes (#718) 2026-10-13 14:18:20 +00:00
seanth b676d9aebe Merge branch 'storytold:main' into small-frame-wrap 2026-10-13 10:18:17 -04:00
Brandon Thomas a390905beb Merge branch 'pr/647' into batch1
# Conflicts:
#	crates/tools/src/lib.rs
#	crates/tools/src/tests.rs
#	crates/ui-egui/src/canvas.rs
2026-10-13 02:23:33 -04:00
Brandon Thomas 9bd099c0ae Merge branch 'pr/639' into batch1 2026-10-13 02:23:11 -04:00
Brandon ThomasandClaude Opus 5.5 b70b586a16 fix(path-type): NaN-safe bracket clamping (f64::clamp panics on a NaN path length)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:22:34 -04:00
Brandon Thomas a0330b03a0 Merge branch 'pr/585' into batch1 2026-10-13 02:21:39 -04:00
sanyamsingh001andCodex e507b98601 PARITY-TAB-LEADERS: draw right-indent tab leaders
Co-Authored-By: Codex <codex@openai.com>
2026-10-13 10:51:50 +10:00
moppeeerandClaude Opus 5.5 f96895f400 feat(text): Edit type on a path along the curve
The Type tool's clicks, drags and double-clicks on type on a path went to
the character at the same spot of the straightened line, and the caret
and highlight were drawn straight. A click now finds the character where
its nearest point along the path is (compose::PathTextMap, from the line
to the path and back, as path_glyphs places the glyphs); the caret stands
across the path there and the highlight bends with the text. A click on
the letters, above the path, hits the frame.

Depends on #636 (PathWarp::nearest).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:35:58 +02:00
aiongg 270dd46b50 Text: stroke behind fill (#619)
A character attribute strokeBehindFill paints a text stroke under the fill
at double width, so its full weight lies outside the letters and they keep
their shape. Screen and PNG rendering, PDF export (stroke as outlines
first, then the filled text, so the text is not duplicated; clipped to the
outside of the glyphs when there is no fill), Create Outlines (outside-
aligned stroke), the Properties panel and Character Style Options.

IDML StrokeAlignment on CharacterStyleRange, CharacterStyle and
ParagraphStyle imports and exports as the attribute (OutsideAlignment =
on, CenterAlignment = off).
2026-10-12 21:06:42 +00:00
Marco Arnulfo de31bd5647 fix(fonts): fall back to a font made for Malayalam (part of #628)
Malayalam took the first installed file mapping it: on macOS Arial Unicode MS, which has no Malayalam shaping, so conjuncts like ക്ഷ fell apart. Fonts made for Malayalam are tried first, loaded on demand through the CJK chain lookup.
2026-10-12 23:03:22 +02:00
Isaac Levine d66f2c47ae Engine: route book chapters and atomic saves through the checked writers, and take file access out of fonts, IDML and ICC loading
Rebased onto the atomic save work: book chapter replacement, canonicalize and
the writability probe, and every command write now check the roots before
they reach crate::atomic. IDML import no longer reads linked images itself
(the engine passes its checked reader), load_icc_file is gone (profiles
arrive as bytes), the script loader goes through the host reader, and
FontDb::load_document_fonts asks a caller-supplied check about the folder and
each font file, so a link that leads out of the read root is skipped.
2026-10-12 16:50:04 -04:00
moppeeerandClaude Opus 5.5 cded7d997e feat(tools): Drag type-on-a-path start and end brackets
Selected type on a path shows its start and end brackets across the path,
as in InDesign, and the Selection and Direct Selection tools drag them
along it (Move Bracket, one undo step): the text starts and ends where
they are, and text past the end bracket is overset.

- doc: PathType.end (None: the path's end)
- geom: PathWarp::nearest, the arc length of the nearest point
- engine: type.pathOptions {end}; brackets stay on the path and can't cross
- compose: the line runs from the start to the end bracket
- idml: EndBracket read and written
- tools: Cursor::PathBracket

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:32:56 +02:00
moppeeerandClaude Opus 5.5 6880042c6a fix(compose): Hyphenation Zone applies to the Single-line Composer only
InDesign's Hyphenation Zone ("the white space allowed at the end of a
line of unjustified text before hyphenation begins") applies only with the
Single-line Composer. The Paragraph Composer, the default, weighs every
break of the paragraph instead. DesignCraft applied the default 3p0 zone
to both, so ragged paragraphs under the Paragraph Composer refused
hyphens InDesign makes. In LYH Studio's poster tutorial the placeholder
text breaks "aper-natem" and "mosticsia-tur"; ours ran a line longer.

The breaker now gets the zone only for unjustified Single-line Composer
paragraphs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:29:01 +02:00
Sean HammondandClaude Opus 5.5 1278957455 Text wrap: the minimum gap applies only where a wrap object reaches the column
free_slot held a column to the minimum gap width (1.5 em) whenever a wrap
object overlapped the line's band vertically, even if the object sat beside
another column of the frame: in a frame of narrow columns, an object beside
column 2 dropped column 1's lines. The minimum now applies only when the
object reaches the column itself (aiongg's review on #589).

Test: wrap_object_beside_one_narrow_column_leaves_the_other_alone (two
18 pt columns in a 14 pt paragraph, an object beside column 2) fails before
(overset) and passes after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
2026-10-12 15:14:08 +00:00
aiongg 152086b3ea Footnotes: notes stack baseline to baseline (#582) 2026-10-12 12:28:06 +00:00
Akash Bhat c310cf72ed fix(compose): enable Norwegian hyphenation patterns
Enable hypher/norwegian in designcraft-compose so no/nb/nn map to the bundled hyph-no.tex patterns. Add unit + composition regression tests, NOTICE attribution, and update parity docs.

Fixes #535.
2026-10-12 12:09:40 +05:30
Sean HammondandClaude Opus 5.5 0635dea065 Text wrap: small single-character frames (tombstones) are set beside text wrap
An article's closing tombstone - a one-character text frame, here a 7.6 pt
Noto Emoji symbol in a 10.5 pt box - was overset (red +, nothing drawn)
whenever its spread had a text-wrap object anywhere, while InDesign sets it.

Two causes in the wrap code:
- Every text frame took every wrap object on its spread as an exclusion,
  whether or not the object reached the frame. Now only objects that
  overlap the frame wrap its text.
- free_slot skips gaps narrower than 1.5 em of the paragraph's size
  (slivers beside a wrapped object), but applied that to the whole column
  too when nothing cut it: with a 14 pt paragraph style, no line could go
  in a frame narrower than 21 pt. The minimum now only applies to gaps a
  wrap object cut; a band no object reaches gets the whole column, however
  narrow.

On the document that showed it (an InDesign 2026 IDML with 12 tombstones and
two unrelated wrap objects on the spread), the 12 tombstone stories are set
and no other story's layout changes (54 -> 42 overset stories, all of the
difference the tombstones).

Tests: small_single_character_frame_sets_beside_unrelated_text_wrap and
narrow_frame_sets_lines_no_wrap_object_reaches fail before (overset) and
pass after.

Probably also #476 (Wingdings bullets overset in 20 x 21 pt frames).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
2026-10-12 06:16:04 +00:00
aiongg 406f1b3d26 Sections: the section marker shows the section's marker text (#556) 2026-10-12 05:09:40 +00:00
seanth a21e8db14f fix(compose): key parent-page compositions by absolute page index
Parent-page text now uses the absolute page index as its cache key, so repeated page numbers and renumbering do not reuse another page's composition.

Validation: targeted canvas and PDF regressions, plus all six cargo xtask ci gates on main after #514 (1,179 native tests passed, 3 ignored; 15 crates passed WASM compilation checks).

Task: #523
2026-10-11 21:27:52 -06:00
moppeeerandskylartaylor 95c8c9cc5b fix(hyphenation): honor capitalized-word settings for uppercase words
Honor the capitalized-word hyphenation setting for uppercase words and retain the current roadmap entries.

Validation: all six cargo xtask ci gates passed on the current main merge candidate; 1,170 native tests passed and all 15 WASM packages checked.

Task: #538

Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-11 19:32:49 -06:00
japbcoelhoandClaude Opus 5.5 2b46ca664c Hyphenation: Portuguese text is hyphenated with hyph-utf8's Portuguese patterns (#512)
Text set in Portuguese ("Portuguese: Brazilian", "Portuguese", pt_BR) got
no hyphenation, so justified Portuguese columns could only stretch their
word spaces (up to 335 % of the normal space in a 56 mm column of 10 pt
Times).

Turn on hypher's "portuguese" feature, beside Spanish: hyph-pt.tex 1.4
(2024-07-13) from hyph-utf8, BSD-3-Clause, credited in NOTICE.
Lang::for_language already maps the Portuguese names and locale codes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:39:53 -06:00
aiongg 0474a8b5ec Compose: jidori runs keep their width when their spaces could stretch; tests for nonbreaking-space lines 2026-10-10 19:22:22 +00:00
aiongg 42cfc8b06c Compose: No Break runs and nonbreaking spaces stretch on justified lines (#368) 2026-10-10 18:54:54 +00:00