Skip to content

feat(avalonia): paged rendering mode for print-like preview - #80

Merged
sonatique merged 2 commits into
mainfrom
feat/issue-79-paged-avalonia-preview
Jul 16, 2026
Merged

feat(avalonia): paged rendering mode for print-like preview#80
sonatique merged 2 commits into
mainfrom
feat/issue-79-paged-avalonia-preview

Conversation

@sonatique

Copy link
Copy Markdown
Owner

Closes #79.

What

Two additive pieces enabling a print-layout (PDF-like) preview for AdocNet.Avalonia consumers:

AdocNet.Layout — stop dropping <<<. LayoutBuilder.BuildBlock silently skipped PageBreakNode, so Layout consumers never saw explicit page breaks. New PageBreakLayout marker (mirrors ThematicBreakLayout), mapped with its SourceRange. AvaloniaRenderer continues to render it as nothing in the continuous preview — same effect as HTML's invisible page-break-after — so existing consumers are unaffected.

AdocNet.AvaloniaPagedAvaloniaRenderer + PageLayoutOptions. Wraps an AvaloniaRenderer (the IncrementalAvaloniaRenderer pattern), renders per-block controls, measures them at the page content width via Avalonia's Measure pass, and flows them greedily into fixed-size pages:

  • a block that doesn't fit starts the next page; an over-tall block gets a page of its own and clips at the page edge
  • PageBreakLayout forces a boundary (no blank leading page for a break at page start)
  • RenderPages() returns the individual page Borders; Render() stacks them ready for a scroller
  • PageLayoutOptions: geometry + paper chrome in DIPs, A4/Letter presets, and FromPdfPoints() (points × 96/72) so a preview can mirror a PdfRenderOptions page setup exactly
  • inline SourceRange stamps are preserved — click-to-source keeps working inside pages

Scope (stated plainly)

This is a print-like preview at block granularity, not PDF-identical pagination: on-screen text metrics differ from the PDF renderer's Helvetica/TTF metrics by design. The PDF cursor model in AdocNet.Converters.Pdf remains the authority for actual PDF page breaks.

Tests

  • LayoutBuilderTests: <<<PageBreakLayout (+ source range carried) — 53 layout tests pass
  • PagedAvaloniaRendererTests (headless): multi-page flow without block loss, forced break, leading-break suppression, over-tall block isolation + clipping, title on first page, points→DIPs conversion, degenerate-margin rejection — 72 headless tests pass
  • Full suite: 3,215 pass / 0 fail; solution Release build clean under TreatWarningsAsErrors

Motivation

Lets editor hosts (e.g. Ascolotl's planned page view) offer a paper-layout preview without a PDF-rasterizer dependency, keeping the pure-managed ethos.

Sylvain Fasel added 2 commits July 16, 2026 16:58
LayoutBuilder silently dropped <<< page breaks, so Layout consumers (the
Avalonia preview among them) could never see them. Add PageBreakLayout — a
marker block mirroring ThematicBreakLayout — and map the node in BuildBlock,
carrying its SourceRange. Continuous renderers may keep ignoring it (it has
no visual form, matching HTML's invisible page-break-after); paged renderers
use it to force a page boundary.
PagedAvaloniaRenderer wraps an AvaloniaRenderer (the IncrementalAvaloniaRenderer
pattern), renders per-block controls, measures them at the page content width
via Avalonia's Measure pass, and flows them greedily into fixed-size pages:
a block that doesn't fit starts the next page, an over-tall block gets a page
of its own and clips, and a PageBreakLayout (<<<) forces a boundary. Inline
SourceRange stamps are preserved, so source mapping keeps working in pages.

PageLayoutOptions carries page geometry and paper chrome in DIPs, with A4 and
Letter presets and FromPdfPoints() to mirror a PdfRenderOptions page setup
(points x 96/72) exactly.

Scope: a print-like preview at block granularity — not PDF-identical
pagination; on-screen metrics differ from the PDF renderer's font metrics by
design. Nine headless tests cover multi-page flow, forced/leading breaks,
over-tall blocks, title placement, unit conversion, and degenerate margins.
@sonatique
sonatique merged commit 8e47901 into main Jul 16, 2026
4 checks passed
sonatique pushed a commit that referenced this pull request Jul 16, 2026
Also documents the paged Avalonia preview (#79), which landed in PR #80 without
a CHANGELOG entry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: paged rendering mode for print-like preview (Avalonia)

1 participant