1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Match image file extensions case-insensitively (#8430)

`image.PNG` and `cat.SVG` were not recognized as images.

Adds `egui::load::has_extension(uri, extension)`, which ignores ASCII
case and any `#fragment`, and uses it for the `.svg`, `.gif`, `.webp`
and `.png` checks.

Note: gif/webp URIs like `a#b.gif` no longer match, since the fragment
is now excluded.

* [x] I have followed the instructions in the PR template

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Emil Ernerfeldt
2026-08-17 21:41:09 -07:00
committed by GitHub
parent 5579f831c2
commit 9bb36b0ac2
5 changed files with 29 additions and 5 deletions

View File

@@ -1720,7 +1720,7 @@ fn save_screenshot_and_exit(
screen_size_in_pixels: [u32; 2], screen_size_in_pixels: [u32; 2],
) { ) {
assert!( assert!(
path.ends_with(".png"), egui::load::has_extension(path, "png"),
"Expected EFRAME_SCREENSHOT_TO to end with '.png', got {path:?}" "Expected EFRAME_SCREENSHOT_TO to end with '.png', got {path:?}"
); );
let screenshot = painter.read_screen_rgba(screen_size_in_pixels); let screenshot = painter.read_screen_rgba(screen_size_in_pixels);

View File

@@ -306,6 +306,19 @@ macro_rules! generate_loader_id {
} }
pub use crate::generate_loader_id; pub use crate::generate_loader_id;
/// Does the given URI end with the given file extension?
///
/// The comparison ignores ASCII case and any `#fragment` at the end of the URI,
/// so `has_extension("cat.GIF#frame=2", "gif")` is `true`.
///
/// This is useful when implementing an [`ImageLoader`].
pub fn has_extension(uri: &str, extension: &str) -> bool {
let path = uri.split('#').next().unwrap_or(uri);
std::path::Path::new(path)
.extension()
.is_some_and(|found| found.eq_ignore_ascii_case(extension))
}
pub type BytesLoadResult = Result<BytesPoll>; pub type BytesLoadResult = Result<BytesPoll>;
/// Represents a loader capable of loading raw unstructured bytes from somewhere, /// Represents a loader capable of loading raw unstructured bytes from somewhere,
@@ -639,3 +652,14 @@ impl Loaders {
} }
} }
} }
#[test]
fn test_has_extension() {
assert!(has_extension("cat.svg", "svg"));
assert!(has_extension("cat.SVG", "svg"));
assert!(has_extension("http://example.com/cat.gif#frame=2", "gif"));
assert!(!has_extension("cat.svg.png", "svg"));
assert!(!has_extension("svg", "svg"));
assert!(!has_extension("cat.jpeg", "jpg"));
assert!(!has_extension("cat.svg?v=1", "svg"));
}

View File

@@ -150,5 +150,5 @@ impl TextureLoader for DefaultTextureLoader {
} }
fn is_svg(uri: &str) -> bool { fn is_svg(uri: &str) -> bool {
uri.ends_with(".svg") super::has_extension(uri, "svg")
} }

View File

@@ -934,7 +934,7 @@ fn animated_image_frame_index(ctx: &Context, uri: &str) -> usize {
/// Checks if uri is a gif file /// Checks if uri is a gif file
fn is_gif_uri(uri: &str) -> bool { fn is_gif_uri(uri: &str) -> bool {
uri.ends_with(".gif") || uri.contains(".gif#") crate::load::has_extension(uri, "gif")
} }
/// Checks if bytes are gifs /// Checks if bytes are gifs
@@ -944,7 +944,7 @@ pub fn has_gif_magic_header(bytes: &[u8]) -> bool {
/// Checks if uri is a webp file /// Checks if uri is a webp file
fn is_webp_uri(uri: &str) -> bool { fn is_webp_uri(uri: &str) -> bool {
uri.ends_with(".webp") || uri.contains(".webp#") crate::load::has_extension(uri, "webp")
} }
/// Checks if bytes are webp /// Checks if bytes are webp

View File

@@ -29,7 +29,7 @@ impl SvgLoader {
} }
fn is_supported(uri: &str) -> bool { fn is_supported(uri: &str) -> bool {
uri.ends_with(".svg") egui::load::has_extension(uri, "svg")
} }
impl Default for SvgLoader { impl Default for SvgLoader {