Skip to content

[major] feat(color)!: migrate ThemeProvider to ktsu.Semantics.Color (gamma fix)#29

Merged
matt-edmondson merged 5 commits into
mainfrom
feat/semantics-color-migration
Jun 30, 2026
Merged

[major] feat(color)!: migrate ThemeProvider to ktsu.Semantics.Color (gamma fix)#29
matt-edmondson merged 5 commits into
mainfrom
feat/semantics-color-migration

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Summary

Migrates ktsu.ThemeProvider off its in-house color types onto the new ktsu.Semantics.Color package (2.3.0), and fixes a long-standing sRGB-as-linear gamma bug in the process. Breaking change → major version bump ([major]).

The public currency type PerceptualColor becomes ktsu.Semantics.Color.Color (linear RGB + alpha) across ISemanticTheme, SemanticColorMapper, the 38 themes, and ImGuiPaletteMapper.

The gamma fix

ThemeProvider previously loaded sRGB hex bytes as if they were linear (no decode) and fed them straight into the Oklab matrix and WCAG luminance. Now hex is parsed with Color.FromHex (correct sRGB→linear) and emitted to ImGui via ToSrgbVector4():

  • Base theme colors render identically (hex→linear→sRGB round-trips — pinned by a new round-trip test).
  • The semantic mapper's derived colors and accessibility/contrast numbers are now computed correctly (the intended behavior change).

What changed (5 commits)

  1. Core library — deleted RgbColor/SRgbColor/OklabColor/PerceptualColor/ColorMath/AccessibilityLevel; rewrote SemanticColorMapper + ColorRange onto Color (algorithm preserved verbatim — gamut chroma search, lightness bucketing, interpolation — only the color primitives swapped; Oklab-L precomputed in hot loops); migrated 38 themes (PerceptualColor.FromRgbColor.FromHex).
  2. ThemeProvider.ImGuiImGuiPaletteMapper emits color.ToSrgbVector4() (consumer-side gamma fix).
  3. Demo — migrated; 13 unsafe != default "not-found" sentinels replaced with a Color? return + is { } color pattern.
  4. Tests (new project — the repo had none) — 15 tests: base-color round-trip invariant (display stability), semantic-mapper in-gamut + lightness-ordering sanity, accessibility (black/white contrast = 21, AdjustForContrast reaches AA).
  5. ApiCompat baseline regen + docs (README/CLAUDE) + [major].

Verification

  • Local builds were green across all target frameworks at each step (net8/9/10 + netstandard2.0/2.1, plus the inherited net5/6/7); dotnet build ThemeProvider.sln clean; 15/15 tests pass. CI on this PR is the authoritative full-branch build+test.
  • Built task-by-task with per-task review; the core library migration (commit 29379bd) had a full review confirming the gamma rule is clean and the SemanticColorMapper algorithm is preserved line-by-line against the original.

Notes / follow-ups

  • ApiCompat: the CompatibilitySuppressions.xml baselines were regenerated for the major break (removed public types). Package-validation/pack runs in CI on merge — if it flags the removed types, the baseline may need a follow-up regeneration with -p:GenerateCompatibilitySuppressionFile=true.
  • Pre-existing minor (predates this PR): an unused priorityLevels local in SemanticColorMapper.
  • Next in the consolidation: migrate ktsu.ImGui.Styler (ImGuiApp) to route its ImColor output through ktsu.ImGui.Color + this updated ThemeProvider, once both publish.

🤖 Generated with Claude Code

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
10.2% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@matt-edmondson matt-edmondson merged commit 289d0d6 into main Jun 30, 2026
4 of 5 checks passed
@matt-edmondson matt-edmondson deleted the feat/semantics-color-migration branch June 30, 2026 09:39
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