separateGlassEquals function

KeyColors? separateGlassEquals(
  1. KeyColors eq,
  2. KeyColors op,
  3. KeyColors digit,
  4. GuardrailLimits lim,
  5. List<int> bgs,
)

Keeps the = glass apart from the operators over any two background samples (the generic equalsVsOperator rule compares every pair) and from the digit tint over the same sample (glassOperatorTint): when it is too close, its tint moves 0.06 at a time in lightness — away from the operator's first, then the other way — at an alpha of at least 230 (a denser jewel varies less across the mesh), re-solving the label each step. Null when no step works.

Implementation

KeyColors? separateGlassEquals(
  KeyColors eq,
  KeyColors op,
  KeyColors digit,
  GuardrailLimits lim,
  List<int> bgs,
) {
  final opLabs = [for (final s in faceSamples(op.face, bgs)) cvdLabs(s)];
  bool ok(KeyColors e) {
    if (glassTintDistance(e.face, digit.face, bgs) < lim.cvdDeltaE) {
      return false;
    }
    for (final s in faceSamples(e.face, bgs)) {
      final labs = cvdLabs(s);
      for (final o in opLabs) {
        if (minCvdDeltaELabs(labs, o) < lim.equalsVsOperatorDeltaE) {
          return false;
        }
      }
    }
    return true;
  }

  if (ok(eq)) return eq;
  final tint = argbToOklch(eq.face | 0xFF000000);
  final alpha = (eq.face >>> 24) & 0xFF;
  final label = argbToOklch(eq.label);
  final opL = argbToOklch(op.face | 0xFF000000).l;
  for (final up in [tint.l >= opL, tint.l < opL]) {
    var l = tint.l;
    for (var i = 0; i < 6; i++) {
      l = clamp01(l + (up ? 0.06 : -0.06));
      final k = solveGlassKey(
        tint: (l: l, c: tint.c, h: tint.h),
        alpha: alpha < 230 ? 230 : alpha,
        label: l < 0.62
            ? (l: 0.98, c: label.c, h: label.h)
            : (l: 0.18, c: label.c, h: label.h),
        bgs: bgs,
        target: lim.labelRatio,
        edge: eq.edge,
      );
      if (k != null && ok(k)) return k;
    }
  }
  return null;
}