phphtmlpdfdompdfpimcore

Not able to render non ANSI characters in PDF using DOMPDF


I am trying to create a PDF using DOMPDF in Pimcore which functionality works absolutly fine, but I am having issues while trying to include non ANSI characters in PDF, like Thai, Koread, Chinese characters. Either they are getting converted to question marks or it returns Squere boxes.

Here is the Code I am using.

    public function downloadPdfTemplate(Request $request): Response
    {

        header('Content-Type: text/html; charset=utf-8');
        $checkStatus = GeneralHelper::getUserAndRoleFromSession();
        $peId = $request && $request->get('id') ? $request->get('id') : 0;
        $userLanguage = $request && $request->get('language') ? $request->get('language') : $checkStatus[LANGUAGE];
        DataObject\PackagingElement::setHideUnpublished(false);
        $peData = DataObject\PackagingElement::getById($peId);

        if ($peData) {
            $pdfData = PackagingElementService::generatePePdf($peData, $userLanguage, $peId, true);

            // Configure Dompdf according to your needs
            $pdfOptions = new Options();
            $pdfOptions->set('isHtml5ParserEnabled', true);
            $pdfOptions->set('isPhpEnabled', true);
            $pdfOptions->set('isFontSubsettingEnabled', true);
            $pdfOptions->set('isRemoteEnabled', true);
            $fontPath = PIMCORE_PROJECT_ROOT.'/public/bundles/frontend/css/fonts/NotoSansThai.ttf'; // Update the path accordingly
            $pdfOptions->setFontDir(PIMCORE_PROJECT_ROOT . '/public/bundles/frontend/css/fonts/');
            $fileContents = file_get_contents($fontPath);
            $html = $this->renderView('@Frontend/packingElements/model/download-pdf-template.html.twig', $pdfData);
            $dompdf = new Dompdf($pdfOptions);
            $canvas = new CPDF([0, 0, 200, 200], "portrait", $dompdf);
            $fontMetrics = new FontMetrics($canvas,$pdfOptions);
            $fontMetrics->registerFont(['family'=>'Noto Sans Thai', 'style'=>'normal', 'weight'=>'normal'],
                $fontPath);
            $dompdf->setFontMetrics($fontMetrics);
            $dompdf->loadHtml($html,'UTF-8');
            $dompdf->render();
            $output = $dompdf->output();

            $pdfagicode = $pdfData['agiCode'];
            $globdesc = $pdfData['globalDescription'];
            $gd = GeneralHelper::replaceSpecialCharacters($globdesc);
            $pdfFilepath = $folderName . '/PE_' . $pdfagicode . '_' . $gd . '.pdf';
            file_put_contents($pdfFilepath, $output);

            // Output the generated PDF to Browser (force download)
            $dompdf->stream('PE_' . $pdfagicode . '_' . $gd . '.pdf', [
                'Attachment' => true,
            ]);
            unlink($pdfFilepath);
        } else {
            return $this->redirect('/packaging-element');
        }

    }

Here is my sample HTML I am using:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link
            href="https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@600&family=Noto+Sans+JP:wght@600&family=Noto+Sans+KR:wght@600&family=Noto+Sans+SC:wght@600&family=Noto+Sans+TC:wght@600&display=swap"
            rel="stylesheet" crossorigin>

        <style>

            /** Define now the real margins of every page in the PDF **/
            body {
                margin-top: 4cm;
                margin-left: 0.5cm;
                margin-right: 0.5cm;
                margin-bottom: 1.8cm;
                border-top: 1px solid #a0a0a0 !important;
                font-family: 'Noto Sans HK', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans Thai','Noto Sans Tai Viet', DejaVu Sans, sans-serif

            }
        </style>
    </head>
    <body>
        <p>Thai text สวัสดี</p>
    </body>
</html>

Please let me know If anyone have any suggestions on this.

Also If possible add solution for Korean, Chinese, Japanese, Vietnamese.


