Say what three retained-layout details mean
Reading this back, three things claim something they do not do. `OnResize::Translate` is returned by `TextView::on_resize` under a comment weighing anchored glyphs against reshaping ones, but nothing consumes it: `try_reuse` asks only whether the answer is `Scale`, so a widget saying `Translate` is redrawn. Say so on the variant, since the comment beside it reads as a description of behaviour. `depend_on_size(child, false)` and `depend_on_size(child, true)` are the difference between a hint, which is context-free, and a size the child produced by drawing, which carries every pixel axis the child read. That is the subtlest rule in the file and it was spelled as a bool; give the two cases their names. `draw_started` is the record of what has drawn during the pass under way, and it worked only because `redraw` removes an id before asking about it -- nothing emptied the set, so it accumulated the id of every widget ever drawn, including ones long gone. Empty it with the pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b1b3eca1c0
commit
f1a47e9b7b
3 files changed
+21
-8
No files matched your search
+13
-8
@@ -161,7 +161,7 @@ impl<'a> Painter<'a> {
|
|||||||
Some(hint) => {
|
Some(hint) => {
|
||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
diag::bump(Counter::HintHits);
|
diag::bump(Counter::HintHits);
|
||||||
self.depend_on_size(id, false);
|
self.depend_on_hint(id);
|
||||||
Some(hint)
|
Some(hint)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -203,17 +203,22 @@ impl<'a> Painter<'a> {
|
|||||||
Some(size)
|
Some(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depend_on_size<W: ?Sized>(&mut self, child: &StrongWidget<W>, inherit_inputs: bool) {
|
/// Depends on a length the child gave without being drawn. A hint is
|
||||||
let (box_inputs, output_inputs) = match inherit_inputs {
|
/// context-free, so this depends on the child but on no pixel axis.
|
||||||
true => self
|
fn depend_on_hint<W: ?Sized>(&mut self, child: &StrongWidget<W>) {
|
||||||
|
self.depend_on_size_inputs(child, [false; 2], [false; 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Depends on a size the child produced by drawing, which carries
|
||||||
|
/// whatever the child read to produce it.
|
||||||
|
fn depend_on_drawn_size<W: ?Sized>(&mut self, child: &StrongWidget<W>) {
|
||||||
|
let (box_inputs, output_inputs) = self
|
||||||
.state
|
.state
|
||||||
.active
|
.active
|
||||||
.get(&child.id())
|
.get(&child.id())
|
||||||
.map_or(([false; 2], [false; 2]), |active| {
|
.map_or(([false; 2], [false; 2]), |active| {
|
||||||
(active.size_box_inputs, active.size_output_inputs)
|
(active.size_box_inputs, active.size_output_inputs)
|
||||||
}),
|
});
|
||||||
false => ([false; 2], [false; 2]),
|
|
||||||
};
|
|
||||||
self.depend_on_size_inputs(child, box_inputs, output_inputs);
|
self.depend_on_size_inputs(child, box_inputs, output_inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +356,7 @@ impl<W: ?Sized> DrawResult<'_, '_, W> {
|
|||||||
diag::bump(Counter::SizeReads);
|
diag::bump(Counter::SizeReads);
|
||||||
diag::size_read(self.child.id(), self.painter.id, self.size);
|
diag::size_read(self.child.id(), self.painter.id, self.size);
|
||||||
}
|
}
|
||||||
self.painter.depend_on_size(self.child, true);
|
self.painter.depend_on_drawn_size(self.child);
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ pub struct UiRenderState {
|
|||||||
/// content dirtiness, these may retain an answer whose observed pixel
|
/// content dirtiness, these may retain an answer whose observed pixel
|
||||||
/// axes did not change.
|
/// axes did not change.
|
||||||
resize_marks: HashSet<WidgetId>,
|
resize_marks: HashSet<WidgetId>,
|
||||||
|
/// What has already been drawn during the pass under way, so a widget
|
||||||
|
/// reached by redrawing an ancestor is not drawn again on its own
|
||||||
|
/// account. Emptied when the pass ends.
|
||||||
draw_started: HashSet<WidgetId>,
|
draw_started: HashSet<WidgetId>,
|
||||||
/// A widget's move slot, which outlives any one `ActiveData`: a redraw
|
/// A widget's move slot, which outlives any one `ActiveData`: a redraw
|
||||||
/// replaces that while its children go on pointing at the slot.
|
/// replaces that while its children go on pointing at the slot.
|
||||||
@@ -138,6 +141,7 @@ impl UiRenderState {
|
|||||||
self.resized = [false; 2];
|
self.resized = [false; 2];
|
||||||
self.invalid_sizes.clear();
|
self.invalid_sizes.clear();
|
||||||
self.resize_marks.clear();
|
self.resize_marks.clear();
|
||||||
|
self.draw_started.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redraw_all(&mut self, root: Option<&StrongWidget>, rsc: &mut dyn UiRsc) {
|
fn redraw_all(&mut self, root: Option<&StrongWidget>, rsc: &mut dyn UiRsc) {
|
||||||
@@ -574,6 +578,7 @@ impl UiRenderState {
|
|||||||
self.layers.clear();
|
self.layers.clear();
|
||||||
self.invalid_sizes.clear();
|
self.invalid_sizes.clear();
|
||||||
self.resize_marks.clear();
|
self.resize_marks.clear();
|
||||||
|
self.draw_started.clear();
|
||||||
rsc.widgets_mut().needs_redraw.clear();
|
rsc.widgets_mut().needs_redraw.clear();
|
||||||
rsc.free();
|
rsc.free();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ pub use widgets::*;
|
|||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
pub enum OnResize {
|
pub enum OnResize {
|
||||||
Scale,
|
Scale,
|
||||||
|
/// Reserved: nothing reads this yet, so a widget saying it is redrawn.
|
||||||
|
/// Keeping an unchanged drawing in a bigger box needs the widget to say
|
||||||
|
/// *where* in that box it should sit, which is the alignment work.
|
||||||
Translate,
|
Translate,
|
||||||
#[default]
|
#[default]
|
||||||
Redraw,
|
Redraw,
|
||||||
|
|||||||
Reference in new issue
Block a user