generated from jric11/baseProject
519 lines
13 KiB
PHP
519 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* E030_svg.php
|
|
*
|
|
* Dedicated SVG rendering example.
|
|
*
|
|
* Exercises all SVG image files shipped in the examples/images/ directory and
|
|
* serves as a visual regression baseline for SVG feature development.
|
|
*
|
|
* @since 2026-04-26
|
|
* @category Library
|
|
* @package Pdf
|
|
* @author Nicola Asuni <info@tecnick.com>
|
|
* @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('OUTPUT_FILE', \realpath(__DIR__ . '/../target') . '/example_svg.pdf');
|
|
|
|
// define fonts directory
|
|
\define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts'));
|
|
|
|
// autoloader when using RPM or DEB package installation
|
|
//require ('/usr/share/php/Com/Tecnick/Pdf/autoload.php');
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// SVG directory
|
|
$svgdir = __DIR__ . '/images';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// PDF object
|
|
|
|
$pdf = new \Com\Tecnick\Pdf\Tcpdf(
|
|
unit: \Com\Tecnick\Pdf\Page\Unit::Millimeter,
|
|
isunicode: true,
|
|
subsetfont: false,
|
|
compress: true,
|
|
);
|
|
|
|
$pdf->setCreator('tc-lib-pdf');
|
|
$pdf->setAuthor('Nicola Asuni');
|
|
$pdf->setSubject('tc-lib-pdf example: 030 — SVG');
|
|
$pdf->setTitle('SVG Rendering Example');
|
|
$pdf->setKeywords('TCPDF tc-lib-pdf SVG example');
|
|
$pdf->setPDFFilename('030_svg.pdf');
|
|
|
|
$pdf->setViewerPreferences(['DisplayDocTitle' => true]);
|
|
|
|
$pdf->enableDefaultPageContent();
|
|
|
|
// Insert a font for page labels
|
|
$bfont = $pdf->font->insert($pdf->pon, 'helvetica', '', 10);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 1 — tcpdf_box.svg
|
|
//
|
|
// A multi-path box illustration that exercises fill, stroke, fill-rule and
|
|
// transform handling.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page01 = $pdf->addPage();
|
|
$pdf->setBookmark(name: 'tcpdf_box.svg', link: '', level: 0, page: -1, posx: 0, posy: 0, fstyle: 'B', color: 'blue');
|
|
|
|
$pdf->page->addContent($bfont['out']);
|
|
|
|
// Label
|
|
$pdf->addTextCell(
|
|
txt: 'tcpdf_box.svg — paths, fill, stroke, fill-rule',
|
|
pid: -1,
|
|
posx: 10,
|
|
posy: 10,
|
|
width: 190,
|
|
height: 6,
|
|
offset: 0,
|
|
linespace: 0,
|
|
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
|
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
|
cell: null,
|
|
styles: [],
|
|
strokewidth: 0,
|
|
wordspacing: 0,
|
|
leading: 0,
|
|
rise: 0,
|
|
jlast: true,
|
|
fill: true,
|
|
stroke: false,
|
|
underline: false,
|
|
linethrough: false,
|
|
overline: false,
|
|
clip: false,
|
|
drawcell: false,
|
|
);
|
|
|
|
// Render at two different sizes to check scaling
|
|
$svg01a = $pdf->addSVG(
|
|
img: $svgdir . '/tcpdf_box.svg',
|
|
posx: 10,
|
|
posy: 20,
|
|
width: 180,
|
|
height: 120,
|
|
pageheight: $page01['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg01a));
|
|
|
|
$svg01b = $pdf->addSVG(
|
|
img: $svgdir . '/tcpdf_box.svg',
|
|
posx: 10,
|
|
posy: 148,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page01['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg01b));
|
|
|
|
$svg01c = $pdf->addSVG(
|
|
img: $svgdir . '/tcpdf_box.svg',
|
|
posx: 105,
|
|
posy: 148,
|
|
width: 45,
|
|
height: 30,
|
|
pageheight: $page01['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg01c));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 2 — testsvg.svg
|
|
//
|
|
// Exercises linear and radial gradients, clip-paths, complex paths, text and
|
|
// image embedding inside an SVG document.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page02 = $pdf->addPage();
|
|
$pdf->setBookmark(name: 'testsvg.svg', link: '', level: 0, page: -1, posx: 0, posy: 0, fstyle: 'B', color: 'green');
|
|
|
|
$pdf->page->addContent($bfont['out']);
|
|
|
|
$pdf->addTextCell(
|
|
txt: 'testsvg.svg — gradients, clip-paths, text, embedded image',
|
|
pid: -1,
|
|
posx: 10,
|
|
posy: 10,
|
|
width: 190,
|
|
height: 6,
|
|
offset: 0,
|
|
linespace: 0,
|
|
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
|
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
|
cell: null,
|
|
styles: [],
|
|
strokewidth: 0,
|
|
wordspacing: 0,
|
|
leading: 0,
|
|
rise: 0,
|
|
jlast: true,
|
|
fill: true,
|
|
stroke: false,
|
|
underline: false,
|
|
linethrough: false,
|
|
overline: false,
|
|
clip: false,
|
|
drawcell: false,
|
|
);
|
|
|
|
// Full-width render
|
|
$svg02a = $pdf->addSVG(
|
|
img: $svgdir . '/testsvg.svg',
|
|
posx: 10,
|
|
posy: 20,
|
|
width: 190,
|
|
height: 95,
|
|
pageheight: $page02['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg02a));
|
|
|
|
// Smaller render to verify scaling
|
|
$svg02b = $pdf->addSVG(
|
|
img: $svgdir . '/testsvg.svg',
|
|
posx: 10,
|
|
posy: 120,
|
|
width: 95,
|
|
height: 47,
|
|
pageheight: $page02['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg02b));
|
|
|
|
$svg02c = $pdf->addSVG(
|
|
img: $svgdir . '/testsvg.svg',
|
|
posx: 110,
|
|
posy: 120,
|
|
width: 47,
|
|
height: 23,
|
|
pageheight: $page02['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg02c));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 3 — testsvgblend.svg
|
|
//
|
|
// Exercises mix-blend-mode (multiply, screen, darken …) and opacity.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page03 = $pdf->addPage();
|
|
$pdf->setBookmark(name: 'testsvgblend.svg', link: '', level: 0, page: -1, posx: 0, posy: 0, fstyle: 'B', color: 'red');
|
|
|
|
$pdf->page->addContent($bfont['out']);
|
|
|
|
$pdf->addTextCell(
|
|
txt: 'testsvgblend.svg — blend modes, opacity',
|
|
pid: -1,
|
|
posx: 10,
|
|
posy: 10,
|
|
width: 190,
|
|
height: 6,
|
|
offset: 0,
|
|
linespace: 0,
|
|
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
|
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
|
cell: null,
|
|
styles: [],
|
|
strokewidth: 0,
|
|
wordspacing: 0,
|
|
leading: 0,
|
|
rise: 0,
|
|
jlast: true,
|
|
fill: true,
|
|
stroke: false,
|
|
underline: false,
|
|
linethrough: false,
|
|
overline: false,
|
|
clip: false,
|
|
drawcell: false,
|
|
);
|
|
|
|
$svg03a = $pdf->addSVG(
|
|
img: $svgdir . '/testsvgblend.svg',
|
|
posx: 10,
|
|
posy: 20,
|
|
width: 190,
|
|
height: 127,
|
|
pageheight: $page03['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg03a));
|
|
|
|
// Side-by-side scaled copies
|
|
$svg03b = $pdf->addSVG(
|
|
img: $svgdir . '/testsvgblend.svg',
|
|
posx: 10,
|
|
posy: 155,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page03['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg03b));
|
|
|
|
$svg03c = $pdf->addSVG(
|
|
img: $svgdir . '/testsvgblend.svg',
|
|
posx: 105,
|
|
posy: 155,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page03['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg03c));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 4 — tux.svg
|
|
//
|
|
// The Tux penguin — a complex multi-path SVG with fine detail and many style
|
|
// attributes (fill, stroke, stroke-width, opacity).
|
|
//
|
|
// Copyright: Larry Ewing — permits any use with proper attribution.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page04 = $pdf->addPage();
|
|
$pdf->setBookmark(name: 'tux.svg', link: '', level: 0, page: -1, posx: 0, posy: 0, fstyle: 'B', color: 'black');
|
|
|
|
$pdf->page->addContent($bfont['out']);
|
|
|
|
$pdf->addTextCell(
|
|
txt: 'tux.svg — complex multi-path illustration (The copyright holder of the Tux image is Larry Ewing)',
|
|
pid: -1,
|
|
posx: 10,
|
|
posy: 10,
|
|
width: 190,
|
|
height: 6,
|
|
offset: 0,
|
|
linespace: 0,
|
|
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
|
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
|
cell: null,
|
|
styles: [],
|
|
strokewidth: 0,
|
|
wordspacing: 0,
|
|
leading: 0,
|
|
rise: 0,
|
|
jlast: true,
|
|
fill: true,
|
|
stroke: false,
|
|
underline: false,
|
|
linethrough: false,
|
|
overline: false,
|
|
clip: false,
|
|
drawcell: false,
|
|
);
|
|
|
|
// Large centred render
|
|
$svg04a = $pdf->addSVG(
|
|
img: $svgdir . '/tux.svg',
|
|
posx: 55,
|
|
posy: 20,
|
|
width: 100,
|
|
height: 121,
|
|
pageheight: $page04['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg04a));
|
|
|
|
// Three scaled thumbnails
|
|
$svg04b = $pdf->addSVG(
|
|
img: $svgdir . '/tux.svg',
|
|
posx: 10,
|
|
posy: 148,
|
|
width: 55,
|
|
height: 66,
|
|
pageheight: $page04['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg04b));
|
|
|
|
$svg04c = $pdf->addSVG(
|
|
img: $svgdir . '/tux.svg',
|
|
posx: 70,
|
|
posy: 148,
|
|
width: 40,
|
|
height: 48,
|
|
pageheight: $page04['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg04c));
|
|
|
|
$svg04d = $pdf->addSVG(
|
|
img: $svgdir . '/tux.svg',
|
|
posx: 115,
|
|
posy: 148,
|
|
width: 25,
|
|
height: 30,
|
|
pageheight: $page04['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg04d));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 5 — all four images together (overview grid)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page05 = $pdf->addPage();
|
|
$pdf->setBookmark(
|
|
name: 'SVG overview grid',
|
|
link: '',
|
|
level: 0,
|
|
page: -1,
|
|
posx: 0,
|
|
posy: 0,
|
|
fstyle: 'B',
|
|
color: 'purple',
|
|
);
|
|
|
|
$pdf->page->addContent($bfont['out']);
|
|
|
|
$pdf->addTextCell(
|
|
txt: 'SVG overview grid — all four images at equal size',
|
|
pid: -1,
|
|
posx: 10,
|
|
posy: 10,
|
|
width: 190,
|
|
height: 6,
|
|
offset: 0,
|
|
linespace: 0,
|
|
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
|
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
|
cell: null,
|
|
styles: [],
|
|
strokewidth: 0,
|
|
wordspacing: 0,
|
|
leading: 0,
|
|
rise: 0,
|
|
jlast: true,
|
|
fill: true,
|
|
stroke: false,
|
|
underline: false,
|
|
linethrough: false,
|
|
overline: false,
|
|
clip: false,
|
|
drawcell: false,
|
|
);
|
|
|
|
// Row 1
|
|
$s1 = $pdf->addSVG(
|
|
img: $svgdir . '/tcpdf_box.svg',
|
|
posx: 10,
|
|
posy: 20,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page05['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $s1));
|
|
|
|
$s2 = $pdf->addSVG(
|
|
img: $svgdir . '/testsvg.svg',
|
|
posx: 105,
|
|
posy: 20,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page05['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $s2));
|
|
|
|
// Row 2
|
|
$s3 = $pdf->addSVG(
|
|
img: $svgdir . '/testsvgblend.svg',
|
|
posx: 10,
|
|
posy: 88,
|
|
width: 90,
|
|
height: 60,
|
|
pageheight: $page05['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $s3));
|
|
|
|
$s4 = $pdf->addSVG(
|
|
img: $svgdir . '/tux.svg',
|
|
posx: 105,
|
|
posy: 88,
|
|
width: 90,
|
|
height: 109,
|
|
pageheight: $page05['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $s4));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 6 — abstract_a4_features.svg (full-page portrait)
|
|
//
|
|
// Dedicated A4 portrait abstract composition that concentrates most SVG
|
|
// features currently supported by this library in one single visual sample.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page06 = $pdf->addPage();
|
|
$pdf->setBookmark(
|
|
name: 'abstract_a4_features.svg',
|
|
link: '',
|
|
level: 0,
|
|
page: -1,
|
|
posx: 0,
|
|
posy: 0,
|
|
fstyle: 'B',
|
|
color: 'orange',
|
|
);
|
|
|
|
$svg06a = $pdf->addSVG(
|
|
img: $svgdir . '/abstract_a4_features.svg',
|
|
posx: 0,
|
|
posy: 0,
|
|
width: $page06['width'],
|
|
height: $page06['height'],
|
|
pageheight: $page06['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg06a));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page 7 — path_text_regressions.svg (full-page portrait)
|
|
//
|
|
// Visual regression sheet for the path and text parsing rules that are easy to
|
|
// break: numbers with no leading digit, packed decimals, scientific notation,
|
|
// elliptical arc flags packed against their neighbours, the smooth curve
|
|
// commands 'S' and 'T', compound subpaths under both fill rules, text
|
|
// anchoring, XML white space handling and multi chunk text layout.
|
|
//
|
|
// Every shape is drawn twice, as a pale fill from a verbose path and as a dark
|
|
// outline from the compact equivalent: the outline must trace the fill exactly.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$page07 = $pdf->addPage();
|
|
$pdf->setBookmark(
|
|
name: 'path_text_regressions.svg',
|
|
link: '',
|
|
level: 0,
|
|
page: -1,
|
|
posx: 0,
|
|
posy: 0,
|
|
fstyle: 'B',
|
|
color: 'purple',
|
|
);
|
|
|
|
$svg07a = $pdf->addSVG(
|
|
img: $svgdir . '/path_text_regressions.svg',
|
|
posx: 0,
|
|
posy: 0,
|
|
width: $page07['width'],
|
|
height: $page07['height'],
|
|
pageheight: $page07['height'],
|
|
);
|
|
$pdf->page->addContent($pdf->getSetSVG(soid: $svg07a));
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Output
|
|
// ---------------------------------------------------------------------------
|
|
|
|
$rawpdf = $pdf->getOutPDFString();
|
|
$pdf->renderPDF(rawpdf: $rawpdf);
|