Moves craft-update, craft-pdf and the krilla patch from storytold/craft-libs
c5a1cbfb to dotCooCoo/craft-libs c7c84230, which is craft-libs main at
0a9d1f48 with storytold/craft-libs#687 and #696 merged in.
- The result window opens whenever the updater's status is not idle: at
the first start after an update it says the version that was installed
or why the update failed, and Help > Check for Updates shows Installing,
Ready and the launcher's choice. A check asked for from the ribbon now
shows the window on the next frame.
- Restart to Update closes the window and asks the app to quit. An update
that asks the app to close quits every window, after asking about each
document with unsaved changes.
- on_exit and the macOS terminate path start the waiting update's helper.
- The update prompt and the result window draw their words through the
interface catalog.
* fix(render): skip drawing paths far past every canvas before flattening
* fix(render): refuse paths with non-finite points too
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* fix(docx): collect an embedded object's relationship ids in a set on save
* style: rustfmt
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* Charts: an automatic series colour follows the series' c:idx (#5963)
A series without its own colour took the accent for its place in the
file. Word picks it by the series' c:idx (c:order doesn't matter), so a
chart whose series aren't numbered 0, 1, 2... in file order, such as a
lone series with idx 2 after a deletion, got different colours.
c:idx is read strictly as the unsignedInt the schema says; a missing or
invalid value falls back to the place in the file.
* Charts: the renumbered test helper fails if ser's layout changes (#5963)
---------
Co-authored-by: kiwi4boy <kiwi4boy@gmail.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
## What changed
Word stores paragraph indents (`w:ind` left/start, right/end, hanging, firstLine) in 16 signed bits and paragraph
spacing (`w:spacing` before/after) in 16 unsigned bits. A file that writes a larger plain integer is read by Word
modulo 2^16: `w:left="66256"` is a 720-twip (0.5") indent in Word. We read the full value, so such a paragraph was
indented by about 46 inches and its text was pushed off the page.
- `crates/docx/src/units.rs`: new `tw_i16` / `tw_u16` readers. A plain integer keeps its low 16 bits (two's
complement for indents, so 66256 -> 720 and 65535 -> -1); values with a unit or a fraction read as before.
- `crates/docx/src/read/props.rs` and `read/styles.rs` use them for `w:ind` and `w:spacing` before/after, in direct
and style formatting.
- In-range values read exactly as before.
## Testing
- `crates/docx/tests/it/twips_wrap.rs`: synthetic documents with out-of-range indents and spacing in paragraph and
style properties check the wrapped values; in-range values and values with units are unchanged.
- Unit tests for the two readers; `cargo xtask ci` passes.
Found by a real-file corpus comparison against Word's own PDFs: a file whose indents exceed 16 bits shows its text on
the page in Word and off the page here.
Co-authored-by: tpawley2001 <268951182+tpawley2001@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
Word treats the end-of-cell mark as a paragraph in the default (Normal)
style, so a cell's last paragraph with contextual spacing in that style
(or in an undefined style, formatted as Normal) loses its space after, as
beside any same-style neighbour; one in another style keeps it.
`layout_box` kept the space after of every last cell paragraph except
automatic spacing, so the row grew by it and the text below the table sat
that much lower (docxide-pdf cell-end-text-context, cell-end-empty-context:
8 pt).
A middle or bottom cell of a row split across pages lines up with the
other cells' kept text, which `align_in_part` counted with its full space
after; it now stops at the cell's content end, so a dropped space after
(contextual or automatic) no longer pushes the aligned cell down.
Co-authored-by: Naxvog <4963183+naxvog@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* layout: line numbers take the "Line Number" style, not a fixed 10 pt grey
Line numbers were laid out in 10 pt grey in the default font, whatever
the document said. Word formats them with the "Line Number" character
style over the document's defaults: in a manuscript whose defaults are
Aptos 12 pt, Word's PDF shows them in Aptos 12 pt black (measured in
Word for Mac), WordCraft's in 10 pt grey.
Lay the number out with the document's "Line Number" style when it has
one, else its plain defaults, so size, font and colour follow the
document.
Test: line numbers take the document's default size and automatic
colour, and a "Line Number" style's size and colour when there is one.
* docs: progress log and parity entries for line-number-style
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
Word for Mac sets raised and lowered text at 0.65 of the run's size
rounded to the half point (measured from digit advances in its PDF
export at base sizes 8 to 36 pt: 11 pt -> 7, 12 -> 8, 24 -> 15.5).
WordCraft used 0.65 exactly, so lines with superscripts were up to
0.5 pt wider and some broke a word early.
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
## What changed
The DOCX writer's content-control planner (`crates/docx/src/write/sdt.rs`) decides whether a control that
covers a whole paragraph is written block-level (`w:sdt` around `w:p`) or run-level (inside the paragraph).
It only treated the control as covering the whole paragraph when nothing but control-end markers followed
its end. Bookmark, comment and permission range markers after the end now count as "nothing" too, so the
control stays block-level and the markers stay at the end of its paragraph.
## Why
Word writes a body-level `_GoBack` bookmark (`<w:bookmarkStart w:name="_GoBack"/><w:bookmarkEnd/>` directly in
`w:body`) in nearly every file it saves. When the last body-level content control was followed by it, the
reader put the bookmark at the end of the control's paragraph, and the writer then turned the control (and
any controls nested in it) into run-level `w:sdt`s inside that paragraph. For a repeating section
(`w15:repeatingSection` / `w15:repeatingSectionItem`), which must wrap whole paragraphs or rows, Microsoft
365 Word then refuses to open the saved file ("the file appears to be corrupted"). Plain nested block
controls changed what they cover the same way.
Found by the real-file corpus: Word reported our saved copy of a form with a repeating section as corrupted.
## How it was tested
- New tests in `crates/docx/tests/it/nested_block_controls.rs` (synthetic packages): a repeating section around
one paragraph, plain nested block controls, nested block controls in a table cell, a run-level control that
must stay in its paragraph, and repeating sections / block controls followed by a body-level bookmark (with
and without data bindings) all round-trip with the controls at the same level and the text kept.
- `cargo xtask ci` passes.
Co-authored-by: tpawley2001 <268951182+tpawley2001@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* #5843: resolve LibreOffice semicolon-separated font fallback lists to first installed family
* #5843: address review comments on font fallback list resolution
* #5843: verify fallback list text on cache hit and accept Times New Roman in tests
* #5843: bound the fallback lists read from a DOCX and reuse their classification
A document could name thousands of fallback families in `w:ascii`/`w:hAnsi`.
Nothing bounded that value, and the name-based rules (roman classification,
Thai family, named substitutes) then scanned every candidate for each shaped
piece, so opening the document took seconds.
`w:ascii` and `w:hAnsi` now keep the leading families within MAX_FONT_NAME
bytes, cut at a `;` so no name is split, as `w:cs`/`w:eastAsia` already bound
their names. The family a real list would pick is kept: a LibreOffice list
names a few families, well under the bound.
The Thai-family and named-substitute answers are worked out once per list and
kept in the fallback-list cache, keyed by the list text, so shaping no longer
rescans candidates for every piece. Resolution still reads every candidate.
A 500-paragraph document whose font names 20,000 candidates laid out in 10.8 s;
bounded on read it takes 17 ms.
Tests:
- a hostile fallback list keeps its leading families, cut on a `;`
- a real LibreOffice list is read whole
- a later Thai or named fallback still classifies, and lists are cached