Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom fonts display correctly in Firefox but incorrectly in Edge and Adobe Acrobat Reader #3714

Closed
mgirolet-gl opened this issue Mar 18, 2024 · 1 comment

Comments

@mgirolet-gl
Copy link

mgirolet-gl commented Mar 18, 2024

Preamble

I have read and understood the contribution guidelines.

I have read #2677 and am applying exactly what it recommends doing for custom font, therefore comments such as 'just see #2677' would be irrelevant.

jsPDF version

v2.5.1 (latest at the time of writing)

Situation

I am importing a font using #2677's/README's recommended method with the fontconverter:

    var font = '/*base64-encoded TTF file*/';
    var callAddFont = function () {
      this.addFileToVFS('OpenSans_SemiCondensed-Regular.ttf', font);
      this.addFont('OpenSans_SemiCondensed-Regular.ttf', 'OpenSansSemiCondensed', 'normal');
	};

    jsPDF.API.events.push(['addFonts', callAddFont]);

I am then writing some text using it to a new document:

    let doc = new jsPDF('l', 'mm', 'a3');

    doc.setFont('OpenSansSemiCondensed');
    doc.setFontSize(30);
    doc.text("This is a test", doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' });

I then save it using FileSaver:

    saveAs(new Blob([doc.output()], { type: 'application/pdf' }), 'test.pdf');

The error

Once exported, the PDF looks as it should with the correct font when opened in Firefox:
Image of the PDF rendered correctly

However, when rendered in Edge, the PDF seems to use a default font instead of the embedded one:
Image of the PDF rendered with the wrong font

And even worse, when opened in Adobe Acrobat Reader (I use version 2024.001.20604 64 bits), a popup indicates 'Cannot extract the embedded font "OpenSansSemiCondensed". Some characters may not display or print correctly.' and the text is rendered using dots instead of actual glyphs:
Image of the PDF rendered with dots instead of text

Most of the forum posts I could find mentionning this issue said that the PDF required the font to be installed on the computer, which makes no sense since the entire point of PDFs is to be portable and therefore embed fonts. Plus, Firefox can display the text correctly so the font is definitely in the document.

Adobe Acrobat Reader does acknowledge the existence of the font in the file properties menu, precising that it's a TrueType (CID) with Identity-H encoding.

MCVE

See this JSFiddle: https://jsfiddle.net/cov42qfe/14/

If the link breaks for any reason, you can recreate it with the following code:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js"></script>
<script src=" https://cdn.jsdelivr.net/npm/[email protected]/dist/jspdf.umd.min.js "></script>

<script>
  async function blobToBase64(blob) {
    return new Promise((resolve, _) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result);
      reader.readAsDataURL(blob);
    });
  }

  async function doStuff() {
    // Font: Open Sans (Semi-condensed, regular)
    // https://fonts.google.com/specimen/Open+Sans
    // https://github.com/googlefonts/opensans/raw/bd7e37632246368c60fdcbd374dbf9bad11969b6/fonts/ttf/OpenSans-CondensedRegular.ttf
    // Licensed under OPL

    const { jsPDF } = window.jspdf;

    var font = '/* Paste the base64-encoded string containing the TTF here. */';
    var callAddFont = function () {
      this.addFileToVFS('OpenSans_SemiCondensed-Regular.ttf', font);
      this.addFont('OpenSans_SemiCondensed-Regular.ttf', 'OpenSansSemiCondensed', 'normal');
    };

    jsPDF.API.events.push(['addFonts', callAddFont]);

    let doc = new jsPDF('l', 'mm', 'a3');

    doc.setFont('OpenSansSemiCondensed');
    doc.setFontSize(30);
    doc.text("This is a test", doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' });

    saveAs(new Blob([doc.output()], { type: 'application/pdf' }), 'test.pdf');
  }
  
  doStuff();
</script>

Additional notes

I have tested this with Open Sans, Free Sans and Deja Vu Sans Condensed, the last of which shows random text junk and invalid characters instead of dots on Adobe Acrobat Reader.

@mgirolet-gl
Copy link
Author

I found where the problem was from.
It turns out that using output() and then building the Blob using new encodes the document in UTF-8, which Firefox accepts but not Edge nor Adobe Acrobat Reader.

The solution was to use output('blob') to get the ANSI-encoded bloc directly from jsPDF and save it:

saveAs(doc.output('blob'), 'test.pdf');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant