From b41c023c61950d9b943b23f8deb9fcac185bc6f5 Mon Sep 17 00:00:00 2001
From: LS <lyubomir.savekov@engview.com>
Date: Wed, 6 Nov 2019 14:49:55 +0200
Subject: [PATCH 3/8] -Fixed color encoding and decoding for ENC. -Replaced the
 code for reading color and color attributes for entities with the original
 intention of bit_read_ENC.  (This was doing additional reading operation from
 the data stream, which was making further reading attempts produce garbage
 values). -Writing to DXF(and DXB) now adds alpha channel information, if
 available.

---
 src/bits.c                  | 67 ++++++++++++++--------------
 src/common_entity_data.spec | 87 +------------------------------------
 src/encode.c                |  1 +
 src/out_dxf.c               | 26 +++++++++++
 src/out_dxfb.c              | 26 +++++++++++
 src/out_geojson.c           |  1 +
 src/out_json.c              |  1 +
 7 files changed, 91 insertions(+), 118 deletions(-)

diff --git a/src/bits.c b/src/bits.c
index 7d7c4f12..7d714ddd 100644
--- a/src/bits.c
+++ b/src/bits.c
@@ -1786,27 +1786,30 @@ void
 bit_read_ENC (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat,
               Dwg_Color *restrict color)
 {
-  color->index = bit_read_BS (dat);
+  color->index = bit_read_BS(dat);
   if (dat->version >= R_2004)
-    {
-      uint16_t flag = (((uint32_t)color->index) >> 8) & 0xff;
-      color->index &= 0x1ff;
-      if (flag & 0x80)
-        color->rgb = bit_read_BL (dat); // ODA bug, documented as BS
-      if (flag & 0x40)
-        {
-          color->handle = calloc (1, sizeof (Dwg_Object_Ref));
-          bit_read_H (hdl_dat, &(color->handle->handleref)); // => DBCOLOR
-          // else defer to dwg_decode_common_entity_handle_data ()
-        }
-      if (flag & 0x20)
-        {
-          BITCODE_BL alpha = bit_read_BL (dat);
-          color->alpha_type = alpha & 0xff; // 0, 1 or 3
-          color->alpha = alpha >> 8;
-        }
-      color->flag = (uint16_t)flag;
-    }
+  {
+    color->flag = color->index >> 8;
+    if (color->flag & 0x20)
+    {
+      BITCODE_BL alpha = bit_read_BL(dat);
+      color->alpha_type = alpha >> 24; //0, 1 or 3
+      color->alpha = alpha & 0xFF;
+    }
+    if (color->flag & 0x40)
+    { //This means that color will be found in the 'Common Entity Handle Data', which comes right after the entity's own data
+      //The handle will be put in color_handle and not in color->handle
+      //There is nothing to do right now.
+    }
+		else if (color->flag & 0x80)
+		{
+      color->rgb = bit_read_BL(dat); //ODA bug, documented as BS
+			color->rgb &= 0xFFFFFF;
+		}
+
+    if(color->flag & (0x20 | 0x40 | 0x80))
+			color->index &= 0xFF;
+  }
 }
 
 /** Write entity color (2004+)
@@ -1817,20 +1820,20 @@ bit_write_ENC (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat,
 {
   bit_write_BS (dat, (color->index & 0x1ff) | (color->flag << 8));
   if (dat->version >= R_2004)
+  {
+    uint16_t flag = color->flag;
+    if (flag & 0x20)
     {
-      uint16_t flag = color->flag;
-      if (flag & 0x20)
-        bit_write_BL (dat, color->alpha);
-      if (!(flag & 0x40) && (flag & 0x80))
-        bit_write_BL (dat, color->rgb);
-      // ?? wide?
-      if ((flag & 0x41) == 0x41)
-        bit_write_T (str_dat, color->name);
-      if ((flag & 0x42) == 0x42)
-        bit_write_T (str_dat, color->book_name);
-      if (flag & 0x40)
-        bit_write_H (hdl_dat, &(color->handle->handleref)); // => DBCOLOR
+      BITCODE_BL alpha = (color->alpha_type << 24) | color->alpha;
+      bit_write_BL(dat, alpha);
     }
+    if (!(flag & 0x40) && (flag & 0x80))
+      bit_write_BL(dat, color->rgb);
+    if ((flag & 0x41) == 0x41)
+      bit_write_TV(dat, color->name); //str_dat
+      if ((flag & 0x42) == 0x42)
+      bit_write_TV(dat, color->book_name); //str_dat
+  }
 }
 
 /** Search for a sentinel; if found, positions "dat->byte" immediately after it
diff --git a/src/common_entity_data.spec b/src/common_entity_data.spec
index dda595ee..fe346983 100644
--- a/src/common_entity_data.spec
+++ b/src/common_entity_data.spec
@@ -81,93 +81,8 @@
   // TODO:
   // group 92 num_proxydata
   // group 310 proxydata
-  // color as FIELD_ENC (DXF, ENCODE)
 
-  SINCE(R_2004) // ENC (entity color encoding)
-    {
-#if 0 /* FIXME */
-      //FIELD_CMC(color, 62,420);
-      FIELD_ENC(color,62,420); // in ODA as CMC(B)
-#else
-      BITCODE_BS flags;
-      FIELD_BSx (color.flag, 0);
-      flags = ent->color.flag >> 8;
-      DECODER {
-        ent->color.rgb = 0L;
-        ent->color.index = ent->color.flag & 0x1ff; // or 0xff?
-        ent->color.flag = flags;
-        LOG_HANDLE(" color.index: %d [ENC 62]\n", ent->color.index);
-      }
-      DXF {
-        // 0: byblock
-        if (FIELD_VALUE(color.index) != 256) // not bylayer
-          FIELD_BS (color.index, 62);
-      }
-
-      if (flags & 0x40 && dat->version < R_2007)
-        { // r2004+ in handle stream
-          FIELD_HANDLE(color.handle, 0, 430); // DBCOLOR 1E9F74 => 1F05B9
-        }
-      if (flags & 0x20)
-        {
-          int type;
-          BITCODE_BL alpha;
-#ifndef IS_DXF
-          FIELD_BL (color.alpha, 0);
-#endif
-          /* 0 BYLAYER, 1 BYBLOCK, 3 alpha */
-          ent->color.alpha_type = ent->color.alpha & 0xff;
-          alpha = ent->color.alpha >> 8;
-          //LOG_HANDLE("alpha: %06x [BL 0]\n", ent->color.alpha);
-#ifdef IS_DECODER
-          LOG_TRACE(" color.alpha_type: %d\n", ent->color.alpha_type);
-#endif
-          if (ent->color.alpha_type == 3) {
-#ifdef IS_ENCODER
-            DXF { FIELD_BL (color.alpha >> 8, 430); }
-#else
-            DXF { FIELD_BL (color.alpha, 430); }
-#endif
-            //else LOG_TRACE("color.alpha: %d [ENC 430]\n", ent->color.alpha >> 8);
-          }
-        }
-      if (flags & 0x80 && !(flags & 0x40)) // and not a reference
-        {
-          int type;
-          FIELD_BL (color.rgb, 0); //ODA bug, documented as BS
-          type = ent->color.rgb & 0xff;
-#ifdef IS_DECODER
-          LOG_TRACE("color.rgb: %06x [ENC.BL 420] (%d)\n", (unsigned)ent->color.rgb,
-                    (int32_t)(ent->color.rgb & 0x00ffffff));
-#elif defined(IS_ENCODER) && defined(IS_DXF)
-          DXF { FIELD_BL (color.rgb, 420); }
-#elif defined(IS_DXF)
-          DXF { FIELD_BL (color.rgb & 0x00ffffff, 420); }
-#endif
-        }
-      /* not with entities, only with CMC or dbcolor handle */
-      if ((flags & 0x41) == 0x41)
-        {
-          FIELD_TV (color.name, 430);
-          //ent->color.name = bit_read_TV(dat);
-          //LOG_TRACE("color.name: %s [ENC.TV 430]\n", ent->color.name);
-        }
-      if ((flags & 0x42) == 0x42)
-        {
-          FIELD_TV (color.book_name, 430);
-          //ent->color.book_name = bit_read_TV(dat);
-          //LOG_TRACE("color.book_name: %s [ENC.TV 430]\n", ent->color.book_name);
-        }
-#if !defined(IS_DECODER) && !defined(IS_FREE)
-      if (!(flags & 0xf0))
-        {
-          LOG_TRACE("color.index: %u [ENC 62]\n", (unsigned)ent->color.index);
-        }
-#endif
-#endif
-    }
-  OTHER_VERSIONS
-    FIELD_CMC(color, 62,420);
+  FIELD_ENC(color, 62, 420); // ODA BUG, documented as CMC(B)
 
   DXF {
     if (FIELD_VALUE(ltype_scale) != 1.0)
diff --git a/src/encode.c b/src/encode.c
index 3084e2e8..378a46b6 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -248,6 +248,7 @@ static bool env_var_checked_p;
   }
 
 #define SUB_FIELD_CMC(o, nam, dxf1, dxf2) bit_write_CMC (dat, &_obj->o.nam)
