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

Track original SVG size (#7098)

This fixes bugs related to how an `Image` follows the size of an SVG.

We track the "source size" of each image, i.e. the original width/height
of the SVG, which can be different from whatever it was rasterized as.
This commit is contained in:
Emil Ernerfeldt
2025-05-28 08:33:01 +02:00
committed by GitHub
parent da67465a6c
commit 2cf6a3a9a6
12 changed files with 180 additions and 96 deletions

View File

@@ -1,3 +1,5 @@
use emath::Vec2;
use crate::{textures::TextureOptions, Color32};
use std::sync::Arc;
@@ -47,18 +49,36 @@ impl ImageData {
#[derive(Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ColorImage {
/// width, height.
/// width, height in texels.
pub size: [usize; 2],
/// Size of the original SVG image (if any), or just the texel size of the image.
pub source_size: Vec2,
/// The pixels, row by row, from top to bottom.
pub pixels: Vec<Color32>,
}
impl ColorImage {
/// Create an image filled with the given color.
pub fn new(size: [usize; 2], color: Color32) -> Self {
pub fn new(size: [usize; 2], pixels: Vec<Color32>) -> Self {
debug_assert!(
size[0] * size[1] == pixels.len(),
"size: {size:?}, pixels.len(): {}",
pixels.len()
);
Self {
size,
source_size: Vec2::new(size[0] as f32, size[1] as f32),
pixels,
}
}
/// Create an image filled with the given color.
pub fn filled(size: [usize; 2], color: Color32) -> Self {
Self {
size,
source_size: Vec2::new(size[0] as f32, size[1] as f32),
pixels: vec![color; size[0] * size[1]],
}
}
@@ -105,7 +125,7 @@ impl ColorImage {
.chunks_exact(4)
.map(|p| Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3]))
.collect();
Self { size, pixels }
Self::new(size, pixels)
}
pub fn from_rgba_premultiplied(size: [usize; 2], rgba: &[u8]) -> Self {
@@ -120,7 +140,7 @@ impl ColorImage {
.chunks_exact(4)
.map(|p| Color32::from_rgba_premultiplied(p[0], p[1], p[2], p[3]))
.collect();
Self { size, pixels }
Self::new(size, pixels)
}
/// Create a [`ColorImage`] from flat opaque gray data.
@@ -135,7 +155,7 @@ impl ColorImage {
gray.len()
);
let pixels = gray.iter().map(|p| Color32::from_gray(*p)).collect();
Self { size, pixels }
Self::new(size, pixels)
}
/// Alternative method to `from_gray`.
@@ -152,7 +172,7 @@ impl ColorImage {
size,
pixels.len()
);
Self { size, pixels }
Self::new(size, pixels)
}
/// A view of the underlying data as `&[u8]`
@@ -185,14 +205,14 @@ impl ColorImage {
.chunks_exact(3)
.map(|p| Color32::from_rgb(p[0], p[1], p[2]))
.collect();
Self { size, pixels }
Self::new(size, pixels)
}
/// An example color image, useful for tests.
pub fn example() -> Self {
let width = 128;
let height = 64;
let mut img = Self::new([width, height], Color32::TRANSPARENT);
let mut img = Self::filled([width, height], Color32::TRANSPARENT);
for y in 0..height {
for x in 0..width {
let h = x as f32 / width as f32;
@@ -205,6 +225,13 @@ impl ColorImage {
img
}
/// Set the source size of e.g. the original SVG image.
#[inline]
pub fn with_source_size(mut self, source_size: Vec2) -> Self {
self.source_size = source_size;
self
}
#[inline]
pub fn width(&self) -> usize {
self.size[0]
@@ -242,10 +269,7 @@ impl ColorImage {
&self.pixels[row * row_stride + min_x..row * row_stride + max_x],
);
}
Self {
size: [width, height],
pixels: output,
}
Self::new([width, height], output)
}
}