* @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 custom XMP namespace injection via setCustomXMP(). * * PDF files carry an XMP metadata stream alongside the classic Info dictionary. * The tc-lib-pdf library always emits standard namespaces (dc:, xmp:, pdf:, * xmpMM:, pdfaid:, etc.). setCustomXMP() lets you inject arbitrary additional * XMP fragments into specific positions within the XMP envelope. * * Valid keys and their injection points * ────────────────────────────────────── * 'x:xmpmeta' * Inserted just before — top-level envelope extension. * * 'x:xmpmeta.rdf:RDF' * Inserted just before — adds a new rdf:Description block. * * 'x:xmpmeta.rdf:RDF.rdf:Description' * Inserted into the main rdf:Description — adds properties to the * existing shared description block (dc, xmp, pdf properties). * * 'x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas' * 'x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas.rdf:Bag' * PDF/A extension schema declarations (only meaningful in PDF/A mode). * * IMPORTANT: the injected XML is NOT validated by the library. You are * responsible for well-formed, namespace-correct XMP. Malformed XMP will * not prevent PDF generation but may confuse metadata readers. * * Use cases illustrated here: * 1. IPTC Core rights metadata (photojournalism / stock-photography DAM) * 2. XMP-MM version history (document management / DAM systems) * 3. Custom application metadata (arbitrary key-value pairs for integration) */ $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: 060'); $pdf->setTitle('Custom XMP Metadata Injection'); $pdf->setKeywords('TCPDF tc-lib-pdf example xmp metadata iptc dublin core dam archiving'); $pdf->setPDFFilename('E060_custom_xmp_metadata.pdf'); $pdf->setViewerPreferences(['DisplayDocTitle' => true]); $pdf->enableDefaultPageContent(); // ----------------------------------------------------------------------- // 1. IPTC Core rights and creator metadata // Injected as a new rdf:Description block inside rdf:RDF. // ----------------------------------------------------------------------- $iptcXmp = <<<'XMP' Copyright © 2026 Tecnick.com LTD. All rights reserved. info@tecnick.com https://tecnick.com Permission is granted to reproduce for personal and commercial use, citing the source. Modification is not allowed. XMP; // Key: inject before $pdf->setCustomXMP('x:xmpmeta.rdf:RDF', $iptcXmp); // ----------------------------------------------------------------------- // 2. XMP Media Management — version / revision history // Also injected as a new rdf:Description block. // ----------------------------------------------------------------------- $xmpMmXmp = <<<'XMP' urn:uuid:tc-lib-pdf-example-060-2026 urn:uuid:tc-lib-pdf-example-060-instance-001 1.0 created 2026-05-01T00:00:00+00:00 tc-lib-pdf urn:uuid:tc-lib-pdf-example-059-2026 1.0 XMP; $pdf->setCustomXMP('x:xmpmeta.rdf:RDF', $xmpMmXmp); // ----------------------------------------------------------------------- // 3. Custom application metadata (key-value pairs for system integration) // Injected as extra properties in the existing shared rdf:Description. // ----------------------------------------------------------------------- $appXmp = <<<'XMP' E060 tc-lib-pdf 2026-05-01 XMP; // Note: this key injects into the existing shared rdf:Description block. // The tcpdf: prefix must be declared in the same Description or a parent. // For self-contained safety we wrap it in its own Description with the ns decl. $appXmpBlock = <<<'XMP' E060 tc-lib-pdf 2026-05-01 custom-xmp-metadata XMP; $pdf->setCustomXMP('x:xmpmeta.rdf:RDF', $appXmpBlock); // ----------------------------------------------------------------------- // Page — explanation and key summary // ----------------------------------------------------------------------- $bfont = $pdf->font->insert($pdf->pon, 'helvetica', '', 10); $bfontB = $pdf->font->insert($pdf->pon, 'helvetica', 'B', 14); $page1 = $pdf->addPage(); $html = <<<'HTML'

Custom XMP Metadata Injection

This PDF embeds three custom XMP metadata blocks beyond the standard dc:/xmp: namespaces that tc-lib-pdf emits automatically. Inspect the XMP stream with a PDF inspector or exiftool -XMP -b output.pdf to verify.

Block 1 — IPTC Core rights

Namespace: Iptc4xmpCore (http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/)
Injection key: x:xmpmeta.rdf:RDF
Contains: CopyrightNotice, CreatorContactInfo (email, URL), UsageTerms.
Typical use: photojournalism DAM, stock-photography catalogues.

Block 2 — XMP-MM version history

Namespace: xmpMM (http://ns.adobe.com/xap/1.0/mm/)
Injection key: x:xmpmeta.rdf:RDF
Contains: DocumentID, InstanceID, VersionID, History (sequence of events), DerivedFrom.
Typical use: document management systems, digital asset lineage tracking.

Block 3 — Custom application metadata

Namespace: tcpdf (https://github.com/tecnickcom/tc-lib-pdf/ns/xmp/1.0/)
Injection key: x:xmpmeta.rdf:RDF
Contains: exampleId, generatedBy, generationDate, featureTag.
Typical use: integration metadata for build pipelines, print-MIS systems, or any workflow that needs to carry arbitrary key-value pairs inside the PDF without modifying the Info dictionary.

Important notes

• The injected XML is embedded as-is; the library does NOT validate XMP well-formedness.
• Multiple calls with the same key are concatenated in insertion order.
• Injection into x:xmpmeta.rdf:RDF.rdf:Description adds properties to the shared Description block; prefer a standalone Description block (as done here) to keep namespace declarations self-contained.
• All standard metadata (title, author, subject, keywords, dates, producer) is still emitted automatically and is not affected by setCustomXMP().

HTML; $pdf->addHTMLCell(html: $html, posx: 15, posy: 20, width: 180); $rawpdf = $pdf->getOutPDFString(); $pdf->renderPDF(rawpdf: $rawpdf);