Skip to content

Add SVG support for draw2d images#252

Open
idrassi wants to merge 2 commits intofrang75:mainfrom
idrassi:issue-222-svg-image-support
Open

Add SVG support for draw2d images#252
idrassi wants to merge 2 commits intofrang75:mainfrom
idrassi:issue-222-svg-image-support

Conversation

@idrassi
Copy link
Copy Markdown

@idrassi idrassi commented Apr 4, 2026

Closes #222.

Summary

This adds a new nsvg library for lightweight SVG support in NAppGUI, based on NanoSVG.

Instead of extending the existing Image loaders, this keeps SVG support in a dedicated module that can either:

  • rasterize SVG into a Pixbuf
  • draw SVG directly into a DCtx as vector content

What changed

  • added a new nsvg module:
    • src/nsvg/nsvg.h
    • src/nsvg/nsvg.hxx
    • src/nsvg/nsvg.hdf
    • src/nsvg/nsvg.c
  • vendored NanoSVG for parsing/rasterization:
    • src/nsvg/depend/nanosvg.h
    • src/nsvg/depend/nanosvgrast.h
  • added a small public SVG API:
    • nsvg_from_data()
    • nsvg_pixbuf()
    • nsvg_draw()
  • extended draw2d so SVG vector rendering can preserve the expected path/paint behavior:
    • path drawing (draw_path_begin/move/line/bezier/close/end)
    • fill rules
    • radial gradients
    • dash offset
    • miter limit
  • implemented the required backend support on GTK, macOS and Windows
  • updated drawhello with an Image/SVG demo and a bundled SVG resource
    • side cards show rasterized output through nsvg_pixbuf()
    • the center card uses nsvg_draw() to show live vector scaling

Why NanoSVG / limitations

NanoSVG was chosen because it is small, easy to vendor, permissively licensed, and fits this change well without adding a large dependency.

This is still intentionally scoped support, not full browser-level SVG rendering. NanoSVG does not implement the entire SVG specification, but it has enough coverage for most commonly used SVG images. More advanced SVG features may still render differently from a browser.

Tested on macOS, Linux and Windows. Below are screenshots of the updated DrawHello Image/SVG panel.

macOS

SVG_macOS

Windows

DrawHello_ImageSVG_Windows

Linux Ubuntu 24.04

DrawHello_ImageSVG_Linux

@idrassi idrassi mentioned this pull request Apr 4, 2026
@frang75
Copy link
Copy Markdown
Owner

frang75 commented Apr 4, 2026

Hi @idrassi!
Great work! Again, I am impressed by the high level of knowledge in the NAppGUI kernel.

However, we need to refactor this. SVG support should be outside of draw2d. This library offers cross-platform support by accessing native APIs. We shouldn't include a third-party library at such a low level.

A better approach, aligned with the NAppGUI architecture, would be:

  • A new nsvg library to include the third-party library, with the draw2d dependency.
  • This interface:
nsvg.h

// NSGV object can contain a cache on SVG operations.
#include "nsvg.hxx"

NSVG *nsvg_from_data(const byte_t *data, const uint32_t size);

void nsvg_destroy(NSVG **svg);

Pixbuf *nsvg_pixbuf(const NSVG *svg, const uint32_t width, const uint32_t height, const pixformat_t format);

// Draw the SVG in vector form in a drawing context.
void nsvg_draw(const NSVG *svg, DCtx *ctx);
nsvg.hxx

// Import draw2d types
#include <draw2d/draw2d.hxx>

typedef struct _nsgv_t NSVG;

This achieves three things:

  • We extract high-level support from the low-level library (draw2d). draw2d provides everything necessary through its public API. We don't need to modify the implementation.
  • We offer users a solution for working with SVGs, but we don't impose it. Users could create a Pixbuf using another solution.
  • We can vector-render SVGs in 2D contexts.

Move SVG handling out of draw2d Image internals into a dedicated nsvg library.
Expose parsing, Pixbuf rasterization, and vector drawing APIs built on NanoSVG.
Extend draw2d with path drawing, fill rules, radial gradients, dash offset, and
miter-limit support across GTK, macOS, and Windows, and update DrawHello to use
the new nsvg API.
@idrassi
Copy link
Copy Markdown
Author

idrassi commented Apr 11, 2026

I updated the PR to align with your suggested architecture.

I added a new nsvg library which exposes the high-level API:

  • nsvg_from_data
  • nsvg_destroy
  • nsvg_pixbuf
  • nsvg_draw

I also updated DrawHello to use nsvg directly

One important point: while implementing nsvg_draw, I found that the current public draw2d API was not quite enough to preserve SVG vector rendering fidelity. Without a few additional generic drawing primitives, nsvg_draw would either need to rasterize internally or approximate some SVG content.

So I extended draw2d with backend-agnostic drawing capabilities that are useful beyond SVG:

  • immediate path drawing
  • fill-rule selection
  • radial gradients
  • dash offset
  • miter limit

These are generic draw2d features needed to render NanoSVG paths through the public drawing API while preserving compound paths, even-odd fills, radial gradients, dashed strokes and miter behavior.

I also kept nsvg_pixbuf() for raster output, so users can still choose SVG-to-Pixbuf when they do not need vector drawing.

I tested the new implementation on Windows, Linux and macOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SVG support?

2 participants