Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/release-notes/v0.4.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
OffPDF v0.4.0 lets Edit PDF change text that is already in a PDF, in the document's own font, and only where the change can be verified. Everything still runs on your computer.

<!-- Draft written with the v0.4 implementation. The maintainer finalises it in the release PR (thanks, packages, known issues). -->

Highlights:

- Edit text (E) changes a line of existing text in the document's own font. The rest of the page stays where it was: every other glyph is checked to stay within 0.01 pt.
- Before a file is saved, each edited page is re-read and checked, then rendered and compared with the original by an independent engine (Poppler). If anything else changed, nothing is saved and the original file is never overwritten.
- Lines that can't be changed safely are shown dotted and say why when selected, for example text inside a reused block, a font made of drawings, or the hidden text layer of a scan.
- A longer line may run into the next text on the line, such as the next table cell or a footnote mark: OffPDF warns, saves it, and checks that the neighbouring words still read the same.
- Size, bold or italic (when the page already has that face), colour and letter spacing for the changed line, with a preview of the page as it will be saved after each change and Show original (O) to compare.
- A keyboard path for the whole flow: E, Tab to the text lines, arrow keys, Enter to edit, Tab to the format bar, Enter to apply.
- Edit PDF now opens on the Select tool; the old Text tool is called Add text and places a new text box.
- Stamps, shapes, images, drawings and markup now save on pages whose content is stored in several parts without line breaks, whenever those parts join cleanly. Pages whose parts would join inside a word, a string or a comment, or just after an inline image, are still refused, so a save never reveals text the original hid.

What's not supported yet:

- Replacing existing images.
- Text inside reused blocks (Form XObjects), shared page content, Type3 fonts, vertical, right-to-left and complex scripts.
- Reflowing paragraphs, multi-line edits or adding fonts: a subset font can only draw the letters the document already uses.
- Signed, password-protected and dynamic XFA PDFs.

