opacity method

AsciiColourRgb opacity(
  1. double amount, {
  2. AsciiInk over = const AsciiColourRgb(0, 0, 0),
})

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),
  );
}