Advanced Text and Streaming Layout
HotPDF combines standards-aware paragraph composition, reusable document-layout planners, bounded shaped-run caching, side-effect-free measurement, owned overflow fragments, reusable page layers, file-backed page staging, page-break constraints, and bounded diagnostics
Unicode line breaking and paragraph composition
ParagraphIndex := PDF.CreateParagraph(0, jtLeft, 36, 36, 36, 36);
Hyphenator := THPDFDictionaryHyphenator.Create;
Hyphenator.AddWord('en-US', 'composition', [3, 5, 7], 25);
PDF.ConfigureParagraphTextLayout(ParagraphIndex, 'en-US', Hyphenator,
pcmOptimal);
HPDFComputeLineBreaks classifies Unicode scalars, preserves surrogate pairs, applies hard-break, combining-mark, emoji, punctuation, numeric, Hangul, and ideographic rules, and invokes the optional LineBreakTailoring hook for application-specific boundaries
THPDFDictionaryHyphenator stores caller-controlled language dictionaries and discretionary break penalties without changing the original text when a break is not selected
pcmOptimal selects HPDFComposeParagraph, which scores feasible lines with badness, penalties, fitness classes, consecutive-hyphen costs, and bounded predecessor pruning; pcmGreedy remains available for minimum-latency composition
Columns, notes, tables, floats, and lists
HPDFBalanceColumnsdistributes splittable flow items across bounded columns while applying widow, orphan, keep, and explicit column-break constraintsHPDFLayoutFootnotesanchors notes to reference pages and carries continuation state across spill pagesHPDFLayoutEndnotesstarts a note section on a caller-selected page while retaining every source reference pageHPDFResolveTableColumnsresolves minimum, preferred, maximum, and weighted widths, whileHPDFPaginateTablesplits permitted rows and repeats headersHPDFGetFloatIntervalssubtracts floated or anchored exclusion regions from each candidate line intervalHPDFLayoutListcomputes nested ordered and unordered markers and exposes matchingL,LI,Lbl, andLBodysemantic rolesHPDFPlanKeepGroupsrequests boundaries before heterogeneous keep groups would overflow the available region
Bounded shaped-run cache
THotPDF.ShapedRunCache reuses producer-side shaping results through hashed keys that include stable font-content identity, font size, the exact 64-bit feature set, script, language, paragraph direction, vertical mode, and text
Exact-run misses can fall through to context-bound non-whitespace slices, allowing unchanged words to be assembled from previous equal-length transformations without rerunning the complete shaping pipeline; length-changing substitutions remain full-run entries so cluster boundaries cannot be corrupted
The LRU cache is bounded by both MaxEntries and MaxBytes, shrinks immediately when either limit changes, and exposes full-run traffic, slice hits and misses, reused UTF-16 code units, evictions, slice and total entry counts, and retained bytes through Stats
Public layout types
- Line analysis uses
THPDFLineBreakClass,THPDFLineBreakKind,THPDFLineBreakOpportunity,THPDFLineBreakOpportunities,THPDFHyphenationPoint, andTHPDFHyphenationPoints - Optimal composition uses
THPDFParagraphComposeOptions,THPDFComposedLine,THPDFComposedLines, and the shared numeric bufferTHPDFSingleArray - Column flow uses
THPDFColumnBreakKind,THPDFKeepCondition,THPDFColumnLayoutOptions,THPDFFlowItemSpec,THPDFFlowItemSpecs,THPDFFlowPlacement, andTHPDFFlowPlacements - Note flow uses
THPDFFootnoteSpec,THPDFFootnoteSpecs,THPDFFootnotePlacement, andTHPDFFootnotePlacementsfor both footnote and endnote planners - Tables use
THPDFTableColumnSpec,THPDFTableColumnSpecs,THPDFTableRowSpec,THPDFTableRowSpecs,THPDFTableRowPlacement, andTHPDFTableRowPlacements - Floats use
THPDFFloatSide,THPDFFloatSpec,THPDFFloatSpecs,THPDFHorizontalInterval, andTHPDFHorizontalIntervals - Lists use
THPDFListItemSpec,THPDFListItemSpecs,THPDFListItemPlacement, andTHPDFListItemPlacements - Shaping cache records use
THPDFShapedRunKey,THPDFShapedRunValue,THPDFShapedRunCacheItem, andTHPDFShapedRunCacheStats
Reusable measure and draw contract
Derive from THPDFLayoutElement and implement side-effect-free Measure plus Draw; measurement receives only THPDFLayoutConstraints, so it has no page or document drawing surface
MeasureLayoutElement validates non-negative dimensions and computes Fits centrally from the same width and height constraints used for placement
THPDFLayoutElementKind lets ElementKind classify an implementation as lekParagraph, lekRow, lekContainer, or lekCustom, while ElementPath supplies stable diagnostic context
Split and overflow ownership
A splittable element returns THPDFLayoutSplit containing caller-owned placed and overflow elements; PlaceLayoutElement remeasures the placed head, draws it only when it fits, and transfers the tail into THPDFLayoutOverflow
THPDFLayoutOverflow records the source page and element path, owns the continuation by default, and transfers it explicitly through DetachElement
HPDFLayoutDOM composes these contracts into owned sections, reusable styled components, repeated page furniture, and repeating-header tables
Declarative page layers
Register callbacks with AddPageLayer before BeginDoc by selecting plkBackground, plkHeader, plkFooter, or plkForeground
Each callback runs exactly once per page in background, header, document-content, footer, and foreground order and is isolated by a graphics-state save and restore pair
RemovePageLayer removes one registration by identifier, while ClearPageLayers resets the reusable composition before document generation starts
THPDFPageLayerRegistration stores the stable identifier, layer kind, and object-method handler used internally by the document's ordered registration list
Immediate page flushing
Set ImmediateFlushLayout before BeginDoc for reports whose page count is not known in advance
When a page closes, its final compressed or uncompressed content stream moves from memory to an owned temporary-file stream while the PDF object remains available for normal cross-reference and resource finalization
ImmediateFlushedPageCount and ImmediateFlushedBytes report the amount of staged content, and temporary files are deleted when their owning streams are released
Paragraph pagination
ParagraphIndex := PDF.CreateParagraph(0, jtLeft, 36, 36, 36, 36);
PDF.ConfigureParagraphPagination(ParagraphIndex, True, 2, 2);
PDF.ConfigureParagraphDirection(ParagraphIndex, pdAuto);
PDF.BeginParagraph(ParagraphIndex);
PDF.CurrentParagraph.ShowUnicodeText(BodyText);
PDF.EndParagraph;
KeepWithNextmoves a paragraph when it would consume the final line that should remain for following contentMinOrphanLinesprevents too few opening lines from being left at the bottom of a pageMinWidowLinesadvances a break when too few closing lines would remain on the next page- Automatic continuation preserves the source page width, height, font, margins, and paragraph settings
- When
ParaAutoAddPageis false, overflow stops on the current page and produces anldkOverflowdiagnostic
Layout diagnostics
THPDFLayoutDiagnostic records the THPDFLayoutDiagnosticKind, source and related page indexes, affected rectangle, line count, element paths, optional source location, and an English reason for each retained decision
THPDFLayoutDiagnosticArray is returned by GetLayoutDiagnostics, while GetLayoutDiagnostic supports indexed access without allocating a copy
LayoutDiagnosticLimit bounds retained records and LayoutDiagnosticDroppedCount reports decisions discarded after that limit
LayoutDiagnosticOptions can enable bounded overlap detection, native vector overlays, caller-supplied source mapping, and synchronous live-preview notifications while leaving every sensitive or expensive option disabled by default
ldkAutomaticPageBreakreports an ordinary continuationldkKeepWithNext,ldkOrphanControl, andldkWidowControlidentify the constraint that moved a breakldkOverflowidentifies content stopped by disabled automatic paginationldkImmediateFlushidentifies a closed page moved to file-backed storageldkPageLayeridentifies a completed declarative page-layer passldkOverlapidentifies intersecting successfully placed elements
Paragraph direction
THPDFParagraphDirection provides pdAuto, pdLeftToRight, and pdRightToLeft
DetectParagraphDirection applies first-strong-character resolution across BMP and supplementary-plane RTL scripts, so neutral prefixes and secondary directional runs do not choose the wrong base direction
Use ConfigureParagraphDirection for a persistent paragraph setting or the THPDFPara.Direction property for the active paragraph
PDF/UA paragraph semantics
Root := PDF.AddStructureElement('Document', nil);
Paragraph := PDF.BeginTaggedParagraph(Root, 'en-US', 'Accessible text');
PDF.CurrentPage.TextOut(36, 72, 0, WideString('Accessible text'));
PDF.EndTaggedParagraph;
PDF.BeginPaginationArtifact(pasHeader);
PDF.CurrentPage.TextOut(36, 20, 0, WideString('Running header'));
PDF.EndPaginationArtifact;
BeginTaggedParagraph emits a standard /P marked-content sequence with an allocated MCID, page parent-tree wiring, and optional /Lang and /ActualText values
THPDFPaginationArtifactSubtype provides pasHeader, pasFooter, pasWatermark, and pasPageNumber, emitted as /Artifact content with /Type /Pagination and the matching standard subtype
Related APIs
- THotPDF.ConfigureParagraphTextLayout
- THotPDF.LineBreakTailoring
- THPDFPara.Language
- THPDFPara.Hyphenator
- THPDFPara.CompositionMode
- THotPDF.ConfigureParagraphPagination
- THotPDF.ConfigureParagraphDirection
- THotPDF.BeginTaggedParagraph
- THotPDF.BeginPaginationArtifact
- THotPDF.MeasureLayoutElement
- THotPDF.PlaceLayoutElement
- THotPDF.GetLayoutDiagnosticStatistics
- THotPDF.AddPageLayer
- THPDFPara