docs/feature-requests/svg-icon-element.md
Is your feature request related to a problem? Please describe. PlantUML sprites date back to early releases inspired by 8-bit gaming and reflect the classic sprite model from earlier graphics systems: small monochrome assets with 4, 8, or 16 gray levels defined by hex pixels. That model is a strong fit for the original PlantUML styling and theme control, but it makes modern full-color SVG icon assets awkward:
This limits SVG fidelity and makes it hard to embed branded icons or detailed SVG artwork without losing color intent.
A new diagram element would provide a clear contract: icons preserve original colors and gradients with the benefit of rich SVG representation and no forced color/monochrome whereas Sprites can continue to be supported with their current features and benefits.
In Icons monochrome is possibly a simpler option than colour overrides to support except in the case of 'single colour' icons / SVGs like in Font-Awesome.
The implementation effort to get to full SVG support inside the current Sprite Usage via the UGraphic abstraction could be significant when a direct rendering alternative for SVG Icons may be a useful feature for our users. The expansion of SVG Icon libraries for items like FontAwesome, Material, Cloud providers and their expanded use in Diagrams was probably not anticipated when the Sprite feature was first added.
Describe the solution you'd like
Introduce a new diagram element, icon, that embeds SVG in full color without monochrome or forced-color transforms. The element should be SVG-native when rendering to SVG (inject the original SVG content using a safe wrapper), and should render via the normal UGraphic pipeline for non-SVG outputs. The element should be sizeable and alignable so it can be placed consistently within nodes and layouts.
At a high level:
Describe alternatives you've considered
Additional context Below is a more detailed proposal for syntax, interfaces, and renderer flow.
Inline SVG icon definition:
icon foo1 <svg>...</svg>
// scale 1x
Alice -> Bob : Testing <$foo1>
// Scale 3x
Alice -> Bob : Testing <$foo1{scale=3}>
// Scale 3.4x, Colour in Orange
Alice -> Bob : Testing
<$foo1,scale=3.4,color=orange>
viewBox if present; otherwise width/height attributes.When the output target is SVG, embed the original SVG within a <g> wrapper that applies translation and scaling. This keeps the icon self-contained and preserves fidelity.
Example wrapper (conceptual):
<g transform="translate(x,y) scale(s)">
<!-- raw SVG content here, without outer <svg> -->
</g>
If the icon must be normalized, map the viewBox to a consistent coordinate system and apply a uniform scale in the wrapper.
To keep rendering deterministic and secure:
href / xlink:href URLs.<image> with external URLs.public interface Icon {
void drawU(UGraphic ug, double scale);
}
public interface SvgIconSource {
String getRawSvg();
String getViewBox(); // optional
int getWidth();
int getHeight();
}
if (ug.isSvgOutput() && icon instanceof SvgIconSource) {
SvgIconSource src = (SvgIconSource) icon;
String normalized = normalizeSvg(src.getRawSvg(), src.getViewBox());
String wrapped = wrapInGroup(normalized, x, y, scale);
ug.appendRawSvg(wrapped);
} else {
icon.drawU(ug, scale);
}
Icon instance.<g> to preserve positioning and scaling.Sprites are intentionally theme-aware and allow monochrome/forced-color overrides. This is desirable for UML styling but conflicts with full-color SVG usage. Separating icon from sprite keeps both behaviors clean and predictable:
The Icon abstraction can be extended later to support PNG/JPEG by adding a RasterIconSource without changing the syntax or rendering contracts.
fit=contain|cover options be allowed for bounding boxes?<style> blocks be allowed if they are self-contained?