Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
16 / 16 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
1 / 1 |
| MultiColumnLayout | |
100.00% |
16 / 16 |
|
100.00% |
2 / 2 |
2 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| withRun | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Phpdftk\HtmlToPdf\Layout; |
| 6 | |
| 7 | use Phpdftk\Css\Value\Color; |
| 8 | |
| 9 | /** |
| 10 | * Resolved multi-column container layout — populated by |
| 11 | * {@see BlockLayout::layoutMultiColumn()} when a box's cascade declares |
| 12 | * `column-count` and/or `column-width` non-`auto`. |
| 13 | * |
| 14 | * The painter reads this to draw `column-rule` strokes between adjacent |
| 15 | * columns (CSS Multi-column 1 §3). The geometry is recorded relative to |
| 16 | * the container's content edge: column 0 starts at `box.geometry.x`, each |
| 17 | * subsequent column at `x + i * (columnWidth + columnGap)`. |
| 18 | */ |
| 19 | final readonly class MultiColumnLayout |
| 20 | { |
| 21 | public function __construct( |
| 22 | public int $columnCount, |
| 23 | public float $columnWidth, |
| 24 | public float $columnGap, |
| 25 | public float $ruleWidth, |
| 26 | public string $ruleStyle, |
| 27 | public ?Color $ruleColor, |
| 28 | /** |
| 29 | * CSS Multi-column 1 §3.3 — `column-fill: auto` fragmentation. When |
| 30 | * true the container's content was laid out in a SINGLE tall column |
| 31 | * (children keep their column-0 positions) and the painter must |
| 32 | * SLICE it into `columnCount` bands of `columnHeight`, translating |
| 33 | * band `i` to column `i`. `contentOffset` is band 0's origin as a |
| 34 | * distance BELOW the container's own content origin — relative |
| 35 | * because block layout can still move the container after this is |
| 36 | * recorded, and the children move with it. False (the default) = the |
| 37 | * classic balance path, where children were already moved to their |
| 38 | * columns and paint once. |
| 39 | */ |
| 40 | public bool $fragmented = false, |
| 41 | public float $columnHeight = 0.0, |
| 42 | public float $contentOffset = 0.0, |
| 43 | /** |
| 44 | * CSS Multi-column 2 §3 — `column-wrap: wrap`. When true the tall |
| 45 | * content is sliced into bands of `columnHeight` and wrapped into a |
| 46 | * `columnCount × rowCount` grid (filling a row of columns left→right, |
| 47 | * then the next row down), rather than a single row of `columnCount` |
| 48 | * columns. `contentHeight` is the tall content's total block size (to |
| 49 | * derive the band/row count); `rowGap` separates the rows. |
| 50 | */ |
| 51 | public bool $columnWrap = false, |
| 52 | public float $contentHeight = 0.0, |
| 53 | public float $rowGap = 0.0, |
| 54 | /** |
| 55 | * CSS Multi-column 1 §3.3 + §6.2 — the container's FRAGMENTED |
| 56 | * columnar runs, in document order. `$fragmented` above can only |
| 57 | * describe ONE tall column; a container carved up by |
| 58 | * `column-span: all` has several independent runs, each with its |
| 59 | * own column height, its own top and its own band count, so those |
| 60 | * are recorded here instead. Empty on every container that does |
| 61 | * not need slicing (the classic balance path) — the painter falls |
| 62 | * back to painting children once. |
| 63 | * |
| 64 | * @var list<ColumnRun> |
| 65 | */ |
| 66 | public array $runs = [], |
| 67 | ) {} |
| 68 | |
| 69 | /** |
| 70 | * Append one fragmented columnar run. `MultiColumnLayout` is readonly |
| 71 | * and is built before the runs are known, so layout rebuilds it as |
| 72 | * each run resolves. |
| 73 | */ |
| 74 | public function withRun(ColumnRun $run): self |
| 75 | { |
| 76 | return new self( |
| 77 | $this->columnCount, |
| 78 | $this->columnWidth, |
| 79 | $this->columnGap, |
| 80 | $this->ruleWidth, |
| 81 | $this->ruleStyle, |
| 82 | $this->ruleColor, |
| 83 | $this->fragmented, |
| 84 | $this->columnHeight, |
| 85 | $this->contentOffset, |
| 86 | $this->columnWrap, |
| 87 | $this->contentHeight, |
| 88 | $this->rowGap, |
| 89 | [...$this->runs, $run], |
| 90 | ); |
| 91 | } |
| 92 | } |