User-facing documentation for Papercraft XML templates and the X39.Solutions.PdfTemplate compatibility bridge.
| Previous: Developer integration appendix | Manual home | Next: Migration to Papercraft |
Renderer backends turn a generated Papercraft document into a concrete output format. The template parser, data binding and layout runtime live in Core; each backend decides how the generated display list is written to a stream.
Use this chapter when an application needs to choose between PDF, raster image, SVG or printer-command output. Lowered XML is also exposed as a render target for diagnostics, but it is not produced by a backend.
| Package | Backend id | Output | Common use |
|---|---|---|---|
X39.Solutions.Papercraft |
skiasharp |
PDF and PNG raster output | Normal application setup through the default facade. |
X39.Solutions.Papercraft.Rendering.SkiaSharp |
skiasharp |
application/pdf, image/png |
Explicit default renderer registration, PDF output and page-by-page PNG rendering. |
X39.Solutions.Papercraft.Rendering.PdfSharp |
pdfsharp |
application/pdf |
Alternative managed PDF backend when PDFsharp integration is preferred. |
X39.Solutions.Papercraft.Rendering.Svg |
svg |
image/svg+xml |
Dependency-free vector output, previews, inspection and tooling workflows. |
X39.Solutions.Papercraft.Rendering.EscPos |
escpos |
application/vnd.papercraft.escpos |
First-pass ESC/POS receipt-printer command streams. |
X39.Solutions.Papercraft.Core contains the backend contracts and runtime, but it does not register a backend by itself.
It can still write lowered XML through RenderTarget.LoweredXml, because that target stops before backend rendering.
Most applications should start with the facade package:
using Microsoft.Extensions.DependencyInjection;
using X39.Solutions.Papercraft;
services.AddPapercraft();
This registers Core, the built-in controls, the built-in transformers, Papercraft, the compatibility PapercraftRenderer and the SkiaSharp backend.
Use a PapercraftSession for the common PDF path:
var papercraft = serviceProvider.GetRequiredService<Papercraft>();
await using var session = papercraft.CreateSession();
await session.GeneratePdfAsync(output, reader, CultureInfo.CurrentUICulture);
Use RenderRasterPagesAsync(...) when each page should be written as PNG:
await session.RenderRasterPagesAsync(
reader,
new RasterPageRenderOutput(
PapercraftMediaTypes.ImagePng,
static (page, cancellationToken) =>
ValueTask.FromResult<Stream>(File.Create($"page-{page.PageNumber}.png"))),
CultureInfo.CurrentUICulture);
Applications running the SkiaSharp backend on Linux should reference the matching SkiaSharp native assets package.
PapercraftSession chooses a backend from the requested render target and registered backend capabilities.
When multiple registered backends can produce the same target, pass BackendId:
using X39.Solutions.Papercraft.Rendering.PdfSharp;
await session.RenderAsync(
reader,
new RenderOutput(PapercraftMediaTypes.ApplicationPdf, output),
CultureInfo.CurrentUICulture,
new PapercraftRenderOptions
{
BackendId = PdfSharpRenderBackend.RendererId,
});
Call ValidateAsync(...) before rendering when users can select an output format:
var validation = await session.ValidateAsync(
reader,
RenderTarget.FromMediaType("image/svg+xml"),
CultureInfo.CurrentUICulture);
if (!validation.IsSupported)
{
// Show validation.Diagnostics to the user.
}
Unsupported diagnostics block rendering. Degraded diagnostics are warnings unless
PapercraftRenderOptions.TreatDegradedAsUnsupported is enabled.
Use lowered XML output when you need to inspect the template after data binding, function evaluation, transformer expansion and style application, but before controls are created and before layout or backend rendering starts.
var loweredXml = await session.ReadLoweredXmlAsync(reader, CultureInfo.CurrentUICulture);
The lowered XML media type is PapercraftMediaTypes.ApplicationPapercraftLoweredXml
(application/vnd.papercraft.lowered+xml).
This target bypasses backend selection, so BackendId, backend capability validation, backend text services,
layout and display-list rendering do not apply.
Register the SVG backend when an application needs vector output without a native rendering dependency:
using X39.Solutions.Papercraft.Rendering.Svg;
services.AddPapercraftSvgRenderer();
Render with the SVG media type:
await session.RenderAsync(
reader,
new RenderOutput(RenderTarget.FromMediaType(SvgRenderBackend.MediaType), output),
CultureInfo.CurrentUICulture);
Multi-page documents are written as one SVG with pages stacked vertically. SVG output is useful for previews and inspection, but exact text metrics can differ from PDF backends.
Register the ESC/POS backend when the application wants receipt-printer command bytes instead of a PDF or image:
using X39.Solutions.Papercraft.Rendering.EscPos;
services.AddPapercraftEscPosRenderer(
new EscPosRenderOptions
{
CharactersPerLine = 42,
CutPaper = true,
});
Render to a caller-owned stream:
await using var output = new MemoryStream();
await session.RenderAsync(
reader,
new RenderOutput(EscPosRenderBackend.Target, output),
CultureInfo.CurrentUICulture,
new PapercraftRenderOptions
{
BackendId = "escpos",
});
byte[] commandBytes = output.ToArray();
The backend only writes ESC/POS command bytes. It does not discover printers, open USB or TCP connections, send spooler jobs, or perform any other transport work.
The first-pass backend is text-oriented. It emits printer initialization, text, line feeds, simple emphasis commands, simple horizontal rules, optional feed lines and optional cut commands. It reports unsupported diagnostics for images, clipping, transparency, link annotations, filled rectangles, non-horizontal lines and backend-specific drawing callbacks. It reports degraded diagnostics for features that cannot be preserved exactly by text-oriented ESC/POS output, such as colors, arbitrary fonts, absolute positioning, multipage layout and rotated text.
Receipt templates should therefore stay intentionally simple: use text, predictable line order and horizontal separators. For logos, QR codes, barcodes or exact visual layout, add semantic printer-command support before treating the backend as a general replacement for PDF output.
Custom renderers implement IPapercraftRenderBackend and advertise their output through RendererCapabilities.
They also expose an ITextService that Papercraft uses while generating documents for that backend.
Register them with Core when the application does not want the default facade:
services.AddPapercraftCore();
services.AddTransient<IPapercraftRenderBackend, MyRenderBackend>();
Backends should validate unsupported display-list features before rendering and write only to the supplied
RenderOutput.Stream. Device transport, storage and network delivery should live in the application layer.
| Previous: Developer integration appendix | Manual home | Next: Migration to Papercraft |