image/rendering: Clamp natural size correctly
This commit is contained in:
parent
171077ffc7
commit
e0df6fc725
2 changed files with 37 additions and 20 deletions
|
|
@ -115,6 +115,15 @@ const MAX_ZOOM_LEVEL: f64 = 20.0;
|
||||||
/// The thumbnail is currently used for drag and drop.
|
/// The thumbnail is currently used for drag and drop.
|
||||||
const THUMBNAIL_SIZE: f32 = 128.;
|
const THUMBNAIL_SIZE: f32 = 128.;
|
||||||
|
|
||||||
|
/// For large enough monitors occupy 30% of the screen area when opening window with image
|
||||||
|
const DEFAULT_OCCUPY_SCREEN: f64 = 0.3;
|
||||||
|
|
||||||
|
/// Screens with this resolution or smaller are handles as small
|
||||||
|
const SMALL_SCREEN_AREA: f64 = 1024. * 768.;
|
||||||
|
|
||||||
|
/// For small monitors occupy 80% of the screen area
|
||||||
|
const SMALL_OCCUPY_SCREEN: f64 = 0.8;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Copy)]
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
pub enum FitMode {
|
pub enum FitMode {
|
||||||
#[default]
|
#[default]
|
||||||
|
|
|
||||||
|
|
@ -129,22 +129,26 @@ impl WidgetImpl for imp::LpImage {
|
||||||
|
|
||||||
fn measure(&self, orientation: gtk::Orientation, _for_size: i32) -> (i32, i32, i32, i32) {
|
fn measure(&self, orientation: gtk::Orientation, _for_size: i32) -> (i32, i32, i32, i32) {
|
||||||
let obj = self.obj();
|
let obj = self.obj();
|
||||||
let (image_width, image_height) = obj.image_size();
|
let (image_width_i32, image_height_i32) = obj.image_size();
|
||||||
|
let image_width = image_width_i32 as f64;
|
||||||
|
let image_height = image_height_i32 as f64;
|
||||||
|
|
||||||
if image_width > 0 && image_height > 0 {
|
if image_width_i32 > 0 && image_height_i32 > 0 {
|
||||||
if let Some((monitor_width, monitor_height)) = self.monitor_size() {
|
if let Some((monitor_width, monitor_height)) = self.monitor_size() {
|
||||||
let hidpi_scale = self.scaling();
|
let hidpi_scale = self.scaling();
|
||||||
|
log::trace!("Physical monitor dimensions: {monitor_width} x {monitor_height}");
|
||||||
|
|
||||||
// areas
|
// areas
|
||||||
let monitor_area = monitor_width * monitor_height;
|
let monitor_area = monitor_width * monitor_height;
|
||||||
let image_area = image_width as f64 * image_height as f64;
|
let logical_monitor_area = monitor_area * hidpi_scale.powi(2);
|
||||||
|
let image_area = image_width * image_height;
|
||||||
|
|
||||||
let occupy_area_factor = if monitor_area < 1024. * 768. {
|
let occupy_area_factor = if logical_monitor_area <= SMALL_SCREEN_AREA {
|
||||||
// for small monitors occupy 80% of the area
|
log::trace!("Small monitor detected: Using {SMALL_OCCUPY_SCREEN} screen area");
|
||||||
0.8
|
SMALL_OCCUPY_SCREEN
|
||||||
} else {
|
} else {
|
||||||
// for large monitors occupy 30% of the area
|
log::trace!("Sufficiently large monitor detected: Using {DEFAULT_OCCUPY_SCREEN} screen area");
|
||||||
0.3
|
DEFAULT_OCCUPY_SCREEN
|
||||||
};
|
};
|
||||||
|
|
||||||
// factor for width and height that will achieve the desired area
|
// factor for width and height that will achieve the desired area
|
||||||
|
|
@ -154,19 +158,23 @@ impl WidgetImpl for imp::LpImage {
|
||||||
let size_scale = f64::sqrt(monitor_area / image_area * occupy_area_factor);
|
let size_scale = f64::sqrt(monitor_area / image_area * occupy_area_factor);
|
||||||
// ensure that we never increase image size
|
// ensure that we never increase image size
|
||||||
let target_scale = f64::min(1.0, size_scale);
|
let target_scale = f64::min(1.0, size_scale);
|
||||||
let mut nat_width = image_width as f64 * target_scale;
|
let mut nat_width = image_width * target_scale;
|
||||||
let mut nat_height = image_height as f64 * target_scale;
|
let mut nat_height = image_height * target_scale;
|
||||||
|
|
||||||
// scale down if targeted occupation does not fit in one direction
|
// Scale down if targeted occupation does not fit horizontally
|
||||||
if nat_width > monitor_width {
|
// Add some margin to not touch corners
|
||||||
nat_width = monitor_width;
|
let max_width = monitor_width - 20.;
|
||||||
nat_height = nat_height * monitor_width / nat_width;
|
if nat_width > max_width {
|
||||||
|
nat_width = max_width;
|
||||||
|
nat_height = image_height * nat_width / image_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// same for other direction
|
// Same for vertical size
|
||||||
if nat_height > monitor_height {
|
// Additionally substract some space for HeaderBar and Shell bar
|
||||||
nat_height = monitor_height;
|
let max_height = monitor_height - (50. + 35. + 20.) * hidpi_scale;
|
||||||
nat_width = nat_width * monitor_height / nat_height;
|
if nat_height > max_height {
|
||||||
|
nat_height = max_height;
|
||||||
|
nat_width = image_width * nat_height / image_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = match orientation {
|
let size = match orientation {
|
||||||
|
|
@ -182,8 +190,8 @@ impl WidgetImpl for imp::LpImage {
|
||||||
// fallback if monitor size or image size is not known:
|
// fallback if monitor size or image size is not known:
|
||||||
// use original image size and hope for the best
|
// use original image size and hope for the best
|
||||||
let size = match orientation {
|
let size = match orientation {
|
||||||
gtk::Orientation::Horizontal => image_width,
|
gtk::Orientation::Horizontal => image_width_i32,
|
||||||
gtk::Orientation::Vertical => image_height,
|
gtk::Orientation::Vertical => image_height_i32,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue