validateGlass function

List<GuardrailViolation> validateGlass(
  1. ThemeSpec spec,
  2. GuardrailLimits lim,
  3. List<int> bgs
)

The Liquid Glass rules (see the library docs); validateTheme adds them for the family. bgs are the background samples.

Implementation

List<GuardrailViolation> validateGlass(
  ThemeSpec spec,
  GuardrailLimits lim,
  List<int> bgs,
) {
  final p = spec.palette;
  final out = <GuardrailViolation>[];
  final groups = {
    'digit': p.digit,
    'operator': p.operator,
    'equals': p.equals,
    'function': p.function,
  };
  for (final MapEntry(key: name, value: k) in groups.entries) {
    final r = glassPressedLabelContrast(k, p.highlight, bgs);
    if (r < glassPressedLabelRatio) {
      out.add(
        GuardrailViolation(
          GuardrailRule.glassPressedLabel,
          r,
          glassPressedLabelRatio,
          name,
        ),
      );
    }
  }
  for (final (name, k) in [('operator', p.operator), ('equals', p.equals)]) {
    final d = glassTintDistance(k.face, p.digit.face, bgs);
    if (d < lim.cvdDeltaE) {
      out.add(
        GuardrailViolation(
          GuardrailRule.glassOperatorTint,
          d,
          lim.cvdDeltaE,
          name,
        ),
      );
    }
  }
  if (spec.accessible) {
    for (final MapEntry(key: name, value: k) in groups.entries) {
      final opaque = ((k.edge >>> 24) & 0xFF) == 255;
      final r = opaque ? _minOver(k.edge, bgs) : 1.0;
      if (r < ratioLarge) {
        out.add(
          GuardrailViolation(GuardrailRule.glassRim, r, ratioLarge, name),
        );
      }
    }
    if (spec.keyStyle.outlineWidthCdp < glassAccessibleRimMinCdp) {
      out.add(
        GuardrailViolation(
          GuardrailRule.glassRim,
          spec.keyStyle.outlineWidthCdp / 100,
          glassAccessibleRimMinCdp / 100,
          'rim width (dp)',
        ),
      );
    }
  }
  if (spec.nonColourOperatorCue == OperatorCue.weight) {
    final bonus = spec.type.operatorWeight - spec.type.keyWeight;
    if (bonus < 200) {
      out.add(
        GuardrailViolation(
          GuardrailRule.glassOperatorCue,
          bonus.toDouble(),
          200,
          'operator weight bonus',
        ),
      );
    }
  }
  return out;
}