# Color encodings

The library at gr/color.fs defines color encoding as well as encoding/decoding
words for them.

At the moment, there's only one supported color encoding, so it has little logic.
It's mostly a placeholder for a fancier color management library.

## Bits layouts and endianness

The encoding defined here are "above" endianness. We refer to pure 32-bit
numbers (we don't support encodings above 32bit), regardless of encoding. When
we refer to bits in the memory layouts described below, we refer to the bits in
the "pure" number, bit 31 being the most significant bit and bit 0 being the
least significant bit.

We expect drivers dealing with those colors to be endianness aware and deal
with writing the correct color in the correct endianness themselves.

Let's use the example of the 24bpp VESA mode. Because it runs on a i386
architecture, it's always going to deal with little endian. So, if we say that
Red is b23:16, Green is b15:8 and Blue is b7:0, then we know that this means
that for a given address "a", Red is the byte at a+2, Green is at a+1 and Blue
is at a+0.

Let's imagine that we manage the same memory layout from a big endian
architecture. Then, the driver will have to deal with it. Either it's going to
specify that its supported color is another encoding (one that has RGB reversed)
or it takes care, when reading and writing those colors, to reverse those bytes.

## Color ID scheme

Color encoding constants are numerical IDs having a particular bitwise
organization:

b31:16 zeroes
b15:11 reserved
b10:8  depth index
b7:0   numerical ID

In short, a color ID is a 8-bit unique ID combined to a 3-bit depth index. The
depth index field has this meaning

000 1-bit
001 2-bit
010 4-bit
011 8-bit (palette)
100 8-bit (not palette)
101 16-bit
110 24-bit
111 32-bit

This depth index is used as a way to organize depth-dependent routine lists, so
it's exposed in the API.

The upper 16-bit are always zeroes and that's by design. We do this so that it's
possible to fit two color encodings in a single 32-bit number. This way, it's
possible to build lookup tables of color pairs.

## Color encoding list

PAL1   $000
  1-bit palette
PAL2   $100
  2-bit palette
PAL4   $200
  4-bit palette
PAL8   $300
  8-bit palette
RGB565 $500
  16-bit RGB encoding with Red=b15:11 Green=b10:5 Blue=b4:0
RGB555 $501
  16-bit RGB encoding with Red=b14:10 Green=b9:5 Blue=b4:0
RGB24  $600
  24-bit RGB encoding with Red=b23:16 Green=b15:8 Blue=b7:0
RGB32  $700
  32-bit RGB encoding with b31:24=0, Red=b23:16 Green=b15:8 Blue=b7:0

## API

colordepthidx ( id -- idx )
  Yields the depth index field of color encoding "id".

idx>bpp ( idx -- bpp )
  Returns the bpp (bits per plane) value for the given index.

colorbpp ( id -- bpp )
  Shortcut for "colordepthidx idx>bpp".

colorbytes ( id -- n )
  Shortcut for "colorbpp 8/".

rgbwhite
rgbblack
rgbred
rgbgreen
rgbblue
rgbyellow
rgbcyan
rgbmagenta ( -- r8 g8 b8 )
  Yield the R/G/B components at "maximum intensity" (either 0 or $ff) of each
  possible mix of R/G/B primary colors.

rgblighter
rgbdarker ( r8 g8 b8 n -- r8 g8 b8 )
  Add or subtract n to each color component, with 0/$ff min/max.

The words below all convert 3 8-bit RGB components into a specific encoding:

>rgb565 ( r8 g8 b8 -- n )
>rgb555 ( r8 g8 b8 -- n )
>rgb24  ( r8 g8 b8 -- n )

RGB24 and RGB32 only differ when they're packed next to each other. ">rgb24" can
be used for the RGB32 encoding.

>color ( r8 g8 b8 id -- n )
  Dynamically selects one of the encoders above depending on "id". Aborts if
  none is found.

And there are also faster re-encoding words that don't require splitting a color
in 3 components:

rgb24>rgb565 ( n -- n )
