validateGlass function
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;
}