Commit Graph
17 Commits
Author SHA1 Message Date
58d368f1f0 M10: Word export keeps an italic run inside its sentence's paragraph (#4158) (#4411)
The reading blocks keep style boundaries, so "Before Chevron after." with an
italic case name reached the Office exporters as three blocks, and each writer
emitted one paragraph per block. A block that continues another on the same
line (the test `continuations` already applies to keep such blocks out of
table cells) is now a run in its own size, bold/italic and colour inside the
paragraph of the block it continues, in Word, HTML, RTF and PowerPoint.

- `continued_from` names the block each one continues (nearest end);
  `continuations` is its `is_some`, so table detection is unchanged.
- `paragraphs` groups blocks left to right, joining only a block that starts
  strictly further left, with the same rotation, and never a table cell or the
  slide title.
- Block text is trimmed, so the engine records the source's spaces at its ends
  (`Block::space_around`, from the reading block's editor text); runs keep that
  space, or one where the page shows a gap.
- A paragraph is a heading only if its runs are (a bold lead-in no longer makes
  its line a heading); a smaller footnote marker does not demote a heading.

Style changes that wrap onto the next line still split paragraphs; that needs
the reading-block grouping change and is left for later.


Claude-Session: https://claude.ai/code/session_0175FWj4xFhMhSH3UpMU8DSC

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-25 10:11:00 -04:00
aiongg aa1c13f71c fix(engine): list a page truncated for both forms and pictures once 2026-10-22 20:56:02 +00:00
aiongg 467c8556ec fix(engine): encode each image once for Office export
Office export encoded and kept a separate copy of an image for every place
a page drew it, so a short content stream repeating Do on one large image
multiplied it into gigabytes before the writers' limits applied. Each image
object is now encoded once and its bytes shared (pdfcraft_export::Image
holds an Arc<[u8]>), distinct pictures share a 512 MiB budget whose
overflow lists the page as truncated, and RTF, which leaves pictures out,
prepares none.
2026-10-22 18:02:33 +00:00
aiongg 30300ae71b fix(engine): compare only documents that allow copying their text
Compare read both documents' words out with no check of the copying
permission, and its result, report and difference comments carry that text,
so a copy-restricted document's text could be taken out through a comparison.
Both documents must now allow copying.
2026-10-22 13:18:26 -04:00
mtlcl410andClaude Opus 5.5 d85d49a4c6 M10: Export to Word keeps the page background colour (#2992)
A page coloured with Edit a PDF > Background exported to Word as a
white page: export pages carried text and images only, and the Word
section has no page colour.

- pdfcraft-edit `page_background`: the colour of the first thing a
  page paints, when that is an opaque fill (no soft mask, Normal blend)
  in a plain gray, RGB or CMYK colour, of a path with a rectangle
  covering the visible page, not clipped smaller; `None` otherwise.
- `export::Page::background` carries it; the Word writer sets it as
  the document background (`w:background`, plus the
  `w:displayBackgroundShape` setting Word needs to show it) when every
  page shares one non-white colour. Word has one background per
  document, so differing colours are left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-20 16:55:20 +08:00
5602fbba12 M10: Office export follows forms 50 deep and up to 50 000 a page and says where it stops (#3120) (#3426)
* M10: Office export reads forms as far as the renderer and says where it stops (#3120)

Export to Word, PowerPoint, HTML and RTF stopped at 12 nested forms and
4 096 forms a page and left the rest out silently. It now follows forms
50 deep, as the renderer does, and up to 50 000 a page (the renderer's
budget for nested paints), still bounded on hostile files.
doc_export_office lists pages past those limits in truncated_pages, with
a warning. New: reading_blocks_checked and export_office_checked;
reading_blocks and export_office keep their signatures.

Fixes #3120

Co-Authored-By: Claude <noreply@anthropic.com>

* Tests: pin the form depth limit to the renderer's 50 (#3120)

The depth test built its chain from MAX_FORM_DEPTH, so it moved with the
constant. Write the renderer's limit out: depth 50 is read, depth 51 is
left out and reported. Fails with the constant at 49 and at 51.

Co-Authored-By: Claude <noreply@anthropic.com>

* Export: say which forms count toward the page limit (#3120)

The page budget also counts forms the page draws itself, which the
renderer does not charge, so a page can be reported as cut although the
viewer shows it. The warning and the tool description now say so.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 13:02:44 -04:00
84a75eae1b M10: Presentation (.pptx) export (#1137) (#1162)
* feat: presentation (.pptx) export (#1137)

- Implement OpenXML PresentationML (.pptx) generator in crates/export/src/pptx.rs:
  - Generate [Content_Types].xml, _rels/.rels, core properties, presentation.xml
  - Build slide master, blank slide layout, and DrawingML theme
  - Render slides per page: largest text block as title shape, remaining paragraphs as body text box with font size, bold, italic, and color formatting
  - Embed images with proper DrawingML picture shapes and relationships
  - Generate DrawingML table shapes with column grid and span merging
- Wire OfficeFormat::Pptx into crates/engine/src/compare.rs and export_office
- Register export.pptx command and mark Presentation (.pptx) Ready in catalog
- Support pptx in automation doc_export_office tool
- Wire export.pptx into UI commands and file save dialog
- Add unit and integration tests across crates/export, engine, automation, and ui-egui
- Update create.export-pptx parity feature evidence and docs

* pptx export: saturating slide positions, matching cell-border tags, theme ea/cs fonts, package test

- Heights and the running vertical position use clamped/saturating arithmetic, so a hostile
  text size or image rectangle (1e300, NaN, inf) can't overflow i64; the item loop uses get().
- The table cells' a:lnR and a:lnT borders were closed with </a:lnL>, which made every slide
  with a table malformed XML; they now close with their own tags.
- The theme's major/minor fonts carry the schema-required a:ea and a:cs children.
- New test walks the produced zip entry by entry (sizes, inflation, central directory), checks
  every XML part's tags balance, the required parts, content-type overrides, relationship
  targets and that no placeholders are used; a hostile-sizes test covers the overflow.
- Test literals gain main's Block/Image rotation and size fields.
- Parity notes say what is still unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: KrzysztofC <krzysztofc@localhost-live.lan>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:55:25 -04:00
7caaa35a81 Fix Word invoice layout and pagination (#773) (#1126)
* M10: keep invoice overlays out of Word body flow (#773)

Export inferred tables without visible borders. Keep text and images
positioned on pages with artwork, rotated or large text, and retain
each source page's size, crop rotation and units.

Cover invoice conversion through the automation tools, and handle
unavailable Windows symlink setup in the confinement test.

Co-authored-by: Codex <noreply@openai.com>

* M10: add @lollinoo's chosen contributor credit (#773)

The contributor requested their public GitHub profile name while preparing the #773 PR.

Co-authored-by: Codex <noreply@openai.com>

* Word export: float a page only when text overlaps an image or watermark

positioned() turned every page with any image, or with text twice the body
size, into absolutely positioned VML text boxes, so a page with a logo or a
big title lost its flowing paragraphs, headings and tables. Now a page floats
only when it has rotated text, or when an image or a watermark-sized text
block actually overlaps other text (bounded pairwise test). Other pages flow
with images inline. Adds a regression test for a page whose image and title
sit clear of the text, and updates the docs and parity notes.

---------

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-11 21:10:32 -04:00
Krzysztof CieślikandKrzysztofC 38df401687 M4: replace selected pages from organize toolbar and context menus (#786) (#1149)
Add 'Replace pages…' action to the Organize Pages toolbar, organize grid thumbnail context menu, and Pages panel context menu to replace selected pages.

- Add ViewAction::ReplacePages triggering replace_pages_dialog()
- Expose 'Replace pages…' button with 'replace' icon on the organize toolbar
- Expose 'Replace pages…' on the organize grid and Pages panel thumbnail context menus
- Update parity evidence for organize.replace-pages
- Add integration tests for toolbar and context menu replace actions in crates/ui-egui/tests/editing.rs

Co-authored-by: KrzysztofC <krzysztofc@localhost-live.lan>
2026-10-11 18:32:29 -04:00
Zeyu LiandBrandon Thomas b91d38c073 M14: text the fonts can't draw is kept and reported, never written as ? silently (#1112)
* M14: text the fonts can't draw is kept and reported, never written as ? silently

Form values and captions, text boxes, callouts, Fill & Sign text, measurement labels and stamp by-lines keep text the standard fonts can't draw, draw ? for it, mark the annotation (PCUndrawn) and report the edit (interface notice, tools' warnings); forms set /NeedAppearances (not in PDF/A). Flattening, redaction overlay text, typed and visible signatures and create-from-text refuse instead. Reports escape such characters as [U+XXXX].

* Catalogs: the two new can't-draw messages in Czech, Slovene, Kazakh, Turkish and Greek; refresh hashes

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-11 17:53:55 -04:00
BooksandBrandon Thomas e7a15783f3 Export to Word/HTML/RTF: read text and images drawn by form XObjects (fixes #314) (#406)
* Export to Word/HTML/RTF: read text and images drawn by form XObjects (fixes #314)

The office export built its paragraphs from text_blocks and its images from
page_images. Both read only the page's own content streams (they back Edit
text and Edit image, which rewrite those streams), so a page drawn through
`/Fm1 Do`, as many print-to-PDF tools emit, exported as an empty document.

Add read-only reading_blocks and reading_images to pdfcraft-edit. They
follow Do into form XObjects (nested ones too), apply each form's /Matrix,
use its own /Resources (or the caller's when it has none), and start it
from the graphics state at the Do. Depth is capped at MAX_FORM_DEPTH and a
form already being read is skipped, so self-referencing and mutually
recursive forms are read once. export_pages uses them; editing is
unchanged and still offers only the page's own text and images.

* Export: a page's walk through form XObjects has a total visit budget, so forms that fan out can't hang it

* Export: keep the image walk within clippy's argument limit

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 18:22:07 -04:00
Brandon ThomasandClaude Opus 5.5 2aca0692fc Fix #526: keep text colour in Word, HTML and RTF export (#547)
The export model (`pdfcraft_export::Block`/`Cell`) had no colour, so
`export_pages` dropped the fill colour that `edit::TextBlock` already
carries and every run came out black.

Block and Cell now carry an sRGB colour, mapped from TextBlock.color.
Word runs get `<w:color w:val="RRGGBB"/>`, HTML paragraphs, headings and
cells a `style="color:#RRGGBB"`, and RTF a colour table with `\cfN`.
Black text keeps each format's default; NaN and out-of-range components
clamp.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:49:21 -04:00
Brandon ThomasandClaude Opus 5.5 d3db99818f Rename PrintCraft to PdfCraft (#174)
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now
PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the
PrintCraft settings and crash-recovery folders to the new name, and both apps read settings
saved under the old storage key, so upgrades keep recent files, preferences and unsaved work.
The signing test fixtures keep their PrintCraft subject names (they are binary).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:03:57 -04:00
Brandon ThomasandClaude Opus 5.5 70280a44d0 M10: Export to Word (.docx), HTML and RTF (new export crate with a small zip writer): paragraphs, headings, bold/italic, images, page breaks; doc_export_office tool
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:40:46 -04:00
Brandon ThomasandClaude Opus 5.5 4d60af8b1e M11: PDF/A (new preflight crate): verify PDF/A-2b/3b structural rules, Save as PDF/A (XMP identification, generated sRGB output intent, forbidden actions, annotation flags, interpolation, encryption), PDF/A dialog; pdfa_verify, pdfa_convert tools
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:19:54 -04:00
Brandon ThomasandClaude Opus 5.5 a4bf717c06 M12: Compare files: visual differences (pages rendered and compared region by region), shaded orange; doc_compare visual option
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:37:23 -04:00
Brandon ThomasandClaude Opus 5.5 c12b795ce5 M12: Compare files (new compare crate): word-level text differences, Compare panel with shading on the new file, report PDF, differences as comments; doc_compare, doc_compare_report, doc_compare_mark tools
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:31:18 -04:00