26

I'm getting the following error when I try and generate a PDF using the mPDF class:

TTF file "C:/wamp/www/inc/mpdf/ttfonts/verdana.ttf": invalid checksum 20f65173c11 table: DSIG (expected 65173c11)

I've uploaded the font files to my ttfonts directory and defined the font in config_fonts.php like this:

"verdana" => array(
    'R' => "verdana.ttf",
    'B' => "verdanab.ttf",
    'I' => "verdanai.ttf",
    'BI' => "verdanaz.ttf",
    ),

I only see the error when I turn on font error reporting in the config settings. When I turn error reporting off, the PDF is generated, but the font being used is not Verdana.

Any idea on what I'm doing wrong?

Paul Dessert
  • 6,363
  • 8
  • 47
  • 74

6 Answers6

26

Following are the steps to add new font family in mpdf library:

  1. Download the font zip and unzip it.
  2. Add new newFont.ttf font file(s) to this location /mpdf/ttfonts folder.
  3. Edit /mpdf/config_fonts.php OR /mpdf/src/config/FontVariables.php to add an entry to the $this->fontdata array for the new font file(s). Like:

    $this->fontdata = array(
        "newFont" => array(
        'R' => "newFont-Regular.ttf",
        'B' => "newFont-Bold.ttf",
        'I' => "newFont-Italic.ttf",
        'BI' => "newFont-BoldItalic.ttf",
    ),
    
  4. font-family: 'newFont'; is now available in the stylesheets.

  5. $mpdfObj = new mPDF('', '', 'newFont'); $mpdfObj->SetFont('newFont');

  6. Now your new font is added.

Ajai
  • 2,492
  • 1
  • 14
  • 23
  • I strongly advise against the method described here. Under no circumstances should you change the original files - all changes are gone with the update. Here is how to do it in the original documentation: https://mpdf.github.io/fonts-languages/fonts-in-mpdf-7-x.html – Peter VARGA Jul 17 '21 at 19:44
22

Based on @hrvoje-golcic answer, here's an improved and less dirty way to add fonts to mPDF without editing config_fonts.php. I'm using Laravel, I installed mPDF using composer.

  1. As suggested by the author, define a constant named _MPDF_TTFONTPATH before initializing mPDF with the value as the path to your ttfonts folder (this constant exists since at least 5.3).
  2. Copy the vendor/mpdf/mpdf/ttfonts folder to a location that you control (outside of the vendor folder).
  3. Add your custom fonts to that folder along with the others.
  4. Add your configuration to the fontdata property on the mPDF instance.

Heads up: The ttfonts folder has around 90MB so there's still might be a better way, but you have to copy all the fonts since the original config adds them. See composer script alternative at the bottom of this answer.

IMPORTANT: CSS font-family will be transformed to lowercase + nospaces so "Source Sans Pro" will become sourcesanspro.

Here's an example:

if (!defined('_MPDF_TTFONTPATH')) {
    // an absolute path is preferred, trailing slash required:
    define('_MPDF_TTFONTPATH', realpath('fonts/'));
    // example using Laravel's resource_path function:
    // define('_MPDF_TTFONTPATH', resource_path('fonts/'));
}

function add_custom_fonts_to_mpdf($mpdf, $fonts_list) {

    $fontdata = [
        'sourcesanspro' => [
            'R' => 'SourceSansPro-Regular.ttf',
            'B' => 'SourceSansPro-Bold.ttf',
        ],
    ];

    foreach ($fontdata as $f => $fs) {
        // add to fontdata array
        $mpdf->fontdata[$f] = $fs;

        // add to available fonts array
        foreach (['R', 'B', 'I', 'BI'] as $style) {
            if (isset($fs[$style]) && $fs[$style]) {
                // warning: no suffix for regular style! hours wasted: 2
                $mpdf->available_unifonts[] = $f . trim($style, 'R');
            }
        }

    }

    $mpdf->default_available_fonts = $mpdf->available_unifonts;
}

$mpdf = new mPDF('UTF-8', 'A4');
add_custom_fonts_to_mpdf($mpdf);
$mpdf->WriteHTML($html);

Composer post-install script

Instead of copying all the fonts and adding them to git, a handy workaround using a composer post-install script can do that for you.

First of all, make sure the folder where you wish to copy the fonts exists, and create a .gitignore in it, with the following contents:

*
!.gitignore
!SourceSansPro-Regular.ttf
!SourceSansPro-Bold.ttf

This will ignore everything except the .gitignore file and the fonts you wish to add.

Next, add the following scripts to your composer.json file:

"scripts": {
    "post-install-cmd": [
        "cp -f vendor/mpdf/mpdf/ttfonts/* resources/fonts/"
    ],
    "post-update-cmd": [
        "cp -f vendor/mpdf/mpdf/ttfonts/* resources/fonts/"
    ]
}

Notes

This was tested to work with 6.1.
In 7.x, the author implemented an elegant way to add external fonts.

Community
  • 1
  • 1
s3v3n
  • 8,203
  • 5
  • 42
  • 56
  • This might be the correct way of adding custom fonts but... if you are using **Laravel and mPDF 7.x** the simplest way is mentioned here [adding custom fonts in mPDF 7.x](https://stackoverflow.com/questions/17586409/adding-font-to-mpdf/54586897#54586897) – Ahamed Rasheed Feb 08 '19 at 06:13
  • Well the problem is that it is very wrong to manually change stuff in the `vendor` folder – s3v3n Feb 08 '19 at 12:15
  • 1
    Ah ah so funny I could not find the lowercase conversion anywhere in the docs. Why did they do it and why why why not document it with a big red giant huge blinking disclaimer in the custom font section? Thank tou @s3v3n. – Marek Maurizio Nov 21 '19 at 10:06
6

There is another "dirty" way to add fonts dynamically in the run-time aside to the lib files. This was my solution because I wasn't able to modify config_fonts.pdf file since it was in vendor/ files and would be overwritten on library update.

function add_custom_fonts_to_mpdf($mpdf, $fonts_list) {
    // Logic from line 1146 mpdf.pdf - $this->available_unifonts = array()...       
    foreach ($fonts_list as $f => $fs) {
        // add to fontdata array
        $mpdf->fontdata[$f] = $fs;

        // add to available fonts array
        if (isset($fs['R']) && $fs['R']) { $mpdf->available_unifonts[] = $f; }
        if (isset($fs['B']) && $fs['B']) { $mpdf->available_unifonts[] = $f.'B'; }
        if (isset($fs['I']) && $fs['I']) { $mpdf->available_unifonts[] = $f.'I'; }
        if (isset($fs['BI']) && $fs['BI']) { $mpdf->available_unifonts[] = $f.'BI'; }
    }
    $mpdf->default_available_fonts = $mpdf->available_unifonts;
}

Make sure to provide font paths relative to to mpdf's ttfonts/ dir

IMPORTANT: CSS font-family will be transformed to lowercase + nospaces so "Source Sans Pro-Regular" will become sourcesanspro-regular

For example here I'm adding 2 fonts and 3 font files because other font has regular and bold version:

$mpdf = new mPDF('utf-8', 'A4', '', '', 20, 15, 50, 25, 10, 10);
$custom_fontdata = array(
    'sourcesanspro-regular' => array(
        'R' => "../../../../wms/hr_frontend/job/internet/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf" 
        // use 'R' to support CSS font-weight: normal
        // use 'B', 'I', 'BI' and etc. to support CSS font-weight: bold, font-style: italic, and both...
    ),
    'someotherfont' => array(
        'R' => "../../../../wms/hr_frontend/job/internet/fonts/someotherfont.ttf", // In CSS font-weight: normal
        'B' => "../../../../wms/hr_frontend/job/internet/fonts/someotherfont-bold.ttf" // In CSS font-weight: bold
    )
);
add_custom_font_to_mpdf($mpdf, $custom_fontdata);
$mpdf->WriteHTML($html);

This was for mpdf 5.x but hopefully it works for 6.x as well. Did anyone try?

Hrvoje Golcic
  • 3,446
  • 1
  • 29
  • 33
  • 1
    I can confirm this worked for the 6.x branch of mPDF. Thanks for suggesting this, I have no idea why all that logic is baked into the initial setup of mpdf and can't be rerun outside of it ಠ_ಠ It would solve a lot of problems with fonts! :) – jaymz Dec 21 '16 at 17:15
2

simply add font to FontVariable.php

                "pacifico" => [
                'R' => "Pacifico.ttf",
                'useOTL' => 0xFF,
                'useKashida' => 75,
            ],

make sure if the ttf file name is start with capital letter like Pacifico.ttf then name the font family with start of small letter as i do on top . e.g make this pacifico and now simply test this with create testing php file

require_once __DIR__ . '/autoload.php';
$defaultConfig = (new Mpdf\Config\ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new Mpdf\Config\FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
$mpdf = new \Mpdf\Mpdf([
'mode' => 'utf-8',
'format' => 'A4'.('orientation' == 'L' ? '-L' : ''),
'orientation' => 0,
'margin_left' => 3,
'margin_right' => 3,
'margin_top' => 3,
'margin_bottom' => 0,
'margin_header' => 0,
'margin_footer' => 0,
]);    
$texttt= '
    <html>
    <p style="font-family: dejavusanscondensed;"> Text in Frutiger </p>
    <p style="font-family: freeserif;"> Text in Frutiger </p>
    <p style="font-family: freemono;"> Text in Frutiger </p>
    <p style="font-family: freeserif;"> مرحبا بالعالم </p>
    <p style="font-family: unbatang;"> 하는 바에 의하여 영장제도 </p>
    <p style="font-family: centurygothic;"> Text in Frutiger </p>
    <p style="font-family: pacifico;"> Text in Frutiger </p>
    <p style="font-family: windsong;"> Text in Frutiger </p>
    </html>';
     $mpdf->WriteHTML($texttt,\Mpdf\HTMLParserMode::HTML_BODY);
$mpdf->Output();
Er Mandeep
  • 41
  • 2
0

No need to show errors on the screen. See all errors and warnings in log file like "error.log" of your php + apache(?) server. It help you to find and resolve the problem based on message in the log file.

I any case you should use recommend fonts - see mPDF manual.

Probably, you need to convert TrueType fonts into proper MPDF's format. (http://mpdf1.com/manual/index.php?tid=409&searchstring=fonts)

Intacto
  • 527
  • 3
  • 8
0

Mpdf add Arial font

  1. Download font file : https://github.com/JotJunior/PHP-Boleto-ZF2/blob/master/public/assets/fonts/arial.ttf

  2. Paste the arial.ttf to mpdf/ttfonts

  3. Open config_fonts.php and the below code with fontdata array

    "arial" => array( 'R' => "arial.ttf", ),

Mohd Bashir
  • 949
  • 1
  • 8
  • 17