Gtk-Rs 3 : what is the best way to scale an SVG image?

Hi all,
I’ve just managed to load a little svg picture in Gtk-Rs 3

use gdk_pixbuf::{InterpType, Pixbuf};
use gio::MemoryInputStream;
use glib::Bytes;
use gtk::prelude::*;
use gtk::DrawingArea;
use gtk::{Application, ApplicationWindow};

fn main() {
    let app = Application::builder()
        .application_id("com.loloof64.BasicChessEndgames")
        .build();

    app.connect_activate(|app| {
        let win = ApplicationWindow::builder()
            .application(app)
            .default_width(400)
            .default_height(400)
            .title("Basic Chess Endgames")
            .build();

        let image_data = include_bytes!("./resources/Chess_blt45.svg");
        let image_data = Bytes::from(image_data);
        let image_stream = MemoryInputStream::from_bytes(&image_data);
        let pixbuf = Pixbuf::from_stream(&image_stream, None::<&gio::Cancellable>)
            .expect("Failed to create stream for image.");
        let pixbuf = pixbuf
            .scale_simple(140, 140, InterpType::Bilinear)
            .expect("Failed to resize the image.");
        let drawing_area = DrawingArea::new();
        drawing_area.connect_draw(move |_drawing_area, cx| {
            cx.set_source_rgb(0.3, 0.3, 0.3);
            cx.rectangle(0.0, 0.0, 400.0, 400.0);
            cx.fill().expect("Failed to fill context");

            cx.set_source_pixbuf(&pixbuf, 0.0, 0.0);
            cx.paint().expect("Failed to draw image.");

            Inhibit(false)
        });
        win.add(&drawing_area);

        win.show_all();
    });

    app.run();
}

The picture is an svg with a base size of 45x45. But when trying to scale the Pixbuf I got from it - as it’s done in the code here -, the result is quite ugly.

So, is there a better way to scale the image ? Should I’ve called a method before transforming the bytes to Pixbuf ?

Finally I’ve found how to fix it : I should have called Pixbuf::from_stream_at_scale instead of Pixbuf::from_stream.

let pixbuf =
            Pixbuf::from_stream_at_scale(&image_stream, 140, 140, true, None::<&gio::Cancellable>)
                .expect("Failed to interpret image.");
1 Like

Alternatively you could also use librsvg directly to load the SVG and render it to a cairo surface. That gives you a lot more flexibility.

1 Like

Thank you. So I’ll also try librsvg.

Will librsvg work natively on Windows ?

Yes, and it also offers a plain-Rust API. If you don’t want to depend on the C library, you can directly depend on the Rust crate. However gdk-pixbuf uses librsvg for loading SVGs anyway, so you must already have it?

Thank you.

Yes I’ve already declared gdk-pixbuf in my Cargo.toml.
So I’ll have a look at the documentation in order to rely on gdk-pixbuf usage of librsvg :slight_smile:
So maybe I can keep my current implementation in order to get benefits from librsvg ?

No, all gdk-pixbuf gives is the API you use already. By using librsvg directly you have much more flexibility how the rendering should be done. If you don’t need that, keep your current code.

1 Like

Thank you very much :slight_smile:
So I can keep the current code as for now, and I’ll switch back to librsvg if I miss flexibility :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.