Pdf-lib: Copy text from embedded fonts to clipboard

Created on 28 Nov 2019  ·  12Comments  ·  Source: Hopding/pdf-lib

First of all, thank you for your lib.

I would like to be able to copy the texts that are written in PDFs, via embed fonts. I thought I was doing something wrong, but I realized that there is also the issue with your example.

With this PDF file generated: https://github.com/Hopding/pdf-lib/blob/master/assets/pdfs/examples/embed_font_and_measure_text.pdf

If I copy/paste the text This is text in an embedded font!, the result is 9KNXĶNXĶWH]WĶNQĶFQĶHREHIIHIĶKTQWķ.

Do you know if it is possible to fix this issue? To include the font in another way maybe? Its encoding?

bug

All 12 comments

Hello @Dewep! It should be possible to copy text written to a PDF with drawText to your clipboard without issue (for standard and embedded fonts). I was under the impression that this was working correctly. But I just ran a quick test of the example you linked with several different PDF readers and discovered the following:

| Reader | Original Text | Copied Text |
| ------- | --------------------------------- | --------------------------------- |
| Preview | This is text in an embedded font! | This is text in an embedded font! |
| Firefox | This is text in an embedded font! | This is text in an embedded font! |
| Foxit | This is text in an embedded font! | This is text in an embedded font! |
| Chrome | This is text in an embedded font! | 9KNXĶNXĶWH]WĶNQĶFQĶHREHIIHIĶKTQWķ |
| Acrobat | This is text in an embedded font! | 􀀷􀁋􀁌􀁖􀀃􀁌􀁖􀀃􀁗􀁈􀁛􀁗􀀃􀁌􀁑􀀃􀁄􀁑􀀃􀁈􀁐􀁅􀁈􀁇􀁇􀁈􀁇􀀃􀁉􀁒􀁑􀁗􀀄 |

So it would appear that Chrome and Acrobat have trouble copying text to clipboard (at least when the text is drawn with the embedded Ubuntu font). This is likely a bug in pdf-lib. It probably has to do with the unicode cmap that is generated for embedded fonts.

I reran the above test using the Helvetica standard (non-embedded) font. It copies correctly in all readers.

| Reader | Original Text | Copied Text |
| ------- | --------------------------------- | ----------------------------------- |
| Preview | This is text in an embedded font! | This is text in an embedded font! |
| Firefox | This is text in an embedded font! | This is text in an embedded font! |
| Foxit | This is text in an embedded font! | This is text in an embedded font! |
| Chrome | This is text in an embedded font! | This is text in an embedded font! |
| Acrobat | This is text in an embedded font! | This is text in an embedded font! |

This is further evidence that the issue has to do with the embedded font unicode cmap.

Yes, I hadn't been clear enough in my message, but I had also noticed that it was just about embedded fonts.

I don't know much about how PDFs work, and even less about what cmap is.
Do you have any idea how to fix it? I doubt I can help, but I can try if you need it.

I need to investigate further to determine the exact cause of the issue and then I'll work on a fix. I don't have an ETA for this at the moment. I need to work through some other issues first, as I've fallen a bit behind on them.

One thing you can do is see if this particular bug existed in version 0.6.4 of pdf-lib. It's possible that the bug was introduced during the rewrite. This is likely to be the case if 0.6.4 does not have the same bug.

Indeed, just by taking your example created at v0.6.4, the problem is not there.

The second page of this document, written via an embedded font, copies well from Chrome: v0.6.4/examples/pdf_results/document_creation.pdf.

I will try to test/debug a little more the difference between these 2 versions, on their CMaps created.

Well, it's not that simple after all. The problem was already there on version 0.6.4, it just seems to depend on the font used.

If I'm using the font v1.3.0/assets/fonts/ubuntu/Ubuntu-C.ttf it works well (with the latest and the 0.6.4 versions). But if I'm using the font v1.3.0/assets/fonts/ubuntu/Ubuntu-L.ttf it doesn't work anymore (with the latest and the 0.6.4 versions).

I've been trying to figure out why, but it's clearly too complicated for me. If you have any other ideas on how I can help, let me know.

Generated PDF files:

@Dewep Thanks for the updates on your findings. I'm almost caught up on all the other issues, so I'm _hoping_ to take a look at this sometime this week.

It looks like the issue goes away if you subset the fonts when embedding them:

const font = await pdfDoc.embedFont(..., { subset: true });

So it must be an issue specifically with CMaps containing multiple bfrange sections. Because subsetting a font results in having only one bfrange.

@Dewep I made some changes in #298 to use a simpler cmap format. This appears to have resolved the issue. Text copies correctly for me in all readers with all embedded fonts I've tried. I've attached a build of pdf-lib with this fix. Please try using this build and let me know if you're still able to reproduce the issue or not.

pdf-lib-v1.3.1-rc1.zip

I would recommend that you test the new build the same way you've been testing for this issue. But for reference, here's the script I'm using to test it:

import fontkit from '@pdf-lib/fontkit';
import { PDFDocument } from 'pdf-lib';

(async () => {
  const ubuntuFontBytes = await fetch(
    'https://github.com/Hopding/pdf-lib/raw/master/assets/fonts/ubuntu/Ubuntu-R.ttf',
  ).then((res) => res.arrayBuffer());
  const jpFontBytes = await fetch(
    'https://github.com/Hopding/pdf-lib/raw/master/assets/fonts/source_hans_jp/SourceHanSerifJP-Regular.otf',
  ).then((res) => res.arrayBuffer());

  const pdfDoc = await PDFDocument.create();

  pdfDoc.registerFontkit(fontkit);
  const font1 = await pdfDoc.embedFont(ubuntuFontBytes, { subset: false });
  const font2 = await pdfDoc.embedFont(jpFontBytes, { subset: true });

  const page = pdfDoc.addPage([500, 500]);
  page.drawText('Hello World!\nДата и время встречи в офисе Президента', {
    font: font1,
    x: 5,
    y: 250,
  });
  page.drawText('Hello World!\n印刷者 印刷日時 社長室会日時', {
    font: font2,
    x: 5,
    y: 150,
  });

  const pdfBytes = await pdfDoc.save();
})();

Version 1.3.1 is now published. It contains the fix for this issue. The full release notes are available here.

You can install this new version with npm:

npm install [email protected]

It's also available on unpkg:

As well as jsDelivr:

Hello @Hopding!

Thank you, I can confirm that it's working perfectly. Thank you for your time and your library.

Keep it up.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dhollenbeck picture dhollenbeck  ·  4Comments

emilsedgh picture emilsedgh  ·  5Comments

keyhoffman picture keyhoffman  ·  4Comments

zimt28 picture zimt28  ·  5Comments

nachum37 picture nachum37  ·  3Comments