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

Pdf non généré si caractères spéciaux dans le nom #35

Open
marek-vanco opened this issue Apr 9, 2020 · 6 comments · May be fixed by #121
Open

Pdf non généré si caractères spéciaux dans le nom #35

marek-vanco opened this issue Apr 9, 2020 · 6 comments · May be fixed by #121

Comments

@marek-vanco
Copy link

Le PDF n'est pas généré si les caractères spéciaux sont utilisés dans le nom. Aucun message erreur n indique la cause de non génération... Le bouton fait rien du tout. En remplaçant des caractères avec ASCII < 128 la génération fonctionne. Mais ce n'est pas évident de trouver la cause pour une personne moins alaise avec le PC.

@philippeBron
Copy link

Bonjour,
merci pour votre issue. Pouvez-vous préciser les caractères spéciaux qui ne fonctionnent pas et devraient figurer dans un nom de famille ?

@marek-vanco
Copy link
Author

marek-vanco commented Apr 9, 2020

J'ai utilisé le caractère č. Oui, ce n'est pas le caractère français. Potentiellement d'autre caractères peuvent poser le même problème. Mais aucun erreur n'a été affiché pour indiquer que c'est le caractère qui n'est pas permis. Je pense qu'afficher le message erreur serait suffisant pour ce type d'erreur car les gens ne peuvent pas deviner d'où viens erreur et pour quoi le pdf ne se génère pas.

@bartoszbielawski
Copy link

C'est la même chose pour lettre "Ś" dans lieu de naissance.

@Hopding
Copy link

Hopding commented Apr 12, 2020

Hello @philippeBron!

It looks like you are using the standard Helvetica font to draw text:

const font = await pdfDoc.embedFont(StandardFonts.Helvetica)

The standard fonts only support characters in the WinAnsi character set. This restriction is an unfortunate artifact of the PDF spec and its age. There are 14 standard fonts (of which Helvetica is one). Here's a document that demonstrates all 14 fonts and their supported character sets:

standard_14_fonts_demo.pdf

pdf-lib also provides an API to access the unicode code points supported by a font. For example:

import { PDFDocument } from 'pdf-lib';

(async () => {
  const pdfDoc = await PDFDocument.create();

  const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
  const characterSet = font.getCharacterSet();

  console.log('Total supported characters:', characterSet.length);

  console.log('Supports è?', characterSet.includes('è'.codePointAt(0)));
  console.log('Supports ç?', characterSet.includes('ç'.codePointAt(0)));

  console.log('Supports č?', characterSet.includes('č'.codePointAt(0)));
  console.log('Supports Ś?', characterSet.includes('Ś'.codePointAt(0)));
})();

// Output:
//   Total supported characters: 218
//   Supports è? true
//   Supports ç? true
//   Supports č? false
//   Supports Ś? false

However, you can still produce PDFs with characters outside the WinAnsi character set. You just need to use an embedded font that supports them. The Ubuntu font, for example. Here's what happens to our above example if we embed the Ubuntu font instead of Helvetica:

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

(async () => {
  const ubuntuFontBytes = await fetch(
    'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf',
  ).then((res) => res.arrayBuffer());

  const pdfDoc = await PDFDocument.create();

  pdfDoc.registerFontkit(fontkit);

  const font = await pdfDoc.embedFont(ubuntuFontBytes);
  const characterSet = font.getCharacterSet();

  console.log('Total supported characters:', characterSet.length);

  console.log('Supports è?', characterSet.includes('è'.codePointAt(0)));
  console.log('Supports ç?', characterSet.includes('ç'.codePointAt(0)));

  console.log('Supports č?', characterSet.includes('č'.codePointAt(0)));
  console.log('Supports Ś?', characterSet.includes('Ś'.codePointAt(0)));
})();

// Output:
//   Total supported characters: 1195
//   Supports è? true
//   Supports ç? true
//   Supports č? true
//   Supports Ś? true

Note that the Ubuntu font supports 1195 characters, significantly more than the 218 supported by the standard Helvetica font. And you can see that č and Ś are among the characters supported by the Ubuntu font.

Finally, I should mention that since custom fonts are embedded in the PDF file you produce, the resulting file size is necessarily increased. This probably isn't a big deal since many custom fonts are pretty small. But if you only use a few of the characters in the font, you can reduce the file size by subsetting the font (with the { subset: true } option). For example:

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

(async () => {
  const ubuntuFontBytes = await fetch(
    'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf',
  ).then((res) => res.arrayBuffer());

  /***** Without Subsetting *****/
  const pdfDoc1 = await PDFDocument.create();

  pdfDoc1.registerFontkit(fontkit);

  const font1 = await pdfDoc1.embedFont(ubuntuFontBytes);

  const page1 = pdfDoc1.addPage([500, 500]);
  page1.setFont(font1);
  page1.drawText('Testing č Ś', { x: 50, y: 150 });

  const pdfBytes1 = await pdfDoc1.save();

  console.log('File size in bytes without subsetting:', pdfBytes1.length);

  /***** With Subsetting *****/
  const pdfDoc2 = await PDFDocument.create();

  pdfDoc2.registerFontkit(fontkit);

  const font2 = await pdfDoc2.embedFont(ubuntuFontBytes, { subset: true });

  const page2 = pdfDoc2.addPage([500, 500]);
  page2.setFont(font2);
  page2.drawText('Testing č Ś', { x: 50, y: 150 });

  const pdfBytes2 = await pdfDoc2.save();

  console.log('File size in bytes with subsetting:', pdfBytes2.length);
})();

// Output:
//   File size in bytes without subsetting: 181211
//   File size in bytes with subsetting: 5566

@marek-vanco
Copy link
Author

@Hopding you have found the solution. May be you can do pull request of your solution..

@TeddyBear06
Copy link

@philippeBron Comme l'a fait remarquer @Hopding, le problème est lié à la police utilisée (Helvetica des StandardFonts de pdf-lib) qui ne supporte qu'un nombre limité de caractères (ceux de la table Windows-1252).

J'ai implémenté le code proposé par @Hopding, cela corrige effectivement le problème.

att_covi

Comme le fait remarquer @marek-vanco, le plus "gênant" (même si ce service est très pratique et que je suis - nous sommes des milliers - à vous remercier de l'avoir mis à disposition de tous), c'est que l'erreur soit silencieuse pour l'utilisateur / trice car un nombre non-négligeable de nos citoyens possèdent un "č" ou encore un "Ś" dans leur nom de famille ou encore leur lieu de naissance.

Il pourrait exister 2 approches :

  • Adopter une police supportant davantage de caractères (même si Ubuntu n'est peut être pas la plus adaptée visuellement);
  • Détecter les caractères hors de la table des caractères supportés par la police et les remplacer par leurs équivalents non-accentués (peut être compliqué dans le cadre d'une vérification d'identité ?), soit afficher un message d'erreur à l'utilisateur / trice pour lui indiquer d'utiliser une version non-accentuée de son nom/lieu de naissance...

P.S : Ci-dessous, le diff de certificate.js au cas où il pourrait être utile.

mod_covi

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

Successfully merging a pull request may close this issue.

5 participants