* @copyright 2002-2026 Nicola Asuni - Tecnick.com LTD * @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE) * @link https://github.com/tecnickcom/tc-lib-pdf * * This file is part of tc-lib-pdf software library. */ // NOTE: local file reads (images, fonts, attachments) are restricted to an allowlist of // trusted paths that covers this package tree, so run the examples in place. To read assets // from other locations, list them in the 'allowedPaths' entry of the fileOptions constructor // parameter (see E047_remote_resources_security.php). // NOTE: run make fonts in the project root to generate the dependencies and example fonts. // autoloader when using Composer require __DIR__ . '/../vendor/autoload.php'; // define fonts directory \define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts')); /** * Demonstrate external TeX hyphenation pattern loading via * loadTexHyphenPatterns() + setTexHyphenPatterns(). * * Background * ────────── * tc-lib-pdf inherits hyphenation support from the tc-lib-unicode library. * By default NO hyphenation patterns are loaded; hyphenation only occurs * when explicit soft-hyphens (­) are present in the source text * (see E028_text_hyphenation.php for that approach). * * When you call setTexHyphenPatterns() with a loaded pattern array, the * library automatically inserts soft-hyphen break points based on the * pattern rules while laying out each text run. This is especially useful * for narrow columns, justified text, or languages with long compound words * (German, Dutch, Finnish, etc.) where manual soft-hyphen insertion would * be impractical. * * API * ─── * loadTexHyphenPatterns(string $file): array * Parses a TeX .tex pattern file (the standard format used by CTAN * packages such as hyph-utf8) and returns a pattern array. * The file must contain a \patterns{ ... } block. * * setTexHyphenPatterns(array $patterns): void * Installs the pattern array as the active hyphenation dictionary. * Pass an empty array [] to disable automatic hyphenation. * * Full pattern files for ~100 languages are available from CTAN: * https://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/tex * * This example uses a small Dutch sample pattern file bundled with the * examples to keep the demo self-contained. The same technique works with * any complete CTAN TeX pattern file. * * Comparison layout * ───────────────── * The page shows the same Dutch paragraph rendered twice side by side: * Left column — NO patterns loaded (only explicit ­ break points) * Right column — Dutch sample patterns loaded via loadTexHyphenPatterns() * * Dutch is a good demonstration language because it has many long compound * words (e.g. "woordenschat", "zelfstandigheid", "werkgelegenheid") that * benefit greatly from automatic hyphenation in narrow columns. */ // Path to the bundled sample Dutch TeX pattern file. $patternFile = \realpath(__DIR__ . '/data/hyph-nl-sample.tex'); if ($patternFile === false) { throw new \RuntimeException('Missing pattern file: examples/data/hyph-nl-sample.tex'); } // ----------------------------------------------------------------------- // Common document setup // ----------------------------------------------------------------------- $pdf = new \Com\Tecnick\Pdf\Tcpdf( unit: \Com\Tecnick\Pdf\Page\Unit::Millimeter, isunicode: true, subsetfont: false, compress: true, mode: \Com\Tecnick\Pdf\PdfConformance::None, objEncrypt: null, ); $pdf->setCreator('tc-lib-pdf'); $pdf->setAuthor('Nicola Asuni'); $pdf->setSubject('tc-lib-pdf example: 064'); $pdf->setTitle('Custom TeX Hyphenation Dictionary'); $pdf->setKeywords('TCPDF tc-lib-pdf example hyphenation tex patterns dutch custom dictionary'); $pdf->setPDFFilename('E064_custom_hyphenation_dictionary.pdf'); $pdf->setViewerPreferences(['DisplayDocTitle' => true]); $pdf->enableDefaultPageContent(); // ----------------------------------------------------------------------- // Load the Dutch pattern file BEFORE generating content. // ----------------------------------------------------------------------- // Step 1: parse the .tex file into a pattern array. $dutchPatterns = $pdf->loadTexHyphenPatterns(file: $patternFile); // Step 2: install as the active dictionary. $pdf->setTexHyphenPatterns(patterns: $dutchPatterns); // ----------------------------------------------------------------------- // Fonts // ----------------------------------------------------------------------- $fontTitle = $pdf->font->insert($pdf->pon, 'helvetica', 'B', 14); $fontH2 = $pdf->font->insert($pdf->pon, 'helvetica', 'B', 11); $fontBody = $pdf->font->insert($pdf->pon, 'times', '', 9); $fontCode = $pdf->font->insert($pdf->pon, 'courier', '', 8); $fontSmall = $pdf->font->insert($pdf->pon, 'helvetica', '', 8); // ----------------------------------------------------------------------- // Dutch sample text — a paragraph with long compound words. // ----------------------------------------------------------------------- $dutchPara = 'De Nederlandse taal staat bekend om zijn lange samenstellingen. ' . 'Woorden zoals woordenschatontwikkeling, zelfstandigheidsbewegingen, ' . 'werkgelegenheidsbeleid, verantwoordelijkheidsgevoelens, ' . 'maatschappelijkontwikkelingswerk en informatietechnologieonderwijs ' . 'zijn perfecte voorbeelden van samenstellingen die automatische ' . 'woordafbreking vereisen voor een goede leesbaarheid in smalle kolommen. ' . 'Zonder patronen worden zulke woorden niet afgebroken en loopt de tekst ' . 'over de kolomrand of ontstaan er grote witruimten bij uitgevulde tekst. ' . 'Met de juiste TeX-patronen worden breekpunten automatisch ingevoegd ' . 'op de linguistisch correcte syllabegrenzen van elk woord.'; // ----------------------------------------------------------------------- // Page 1 — Side-by-side comparison // ----------------------------------------------------------------------- $page1 = $pdf->addPage(); // --- Title --- $pdf->page->addContent($fontTitle['out']); $pdf->page->addContent($pdf->getTextCell( 'Custom TeX Hyphenation Dictionary', 15.0, 18.0, 180.0, 0.0, drawcell: false, valign: \Com\Tecnick\Pdf\TextVAlign::Top, halign: \Com\Tecnick\Pdf\TextHAlign::Left, )); $pdf->page->addContent($fontSmall['out']); $pdf->page->addContent($pdf->getTextCell( 'loadTexHyphenPatterns() + setTexHyphenPatterns() — Dutch sample patterns vs no patterns', 15.0, 27.0, 180.0, 0.0, drawcell: false, valign: \Com\Tecnick\Pdf\TextVAlign::Top, halign: \Com\Tecnick\Pdf\TextHAlign::Left, )); // --- Column headers --- $pdf->page->addContent($fontH2['out']); $pdf->page->addContent($pdf->getTextCell( 'Without patterns', 15.0, 37.0, 87.0, 0.0, drawcell: false, valign: \Com\Tecnick\Pdf\TextVAlign::Top, halign: \Com\Tecnick\Pdf\TextHAlign::Center, )); $pdf->page->addContent($pdf->getTextCell( 'With Dutch patterns', 108.0, 37.0, 87.0, 0.0, drawcell: false, valign: \Com\Tecnick\Pdf\TextVAlign::Top, halign: \Com\Tecnick\Pdf\TextHAlign::Center, )); // Separator line between header and body $sepStyle = [ 'lineWidth' => 0.3, 'lineCap' => 'butt', 'lineJoin' => 'miter', 'dashArray' => [], 'dashPhase' => 0, 'lineColor' => '#336699', 'fillColor' => '', ]; $pdf->page->addContent($pdf->graph->getLine(15.0, 43.5, 195.0, 43.5, $sepStyle)); // Vertical divider between columns $divStyle = [ 'lineWidth' => 0.2, 'lineCap' => 'butt', 'lineJoin' => 'miter', 'dashArray' => [], 'dashPhase' => 0, 'lineColor' => '#aaaaaa', 'fillColor' => '', ]; $pdf->page->addContent($pdf->graph->getLine(103.0, 44.0, 103.0, 200.0, $divStyle)); // ----------------------------------------------------------------------- // Left column — no automatic hyphenation // ----------------------------------------------------------------------- // Temporarily disable patterns. $pdf->setTexHyphenPatterns(patterns: []); $leftHtml = '
' . $dutchPara . '
'; // Re-insert non-bold font before left column addHTMLCell. $pdf->font->insert($pdf->pon, 'helvetica', '', 9); $pdf->addHTMLCell(html: $leftHtml, posx: 15.0, posy: 45.0, width: 87.0); // ----------------------------------------------------------------------- // Right column — Dutch patterns active // ----------------------------------------------------------------------- // Re-enable Dutch patterns. $pdf->setTexHyphenPatterns(patterns: $dutchPatterns); $rightHtml = '
' . $dutchPara . '
'; // Reset font stack to non-bold before second addHTMLCell. $pdf->font->insert($pdf->pon, 'helvetica', '', 9); $pdf->addHTMLCell(html: $rightHtml, posx: 108.0, posy: 45.0, width: 87.0); // ----------------------------------------------------------------------- // Pattern statistics block (below columns) // ----------------------------------------------------------------------- $pdf->page->addContent($fontSmall['out']); $patternCount = \count($dutchPatterns); $pdf->page->addContent($pdf->getTextCell( "Pattern file: examples/data/hyph-nl-sample.tex | Patterns loaded: {$patternCount}" . ' | Source: CTAN hyph-utf8 (excerpt)', 15.0, 205.0, 180.0, 0.0, drawcell: false, valign: \Com\Tecnick\Pdf\TextVAlign::Top, halign: \Com\Tecnick\Pdf\TextHAlign::Center, )); // ----------------------------------------------------------------------- // Page 2 — API reference and usage guidance // ----------------------------------------------------------------------- $page2 = $pdf->addPage(); // Re-insert non-bold base font so the font stack is clean before addHTMLCell. $pdf->font->insert($pdf->pon, 'helvetica', '', 8); $html2 = <<<'HTML'

