mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-26 17:41:06 -04:00
Slice 2 of the nest report plan: pagination, overflow and dense-label
coverage on top of the Slice 1 one-plate library.
- NestPdfWriter: general multi-plate pagination. Summary/plate tables
continue across pages with repeated (HeadingFormat) header rows; notes
flow as an ordinary paragraph instead of a bounded cell; page headers
are wrapped and sized into the top margin; drawing areas are located
per page via DocumentRenderer.GetRenderInfoFromPage.
- ReportText: lossless pre-wrapping (MigraDoc clips an over-tall row and
lets an unbroken token overflow a narrow cell without warning), capped
table-cell line counts, plate-range compression ("1-2, 4"), and
A/B/.../AA map-grid row names.
- NestReportDiagram: label placement centers each part ID on its
PolyLabel pole (matching PlateView's LayoutPart), computed on a
placement-independent quantized copy so identical parts share one
label position. Parts whose ID cannot fit legibly at overview scale
get a lettered/numbered map grid and a zoomed, framed detail page per
crowded cell; the writer fails with plate/part/ID when even that
cannot place a label, or a plate would need more than 24 detail views.
- Tests: NestPdfLayoutTests (multi-plate totals/ranges/same-named
references, table continuation with no lost rows, long name/notes
wrapping without column overflow, mm units in all four quadrants,
dense-label detail views with hole avoidance, save/reload of the
tabbed/lead-in fixture with stale tab flags, invalid later-plate data,
late write failures against an existing destination, source
unchanged on success/failure), ReportPdf test helper (page/word/
content-stream extraction).
- docs/nest-reports.md: replace the Slice 1 one-plate limits section
with the general pagination/dense-label contract and the process-wide
PDFsharp/MigraDoc render lock.
Verification: Reporting filter 70/70; full OpenNest.Tests 2524
passed/21 skipped/0 failed; Engine 351/351; IO 77/77;
EnableWindowsTargeting=true full-solution build 0 errors; scoped
dotnet format --verify-no-changes exit 0. Preview PDFs rendered and
visually inspected (evidence: /home/aj/extracted/2026-09-29/opennest-report-slice2/).
Windows runtime, the desktop adapter and packaged-app font deployment
remain unverified (Slice 3).
135 lines
7.7 KiB
Markdown
135 lines
7.7 KiB
Markdown
# Nest report PDF library
|
|
|
|
The first delivery is a bounded, cross-platform library slice, not yet a desktop
|
|
menu command or a general report layout engine. Capture a stable `Nest` on its
|
|
owning thread, then render only the detached snapshot:
|
|
|
|
```csharp
|
|
var snapshot = NestReportBuilder.Capture(nest, DateTimeOffset.Now);
|
|
NestPdfWriter.Write(snapshot, destinationPath);
|
|
```
|
|
|
|
Reporting does not select a post, generate CNC, refresh drawing quantities, change
|
|
the selected plate, or certify that a layout passed geometry/pre-post checks.
|
|
|
|
## Snapshot contract
|
|
|
|
- IDs (`R001`, ...) are local to the report. Visit non-cutoff placements in plate
|
|
and part order, then append unseen demanded drawings ordered by ordinal name and
|
|
source path. Identity is by reference: distinct same-named drawings stay distinct,
|
|
including placed drawings absent from the name-keyed drawing collection.
|
|
- Recount nested quantities from placements times sheet copies exactly once using
|
|
checked wide integers. Include unplaced demand; report shortage and extra
|
|
separately. Cached `Quantity.Nested` is not authoritative.
|
|
- Distinguish distinct layouts from physical sheets. Per-sheet quantities do not
|
|
include copies; total quantities do. Utilization uses net part area divided by
|
|
full sheet area, excluding cutoffs.
|
|
- Actual placed programs already contain rotations. Capture their material paths
|
|
with the location applied once. Preserve holes and intentional tab gaps; exclude
|
|
rapid, scribe, lead-in and lead-out paths. Keep Cut and Display contours.
|
|
- If any material contour of a part is open, show all its contours without fill.
|
|
Do not close the gap or substitute the drawing's nominal outline. Cutoffs are
|
|
separate strokes with no product ID or quantity.
|
|
- Snapshots retain values, not live drawings, parts, CNC programs or mutable
|
|
geometry. Invalid/missing/nonfinite geometry fails with drawing/plate context.
|
|
|
|
## Layout, pagination and dense-label fallback
|
|
|
|
An empty/demand-only job, a single plate, or many plates and drawings all
|
|
produce one document: a Letter portrait summary followed by one Letter
|
|
landscape section per plate, every page carrying a repeated header and
|
|
"Page X of Y". Long notes, long drawing names, many drawings and many parts
|
|
per sheet paginate naturally: MigraDoc continues the Plates/Parts tables and
|
|
each plate's part table across pages with the heading row repeated, and notes
|
|
flow as an ordinary paragraph. No row, table or note text is ever dropped or
|
|
truncated to fit a page.
|
|
|
|
Each part ID is centered on its part's pole of inaccessibility (`PolyLabel`,
|
|
the same method `PlateView`'s `LayoutPart` uses), computed on a
|
|
placement-independent quantized copy so identical parts always get the
|
|
identical label position and the label naturally clears a central hole. When
|
|
an ID cannot sit legibly inside its own material at overview scale (for
|
|
example, a cluster of tiny repeated parts), the plate gains a lettered
|
|
(rows)/numbered (columns) map grid drawn beneath the sheet, and only the
|
|
crowded cells get a zoomed, framed detail page listing that cell's real
|
|
coordinates. Detail-cell outlines use a long dash-dot stroke, distinct from
|
|
the shorter dashed scrap-cutoff stroke and the dotted grid lines. IDs are
|
|
never shrunk below 7 pt or silently dropped.
|
|
|
|
The writer still rejects, with `NotSupportedException` and before touching
|
|
the destination:
|
|
|
|
- a page header (nest name plus plate/material line) needing more than 3
|
|
wrapped lines;
|
|
- a table cell needing more than 20 wrapped lines;
|
|
- a part ID that cannot be placed legibly even in the most zoomed supported
|
|
detail view, or a plate that would need more than 24 detail views to label
|
|
every part — named with the plate, part index and ID.
|
|
|
|
Summary thumbnails and the sheet diagram are vector paths, never raster images.
|
|
Each thumbnail is a small PDFsharp page embedded by MigraDoc as a form XObject.
|
|
The diagram is drawn into a fixed-height table row reserved in MigraDoc's flow,
|
|
located after layout with `DocumentRenderer.GetRenderInfoFromPage`. Closed parts
|
|
use one even-odd filled path, so holes stay unfilled. Parts with any open contour,
|
|
and cutoffs (dashed), stroke each contour as its own path: PDFsharp's
|
|
`StartFigure` does not start a new subpath after an open figure, and would
|
|
otherwise draw a false segment across a tab gap.
|
|
|
|
A report is fully rendered to a unique temporary sibling before replacement of
|
|
its destination. A failed render or write leaves an existing report untouched and
|
|
removes temporary output. Applications should obtain overwrite consent before
|
|
calling the library. PDFsharp/MigraDoc layout and font state is process-wide;
|
|
`NestPdfWriter.Write` serializes every export behind one static lock so
|
|
concurrent calls cannot lay out text differently from a sequential export.
|
|
|
|
Advanced timing, cutting distances, pierce counts, weights, costs, gas use, and
|
|
machine/NC identity are intentionally omitted until their semantics are verified.
|
|
The PDF can be opened or printed through a normal PDF viewer; its fitted diagram
|
|
is not a dimensioned cutting drawing.
|
|
|
|
## Backend, fonts and redistribution
|
|
|
|
- Official `PDFsharp-MigraDoc` Core **6.2.4**, with `PDFsharp` **6.2.4**, targeting
|
|
net8.0. No GDI/WPF dependency or printer driver is used. MigraDoc owns flowing
|
|
document layout; PDFsharp draws vectors into its measured reserved areas.
|
|
- DejaVu Sans **2.37**, regular and bold, is bundled unmodified as assembly
|
|
resources. Source: https://dejavu-fonts.github.io/ ; binary provenance:
|
|
Ubuntu `fonts-dejavu-core` **2.37-8**. Both required faces are embedded in PDFs;
|
|
neither generation nor viewing needs a platform font installation.
|
|
- A custom resolver is installed once before fonts are created. Repeated exports
|
|
reuse it. An already-installed foreign resolver is an explicit integration
|
|
error, never silently replaced. A host that already uses PDFsharp needs resolver
|
|
composition before adding report support. MigraDoc's predefined error font is
|
|
pointed at the bundled family; its default (`Courier New`) is a platform font
|
|
the bundled resolver deliberately cannot supply.
|
|
- The initial text contract is printable ASCII/Latin-1 and line/tab separators.
|
|
Other codepoints, controls and soft hyphens fail with the field and codepoint;
|
|
there is no silent missing-glyph substitution. Broader Unicode/shaping support
|
|
is deferred rather than implied by the font's larger character inventory.
|
|
- PDFsharp/MigraDoc are MIT-licensed. The actual v6.2.4 license and the Microsoft
|
|
transitive dependency notices are in `OpenNest.Reporting/THIRD-PARTY-NOTICES.txt`.
|
|
Font permission/redistribution terms are in `OpenNest.Reporting/Fonts/LICENSE.txt`
|
|
(Bitstream Vera permission with DejaVu changes in the public domain). Preserve
|
|
both files in `ReportingNotices/` when publishing; embedded fonts do not replace
|
|
the obligation to ship their notices. Package notices are deduplicated, not
|
|
rewritten or shortened.
|
|
|
|
## Verification
|
|
|
|
```sh
|
|
dotnet test OpenNest.Tests/OpenNest.Tests.csproj --filter FullyQualifiedName~Reporting
|
|
```
|
|
|
|
The writer tests read page sizes and content streams with PDFsharp. Text
|
|
assertions extract with Poppler's `pdftotext -layout` and are skipped, not
|
|
passed, when poppler-utils is absent. For manual inspection also use `pdfinfo`,
|
|
`pdffonts` and `pdftoppm -png` (Linux verification baseline: poppler-utils
|
|
24.02.0). Confirm page sizes, quantity rows, page X of Y, embedded fonts, native
|
|
vector curves, unfilled holes and visible tab gaps with no connecting stroke.
|
|
Pixel inspection supplements geometry assertions; it is not a CNC-validation
|
|
result.
|
|
|
|
Windows compilation is not runtime acceptance. The later desktop adapter must be
|
|
tested on Windows for busy-operation guards, cancellation, overwrite handling,
|
|
unchanged job state and PDF viewing/printing, including the packaged application.
|