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

Use custom font (via vfs_fonts.js) #33

Closed
matthias-001 opened this issue May 26, 2014 · 46 comments
Closed

Use custom font (via vfs_fonts.js) #33

matthias-001 opened this issue May 26, 2014 · 46 comments

Comments

@matthias-001
Copy link

It seems that the vfs_fonts.js file contains the binary font data of the Roboto font but somehow encoded (data URI / base64 ?).
could you explain how to generate the required JS file for other fonts (and: is the LICENSE.txt required ?)

btw: great work - thanks, seems quite promising !

kind regards,
matthias

@bpampuch
Copy link
Owner

vfs_fonts.js assigns a "virtual-file-system" object to pdfMake.vfs

Each key of this object is a filename, while value contains base64 encoded file content.

When you run

grunt dump_dir

a new vfs_fonts.js is created, containing all files from examples/fonts directory.

I'm not sure if LICENSE.txt is required or not for Roboto. I've included it just to make sure I don't break the license.

To use custom fonts, 3 steps are required:

  1. create vfs_fonts.js containing your fonts
  2. define font family
  3. change font family in doc-definition-object

1. create vfs_fonts.js containing your fonts

Copy your fonts to examples/fonts directory

run grunt dump_dir (you can update Gruntfile.js if you'd like to change base directory or add an alternative config for dump_dir task)

Use your new build/vfs_fonts.js on your web page

BTW - the above action dumps all files from examples/fonts (not only fonts), which means you could put images there, run grunt dump_dir and reference them by name in doc-definition-object

2. define font family

before calling pdfMake.createPdf(docDefinition) set pdfMake.fonts to the following object:

{
   yourFontName: {
     normal: 'fontFile.ttf',
     bold: 'fontFile2.ttf',
     italics: 'fontFile3.ttf',
     bolditalics: 'fontFile4.ttf'
   },
   anotherFontName: {
     (...)
   }
}

keys are font-family names you can later use in doc-definition

Each font-family defines 4 properties: normal, bold, italics and bolditalics referring to appropriate files (by default these are file paths relative to examples/fonts/)

By default pdfMake uses the following structure:

{
        Roboto: {
                normal: 'Roboto-Regular.ttf',
                bold: 'Roboto-Medium.ttf',
                italics: 'Roboto-Italic.ttf',
                bolditalics: 'Roboto-Italic.ttf'
        }
};

3. change font family in doc-definition-object

Currently pdfmake uses 'Roboto' as default family name, so in order to use your font, you should change it. The easiest way is to do it globally in defaultStyle

var docDefinition = {
  content: (...),
  defaultStyle: {
    font: 'yourFontName'
  }
}

I know this it is overly complicated at the moment.

I'm going to change it in 0.2.0

@matthias-001
Copy link
Author

sorry for replying so late - youe explanation works perfectly (not complicated at all)
Ii took me a bit of time till I noted that ALL 4 font-styles (normal, bold, italics and bolditalics have to be specified in order to make it work)

Kind Regards !

@venugopalangithub
Copy link

Hi bpampuch,
I am new to pdfmake.I tried above 3 steps for custom font rendering in PDF, but i got blank space in that pdf for that particular word, i attached the PDF(converted to png
document) for your reference and my code.Please check and tell what i did wrong.Please guide how to use custom font in pdfmake.Thanks in advance.

This is code,

pdfMake.font={
Roboto: {
normal: 'examples/fonts/Roboto-Regular.ttf',
bold: 'examples/fonts/Roboto-Medium.ttf',
italics: 'examples/fonts/Roboto-Italic.ttf',
bolditalics: 'examples/fonts/Roboto-Italic.ttf'
},
lohit: {
normal: 'examples/fonts/lohit-Regular.ttf',
bold: 'examples/fonts/lohit-Medium.ttf',
italics: 'examples/fonts/lohit-Italic.ttf',
bolditalics: 'examples/fonts/lohit-Italic.ttf'
}
}
var docDefinition = { content: ("Test Tamil கிருஷ்ணன் Word"),
Style: {
font: 'lohit'
}
};
pdfMake.createPdf(docDefinition).open();

Thanks,
Venu

@sokdararith
Copy link

Hi bpampuch,
Thanks for great lib. I am wondering if this support unicode font like Khmer Unicode. I am working on generating invoice for my client. My output did not display as intended as the subscript not working. Please help guide me on how to do this I am using Khmer font "Battambang".

Thanks,
Rith

@infacq
Copy link

infacq commented Oct 15, 2014

hi, can you show how to set the code for client use?

@sokdararith
Copy link

Dear Muhaimin,
Thank you for your response. I am providing with zip code of my client use. To give your more info please let me elaborate a bit more of my project and my intended use.
I would love to use this to generate a report and also invoices in pdf file. Our database uses Khmer language. Khmer language has combination of supscript and superscript but in the example the subscript did not work.
I generated font based on what you described in the guide by including the font on examples/fonts folder and run grunt dump_dir command. Please advise what I can do to achieve the intended result. I highly appreciated your great work and support.
Sincerely, Rith

Date: Wed, 15 Oct 2014 00:29:05 -0700
From: notifications@github.com
To: pdfmake@noreply.github.com
CC: praksokdararith@outlook.com
Subject: Re: [pdfmake] Use custom font (via vfs_fonts.js) (#33)

hi, can you show how to set the code for client use?


Reply to this email directly or view it on GitHub. =

@dingzhanjun
Copy link

This is a great library, does this support Asian characters?

@Svobi
Copy link

Svobi commented Nov 6, 2014

After including the Font into the vfs_fonts.js like descripted above, this worked fine:

pdfMake.fonts = {
  myFont: {
      normal: 'myFont-Regular.ttf',
      bold: 'myFont-Medium.ttf',
      italics: 'myFont-Italic.ttf',
      bolditalics: 'myFont-Italic.ttf'
  }
}
var docDefinition = {
  content: (...),
  defaultStyle: {
    font: 'myFont'
  }
}
pdfMake.createPdf(docDefinition).open();

@TheShakyCoder
Copy link

Absolutely great library and I have managed to get it working in Dart via JsObject.

Problem is the 'bold' and 'italics' rendering is either all or nothing.

eg. taking bold in this case, below renders everything bold:

    content: {
        table: {
            body: [
                [{text:'Embolden', style:'embolden'}, {text:'Embolden2', style:'embolden2'}],
                ['1', '2']
            ]
        },
        bold:false
    },
    styles: {
        embolden: {
            fontSize:18,
            bold:true,
        },
        embolden2: {
            fontSize:12,
            bold:false
        },
    },
    defaultStyle: {
        fontSize:36,
        bold:false
    },

UPDATE: I have got a workaround by setting each font style as a new font ie.

    'TimesNewRoman': {
        'normal': 'Times-New-Roman.ttf'
    },
    'TimesNewRomanBold': {
        'normal': 'Times-New-Roman-Bold.ttf'
    },

@roundbox
Copy link

I can generate the pdf with whatever font I choose but when I open the file in Illustrator, the characters are converted to gibberish. I need to be able to generate the pdf and run through rip software for printing from Illustrator. Is there a workaround anyone knows of?

@shuklaalok7
Copy link

@bpampuch, May I please suggest to use Ubuntu font by default as it contains larger character-set?

@luciash
Copy link

luciash commented Apr 5, 2015

+1

On 04/04/2015 06:04 AM, Alok Shukla wrote:

@bpampuch https://github.com/bpampuch, May I please suggest to use
Ubuntu font http://font.ubuntu.com/ by default as it contains larger
character-set?


Reply to this email directly or view it on GitHub
#33 (comment).

@jthoenes
Copy link
Contributor

jthoenes commented Apr 5, 2015

I would vote strongly against it for two reasons:

  • embedding a larger font by default slows down the processing significantly (using Arial Unicode made our processing 20 times slower)
  • we break backwards compatibility for everyone

There is a valid way if you need a different font! (and I know what I'm talking about. We're using Arial in our app - without any problems).

@Chaitanya2207
Copy link

Hello Guys,
I am not understanding the First Step:- 1. create vfs_fonts.js containing your fonts.

Here, I copied the font files I need to examples/fonts directory. After that i have to "run grunt dump_dir", but I don't understand where to run this command?
Pl. help in that.

@Svobi
Copy link

Svobi commented Jul 13, 2015

You need a running grunt environement, this means, an installation of

  • node.js, (start here https://nodejs.org/download/ )
  • npm (Node Package Manager included in nodejs ),
  • an grunt Configuration and Installations, (learn here http://gruntjs.com/ -> install via npm)
  • and a grunt modul named "dump_dir" (install via npm "grunt-dump-dir").

THAN you can "compile" / DUMP the font to use in Javascript.

@Chaitanya2207
Copy link

Hi Svobi, Thanks for your help. I did based on what you mentioned here. I installed grunt and plugins in dependancy of package.json. after that i tried to install grunt-dum-dir , using following command,
"npm install grunt-dump-dir --save-dev" after running this command , i got error "D:\grunt\font\grunt-dump-dir-master>npm install grunt-dump-dir
npm WARN package.json grunt-dump-dir@0.1.2 No license field.
npm WARN install Refusing to install grunt-dump-dir as a dependency of itself"
Pl. help me in this

@Chaitanya2207
Copy link

image

@Svobi
Copy link

Svobi commented Jul 14, 2015

Well it seems only to be a warning.
Did you try to grunt already ?

@Chaitanya2207
Copy link

Thanks I was able to create the vfs_font.js.

@Chaitanya2207
Copy link

I created PDF but fonts are not reflecting in PDF. It Still shows the same old font. As step 2 a & 3 I wrote following code.

pdfMake.fonts = {
CALIBRI: {
normal: 'CALIBRI.TTF',
bold: 'CALIBRIB.TTF',
italics: 'Calibri Italic.ttf',
bolditalics: 'Calibri Bold Italic.ttf'
}
};

docDef = {
footer: function(pageCount)
{
pgCnt++;
return {columns:[{image:j,"width":w,"height":h},{text:' Please refer to site observation photographs.These defects are example and might not represent the entire Pg. '+pgCnt+'',fontSize:8}]}
},
defaultStyle: {
font: 'CALIBRI'
}
};

@Chaitanya2207
Copy link

When i converted my generated PDF to word doc, from an online converter and open doc file, the font were the same which i wanted to have. So, In PDF Fonts are not reflecting, but if I am converting that PDF to word. I am getting the fonts which i wanted.Pl. help in this

@kaunghtetaung
Copy link

Hello, I chage default font to Myanmar (Burmese) Unicode Font. It is working but unicode char display is not show correctly. Please see this error link http://prntscr.com/93nxfm.
This is correct link. http://prntscr.com/93nxvn

@jacksnose
Copy link

Hi. I’m using pdfMake and it seems great so far. However, I am struggling to get Times New Roman text into my PDF. In my project folder I’ve got a folder pdfMakeMaster, as well as my index file, my javascript file, and a bunch of other files I won’t mention.

In pdfMakeMaster, I’ve got:

build [ folder ]
examples [ folder ]
Gruntfile.js
pdfmake.js
pdfmake.min.js
vfs_fonts.js

… and a bunch of other files I won’t mention.
In examples, there’s a folder called fonts, inside which, I’ve got:

LICENSE.txt
Roboto-Italic.ttf
Roboto-Medium.ttf
Roboto-Regular.ttf
Times New Roman Bold.ttf
Times New Roman Italic.ttf
Times New Roman.ttf

You list three steps for getting a new font into my pdfMake document; I believe that I have successfully completed Step 1: creating a new version of vfs_fonts.js that includes the Times New Roman ttf files. When I change my directory via cd to my pdfMakeMaster folder and run grunt dump_dir I get the output:

Running "dump_dir:fonts" (dump_dir) task
File "build/vfs_fonts.js" created.

Done, without errors.

…and there’s a (new) file vfs_fonts.js in my build folder with a Date Created of 1 minute ago. It’s slightly larger (4.4 MB) in size than the vfs_fonts.js file resulting a grunt dump_dir run with only the Roboto ttf files (and no Times ttf files) in pdfMakeMaster/examples/fonts. So far, so good.

In my index file:

< script src='pdfMakeMaster/pdfmake.js'></script>
< script src='pdfMakeMaster/build/vfs_fonts.js'></script>

In my javascript file:

function pdfTest(){
var dd = { content: 'Test', styles: { defaultStyle: { font: 'Times' } } }
pdfMake.createPdf(dd).open();
}

When pdfTest() is called, a new tab opens displaying a PDF with the word “Test” in the Roboto font; there are no errors. (Notice that Step 3 is already completed: the defaultStyle is set to font: Times. Although it does not error, it does not use Times font.) Now, I try to to work in Step 2: defining my font family. So now in my javascript file, I’ve got:

function pdfTest(){
pdfMake.fonts = {
Roboto: {
normal: 'examples/fonts/Roboto-Regular.ttf',
bold: 'examples/fonts/Roboto-Medium.ttf',
italics: 'examples/fonts/Roboto-Italic.ttf',
bolditalics: 'examples/fonts/Roboto-Italic.ttf'
},
Times: {
normal: 'examples/fonts/Times New Roman.ttf',
bold: 'examples/fonts/Times New Roman Bold.tff',
italics: 'examples/fonts/Times New Roman Italic.ttf',
bolditalics: 'examples/fonts/Times New Roman Italic.ttf'
}
};
var dd = { content: 'Test', styles: { defaultStyle: { font: 'Times' } } }
pdfMake.createPdf(dd).open();
}

When pdfTest() is called, I receive the console error: “Uncaught Error: No unicode cmap for font — pdfmake.js: 30835” …which is the result of the snippet:

if (!this.font.cmap.unicode) { throw new Error('No unicode cmap for font'); }

… from pdfmake.js. Interestingly, I receive the same error when attempting to define my fonts with only Roboto (without Times):

function pdfTest(){
pdfMake.fonts = {
Roboto: {
normal: 'examples/fonts/Roboto-Regular.ttf',
bold: 'examples/fonts/Roboto-Medium.ttf',
italics: 'examples/fonts/Roboto-Italic.ttf',
bolditalics: 'examples/fonts/Roboto-Italic.ttf'
}
};
var dd = { content: 'Test', styles: { defaultStyle: { font: 'Times' } } }
pdfMake.createPdf(dd).open();
}

There was some discussion here [ https://github.com//issues/18 ] that this error resulted from using pdfmake.min.js, but could be avoided if one used the non-min’ed version: pdfmake.js. Notice that I am using pdfmake.js (which I got from the build folder) and am still encountering the error.

I would love for a little help getting through this issue as I have been stuck on it for some time. Please let me know of any additional information you need to help me to identify the root of my problem.

@Joeper214
Copy link

@jacksnose
+1

I've been also encoutering the same error. Does anyone has a workaround on this? Thanks

@ewarrenG
Copy link

ewarrenG commented Feb 3, 2016

@Joeper214 Our problem turned out to be that our font filepaths were incorrect. They should not start with examples/fonts. For example, 'examples/fonts/Roboto-Regular.ttf', should be 'Roboto-Regular.ttf'. Hope this helps!

@Joeper214
Copy link

@ewarrenG . Got it! Thanks for the help.

@anupam99
Copy link

anupam99 commented Feb 7, 2016

This looks very promising. Thanks Bartek.
I was playing around with custom fonts and embedded 'mangal.ttf' font for hindi langauage.
i have one sentence using my custom font and other using the roboto.

Adobe reader shows that the font is embedded...but isn't using the 'mangal' font
the font is installed on local machine as well.

image
Could it be an Adobe setting? , any pointers would be appreciated.

@AmitKannaujiya
Copy link

I had gone through step 1: create vfs_fonts.js
2: i defined custom font
pdfMake.fonts = {
FontAwesome: {
normal: 'fontawesome-webfont.ttf',
bold: 'fontawesome-webfont.ttf',
italics: 'fontawesome-webfont.ttf',
bolditalics: 'fontawesome-webfont.ttf'
},
Roboto: {
normal: 'Roboto-Regular.ttf',
bold: 'Roboto-Medium.ttf',
italics: 'Roboto-Italic.ttf',
bolditalics: 'Roboto-Italic.ttf'
}

                            };

now using it like : {font:'FontAwesome', text:'300.00'+'[]'} // '[]' = unicode for ₹
but no text shown in pdf file .
Please help

@askie
Copy link

askie commented May 26, 2016

@AmitKannaujiya the same error, no chinese words show:
using https://github.com/bpampuch/pdfmake/wiki/Custom-Fonts---client-side create my own custorm fonts, success!
browser js code:
pdfMake.fonts = { STSONG: { normal: 'STSONG.TTF', bold: 'STSONG.TTF', italics: 'STSONG.TTF', bolditalics: 'STSONG.TTF' } }; var docDefinition = { content: "abc汉语能显示了吗?", defaultStyle: { font: 'STSONG' }, }; pdfMake.createPdf(docDefinition).open();

chrome devtools no error show,the pdf can not show Chinese like below:
image

@AmitKannaujiya
Copy link

@askie: Thanks , i had done same thing, used my custom font .

@askie
Copy link

askie commented May 27, 2016

@AmitKannaujiya when I change another ttf font file , all is ok ! so try some fonts again and again !

@joungmin92
Copy link

  • I had done, i used my custom font to created vfs_fonts.js file and.Default my fonts is Roboto.tff
    image.
    The fonts i want to used is Timesnewroman.tff , and i rename it to Roboto.tff I coppied All font i want to change from scrource and rename it. and then vfs_fonts was created.
    pdfmake.js does not change it .
    image

I was successfully.

@EmirGluhbegovic
Copy link

EmirGluhbegovic commented Jan 25, 2017

Hey guys,

Im busy trying to add a custom font to pdfMake, am using it through amCharts.js.

Can someone show me what the gruntfile.js should look like?
Atm this is mine:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    dump_dir: {
      options: {
        // options
      },
      fonts: {
        'vfs_fonts.js': [ 'examples/fonts/*' ]
      },
    },
  });

  // Load the plugin that provides the "uglify" task.
  //grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-dump-dir');

  // Default task(s).
  grunt.registerTask('default', ['dump-dir']);
  //grunt.registerTask('dump-dir', ['dump-dir']);

};

When I run grunt dum_dir I get the following:
Running "dump_dir:fonts" (dump_dir) task

Done, without errors

Nothing else happens?

@tdolphin
Copy link

I didn't have to use any tools to add a custom font. I added the huge 22MB arialuni.ttf. I don't care about download size because I am using it on LAN only.
The only thing I used is Notepad++.
I opened the file and then in mime tools, I chose Base64 encode.
Then copied the result to vfs_fonts.js directly between the quotes after the colon.
,"arialuni.ttf" :""

I was surprised that copying and pasting this large amount took roughly 3 seconds.

Adding wingdings.ttf kept giving errors in pdfmake.
I am assuming because it is not openType compatible??

@solidet
Copy link

solidet commented Apr 21, 2017

Hello, I come across one issue. I already customized the font. I generated new vfs_fonts.js that contains Roboto and simfang (chinese font). The problem is the file is about 15MB and the system loads very slow for the first time because it takes much time loading that font (as I check in network tab). I have to wait for long (on production). Does anybody have solution for this ?

@oscarhandsome
Copy link

Thank you bpampuch
and all who answer and showed examples!

@fogzot
Copy link

fogzot commented Sep 4, 2017

In fact you don't even need the pdfmake source code or to include vfs_fonts.js if you better like to download the fonts from the server (that probably has them already in cache if you use the same fonts in the HTML page and the PDF). We do it this way (the language used is TypeScript but you can easily convert this to standard Javascript using promises instead of async/await):

import pdfMake from 'pdfmake/build/pdfmake';

// Avoid to re-download the fonts every time pdfmake is used, useful for SPA.
let pdfMakeInstance: any = null;

let fonts = {
    light: { normal: 'FiraSans-Light.ttf' },
    regular: { normal: 'FiraSans-Regular.ttf' },
    medium: { normal: 'FiraSans-Medium.ttf' }
}

# baseURL would be something like `/assets/fonts/`.
export async function getPdfMake(baseURL: string) {
    if (!pdfMakeInstance) {
        let vfs = {};
        let fonts = {}
        for (let fontFamily in fonts) {
            for (let font in fonts[fontFamily]) {
                let file = fonts[fontFamily][font];
                if (file && typeof vfs[file] === 'undefined') {
                    vfs[file] = (await getAsDataURL(baseURL + file)).substr(35);
                }
            }
        }

        pdfMake.vfs = vfs
        pdfMake.fonts = fonts;
        pdfMakeInstance = pdfMake;
    }

    return pdfMakeInstance;
}

function getAsDataURL(url: string): Promise<string> {
    return fetch(url, { method: 'GET' })
    .then(res => res.blob())
    .then(blob => new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = reject
        reader.readAsDataURL(blob)
      }));
}

