engine/contrast library
WCAG 2.2 contrast on 8-bit ARGB and OKLCH-lightness repair (research theme-engine.md §4, Recommendations 3–4).
Ratios are computed on the final quantised colour and are never rounded: 4.499:1 fails 4.5:1.
Classes
- ContrastPolicy
- Label-solving policy: floors plus the two WCAG-2 blind-spot heuristics (research §4.5). Immutable; configurable per family or Accessible lock.
Constants
- alwaysReachableRatio → const double
-
max(CR(bg, white), CR(bg, black)) ≥ √21for every background, so any target up to this is always reachable with black or white. - ratioAccessible → const double
- WCAG AAA text (Accessible lock).
- ratioLarge → const double
- WCAG AA large text / non-text (1.4.11).
- ratioText → const double
- WCAG AA text.
- yDarkFace → const double
- Faces darker than this are "dark faces" (≈ L_ok 0.37).
- yEqualContrast → const double
-
Luminance at which black and white give equal contrast:
sqrt(1.05 · 0.05) − 0.05. Below it, lighter labels win. - yPolarityBandTop → const double
- Upper edge of the mid-tone band where WCAG 2 over-rates dark labels (APCA's neutral polarity crossover, research §4.5).
Functions
-
blackOrWhite(
int bgArgb) → int -
Pure black or white, whichever contrasts more with
bgArgb. -
contrastOver(
int fg, int bg) → double -
Contrast of a possibly translucent
fgcomposited over opaquebg, againstbg. -
contrastRatio(
int a, int b) → double - Contrast ratio between two ARGB colours (alpha ignored).
-
contrastY(
double y1, double y2) → double -
Contrast ratio of two luminances,
(Y_lighter + 0.05) / (Y_darker + 0.05), in1, 21. -
luminanceArgb(
int argb) → double - WCAG relative luminance of an ARGB colour (alpha ignored; 0.04045 threshold via the decode table).
-
luminanceLin(
LinRgb c) → double - WCAG relative luminance of linear sRGB.
-
repairPair(
Lch face, Lch label, {ContrastPolicy policy = ContrastPolicy.standard}) → RepairedPair -
Repairs a label/face pair to
policy(research §4.3 repair order): -
solveForContrast(
double l0, double c, double hDeg, int bgArgb, double target) → int - solveLightness that throws when the target is unreachable.
-
solveLabel(
int faceArgb, Lch label, {ContrastPolicy policy = ContrastPolicy.standard}) → int? -
Solves a label (start colour
label) on the opaque facefaceArgbunderpolicy: dark-face boost, then the polarity rule, then the plain floor. Returns null only if even the floor is unreachable at this chroma/hue (possible above 4.583:1). -
solveLightness(
{required double l0, required double c, required double hDeg, required int againstArgb, required double target, bool? preferLighter, double? lighterFrom, double? darkerFrom}) → int? -
Bisects the OKLCH lightness of a colour with chroma
cand huehDeg, starting atl0, until its quantised ARGB reachestargetagainstagainstArgb. Returns null if neither direction can reach it.
Typedefs
- RepairedPair = ({int face, Lch faceLch, int label, int rounds})
- A repaired (face, label) pair.