diff --git a/app/Config/exports.php b/app/Config/exports.php index 2e22bc759e3..f48fe0a67a3 100644 --- a/app/Config/exports.php +++ b/app/Config/exports.php @@ -68,7 +68,7 @@ * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic, * Symbol, ZapfDingbats. */ - 'font_dir' => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782) + 'font_dir' => storage_path('fonts/dompdf'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782) /** * The location of the DOMPDF font cache directory. @@ -78,7 +78,7 @@ * * Note: This directory must exist and be writable by the webserver process. */ - 'font_cache' => storage_path('fonts/'), + 'font_cache' => storage_path('fonts/dompdf/cache'), /** * The location of a temporary directory. diff --git a/app/Exports/PdfGenerator.php b/app/Exports/PdfGenerator.php index f31d8aad078..df40bf44f81 100644 --- a/app/Exports/PdfGenerator.php +++ b/app/Exports/PdfGenerator.php @@ -4,6 +4,8 @@ use BookStack\Exceptions\PdfExportException; use Dompdf\Dompdf; +use FontLib\Font; +use Illuminate\Support\Str; use Knp\Snappy\Pdf as SnappyPdf; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Process; @@ -60,12 +62,57 @@ protected function renderUsingDomPdf(string $html): string $domPdf = new Dompdf($options); $domPdf->setBasePath(base_path('public')); + $fontMetrics = $domPdf->getFontMetrics(); + $userFontfamilies = $this->getUserDomPdfFontFamilies(); + foreach ($userFontfamilies as $fontFamily => $fonts) { + $fontMetrics->setFontFamily($fontFamily, $fonts); + } + +// dd($userFontfamilies, $fontMetrics->getFontFamilies()); $domPdf->loadHTML($this->convertEntities($html)); $domPdf->render(); return (string) $domPdf->output(); } + /** + * @return array> + */ + protected function getUserDomPdfFontFamilies(): array + { + $fontStore = storage_path('fonts/dompdf'); + if (!is_dir($fontStore)) { + return []; + } + + $fontFamilies = []; + $fontFiles = glob($fontStore . DIRECTORY_SEPARATOR . '*.ttf'); + foreach ($fontFiles as $fontFile) { + $fontFileName = basename($fontFile, '.ttf'); + $expectedUfm = $fontStore . DIRECTORY_SEPARATOR . $fontFileName . '.ufm'; + if (!file_exists($expectedUfm)) { + $font = Font::load($fontFile); + $font->parse(); + $font->saveAdobeFontMetrics($expectedUfm); + } + + $nameParts = explode('-', $fontFileName); + if (count($nameParts) === 1 || $nameParts[1] === 'Regular') { + $nameParts[1] = 'Normal'; + } + + $family = trim(strtolower(preg_replace('/([A-Z])/', ' $1', $nameParts[0]))); + $variation = Str::snake($nameParts[1]); + if (!isset($fontFamilies[$family])) { + $fontFamilies[$family] = []; + } + + $fontFamilies[$family][$variation] = $fontStore . DIRECTORY_SEPARATOR . $fontFileName; + } + + return $fontFamilies; + } + /** * @throws PdfExportException */ diff --git a/storage/fonts/.gitignore b/storage/fonts/.gitignore index c96a04f008e..cb0b47dace2 100755 --- a/storage/fonts/.gitignore +++ b/storage/fonts/.gitignore @@ -1,2 +1,6 @@ +# Font cache files have once been stored directly in this folder +# therefore its important the contents non-ignored by git +# are chosen selectively * -!.gitignore \ No newline at end of file +!.gitignore +!dompdf/ \ No newline at end of file diff --git a/storage/fonts/dompdf/.gitignore b/storage/fonts/dompdf/.gitignore new file mode 100644 index 00000000000..23ef65311b4 --- /dev/null +++ b/storage/fonts/dompdf/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!cache/ \ No newline at end of file diff --git a/storage/fonts/dompdf/cache/.gitignore b/storage/fonts/dompdf/cache/.gitignore new file mode 100644 index 00000000000..c96a04f008e --- /dev/null +++ b/storage/fonts/dompdf/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file