On Thu, Jun 30, 2016 at 09:43:49PM +0800, Fengguang Wu <[email protected]> 
wrote:
> On Thu, Jun 30, 2016 at 02:34:41PM +0300, Emanuele Giaquinta wrote:
> > On Thu, Jun 23, 2016 at 08:28:46PM +0800, Fengguang Wu wrote:
> > > When the color cube slot is found to be already occupied by a similar
> > > 24-bit color, search through the -1, 0, +1 R/G/B indices trying to find
> > > an empty slot, or the oldest used one (which hopefully is no longer in
> > > active use).
> > > 
> > > This effectively reduces random collisions, hence make it pretty hard to
> > > hit a vim GUI color scheme that cannot be correctly showed in urxvt.
> > 
> > Applied without hashing and with some cleanups. Thanks again.
> 
> Thank you! I tried run it with the debug patch and it looks alright.

After playing around with it some more (and coming to the same
conclusion), I think going through all 26 neighbouring colours creates
colours that are too far off.

I have tuned it a bit, and got satisfactory results with the below code
(also in CVS) - this only visits the 6 nearest colours (+-1 in each
component), which is a compromise between being too far off and having some
replacement candidates.

As a side effect, it allows some code minor simplification, allows us to
visit the blue colours first, and of course can be much faster because it
only looks at 7 instead of 27 colours, not that any of it matters.

What do you think of this approach?

unsigned int
rxvt_term::map_rgb24_color (unsigned int r, unsigned int g, unsigned int b)
{
  r &= 0xff;
  g &= 0xff;
  b &= 0xff;

  unsigned int color = (r << 16) | (g << 8) | b;
  unsigned int idx_r = r / (0xff / (Red_levels - 1));
  unsigned int idx_g = g / (0xff / (Green_levels - 1));
  unsigned int idx_b = b / (0xff / (Blue_levels - 1));
  unsigned int idx = colorcube_index (idx_r, idx_g, idx_b);

  if (rgb24_color[idx] == color)
    return idx + minTermCOLOR24;

  /* we allow one of the 6 directly neighbouring colours */
  /* to replace the current color, if they not used recently */
  static const signed char dxyz[][3] = {
     0,  0,  0,
     0,  0, -1,
     0,  0, +1,
     0, -1,  0,
     0, +1,  0,
    -1,  0,  0,
    +1,  0,  0,
  };

  for (int n = 0; n < ecb_array_length (dxyz); ++n)
    {
      int i = idx_r + dxyz[n][0];
      int j = idx_r + dxyz[n][1];
      int k = idx_r + dxyz[n][2];

      if (!IN_RANGE_EXC (i, 0, Red_levels))
        continue;

      if (!IN_RANGE_EXC (j, 0, Green_levels))
        continue;

      if (!IN_RANGE_EXC (k, 0, Blue_levels))
        continue;

      unsigned int index = colorcube_index (i, j, k);

      // minor issue: could update index 0 few more times
      if ((rgb24_seqno[index] | rgb24_color[index]) == 0)
        {
          idx = index;
          goto update;
        }

      if (rgb24_color[index] == color)
        return index + minTermCOLOR24;

      // like (rgb24_seqno[idx] > rgb24_seqno[index])
      // but also handles wrap around values good enough
      if ((uint16_t)(rgb24_seqno[idx] - rgb24_seqno[index]) < 0x7fff)
        idx = index;
    }

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      [email protected]
      -=====/_/_//_/\_,_/ /_/\_\

_______________________________________________
rxvt-unicode mailing list
[email protected]
http://lists.schmorp.de/mailman/listinfo/rxvt-unicode

Reply via email to