+#define FIELD_ENC(nam, dxf1, dxf2) bit_write_ENC(dat, 0, 0, &_obj->nam)
 
 #define FIELD_BE(nam, dxf)                                                    \
   bit_write_BE (dat, FIELD_VALUE (nam.x), FIELD_VALUE (nam.y),                \
diff --git a/src/out_dxf.c b/src/out_dxf.c
index 8873372d..5adce060 100644
--- a/src/out_dxf.c
+++ b/src/out_dxf.c
@@ -489,6 +489,32 @@ dxf_print_rd (Bit_Chain *dat, BITCODE_RD value, int dxf)
         VALUE_RL(_obj->o.color.rgb, dxf2);                                    \
       }                                                                       \
   }
+#define FIELD_ENC(color,dxf1,dxf2)                                            \
+  {                                                                           \
+    if (_obj->color.index != 256)                                             \
+      {                                                                       \
+        VALUE_RS(_obj->color.index, dxf1);                                    \
+      }                                                                       \
+    if (dat->version >= R_2004)                                               \
+      {                                                                       \
+        if (dxf2 > 0 && _obj->color.rgb != 0)                                 \
+          {                                                                   \
+            VALUE_RL(_obj->color.rgb, dxf2);                                  \
+          }                                                                   \
+        if (_obj->color.name != 0)                                            \
+          {                                                                   \
+            VALUE_TV(_obj->color.name, 430)                                   \
+          }                                                                   \
+        else if (_obj->color.book_name != 0)                                  \
+          {                                                                   \
+            VALUE_TV(_obj->color.book_name, 430)                              \
+          }                                                                   \
+        if (_obj->color.alpha_type != 0 || _obj->color.alpha != 0)            \
+          {                                                                   \
+            VALUE_BL(((_obj->color.alpha_type<<24)|_obj->color.alpha), 440)   \
+          }                                                                   \
+      }                                                                       \
+  }
 #define HEADER_TIMEBLL(nam, dxf)                                              \
   HEADER_9 (nam);                                                             \
   FIELD_TIMEBLL (nam, dxf)
