mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
Merge PR #655
This commit is contained in:
commit
b31e0e2ec6
3 files changed
+51
-4
No files matched your search
@@ -215,6 +215,9 @@ pub struct Headless {
|
||||
pub view: HeadlessView,
|
||||
/// The largest texture the pretend GPU takes (what a WebGL device may report: 2048).
|
||||
pub max_texture_side: usize,
|
||||
/// The limit egui was last told. Like a native host (egui-winit) it is reported once, not in
|
||||
/// every frame's input: code that reads the raw input sees `None` from then on (issue #652).
|
||||
reported_texture_side: Option<usize>,
|
||||
/// Logical size (points) and scale.
|
||||
pub size: egui::Vec2,
|
||||
pub pixels_per_point: f32,
|
||||
@@ -248,6 +251,7 @@ impl Headless {
|
||||
app,
|
||||
view: HeadlessView::new(),
|
||||
max_texture_side: 16384,
|
||||
reported_texture_side: None,
|
||||
size,
|
||||
pixels_per_point,
|
||||
time: 0.0,
|
||||
@@ -280,7 +284,8 @@ impl Headless {
|
||||
(self.size, self.pixels_per_point) = bounded_viewport(self.size, self.pixels_per_point);
|
||||
let mut raw = HeadlessView::raw_input(self.size, self.pixels_per_point, self.time, std::mem::take(&mut self.events));
|
||||
raw.viewports.entry(ViewportId::ROOT).or_default().maximized = Some(self.window_maximized);
|
||||
raw.max_texture_side = Some(self.max_texture_side);
|
||||
raw.max_texture_side = (self.reported_texture_side != Some(self.max_texture_side)).then_some(self.max_texture_side);
|
||||
self.reported_texture_side = Some(self.max_texture_side);
|
||||
self.app.raw_input_hook(&mut raw);
|
||||
let app = &mut self.app;
|
||||
let mut cursor = egui::CursorIcon::Default;
|
||||
|
||||
@@ -187,10 +187,14 @@ pub(crate) fn navigate_gesture(app: &mut LightcraftApp, ui: &mut egui::Ui, resp:
|
||||
true
|
||||
}
|
||||
|
||||
/// The largest texture the GPU behind `ctx` takes (egui reports it; 2048 when it doesn't, the
|
||||
/// The largest texture the GPU behind `ctx` takes (egui reports it; 2048 until it does, the
|
||||
/// smallest limit WebGL devices have).
|
||||
///
|
||||
/// The value egui keeps, not the frame's raw input: a native host (egui-winit) reports the limit
|
||||
/// in the first frame's input only, so the raw value is `None` from the second frame on
|
||||
/// (issue #652: every window render was cut to 2048 px, with blurry strips beside it).
|
||||
pub(crate) fn texture_side(ctx: &egui::Context) -> usize {
|
||||
ctx.input(|i| i.raw.max_texture_side).unwrap_or(2048)
|
||||
ctx.input(|i| i.max_texture_side)
|
||||
}
|
||||
|
||||
/// The photo's own pixels as it is shown: its size after the crop and the user's rotation (what
|
||||
@@ -2139,7 +2143,23 @@ fn straighten_overlay(app: &mut LightcraftApp, ui: &mut egui::Ui, resp: &egui::R
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::film_label;
|
||||
use super::{film_label, texture_side};
|
||||
|
||||
/// Issue #652: a native host reports the GPU's texture limit in the first frame's input only.
|
||||
/// The loupe must still know it in every later frame (it read the raw input, found nothing and
|
||||
/// cut every window render to 2048 px).
|
||||
#[test]
|
||||
fn the_texture_limit_outlives_the_frame_it_was_reported_in() {
|
||||
let ctx = egui::Context::default();
|
||||
assert_eq!(texture_side(&ctx), 2048, "until the host says: the smallest limit there is");
|
||||
let mut seen = Vec::new();
|
||||
for reported in [Some(8192), None, None] {
|
||||
let raw = egui::RawInput { max_texture_side: reported, ..Default::default() };
|
||||
let mut out = ctx.run_ui(raw, |ui| seen.push(texture_side(ui.ctx())));
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
assert_eq!(seen, [8192, 8192, 8192]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn film_labels_cut_on_characters_not_bytes() {
|
||||
|
||||
@@ -352,6 +352,28 @@ mod in_the_loupe {
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #652: given a canvas wider than 2048 px on a desktop GPU (which reports its texture
|
||||
// limit to egui once, in the first frame), when I zoom to 1:1, then the window render covers
|
||||
// the whole canvas: no strip of the magnified whole-frame render beside it
|
||||
#[test]
|
||||
fn a_window_covers_a_canvas_wider_than_2048_px() {
|
||||
let (mut h, native) = detail_in([2600.0, 1200.0]);
|
||||
assert!(native > 2600, "the photo is wider than the canvas at 1:1: {native}");
|
||||
h.request("engine.execute", json!({"command": "view.zoom100"}), T);
|
||||
h.settle(SETTLE);
|
||||
let canvas = h.app.canvas_rect.expect("the loupe was drawn");
|
||||
let image = h.app.image_rect.expect("the photo was drawn");
|
||||
let region = h.app.region_view.expect("a window");
|
||||
// the canvas in pixels of the window's frame (scale 1, at 100 %: a point is a pixel)
|
||||
let to_px = region.full.0 as f32 / image.width();
|
||||
let (left, right) = (to_px * (canvas.left() - image.left()), to_px * (canvas.right() - image.left()));
|
||||
assert!(right - left > 2048.0, "the canvas shows more than 2048 px: {left}..{right}");
|
||||
let (x0, x1) = (region.window.x as f32, (region.window.x + region.window.w) as f32);
|
||||
assert!(x0 <= left + 0.5 && x1 >= right - 0.5, "the window {x0}..{x1} leaves part of the canvas {left}..{right} to the preview");
|
||||
let (w, _) = region_tile(&h).expect("the window rendered");
|
||||
assert_eq!(w, region.window.w, "and that is the texture drawn");
|
||||
}
|
||||
|
||||
// Given 400 % on a big photo, when a slider is dragged, then the work per frame follows the
|
||||
// canvas, not the zoom: a draft of the whole frame at canvas scale and a draft of the window
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user