Skip to content

v1.7.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 14:02
· 96 commits to main since this release

Added

  • PdfFontSource: parses a font once and shares it between documents (PdfDocument.AddFont and PdfDocumentWriter.AddFont overloads), so producing many documents with the same face does not parse and validate it each time.

  • PdfDocumentWriter packs dictionaries and arrays into compressed object streams (the catalog stays plain) unless the cross-reference format is a table. A tagged 250-page table went from 8.0 MB to 2.0 MB.

  • PdfDocument.AddPngImage: a minimal PNG reader for image XObjects. Plain non-interlaced PNGs (gray, RGB, palette, 1 to 16 bits) are passed through with their IDAT data unchanged (FlateDecode, /Predictor 15); interlaced PNGs and PNGs with alpha are decoded, alpha becoming a soft mask; tRNS becomes a colour-key mask where it can, and a matching iCCP profile becomes an ICCBased colour space. A png fuzz target covers it. See docs/content-creation.md.

  • PdfContentBuilder.DrawGlyphRun and PdfShapedGlyph: draw glyphs chosen by a shaping engine, by glyph index with advances, offsets and clusters, from an embedded font. Each cluster maps to text through the font's /ToUnicode map, or through /ActualText where one glyph cannot carry it (reordered or split clusters, a glyph reused for other text), so extraction returns the logical text.

  • Marked content on the content builder: BeginMarkedContent, BeginSpan, BeginArtifact, EndMarkedContent, MarkedContentDepth. Marked content and Save/Restore must nest.

  • PdfDocumentWriter: streaming creation. Each page is written when committed, so a 10,000-page document needs a few hundred bytes of memory per page. It brings PdfStreamPageBuilder, reserved forms for "page X of Y" (ReserveForm), links, bookmarks and named destinations, and a tagged structure tree (BeginStructureElement, PdfStructureElement, PdfStructureElementOptions, PdfStructureAttributes, MapRole) with marked-content ids, OBJR entries for links, a parent tree and /Tabs /S.

  • PdfDocumentWriter.AddPageLabelRange: page labels (ISO 32000-2 12.4.2) for streamed documents: decimal, roman and letter styles, prefixes and start numbers.

  • PdfDocumentWriter.BeginStructureElement(parent, type, options) and EndStructureElement(element): begin a structure element under an explicit parent and end any open element once its own children have ended, so a producer whose content continues on later pages (a table row split over pages) can keep several branches open at once. The earlier overloads are unchanged.

  • RecursiveAI.OnePdf.Layout, a new package that depends on RecursiveAI.OnePdf, RecursiveAI.OnePdf.Fonts and RecursiveAI.OneFont 1.1.0: a fluent layout layer. LayoutDocument.Compose takes nested delegates for pages, header, content and footer slots, decorators (padding, border, background, rounded corners, size limits, alignment, rotate/scale/translate), columns, rows, layers, lists, tables with spans and repeated header and footer rows, images, canvas, shaped rich text with page numbers and totals, links, bookmarks, tagging and right-to-left documents; IComponent for reuse; Save streams page by page, Save(stream, PdfSaveOptions) adds PDF/A and encryption, ToPdfDocument hands the result to the core API. The element objects stay public as the lower layer. See docs/layout.md and docs/migrating-from-questpdf.md.

  • layout fuzz target and a set of layout reference documents with page images (testdata/layout-references, tools/OnePdf.Layout.References).

Changed

  • Layout: shaping is done once per text and released after its last line; fonts are parsed once per face; Table.MeasuredRows is int? (null: every row when a column is automatic, otherwise the first 100 body rows). Producing documents is about twice as fast and allocates about half as much.
  • Layout: page totals ("page X of Y") are shaped and drawn with the embedded font, so documents with totals pass PDF/A-2b and PDF/UA-1 font checks. Row.Compact makes a row as wide as its items. Rotate and Scale throw PdfLayoutException when their child would need a page break, instead of dropping the content after it.