ValueObjects: domain primitives + units
At a glance
Section titled “At a glance”The ValueObjects module provides the immutable geometry primitives used across
the engine: PageSize, Dimension, Position, Margin, and the Unit enum.
Each one is a final readonly class. You can share an instance freely, and
each transformation returns a new instance.
Install
Section titled “Install”composer require nextpdf/core:^3Conceptual overview
Section titled “Conceptual overview”All four value objects are final readonly. They store float coordinates and
expose no mutators; transformation methods rebuild a new instance with named
arguments. You can cache them, pass them between documents, and share them
across workers without defensive copying.
PageSize stores width, height (in points; 1 pt = 1/72 inch), and a name.
Static factories cover the International Organization for Standardization
(ISO) 216 A series (A0–A6), the ISO 216 B series (B0–B5), and North
American sizes (Letter, Legal, Tabloid). The A/B dimensions follow the
trimmed paper-size series defined by ISO 216. fromName() resolves names
without case sensitivity and throws PageLayoutException for an unknown name.
landscape() and portrait() return the orientation variant, or self when
the page already has that orientation. toDimension() converts the page size
to a Dimension in points.
Dimension stores width, height, and a Unit. Factories
(fromMillimeters(), fromPoints(), fromInches()) create a dimension in the
selected unit. toPoints() and toMillimeters() convert units; toPoints()
returns self when the dimension is already in points. withWidth() and
withHeight() return a resized copy. Conversion uses exact factors: 72/25.4
points per millimeter, 72/2.54 per centimeter, and 72 per inch.
Position is a 2D point in Portable Document Format (PDF) user space
(x, y). origin() returns (0, 0). translate(dx, dy) returns an offset
copy. withX() / withY() return a copy with one axis replaced.
Margin holds top, right, bottom, and left. Factories are
uniform() (same value on all sides), symmetric(vertical, horizontal), and
zero().
Unit is a string-backed enum: Point (pt), Millimeter (mm),
Centimeter (cm), and Inch (in). toPointFactor() returns the
multiplier to points.
API surface
Section titled “API surface”| Symbol | Kind | Key members |
|---|---|---|
NextPDF\ValueObjects\PageSize | final readonly class | $width, $height, $name; factories A0–A6, B0–B5, Letter, Legal, Tabloid; fromName(), landscape(), portrait(), toDimension() |
NextPDF\ValueObjects\Dimension | final readonly class | $width, $height, $unit; fromMillimeters(), fromPoints(), fromInches(), toPoints(), toMillimeters(), withWidth(), withHeight() |
NextPDF\ValueObjects\Position | final readonly class | $x, $y; origin(), translate(), withX(), withY() |
NextPDF\ValueObjects\Margin | final readonly class | $top, $right, $bottom, $left; uniform(), symmetric(), zero() |
NextPDF\ValueObjects\Unit | string enum | Point, Millimeter, Centimeter, Inch; toPointFactor() |
Code sample — Quick start
Section titled “Code sample — Quick start”Use factories to construct geometry primitives.
<?php
declare(strict_types=1);
use NextPDF\ValueObjects\Margin;use NextPDF\ValueObjects\PageSize;use NextPDF\ValueObjects\Position;
$page = PageSize::A4(); // 595.276 x 841.890 pt$margin = Margin::uniform(18.0); // 18 pt all sides$origin = Position::origin()->translate(72.0, 72.0); // 1 inch in from cornerCode sample — Production
Section titled “Code sample — Production”Convert units, derive orientation, and pass margins into a configuration.
<?php
declare(strict_types=1);
use NextPDF\Core\Config;use NextPDF\ValueObjects\Dimension;use NextPDF\ValueObjects\Margin;use NextPDF\ValueObjects\PageSize;
// A label sized in millimeters, resolved to points for the engine.$label = Dimension::fromMillimeters(width: 100.0, height: 150.0)->toPoints();
$page = PageSize::A4()->landscape(); // swap to width >= height$margin = Margin::symmetric(vertical: 20.0, horizontal: 15.0);
$config = (new Config()) ->withPageSize($page) ->withMargins($margin);
// $label->width / $label->height are now in points for downstream layout.Edge cases & gotchas
Section titled “Edge cases & gotchas”- All dimensions use points unless you provide a
Dimensionwith an explicitUnit.Configmargins use points by default. PageSize::landscape()/portrait()return the same instance when the orientation already matches; no allocation occurs, and identity is preserved.PageSize::fromName()ignores case but resolves only the named factories. An unknown name throwsPageLayoutException, not a default size.Dimension::toPoints()returnsselfwhen the unit is alreadyPoint; do not assume a new object.- These objects hold raw
floatvalues and apply no range validation. They accept negative or zero dimensions at construction. The layout and writer layers enforce geometry validity, not these objects. - Floating-point conversion uses exact rational factors (72/25.4, 72/2.54); round only at the presentation boundary to keep reproducible output stable.
Performance
Section titled “Performance”Each value object is a flat readonly struct of floats. Construction and each
transformation are O(1) single allocations with no deep copy because there is
no nested mutable state. You can share an instance across documents without
extra cost. The default performance_budget for this reference page is
wall_ms: 1500, peak_mb: 64.
Security notes
Section titled “Security notes”These value objects perform no input/output (I/O), carry no user-supplied
strings beyond a page-size name, and hold no external resource handles, so they
present no direct attack surface. PageSize::fromName() rejects unknown input
with an exception instead of falling back silently, so a malformed configuration
fails explicitly rather than producing unexpected page geometry.
Conformance
Section titled “Conformance”| Spec | Clause | Topic |
|---|---|---|
| ISO 216:2007 | A / B series | Trimmed paper-size dimensions for the A* / B* factories (paraphrased; ISO prose not quoted, no chunk pinned) |
The A and B factory dimensions correspond to the ISO 216 trimmed sizes,
expressed in points. North American sizes (Letter, Legal, Tabloid) are de
facto industry sizes with no ISO basis. The ISO reference is paraphrased under
the site citation policy. No verbatim chunk is pinned.
See also
Section titled “See also”/modules/core/config/—ConfigusesPageSizeandMargin/modules/core/layout/— layout consumers for these primitives/modules/core/graphics/—Positionin drawing coordinate space/modules/core/contracts/—OrientationwithPageSize/modules/core/exception/—PageLayoutExceptionfromfromName()