Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ image operations using `Span<T>`, and supports independent-copy cropping for loa
- 🖨️ **TIFF Codec** - Load/save 8-bit RGB/RGBA/Grayscale TIFF files
- 🗜️ **JPEG Codec** - Load baseline/progressive; save baseline JPEG
- 🎞️ **GIF Codec** - Decode-only load of first GIF frame; `GetInfo` reports the true frame count
- 📐 **SVG Codec** - Rasterize a common SVG subset to a surface
- 📐 **SVG Codec** - Rasterize a common SVG subset, including markers/filters and weight/style-aware
font matching, to a surface
- 🔍 **Header-Only Probing** - `GetInfo` reads headers without decoding pixels (GIF excepted)
- 🖌️ **Path Filling** - Antialiased nonzero/even-odd fill of vector paths
- 🖊️ **Stroke-to-Fill** - Convert stroked paths into fillable outlines
Expand Down
229 changes: 209 additions & 20 deletions docs/design/canvas-net/codecs/svg-codec.md

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions docs/reqstream/canvas-net.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,55 @@ sections:
tests:
- CanvasNet_SystemIntegration_SvgLoad_ReturnsExpectedPixel

- id: CanvasNet-Lib-SvgMarkerRendering
title: >-
The library shall rasterize marker elements referenced from a line, polyline, polygon,
or path element's marker-start/marker-mid/marker-end presentation attributes, at the
correct vertex, orientation, and scale, and shall reject an unbounded
marker-referencing-marker reference cycle the same way an unbounded use reference cycle
is already rejected.
tags: [system]
justification: |
Connector arrowheads and other per-vertex line decorations built via SVG's marker
mechanism are common in real-world diagrams and flowcharts; callers need these to
render rather than silently vanish, with the same bounded, predictable error-handling
behavior already established for use reference cycles.
children:
- CanvasNet-Codecs-SvgMarkerRendering
tests:
- SvgCodec_Load_MarkerEndOnLine_RendersArrowheadPastLineEnd
- SvgCodec_Load_MarkerStartMidEndOnPolyline_RendersDistinctMarkersAtEachVertex
- SvgCodec_Load_ArrowMarkersFixture_RendersArrowheadPastLineEnd
- SvgCodec_Load_MarkerSelfReferenceCycle_ThrowsInvalidDataException
- SvgCodec_Load_MarkerTwoElementReferenceCycle_ThrowsInvalidDataException

- id: CanvasNet-Lib-SvgFilterRendering
title: >-
The library shall rasterize filter elements referenced from any directly renderable
shape or text element's filter presentation attribute, evaluating a
feFlood/feGaussianBlur/feOffset/feComposite/feMerge primitive chain against that
element's own content within a bounded-size temporary offscreen surface, and shall
tolerate a dangling filter reference, an unsupported primitive type, and a
pathologically large filter region or blur radius without failing or hanging.
tags: [system]
justification: |
Solid-color halo/glow backgrounds behind text labels, built via SVG's filter
mechanism, are common in real-world diagrams (the reported real-world bug this feature
fixes: SvgRenderer's own midpoint line labels use exactly this pattern, and previously
lost their halo entirely, causing label text to overlap the line beneath it); callers
need this common pattern to render rather than silently vanish, with the same bounded,
predictable resource-safety behavior already established for this codec's other
reference-following and work-budget concerns.
children:
- CanvasNet-Codecs-SvgFilterRendering
tests:
- SvgCodec_Load_FeFloodFilter_RendersSolidColorBehindElement
- SvgCodec_Load_FeFloodFeGaussianBlurFeCompositeFilter_RendersBlurredHaloBehindContent
- SvgCodec_Load_LabelHaloFixture_RendersWhiteHaloBehindLineMidpointLabel
- SvgCodec_Load_FilterDanglingReference_RendersElementNormally
- SvgCodec_Load_FilterPathologicallyLargeRegion_SkipsFilterRatherThanUnboundedAllocation
- SvgCodec_Load_FilterPathologicallyLargeBlurStdDeviation_ClampsRatherThanUnboundedWork

- id: CanvasNet-Lib-SvgViewBoxFitting
title: >-
The library shall fit an SVG document's intrinsic viewBox into the requested raster size
Expand Down Expand Up @@ -1017,6 +1066,28 @@ sections:
- SvgCodec_Load_TextFontFamilyNoMatch_SkipsSilentlyWithoutThrowing
- SvgCodec_Load_TextFontFamilyCommaSeparatedList_MatchesFirstAvailableFont

- id: CanvasNet-Lib-SvgFontWeightStyleMatching
title: >-
The library shall register more than one font face (varying in font-weight/font-style)
per SVG text font-family and select the closest-matching registered face for each text
element's own cascaded font-weight/font-style, while preserving the pre-existing
single-font-per-family Load overload's behavior unchanged.
tags: [system]
justification: |
Callers commonly need bold titles and italic keywords rendered with the correct
distinct font face, rather than every element in a family always resolving to the
same single font regardless of its requested weight/style; existing callers of the
single-font-per-family overload must observe no behavior change.
children:
- CanvasNet-Codecs-SvgFontWeightStyleMatching
tests:
- SvgCodec_Load_TextFontWeightBold_SelectsBoldFaceOverNormalFace
- SvgCodec_Load_TextFontStyleItalic_SelectsItalicFaceOverNormalFace
- SvgCodec_Load_TextFontWeightAndStyleCombined_SelectsExactMatchAmongThreeFaces
- SvgCodec_Load_GroupFontWeightInheritance_AppliesToChildTextWithoutOwnFontWeight
- SvgCodec_Load_GroupFontStyleInheritance_AppliesToChildTextWithoutOwnFontStyle
- SvgCodec_Load_TextLegacySingleFontOverload_IgnoresRequestedWeightAndStyle