This works on all "modern" browsers and IE 10 & 11 with the 'fetch' polyfill.

@dieunguyen95
Copy link

I tried all of the above but it still did not change

@suchislife801
Copy link

After reading the following post describing the need for a minimum of 4 fonts I was wondering.

If you need to use a font like OCR-B for optical character recognition and this font comes in only 1 style, how can I make vfs_fonts.js work with only 1 font? If this has not yet been implemented I understand.

@bhagyanath
Copy link

Does pdfMake support Unicode ?

@samayo
Copy link

samayo commented Feb 9, 2018

Just in-case anyone else has a question like @suchislife801, if you are using OCR-B like fonts, which come only in one format, then the way I got it to work was following this instruction was to copy that 1 ocr font 4 times and give then a name like; ocr-bold, ocr-normal, orc-bolditalics and ocr-italics,

after that just pass

pdfMake.fonts = {
  ocr_demo: {
    normal: 'OCR-normal.TTF',
    bold: 'OCR-bold.TTF',
    italics: 'OCR-italics.TTF',
    bolditalics: 'OCR-bolditalics.TTF',
  }
}

@jbbae
Copy link

jbbae commented Apr 17, 2018

Does anyone else encounter the issue of their custom-made vfs_fonts.js dissappearing every now and then...?

@samayo
Copy link

samayo commented Apr 17, 2018

@nickbae91 yeah, it happened to me last time, everyone who forks your lib needs to rebuild them otherwise if the push without the fonts you'll lose them too

@suhasbhattu
Copy link

I would vote strongly against it for two reasons:

  • embedding a larger font by default slows down the processing significantly (using Arial Unicode made our processing 20 times slower)
  • we break backwards compatibility for everyone

There is a valid way if you need a different font! (and I know what I'm talking about. We're using Arial in our app - without any problems).

Hi @jthoenes , Can you please tell how to handle large size fonts (I am using Arial Unicode, and it takes around a minute to load fonts only.) How did you handle this in your app?

@jthoenes
Copy link
Contributor

@suhasbhattu There's no . way around this. Large font are slow. Sorry :-/

@GoodVincentTu
Copy link

I've occurred the same issue especially the font is unicode supported. In my case, I run the build
command with the font needed to support the Mandarin characters, and the file size is more than 20MB. The temporary solution for me is to load them asynchronously.

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

No branches or pull requests