Inline PDF comparison draws replacement text on top of the following line

Inline PDF comparison draws replacement text on top of the following line

Product: GroupDocs.Comparison for Java

Version: 26.8.2

Platform: Java 21 (Zulu), macOS 15

Summary

In the default inline display mode, when a change makes a line longer than the

original, the overflow is drawn at a fixed 4pt offset from the line it came from,

regardless of the font size or the line pitch of the document. With any normal body

text size the overflow collides with the next line and the two print on top of each

other, making both unreadable.

Steps to reproduce

Attached are two single-page PDFs: five lines of 12pt Times Roman on a 20pt line

pitch, differing in two places (“seven"→"ten”, “five"→"three”). MakePara.java

rebuilds them with PDFBox 3.x.


try (Comparer comparer = new Comparer("para-v1.pdf")) {

comparer.add("para-v2.pdf");

PdfCompareOptions options = new PdfCompareOptions();

options.setDisplayMode(PdfCompareOptions.ComparisonDisplayMode.INLINE);

comparer.compare("inline-result.pdf", options);

}

Expected: the reflowed text makes room for itself, or at least does not overlap.

Actual: see inline-result-page1.png. The wrapped fragment “days.” is drawn

over the top of “Section 5. This agreement is governed by the laws of the state.”

Dumping the baseline of every glyph in the result confirms the spacing:


y=713.20 Section 3. The supplier shall maintain records of every inspection

y=693.20 performed during the reporting period, and shall retain those records

y=673.20 for a minimum of sevten years from the date of the initial inspection.

y=653.20 Section 4. Deviations shall be reported within threefive business

y=640.00 days.

y=633.20 Section 5. This agreement is governed by the laws of the state.

The document’s own line pitch is 20pt throughout. The overflow line “days.” is

placed 13.2pt below its parent line and only 6.8pt above the next one — far

less than the 12pt text needs. We measured the same fixed 4pt offset on other

documents at a 40pt line pitch, where there was ample room, so the offset appears

to be a constant that ignores the space actually available.

CompareOptions.setLeaveGaps(true) (now deprecated) makes no difference: the

output is byte-identical with and without it.

Secondary issue in the same output

Deleted and inserted words are concatenated with no separator — “sevten” for

seven→ten, “threefive” for five→three. Only the colour distinguishes them, so the

result reads as a corrupted word rather than a substitution, and it is lost

entirely in greyscale printing or for a colour-blind reader.

Our current position

We have switched to SIDE_BY_SIDE, which avoids both problems, at the cost of a

page twice as wide and a much larger output file. It would be good to have inline

usable, since it is the mode most reviewers expect.

inline-overprint-repro.zip (30.8 KB)

Hi @ristomattip ,
Thank you for such a detailed report — and especially for attaching the two sample PDFs. That made it very easy for us on our side, and we were able to reproduce the overlap exactly as you describe.

1. Overflow text drawn on top of the following line

We have confirmed the issue and logged it for investigation. We will work on it and let you know here as soon as a release containing the fix becomes available.

One clarification that may be useful for your expectations of the eventual fix. In the specific documents you attached, the overlap does indeed look like a plain defect: the changed line is still short enough to fit on a single line without any wrapping at all, so no second line should have been produced in the first place. That part we agree is wrong and that is what we will address.

However, in the general case the overlap can still occur even after that. When a replacement genuinely makes a line longer than the page width allows, the surplus text has to be wrapped onto an additional line, and in a fixed-layout format such as PDF there is no free vertical space to push the rest of the page down into. The original document’s line pitch was computed for the original text, and inline mode has to place the extra line somewhere within it. So on documents where changes are large enough to force real wrapping, some crowding between the wrapped fragment and the following line remains inherent to inline rendering of a fixed-layout document.
This is also why SIDE_BY_SIDE does not show the problem: the documents are placed next to each other rather than merged, so no line has to grow.

2. Deleted and inserted words concatenated without a separator

This one is configurable, and you do not need to wait for a release. You can attach separator strings (and colours/styles) to inserted, deleted and changed items through StyleSettings:

In Java it would look roughly like this:

try (Comparer comparer = new Comparer(sourcePath)) {
    comparer.add(targetPath);

    CompareOptions compareOptions = new CompareOptions();

    StyleSettings deletedStyle = new StyleSettings();
    deletedStyle.setStartStringSeparator("{");
    deletedStyle.setEndStringSeparator("}");
    deletedStyle.setFontColor(Color.RED);
    compareOptions.setDeletedItemStyle(deletedStyle);

    StyleSettings insertedStyle = new StyleSettings();
    insertedStyle.setStartStringSeparator("[");
    insertedStyle.setEndStringSeparator("]");
    insertedStyle.setFontColor(Color.BLUE);
    compareOptions.setInsertedItemStyle(insertedStyle);

    comparer.compare(outputPath, compareOptions);
}

One thing — you mentioned greyscale printing and colour-blind readers, so it sounds like the comparison results go on to some kind of human review. Could you tell us a bit about how they are used afterwards? Knowing the actual workflow would help us prioritise the inline-mode improvements.

Please let us know if you have any other questions.