fixed space to tabs

This commit is contained in:
2026-05-08 11:36:25 +02:00
parent a67f5ead68
commit 775229ad0a
2 changed files with 192 additions and 191 deletions

View File

@ -13,37 +13,37 @@ $pdf = new \Com\Tecnick\Pdf\Tcpdf();
*/ */
function readParams(): array function readParams(): array
{ {
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
$options = \getopt('', ['dot-size:', 'space:']); $options = \getopt('', ['dot-size:', 'space:']);
return [ return [
'dot-size' => parseFloatParam($options['dot-size'] ?? null, 0.35), 'dot-size' => parseFloatParam($options['dot-size'] ?? null, 0.35),
'space' => parseFloatParam($options['space'] ?? null, 5.0), 'space' => parseFloatParam($options['space'] ?? null, 5.0),
]; ];
} }
return [ return [
'dot-size' => parseFloatParam($_GET['dot-size'] ?? null, 0.35), 'dot-size' => parseFloatParam($_GET['dot-size'] ?? null, 0.35),
'space' => parseFloatParam($_GET['space'] ?? null, 5.0), 'space' => parseFloatParam($_GET['space'] ?? null, 5.0),
]; ];
} }
function parseFloatParam(mixed $value, float $default): float function parseFloatParam(mixed $value, float $default): float
{ {
if ($value === null || $value === '') { if ($value === null || $value === '') {
return $default; return $default;
} }
if (\is_array($value)) { if (\is_array($value)) {
fail('Parameter value must be a single number.'); fail('Parameter value must be a single number.');
} }
$normalized = \str_replace(',', '.', (string) $value); $normalized = \str_replace(',', '.', (string) $value);
if (! \is_numeric($normalized)) { if (! \is_numeric($normalized)) {
fail('Parameter value must be numeric.'); fail('Parameter value must be numeric.');
} }
return (float) $normalized; return (float) $normalized;
} }
/** /**
@ -51,103 +51,103 @@ function parseFloatParam(mixed $value, float $default): float
*/ */
function validateParams(array $params): void function validateParams(array $params): void
{ {
if ($params['dot-size'] <= 0 || $params['dot-size'] > 2) { if ($params['dot-size'] <= 0 || $params['dot-size'] > 2) {
fail('Invalid --dot-size value. Use a number greater than 0 and at most 2 mm.'); fail('Invalid --dot-size value. Use a number greater than 0 and at most 2 mm.');
} }
if ($params['space'] < 2 || $params['space'] > 20) { if ($params['space'] < 2 || $params['space'] > 20) {
fail('Invalid --space value. Use a number from 2 to 20 mm.'); fail('Invalid --space value. Use a number from 2 to 20 mm.');
} }
} }
function fail(string $message): never function fail(string $message): never
{ {
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
\fwrite(STDERR, 'Error: ' . $message . PHP_EOL); \fwrite(STDERR, 'Error: ' . $message . PHP_EOL);
exit(1); exit(1);
} }
\http_response_code(400); \http_response_code(400);
\header('Content-Type: text/plain; charset=utf-8'); \header('Content-Type: text/plain; charset=utf-8');
echo 'Error: ' . $message; echo 'Error: ' . $message;
exit; exit;
} }
function getLineStyle(float $width, string $color): array function getLineStyle(float $width, string $color): array
{ {
return [ return [
'lineWidth' => $width, 'lineWidth' => $width,
'lineCap' => 'butt', 'lineCap' => 'butt',
'lineJoin' => 'miter', 'lineJoin' => 'miter',
'dashArray' => [], 'dashArray' => [],
'dashPhase' => 0, 'dashPhase' => 0,
'lineColor' => $color, 'lineColor' => $color,
]; ];
} }
function getFillStyle(string $color): array function getFillStyle(string $color): array
{ {
return [ return [
'all' => [ 'all' => [
'lineWidth' => 0, 'lineWidth' => 0,
'lineCap' => 'butt', 'lineCap' => 'butt',
'lineJoin' => 'miter', 'lineJoin' => 'miter',
'dashArray' => [], 'dashArray' => [],
'dashPhase' => 0, 'dashPhase' => 0,
'lineColor' => $color, 'lineColor' => $color,
'fillColor' => $color, 'fillColor' => $color,
], ],
]; ];
} }
/** /**
* @param array{x: float, y: float, width: float, height: float} $tableBox * @param array{x: float, y: float, width: float, height: float} $tableBox
*/ */
function drawDotGrid( function drawDotGrid(
\Com\Tecnick\Pdf\Tcpdf $pdf, \Com\Tecnick\Pdf\Tcpdf $pdf,
float $left, float $left,
float $top, float $top,
float $right, float $right,
float $bottom, float $bottom,
float $dotSize, float $dotSize,
float $space, float $space,
array $tableBox array $tableBox
): void { ): void {
$radius = $dotSize / 2.0; $radius = $dotSize / 2.0;
$dotStyle = getFillStyle('rgb(145,145,145)'); $dotStyle = getFillStyle('rgb(145,145,145)');
for ($y = $top; $y <= $bottom; $y += $space) { for ($y = $top; $y <= $bottom; $y += $space) {
for ($x = $left; $x <= $right; $x += $space) { for ($x = $left; $x <= $right; $x += $space) {
$insideTable = ( $insideTable = (
$x >= $tableBox['x'] $x >= $tableBox['x']
&& $x <= ($tableBox['x'] + $tableBox['width']) && $x <= ($tableBox['x'] + $tableBox['width'])
&& $y >= $tableBox['y'] && $y >= $tableBox['y']
&& $y <= ($tableBox['y'] + $tableBox['height']) && $y <= ($tableBox['y'] + $tableBox['height'])
); );
if ($insideTable) { if ($insideTable) {
continue; continue;
} }
$pdf->page->addContent($pdf->graph->getCircle($x, $y, $radius, 0, 360, 'F', $dotStyle)); $pdf->page->addContent($pdf->graph->getCircle($x, $y, $radius, 0, 360, 'F', $dotStyle));
} }
} }
} }
function drawFrame(\Com\Tecnick\Pdf\Tcpdf $pdf, float $pageWidth, float $pageHeight): void function drawFrame(\Com\Tecnick\Pdf\Tcpdf $pdf, float $pageWidth, float $pageHeight): void
{ {
$outerMargin = 5.0; $outerMargin = 5.0;
$pdf->page->addContent( $pdf->page->addContent(
$pdf->graph->getRect( $pdf->graph->getRect(
$outerMargin, $outerMargin,
$outerMargin, $outerMargin,
$pageWidth - (2 * $outerMargin), $pageWidth - (2 * $outerMargin),
$pageHeight - (2 * $outerMargin), $pageHeight - (2 * $outerMargin),
'D', 'D',
['all' => getLineStyle(0.18, 'black')] ['all' => getLineStyle(0.18, 'black')]
) )
); );
} }
/** /**
@ -155,66 +155,66 @@ function drawFrame(\Com\Tecnick\Pdf\Tcpdf $pdf, float $pageWidth, float $pageHei
*/ */
function drawTitleBlock(\Com\Tecnick\Pdf\Tcpdf $pdf, array $tableBox): void function drawTitleBlock(\Com\Tecnick\Pdf\Tcpdf $pdf, array $tableBox): void
{ {
assertFontIsAvailable(); assertFontIsAvailable();
$font = $pdf->font->insert($pdf->pon, 'helvetica', '', 7.0, 0.0, 1.0); $font = $pdf->font->insert($pdf->pon, 'helvetica', '', 7.0, 0.0, 1.0);
$pdf->page->addContent($font['out']); $pdf->page->addContent($font['out']);
$pdf->page->addContent($pdf->color->getPdfColor('black')); $pdf->page->addContent($pdf->color->getPdfColor('black'));
$lineStyle = getLineStyle(0.16, 'black'); $lineStyle = getLineStyle(0.16, 'black');
$rowHeight = $tableBox['height'] / 4.0; $rowHeight = $tableBox['height'] / 4.0;
$labelWidth = 28.0; $labelWidth = 28.0;
$pdf->page->addContent( $pdf->page->addContent(
$pdf->graph->getRect($tableBox['x'], $tableBox['y'], $tableBox['width'], $tableBox['height'], 'D', [ $pdf->graph->getRect($tableBox['x'], $tableBox['y'], $tableBox['width'], $tableBox['height'], 'D', [
'all' => $lineStyle, 'all' => $lineStyle,
]) ])
); );
for ($row = 1; $row < 4; ++$row) { for ($row = 1; $row < 4; ++$row) {
$lineY = $tableBox['y'] + ($row * $rowHeight); $lineY = $tableBox['y'] + ($row * $rowHeight);
$pdf->page->addContent( $pdf->page->addContent(
$pdf->graph->getLine($tableBox['x'], $lineY, $tableBox['x'] + $tableBox['width'], $lineY, $lineStyle) $pdf->graph->getLine($tableBox['x'], $lineY, $tableBox['x'] + $tableBox['width'], $lineY, $lineStyle)
); );
} }
$pdf->page->addContent( $pdf->page->addContent(
$pdf->graph->getLine( $pdf->graph->getLine(
$tableBox['x'] + $labelWidth, $tableBox['x'] + $labelWidth,
$tableBox['y'], $tableBox['y'],
$tableBox['x'] + $labelWidth, $tableBox['x'] + $labelWidth,
$tableBox['y'] + $tableBox['height'], $tableBox['y'] + $tableBox['height'],
$lineStyle $lineStyle
) )
); );
$labels = ['Názov projektu', 'Autor', 'Dátum', 'Revízia']; $labels = ['Názov projektu', 'Autor', 'Dátum', 'Revízia'];
foreach ($labels as $index => $label) { foreach ($labels as $index => $label) {
$pdf->page->addContent( $pdf->page->addContent(
$pdf->getTextCell( $pdf->getTextCell(
$label, $label,
$tableBox['x'] + 2.0, $tableBox['x'] + 2.0,
$tableBox['y'] + ($index * $rowHeight) + 2.7, $tableBox['y'] + ($index * $rowHeight) + 2.7,
$labelWidth - 4.0, $labelWidth - 4.0,
4.0, 4.0,
valign: 'C', valign: 'C',
halign: 'L', halign: 'L',
drawcell: false drawcell: false
) )
); );
} }
} }
function assertFontIsAvailable(): void function assertFontIsAvailable(): void
{ {
$fontFile = K_PATH_FONTS . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'helvetica.json'; $fontFile = K_PATH_FONTS . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'helvetica.json';
if (! \is_readable($fontFile)) { if (! \is_readable($fontFile)) {
fail( fail(
'Missing font file helvetica.json. Generate fonts first: ' 'Missing font file helvetica.json. Generate fonts first: '
. 'cd vendor\\tecnickcom\\tc-lib-pdf-font\\util && composer install && cd .. && composer install ' . 'cd vendor\\tecnickcom\\tc-lib-pdf-font\\util && composer install && cd .. && composer install '
. '&& cd util && php bulk_convert.php' . '&& cd util && php bulk_convert.php'
); );
} }
} }
/** /**
@ -222,63 +222,63 @@ function assertFontIsAvailable(): void
*/ */
function buildPdf(\Com\Tecnick\Pdf\Tcpdf $pdf, array $params): string function buildPdf(\Com\Tecnick\Pdf\Tcpdf $pdf, array $params): string
{ {
$pageWidth = 210.0; $pageWidth = 210.0;
$pageHeight = 297.0; $pageHeight = 297.0;
$innerMargin = 10.0; $innerMargin = 10.0;
$tableBox = [ $tableBox = [
'width' => 80.0, 'width' => 80.0,
'height' => 40.0, 'height' => 40.0,
'x' => $pageWidth - $innerMargin - 80.0, 'x' => $pageWidth - $innerMargin - 80.0,
'y' => $pageHeight - $innerMargin - 40.0, 'y' => $pageHeight - $innerMargin - 40.0,
]; ];
$pdf->setCreator('pdfCreator'); $pdf->setCreator('pdfCreator');
$pdf->setAuthor(''); $pdf->setAuthor('');
$pdf->setSubject('Dotted technical drawing paper'); $pdf->setSubject('Dotted technical drawing paper');
$pdf->setTitle('Dotted technical drawing paper'); $pdf->setTitle('Dotted technical drawing paper');
$pdf->setKeywords('PDF dotted grid technical drawing floor plan'); $pdf->setKeywords('PDF dotted grid technical drawing floor plan');
$pdf->setPDFFilename('dotted.pdf'); $pdf->setPDFFilename('dotted.pdf');
$pdf->addPage(['format' => 'A4', 'orientation' => 'P']); $pdf->addPage(['format' => 'A4', 'orientation' => 'P']);
drawFrame($pdf, $pageWidth, $pageHeight); drawFrame($pdf, $pageWidth, $pageHeight);
drawDotGrid( drawDotGrid(
$pdf, $pdf,
$innerMargin, $innerMargin,
$innerMargin, $innerMargin,
$pageWidth - $innerMargin, $pageWidth - $innerMargin,
$pageHeight - $innerMargin, $pageHeight - $innerMargin,
$params['dot-size'], $params['dot-size'],
$params['space'], $params['space'],
$tableBox $tableBox
); );
drawTitleBlock($pdf, $tableBox); drawTitleBlock($pdf, $tableBox);
return $pdf->getOutPDFString(); return $pdf->getOutPDFString();
} }
function outputPdf(\Com\Tecnick\Pdf\Tcpdf $pdf, string $rawPdf): void function outputPdf(\Com\Tecnick\Pdf\Tcpdf $pdf, string $rawPdf): void
{ {
if (PHP_SAPI !== 'cli') { if (PHP_SAPI !== 'cli') {
if (\ob_get_length() !== false && \ob_get_length() > 0) { if (\ob_get_length() !== false && \ob_get_length() > 0) {
\ob_clean(); \ob_clean();
} }
$pdf->renderPDF($rawPdf); $pdf->renderPDF($rawPdf);
return; return;
} }
$outputDir = \dirname(__DIR__) . DIRECTORY_SEPARATOR . 'output'; $outputDir = \dirname(__DIR__) . DIRECTORY_SEPARATOR . 'output';
if (! \is_dir($outputDir) && ! \mkdir($outputDir, 0775, true) && ! \is_dir($outputDir)) { if (! \is_dir($outputDir) && ! \mkdir($outputDir, 0775, true) && ! \is_dir($outputDir)) {
fail('Unable to create output directory: ' . $outputDir); fail('Unable to create output directory: ' . $outputDir);
} }
$outputFile = $outputDir . DIRECTORY_SEPARATOR . 'dotted.pdf'; $outputFile = $outputDir . DIRECTORY_SEPARATOR . 'dotted.pdf';
if (\file_put_contents($outputFile, $rawPdf) === false) { if (\file_put_contents($outputFile, $rawPdf) === false) {
fail('Unable to write PDF file: ' . $outputFile); fail('Unable to write PDF file: ' . $outputFile);
} }
echo 'PDF generated: ' . $outputFile . PHP_EOL; echo 'PDF generated: ' . $outputFile . PHP_EOL;
} }
$params = readParams(); $params = readParams();

View File

@ -1,7 +1,8 @@
<?php <?php
namespace Igor\Pdfcreator; namespace Igor\Pdfcreator;
require __DIR__.'/../vendor/autoload.php';
require __DIR__ . '/../vendor/autoload.php';
\define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts')); \define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts'));
@ -16,12 +17,12 @@ $pdf->page->addContent($bfont['out']);
$html = '<h1>Hello, PDF!</h1><p>Generated with tc-lib-pdf.</p>'; $html = '<h1>Hello, PDF!</h1><p>Generated with tc-lib-pdf.</p>';
$pdf->addHTMLCell( $pdf->addHTMLCell(
html: $html, html: $html,
posx: 15, // mm from left page edge posx: 15, // mm from left page edge
posy: 20, // mm from top page edge posy: 20, // mm from top page edge
width: 180, // mm wide (0 = to right margin) width: 180, // mm wide (0 = to right margin)
); );
$rawpdf = $pdf->getOutPDFString(); $rawpdf = $pdf->getOutPDFString();
$pdf->renderPDF($rawpdf); $pdf->renderPDF($rawpdf);