Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
BarcodeRendering
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
8
100.00% covered (success)
100.00%
1 / 1
 renderInto
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2
3declare(strict_types=1);
4
5namespace Phpdftk\Pdf\Writer;
6
7use Phpdftk\Barcode\BarcodeBitmap;
8use Phpdftk\Pdf\Core\Content\ContentStream;
9
10/**
11 * Internal helper that walks a {@see BarcodeBitmap} and emits the
12 * filled-rectangle operators that draw it into a `ContentStream`.
13 *
14 * Shared between `PdfDoc::createBarcode` (FormXObject), the
15 * `Pdf::addBarcode` flow adapter, and `Writer\Page::drawBarcode`
16 * positioned adapter so the visual output is identical.
17 *
18 * @internal
19 */
20final class BarcodeRendering
21{
22    /**
23     * Emit fills for every dark module of `$bitmap` into `$cs`, with
24     * `(0, 0)` at the bottom-left of the quiet zone. Coordinates are
25     * in user units (points for PDF).
26     *
27     * Caller is responsible for `saveGraphicsState` + transformations
28     * (translate / scale) that position the barcode on the page.
29     */
30    public static function renderInto(ContentStream $cs, BarcodeBitmap $bitmap): void
31    {
32        $mw = $bitmap->moduleWidth;
33        $rows = $bitmap->rows();
34        $cols = $bitmap->columns();
35        $quiet = $bitmap->quietZoneModules;
36        $cs->setFillColorRGB(0.0, 0.0, 0.0);
37
38        // 1D barcode = single row → all bars use the full bar height.
39        // 2D barcode = N rows × moduleWidth squares.
40        $is2D = $rows > 1;
41
42        for ($y = 0; $y < $rows; $y++) {
43            $row = $bitmap->modules[$y];
44            // For 2D, rows are drawn top-down; bottom-left of the
45            // top-row module is at totalHeight - moduleWidth.
46            $cellH = $is2D ? $mw : $bitmap->height;
47            $rowOriginY = $is2D
48                ? ($rows - 1 - $y) * $mw
49                : 0.0;
50
51            // Coalesce consecutive dark modules into one rectangle to
52            // minimise emitted ops.
53            $x = 0;
54            while ($x < $cols) {
55                if (!$row[$x]) {
56                    $x++;
57                    continue;
58                }
59                $runStart = $x;
60                while ($x < $cols && $row[$x]) {
61                    $x++;
62                }
63                $runLen = $x - $runStart;
64                $cs->rectangle(
65                    ($quiet + $runStart) * $mw,
66                    $rowOriginY,
67                    $runLen * $mw,
68                    $cellH,
69                );
70            }
71            $cs->fill();
72        }
73    }
74}