diff --git a/src/out_dxfb.c b/src/out_dxfb.c
index 82c12c7c..d60c2c11 100644
--- a/src/out_dxfb.c
+++ b/src/out_dxfb.c
@@ -420,6 +420,32 @@ static void dxfb_cvt_tablerecord (Bit_Chain *restrict dat,
         VALUE_RL(_obj->o.color.rgb, dxf2);                                    \
       }                                                                       \
   }
+#define FIELD_ENC(color,dxf1,dxf2)                                            \
+  {                                                                           \
+    if (_obj->color.index != 256)                                             \
+      {                                                                       \
+        VALUE_RS(_obj->color.index, dxf1);                                    \
+      }                                                                       \
+    if (dat->version >= R_2004)                                               \
+      {                                                                       \
+        if (dxf2 > 0 && _obj->color.rgb != 0)                                 \
+          {                                                                   \
+            VALUE_RL(_obj->color.rgb, dxf2);                                  \
+          }                                                                   \
+        if (_obj->color.name != 0)                                            \
+          {                                                                   \
+            VALUE_TV(_obj->color.name, 430)                                   \
+          }                                                                   \
+        else if (_obj->color.book_name != 0)                                  \
+          {                                                                   \
+            VALUE_TV(_obj->color.book_name, 430)                              \
+          }                                                                   \
+        if (_obj->color.alpha_type != 0 || _obj->color.alpha != 0)            \
+          {                                                                   \
+            VALUE_BL(((_obj->color.alpha_type<<24)|_obj->color.alpha), 440)   \
+          }                                                                   \
+      }                                                                       \
+  }
 #define HEADER_CMC(nam, dxf)                                                  \
   HEADER_9 (nam);                                                             \
   VALUE_RS (dwg->header_vars.nam.index, dxf)
diff --git a/src/out_geojson.c b/src/out_geojson.c
index 340ea45c..089beb69 100644
--- a/src/out_geojson.c
+++ b/src/out_geojson.c
@@ -250,6 +250,7 @@ static unsigned int cur_ver = 0;
   LASTVALUE_3DPOINT (_obj->name.x, _obj->name.y, _obj->name.z)
 #define FIELD_CMC(name, dxf1, dxf2)
 #define FIELD_TIMEBLL(name, dxf)
+#define FIELD_ENC(name, dxf1, dxf2)
 
 // FIELD_VECTOR_N(name, type, size):
 // reads data of the type indicated by 'type' 'size' times and stores
diff --git a/src/out_json.c b/src/out_json.c
index b43084e2..7d8cc46f 100644
--- a/src/out_json.c
+++ b/src/out_json.c
@@ -422,6 +422,7 @@ field_cmc (Bit_Chain *restrict dat, const char *restrict key,
 #define FIELD_CMC(color, dxf1, dxf2) field_cmc (dat, #color, &_obj->color)
 #define SUB_FIELD_CMC(o, color, dxf1, dxf2)                                   \
   field_cmc (dat, #color, &_obj->o.color)
+#define FIELD_ENC(color, dxf1, dxf2)
 
 #define FIELD_TIMEBLL(nam, dxf)                                               \
   PREFIX fprintf (dat->fh, "\"" #nam "\": " FORMAT_BL "." FORMAT_BL ",\n",    \
-- 
2.22.0.windows.1

