withDeterministic(new DeterministicSettings( new DateTimeImmutable('2026-07-24T00:00:00Z'), \str_repeat('8', 32), )); $doc = Document::createStandalone($config); $doc->setTitle('GS1 Barcode Sample Sheet'); $doc->setPrintFooter(false); $doc->addPage(); $doc->setFont('helvetica', 'B', 18); $doc->setXY(24, 20); $doc->cell(0, 12, 'GS1 Barcode Sample Sheet', newLine: true); $caption = static function ( Document $document, float $x, float $y, string $cellId, string $symbologyAndVersion, string $ecc, string $payload, ): void { $publicCellId = \preg_replace('/^w[0-9]+-/', '', $cellId) ?? $cellId; $document->setFont('helvetica', '', 6.5); foreach (["CELL {$publicCellId}:", $symbologyAndVersion, "ECC={$ecc}", "payload={$payload}"] as $line => $text) { $document->setXY($x, $y + ($line * 9)); $document->cell(170, 9, $text); } }; $layoutCaption = static function (Document $document, array $layout): void { $document->setFont('helvetica', '', 6.5); foreach ($layout['lines'] as $line => $text) { $document->setXY($layout['captionX'], $layout['captionY'] + $line * $layout['lineHeight']); $document->cell($layout['cellWidth'], $layout['lineHeight'], $text); } }; $qrPairs = []; foreach (BarcodeSheetLayout::gs1QrPairs() as $pair) { $qrPairs[$pair['id']] = $pair; } $capabilities = CapabilityRegistry::getInstance(); $dataBarAvailable = $capabilities->has('barcode.gs1databar') && $capabilities->get('barcode.gs1databar')->isAvailable() && \class_exists('NextPDF\\Pro\\Barcode\\Gs1DataBar\\Gs1DataBarEncoder'); $gs1Available = $capabilities->has('barcode.gs1') && $capabilities->get('barcode.gs1')->isAvailable() && \class_exists('NextPDF\\Pro\\Barcode\\Gs1\\Gs1DataParser'); if ($dataBarAvailable) { $stackedOmnidirectional = new readonly class implements Barcode2DSymbolOptionsInterface { public function symbology(): Barcode2DType { return Barcode2DType::GS1DataBar; } public function toEncoderOptions(): array { return ['variant' => 'STACKED_OMNIDIRECTIONAL']; } }; $caption($doc, 24, 55, 'w1-databar-stacked-omni', 'GS1 DataBar / version=Stacked Omni', 'check', '09501101530003'); $doc->write2DBarcodeWithOptions( '09501101530003', Barcode2DType::GS1DataBar, symbolOptions: $stackedOmnidirectional, x: 75, y: 100, w: 50, h: 95, ); } $gs1Payload = '(01)09501101530003(17)260101'; if ($gs1Available) { $caption($doc, 214, 55, 'w1-gs1-datamatrix', 'GS1 DataMatrix / version=auto', 'ECC200', '(01)09501101530003(17)260101'); $doc->write2DBarcode( $gs1Payload, Barcode2DType::DataMatrix, x: 250, y: 100, w: 100, h: 100, gs1: true, ); $gs1Qr = $qrPairs['gs1-qr']; $layoutCaption($doc, $gs1Qr); $doc->write2DBarcode( $gs1Qr['payload'], Barcode2DType::QRCode, x: $gs1Qr['symbolX'], y: $gs1Qr['symbolY'], w: $gs1Qr['symbolSize'], h: $gs1Qr['symbolSize'], gs1: true, ); } $renderComponent = static function ( Document $document, Barcode2DData $symbol, string $payload, float $x, float $pdfY, float $width, float $height, string $profile, ): void { $operators = (new BarcodeRenderer())->render2DInBox( data: $symbol, x: $x, y: $pdfY, w: $width, h: $height, fallbackModuleSize: 1.0, ); $components = (new CompositePlacementEmitter())->prepare([ new BarcodeComponentDrawSpec( kind: 'main', contentStream: $operators, bounds: new PlacementBounds($x, $pdfY, $width, $height), ), ]); $context = $document->createCommitContext( type: $symbol->type, rawPayload: $payload, rawRequest: BarcodeRawRequest::single($payload), canonicalPayload: CanonicalBarcodePayload::single($symbol->data), appearance: new BarcodeAppearance(), x: $x, y: $pdfY, width: $width, height: $height, optionsSnapshot: ['profile' => $profile], ); $document->commitComponents($components, $context); }; $ccAAvailable = $capabilities->has('barcode.gs1-composite-cc-a') && $capabilities->get('barcode.gs1-composite-cc-a')->isAvailable() && \class_exists(CompositeComponentA::class); $ccBAvailable = $capabilities->has('barcode.gs1-composite-cc-b') && $capabilities->get('barcode.gs1-composite-cc-b')->isAvailable() && \class_exists(CompositeComponentB::class); $ccCAvailable = $capabilities->has('barcode.gs1-composite-cc-c') && $capabilities->get('barcode.gs1-composite-cc-c')->isAvailable() && \class_exists(CompositeComponentC::class); if ($ccAAvailable) { $payload = '(21)1234-abcd'; $caption($doc, 24, 275, 'w1-gs1-composite-cc-a', 'GS1 Composite / version=CC-A', 'variant-defined', '(21)1234-abcd'); $renderComponent( $doc, (new CompositeComponentA())->encode($payload, [ 'carrierType' => CompositeCarrierType::EAN_13, 'dataFormat' => CompositeDataFormat::ParenthesizedElementString, ]), $payload, 55, 500, 100, 80, 'CC-A', ); } if ($ccBAvailable) { $payload = '(10)abcdefghijklmnopqrst'; $caption($doc, 214, 275, 'w1-gs1-composite-cc-b', 'GS1 Composite / version=CC-B', 'variant-defined', '(10)abcdefghijklmnopqrst'); $renderComponent( $doc, (new CompositeComponentB())->encode($payload, [ 'carrierType' => CompositeCarrierType::UPC_A, 'dataFormat' => CompositeDataFormat::ParenthesizedElementString, ]), $payload, 245, 500, 100, 80, 'CC-B', ); } if ($ccCAvailable) { $payload = '(10)ABCD123456(410)3898765432108'; $caption($doc, 404, 275, 'w1-gs1-composite-cc-c', 'GS1 Composite / version=CC-C', 'variant-defined', '(10)ABCD123456(410)3898765432108'); $renderComponent( $doc, (new CompositeComponentC())->encode($payload, [ 'carrierType' => CompositeCarrierType::GS1_128, 'dataFormat' => CompositeDataFormat::ParenthesizedElementString, 'columns' => 5, 'logicalMatrix' => true, ]), $payload, 435, 500, 100, 80, 'CC-C', ); } if ($dataBarAvailable) { $dataBarOptions = static fn(string $variant, ?int $segmentsPerRow = null): Barcode2DSymbolOptionsInterface => new readonly class($variant, $segmentsPerRow) implements Barcode2DSymbolOptionsInterface { public function __construct(private string $variant, private ?int $segmentsPerRow) { } public function symbology(): Barcode2DType { return Barcode2DType::GS1DataBar; } public function toEncoderOptions(): array { $options = ['variant' => $this->variant]; if ($this->segmentsPerRow !== null) { $options['segmentsPerRow'] = $this->segmentsPerRow; } return $options; } }; $gtin = '09501101530003'; $expandedPayload = '010950110153000310ABC123'; $dataBarCells = [ ['w2-databar-omni', 'Omni', 'OMNIDIRECTIONAL', $gtin, 24, 35, 430, 480], ['w2-databar-truncated', 'Truncated', 'TRUNCATED', $gtin, 214, 225, 430, 480], ['w2-databar-stacked', 'Stacked', 'STACKED', $gtin, 404, 415, 430, 480], ['w2-databar-limited', 'Limited', 'LIMITED', $gtin, 24, 35, 570, 620], ['w2-databar-expanded', 'Expanded', 'EXPANDED', $expandedPayload, 214, 225, 570, 620], ['w2-databar-expanded-stacked', 'Exp Stacked', 'EXPANDED_STACKED', $expandedPayload, 404, 415, 570, 620], ]; foreach ($dataBarCells as [$cellId, $label, $variant, $payload, $captionX, $symbolX, $captionY, $symbolY]) { $captionPayload = \str_starts_with($variant, 'EXPANDED') ? '(01)09501101530003(10)ABC123' : $payload; $caption($doc, $captionX, $captionY, $cellId, "GS1 DataBar / version={$label}", 'check', $captionPayload); $doc->write2DBarcodeWithOptions( $payload, Barcode2DType::GS1DataBar, symbolOptions: $dataBarOptions( $variant, $variant === 'EXPANDED_STACKED' ? 6 : null, ), x: $symbolX, y: $symbolY, w: 140, h: 65, ); } } if ($gs1Available) { $caption($doc, 24, 710, 'w2-gs1-128-profile', 'GS1-128 / version=auto', 'check', $gs1Payload); $doc->write1DBarcode( $gs1Payload, BarcodeType::GS1_128, x: 35, y: 755, w: 140, h: 50, ); $aiLayerQr = $qrPairs['gs1-ai-layer']; $layoutCaption($doc, $aiLayerQr); $doc->write2DBarcode( $aiLayerQr['payload'], Barcode2DType::QRCode, x: $aiLayerQr['symbolX'], y: $aiLayerQr['symbolY'], w: $aiLayerQr['symbolSize'], h: $aiLayerQr['symbolSize'], gs1: true, ); } $output = \getenv('NEXTPDF_SAMPLE_OUTPUT') ?: __DIR__ . '/../output/44-barcode-gs1.pdf'; $doc->save($output); if (!$dataBarAvailable) { echo "SKIP: w1-databar-stacked-omni requires nextpdf/pro\n"; echo "SKIP: w2-databar mode-completeness cells require nextpdf/pro\n"; } if (!$gs1Available) { echo "SKIP: w1-gs1-datamatrix and w1-gs1-qr require nextpdf/pro\n"; echo "SKIP: w2-gs1 profile cells require nextpdf/pro\n"; } if (!$ccAAvailable) { echo "SKIP: w1-gs1-composite-cc-a requires nextpdf/pro\n"; } if (!$ccBAvailable) { echo "SKIP: w1-gs1-composite-cc-b requires nextpdf/pro\n"; } if (!$ccCAvailable) { echo "SKIP: w1-gs1-composite-cc-c requires nextpdf/pro\n"; } echo "Created: {$output}\n";