fix: close five Θ-W6-T1 review minors — headroom figure, knob-face radius, degenerate band clamp
Aligns inKnobFace's hit radius with computeKnob's draw-side min(w,h) rule and adds a non-square-rect test; clamps halfSpan for degenerate waveform bands with a test; fixes stale docs/comments and annotates an uncommitted perf measurement.
This commit is contained in:
@@ -197,7 +197,9 @@ static void testWaveformColumnCount() {
|
||||
// The regression this exists to catch: rounding applied to the resulting y instead of to the
|
||||
// scaled amplitude draws a symmetric column one pixel taller above the zero line than below.
|
||||
static void testSymmetricColumnDrawsEqualHeightAboveAndBelowTheZeroLine() {
|
||||
const WaveformBand band = waveformBand(0, 41); // odd height -> fractional half-span
|
||||
// Odd height so midY sits equidistant from lo/hi — the fractional half-span below comes
|
||||
// from the amplitude product, not the height's parity.
|
||||
const WaveformBand band = waveformBand(0, 41);
|
||||
// Sweep amplitudes whose scaled value is fractional, which is where the two edges can
|
||||
// round in opposite directions.
|
||||
for (int i = 1; i <= 20; ++i) {
|
||||
@@ -256,6 +258,18 @@ static void testBandMetricsMirrorTheDrawnInset() {
|
||||
CHECK(b.halfSpan == 18.0); // half the band, less the 2px breathing room
|
||||
}
|
||||
|
||||
// A band too short for the 2px breathing room (height <= 4, so height/2 - 2 <= 0) must clamp
|
||||
// halfSpan to 0 rather than go negative and mirror every positive column below the zero line.
|
||||
static void testDegenerateBandClampsHalfSpanToZero() {
|
||||
CHECK(waveformBand(0, 4).halfSpan == 0.0);
|
||||
CHECK(waveformBand(0, 3).halfSpan == 0.0);
|
||||
CHECK(waveformBand(0, 0).halfSpan == 0.0);
|
||||
// A zero half-span collapses every column onto the zero line regardless of amplitude sign.
|
||||
const WaveformBand b = waveformBand(10, 4);
|
||||
const WaveformColumnSpan s = waveformColumnSpan(b, 1.0, -1.0);
|
||||
CHECK(s.top == b.midY && s.bottom == b.midY);
|
||||
}
|
||||
|
||||
int main() {
|
||||
testHitTestBoxHalfOpen();
|
||||
testButtonBoxInset();
|
||||
@@ -279,6 +293,7 @@ int main() {
|
||||
testTallerAmplitudeNeverDrawsAShorterColumn();
|
||||
testBothEdgesAndTheStrokeClampToTheBand();
|
||||
testBandMetricsMirrorTheDrawnInset();
|
||||
testDegenerateBandClampsHalfSpanToZero();
|
||||
|
||||
if (g_fail == 0) std::printf("component_geometry: all tests passed\n");
|
||||
else std::printf("component_geometry: %d CHECK(s) FAILED\n", g_fail);
|
||||
|
||||
@@ -382,6 +382,27 @@ static void testKnobFaceResolvesInnerRingOuterRingAndMisses() {
|
||||
CHECK(hitTestKnobFace(dl, cx + diag, cy + diag).id == -1);
|
||||
}
|
||||
|
||||
// A non-square knob rect (e.g. a squashed chrome row clamps knob height below its width) must
|
||||
// resolve against min(width, height)/2 — the same radius computeKnob draws — never against
|
||||
// width alone, or the hit disc would claim territory above/below where nothing is drawn.
|
||||
static void testInKnobFaceUsesTheSmallerDimensionOnANonSquareRect() {
|
||||
const Rect wide{0, 0, 40, 20}; // width > height: draws a 10px-radius disc, not 20px
|
||||
const int cx = wide.x + wide.width / 2;
|
||||
const int cy = wide.y + wide.height / 2;
|
||||
CHECK(inKnobFace(wide, cx, cy)); // dead centre always hits
|
||||
CHECK(inKnobFace(wide, cx, cy + 9)); // just inside the drawn (height-limited) radius
|
||||
CHECK(!inKnobFace(wide, cx, cy + 10)); // on the drawn rim: exclusive miss
|
||||
CHECK(!inKnobFace(wide, cx, cy + 15)); // inside the RECT but outside the smaller-radius disc
|
||||
CHECK(!inKnobFace(wide, cx + 15, cy)); // same check along the wider axis
|
||||
|
||||
const Rect tall{0, 0, 20, 40}; // height > width: draws a 10px-radius disc, not 20px
|
||||
const int tcx = tall.x + tall.width / 2;
|
||||
const int tcy = tall.y + tall.height / 2;
|
||||
CHECK(inKnobFace(tall, tcx, tcy));
|
||||
CHECK(!inKnobFace(tall, tcx + 15, tcy));
|
||||
CHECK(!inKnobFace(tall, tcx, tcy + 15));
|
||||
}
|
||||
|
||||
static void testEmptyDeck() {
|
||||
const std::vector<DeckGroupDesc> none;
|
||||
CHECK(deckRowCount(none, 800) == 0);
|
||||
@@ -401,6 +422,7 @@ int main() {
|
||||
testCaptionRadioGeometryAndHit();
|
||||
testInnerDialHit();
|
||||
testKnobFaceResolvesInnerRingOuterRingAndMisses();
|
||||
testInKnobFaceUsesTheSmallerDimensionOnANonSquareRect();
|
||||
testCaptionToggle2();
|
||||
testEmptyDeck();
|
||||
if (g_fail) {
|
||||
|
||||
Reference in New Issue
Block a user