From b7078c17f1bef6350c893b0f87f9726b6a115120 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Fri, 31 Jul 2026 15:26:49 +0000 Subject: [PATCH] formats/svg: support librsvg 2.40 librsvg 2.41 rewrote the library in Rust, which rules it out on platforms without a Rust toolchain (PowerPC among them); 2.40.x is the last usable series there. The decoder only used three pieces of the newer API, all with direct old-API equivalents: * rsvg_handle_render_document() -> emulated with a cairo translate/scale of the viewport plus rsvg_handle_render_cairo(); the transform composes with the caller's rotation/flip transforms exactly like the viewport-based renderer does. * rsvg_handle_get_intrinsic_dimensions() in get_canvas() -> rsvg_handle_get_dimensions(), which resolves units and viewbox into pixels itself. * the RsvgRectangle/RsvgLength types -> a local RsvgRectangle definition; RsvgLength is only needed in the new-API branches. Everything is guarded by LIBRSVG_CHECK_VERSION(2, 46, 0), so builds against modern librsvg are unchanged. The meson requirement is relaxed to >= 2.40 accordingly. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01G6m1eevhAns3j85HMZYKna --- meson.build | 2 +- src/formats/svg.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index ff0f7da..926d4a5 100644 --- meson.build +++ meson.build @@ -95,7 +95,7 @@ jp2 = dependency('libopenjp2', required: get_option('jp2')) jxl = dependency('libjxl', required: get_option('jxl')) jxl_threads = dependency('libjxl_threads', required: get_option('jxl')) png = dependency('libpng', required: get_option('png')) -rsvg = dependency('librsvg-2.0', version: '>=2.46', required: get_option('svg')) +rsvg = dependency('librsvg-2.0', version: '>=2.40', required: get_option('svg')) tiff = dependency('libtiff-4', required: get_option('tiff')) sixel = dependency('libsixel', required: get_option('sixel')) raw = dependency('libraw', required: get_option('raw')) diff --git a/src/formats/svg.cpp b/src/formats/svg.cpp index c530e90..4b1f625 100644 --- src/formats/svg.cpp +++ src/formats/svg.cpp @@ -10,6 +10,35 @@ #include #pragma GCC diagnostic pop +#if !LIBRSVG_CHECK_VERSION(2, 46, 0) +// librsvg before 2.46 (e.g. 2.40.x, the last pre-Rust series) lacks +// the viewport-based render API and the intrinsic-dimension queries; +// map what the code below needs onto the old cairo-based API. +struct RsvgRectangle { + double x; + double y; + double width; + double height; +}; + +static void compat_render_document(RsvgHandle* svg, cairo_t* cr, + const RsvgRectangle* viewport) +{ + RsvgDimensionData dim; + rsvg_handle_get_dimensions(svg, &dim); + cairo_save(cr); + cairo_translate(cr, viewport->x, viewport->y); + if (dim.width > 0 && dim.height > 0) { + cairo_scale(cr, viewport->width / dim.width, + viewport->height / dim.height); + } + rsvg_handle_render_cairo(svg, cr); + cairo_restore(cr); +} +#define rsvg_handle_render_document(svg, cr, viewport, error) \ + compat_render_document((svg), (cr), (viewport)) +#endif + #include #include #include @@ -90,6 +119,7 @@ private: { RsvgRectangle canvas {}; +#if LIBRSVG_CHECK_VERSION(2, 46, 0) RsvgLength svg_w; RsvgLength svg_h; RsvgRectangle viewbox; @@ -112,6 +142,18 @@ private: canvas.width = CANVAS_SIZE_DEF_PX; canvas.height = CANVAS_SIZE_DEF_PX; } +#else + // The old API resolves units and viewbox into pixels itself. + RsvgDimensionData dim; + rsvg_handle_get_dimensions(svg, &dim); + if (dim.width > 0 && dim.height > 0) { + canvas.width = dim.width; + canvas.height = dim.height; + } else { + canvas.width = CANVAS_SIZE_DEF_PX; + canvas.height = CANVAS_SIZE_DEF_PX; + } +#endif if (canvas.width < CANVAS_SIZE_MIN_PX || canvas.height < CANVAS_SIZE_MIN_PX) { @@ -137,6 +179,11 @@ private: */ static std::string get_format(RsvgHandle* svg) { +#if !LIBRSVG_CHECK_VERSION(2, 46, 0) + RsvgDimensionData dim; + rsvg_handle_get_dimensions(svg, &dim); + return std::format("SVG {}x{}px", dim.width, dim.height); +#else RsvgLength svg_w; RsvgLength svg_h; RsvgRectangle viewbox; @@ -198,6 +245,7 @@ private: static_cast(svg_h.length), units); } return format; +#endif } private: