Skip to content
TwinScope0.3.10

PDF

Pages paired by their content, not by their number, so inserting a cover page does not report the whole document as changed. Each changed page is compared by the text engine, marks and folding included.

Click to enlarge
Page 1 is added; nothing after it moved. The page numbers on each side of a row are what pairing by content buys you.

Pages pair by content, not by index#

This is the decision the engine is built around. Insert a cover page and every page number after it shifts by one — so a comparison that paired page 4 against page 4 would report an entire document as rewritten when a single page was added at the front.

Instead, the two lists of page texts are aligned the way the text engine aligns lines, one level up: a sequence diff with a similarity comparator, so two pages count as the same page when they share more than half their words. A removal immediately followed by an addition is read as a rewritten page while both sides still have one; past that, whichever side ran out has the page missing.

The sample pair#

11-pdf/ is a three-page supply agreement against a four-page revision of it. The revision adds a cover page at the front, edits the delivery and payment terms, and turns the last page landscape:

BeforeAfterStateWhy
1addedThe new cover page
12sameDefinitions and Orders, untouched
23changed30 days → 14 days, 30 days → 45 days, 4% → 8%, one new sentence
34changedThe words are identical; the page was rotated

Every page keeps its identity. Paired on number instead, all four rows would have read as changed.

Each changed page is a text diff#

The comparison inside a page is the text engine's, not a second implementation of one. So word-level marks, folded unchanged runs and the shared normalisation rules all work inside a page for free:

Page 2 → 33 modified
The Supplier shall deliver within 30 days of acknowledgement.
The Supplier shall deliver within 14 days of acknowledgement.
Risk passes on delivery to the Customer premises.
Interest on late payment accrues at 4% above base rate.
Interest on late payment accrues at 8% above base rate.

Metadata is its own table#

Title, Author, Producer and whatever else the document carries are compared as a table of their own, and only the fields that differ are listed. In the sample pair that is one field: the Title gains a v3 while the Author and Producer are unchanged.

Metadata comparison is an option and can be turned off, in which case no metadata rows appear at all.

Geometry: a resized page is a changed page#

A page whose size in points changed is reported even when its words did not. That is the last row of the sample pair: 595 × 842 became 842 × 595 — the same A4 page turned landscape — with identical text on it. A comparison that only looked at words would have called that page unchanged, which is not what a reader would say about it.

A page with no text says so#

A scan, or a page that is one large image, has nothing for a text comparison to read. Those pages are counted and named — reported as having no extractable text — rather than shown as identical, which is what an empty-against-empty comparison would otherwise produce.

The count is of page positions, not of pages: a position that is blank on both sides is one page in the comparison, not two.

Two honest limits#

A gotcha worth knowing about#

Limits#

LimitValueWhat happens past it
Pages per side500Reading stops and the notes say so
Page similarity0.5Below it, two pages are a removal and an addition rather than one edited page

The similarity floor is deliberately lower than the text engine's line threshold: a page holds far more words than a line, so two versions of the same page can differ a great deal and still obviously be the same page.

When a document cannot be read#

An encrypted or corrupt PDF is a real answer, not a crash. The error names the reason and offers Compare as files as a button — the binary engine can still say whether the two files are the same bytes, which is sometimes all you needed.

In the app#

ControlWhat it does
ShowChanged pages · All (with a count)
Page-count chip3 → 4 pages, always visible
No-text chipAppears only when some page has no extractable text