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

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

Related APIs