Owner report: with the MossTank plugin window BEHIND the inventory window,
the plugin's "Force Buff"/"Cancel Force Buff" button border outlines drew on
top of the inventory paperdoll. Only outlines leaked; fills did not.
Root cause: TextRenderer composited three buckets per layer — submission-
ordered sprite segments, then ALL untextured DrawRect quads (_rectBuf), then
debug text (Flush/DrawLayer). UiRenderContext.DrawRect forwarded into that
separate rect bucket, which always flushed AFTER every sprite segment
regardless of submission order. UiRenderContext.DrawRectOutline is four
DrawRect calls, so every BorderColor outline in the retained UI (UiPanel,
UiMarkupList) composited above every window's sprite content drawn after it,
instead of only the windows actually painted before it.
Fix: UiRenderContext.DrawRect now forwards to DrawFill — the same untextured
SPRITE-bucket segment DrawFill already used for panel backgrounds — so
DrawRectOutline inherits real painter/submission order. Audited the only
other DrawRect caller (UiMeter's bg-then-bar fill, which already relied on
same-call submission order and is unaffected) and the only other
DrawRectOutline callers (UiPanel, UiMarkupList, both routed through the same
fixed chokepoint). TextRenderer.DrawRect/DrawRectOutline and the _rectBuf
bucket are left in place (not deleted) with updated doc comments noting no
caller in src/ outside TextRenderer itself reaches them anymore; a future
non-retained-UI caller (e.g. a debug overlay) could still want that
"always on top of sprites" behavior. Added TextRenderer.DebugRectVertexCount
(test-only) and a failing-first regression test
(UiRectOutlinePainterOrderTests) that builds a real UiPanel border behind a
later-added opaque sprite and asserts submission order.
No retail-divergence register row: this is a renderer ordering bug, not a
documented retail behavior deviation.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>