- id: CanvasNet-Lib-SvgValidationNull
title: >-
The library shall reject null stream/path arguments to SVG Load and GetInfo operations
Expand Down
73 changes: 73 additions & 0 deletions docs/reqstream/canvas-net/codecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,55 @@ sections:
- CanvasNet_SystemIntegration_SvgLoad_ReturnsExpectedPixel
- SvgCodec_Load_NonPositiveWidth_PropagatesSurfaceArgumentOutOfRangeException

- id: CanvasNet-Codecs-SvgMarkerRendering
title: >-
The Codecs subsystem shall rasterize marker elements referenced from a line,
polyline, polygon, or path element's marker-start/marker-mid/marker-end
presentation attributes, at the correct vertex, orientation, and scale, and shall
reject an unbounded marker-referencing-marker reference cycle the same way an
unbounded use reference cycle is already rejected.
justification: |
Connector arrowheads and other per-vertex line decorations built via SVG's marker
mechanism are common in real-world diagrams and flowcharts; callers need these to
render rather than silently vanish, with the same bounded, predictable
error-handling behavior already established for use reference cycles.
children:
- CanvasNet-Codecs-SvgCodec-MarkerRendering
- CanvasNet-Codecs-SvgCodec-MarkerReferenceCycle
tests:
- SvgCodec_Load_MarkerEndOnLine_RendersArrowheadPastLineEnd
- SvgCodec_Load_MarkerStartMidEndOnPolyline_RendersDistinctMarkersAtEachVertex
- SvgCodec_Load_ArrowMarkersFixture_RendersArrowheadPastLineEnd
- SvgCodec_Load_MarkerSelfReferenceCycle_ThrowsInvalidDataException
- SvgCodec_Load_MarkerTwoElementReferenceCycle_ThrowsInvalidDataException

- id: CanvasNet-Codecs-SvgFilterRendering
title: >-
The Codecs subsystem shall rasterize filter elements referenced from any directly
renderable shape or text element's filter presentation attribute, evaluating a
feFlood/feGaussianBlur/feOffset/feComposite/feMerge primitive chain against that
element's own content within a bounded-size temporary offscreen surface, and shall
tolerate a dangling filter reference, an unsupported primitive type, and a
pathologically large filter region or blur radius without failing or hanging.
justification: |
Solid-color halo/glow backgrounds behind text labels, built via SVG's filter
mechanism, are common in real-world diagrams (the reported real-world bug this
feature fixes: SvgRenderer's own midpoint line labels use exactly this pattern, and
previously lost their halo entirely, causing label text to overlap the line
beneath it); callers need this common pattern to render rather than silently
vanish, with the same bounded, predictable resource-safety behavior already
established for this codec's other reference-following and work-budget concerns.
children:
- CanvasNet-Codecs-SvgCodec-FilterRendering
- CanvasNet-Codecs-SvgCodec-FilterResourceSafety
tests:
- SvgCodec_Load_FeFloodFilter_RendersSolidColorBehindElement
- SvgCodec_Load_FeFloodFeGaussianBlurFeCompositeFilter_RendersBlurredHaloBehindContent
- SvgCodec_Load_LabelHaloFixture_RendersWhiteHaloBehindLineMidpointLabel
- SvgCodec_Load_FilterDanglingReference_RendersElementNormally
- SvgCodec_Load_FilterPathologicallyLargeRegion_SkipsFilterRatherThanUnboundedAllocation
- SvgCodec_Load_FilterPathologicallyLargeBlurStdDeviation_ClampsRatherThanUnboundedWork

- id: CanvasNet-Codecs-SvgViewBoxFitting
title: >-
The Codecs subsystem shall fit an SVG document's intrinsic viewBox into the
Expand Down Expand Up @@ -982,6 +1031,30 @@ sections:
- SvgCodec_Load_TextFontFamilyNoMatch_SkipsSilentlyWithoutThrowing
- SvgCodec_Load_TextFontFamilyCommaSeparatedList_MatchesFirstAvailableFont

- id: CanvasNet-Codecs-SvgFontWeightStyleMatching
title: >-
The Codecs subsystem shall register more than one font face (varying in
font-weight/font-style) per SVG text font-family and select the closest-matching
registered face for each text element's own cascaded font-weight/font-style,
while preserving the pre-existing single-font-per-family Load overload's behavior
unchanged.
justification: |
Callers commonly need bold titles and italic keywords rendered with the correct
distinct font face, rather than every element in a family always resolving to the
same single font regardless of its requested weight/style; existing callers of the
single-font-per-family overload must observe no behavior change.
children:
- CanvasNet-Codecs-SvgCodec-FontWeightStyleCascade
- CanvasNet-Codecs-SvgCodec-FontFaceMatching
- CanvasNet-Codecs-SvgCodec-LegacySingleFontCompatibility
tests:
- SvgCodec_Load_TextFontWeightBold_SelectsBoldFaceOverNormalFace
- SvgCodec_Load_TextFontStyleItalic_SelectsItalicFaceOverNormalFace
- SvgCodec_Load_TextFontWeightAndStyleCombined_SelectsExactMatchAmongThreeFaces
- SvgCodec_Load_GroupFontWeightInheritance_AppliesToChildTextWithoutOwnFontWeight
- SvgCodec_Load_GroupFontStyleInheritance_AppliesToChildTextWithoutOwnFontStyle
- SvgCodec_Load_TextLegacySingleFontOverload_IgnoresRequestedWeightAndStyle

- id: CanvasNet-Codecs-SvgValidationNull
title: >-
The Codecs subsystem shall reject null stream/path arguments to SVG Load and
Expand Down
Loading
Loading