Merge remote-tracking branch 'origin/master' into worktree-spot-removal
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
Build and test / Desktop (Linux) (push) Successful in 20m9s
Build and test / Layer separation (push) Successful in 39s
Traceability / Requirement traces (push) Successful in 26s
Build and test / Android (aarch64) (push) Failing after 33m10s
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
Build and test / Desktop (Linux) (push) Successful in 20m9s
Build and test / Layer separation (push) Successful in 39s
Traceability / Requirement traces (push) Successful in 26s
Build and test / Android (aarch64) (push) Failing after 33m10s
# Conflicts: # docs/traceability.md
This commit is contained in:
+52
-2
@@ -770,6 +770,41 @@ fn no_choices() -> slint::ModelRc<slint::SharedString> {
|
||||
EMPTY.with(Clone::clone)
|
||||
}
|
||||
|
||||
/// The choices model for one enum parameter, built once per variant list.
|
||||
///
|
||||
/// Memoised for exactly the reason [`no_choices`] is shared: `ModelRc` compares
|
||||
/// by *identity*, so building a fresh one each call makes the row differ from
|
||||
/// itself on every parameter event. `sync_rows` would then replace the row —
|
||||
/// destroying the elements built from it, including whichever `TouchArea` is
|
||||
/// holding the current gesture — and the enum's own control would fight every
|
||||
/// slider drag elsewhere in the panel.
|
||||
///
|
||||
/// Curve rows solve the same problem the other way, by writing new values
|
||||
/// through the existing model. That is not available here: a variant list is
|
||||
/// fixed at compile time, so the model never needs updating and can simply be
|
||||
/// the same one every time.
|
||||
///
|
||||
/// Keyed on the labels rather than the slice's address, because they are
|
||||
/// resolved through the UI's catalogue and two operations offering the same
|
||||
/// choices should share one model.
|
||||
fn choices_model(labels: &[slint::SharedString]) -> slint::ModelRc<slint::SharedString> {
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
thread_local! {
|
||||
static CACHE: RefCell<HashMap<String, slint::ModelRc<slint::SharedString>>> =
|
||||
RefCell::new(HashMap::new());
|
||||
}
|
||||
let key = labels.join("\u{1f}");
|
||||
CACHE.with(|cache| {
|
||||
cache
|
||||
.borrow_mut()
|
||||
.entry(key)
|
||||
.or_insert_with(|| slint::ModelRc::new(slint::VecModel::from(labels.to_vec())))
|
||||
.clone()
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether this frontend has an implementation of `widget` **anywhere**.
|
||||
///
|
||||
/// "Anywhere" is doing real work: a widget may be drawn in the panel, as the
|
||||
@@ -989,7 +1024,7 @@ pub(crate) fn rows_filtered(
|
||||
choices: if choices.is_empty() {
|
||||
no_choices()
|
||||
} else {
|
||||
slint::ModelRc::new(slint::VecModel::from(choices))
|
||||
choices_model(&choices)
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -2655,8 +2690,23 @@ impl DevelopSession {
|
||||
// stock looks comes from. The sensor's width in pixels then says how
|
||||
// much film one pixel covers, and the grain model needs nothing else
|
||||
// to be correct at any zoom.
|
||||
// TRACES: FR-DEV-3f
|
||||
// The frame this is being simulated on, against the pixels it is being
|
||||
// rendered to: together they are the enlargement, and the enlargement
|
||||
// is what decides how grainy the result looks. A crystal is a fixed
|
||||
// size in micrometres — the same emulsion on a sheet averages far more
|
||||
// of them into each pixel than it does on 35 mm.
|
||||
let format = dr_film::Format::from_index(
|
||||
self.graph
|
||||
.param(
|
||||
dr_pipeline::ops::film_sim::ID,
|
||||
dr_pipeline::ops::film_sim::FORMAT,
|
||||
)
|
||||
.unwrap_or(0.0)
|
||||
.max(0.0) as usize,
|
||||
);
|
||||
let (source_width, _) = self.demosaiced.size();
|
||||
let pixel_size_um = dr_film::grain::FRAME_WIDTH_UM / source_width.max(1) as f32;
|
||||
let pixel_size_um = format.width_um() / source_width.max(1) as f32;
|
||||
let grain = dr_film::Grain::for_pixel_size(profile, pixel_size_um);
|
||||
|
||||
let baked = dr_film::bake(&dr_film::Recipe {
|
||||
|
||||
Reference in New Issue
Block a user