pdfme / pdfme

A TypeScript based PDF generator library, made with React.
https://pdfme.com
MIT License
2.16k stars 192 forks source link

Fix pdf text render overlap by avoiding line breaks in pdflib #417

Closed peteward closed 3 months ago

peteward commented 3 months ago

fixes #398

Pdfme calculates how lines should be split and renders them individually. It does this for a number of reasons including alignment, dynamic font size calculation and rotation.

Pdflib has it's own line breaking which, in theory, shouldn't happen if calculations between the 2 libraries match up. However, pdflib appears to be calculating the width of a line of some fonts differently (incorrectly) compared to pdfme. Regardless of what and why this difference is (it wasn't immediately obvious to me), we don't need pdflib to split lines because we've already done it.

You cannot tell pdflib not to split lines, but we can make it impossible through this change.

pdflib drawText() function does the following:

    const lines =
      options.maxWidth === undefined
        ? lineSplit(cleanText(text))
        : breakTextIntoLines(text, wordBreaks, options.maxWidth, textWidth);

Previously we pass the maxWidth option which will result in breakTextIntoLines() being called. This is a more intelligent line breaking algorithm which is very similar to what pdfme does (although comes up with a different result).

By not passing maxWidth, we instead will call lineSplit(), which is simply the following:

export const lineSplit = (text: string) => text.split(/[\n\f\r\u000B]/);

By updating our split regex to include \f (form feed) and u000B (line tabulation) we can ensure that no splitting will happen in pdf rendering, even if those characters are unlikely in the input.

BEFORE with text overlapping using Cairo font: Screenshot 2024-01-31 at 07 05 26

AFTER with no overlap: Screenshot 2024-01-31 at 07 05 48

vercel[bot] commented 3 months ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
add-dynamic-table-schema-332 ❌ Failed (Inspect) Jan 31, 2024 7:07am
1 Ignored Deployment | Name | Status | Preview | Updated (UTC) | | :--- | :----- | :------ | :------ | | **pdfme-playground** | ⬜️ Ignored ([Inspect](https://vercel.com/labelmake/pdfme-playground/ERqeazFD7sdnMpbSh8mTcCGsT8Uk)) | | Jan 31, 2024 7:07am |
hand-dot commented 3 months ago

@peteward Great. By adding |\f|\u000B, we can now correctly split patterns that were not covered before.

I plan to merge and release this later.