See [docs/EDIT_TEXT.md](https://github.com/McanKul/offpdf/blob/v0.4.0/docs/EDIT_TEXT.md) for the full list, the reason codes and the verification design.

Known issues:

- A file with any damaged JPEG image is refused for Edit text with "This PDF needs repair first", even when the damaged image is on another page. Run it through Repair PDF first.
- Reading a page and previewing a change can't be cancelled; Save can.
- Files over 256 MB are not kept in memory between steps: each page visit and preview reads them again, so Edit text is slower on them.

Thanks to <!-- contributors: filled in by the maintainer --> for contributing to this release.

Packages:

- Signed and notarized DMG for Apple Silicon Macs
- Windows x64 NSIS installer — unsigned while Authenticode signing is pending. Verify the accompanying SHA-256 file before use.

See [CHANGELOG.md](https://github.com/McanKul/offpdf/blob/v0.4.0/CHANGELOG.md) for full details.
22 changes: 21 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,16 @@ jobs:
librsvg2-dev \
libwebkit2gtk-4.1-dev \
patchelf \
poppler-utils \
qpdf \
wget

- name: Show PDF engine versions
run: |
qpdf --version | head -n 1
pdftotext -v 2>&1 | head -n 1
pdftoppm -v 2>&1 | head -n 1

- name: Use stable Rust
run: rustup default stable

Expand All @@ -79,4 +86,17 @@ jobs:
run: cargo check --manifest-path src-tauri/Cargo.toml

- name: Test Rust backend
run: cargo test --manifest-path src-tauri/Cargo.toml --lib
shell: bash
env:
# Edit text tests fail instead of skipping when qpdf or Poppler is missing;
# the grep below also catches the older tests' `skip:` lines.
OFFPDF_REQUIRE_ENGINES: "1"
run: |
cargo test --manifest-path src-tauri/Cargo.toml --lib -- --nocapture 2>&1 | tee rust-test.log
skips=$(grep -c 'skip:' rust-test.log || true)
echo "skip lines: $skips"
if [ "$skips" -ne 0 ]; then
grep 'skip:' rust-test.log
echo "::error::Rust tests skipped because a PDF engine was missing"
exit 1
fi
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ All notable project changes should be documented here.

## Unreleased

### Added

- Edit PDF can change existing text in place, in the document's own font. OffPDF only offers lines it can verify: every other glyph on the page is checked to stay within 0.01 pt, each edited page is re-read, re-rendered and compared before the new file replaces the destination, and lines that can't be changed safely, including text inside reusable blocks, say why. A longer line that runs into the next text on the line (a table cell, for example) saves with a warning. The original file is never overwritten. See [docs/EDIT_TEXT.md](docs/EDIT_TEXT.md).

### Changed

- The source-content classifier reads each PDF once with bounded decompression and per-page limits, decodes text, and reports text rise, rendering mode, mirrored text, clipping extent, shared content and font coverage with explicit reason codes.
- Edit PDF opens on the Select tool, and the old Text tool is now called Add text.

### Fixed

- Edit PDF page previews refresh when a source file changes on disk, even when its size and modification time stay the same, and older cached page files are removed.
- Edit PDF no longer rejects a save that adds stamps, shapes, images, drawings or markup to a page whose content is stored in several parts that don't end with a line break, as long as the parts join cleanly. This applies to every Edit PDF save, not only saves with text changes. A page whose parts would join inside a word, a string or a comment, or just after an inline image, is still refused, so a save can never make text that the original hid (for example, a line commented out across two parts) visible.
- Job commands accept only plain job ids, so a job's temporary work folder always stays inside the app's temp area.

## 0.3.2 - 2026-09-11

### Added
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml
```

Text-edit verification tests need qpdf ≥ 11 and Poppler (`pdftotext`,
`pdftoppm`). Set `OFFPDF_REQUIRE_ENGINES=1` to make missing engines fail instead
of skip. CI installs both, sets the variable, and fails when any Rust test prints
a `skip:` line. Edit text's design, reason codes and module map are in
[docs/EDIT_TEXT.md](./docs/EDIT_TEXT.md); adding a reason code, a font class or a
producer fixture, and regenerating benchmarks and goldens are in
[src/lib/editor/EDIT_MODEL.md](./src/lib/editor/EDIT_MODEL.md#edit-text-contributor-workflow).

`npm run check:versions` verifies that the release version matches in
`package.json`, both root version fields in `package-lock.json`,
`src-tauri/Cargo.toml`, the OffPDF entry in `src-tauri/Cargo.lock`, and
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ The Edit PDF workspace adds text, images, shapes, links, and freehand drawing as
new content. It can also create PDF notes, highlights, underlines, strikeouts,
and ink annotations while preserving existing annotations.

**Edit existing text.** Change a line of existing text in the document's own
font when OffPDF can verify the change: every other glyph is checked to stay
within 0.01 pt, lines that can't be changed safely say why, and the original
file is never overwritten. See [docs/EDIT_TEXT.md](./docs/EDIT_TEXT.md).

For interactive PDFs, OffPDF can fill existing AcroForm text fields (including
multiline fields), checkboxes, radio buttons, combo boxes, and list boxes. Form
fields stay interactive by default.
Expand All @@ -75,10 +80,11 @@ The two flattening options have different scopes:
page content. When a PDF contains form fields, OffPDF requires form fields to
be flattened as part of this operation.

Current limits: XFA forms are not supported; only the first PDF's AcroForm can
be filled when several files are combined; and Edit PDF does not rewrite text
or images already embedded in a source page. New text and images are added as
overlays instead.
Current limits: XFA forms are not supported, and only the first PDF's AcroForm
can be filled when several files are combined. Edit text changes one line at a
time in the document's own font. It does not reflow paragraphs, add fonts, or
change text inside reused blocks, rotated or vertical text, scanned pages, or
signed and encrypted PDFs. Existing images are not replaced.

## Downloads

Expand Down Expand Up @@ -170,8 +176,8 @@ npm run tauri:build

| Engine | Used for |
| --- | --- |
| `qpdf` | Merge, split, organize, encrypt, decrypt, repair, and lossless optimization |
| Poppler (`pdftoppm`, `pdftotext`) | Previews, image export, comparison, text export, and lossy compression |
| `qpdf` | Merge, split, organize, encrypt, decrypt, repair, lossless optimization, and writing Edit text changes |
| Poppler (`pdftoppm`, `pdftotext`) | Previews, image export, comparison, text export, lossy compression, and verifying Edit text changes |
| Tesseract | OCR and searchable PDFs |
| LibreOffice | Office conversion and PDF/A export |

Expand Down
13 changes: 10 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ reliable local processing, clear packaging, and a contributor-friendly project.

## Current release

- **v0.3.1** is the latest published release. Its Windows package is unsigned
- **v0.3.2** is the latest published release. Its Windows package is unsigned
and remains available through GitHub Releases.
- The Apple Silicon macOS build is signed and notarized. It bundles qpdf,
Poppler, and Tesseract; LibreOffice remains optional for Office and PDF/A work.
Expand All @@ -22,6 +22,7 @@ reliable local processing, clear packaging, and a contributor-friendly project.
## Current focus

- Stabilize the visual editor and make exported edits match the on-screen preview.
- Harden Edit text across more real-world PDFs.
- Improve automated coverage for complex PDF geometry, rotation, and page boxes.
- Make releases easier to trust and install, starting with Windows code signing.
- Give new contributors smaller, clearly scoped issues with reproducible tests.
Expand Down Expand Up @@ -52,15 +53,21 @@ reliable local processing, clear packaging, and a contributor-friendly project.
- Flatten form fields converts form widgets to page content while preserving
other annotations. Flatten annotations converts all remaining annotations to
page content and requires form fields to be flattened when they are present.
- Edit PDF adds new text, images, and shapes as overlays; it does not rewrite
existing text or images inside the source document.
- Edit text changes one line at a time in the document's own font, only where
OffPDF can verify the change; other lines say why they can't be changed. It
does not reflow paragraphs, add fonts, change text inside reused blocks,
rotated or vertical text, or replace existing images. See
[docs/EDIT_TEXT.md](./docs/EDIT_TEXT.md).
- Auto-update is intentionally not enabled.

## Later

- Add optional, clearly disclosed update checks behind an offline-first setting.
- Broaden platform packaging and package-manager distribution.
- Add more advanced editing workflows where they can remain reliable and local.
- Edit text: shared content streams, text inside reusable blocks (Form
XObjects), and Type3 fonts.
- Replace existing images, after a dedicated spike.

Priorities can change as real bug reports and contributor feedback arrive. See
the [open issues](https://github.com/McanKul/offpdf/issues) for work that is
Expand Down
Loading
Loading