validatePaperInk function

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

The Paper & ink rules (on top of the generic ones):

Implementation

List<GuardrailViolation> validatePaperInk(
  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 opaque = ((k.edge >>> 24) & 0xFF) == 255;
    final r = opaque ? _minContrastOn(k.edge, bgs) : 1.0;
    if (r < ratioLarge) {
      out.add(
        GuardrailViolation(GuardrailRule.paperOutline, r, ratioLarge, name),
      );
    }
  }
  final width = spec.keyStyle.outlineWidthCdp;
  if (!paperInkOutlineWidthCdp.contains(width)) {
    out.add(
      GuardrailViolation(
        GuardrailRule.paperOutline,
        width / 100,
        paperInkOutlineWidthCdp.lo / 100,
        'outline width (dp)',
      ),
    );
  }

  if (spec.nonColourOperatorCue != OperatorCue.pattern) {
    out.add(
      const GuardrailViolation(GuardrailRule.paperOperatorCue, 0, 1, 'cue'),
    );
  }
  final shade = spec.keyStyle.edgeShadePermille;
  if (!paperInkHatchPermille.contains(shade)) {
    out.add(
      GuardrailViolation(
        GuardrailRule.paperOperatorCue,
        shade / 1000,
        paperInkHatchPermille.lo / 1000,
        'hatch opacity',
      ),
    );
  }
  final hatch = paperHatchContrast(p.operator, shade);
  if (hatch < paperHatchRatio) {
    out.add(
      GuardrailViolation(
        GuardrailRule.paperOperatorCue,
        hatch,
        paperHatchRatio,
        'hatch contrast',
      ),
    );
  }
  final bonus = spec.type.operatorWeight - spec.type.keyWeight;
  if (bonus < 200) {
    out.add(
      GuardrailViolation(
        GuardrailRule.paperOperatorCue,
        bonus.toDouble(),
        200,
        'operator weight bonus',
      ),
    );
  }

  final stamp = contrastRatio(p.equals.face, p.digit.face);
  if (stamp < paperStampRatio) {
    out.add(GuardrailViolation(GuardrailRule.paperStamp, stamp, 3));
  }

  final rimAlpha = (p.highlight >>> 24) & 0xFF;
  if (rimAlpha > paperWashRimMaxAlpha) {
    out.add(
      GuardrailViolation(
        GuardrailRule.paperWash,
        rimAlpha.toDouble(),
        paperWashRimMaxAlpha.toDouble(),
        'maximum alpha',
      ),
    );
  }
  final washed = paperWashLabelContrast(p, p.highlight);
  if (washed < lim.labelRatio) {
    out.add(
      GuardrailViolation(GuardrailRule.paperWash, washed, lim.labelRatio),
    );
  }
  return out;
}