Skip to content

SVG Text Rendering Issue in egui_extras #5977

@cernec1999

Description

@cernec1999

Bug Report: SVG Text Rendering Issue in egui

Describe the bug

SVG text elements are not rendered correctly in egui when using SVGs that include text. In the example provided, the text "Test Text" either fails to render or renders incorrectly due to font issues. The underlying problem seems connected to the fact that the font database does not have any fonts loaded unless explicitly instructed to do so.

To Reproduce

Steps to reproduce the behavior:

  1. Create a new application and add the following minimally reproducible example:

    use egui::ImageSource;
    use log::LevelFilter;
    use simplelog::{ColorChoice, Config, TermLogger, TerminalMode};
    
    pub struct EguiSvgTextBugDemo {
        demo_image: ImageSource<'static>,
    }
    
    impl Default for EguiSvgTextBugDemo {
        fn default() -> Self {
            let svg_bytes = r##"
    <svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 124 124" fill="none">
    <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 84)">
    <g id="node1" class="node">
    <title>N0</title>
    <polygon fill="#1e1e1e" stroke="none" points="196.03,-80 0,-80 0,0 196.03,0 196.03,-80"/>
    <text text-anchor="start" x="10" y="-60" font-family="Courier,monospace" font-size="12.00" fill="#ffd964">Test Text</text>
    </g>
    </g>
    </svg>
            "##.as_bytes().to_vec();
    
            let demo_image = ImageSource::Bytes {
                uri: std::borrow::Cow::Owned("bytes://test.svg".to_owned()),
                bytes: svg_bytes.into(),
            };
    
            Self {
                demo_image,
            }
        }
    }
    
    impl eframe::App for EguiSvgTextBugDemo {
        fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
            egui::CentralPanel::default().show(ctx, |ui| {
                ui.image(self.demo_image.clone());
            });
        }
    }
    
    fn main() -> eframe::Result<()> {
        TermLogger::init(
            LevelFilter::Warn,
            Config::default(),
            TerminalMode::Mixed,
            ColorChoice::Auto,
        )
        .unwrap();
    
        let options = eframe::NativeOptions::default();
        eframe::run_native(
            "SVG Rendering Bug",
            options,
            Box::new(|cc| {
                // Install image loaders for egui_extras.
                egui_extras::install_image_loaders(&cc.egui_ctx);
                Ok(Box::<EguiSvgTextBugDemo>::default())
            }),
        )
    }
  2. Compile and run the application.

  3. Observe that the SVG is rendered, but the text elements (e.g., "Test Text") do not appear as expected.

Expected behavior

SVGs should render correctly with all visual elements intact. In particular, text elements should respect properties like font-family, font-size, and fill as specified in the SVG markup.

Screenshots

Image

Desktop:

  • OS: Windows 11
  • Browser: N/A (native application)
  • Version: 0.31.1 (latest release from crates.io)

Additional context

I have investigated and implemented a fix in the load_svg_bytes_with_size function found in egui/crates/egui_extras/src/image.rs. The adjustments required are:

  • Font Loading: The issue was largely due to fontdb not loading any fonts unless explicitly triggered. Calling load_system_fonts on the font database within resvg / usvg resolves this:

    opt.fontdb_mut().load_system_fonts();
  • Compatibility with Latest resvg/usvg: I updated the code to work with the latest versions of resvg and usvg. However, I've noticed that the latest version of resvg no longer supports manually updating the image size, as the property formerly used by egui has become a private field.

Screenshots of Working Solution

Image

Clarifications Needed

  1. Image Size Adjustment:
    The latest version of resvg does not allow manual image size updates due to the related field now being private. Is this functionality necessary within egui, or should we rely on the default sizing logic provided by resvg? How would the maintainers like to approach this change?
  2. Font Loading Alternatives:
    Besides loading system fonts using fontdb_mut().load_system_fonts(), there may be cases where the user provides custom fonts for egui text rendering. Should we consider integrating user-provided fonts into the SVG rendering process, or is there a preferred strategy for handling alternative font sources?
  3. Former PR:
    I see this PR: egui_extras: feature svg_text #4659 which would have resolved this issue, but we need to be smart about how we initialize the SVG rendering and fonts DB, so that it doesn't get invoked upon EVERY render: egui_extras: feature svg_text #4659 (comment)

I am prepared to file a PR with the current fix for the SVG text rendering issue but would appreciate some guidance on the questions above to ensure a robust and future-proof solution.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions