Skip to content

fix(charts): anchor stacked bars at zero and guard paintForSeries#191

Merged
DemchaAV merged 2 commits into
developfrom
fix/v18-chart-stacked-floor
Jun 14, 2026
Merged

fix(charts): anchor stacked bars at zero and guard paintForSeries#191
DemchaAV merged 2 commits into
developfrom
fix/v18-chart-stacked-floor

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Why

Two chart-engine issues:

  1. Stacked bars are mis-anchored with a non-zero axis minimum. A stacked bar sums its segments up from a fixed floor, and each segment's height is value / range. An explicit valueAxis().min() moved the baseline off zero without rescaling the segments — a positive min made the stack overshoot its total (past the plot top), a negative min anchored it below zero (top undershoots).
  2. ChartStyle.paintForSeries leaks a bare IndexOutOfBoundsException on a negative index (the palette modulo gives a negative remainder).

What

  • ChartLayoutSupport.computeFrame pins the stacked floor to exactly zero (if (stacked && domain[0] != 0.0) domain[0] = 0.0), regardless of the requested min's sign. Grouped bars still honour an explicit minimum. Single-source — covers vertical and horizontal stacked via the shared Frame.
  • BarGrouping.STACKED Javadoc documents the always-zero baseline.
  • ChartStyle.paintForSeries rejects a negative index with IllegalArgumentException("series index must be >= 0: …").

Tests

  • ChartLayoutResolverTest: stacked + explicit positive min AND negative min — both assert the stack fills exactly to the value-total at the plot top (positive min overshot to ~135, negative undershot to ~75 before the fix).
  • ChartStyleTest (new): negative index rejected; valid index cycles the fallback palette.
  • Existing chart snapshots unchanged — the floor guard fires only for stacked + explicit non-zero min, which no existing chart uses. Full suite 1378 green.

Scope note

The plan's NumberFormatSpec DecimalFormat-caching item is not here: a bounded compile-path micro-opt (charts resolve once per layout, not a per-row hot path), ~11 call sites across 3 files for negligible gain. Deferred as an optional separate PR.

Lane: canonical charts (correctness; no perf-characteristic change, so no benchmark gate).

DemchaAV added 2 commits June 14, 2026 14:48
Stacked bars sum their segments up from a fixed floor, with each segment's
height measured from zero (value / range). An explicit positive
valueAxis().min() lifted the baseline without shrinking the segments, so the
stack overshot its total and ran past the plot top. Pin the stacked floor to
zero in ChartLayoutSupport.computeFrame, independent of the requested min;
grouped bars still honour an explicit minimum. Document the zero baseline on
BarGrouping.STACKED.

ChartStyle.paintForSeries now rejects a negative index with a value-naming
IllegalArgumentException instead of leaking a bare IndexOutOfBoundsException
from the palette modulo.

Tests: a stacked + positive-min case asserting the stack stays within the
plot, and paintForSeries negative-index + cycling cases. Existing chart
snapshots are unchanged (the floor guard fires only for stacked + positive
min, which no existing chart uses). Full suite green (1377).
The stacked zero-floor pin only fired for a positive valueAxis().min();
a negative explicit min still anchored the stack below zero, so its top
undershot the total. Pin the floor to exactly zero for any non-zero min,
and align the BarGrouping.STACKED Javadoc. Add a negative-min regression
case and tighten both stacked assertions to the exact plot-top fill.
@DemchaAV DemchaAV merged commit 0bca6ed into develop Jun 14, 2026
19 of 20 checks passed
@DemchaAV DemchaAV deleted the fix/v18-chart-stacked-floor branch June 14, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant