mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 14:20:04 -04:00
Make Image::paint_at pixel-perfect crisp for SVG images (#7078)
This commit is contained in:
@@ -3114,6 +3114,8 @@ impl Context {
|
|||||||
));
|
));
|
||||||
let max_preview_size = vec2(48.0, 32.0);
|
let max_preview_size = vec2(48.0, 32.0);
|
||||||
|
|
||||||
|
let pixels_per_point = self.pixels_per_point();
|
||||||
|
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
.max_height(300.0)
|
.max_height(300.0)
|
||||||
@@ -3128,15 +3130,16 @@ impl Context {
|
|||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
for (&texture_id, meta) in textures {
|
for (&texture_id, meta) in textures {
|
||||||
let [w, h] = meta.size;
|
let [w, h] = meta.size;
|
||||||
|
let point_size = vec2(w as f32, h as f32) / pixels_per_point;
|
||||||
|
|
||||||
let mut size = vec2(w as f32, h as f32);
|
let mut size = point_size;
|
||||||
size *= (max_preview_size.x / size.x).min(1.0);
|
size *= (max_preview_size.x / size.x).min(1.0);
|
||||||
size *= (max_preview_size.y / size.y).min(1.0);
|
size *= (max_preview_size.y / size.y).min(1.0);
|
||||||
ui.image(SizedTexture::new(texture_id, size))
|
ui.image(SizedTexture::new(texture_id, size))
|
||||||
.on_hover_ui(|ui| {
|
.on_hover_ui(|ui| {
|
||||||
// show larger on hover
|
// show larger on hover
|
||||||
let max_size = 0.5 * ui.ctx().screen_rect().size();
|
let max_size = 0.5 * ui.ctx().screen_rect().size();
|
||||||
let mut size = vec2(w as f32, h as f32);
|
let mut size = point_size;
|
||||||
size *= max_size.x / size.x.max(max_size.x);
|
size *= max_size.x / size.x.max(max_size.x);
|
||||||
size *= max_size.y / size.y.max(max_size.y);
|
size *= max_size.y / size.y.max(max_size.y);
|
||||||
ui.image(SizedTexture::new(texture_id, size));
|
ui.image(SizedTexture::new(texture_id, size));
|
||||||
|
|||||||
@@ -413,6 +413,8 @@ pub trait ImageLoader {
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct SizedTexture {
|
pub struct SizedTexture {
|
||||||
pub id: TextureId,
|
pub id: TextureId,
|
||||||
|
|
||||||
|
/// Size in logical ui points.
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{borrow::Cow, slice::Iter, sync::Arc, time::Duration};
|
use std::{borrow::Cow, slice::Iter, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use emath::{Align, Float as _, Rot2};
|
use emath::{Align, Float as _, GuiRounding as _, NumExt as _, Rot2};
|
||||||
use epaint::{
|
use epaint::{
|
||||||
text::{LayoutJob, TextFormat, TextWrapping},
|
text::{LayoutJob, TextFormat, TextWrapping},
|
||||||
RectShape,
|
RectShape,
|
||||||
@@ -373,9 +373,23 @@ impl<'a> Image<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn paint_at(&self, ui: &Ui, rect: Rect) {
|
pub fn paint_at(&self, ui: &Ui, rect: Rect) {
|
||||||
|
let pixels_per_point = ui.pixels_per_point();
|
||||||
|
|
||||||
|
let rect = rect.round_to_pixels(pixels_per_point);
|
||||||
|
|
||||||
|
// Load exactly the size of the rectangle we are painting to.
|
||||||
|
// This is important for getting crisp SVG:s.
|
||||||
|
let pixel_size = (pixels_per_point * rect.size()).round();
|
||||||
|
|
||||||
|
let texture = self.source(ui.ctx()).clone().load(
|
||||||
|
ui.ctx(),
|
||||||
|
self.texture_options,
|
||||||
|
SizeHint::Size(pixel_size.x as _, pixel_size.y as _),
|
||||||
|
);
|
||||||
|
|
||||||
paint_texture_load_result(
|
paint_texture_load_result(
|
||||||
ui,
|
ui,
|
||||||
&self.load_for_size(ui.ctx(), rect.size()),
|
&texture,
|
||||||
rect,
|
rect,
|
||||||
self.show_loading_spinner,
|
self.show_loading_spinner,
|
||||||
&self.image_options,
|
&self.image_options,
|
||||||
@@ -467,19 +481,24 @@ impl ImageFit {
|
|||||||
impl ImageSize {
|
impl ImageSize {
|
||||||
/// Size hint for e.g. rasterizing an svg.
|
/// Size hint for e.g. rasterizing an svg.
|
||||||
pub fn hint(&self, available_size: Vec2, pixels_per_point: f32) -> SizeHint {
|
pub fn hint(&self, available_size: Vec2, pixels_per_point: f32) -> SizeHint {
|
||||||
let size = match self.fit {
|
let point_size = match self.fit {
|
||||||
ImageFit::Original { scale } => return SizeHint::Scale(scale.ord()),
|
ImageFit::Original { scale } => {
|
||||||
|
return SizeHint::Scale((pixels_per_point * scale).ord())
|
||||||
|
}
|
||||||
ImageFit::Fraction(fract) => available_size * fract,
|
ImageFit::Fraction(fract) => available_size * fract,
|
||||||
ImageFit::Exact(size) => size,
|
ImageFit::Exact(size) => size,
|
||||||
};
|
};
|
||||||
let size = size.min(self.max_size);
|
let point_size = point_size.at_most(self.max_size);
|
||||||
let size = size * pixels_per_point;
|
|
||||||
|
let pixel_size = pixels_per_point * point_size;
|
||||||
|
|
||||||
// `inf` on an axis means "any value"
|
// `inf` on an axis means "any value"
|
||||||
match (size.x.is_finite(), size.y.is_finite()) {
|
match (pixel_size.x.is_finite(), pixel_size.y.is_finite()) {
|
||||||
(true, true) => SizeHint::Size(size.x.round() as u32, size.y.round() as u32),
|
(true, true) => {
|
||||||
(true, false) => SizeHint::Width(size.x.round() as u32),
|
SizeHint::Size(pixel_size.x.round() as u32, pixel_size.y.round() as u32)
|
||||||
(false, true) => SizeHint::Height(size.y.round() as u32),
|
}
|
||||||
|
(true, false) => SizeHint::Width(pixel_size.x.round() as u32),
|
||||||
|
(false, true) => SizeHint::Height(pixel_size.y.round() as u32),
|
||||||
(false, false) => SizeHint::Scale(pixels_per_point.ord()),
|
(false, false) => SizeHint::Scale(pixels_per_point.ord()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user