Skip to content
getnextpdf.com

Pro edition

Legal — Deep Reference

  • Generates sequential Bates number stamps as per-page PDF content stream fragments.
  • Three public types: BatesNumberConfig (immutable configuration), BatesNumberer (engine), BatesPosition (six-case position enum).
  • Each fragment is self-contained. Graphics state is saved and restored, so appending never disturbs existing page content.
  • Output is deterministic: a fragment is a pure function of configuration, stamp text, and page size.
  • The module raises no exceptions. Out-of-range inputs degrade by the documented fallback rules.

This capability ships in NextPDF Pro (nextpdf/pro) and activates with a Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.

No per-feature license flag exists. This is a Pro-edition capability.

Terminal window
composer require nextpdf/pro:^3
SymbolParametersDefault behaviorReturnsThrows or fails withNotes
BatesNumberConfig::__constructstring $prefix = '', string $suffix = '', int $startNumber = 1, int $padding = 5, BatesPosition $position = BatesPosition::BottomRight, float $fontSize = 9.0, string $fontFamily = 'Courier', float $opacity = 1.0, bool $useLayer = true, string $layerName = 'Bates Numbers', float $inset = 15.0Immutable appearance and numbering configurationBatesNumberConfigAll eleven properties are public and readonly.
BatesNumberConfig::formatNumberint $pageIndex (0-based)prefix + zero-padded (startNumber + pageIndex) + suffixstringA number wider than padding is not truncated.
BatesNumberConfig::getRangeint $pageCountFirst and last formatted stamps for the runarray{first: string, last: string}Assumes pageCount >= 1; a count of 0 formats page index -1.
BatesNumberer::__constructBatesNumberConfig $configBinds the configurationBatesNumbererThe class is final and readonly.
BatesNumberer::generateint $pageCount, array $pageSizes, string $prefix = '', int $startFrom = 1Static fast path with default appearancelist<string>Suffix, position, font, opacity, and layer stay at their defaults.
BatesNumberer::generateStreamsint $pageCount, list<array{width: float, height: float}> $pageSizesOne self-contained fragment per pagelist<string>Never throws; a missing size entry falls back to A4 portraitFragment count equals pageCount; extra size entries are ignored.
BatesNumberer::buildPageStreamstring $text, float $pageWidth, float $pageHeightBuilds one page’s stamp fragmentstringq/Q wrapped; stamp text escaped for literal-string syntax.
BatesNumberer::getConfigReturns the bound configurationBatesNumberConfig
BatesPositionenum cases BottomLeft, BottomCenter, BottomRight, TopLeft, TopCenter, TopRightString-backed position vocabularyBacking values are kebab-case (for example bottom-right).
BatesPosition::coordinatesfloat $pageWidth, float $pageHeight, float $textWidth, float $inset = 15.0X/Y for the stamp baseline in PDF-native spacearray{x: float, y: float}Origin is bottom-left; top rows place the baseline inset from the top edge.
public function __construct(
public string $prefix = '',
public string $suffix = '',
public int $startNumber = 1,
public int $padding = 5,
public BatesPosition $position = BatesPosition::BottomRight,
public float $fontSize = 9.0,
public string $fontFamily = 'Courier',
public float $opacity = 1.0,
public bool $useLayer = true,
public string $layerName = 'Bates Numbers',
public float $inset = 15.0,
) {}
public static function generate(
int $pageCount,
array $pageSizes,
string $prefix = '',
int $startFrom = 1,
): array
public function generateStreams(int $pageCount, array $pageSizes): array
public function buildPageStream(string $text, float $pageWidth, float $pageHeight): string
public function coordinates(
float $pageWidth,
float $pageHeight,
float $textWidth,
float $inset = 15.0,
): array

BatesNumberConfig::formatNumber computes startNumber + pageIndex, left-pads the number with zeros to padding digits, and wraps it with prefix and suffix. getRange returns the first and last formatted stamps for a page count. Use it to chain continuation numbering across productions.

Each fragment is, in order: a graphics-state save (q), a fill-color operator, an optional marked-content begin, a text block that positions and shows the stamp, an optional marked-content end, and a restore (Q). Coordinates and the font size are serialized with six decimal places, so identical inputs produce identical bytes. The stamp text escapes \, (, and ) before it enters the literal string.

The text block selects the fixed font resource name /BatesFont. The embedding page’s resource dictionary must map that name to a font matching the configured fontFamily, and the family must resolve in the font registry. Fragment generation itself never consults the registry.

BatesPosition::coordinates computes the stamp baseline in PDF-native space; the origin is bottom-left. Center and right placement subtract an estimated text width: byte length times 0.6 times the font size, a monospace approximation. Proportional fonts and multi-byte text shift that estimate. Left placement does not depend on it.

With useLayer enabled (the default), the fragment brackets the text between BDC and EMC marked-content operators. The marked-content name has the form /Lyr_<name>, derived from layerName with non-word characters replaced by underscores. The bracketing is fragment-level only: registering the corresponding optional content group in the document — the step that makes the layer toggleable in a viewer — belongs to the embedding writer.

An opacity below 1.0 is emitted as a lighter grayscale fill. A fully opaque stamp renders black.

The engine applies Bates numbering exactly as configured.

  • generateStreams never throws on a pageSizes mismatch. A missing entry falls back to A4 portrait, 595.276 by 841.890 points; extra entries are ignored.
  • Fragment count always equals pageCount.
  • A number wider than padding is not truncated; the stamp text simply grows.
  • getRange assumes pageCount >= 1. A count of 0 formats page index -1, that is startNumber - 1.
  • Opacity is a grayscale lightening, not ExtGState transparency; overlapped content beneath the stamp is not blended.
  • Stamp bytes other than \, (, and ) pass through unencoded. Encoding correctness for non-ASCII text depends on the bound font.
  • Bates marks are overlay content. They do not redact, remove, or encrypt anything on the page.
  • The module performs no cryptographic operations; FIPS mode does not change its behavior.
BehaviorReferenceStatus
Layer bracketing via BDC/EMC marked-content operatorsISO 32000-2:2020 §8.11.3.2Partial — the fragment emits the bracketing; optional content group registration is the embedding writer’s step

These rows record the specification the module is built against.

  • Fragments are pure string values. Test them by direct byte comparison; no document context is required.
  • buildPageStream is public and unit-testable in isolation: pass pre-formatted text and explicit page dimensions.
  • For continuation numbering across productions, seed startNumber from the previous run and record the getRange output in your production log.
  • Layer names are sanitized to word characters. Prefer ASCII layer names so the marked-content name stays readable in inspection tools.

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.