billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=0eb223f1b81f929622b51bab427479c06260a407

commit 0eb223f1b81f929622b51bab427479c06260a407
Author: Boris Faure <bill...@gmail.com>
Date:   Sun Mar 11 19:51:11 2018 +0100

    termptyesc: approximate true color. Ref T746
---
 src/bin/termptyesc.c | 171 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 145 insertions(+), 26 deletions(-)

diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c
index 06c418b..a8c4f9e 100644
--- a/src/bin/termptyesc.c
+++ b/src/bin/termptyesc.c
@@ -491,6 +491,95 @@ _handle_esc_csi_reset_mode(Termpty *ty, Eina_Unicode cc, 
Eina_Unicode *b)
      }
 }
 
+static int
+_csi_truecolor_arg_get(Eina_Unicode **ptr)
+{
+   Eina_Unicode *b = *ptr;
+   int sum = 0;
+
+   if (!b)
+     goto error;
+
+   if ((*b == ';')  || (*b == ':'))
+     {
+        b++;
+        *ptr = b;
+        return 0;
+     }
+
+   if (!*b)
+     goto error;
+
+   while ((*b >= '0') && (*b <= '9'))
+     {
+        if (sum > INT32_MAX/10 )
+          goto error;
+        sum *= 10;
+        sum += *b - '0';
+        b++;
+     }
+
+   if ((*b == ';') || (*b == ':'))
+     b++;
+
+   *ptr = b;
+   return sum;
+
+error:
+   *ptr = NULL;
+   return -1;
+}
+
+
+static int
+_handle_esc_csi_truecolor(Termpty *ty EINA_UNUSED, Eina_Unicode **ptr)
+{
+   int r0, g0, b0;
+   int chosen_color = COL_DEF;
+   int c;
+   int distance_min = INT_MAX;
+   Evas_Object *textgrid;
+
+   r0 = _csi_truecolor_arg_get(ptr);
+   g0 = _csi_truecolor_arg_get(ptr);
+   b0 = _csi_truecolor_arg_get(ptr);
+
+   if ((r0 < 0) || (g0 < 0) || (b0 < 0))
+     return COL_DEF;
+
+   textgrid = termio_textgrid_get(ty->obj);
+   for (c = 0; c < 256; c++)
+     {
+        int r1 = 0, g1 = 0, b1 = 0, a1 = 0;
+        int delta_red_sq, delta_green_sq, delta_blue_sq, middle_red;
+        int distance;
+
+        evas_object_textgrid_palette_get(textgrid,
+                                         EVAS_TEXTGRID_PALETTE_EXTENDED,
+                                         c, &r1, &g1, &b1, &a1);
+        /* Compute the color distance
+         * XXX: this is inacurate but should give good enough results.
+         * See * https://en.wikipedia.org/wiki/Color_difference
+         */
+        middle_red = (r0 + r1) / 2;
+        delta_red_sq = (r0 - r1) * (r0 - r1);
+        delta_green_sq = (g0 - g1) * (g0 - g1);
+        delta_blue_sq = (b0 - b1) * (b0 - b1);
+
+        distance = 2 * delta_red_sq
+           + 4 * delta_green_sq
+           + 3 * delta_blue_sq
+           + ((middle_red) * (delta_red_sq - delta_blue_sq) / 256);
+        if (distance < distance_min)
+          {
+             distance_min = distance;
+             chosen_color = c;
+          }
+     }
+
+   return chosen_color;
+}
+
 static void
 _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr)
 {
@@ -586,21 +675,36 @@ _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr)
                    ty->termstate.att.fgintense = 0;
                    break;
                 case 38: // xterm 256 fg color ???
-                   // now check if next arg is 5
                    arg = _csi_arg_get(&b);
-                   if (arg != 5) ERR("Failed xterm 256 color fg esc 5 (got 
%d)", arg);
-                   else
+                   switch (arg)
                      {
-                        // then get next arg - should be color index 0-255
-                        arg = _csi_arg_get(&b);
-                        if (!b) ERR("Failed xterm 256 color fg esc val");
-                        else if (arg < 0 || arg > 255)
-                          ERR("Invalid fg color %d", arg);
-                        else
-                          {
-                             ty->termstate.att.fg256 = 1;
-                             ty->termstate.att.fg = arg;
-                          }
+                      case 2:
+                         ty->termstate.att.fg256 = 1;
+                         ty->termstate.att.fg =
+                            _handle_esc_csi_truecolor(ty, &b);
+                         DBG("truecolor fg: approximation got color %d",
+                             ty->termstate.att.fg);
+                         break;
+                      case 3:
+                         WRN("TODO: support colors in the Cyan-Magenta-Yellow 
colorspace");
+                         break;
+                      case 4:
+                         WRN("TODO: support colors in the 
Cyan-Magenta-Yellow-Black colorspace");
+                         break;
+                      case 5:
+                         // then get next arg - should be color index 0-255
+                         arg = _csi_arg_get(&b);
+                         if (!b) ERR("Failed xterm 256 color fg esc val");
+                         else if (arg < 0 || arg > 255)
+                           ERR("Invalid fg color %d", arg);
+                         else
+                           {
+                              ty->termstate.att.fg256 = 1;
+                              ty->termstate.att.fg = arg;
+                           }
+                         break;
+                      default:
+                         ERR("Failed xterm 256 color fg (got %d)", arg);
                      }
                    ty->termstate.att.fgintense = 0;
                    break;
@@ -622,21 +726,36 @@ _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr)
                    ty->termstate.att.bgintense = 0;
                    break;
                 case 48: // xterm 256 bg color ???
-                   // now check if next arg is 5
                    arg = _csi_arg_get(&b);
-                   if (arg != 5) ERR("Failed xterm 256 color bg esc 5 (got 
%d)", arg);
-                   else
+                   switch (arg)
                      {
-                        // then get next arg - should be color index 0-255
-                        arg = _csi_arg_get(&b);
-                        if (!b) ERR("Failed xterm 256 color bg esc val");
-                        else if (arg < 0 || arg > 255)
-                          ERR("Invalid bg color %d", arg);
-                        else
-                          {
-                             ty->termstate.att.bg256 = 1;
-                             ty->termstate.att.bg = arg;
-                          }
+                      case 2:
+                         ty->termstate.att.bg256 = 1;
+                         ty->termstate.att.bg =
+                            _handle_esc_csi_truecolor(ty, &b);
+                         DBG("truecolor bg: approximation got color %d",
+                             ty->termstate.att.bg);
+                         break;
+                      case 3:
+                         WRN("TODO: support colors in the Cyan-Magenta-Yellow 
colorspace");
+                         break;
+                      case 4:
+                         WRN("TODO: support colors in the 
Cyan-Magenta-Yellow-Black colorspace");
+                         break;
+                      case 5:
+                         // then get next arg - should be color index 0-255
+                         arg = _csi_arg_get(&b);
+                         if (!b) ERR("Failed xterm 256 color bg esc val");
+                         else if (arg < 0 || arg > 255)
+                           ERR("Invalid bg color %d", arg);
+                         else
+                           {
+                              ty->termstate.att.bg256 = 1;
+                              ty->termstate.att.bg = arg;
+                           }
+                         break;
+                      default:
+                         ERR("Failed xterm 256 color bg (got %d)", arg);
                      }
                    ty->termstate.att.bgintense = 0;
                    break;

-- 


Reply via email to