You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add CanvasNet.Pptx Phases 1a-1d: OOXML package layer, presentation model, geometry/paint, and text layout/rendering - #33
A new PowerPoint (.pptx) rendering feature, introducing the DemaConsulting.CanvasNet.Pptx package, modeled on the existing DemaConsulting.CanvasNet.Pdf package as a single Software Unit
(PptxDocument), plus a new, independently-distributed DemaConsulting.CanvasNet.Charts package providing OOXML chart
model/rendering/parsing support consumed by the PPTX renderer. This PR
has grown across Phases 1a-1f plus several Phase 2 follow-ups and now
covers:
Phase 1a - OOXML package layer: zip container opening
(System.IO.Compression.ZipArchive), [Content_Types].xml resolution,
package/part relationship resolution (_rels/.rels, per-part .rels,
relative ../ target traversal and root-escape rejection), hardened
against malformed/oversized/case-mismatched input.
Phase 1b - Presentation/theme/slide-master/slide-layout/slide model
and placeholder property inheritance (placeholder -> layout -> master ->
theme).
Phase 1c - DrawingML shape geometry (<a:xfrm>, custom/preset
geometry, group transforms) and paint (solid/gradient fills, outlines).
Phase 1e - Picture shape decoding/cropping/compositing, table
structure/cell-rect/paint resolution, and recursive full shape-tree
parsing (including nested groups).
Phase 1f - The public, per-slide Render API, dispatching a
document-order walk of a slide's shape tree to the Phase 1c/1d/1e
resolvers/painters.
Phase 2 follow-ups (this release, cumulative) - slide/layout/master <p:bg> background-fill resolution, <a:buChar>/<a:buAutoNum>
bullet/numbering rendering, <p:cxnSp> connector-shape rendering,
pattern fill (30 of 54 named preset patterns, including shape/table
fills) and picture fill, and <p:graphicFrame> chart integration via
the new DemaConsulting.CanvasNet.Charts package (bar/column/line/
pie/doughnut/area chart types).
Still excluded: full text justification, spAutoFit shape-resize,
kerning, text-overflow clipping, nested tables, table auto-sizing/
banding, and radial/path gradients. Pattern and picture fills - including
slide/layout/master background fills (<p:bg>), not just shape/table
fills - are implemented. A corpus-driven hardening pass (mirroring the
PDF feature's own phased history) remains a possible future follow-up.
The DemaConsulting.CanvasNet.Pptx package depends on core DemaConsulting.CanvasNet and the new DemaConsulting.CanvasNet.Charts
package (never on .Pdf or .Svg), consistent with existing precedent.
Type of Change
Bug fix (non-breaking change which fixes an issue)
New feature (non-breaking change which adds functionality)
Breaking change (fix or feature that would cause existing functionality to not work as expected)
Documentation update
Code quality improvement
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
Code builds successfully and all tests pass: pwsh ./build.ps1
Code produces zero warnings
Code Quality
New code has appropriate XML documentation comments
Static analyzer warnings have been addressed
Quality Checks
All linters pass: pwsh ./lint.ps1 - clean (markdownlint, cspell, yamllint, dotnet format, reqstream, versionmark, reviewmark, sysml2tools)
Testing
Added unit tests for new functionality (package-layer, presentation/theme/model, geometry/paint, text layout/rendering, pictures/tables/shape-tree, background fill, bullets, connectors, pattern/picture fill, and chart parsing/rendering/integration, plus system integration)
Updated existing tests if behavior changed (N/A - new packages)
All tests follow the AAA (Arrange, Act, Assert) pattern
Test coverage is maintained or improved
Documentation
Updated README.md (if applicable) - deferred; no end-user-visible feature yet
Updated docs/ documentation (design/verification/reqstream/sysml2 companion artifacts added/updated for the full scope landed in this PR)
Added code examples for new features (if applicable) - deferred until a later release
Updated requirements.yaml (if applicable)
Additional Notes
Remaining deferred items (full text justification, spAutoFit,
kerning, text-overflow clipping, nested tables, table auto-sizing/
banding, radial/path gradients, pattern/picture slide background fill)
and a possible future corpus-driven hardening pass are tracked
internally as potential follow-up work, not committed phases of this PR.
This unit design still says the implementation uses only BCL types and no CanvasNet core type, but Phase 1b now parses theme colors into Canvas.Rgba32 and the project references the core package. Update this dependency statement so the design does not contradict the implementation and system design.
Fixes accumulated GitHub Copilot PR-review findings against
PptxDocument.Package.cs:
- Switch OPC part-name lookup from OrdinalIgnoreCase to ordinal
(case-sensitive) comparison per the OPC spec, and reject duplicate
ZIP entry names instead of silently overwriting the earlier one.
- Bound XML parsing of [Content_Types].xml and relationship parts via
XmlReaderSettings (DTD processing disabled, MaxCharactersInDocument
capped) to prevent an XML-bomb/zip-bomb pattern from exhausting
memory during Open.
- Validate [Content_Types].xml's root element/namespace before
parsing Default/Override children; throw InvalidDataException for a
malformed root instead of silently finding no entries.
- Require Default's Extension/ContentType and Override's
PartName/ContentType attributes; throw InvalidDataException for any
malformed element instead of silently discarding it.
- Validate relationship-part root element/namespace (package-level
_rels/.rels and per-part .rels) and require each Relationship's
Id/Type/Target attributes, throwing InvalidDataException for a bad
root or a missing required attribute at both call sites.
- Update stale doc comments describing the old case-insensitive
lookup behavior.
- Fix a test fixture relationship in PptxTextTests.cs that was
missing a now-required Type attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…review findings 7-8)
Fixes accumulated GitHub Copilot PR-review findings against
PptxDocument.Presentation.cs:
- ParseSlideIdList now validates each resolved <p:sldId> relationship
Type ends with the OOXML slide-relationship suffix ("/slide"),
throwing InvalidDataException if a slide ID is mistargeted at a
theme or other arbitrary part instead of silently accepting it as a
valid slide.
- GetSlideSizeInPixels now range-checks the rounded width/height
against int.MinValue/int.MaxValue before casting, throwing
InvalidDataException for an oversized EMU dimension/DPI combination
instead of silently wrapping to a negative/invalid size.
- Updated doc comments to describe the new validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…lor attributes (PR #33 review findings 9-12)
Fixes accumulated GitHub Copilot PR-review findings against
PptxDocument.Geometry.cs, PptxDocument.Paint.cs, and
PptxDocument.Theme.cs:
- Added a shared ParseRequiredFloatAttribute helper using
invariant-culture TryParse, and refactored ResolveShapeFrame's
<a:off>/<a:ext> attribute parsing (ParseOff/ParseExt) to use it
instead of a direct (float?) cast, so a non-numeric x/y/cx/cy
attribute throws InvalidDataException rather than an unrelated raw
FormatException.
- ParseOptionalPoint (group <a:chOff>/<a:chExt> parsing) now requires
both attributes whenever the element itself is present, throwing
InvalidDataException for a present-but-incomplete element instead
of silently substituting a default - a present element with a
missing required attribute is malformed input, not the "absent
element" case the default is meant to cover.
- Gradient-stop <a:gs> pos parsing now uses invariant-culture TryParse
and throws InvalidDataException for a non-numeric value instead of
an unrelated raw FormatException.
- ParseSchemeColor now validates an OOXML color value is exactly six
hex digits before calling Rgba32.Parse, throwing
InvalidDataException for an eight-digit (AARRGGBB) value instead of
silently misreading its leading byte as alpha.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ntegration test to public API (finding 13)
Adds regression test coverage for review findings 1-12, and fixes
finding 13:
- PptxDocumentTests.cs: new tests covering case-sensitive/duplicate
part names, bounded XML parsing, Content_Types/Relationships root
and required-attribute validation, external-target-mode rejection,
slide relationship type validation, slide-dimension overflow, and
eight-digit theme color rejection.
- PptxGeometryTests.cs: new tests covering non-numeric <a:off>/<a:ext>
attributes and present-but-incomplete <a:chOff>/<a:chExt>.
- PptxPaintTests.cs: new test covering a non-numeric gradient-stop pos
attribute.
- PptxSystemIntegrationTests.cs: restructured the well-formed-package
system test to assert only through PptxDocument's public API
(SlideCount/SlideSize) instead of the internal
ResolveRelationship/ResolvePart members, since a system-integration
test exercising internal-only APIs contradicted this project's own
verification-document claim that system tests exercise only
consumer-visible behavior. The internal-API assertion this test
previously made is already covered by the unit-test suite.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…se 1a-1d scope (PR #33 review findings 14, 16-18)
Fixes documentation staleness findings where internal artifacts still
described an earlier phase as "current" despite Phase 1c/1d having
landed:
- NamespaceDoc.cs: rewrote the summary/remarks to describe the actual
current (Phase 1d) cumulative feature set - package layer,
presentation/theme/master/layout/slide model, DrawingML shape
geometry/paint, and text layout/rendering - instead of calling
PptxDocument a "decode/rasterize-only codec" or freezing the
description at Phase 1b.
- PptxDocument.Package.cs: fixed two stale doc-comment claims that no
presentation-specific content is parsed anywhere in the class (see
the companion code-change commit for the Package.cs diff itself -
these comment fixes are included there).
- docs/design/canvas-net-pptx.md: removed a stale "(this release)"
label from the Phase 1b paragraph.
- docs/design/introduction.md: rewrote the CanvasNetPptx system bullet
to describe the full Phase 1a-1d cumulative scope and dependency
list (Geometry/Drawing/Fonts), moving the "(the current release)"
label to Phase 1d.
- docs/verification/canvas-net-pptx.md: fixed the stale first-scenario
description (now references SlideCount/SlideSize instead of internal
ResolveRelationship/ResolvePart), added the already-existing Phase
1c/1d system-test scenarios, and rewrote the Acceptance Criteria
paragraph to describe the complete current feature set instead of
claiming geometry/paint/text rendering doesn't exist.
- docs/reqstream/canvas-net-pptx/pptx-document.yaml and
docs/verification/canvas-net-pptx/pptx-document.md: linked all new
regression tests added for findings 1-12 into their corresponding
requirements' test lists (widening several requirement titles to
describe the hardened/validated behavior), and added a new
CanvasNetPptx-PptxDocument-CaseSensitivePartNames requirement to
cover finding 1's case-sensitivity/duplicate-entry behavior, which
no existing requirement described.
- docs/sysml2/model/canvas-net-pptx/pptx-document.sysml: fixed a
matching stale "presentation-rendering codec" phrase describing
rendering as a deferred "later phase" capability, now that it ships.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implements Phase 1a of the multi-phase PowerPoint (.pptx) rendering
feature per .agent-logs/planning-pptx-phase1a-7f3a1c.md:
- New DemaConsulting.CanvasNet.Pptx project (net8.0/9.0/10.0),
referencing only the core CanvasNet package, plus its
DemaConsulting.CanvasNet.Pptx.Tests test project; both registered
in CanvasNet.slnx.
- PptxDocument public API stub: Open(Stream), Open(string), Dispose().
- PptxDocument.Package.cs: internal OOXML package layer - opens a
.pptx as a read-only ZipArchive, resolves [Content_Types].xml
(default extension mappings and part-specific overrides), and
resolves package-level (_rels/.rels) and per-part relationships,
including relative-target (../) resolution and root-escape
rejection. No presentation-specific content (ppt/presentation.xml,
slides, layouts, masters, rendering) is parsed - deferred to later
phases.
- Unit tests (PptxDocumentTests.cs) and system-integration tests
(PptxSystemIntegrationTests.cs) using hand-authored, fully
in-memory ZipArchive-over-MemoryStream fixtures.
- Companion artifacts: reqstream requirements (system, unit, and
platform-requirements), design docs, verification docs, SysML2
model files (no dependency edge to core yet, since no core symbol
is used this phase), .reviewmark.yaml review-set blocks, and a new
CanvasNetPptx paragraph in docs/design/introduction.md's Scope
section.
- Added pptx/OOXML-related technical terms to .cspell.yaml.
Deviation from the task's literal file list: no
src/DemaConsulting.CanvasNet.Pptx/README.md was created, matching
the existing precedent that neither DemaConsulting.CanvasNet.Pdf nor
DemaConsulting.CanvasNet.Svg have a per-project README.md - the
repo-root README.md is already packed as the NuGet readme via each
csproj's existing relative-path "..\..\README.md" Pack entry.
Validated: fix.ps1, build.ps1 (full solution + 7347/7347 tests
passing, zero regressions), and lint.ps1 (yamllint, cspell,
markdownlint, reqstream, versionmark, reviewmark, sysml2tools,
dotnet format) all pass cleanly.
Implements a format-agnostic OOXML c:chartSpace parser internal to
DemaConsulting.CanvasNet.Charts, consuming only System.Xml.Linq with no
OPC/ZIP/PresentationML/.Pptx dependency, reading only cached values
(c:numCache/c:strCache). Parses c:barChart (bar/col via c:barDir),
c:lineChart, c:pieChart, c:doughnutChart, and c:areaChart, including
series names, categories, values, chart title, legend presence/position,
and axis titles/range. Throws a new ChartUnsupportedFeatureException for
unsupported chart kinds (radar/scatter/bubble/stock/surface/3D/ofPie),
combo charts, and series with no cached values.
- src/DemaConsulting.CanvasNet.Charts/OpenXml/OpenXmlChartParser.cs
- src/DemaConsulting.CanvasNet.Charts/OpenXml/ChartUnsupportedFeatureException.cs
- src/DemaConsulting.CanvasNet.Charts/OpenXml/NamespaceDoc.cs
- test/DemaConsulting.CanvasNet.Charts.Tests/OpenXmlChartParserTests.cs (57 tests)
- test/DemaConsulting.CanvasNet.Charts.Tests/OpenXmlChartFixtures/README.md
Includes companion reqstream requirements, design docs, verification
docs, SysML2 model/view, .reviewmark.yaml review-set, README feature
note, and user guide API/example section. Adds openxml/textless/aiden/
misrouting/parameterless/Lbls to .cspell.yaml as genuine technical terms
introduced by this phase.
10359/10359 tests passing (up from 10188 baseline), 0 build warnings/
errors.
Resolve <p:graphicFrame> chart relationships, parse via OpenXmlChartParser,
and render via ChartRenderer onto the slide surface using the existing
picture-compositing pattern (transform/clip/z-order). Deferred chart-type
gaps in OpenXmlChartParser (ChartUnsupportedFeatureException) are wrapped
as PptxUnsupportedFeatureException at the Pptx integration boundary to
preserve the fail-closed convention and avoid leaking Charts-specific
exception types from PptxDocument's public API.
- Add one-directional project reference: Pptx -> Charts
- New PptxDocument.Charts.cs: chart part resolution + parse + exception wrap
- Thread chart-part resolution through ShapeTree/Slides/Layouts/Masters
- Render.cs: composite rendered chart onto slide surface like pictures
- Rewrite 3 existing corpus tests to expect successful chart rendering
- Add 2 new real fixtures: supported line chart, unsupported radar chart
- New PptxChartsTests.cs covering dispatch, exception wrapping, malformed
<c:chart>, and synthetic end-to-end rendering
- Update companion docs/reqstream/verification/sysml2/reviewmark entries
and .cspell.yaml for new genuine technical terms (texel, precomputes,
uncontained, prst)
Tests: 10359 -> 10395 (all passing), 0 build warnings/errors.
Documentation/compliance finalization pass for the DemaConsulting.CanvasNet.Charts
feature (Phase 5 of 5, final phase). No chart code, test, or public API changes.
- requirements.yaml: add missing include for
docs/reqstream/canvas-net-charts/chart-model/chart-renderer.yaml, fixing 15
reqstream --lint "unknown child" errors.
- docs/design/introduction.md: rewrite the CanvasNetCharts bullet to present
tense (Phase 4 PptxDocument integration is complete, not future) with an
accurate deferred-chart-type clause (radar/scatter/bubble/stock/surface/3-D/
"of pie"/combo deferred; bar/column/line/pie/doughnut/area supported); correct
the stale CanvasNetPptx bullet claim that pattern/picture fills "remain
explicitly deferred" (30 of 54 pattern presets are now supported, 24 remain
deferred; picture fill is implemented).
- docs/design/canvas-net-charts.md,
docs/design/canvas-net-charts/chart-model.md,
docs/design/canvas-net-charts/open-xml-chart.md,
docs/design/canvas-net-charts/open-xml-chart/open-xml-chart-parser.md:
remove stale "Phase 3/Phase 4/future phase" framing, replacing with
present-tense phrasing describing the completed CanvasNetPptx integration.
- docs/verification/canvas-net-charts.md: remove the "remains expected in a
later phase" paragraph; cross-reference the existing PptxChartsTests.cs/
fixture-corpus system-level tests in CanvasNetPptx's own verification doc.
- docs/sysml2/model/canvas-net-charts.sysml: correct a stale "As of this
release (Phase 3)" qualifier on the CanvasNetCharts-must-never-reference-
CanvasNetPptx constraint, which the design doc already documents as a
permanent architectural rule, not phase-specific.
- .cspell.yaml: add gridline, gridlines, misrender (genuine Charts-related
technical terms) plus horz, Horz, Dmnd, patt, pythonpptx, slidenum, xfrm,
drawingml, Calibri, unoverridden, subtable (genuine pre-existing
CanvasNetPptx technical terms/tool names needed for lint.ps1 to pass
cleanly end-to-end).
- .reviewmark.yaml: shorten 5 over-120-char comment lines.
- docs/verification/canvas-net-charts/chart-model/chart-document.md,
docs/verification/canvas-net-charts/chart-model/chart-renderer.md: rewrap
heading lines for markdownlint MD013 compliance.
- docs/verification/canvas-net-pptx/pptx-document.md,
test/DemaConsulting.CanvasNet.Pptx.Tests/PptxFixtures/README.md: shorten
pre-existing over-120-char heading/table lines (introduced in Phase 4) also
required for lint.ps1 to pass cleanly.
- README.md, docs/user_guide/introduction.md: add a brief mention of PPTX
chart auto-rendering via PptxDocument.Render.
Verification performed:
- Confirmed the SysML2 Charts model (system/subsystem/unit level) is
consistent; sysml2tools lint passes with no errors.
- Confirmed the existing user guide Chart/ChartBuilder/ChartRenderer content
and Examples 14-15 already provide a realistic ChartBuilder + Render
sample; no new user-guide file was warranted (no per-system file
convention exists for Pdf/Svg/Pptx either).
- Confirmed deferred chart types and the ~24 deferred pattern-fill presets
are both documented and discoverable from docs/design/introduction.md.
pwsh ./lint.ps1 passes cleanly (markdownlint-cli2, cspell, yamllint,
dotnet format, reqstream, versionmark, reviewmark, sysml2tools).
pwsh ./build.ps1 passes with 0 warnings, 0 errors, and the full 10395-test
suite passing (unchanged from baseline).
Clamp c:numCache/c:strCache's c:ptCount to 1,048,576 (Excel's own max
worksheet row count) before allocating the dense values/labels array.
A crafted or corrupted chart1.xml could previously declare an
arbitrarily large ptCount (e.g. 2000000000), driving an
attacker-controlled array allocation of up to ~16 GB per series and
crashing the host process with OutOfMemoryException instead of a
clean, fail-closed rejection.
Exceeding the cap now throws the existing
ChartUnsupportedFeatureException (feature token
charts-openxml-point-count-too-large), which PptxDocument already
wraps as PptxUnsupportedFeatureException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Reject nested [/Pattern /Pattern] color space bases in
ResolvePatternColorSpace by throwing UnsupportedImageFeatureException
(feature pdf-colorspace-Pattern-nested) instead of letting it reach
ComponentCount's documented-unreachable InvalidOperationException
backstop.
- BuildShadingPattern now reads the shading dictionary's own /Domain
entry (default [0, 1]) instead of always assuming the default,
independently of the sampled /Function's own /Domain.
- ApplyTiffPredictor now validates decoded data length is an exact
multiple of the row stride, mirroring ApplyPngPredictor's existing
check, instead of silently truncating a partial trailing row.
- RenderTilingPatternCell now disposes tileSurface if cell execution or
recoloring throws partway through, preventing a resource leak on the
exception path.
Adds one regression test per fix in PdfDocumentTests.cs.
…erflow DoS
Both ParseShapeTree (parse-time) and RenderNode (render-time) recursed
into nested <p:grpSp> elements with no depth limit. A crafted .pptx with
deeply nested group shapes could trigger an uncatchable
StackOverflowException.
Adds MaxGroupShapeNestingDepth = 100, applied identically to both parse
and render paths, throwing InvalidDataException (matching the existing
PptxDocument size-cap convention) when exceeded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lint.ps1 was failing on 3 unrecognized words ('uncatchable' x2,
'nullably') introduced by the group-shape recursion-depth fix. Reworded
the comments instead of adding new entries to .cspell.yaml's protected
word list.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… table fill transforms
- Enforce cumulative chart cache allocation budget in OpenXmlChartParser
- Prevent double-to-float overflow in category chart value mapping
- Apply transforms to all coordinate-dependent paints in table fills
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ment links
- Fix stale test method names referenced in pptx-document.yaml requirements
(renamed tests were not updated in multiple requirement blocks)
- Wire 22 previously-orphaned Pptx requirements into existing parent
children lists (Open, PlaceholderInheritance, ShapeGeometryAndPaint,
TextLayoutAndRendering)
- Add 5 new top-level Pptx requirement blocks for Phase-2 follow-up
features that had no existing thematic parent (SlideBackgroundFill,
MasterLayoutShapeRendering, BulletsAndNumbering, ConnectorShapes,
ChartGraphicFrames)
- Add CanvasNet-Canvas-PixelCompositing and CanvasNet-Lib-PixelCompositing
to wire the orphaned Rgba32-CompositeOver requirement into root
reachability
- Wire 3 orphaned Charts requirements (ChartUnsupportedFeatureException,
RealFixtureEndToEnd, RenderRoundTrip) into existing/new parents
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ClassifyPlotArea matches chart kinds by LocalName alone, so a foreign-namespace element named barChart/radarChart is accepted as a c:* chart. If it carries c:ser children, malformed XML can be turned into a valid Chart instead of being rejected. Require e.Name.Namespace == ChartNs before applying these lookup tables.
ClassifyPlotArea matched chart-type elements by LocalName alone, so a
foreign-namespace element named e.g. barChart/radarChart could be accepted
as a c:* chart and, if it carried c:ser children, turn malformed XML into a
valid Chart instead of being rejected. Now requires e.Name.Namespace ==
ChartNs before applying the chart-type lookup tables.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With mixed extreme finite values such as [-double.MaxValue, double.MaxValue], max - min becomes Infinity; mapping either endpoint then computes Infinity / Infinity, producing NaN coordinates and silently losing the plotted bars/points even though the render succeeds. The extreme-value test only checks the surface dimensions, so use a scaled/normalized difference when the range overflows and assert that the data remains visible.
Update verification inventory with new chart subsystems
docs/verification/introduction.md:48
The verification introduction still describes CanvasNetCharts as a single ChartModel subsystem containing only ChartDocument, but this PR adds ChartRenderer and the separate OpenXmlChart subsystem with OpenXmlChartParser. Update this top-level verification inventory so it does not omit the new units and subsystem.
…w, verification doc staleness
- Dispose decoded picture surfaces after painting:
- Render-time-only picture fills (backgrounds, shape/connector
fills, and direct <p:pic> images) are tracked per Render() call
and disposed once painting completes.
- Table-cell picture fills, resolved once at parse time and cached
inside a master/layout/slide's own shape tree, are instead owned
by PptxDocument and disposed by Dispose().
- Added regression tests proving repeated Render() calls on the
same slide still paint correctly for both the render-time and
cached picture-fill paths.
- Prevent overflow when mapping extreme chart values: ValueToPixel
now uses a SafeRatio helper that falls back to a halved-operand
subtraction when max - min overflows to Infinity, avoiding
Infinity / Infinity = NaN. Strengthened the extreme-value test to
assert data is still visibly plotted.
- Update verification inventory with new chart subsystems:
docs/verification/introduction.md now lists ChartRenderer and the
OpenXmlChart/OpenXmlChartParser subsystem alongside ChartDocument.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Although the class is documented as an immutable options bag, this property stores the caller's IReadOnlyList reference directly. A caller can mutate the underlying list after options construction (or concurrently during rendering), changing palette resolution and potentially causing inconsistent results. Make a defensive immutable copy when the property is initialized.
Document CanvasNetPptx installation in the README
README.md:106
The README now documents installation for the new Charts package but omits DemaConsulting.CanvasNet.Pptx, even though this PR introduces that independently distributed public package and the root README is packed into it. Add a PPTX installation section alongside the existing SVG/PDF/Charts sections so users can discover how to consume the feature.
Add CanvasNetCharts to the system dependency summary
docs/design/introduction.md:120
This new system summary lists Canvas/Geometry/Drawing/Fonts/Codecs as CanvasNetPptx's dependencies but omits the newly introduced CanvasNetCharts dependency, even though embedded chart graphic frames now route through OpenXmlChartParser and ChartRenderer. Update the dependency summary so the design introduction does not contradict the package/model dependency graph.
Add CanvasNetPptx to the verification-system inventory
docs/verification/introduction.md:49
The verification-system inventory adds CanvasNetCharts but still omits the new CanvasNetPptx system, despite the PR adding docs/verification/canvas-net-pptx.md and its requirements. This makes the verification introduction incomplete and breaks the top-level navigation to the PPTX verification design.
…te immutability, doc gaps
- PptxDocument.Render.cs/Images.cs: replace the shared _currentRenderImages
instance field with a call-local renderImages list threaded explicitly
through Render/RenderNode/RenderShape/RenderPicture/RenderConnector and
ResolveAndTrackPictureSurface. Two concurrent Render() calls on the same
PptxDocument instance could previously race on the shared field, causing
premature/duplicate disposal or leaked images; each call's own list is now
fully isolated.
- ChartRenderOptions.cs: ColorPalette now defensively copies the caller's
list/array in its init accessor, so mutating the original collection after
constructing a ChartRenderOptions instance can no longer retroactively
change palette resolution for that (documented-immutable) instance. Added
ChartRenderOptionsTests.cs covering the defensive copy.
- README.md: documented the missing DemaConsulting.CanvasNet.Pptx package
installation section.
- docs/design/introduction.md: added CanvasNetPptx's dependency on
CanvasNetCharts to the system dependency summary.
- docs/verification/introduction.md: added the missing CanvasNetPptx system
entry to the verification-system inventory.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The defensive copy is stored as a raw array behind an IReadOnlyList interface. Consumers can cast options.ColorPalette back to Rgba32[] (or IList<Rgba32>) and mutate the supposedly immutable options instance, unlike the ReadOnlyCollection snapshots used by Chart and ChartSeries. Store a read-only wrapper around the copied array.
Prevent pie total overflow from suppressing all wedges
Summing valid finite pie values directly can overflow: two or more large positive double values (which ChartSeries accepts) make total become Infinity, so every share becomes zero and the renderer paints no wedges. Accumulate normalized values relative to the largest positive value, or otherwise use an overflow-safe summation, and use the same scale when calculating each share.
Wrap chart model validation errors as InvalidDataException
Malformed chart data can still escape as ArgumentException here. OpenXmlChartParser.Parse delegates cache/count/range validation to Chart/ChartSeries/ChartAxis constructors, which throw ArgumentException, but this integration only translates ChartUnsupportedFeatureException; the Pptx requirement explicitly promises InvalidDataException for any malformed chart part. Catch the model-validation exception and wrap it as InvalidDataException while preserving the unsupported-feature wrapper.
…, pie overflow, chart validation wrapping
- PptxDocument/PdfDocument: explicitly document that a single instance
is not thread-safe, matching common .NET document/parser conventions
(e.g. XDocument, Stream), instead of serializing every lazy cache
behind a document-wide lock. Callers needing concurrent rendering
should open one instance per thread or synchronize externally.
- ChartRenderOptions.ColorPalette: wrap the defensive copy in a
ReadOnlyCollection<Rgba32> (matching Chart/ChartSeries' own pattern)
so a caller casting the property back to Rgba32[]/IList<Rgba32>
can no longer mutate the options instance.
- ChartRenderer.PieChart: normalize each value against the largest
positive value before accumulating, so summing large-but-finite pie
values can no longer overflow to Infinity and zero every wedge share.
- PptxDocument.Charts: catch ArgumentException thrown by Chart/
ChartSeries/ChartAxis model-validation (via OpenXmlChartParser.Parse)
and rewrap it as InvalidDataException, preserving the existing
ChartUnsupportedFeatureException -> PptxUnsupportedFeatureException
wrapping.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These render remarks say picture backgrounds are fully supported and covered pattern backgrounds are fully supported, but the PR description explicitly lists pattern/picture slide backgrounds as excluded. ResolveSlideBackgroundFill currently passes those fills through ResolveFill, so the implementation and stated scope disagree; please reconcile the behavior or the documented deferred boundary before release.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Description
A new PowerPoint (.pptx) rendering feature, introducing the
DemaConsulting.CanvasNet.Pptxpackage, modeled on the existingDemaConsulting.CanvasNet.Pdfpackage as a single Software Unit(
PptxDocument), plus a new, independently-distributedDemaConsulting.CanvasNet.Chartspackage providing OOXML chartmodel/rendering/parsing support consumed by the PPTX renderer. This PR
has grown across Phases 1a-1f plus several Phase 2 follow-ups and now
covers:
(
System.IO.Compression.ZipArchive),[Content_Types].xmlresolution,package/part relationship resolution (
_rels/.rels, per-part.rels,relative
../target traversal and root-escape rejection), hardenedagainst malformed/oversized/case-mismatched input.
and placeholder property inheritance (placeholder -> layout -> master ->
theme).
<a:xfrm>, custom/presetgeometry, group transforms) and paint (solid/gradient fills, outlines).
(placeholder -> layout -> master
<p:txStyles>-> theme), word-wrap /alignment / vertical-anchor /
normAutofitlayout, and glyph renderingreusing the core
TrueTypeFont/SystemFontCatalog/PathFillerpipeline.
structure/cell-rect/paint resolution, and recursive full shape-tree
parsing (including nested groups).
RenderAPI, dispatching adocument-order walk of a slide's shape tree to the Phase 1c/1d/1e
resolvers/painters.
<p:bg>background-fill resolution,<a:buChar>/<a:buAutoNum>bullet/numbering rendering,
<p:cxnSp>connector-shape rendering,pattern fill (30 of 54 named preset patterns, including shape/table
fills) and picture fill, and
<p:graphicFrame>chart integration viathe new
DemaConsulting.CanvasNet.Chartspackage (bar/column/line/pie/doughnut/area chart types).
Still excluded: full text justification,
spAutoFitshape-resize,kerning, text-overflow clipping, nested tables, table auto-sizing/
banding, and radial/path gradients. Pattern and picture fills - including
slide/layout/master background fills (
<p:bg>), not just shape/tablefills - are implemented. A corpus-driven hardening pass (mirroring the
PDF feature's own phased history) remains a possible future follow-up.
The
DemaConsulting.CanvasNet.Pptxpackage depends on coreDemaConsulting.CanvasNetand the newDemaConsulting.CanvasNet.Chartspackage (never on
.Pdfor.Svg), consistent with existing precedent.Type of Change
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
pwsh ./build.ps1Code Quality
Quality Checks
pwsh ./lint.ps1- clean (markdownlint, cspell, yamllint, dotnet format, reqstream, versionmark, reviewmark, sysml2tools)Testing
Documentation
Additional Notes
Remaining deferred items (full text justification,
spAutoFit,kerning, text-overflow clipping, nested tables, table auto-sizing/
banding, radial/path gradients, pattern/picture slide background fill)
and a possible future corpus-driven hardening pass are tracked
internally as potential follow-up work, not committed phases of this PR.