Solution

  • Make sure you use a font which supports your language (e.g. Noto Sans Thai font which supports Thai characters)

    So say use the following (for thai):

    <link href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Noto+Sans+Thai:wght@100..900&display=swap" rel="stylesheet">
    
    <style>
    
    .noto-sans-thai {
      font-family: "Noto Sans Thai", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "wdth" 100;
    }
    
    
    </style>
    

    then use something like

     <p class="noto-sans-thai">
             สวัสดี Stackoverflow Ken Lee สวัสดี
        </p>
    
    

    Fully working code:

    <?php
    require 'vendor/autoload.php';
    use Dompdf\Dompdf;
    
    
    $html = <<<HTML
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Noto+Sans+Thai:wght@100..900&display=swap" rel="stylesheet">
    
    <style>
    
    .noto-sans-thai {
      font-family: "Noto Sans Thai", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "wdth" 100;
    }
    
    
    </style>
    </head>
    <body>
        <p class="noto-sans-thai">
            สวัสดี Stackoverflow Ken Lee สวัสดี
        </p>
    </body>
    </html>
    HTML
    ;
    
    //$_dompdf_show_warnings = true;
    //$_dompdf_debug = true;
    
    $tmp = sys_get_temp_dir();
    
    $dompdf = new Dompdf([
        'logOutputFile' => '',
        // authorize DomPdf to download fonts and other Internet assets
        'isRemoteEnabled' => true,
        // all directories must exist and not end with /
        'fontDir' => $tmp,
        'fontCache' => $tmp,
        'tempDir' => $tmp,
        'chroot' => $tmp,
    ]);
    
    $dompdf->loadHtml($html);
    
    $dompdf->render();
    
    $dompdf->stream('hello.pdf', [
        'compress' => true,
        'Attachment' => false,
    ]);
    

    See result below:

    enter image description here

    -Additional Points-

    In case you want to display other languages, you need to use the correct font for that language, so see the following:

    <?php
    require 'vendor/autoload.php';
    use Dompdf\Dompdf;
    
    
    $html = <<<HTML
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Noto+Sans+Thai:wght@100..900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100..900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100..900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&display=swap" rel="stylesheet">
    
    <style>
    
    .noto-sans-thai {
      font-family: "Noto Sans Thai", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "width" 100;
    }
    
    .noto-sans-TC {
      font-family: "Noto Sans TC", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "width" 100;
    }
    
    .noto-sans-SC {
      font-family: "Noto Sans SC", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "width" 100;
    }
    
    .noto-sans-JP {
      font-family: "Noto Sans JP", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "width" 100;
    }
    
    .noto-sans-KR {
      font-family: "Noto Sans KR", sans-serif;
      font-optical-sizing: auto;
      font-weight: <weight>;
      font-style: normal;
      font-variation-settings:
        "width" 100;
    }
    
    
    
    </style>
    </head>
    <body>
        <p class="noto-sans-thai">
            สวัสดี Stackoverflow สวัสดี
        </p>
        <p class="noto-sans-TC">
            圖書館 Stack Overflow  圖書館
        </p>
        <p class="noto-sans-SC">
            图书馆 Stack Overflow  图书馆
        </p>
        <p class="noto-sans-KR">
           라이브러리 스택 오버플로 라이브러리
        </p>
        <p class="noto-sans-JP">
            ライブラリ スタック オーバーフロー ライブラリ
        </p>
    </body>
    </html>
    HTML
    ;
    
    //$_dompdf_show_warnings = true;
    //$_dompdf_debug = true;
    
    $tmp = sys_get_temp_dir();
    
    $dompdf = new Dompdf([
        'logOutputFile' => '',
        // authorize DomPdf to download fonts and other Internet assets
        'isRemoteEnabled' => true,
        // all directories must exist and not end with /
        'fontDir' => $tmp,
        'fontCache' => $tmp,
        'tempDir' => $tmp,
        'chroot' => $tmp,
    ]);
    
    $dompdf->loadHtml($html);
    
    $dompdf->render();
    
    $dompdf->stream('hello.pdf', [
        'compress' => true,
        'Attachment' => false,
    ]);
    

    See below for result (note: I do not know Vietnamese so cannot find the font, please search by yourself for Vientamese)

    enter image description here