25
votes

Is it possible to include custom fonts in jsPDF ?

With the basic library, if I console log 'doc.getFontList()' I get:

Courier, Helvetica, Times, courier, helvetica, times

But, say I want to use 'Comic Sans' ( not that I would ;o) ) can it be done ?

Even better, could I use a font is locally stored and has been declared in the site with @font-face ?

7

7 Answers

28
votes

I found this was possible by modifying jsPDF.js to expose the existing addFont method in the public API.

In jsPDF.js, look for:

//---------------------------------------
// Public API

Add the following:

    API.addFont = function(postScriptName, fontName, fontStyle) {
      addFont(postScriptName, fontName, fontStyle, 'StandardEncoding');
    };

I put this method near other font methods for clarity - API.setFont, API.setFontSize, API.setFontType, etc.

Now in your code, use:

doc.addFont('ComicSansMS', 'Comic Sans', 'normal');
doc.setFont('Comic Sans');
doc.text(50,50,'Hello World');

This works for me with @font-face fonts included with css before loading jsPDF, as well as system fonts. There's probably a better way to do this using jsPDF's plugin framework, but this quick and dirty solution should at least get you going.

Note that doc.getFontList() will not show added fonts:

// TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
20
votes

It seems to be a lot easier with the latest version of jsPDF (1.5.3):

If you look in the folder jsPDF-master > fontconverter, there's a file fontconverter.html. Open in your browser and use the Browse... button to navigate to, and select your .ttf font file.

Click 'Create'.

enter image description here

The page will offer a "download" to be saved. This will produce a .js file called [something like] RopaSans-Regular-normal.js. This needs to be included in your page producing the PDF's. Personally, I've done it in the main page's header (and please note the order of the scripts):

<!-- pdf creation -->
<script src="FileSaver.js-master/src/FileSaver.js"></script>
<script src="jsPDF-master/dist/jspdf.debug.js"></script>

<!-- custom font definition -->
<script src="path-to-the-file-just-saved/RopaSans-Regular-normal.js" type="module"></script>

Now in your PDF generation method in js:

doc.setFont('RopaSans-Regular');
doc.setFontType('normal');
5
votes

Here is the solution I'm using...

First, as others have mentioned - you need these two libraries:

  1. jsPDF: https://github.com/MrRio/jsPDF
  2. jsPDF-CustomFonts-support: https://github.com/sphilee/jsPDF-CustomFonts-support

Next - the second library requires that you provide it with at least one custom font in a file named default_vfs.js. I'm using two custom fonts - Arimo-Regular.ttf and Arimo-Bold.ttf - both from Google Fonts. So, my default_vfs.js file looks like this:

