enhancement
major
minor
defect
critical
major
minor
minor
#30187
Exporting diagrams as SVG (reactFlowToSvg, flowToSvg) is not suitable for Batik or printing
Problem
The SVG generated by reactFlowToSvg(...) cannot be rendered using pdfFile (Flying Saucer + Batik, embedded as <img src="data:image/svg+xml;base64,...">):
- The engine sets `fill="transparent" ` or `stroke="transparent"`, including in `GanttLayoutOperations` and `GraphEdgeOperations` (tl-react-flow-common). Batik does not recognize "transparent " and terminates.
- rgba(...)-colors are discarded by Batik.
- The screen stylesheet is always embedded. It contains `var(--...)`, which is not resolved outside the browser.
The same applies to the flowToSvg(...) export of classic diagrams (tl-graphic-blocks-server): Colors from the script are carried over unchanged, and the embedded stylesheet tl-flow-core.css uses CSS variables.
Workaround in the application: The SVG is edited as text. ` transparent ` becomes ` none`, `rgba ` becomes ` rgb + fill-opacity`, and the stylesheet is removed. This requires a workaround using `parseCSV `; see the ticket “TL-Script: Read binary value as text.”
Expected
An exported SVG is portable:
- `none ` instead of ` transparent`
- `fill-opacity`/`stroke-opacity ` instead of ` rgba`
- No stylesheet with CSS variables
Solution
reactFlowToSvg and flowToSvg always generate portable SVG that Batik (and thus pdfFile) can render. No option is needed; the display in the browser remains the same. The application can remove the workaround.
- ColorFormat also supports the CSS notation rgb(r, g, b) / rgba(r, g, b, a) (channels 0–255 or percentages, alpha 0–1 or percentages). ColorFormat.parseColorOrNull returns null for text that is not a color.
- The ` SvgTagWriter ` in both export lines converts `fill` and`stroke ` using `ColorFormat `: Each color is written as `#RRGGBB ` (including color names, e.g., ` black` as ` #000000`). A fully transparent color is rendered as `none`; the opacity of a partially transparent color is specified in `fill-opacity `/`stroke-opacity`, multiplied by an opacity value set on the element. Values that are not colors (`none`, `url(#...)`, `currentColor`) remain unchanged.
- Instead of the on-screen stylesheet, the export embeds its own CSS2 stylesheet without variables (tl-react-flow-export.css or tl-flow-export.css in the classpath next to the respective FlowFactory), which only hides the selection markers. The on-screen display remains unchanged.
Test
- TestColorFormat
- TestSvgTagWriter in tl-react-flow-server and tl-graphic-blocks-server
- TestFlowSvgPortable (tl-react-flow-server) and TestFlowPdf (tl-graphic-blocks-server): exported SVG without transparent, rgba(, and var(; rendering via pdfFile without Batik errors.