Prune commentary and stale Rust port notes
This commit is contained in:
1 parent
3ae034a47b
commit
1e6d3b1edd
84 files changed
+334
-5648
No files matched your search
@@ -18,11 +18,9 @@ pub struct Painter<'a> {
|
||||
pub(super) mask: MaskIdx,
|
||||
pub(super) move_slot: MoveIdx,
|
||||
pub(super) child_move_slot: Option<MoveIdx>,
|
||||
/// This widget's retained mask slot.
|
||||
pub(super) own_mask: MaskIdx,
|
||||
pub(super) textures: Vec<TextureHandle>,
|
||||
pub(super) primitives: Vec<PrimitiveHandle>,
|
||||
/// Previous handles, consumed in draw order and freed if left over.
|
||||
pub(super) recycle: std::iter::Peekable<std::vec::IntoIter<PrimitiveHandle>>,
|
||||
pub(super) children: Vec<WidgetId>,
|
||||
pub(super) size_dependencies: Vec<WidgetId>,
|
||||
@@ -37,16 +35,12 @@ pub struct Painter<'a> {
|
||||
pub(super) id: WidgetId,
|
||||
}
|
||||
|
||||
/// A child draw whose size has not necessarily been observed by its parent.
|
||||
/// Holding this value keeps the painter borrowed, so `.size()` can only name
|
||||
/// the child from the immediately preceding draw.
|
||||
pub struct DrawResult<'p, 'a> {
|
||||
painter: &'p mut Painter<'a>,
|
||||
child: WidgetId,
|
||||
}
|
||||
|
||||
impl DrawResult<'_, '_> {
|
||||
/// Return the child's reported size and record the layout dependency.
|
||||
pub fn size(self) -> Size {
|
||||
if !self.painter.size_dependencies.contains(&self.child) {
|
||||
self.painter.size_dependencies.push(self.child);
|
||||
@@ -56,8 +50,6 @@ impl DrawResult<'_, '_> {
|
||||
}
|
||||
|
||||
impl<'a> Painter<'a> {
|
||||
/// Record the size this widget used. Every `Widget::draw` calls this
|
||||
/// exactly once; parents observe it through [`DrawResult::size`].
|
||||
pub fn set_size(&mut self, size: Size) {
|
||||
assert!(
|
||||
self.size.replace(size).is_none(),
|
||||
@@ -69,10 +61,6 @@ impl<'a> Painter<'a> {
|
||||
self.write_primitive(primitive, region, Drawn::Yes);
|
||||
}
|
||||
|
||||
/// The next handle from the previous draw, if it can hold what is
|
||||
/// about to be written: same kind of primitive, same layer, and the
|
||||
/// same answer to "does a layer's draw order name it".
|
||||
///
|
||||
/// **Consumed strictly in order, and one mismatch ends recycling for
|
||||
/// the rest of the draw.** A widget's `draw` is a function of its own
|
||||
/// state, so a redraw writes the same sequence of primitives in the
|
||||
@@ -90,8 +78,6 @@ impl<'a> Painter<'a> {
|
||||
self.recycle.next()
|
||||
}
|
||||
|
||||
/// The one path every primitive this widget owns goes through --
|
||||
/// drawn or, for a mask's shape, only referenced.
|
||||
fn write_primitive<P: Primitive>(
|
||||
&mut self,
|
||||
primitive: P,
|
||||
@@ -121,13 +107,6 @@ impl<'a> Painter<'a> {
|
||||
}
|
||||
|
||||
/// Take ownership of a handle this widget just wrote.
|
||||
///
|
||||
/// The one place a `PrimitiveHandle` enters `self.primitives`, and so
|
||||
/// the one place that can keep `Primitives::handle_index` in step with
|
||||
/// where it lands -- which is what `UiRenderState::apply_free` reads
|
||||
/// instead of scanning this vec. Anything that writes a primitive
|
||||
/// without coming through here leaves that index unset, and its
|
||||
/// position in a layer's draw order stops being renumbered.
|
||||
fn own(&mut self, h: PrimitiveHandle) {
|
||||
self.state
|
||||
.primitives
|
||||
@@ -135,7 +114,6 @@ impl<'a> Painter<'a> {
|
||||
self.primitives.push(h);
|
||||
}
|
||||
|
||||
/// Writes a primitive to be rendered
|
||||
pub fn primitive<P: Primitive>(&mut self, primitive: P) {
|
||||
self.primitive_at(primitive, self.region)
|
||||
}
|
||||
@@ -144,18 +122,6 @@ impl<'a> Painter<'a> {
|
||||
self.primitive_at(primitive, region.within(&self.region));
|
||||
}
|
||||
|
||||
/// Clip everything this widget draws, itself and its descendants, to
|
||||
/// `region`. One call per widget; a widget drawn inside another
|
||||
/// widget's mask nests instead -- the new mask chains to the inherited
|
||||
/// one (`Mask::parent`) and the fragment stage multiplies both
|
||||
/// coverages, which is what lets a transcript row's code fence clip
|
||||
/// to itself *and* to the list it scrolls inside.
|
||||
///
|
||||
/// The clip is a **primitive**, not a rectangle copied into the mask:
|
||||
/// this writes an undrawn `RectPrimitive` at `region` and points the
|
||||
/// mask at it, so the fragment stage evaluates the same rounded-rect
|
||||
/// coverage a drawn rect gets. See LAYOUT.md's "Masks with a shape".
|
||||
///
|
||||
/// The slot is allocated once and **rewritten in place** on every
|
||||
/// later draw rather than pushed again, because a descendant whose own
|
||||
/// region did not change is not redrawn (`draw_inner`'s fast path) and
|
||||
@@ -184,24 +150,12 @@ impl<'a> Painter<'a> {
|
||||
self.set_mask_to(slot);
|
||||
}
|
||||
|
||||
/// Points this widget's mask at a primitive that has already been
|
||||
/// written -- the shared half of [`Self::set_mask`].
|
||||
fn set_mask_to(&mut self, shape: u32) {
|
||||
// `assert!`, not `debug_assert!`: one comparison per widget draw,
|
||||
// and the second call silently *replacing* the first is a widget
|
||||
// drawn unclipped -- which reaches the screen and nothing says so.
|
||||
// Every build anybody runs here is release
|
||||
// (review, 2026-09-07).
|
||||
assert!(
|
||||
self.own_mask == MaskIdx::NONE || self.mask != self.own_mask,
|
||||
"set_mask called twice while drawing one widget: the second would replace the first \
|
||||
rather than nest inside it",
|
||||
);
|
||||
// A glyph would need a CPU-side alpha plane for the hit test to
|
||||
// agree with the shader, and a standalone image a bind-group
|
||||
// switch the fragment stage cannot make -- see `Mask::primitive`.
|
||||
// Named here rather than left to the shader, which would read a
|
||||
// rect that is not there and clip to nothing.
|
||||
let binding = self.state.primitives.instance(shape).binding;
|
||||
assert_eq!(
|
||||
binding,
|
||||
@@ -215,9 +169,6 @@ impl<'a> Painter<'a> {
|
||||
};
|
||||
let old_parent = if self.own_mask == MaskIdx::NONE {
|
||||
let slot = self.rsc.ui_mut().masks.push(mask);
|
||||
// The one ref this widget holds on its own slot, so the slot
|
||||
// outlives any single frame's primitives; released in
|
||||
// `UiRenderState::remove`'s `undraw` branch.
|
||||
self.rsc.ui_mut().masks.push_ref(slot);
|
||||
self.own_mask = slot;
|
||||
MaskIdx::NONE
|
||||
@@ -226,10 +177,6 @@ impl<'a> Painter<'a> {
|
||||
*self.rsc.ui_mut().masks.get_mut(self.own_mask) = mask;
|
||||
old
|
||||
};
|
||||
// The chain link's own ref, taken before the old one is dropped so
|
||||
// that re-chaining to the same slot cannot free it in between.
|
||||
// Released here when the link changes, and in
|
||||
// `UiRenderState::remove` when this widget's slot goes.
|
||||
if old_parent != parent {
|
||||
if parent != MaskIdx::NONE {
|
||||
self.rsc.ui_mut().masks.push_ref(parent);
|
||||
@@ -241,14 +188,10 @@ impl<'a> Painter<'a> {
|
||||
self.mask = self.own_mask;
|
||||
}
|
||||
|
||||
/// Draw a widget within this widget's region. Reading the result's size
|
||||
/// records that this widget's layout depends on the child.
|
||||
pub fn widget<'p, W: ?Sized>(&'p mut self, id: &StrongWidget<W>) -> DrawResult<'p, 'a> {
|
||||
self.widget_at(id, self.region)
|
||||
}
|
||||
|
||||
/// Draws a widget somewhere within this one.
|
||||
/// Useful for drawing child widgets in select areas.
|
||||
pub fn widget_within<'p, W: ?Sized>(
|
||||
&'p mut self,
|
||||
id: &StrongWidget<W>,
|
||||
@@ -263,11 +206,6 @@ impl<'a> Painter<'a> {
|
||||
/// Once retained, it may be updated later in a redraw (for example after
|
||||
/// measuring a changed child). All deeper descendants inherit it and the
|
||||
/// CPU hit-test walk resolves the same translation as the shader.
|
||||
///
|
||||
/// This offsets the child coordinate space, not this widget: its own
|
||||
/// primitives and hit region remain fixed. Once allocated, the boundary
|
||||
/// stays in the chain across redraws; set it to zero to return children to
|
||||
/// their unshifted positions.
|
||||
pub fn set_child_offset(&mut self, offset: Vec2) {
|
||||
let slot = match self.child_move_slot {
|
||||
Some(slot) => slot,
|
||||
@@ -322,13 +260,6 @@ impl<'a> Painter<'a> {
|
||||
region: UiRegion,
|
||||
) -> DrawResult<'p, 'a> {
|
||||
self.children.push(id.id());
|
||||
// Passed directly rather than looked up from `self.active`: this
|
||||
// widget's own `ActiveData` (which would carry its `move_slot`) is
|
||||
// not inserted there until *after* its own `Widget::draw` returns,
|
||||
// so a lookup here -- for a child drawn partway through that same
|
||||
// call -- would always find nothing. `self.move_slot` is this
|
||||
// widget's own slot, already known, and always correct regardless
|
||||
// of insertion order. See `UiRenderState::move_parent_of`.
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
self.layer,
|
||||
@@ -346,7 +277,6 @@ impl<'a> Painter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Place an already-drawn child's used area, redrawing only if its size changes.
|
||||
pub fn place<'p, W: ?Sized>(
|
||||
&'p mut self,
|
||||
id: &StrongWidget<W>,
|
||||
@@ -436,9 +366,6 @@ impl<'a> Painter<'a> {
|
||||
self.write_image(handle.image_index(), region);
|
||||
}
|
||||
|
||||
/// A standalone image draws with its own bind group rather than sharing
|
||||
/// the layer's one instanced draw, so it goes through
|
||||
/// `Primitives::write_image` instead of `primitive_at`/`Primitive::vec`.
|
||||
fn write_image(&mut self, texture_idx: u32, region: UiRegion) {
|
||||
let h = match self.take_recycled(IMAGE_BINDING, Drawn::Yes) {
|
||||
Some(h) => {
|
||||
@@ -474,27 +401,16 @@ impl<'a> Painter<'a> {
|
||||
width: Option<f32>,
|
||||
) -> RenderedText {
|
||||
let density = self.state.density;
|
||||
// Counted here rather than in `TextView::render`, which returns
|
||||
// its memoized layout without reaching this -- so this counts
|
||||
// shapes, not requests. `UiRenderState::take_counters`.
|
||||
self.state.shape_count += 1;
|
||||
let ui = self.rsc.ui_mut();
|
||||
ui.text
|
||||
.render(buffer, attrs, width, &mut ui.textures, density)
|
||||
}
|
||||
|
||||
/// Which glyph atlas the glyphs handed out right now belong to --
|
||||
/// what a widget caching a [`RenderedText`] across frames has to
|
||||
/// compare against before re-emitting it (`GlyphAtlas::clear`).
|
||||
pub fn atlas_generation(&mut self) -> u64 {
|
||||
self.rsc.ui_mut().text.atlas.generation()
|
||||
}
|
||||
|
||||
/// Draw a laid-out string: one quad per glyph, all sampling the atlas.
|
||||
///
|
||||
/// `origin` is where the text's top-left goes; every glyph is placed at an
|
||||
/// absolute pixel offset from it, so re-drawing after a resize is this loop
|
||||
/// and nothing else.
|
||||
pub fn glyphs(&mut self, text: &RenderedText, origin: UiRegion) {
|
||||
// A caller re-emitting quads placed against an atlas that has since
|
||||
// been cleared draws every glyph from coordinates now holding
|
||||
|
||||
Reference in new issue
Block a user