#325 adds fifteen File › New › Document strings to the shared table; next's de.rs (#311) keeps a
row for every shared key. The rows carry over the shared table's German column, so lookups are
unchanged.
Conflict: crates/ui-egui/src/lib.rs: both modules kept, mod new_document before mod object_control
Conflict: crates/ui-egui/src/dialogs.rs: the PR's translated ok_label plus next's findFont arm, translated the same way ("Replace All"); cancel_label is a match: newDocument "Close", findFont "Done", else "Cancel"
Conflict: crates/ui-egui/src/i18n/it.rs: both blocks kept (next's machine-translated and Tabs rows, then the PR's File › New › Document rows)
#343 adds its twelve Tabs strings to the shared table; next's ja.rs (#272) keeps a row for every
shared key. The rows carry over the shared table's Japanese column, so lookups are unchanged.
#343 adds its twelve Tabs strings to the shared table; next's de.rs (#311) keeps a row for every
shared key. The rows carry over the shared table's German column, so lookups are unchanged.
Conflict: ROADMAP.md: both lines kept (next's IDML1 line, then the Tabs panel line)
Conflict: crates/engine/src/cmd/mod.rs: both spec lists kept (thread::specs, then tabs::specs)
Conflict: crates/ui-egui/src/dialogs.rs: next's delete_paragraph_style and the PR's style_tabs both kept, without the section_list doc comment that next removed; in the tests the PR's copies of draw, ruled_paragraph, undo_steps, the rule tests, command_app, the generic command tests and the text frame options test duplicated next's identical ones and were dropped, keeping only the PR's new Tabs section test
Conflict: crates/ui-egui/src/i18n/it.rs: both blocks kept (next's machine-translated rows, then the Tabs rows)
Conflict: crates/ui-egui/src/i18n/uk.rs: both blocks kept (next's machine-translated rows, then the Tabs rows)
Type › Tabs (Cmd+Shift+T) floats a Tabs panel: alignment buttons, X,
Leader and Align On fields, and a ruler where a click adds a stop, a
drag moves it and dragging it off the ruler deletes it. The triangles
on the ruler drag the first-line, left and right indents. The panel
menu has Clear All, Delete Tab, Repeat Tab and Reset Indents. The panel
opens above the selected horizontal text frame with the ruler at the
view's zoom over the column; the magnet button places it there again.
type.tabs.* edit the stops of the selected paragraphs or, with a style
parameter, of a paragraph style. Positions are finite and clamped, a
paragraph holds at most 100 stops, leaders up to 8 characters and the
align-on character is one character. type.tabs.get reports the stops,
indents and the text column they are measured in.
#336 adds the Show CJK Features string to the shared table and the ja, ar, pt_br, it and uk tables; next's German table (#311) covers every key of those tables, so it gets a row too (machine translation, the shared table's German column).
Conflict: ROADMAP.md: next's Right-to-left and Interface language lines (IDML Kashidas, German and Japanese cover every catalog, Ukrainian covers every key) plus the PR's Show CJK Features line
Conflict: crates/ui-egui/src/lib.rs: the PR's cjk_features() before next's opens_as_document (with .indd/.indt and its doc comment)
Preferences > Type > Show CJK Features (cjkFeatures; unset follows the
interface language: on for Japanese, Chinese and Korean) hides the
CJK-only Type menu items (Tate-Chu-Yoko, Ruby, Kenten, Warichu) and the
Ruby Quick Apply entry. The commands, layout and IDML work either way.
Static families such as Alexandria name every weight's legacy family
"Alexandria <Weight>" with subfamily "Regular". Matching names and aliases in
one pass let the first such face (Black) answer for Regular, so text set in
Regular came out in Black, wider, and pushed lines into overset.
(cherry picked from commit 681a3ec499834b866dd18244e5b25b425c682b10)
File > New > Document now shows Recent, Saved, Print, Web and Mobile
tabs of page cards (drawn to the preset's proportions; double-click
creates) beside the preset's details: document name, width and height
with arrows, units, orientation, pages, start page #, facing pages,
primary text frame, columns and gutter, and collapsible margins and
bleed and slug per edge with link toggles. Save Document Preset keeps
presets by name; documents made are remembered for the Recent tab.
Small windows stack the details above the presets and scroll; the
layout mirrors for right-to-left languages. New strings go through the
translation tables (Italian, German, French, Spanish, Japanese, Chinese).
file.new takes intent, units, startPage and per-edge bleed and slug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nested repetitions such as ((a)*)* asked the group below for the same end
positions again and again, which is exponential in their depth: remember
the positions of a group per start position while one element's children
are matched. The search for the closing semicolon of a parameter-entity
reference had a 256-byte window, so a longer name was left unexpanded
without an error: stop the search at whitespace or the next percent sign
instead, which keeps a round linear and puts no limit on the name.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Every IDML root style carries LeadingModelAkiBelow and AlignEmCenter, but only
the Japanese composers (HL Composer J, HL Single J) use them; the Adobe and
World-Ready composers set lines baseline to baseline with every character on
the Roman baseline. Applying them everywhere moved lines down after a size
change and lowered smaller-em glyphs, pushing the last lines of tight frames
(and whole keep-together paragraphs) into overset.
Composer gains Japanese and JapaneseSingleLine, read from and written to IDML;
the composer choice in the UI keeps the kind.
Automatic page numbers (and section markers) were set from the page name as
typed, so a page number in Hindi Digits text drew Western digits, which an
Arabic-only font shows as missing-glyph boxes. They now map their digits like
typed text does.
#83 adds native format 2 and an upgrade that pins Keep Lines Together and Align Left Edge where a format-1 style chain leaves them unset. #305's tests save the same document as native ZIP and as legacy JSON (format 1) and compared both as whole documents. The base style now sets both attributes, and only the native ZIP is compared as a whole document; the nullable resolution is checked for both.
When OS/2 has no usable sCapHeight / sxHeight, the face measures them from the
unhinted outlines of flat-topped letters (H I E T for cap height, x z v for
x-height) at the face's variation location, and falls back to a share of the
ascent only when none of those letters has a plausible outline. Measuring
outlines instead of the glyf bounding box also covers CFF and variable fonts.
Based on seanth's measurement in #292.
Co-authored-by: Sean Hammond <sean.hammond@und.edu>
A run that begins with combining marks, after a run that differs only in
OpenType features (ligatures, kerning, OTF features), now gives those marks
to the run before it. The shaper attaches each mark to its base, and a
missing font's fallback draws the mark in the same face as its letter
instead of the substitute's missing-glyph box. Runs in another font, size
or colour keep their marks.
Parameter entities were expanded by up to eight rounds of text.replace
per entity over the whole text, so a few hundred bytes of DTD grew
exponentially and a large one cost entities x length per round. Expand
them one scan per round with a map, bound the result and the depth, and
refuse cycles. Content-model groups recursed once per parenthesis with
no limit (a stack overflow), and the positions after each item of a
sequence were kept as a list of paths (2^n for n optional items): limit
the nesting and keep the positions a set.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
#311's de.rs translates "Select an object to color its fill or stroke."; #81/#84 on next say "Select an object or text to color its fill or stroke.", so the German interface showed it in English. The row takes the new key.
Conflict: crates/compose/src/tests.rs: tests only, both (#310's tight word spacing test, #316's GREP style test)
#316's overlay test calls overlays() with the drop_end argument next added (#83).
One shared compiler (designcraft_compose::grep) translates the GREP dialect
documents and users write: \l \u \L \U letter classes, \h \H \v \V \R \N,
\r paragraph end and \n forced line break, ~ special-character codes,
Unicode-aware POSIX classes, and literal [ & -- inside character classes.
It compiles with fancy-regex, so lookahead, lookbehind, atomic groups,
possessive quantifiers, backreferences and \K work; a backtrack limit stops
pathological patterns with an error.
GREP styles skip a pattern that fails to compile or gives up on a search,
with one log warning. Find/Change returns the error. The paragraph style
dialog validates with the same compiler. Fixes en dash (~=) mapping to an
em dash in Find/Change.
Conflict: crates/tools/src/snap.rs: first_on_axis: a guide or margin in reach competes with the baseline grid through #84's nearer(); otherwise #309's smart-guide passes run and the baseline grid comes last. #84's nearer_of_margin_and_baseline_wins and #309's tests pass.
#171's style.character.delete (and the style.paragraph.delete it copies) reassigned only text runs;
next's rename_style already rewrites styles, stories, table cells, nested and GREP styles and
footnotes. Both deletes now go through one delete_style that removes the style, rebases its
children and calls rename_style, in one undo step.
- Children of the deleted style are based on the replacement ([None] and [No Paragraph Style]
clear Based On); when the replacement descends from the deleted style they take its parent,
so no based-on chain loops.
- rename_style also covers drop cap styles, cell styles' paragraph style, footnote and endnote
paragraph styles, the endnote heading style, TOC entries and the default paragraph and
character styles, which fixes renames too.
- A missing, empty, unknown or built-in name, an unknown replacement and a replacement equal to
the deleted style are errors that change nothing.
A German table (crates/ui-egui/src/i18n/de.rs) covers every key of the shared,
Japanese, Arabic, Brazilian Portuguese, Italian and Ukrainian catalogs (1,697
rows; before, 164 strings were German). The shared table's German column stays
the fallback for keys added after it. Tests check placeholders, padding, colons
and ellipses against the English source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflict: crates/compose/src/breaker.rs: next's multi-line Item::boxed/penalty with edge_elastic and start_elastic plus #310's over; glue in items() keeps next's edge_elastic and sets #310's over; kp_pass first node keeps next's first_box/first_hang/first_elastic and ty/tz plus #310's to
On the vertical axis the baseline grid was tried before smart guides.
It snaps while hidden, and with lines every 12 pt and a box's top,
centre and bottom each reaching 4 pt either side, one of them is nearly
always in the zone. It took almost every vertical move and drew nothing,
so object alignment and equal spacing hardly ever showed on y. The
baseline pass now runs after the smart guide passes.
Smart spacing also only matched a gap between two other boxes. A box
dragged between two neighbours now snaps to where both of its gaps are
equal, and both gaps are marked.
Fixes#188
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N5fQBTFb4hhKXsCFYitZ1P
Stretch past the maximum word spacing was shared by every space on the
line, so em, en and thin spaces widened along with word spaces. Only word
spaces take it now; a line without word spaces gives it to its letter
gaps, matching how the paragraph composer rates such a line.
Stretch past the maximum word spacing was rated in units of the word
spaces' own stretch. With a narrow range (100-105%) that unit is tiny, so
a loose line with several word spaces rated far worse than a single word
letter-spaced across the measure, and the paragraph composer chose the
single word. Rate the overflow in units of at least a third of the word
spaces' width (the default range), so word spaces take the extra stretch.
Apply the displayed precision before testing for a 12-point carry,
so measurements near a pica/cicero boundary do not display as 0p12
or 0c12. Cover positive, negative, coarse, and subunit rounding.
Reject non-quarter-turn or non-integer view angles instead of silently
truncating or defaulting them. Add a command-level regression test for
invalid inputs, valid quarter turns, and clearing the rotation.