Cut shell/panel comment bloat ~47% (comments only, zero code change)

This commit is contained in:
2026-07-29 20:48:56 -04:00
parent 1f24c4b095
commit cc36dd59c7
15 changed files with 627 additions and 1320 deletions
+19 -55
View File
@@ -1,17 +1,14 @@
// draw_kit — the LICE/SWELL shell half of the drawing kit. See draw_kit.h.
//
// Compiled into the reaper_reasampler MODULE. SHELL layer: it is the only kit file that
// touches LICE + SWELL. All colors come from the pure `theme` module; all geometry from
// the pure `component_geometry` module. DAW-verified, not unit-tested.
// SHELL: the only kit file that touches LICE + SWELL. Colors come from `theme`;
// geometry from `component_geometry`. DAW-verified, not unit-tested.
#include "shell/panel/draw_kit.h"
#include <cstddef>
#include "core/ui/bank_grid.h" // compressAmplitudeForDisplay — the shared dB display curve (pure)
#include "core/ui/bank_grid.h" // compressAmplitudeForDisplay — the shared dB display curve
// SWELL / LICE. On Windows use native Win32 (windows.h first); on mac/linux SWELL is
// provided by the host. Mirrors the panel TUs' (shell/panel/) include discipline.
// On Windows use native Win32 (windows.h first); on mac/linux SWELL is provided by the host.
#ifdef _WIN32
#include <windows.h>
#else
@@ -23,7 +20,6 @@
namespace reasampler {
// Real-namespace-home using-declarations (Q-W6: the namespaces.h shim is retired).
using audio::ChannelEnvelope;
using audio::columnMinMax;
using audio::MinMax;
@@ -32,24 +28,18 @@ using ui::roleColor;
using ui::roleColorState;
using ui::spectralColor;
// --- KitColor <-> LICE boundary ----------------------------------------------
// The one place a pure KitColor becomes a LICE_pixel. Verified packing: LICE_RGBA(r,g,b,a)
// (lice.h:57). The theme owns the color; the shell owns the packing. Declared in draw_kit.h
// so shell translation units (bank_panel) can use it without duplicating the LICE_RGBA pack.
// The one place a pure KitColor becomes a LICE_pixel (LICE_RGBA(r,g,b,a), verified against
// lice.h). The theme owns the color; the shell owns the packing.
LICE_pixel toLice(const KitColor& c) {
return LICE_RGBA(c.r, c.g, c.b, c.a);
}
namespace {
// The draw alpha the LICE primitives take (0..1), from the KitColor's 8-bit alpha. Used so
// a disabled surface (alpha 0.4) composites at the right opacity — LICE_FillRect etc. take
// a float alpha argument separate from the pixel's own alpha byte.
// LICE_FillRect etc. take a float alpha (0..1) separate from the pixel's own alpha byte —
// this converts a KitColor's 8-bit alpha so a disabled surface composites at the right opacity.
float drawAlpha(const KitColor& c) { return c.a / 255.0f; }
// --- Font set (owned by the kit) ---------------------------------------------
struct KitFonts {
LICE_CachedFont title;
LICE_CachedFont label;
@@ -92,8 +82,8 @@ UINT alignFlag(Align a) {
return DT_LEFT;
}
// A 1px inner highlight on the top edge and shadow on the bottom edge — the vwnd trick
// that gives a flat fill dimension (§2.2). Lightens the top row, darkens the bottom row.
// A 1px inner highlight on the top edge and shadow on the bottom edge gives a flat fill
// dimension without a border.
void innerEdges(LICE_IBitmap* bmp, const KitBox& b, float alpha) {
if (b.width < 2 || b.height < 2) return;
const LICE_pixel hi = LICE_RGBA(255, 255, 255, 255);
@@ -111,9 +101,8 @@ void fillGradient(LICE_IBitmap* bmp, const KitBox& b, const KitColor& top,
const KitColor& bottom) {
if (b.empty()) return;
const float a = drawAlpha(top);
// LICE_GradRect wants initial R/G/B/A (0..1) and per-axis deltas. Verified signature
// lice.h:466 — ir..ia are the top-left color; drdy..dady ramp DOWN the height so the
// bottom row reaches `bottom`. No horizontal ramp (drdx.. = 0).
// LICE_GradRect (lice.h) takes initial R/G/B/A plus per-axis deltas: ir..ia are the
// top-left color, drdy..dady ramp DOWN the height so the bottom row reaches `bottom`.
const float ir = top.r / 255.0f, ig = top.g / 255.0f, ib = top.b / 255.0f;
const float dr = (bottom.r - top.r) / 255.0f;
const float dg = (bottom.g - top.g) / 255.0f;
@@ -145,12 +134,8 @@ RECT toRect(const KitBox& b) {
} // namespace
// --- Font lifecycle ----------------------------------------------------------
void kitFontsInit() {
if (g_fonts.ready) return; // idempotent
// §3.1 type scale: title ~15px semibold, label ~12px, value-mono ~12px tabular,
// micro ~10px. Segoe UI (universal on the Windows target); Consolas for numerics.
loadFont(g_fonts.title, 15, FW_SEMIBOLD, "Segoe UI");
loadFont(g_fonts.label, 12, FW_NORMAL, "Segoe UI");
loadFont(g_fonts.valueMono, 12, FW_NORMAL, "Consolas");
@@ -160,11 +145,8 @@ void kitFontsInit() {
void kitFontsShutdown() {
if (!g_fonts.ready) return; // idempotent
// LICE_CachedFont's destructor frees its OWNS_HFONT HFONT. Re-assigning an empty font
// via SetFromHFont(nullptr) would leak nothing but also do nothing useful; instead we
// mark not-ready and let the fonts release their HFONTs when g_fonts is reset. Because
// g_fonts is a static instance (not re-created), free the HFONTs explicitly by handing
// each a null font, which OWNS semantics clean up the prior HFONT (lice_text.h:41).
// g_fonts is a static instance, never re-created, so free the HFONTs explicitly:
// handing each a null font with OWNS_HFONT cleans up the prior HFONT (lice_text.h).
g_fonts.title.SetFromHFont(nullptr, LICE_FONT_FLAG_OWNS_HFONT);
g_fonts.label.SetFromHFont(nullptr, LICE_FONT_FLAG_OWNS_HFONT);
g_fonts.valueMono.SetFromHFont(nullptr, LICE_FONT_FLAG_OWNS_HFONT);
@@ -172,8 +154,6 @@ void kitFontsShutdown() {
g_fonts.ready = false;
}
// --- Text --------------------------------------------------------------------
void text(LICE_IBitmap* bmp, const KitBox& box, const char* str,
Font font, const KitColor& color, Align align) {
if (!bmp || !str || box.empty()) return;
@@ -191,8 +171,6 @@ void text(LICE_IBitmap* bmp, const KitBox& box, const char* str,
text(bmp, box, str, font, roleColor(role), align);
}
// --- Surfaces + components ----------------------------------------------------
void fillSurface(LICE_IBitmap* bmp, const KitBox& box, Role role, InteractionState state) {
if (!bmp || box.empty()) return;
const KitColor base = roleColorState(role, state);
@@ -211,9 +189,8 @@ void drawButton(LICE_IBitmap* bmp, const KitButtonBox& button, const char* label
KitColor top, bottom;
gradientPair(base, top, bottom);
// Rounded surface: fill the interior gradient, then an AA rounded border. Corner
// radius scales gently with height, clamped so tiny buttons stay legible.
fillGradient(bmp, b, top, bottom);
// Corner radius scales with height, clamped so tiny buttons stay legible.
const int radius = b.height >= 20 ? 5 : (b.height >= 12 ? 3 : 2);
const KitColor borderCol =
(state == InteractionState::Active || state == InteractionState::Focus)
@@ -224,9 +201,7 @@ void drawButton(LICE_IBitmap* bmp, const KitButtonBox& button, const char* label
radius, toLice(borderCol), drawAlpha(borderCol), 0, true);
if (label && *label) {
// Active fill is the accent — draw its label in the base bg for contrast; else
// text/primary (disabled dims via the state on the surface, label stays primary
// but the whole control reads recessed).
// Active fill is the accent — label goes in bg/base for contrast; else text/primary.
const Role textRole = (state == InteractionState::Active)
? Role::BgBase
: Role::TextPrimary;
@@ -237,10 +212,8 @@ void drawButton(LICE_IBitmap* bmp, const KitButtonBox& button, const char* label
void drawSlider(LICE_IBitmap* bmp, const SliderGeometry& geom, InteractionState state) {
if (!bmp || geom.track.empty()) return;
// Track groove: the cell surface, recessed (pressed-ish) so it reads as a channel.
fillSurface(bmp, geom.track, Role::BgCell, InteractionState::Pressed);
// Filled portion up to the handle: the accent (hover/dragging brighten it).
if (!geom.filled.empty()) {
const InteractionState fillState =
(state == InteractionState::Hover || state == InteractionState::Dragging)
@@ -251,7 +224,6 @@ void drawSlider(LICE_IBitmap* bmp, const SliderGeometry& geom, InteractionState
fillGradient(bmp, geom.filled, top, bottom);
}
// Handle: a raised knob honoring state.
if (!geom.handle.empty()) {
const KitButtonBox knob{geom.handle};
drawButton(bmp, knob, nullptr, state, /*warn=*/false);
@@ -263,18 +235,16 @@ void drawListRow(LICE_IBitmap* bmp, const ListRowBox& row, const char* label,
const KitBox& b = row.box;
if (!bmp || b.empty()) return;
// Row surface: bg/cell transformed by state (hover lightens, active = accent).
fillSurface(bmp, b, Role::BgCell, state);
// Focus ring: a 1px text/primary rectangle, distinct from the accent selection fill.
// Focus ring is text/primary, distinct from the accent selection fill.
if (state == InteractionState::Focus) {
const KitColor ring = roleColor(Role::TextPrimary);
LICE_DrawRect(bmp, b.x, b.y, b.width - 1, b.height - 1,
toLice(ring), drawAlpha(ring), 0);
}
// Label in the width after the reserved thumbnail inset. Active rows draw the label in
// bg/base for contrast against the accent fill; else text/primary.
// Active rows draw the label in bg/base for contrast against the accent fill.
if (label && *label) {
const int inset = thumbWidth > 0 ? thumbWidth + 6 : 6;
KitBox labelBox{b.x + inset, b.y, b.width - inset - 6, b.height};
@@ -314,13 +284,7 @@ void drawWaveform(LICE_IBitmap* bmp, const KitBox& box, const Envelope& env) {
if (bins.empty() || innerW <= 0) continue;
// Render one filled vertical span per pixel column. peaks::columnMinMax merges
// all bins that project to column `col` under the exact same partition as
// computeEnvelope used to build the envelope, so every pixel column is covered
// with no gaps regardless of the bins-to-pixels ratio. With one bin per column
// (kWaveformOversample == 1) each span covers the true min/max of exactly the
// frames that fall in that column. Same dB display compression everywhere
// (bank_grid, pure).
// One filled span per pixel column (see draw_kit.h — gap-free via columnMinMax).
for (int col = 0; col < innerW; ++col) {
const MinMax mm = columnMinMax(bins, innerW, col);
const int x = box.x + 2 + col;