opacity method
This colour at amount strength over over — the fade ANSI has no code
for, worked out in advance.
A colour code carries three channels and no alpha, so nothing in the escape sequence can ask for half-strength text. AsciiStyledString.dim is the only code that gestures at it and most terminals ignore it. Mixing the two colours here gives the same look and always renders — the price is that you have to name the background being mixed into, because nothing can ask the terminal what its background really is.
// a red that has faded halfway into a near-black terminal
'09'.foreground(const AsciiColour.rgb(5, 0, 0).opacity(0.5));
// over something else
'watermark'.foreground(
colours.high_white.opacity(0.15, over: const AsciiColourRgb.hex(0x1E1E1E)),
);
1 is the colour untouched and 0 is the background, which paints
text that is there but invisible. The result is 24-bit, so a terminal
stuck on the 256-colour table will approximate it or drop it.
Implementation
AsciiColourRgb opacity(
double amount, {
AsciiInk over = const AsciiColourRgb(0, 0, 0),
}) {
assert(amount >= 0 && amount <= 1, 'amount must be 0-1');
final AsciiColourRgb front = toRgb();
final AsciiColourRgb back = over.toRgb();
int mix(int f, int b) => ((f * amount) + (b * (1 - amount))).round();
return AsciiColourRgb(
mix(front.red, back.red),
mix(front.green, back.green),
mix(front.blue, back.blue),
);
}