将字体添加到mPDF

26

使用 mPDF 类生成 PDF 时,我遇到了以下错误:

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

我已将字体文件上传到我的ttfonts目录,并在config_fonts.php中定义了字体,如下所示:

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

只有在我打开配置文件中的字体错误报告时才会看到错误。当我关闭错误报告时,PDF被生成了,但使用的字体不是Verdana。

你对我做错了什么有什么想法吗?


你有成功吗? - alexej_d
请查看此链接:http://www.mpdf1.com/forum/discussion/1139/fonts-not-showing/p1 - Ajit Singh
6个回答

28

以下是在mpdf库中添加新字体族的步骤:

  1. 下载字体zip文件并解压缩。
  2. 将新的 newFont.ttf 字体文件添加到此位置 /mpdf/ttfonts 文件夹中。
  3. 编辑 /mpdf/config_fonts.php/mpdf/src/config/FontVariables.php,为新字体文件添加一个条目到 $this->fontdata 数组中。例如:

    $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';现在可以在样式表中使用。

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

  6. 现在您的新字体已经添加成功。


我强烈反对在此处描述的方法。无论什么情况下,都不应更改原始文件 - 所有更改都会随着更新消失。以下是在原始文档中如何处理的方法:https://mpdf.github.io/fonts-languages/fonts-in-mpdf-7-x.html - Peter VARGA

22

基于 @hrvoje-golcic 的回答,这里提供一种改进且更少污染的方法来向 mPDF 添加字体而无需编辑config_fonts.php。我正在使用 Laravel,使用 composer 安装了 mPDF。

  1. 按照作者建议,在初始化 mPDF 之前定义一个名为 _MPDF_TTFONTPATH 的常量,并将值设置为您的 ttfonts 文件夹的路径(此常量至少自5.3版以来就已存在)。
  2. vendor/mpdf/mpdf/ttfonts 文件夹复制到您控制的位置(位于 vendor 文件夹之外)。
  3. 将您的自定义字体与其他字体一起添加到该文件夹中。
  4. 将您的配置添加到 mPDF 实例的fontdata属性中。

注意:ttfonts 文件夹大小约为90MB,因此可能仍有更好的方法,但您必须复制所有字体,因为原始配置会将它们添加到里面。请参见本答案底部的composer脚本替代方案。

重要提示:CSS font-family 将转换为小写字母+无空格,因此“Source Sans Pro”将变为 sourcesanspro。

以下是一个例子:

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安装后脚本

使用Composer安装后脚本的巧妙方法,可以避免复制所有字体并将它们添加到git中。

首先,请确保您希望复制字体的文件夹存在,并在其中创建一个 .gitignore 文件,并添加以下内容:

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

这将忽略除.gitignore文件和您想要添加的字体之外的所有内容。

接下来,在您的composer.json文件中添加以下脚本:

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

注意事项

此版本已测试通过6.1。
在7.x中,作者实现了一种优雅的方式来添加外部字体。


这可能是添加自定义字体的正确方法,但是...如果您正在使用Laravel和mPDF 7.x,最简单的方法在此处提到在mPDF 7.x中添加自定义字体 - Ahamed Rasheed
问题在于手动更改 vendor 文件夹中的内容是非常不正确的。 - s3v3n
1
啊哈,太有趣了,我无法在文档中找到任何小写转换。他们为什么要这样做,为什么不在自定义字体部分用大红色的巨大闪烁的免责声明来记录它?感谢 @s3v3n。 - Marek Maurizio

6

除了使用lib文件之外,还有一种“不正规”的方法可以在运行时动态添加字体。这是我的解决方案,因为我无法修改config_fonts.pdf文件,因为它在vendor/文件夹中,会在库更新时被覆盖。

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;
}

请确保提供的字体路径是相对于mpdf的ttfonts/目录的。 重要提示: CSS font-family将被转换为小写+去除空格,例如"Source Sans Pro-Regular"将变为sourcesanspro-regular。 例如,在这里我添加了2种字体和3个字体文件,因为其他字体有常规和粗体版本:
$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);

这是针对mpdf 5.x的,但希望在6.x上也能使用。有人试过吗?

1
我可以确认这适用于mPDF的6.x分支。感谢您提出此建议,我不知道为什么所有这些逻辑都被嵌入到mpdf的初始设置中,而不能在其外部重新运行 ಠ_ಠ 它将解决许多字体问题! :) - jaymz

2
只需将字体添加到FontVariable.php文件中。"最初的回答"。
                "pacifico" => [
                'R' => "Pacifico.ttf",
                'useOTL' => 0xFF,
                'useKashida' => 75,
            ],

请确保ttf文件名以大写字母开头,例如Pacifico.ttf,那么在命名字体族时要以小写字母开头,就像我在顶部所做的那样。 例如将其命名为pacifico 然后,使用创建测试php文件来简单测试它。

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();

0

0

不需要在屏幕上显示错误。 在您的php + apache(?)服务器的“error.log”日志文件中查看所有错误和警告。 它可以帮助您根据日志文件中的消息找到并解决问题。

无论如何,您应该使用推荐的字体-请参阅mPDF手册。

可能需要将TrueType字体转换为适当的MPDF格式。 (http://mpdf1.com/manual/index.php?tid=409&searchstring=fonts)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接