Enterprise edition
Branding — Deep Reference
At a glance
Section titled “At a glance”This page is the deep reference for the NextPDF\Enterprise\Branding module. The module marks evaluation output and leaves paid output untouched. A license-resolved BrandingMode selects a strategy; BrandingApplicator applies the resolved strategy to rendered PDF bytes. Under a paid license the transform is the identity: output is byte-for-byte unchanged, with no code change required. For the evaluation workflow, read the Branding capability page first.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
The subsystem carries the dedicated enterprise.branding capability code because it governs evaluation behavior across all editions. The branding mode is resolved from the signed license envelope at runtime; no application flag selects it. A paid license resolves the mode to None and never produces branded output. There is no production build to switch.
Public API surface
Section titled “Public API surface”| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
BrandingMode | — | None ('none'): no modification | — | — | String-backed enum; EvaluationWatermark ('evaluation') activates evaluation branding. |
BrandingStrategy | — | Contract consumed by integration points | — | — | Interface; callers never branch on BrandingMode directly. |
BrandingStrategy::isActive | — | false for null strategy, true for evaluation strategy | bool | — | false means every other method returns identity values. |
BrandingStrategy::buildPageWatermark | float $pageWidth, float $pageHeight (points) | Empty string when inactive; diagonal watermark operators when active | string | — | Stream assumes a /helvetica font resource on the page. |
BrandingStrategy::decorateProducer | string $producer | Identity when inactive; appends the evaluation suffix when active | string | — | Default suffix: [EVALUATION]. |
BrandingStrategy::decorateSubject | string $subject | Identity when inactive; prepends the evaluation prefix when active | string | — | Empty subject yields the trimmed marker. |
BrandingStrategyFactory::create | BrandingMode $mode, ?EvaluationBrandingConfig $config = null | Maps None to NullBrandingStrategy, EvaluationWatermark to EvaluationBrandingStrategy | BrandingStrategy | — | Static; null config uses the defaults. |
EvaluationBrandingConfig::__construct | Six optional named parameters (text, suffix, prefix, size, gray, angle) | Defaults: 48 pt, gray 0.85, 45 degrees | Instance | InvalidArgumentException on empty text, non-positive font size, or gray outside 0.0–1.0 | final readonly; immutable. |
EvaluationBrandingStrategy | Optional EvaluationBrandingConfig | Applies watermark and metadata decoration | — | — | final readonly; implements BrandingStrategy. |
NullBrandingStrategy | — | Identity on every method | — | — | Selected under a paid license. |
BrandingApplicator::apply | string $pdfBytes, BrandingStrategy $strategy | Inactive strategy: input returned byte-for-byte; active: one incremental update appended | string | BrandingApplicationException when active branding cannot be applied safely | Pure, deterministic byte transform. |
BrandingApplicationException | — | Terminal, fail-closed failure signal | — | — | Carries SPEC_CODE (SPEC-BRANDING-UNAPPLICABLE); factory unsupportedStructure(). |
Entry-point signatures
Section titled “Entry-point signatures”enum BrandingMode: string{ case None = 'none'; case EvaluationWatermark = 'evaluation';}public static function create( BrandingMode $mode, ?EvaluationBrandingConfig $config = null,): BrandingStrategypublic function __construct( public string $watermarkText = 'EVALUATION COPY — Not for Production Use', public string $producerSuffix = ' [EVALUATION]', public string $subjectPrefix = '[EVALUATION] ', public float $watermarkFontSize = 48.0, public float $watermarkGray = 0.85, public float $watermarkAngle = 45.0,)public function apply(string $pdfBytes, BrandingStrategy $strategy): stringBehavior contract
Section titled “Behavior contract”Mode and strategy resolution. The license state — not application code — selects the BrandingMode. BrandingStrategyFactory::create maps None to NullBrandingStrategy and EvaluationWatermark to EvaluationBrandingStrategy. Integration points consume the BrandingStrategy interface and never inspect the mode directly, so branding logic stays centralized. Under a paid license the null strategy is selected and output is identical to output produced with no branding subsystem at all.
Watermark generation. buildPageWatermark emits PDF content-stream operators for one page: an isolated graphics state (q/Q), the standard-14 Helvetica font via the /helvetica resource name, fill text rendering mode, and a rotation matrix that places the text diagonally through the page center. The default style is 48 pt text at gray level 0.85, rotated 45 degrees. Centering approximates text width by glyph count — grapheme clusters when intl is loaded, Unicode code points via mbstring otherwise, byte length as the final fallback. No per-glyph advance widths are consulted by design. The watermark text is escaped as a PDF literal string per ISO 32000-2:2020 §7.3.4.2 (backslash and parentheses).
Metadata decoration. decorateProducer appends the producer suffix to the /Producer value. decorateSubject prepends the subject prefix to the /Subject value; an empty subject yields the trimmed marker, so a document without subject metadata is still marked.
Byte application. BrandingApplicator::apply is the terminal consumer of the branding control. With an inactive strategy it returns the input byte-for-byte. With an active strategy it appends a single incremental update in the shape defined by ISO 32000-2:2020 §7.5.6: the original bytes stay intact, and the appended body holds a decorated Info object (reusing the existing object number), one watermark content stream plus one updated page object per page, and a new cross-reference stream (/Type /XRef, /W [1 4 2]) whose /Prev points back to the prior startxref. The transform is pure and deterministic for a given input and configuration.
Fail-closed contract. When the strategy is active, the input must be brandable: a %PDF- header, no /Encrypt entry, no object streams (/ObjStm), a cross-reference-stream tail, and a /helvetica font resource resolvable from every page. Any violation raises BrandingApplicationException instead of returning unbranded bytes. Callers must treat the exception as terminal and must not commit the original, unmarked bytes.
Edge cases & failure modes
Section titled “Edge cases & failure modes”- Branded output means the license state is evaluation-style. That reflects license state, not a defect.
- The watermark is centered and diagonal by design. It is not tunable for production use; a paid license removes it entirely.
EvaluationBrandingConfigrejects empty watermark text, a non-positive font size, and a gray level outside 0.0–1.0 withInvalidArgumentException.- An active strategy that produces no Producer, Subject, or watermark change is refused with
BrandingApplicationExceptionrather than emitting bytes that look paid. - A page without a usable
/MediaBox(absent or inherited) is watermarked at the ISO 216 A4 default of 595.276 × 841.890 points. /Contentsin single-reference and array forms are both supported; the watermark reference is appended last so it draws on top. A page with no/Contentsreceives one.- Info string values round-trip in their original representation: hexadecimal strings (UTF-16BE) stay hexadecimal, literal strings stay literal. An absent key is appended, hex-encoded when the value contains non-ASCII characters.
- Encrypted documents are refused: rewriting string objects under
/Encryptwould require the document encryption key. - Failures carry the stable code
SPEC-BRANDING-UNAPPLICABLE(BrandingApplicationException::SPEC_CODE) so consuming pipelines can dead-letter and audit unbrandable output. - The module performs no cryptographic operations. License-envelope signature verification belongs to the licensing subsystem; see the Licensing deep reference.
Conformance
Section titled “Conformance”| Claim | Standard | Clause |
|---|---|---|
| Incremental updates append changes to the end of the file and leave the original contents intact. | ISO 32000-2 | §7.5.6 |
The update’s cross-reference section covers only changed objects, and the added trailer carries a Prev entry locating the previous cross-reference section. | ISO 32000-2 | §7.5.6 |
| Literal strings are written in parentheses; unbalanced parentheses and the reverse solidus require escape treatment. | ISO 32000-2 | §7.3.4.2 |
All clauses are paraphrased; NextPDF does not reproduce normative text. The applicator writes incremental updates in the cited ISO 32000-2 shape as a capability statement. This page describes runtime behavior only. It makes no warranty, no statement about eligibility or legal effect, and does not constitute legal advice; the terms of an evaluation or subscription are defined solely by the license agreement.
Development notes
Section titled “Development notes”BrandingMode,BrandingStrategy, both strategies, and the config carry@since 3.0.0;BrandingApplicatorandBrandingApplicationExceptioncarry@since 3.1.0.- The subsystem makes no network calls. The applicator reads only the structural fields it rewrites: the Info dictionary strings, page dictionaries, and the cross-reference tail.
- The license envelope is a signed artifact whose issuer signature the runtime verifies. License provisioning, renewal, and secure storage are the operator’s responsibility.
- All concrete types are
final; the strategies and the config are alsoreadonly. Construct a new config instance to change watermark style. BrandingStrategy::isActive()returningfalseguarantees identity values from every other method; callers may short-circuit on it for performance.- The watermark stream references the
/helveticaresource name. Core registers this resource for its own branding; an integration that disables Core branding must ensure the resource exists. - The applicator computes no digest; the caller re-digests the branded bytes before committing them.
- Internal mechanism detail stays in the source repository’s internal documentation and is out of scope for this manual.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.
See also
Section titled “See also”- Branding — capability page for the evaluation-branding subsystem.
- Trial and Evaluation Branding — the end-to-end evaluation story.
- Licensing — Deep Reference
- Enterprise overview