Declarative Layout DOM
HPDFLayoutDOM builds reusable document components over THPDFLayoutElement, MeasureLayoutElement, PlaceLayoutElement, owned overflow fragments, and ImmediateFlushLayout
Document and section composition
Document := THPDFDOMDocument.Create;
Renderer := THPDFDOMRenderer.Create;
try
Section := Document.AddSection;
Section.PageWidth := 595.28;
Section.PageHeight := 841.89;
Section.Header := THPDFDOMText.Create('Quarterly report');
Section.Footer := THPDFDOMText.Create('Confidential');
Section.Body.Style.Padding := 12;
Section.Body.Style.Spacing := 8;
Section.Body.AddText(BodyText, 'Narrative');
PDF.OutputStream := Output;
PDF.ImmediateFlushLayout := True;
Statistics := Renderer.Render(Document, PDF);
finally
Renderer.Free;
Document.Free;
end;
THPDFDOMDocument owns its sections, every THPDFDOMSection owns its body, header, footer, and style, and every stack or container owns the components attached to it
THPDFDOMRenderer.Render starts and ends the target document, creates a fresh page for each new section, repeats section furniture on continuation pages, and returns page, placement, split, furniture, structure, marked-content, artifact, and maximum-continuation statistics
Set all THotPDF output, compression, conformance, layer, and immediate-flush options before calling Render
GenerateStructure defaults to True, so the renderer also builds a continuation-safe logical structure tree and uses THPDFDOMDocument.Language when the target has no language
Components
THPDFDOMTextwraps Unicode text, caches line boundaries by width and inherited text metrics, and splits through source character ranges without copying the source textTHPDFDOMSpacerreserves vertical space and can split across pagesTHPDFDOMStacklays out owned children vertically with inherited padding and spacingTHPDFDOMContaineradds a styled box around one owned child and forwards split continuationsTHPDFDOMTableresolves weighted columns, draws styled rows and cells, and repeats leading header rows on continuation pagesTHPDFDOMListcreates numbered or unnumbered list items with label and body componentsTHPDFDOMImageowns a cloned graphic, resolves explicit dimensions, and provides figure semantics and compression control
All components expose stable Name, Path, Style, Clone, Measure, Draw, and Split contracts plus semantic role, language, alternate text, replacement text, expansion text, and artifact overrides
Top-level body traversal is linear and does not clone components; text and table continuations retain range or row-slice metadata instead of copying the complete content tree
Style inheritance
THPDFDOMStyle resolves font name, size, styles, text colour, background, border, padding, spacing, and line height through its parent chain
A section style is the parent of its body and furniture, a stack or container style is the parent of its children, and table style flows through rows to cells
Only explicitly assigned values override the parent; Clear removes local assignments and the parent link, while Assign copies local assignments without copying ownership or ancestry
Parent chains deeper than 64 levels are rejected as cyclic or unbounded
Reusable component factories
THPDFDOMComponentFactory is an anonymous function that creates one caller-owned THPDFDOMComponent instance per invocation
Document.RegisterComponent('notice',
function: THPDFDOMComponent
begin
Result := THPDFDOMContainer.Create(
THPDFDOMText.Create('Reusable notice'));
end);
Section.Body.Add(Document.CreateComponent('notice'));
Factory names are case-insensitive and unique, each call must return a new component instance, and the receiving container takes ownership after Add
Use SetHeaderClone, SetFooterClone, or Clone when one declared component must be reused at several ownership sites
Repeating-header tables
Table := THPDFDOMTable.Create('Orders');
Table.AddColumn(1);
Table.AddColumn(3);
Header := Table.AddRow(18, True);
Header[0].Text := 'ID';
Header[1].Text := 'Description';
Row := Table.AddRow(22);
Row[0].Text := '1001';
Row[1].Text := 'Bounded streaming layout';
Section.Body.Add(Table);
Header rows must be contiguous and precede body rows, positive column weights divide the available width, and row heights are explicit positive values
When RepeatHeaders is true, a split requires room for all leading header rows and at least one body row, preventing header-only continuation pages
Pagination and failure boundaries
The renderer first remeasures each component against the remaining body rectangle, moves an unsplittable minimum fragment to a fresh page when possible, and delegates every valid split to PlaceLayoutElement
An element that cannot fit an empty body page raises an exception with its stable element path instead of silently discarding content
MaximumContinuationDepth defaults to 100,000 and bounds malformed components that repeatedly return a non-progressing continuation
Section page dimensions must be positive, margins and furniture gaps cannot be negative, and header plus footer geometry must leave a positive body rectangle
C++Builder
std::unique_ptr<THPDFDOMDocument> document(new THPDFDOMDocument());
THPDFDOMSection* section = document->AddSection();
section->Header = new THPDFDOMText(L"Report", "Header");
section->Body->AddText(L"Declarative content", "BodyText");
std::unique_ptr<THPDFDOMRenderer> renderer(new THPDFDOMRenderer());
THPDFDOMRenderStatistics statistics =
renderer->Render(document.get(), pdf.get());
The generated HPDFLayoutDOM.hpp exports the same document, style, component, table, section, renderer, and statistics surfaces