Pro edition
Converter — Deep Reference
At a glance
Section titled “At a glance”NextPDF\Pro\Converter exports an existing PDF to positioned HTML, simplified SVG, or plain text, and segments document content into typed structural regions. This deep reference enumerates the public API surface, the operator coverage matrix, the behavior contract, and the failure modes. It is a content-extraction exporter, not a pixel-perfect renderer.
Availability & licensing
Section titled “Availability & licensing”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 runtime capability flag gates this module. The converter classes resolve whenever the Pro package is installed and licensed.
Public API surface
Section titled “Public API surface”| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
PdfToHtmlConverter::convert() | string $pdfData, ?ConversionConfig $config = null | Exports every text-bearing page to one self-contained HTML5 document | ConversionResult (target Html5) | InvalidArgumentException when $pdfData is empty | Null config defaults to ConversionTarget::Html5 |
PdfToSvgConverter::convert() | string $pdfData, int $pageIndex = 0, ?ConversionConfig $config = null | Exports one page to a standalone SVG document | ConversionResult (target Svg; pageCount is always 1) | InvalidArgumentException when $pdfData is empty | Out-of-range $pageIndex yields a background-only SVG |
PdfToTextConverter::convert() | string $pdfData | Extracts decoded text from all pages, separated by a page-break marker | ConversionResult (target PlainText) | InvalidArgumentException when $pdfData is empty | Only this target decodes literal-string escapes |
PdfToTextConverter::extractPage() | string $pdfData, int $pageIndex | Extracts decoded text for one zero-based page | string | Does not throw; returns '' for a missing page or empty input | Unlike convert(), no empty-input guard |
DocumentSegmentationEngine::segment() | string $pdfData | Classifies page content into typed structural segments using spatial and font heuristics | NextPDF\Pro\Interop\V1\Segment\DocumentSegmentation | InvalidArgumentException when input is empty or the PDF structure cannot be parsed | Rule-based; performs no AI inference |
ConversionConfig::__construct() | ConversionTarget $target, bool $embedFonts = false, bool $embedImages = true, float $scaleFactor = 1.0, string $cssClass = 'pdf-page' | Immutable conversion settings | ConversionConfig | — | embedFonts and embedImages are accepted but not consumed in 3.1.0 |
ConversionResult::size() | — | Byte length of the produced output | int | — | Public readonly fields: output, target, pageCount, processingTimeMs |
ConversionResult::isValid() | — | Reports whether output is non-empty | bool | — | HTML and SVG document shells are never empty; check pageCount instead |
ConversionTarget | String-backed cases Html5, Svg, PlainText | Selects the export target | mimeType(): string, fileExtension(): string | — | fileExtension() maps to html, svg, txt |
Entry-point signatures:
public function convert(string $pdfData, ?ConversionConfig $config = null): ConversionResultpublic function convert( string $pdfData, int $pageIndex = 0, ?ConversionConfig $config = null,): ConversionResultpublic function convert(string $pdfData): ConversionResultpublic function extractPage(string $pdfData, int $pageIndex): stringpublic function segment(string $pdfData): DocumentSegmentationBehavior contract
Section titled “Behavior contract”Inputs are raw PDF bytes; outputs are a ConversionResult value object. The three export converters share a scanning model: locate stream/endstream boundaries, isolate BT/ET text blocks, and parse text-showing operators. They do not parse the cross-reference table and do not inflate compressed streams. DocumentSegmentationEngine differs: it resolves the trailer, catalog, and page tree, and inflates FlateDecode page content before classification.
Operator coverage:
| PDF operator | HTML | SVG | Text |
|---|---|---|---|
Tj (show string) | yes | yes | yes |
TJ (show array) | yes | yes | yes |
' (move + show) | no | no | yes |
Td / Tm (position) | yes | yes | n/a |
Tf (font size) | yes | yes | n/a |
re (rectangle) | no | yes | no |
m / l (line) | no | yes | no |
RG (RGB stroke) | no | yes (applied to rect/line stroke) | no |
| curves, shading, clipping, images | no | no | no |
- Positioning. Each
BT/ETblock resolves one position from its firstTdorTmmatch;Tmtakes precedence when both appear. The Y axis is flipped from PDF user space to top-left output space. Font size defaults to 12 pt when noTfis present. - Page geometry. HTML and SVG assume an A4 page box (595 x 842 pt) multiplied by
scaleFactor. The SVG root carries matchingviewBox, width, and height attributes over a white background rectangle. - Stroke color.
RGoperators are resolved positionally, so a stream that changes stroke color more than once colors each rectangle and line by the most recent preceding operator. Components are clamped to the 0..1 range before hex conversion. Rectangle fill is always black; thergfill operator is not evaluated. - String decoding. The text target decodes literal-string escapes per ISO 32000-2:2020 §7.3.4.2: named escapes, octal
\dddcodes masked to one byte, backslash line continuations, and lone-backslash removal. HTML and SVG targets emit the raw bytes between parentheses after HTML or XML escaping; they do not decode escapes. - Output assembly. The text target joins block texts with a space, and pages with
--- Page Break ---framed by blank lines. The HTML target emits one absolutely positioned<div>per text block inside a per-page container carrying the configured CSS class and adata-pageattribute. - Determinism. For identical input and configuration, the produced HTML, SVG, or text bytes are stable.
processingTimeMsis a wall-clock measurement and is excluded from the deterministic surface.
Edge cases & failure modes
Section titled “Edge cases & failure modes”- Empty input: every
convert()andsegment()entry point raisesInvalidArgumentException(“PDF data must not be empty”). No partial output is produced.extractPage()is the exception: it returns''without throwing. - Streams without
BT/ETare skipped by the HTML and text converters. A PDF containing only such streams yields a zeropageCountwith an empty text output or a pages-free HTML shell. isValid()only checks for non-empty output. HTML and SVG converters always emit a document shell, soisValid()staystrueeven when no text was found; usepageCount(HTML, text) to detect empty extraction.- FlateDecode content is not inflated by the three export converters. Compressed-only PDFs export little or no content through them.
segment()does inflate FlateDecode page streams. segment()bounds decompression by per-stream size, compression ratio, and a cumulative budget. A stream breaching a ceiling degrades to empty page content instead of exhausting memory; it does not throw.segment()raisesInvalidArgumentExceptionwhen the trailer, cross-reference offset, document catalog, or page tree cannot be resolved.- Page indexing differs per converter. HTML and text converters count only text-bearing streams; the SVG converter counts streams containing any recognized graphics or text operator. The same
$pageIndexmay therefore address different streams. TJnumeric kerning adjustments are discarded; array strings are concatenated without inter-glyph spacing.- Glyph-to-Unicode mapping is not applied. Text set in fonts with custom encodings exports as the raw byte sequence.
- Rotated text, non-text transforms, and column flow are approximated by first-match positioning and may not reproduce the original layout.
- No cryptographic operation occurs in this module, so FIPS mode has no module-specific behavior.
Conformance
Section titled “Conformance”NextPDF documents capability against the cited clauses. Support statements describe implemented behavior.
| Claim | Spec clause | Status |
|---|---|---|
Tj text-showing operator parsed | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
TJ array text-showing operator parsed | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
' move-and-show operator parsed (text target only) | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
| Literal-string escapes decoded (text target only) | ISO 32000-2:2020 §7.3.4.2 | Implemented; bytes returned as-is, charset interpretation is downstream |
re, m, l path construction recognized (SVG target) | ISO 32000-2:2020 §8.5.2 | Partial: subset without curves, closing, or painting-mode evaluation |
| Full text-state machine and page rendering | — | Not supported (out of scope) |
The converter parses text-showing operators to recover content; it does not implement the full text-state machine, so glyph positioning is approximate rather than spec-exact.
Development notes
Section titled “Development notes”- Parsing is linear in PDF byte length. Memory tracks the input plus the produced output string. The
performance_budgetfront matter is the per-invocation reference for a typical office document. - The converters parse untrusted PDF bytes with bounded
strpos/substrscanning. They execute no embedded JavaScript and follow no external references. Treat exported HTML as untrusted content and escape it for its destination. - HTML output is escaped with
htmlspecialchars(ENT_QUOTES, HTML5); SVG text is XML-escaped. The configuredcssClassis escaped before emission. - Config consumption:
scaleFactorapplies to the HTML and SVG targets;cssClassapplies to HTML only;embedFontsandembedImagesare reserved and currently unused; thetargetfield does not override a converter’s own output format. - The export converters ship since 1.9.0;
DocumentSegmentationEngineships since 2.1.0 and backs the Pro MCPsegment_documenttool and the Interop segmentation contract. PdfPageExtractorandPdfPageDatain the same namespace are internal to the segmentation engine and are not public API.
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.