API Reference and Usage Guidance

loadTexHyphenPatterns(string $file): array

Reads a TeX hyphenation pattern file and returns an associative array mapping pattern keys to their weighted strings. The file must contain a \patterns{ ... } block in standard TeX format. Comments (lines starting with %) are stripped before parsing.

The returned array can be stored and reused across multiple PDF objects without re-reading the file:

    $patterns = $pdf->loadTexHyphenPatterns(lang: '/path/to/hyph-en-us.tex');
    $pdf->setTexHyphenPatterns(lang: $patterns);
    

setTexHyphenPatterns(array $patterns): void

Installs the pattern array as the active hyphenation dictionary. Hyphenation applies to all subsequent text layout calls. Pass an empty array [] to disable automatic hyphenation.

Obtaining pattern files

Full-quality pattern files for approximately 100 languages are available from the CTAN hyph-utf8 package:
https://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/tex

Notable files:

File Language
hyph-en-us.texEnglish (US)
hyph-de-1996.texGerman (1996 reform)
hyph-nl.texDutch
hyph-fr.texFrench
hyph-pl.texPolish
hyph-fi.texFinnish
hyph-pt.texPortuguese
hyph-sv.texSwedish

Soft hyphens vs automatic patterns — when to use each

&shy; (soft hyphens in HTML) — best for single documents with known content where exact break points matter (e.g. trade-marked compound names, proper nouns that patterns would get wrong). See E028_text_hyphenation.php.

setTexHyphenPatterns() — best for documents with large amounts of flowing text where manual annotation is impractical (articles, books, reports). Patterns are applied automatically to every word during layout without modifying the source string.

Switching languages mid-document

You can switch the active dictionary between pages or even between HTML cells by calling setTexHyphenPatterns() again with a different pattern array. Load all required pattern arrays at startup to avoid disk I/O during layout, then swap them as needed.

HTML; $pdf->addHTMLCell(html: $html2, posx: 15.0, posy: 20.0, width: 180.0); $rawpdf = $pdf->getOutPDFString(); $pdf->renderPDF(rawpdf: $rawpdf);