(

(function (jsPDFAPI) { 
    "use strict";
    jsPDFAPI.addFileToVFS('Arimo-Regular.ttf','[Base64-encoded string of your font]');
    jsPDFAPI.addFileToVFS('Arimo-Bold.ttf','[Base64-encoded string of your font]');
})(jsPDF.API);

Obviously, you version would look different, depending on the font(s) you're using.

There's a bunch of ways to get the Base64-encoded string for your font, but I used this: https://www.giftofspeed.com/base64-encoder/.

It lets you upload a font .ttf file, and it'll give you the Base64 string that you can paste into default_vfs.js.

You can see what the actual file looks like, with my fonts, here: https://cdn.rawgit.com/stuehler/jsPDF-CustomFonts-support/master/dist/default_vfs.js

So, once your fonts are stored in that file, your HTML should look like this:

    <script src="js/jspdf.min.js"></script>
    <script src="js/jspdf.customfonts.min.js"></script>
    <script src="js/default_vfs.js"></script>

Finally, your JavaScript code looks something like this:

const doc = new jsPDF({
      unit: 'pt',
      orientation: 'p',
      lineHeight: 1.2
    });

doc.addFont("Arimo-Regular.ttf", "Arimo", "normal");
doc.addFont("Arimo-Bold.ttf", "Arimo", "bold");

doc.setFont("Arimo");
doc.setFontType("normal");
doc.setFontSize(28);

doc.text("Hello, World!", 100, 100);

doc.setFontType("bold");

doc.text("Hello, BOLD World!", 100, 150);

doc.save("customFonts.pdf");

This is probably obvious to most, but in that addFont() method, the three parameters are:

  1. The font's name you used in the addFileToVFS() function in the default_vfs.js file
  2. The font's name you use in the setFont() function in your JavaScript
  3. The font's style you use in the setFontType() function in your JavaScript

You can see this working here: https://codepen.io/stuehler/pen/pZMdKo

Hope this works as well for you as it did for me.

3
votes

I'm using Angular 8 and Todd's answer worked for me.

Once you get the .js file from fontconverter.html, you can import it in typescript like so:

import fontref = require('path/to/font/CustomFont-normal.js')

Then all you have to do to load the font is 'call' fontref:

makePdf() {
    let doc = new jsPDF();

    fontref;                             // 'call' .js to load font

    doc.getFontList();                   // contains a key-value pair for CustomFont

    doc.setFont("CustomFont");           // set font
    doc.setFontType("normal");
    doc.setFontSize(28);
    doc.text("Hello", 20, 20);

    window.open(doc.output('bloburl'));  // open pdf in new tab
  }
1
votes

Some of these answers are outdated, so I am linking the readme file from Mr. Rio himself regarding the latest release as of this post. Below is a copy of the paragraph from that readme file followed by a link to the readme file itself. Hope this additional resource is helpful:

Use of UTF-8 / TTF: The 14 standard fonts in PDF are limited to the ASCII-codepage. If you want to use UTF-8 you have to to integrate a custom font, which provides the needed glyphs. jsPDF supports .ttf-files. So if you want to have for example chinese text in your pdf, your font has to have the necessary chinese glyphs. So check if your font supports the wanted glyphs or else it will show a blank space instead of the text.

To add the font to jsPDF use our fontconverter in /fontconverter/fontconverter.html . The fontconverter will create a js-file with the content of the provided ttf-file as base64 encoded string and additional code for jsPDF. You just have to add this generated js-File to your project. You are then ready to go to use setFont-method in your code and write your UTF-8 encoded text.

https://github.com/MrRio/jsPDF/blob/master/README.md#use-of-utf-8--ttf

0
votes

The easiest way that I have found by far is using the jspdf-customfonts package. Simply install the package by npm i jspdf-customfonts then add the following files in the head tag of your index.html for default configurations

script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script> 
<script src="dist/jspdf.customfonts.min.js"></script> 
<script src="dist/default_vfs.js"></script> 

Now you can download the ttf file of whichever font you want. Then go to this site, select your font and copy the code, and you are done!

jsPDF-CustomFonts

0
votes

After looking at the fontconverter.html, and seeing that it does nothing more than package the TTF files into a base64 string inside a JS file, I came up with the following method that I call before creating my document. It basically does what the individual files resulting from fontconverter.html do, just on-demand:

async function loadFont(src, name, style, weight) {
    const fontBytes = await fetch(src).then(res => res.arrayBuffer());
    
    var filename = src.split('\\').pop().split('/').pop();
    var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(fontBytes)));

    var callAddFont = function () {
        this.addFileToVFS(filename, base64String);
        this.addFont(filename, name, style, weight );
        };
    jsPDF.API.events.push(['addFonts', callAddFont]);
}

Call it like this:

await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-italic.ttf", "Exo-2", "italic", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-regular.ttf", "Exo-2", "normal", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500.ttf", "Exo-2", "normal", 500);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500italic.ttf", "Exo-2", "italic", 500);

It loads the font from the URL, and adds it to the VFS and font manager. Important: the font name cannot include spaces. You won't get any warnings, but the resulting PDF will either not open or the text will look funny.