]> source.dussan.org Git - tigervnc.git/commitdiff
Use templates for optimized code
authorPierre Ossman <ossman@cendio.se>
Sat, 10 Sep 2022 11:48:53 +0000 (13:48 +0200)
committerPierre Ossman <ossman@cendio.se>
Wed, 1 Feb 2023 20:15:36 +0000 (21:15 +0100)
Avoid preprocessor magic and instead rely on templating to generate
optimized functions for performance critical code.

31 files changed:
common/rfb/EncodeManager.cxx
common/rfb/EncodeManager.h
common/rfb/EncodeManagerBPP.cxx [deleted file]
common/rfb/HextileDecoder.cxx
common/rfb/HextileDecoder.h
common/rfb/HextileEncoder.cxx
common/rfb/HextileEncoder.h
common/rfb/PixelFormat.cxx
common/rfb/PixelFormat.h
common/rfb/PixelFormatBPP.cxx [deleted file]
common/rfb/RREDecoder.cxx
common/rfb/RREDecoder.h
common/rfb/RREEncoder.cxx
common/rfb/RREEncoder.h
common/rfb/TightDecoder.cxx
common/rfb/TightDecoder.h
common/rfb/TightEncoder.cxx
common/rfb/TightEncoder.h
common/rfb/TightEncoderBPP.cxx [deleted file]
common/rfb/ZRLEDecoder.cxx
common/rfb/ZRLEDecoder.h
common/rfb/ZRLEEncoder.cxx
common/rfb/ZRLEEncoder.h
common/rfb/ZRLEEncoderBPP.cxx [deleted file]
common/rfb/hextileDecode.h [deleted file]
common/rfb/hextileEncode.h [deleted file]
common/rfb/hextileEncodeBetter.h [deleted file]
common/rfb/rreDecode.h [deleted file]
common/rfb/rreEncode.h [deleted file]
common/rfb/tightDecode.h [deleted file]
common/rfb/zrleDecode.h [deleted file]

index 6a78939ef3173d77e221436d8db7380df3eaae9a..0fd070e86fbf358c8b232f22aa42058121c72d95 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2014-2018 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * Copyright 2018 Peter Astrand for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
@@ -1065,14 +1065,78 @@ rdr::U8* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /
   throw rfb::Exception("Invalid write attempt to OffsetPixelBuffer");
 }
 
-// Preprocessor generated, optimised methods
-
-#define BPP 8
-#include "EncodeManagerBPP.cxx"
-#undef BPP
-#define BPP 16
-#include "EncodeManagerBPP.cxx"
-#undef BPP
-#define BPP 32
-#include "EncodeManagerBPP.cxx"
-#undef BPP
+template<class T>
+inline bool EncodeManager::checkSolidTile(const Rect& r,
+                                          const T colourValue,
+                                          const PixelBuffer *pb)
+{
+  int w, h;
+  const T* buffer;
+  int stride, pad;
+
+  w = r.width();
+  h = r.height();
+
+  buffer = (const T*)pb->getBuffer(r, &stride);
+  pad = stride - w;
+
+  while (h--) {
+    int w_ = w;
+    while (w_--) {
+      if (*buffer != colourValue)
+        return false;
+      buffer++;
+    }
+    buffer += pad;
+  }
+
+  return true;
+}
+
+template<class T>
+inline bool EncodeManager::analyseRect(int width, int height,
+                                       const T* buffer, int stride,
+                                       struct RectInfo *info, int maxColours)
+{
+  int pad;
+
+  T colour;
+  int count;
+
+  info->rleRuns = 0;
+  info->palette.clear();
+
+  pad = stride - width;
+
+  // For efficiency, we only update the palette on changes in colour
+  colour = buffer[0];
+  count = 0;
+  while (height--) {
+    int w_ = width;
+    while (w_--) {
+      if (*buffer != colour) {
+        if (!info->palette.insert(colour, count))
+          return false;
+        if (info->palette.size() > maxColours)
+          return false;
+
+        // FIXME: This doesn't account for switching lines
+        info->rleRuns++;
+
+        colour = *buffer;
+        count = 0;
+      }
+      buffer++;
+      count++;
+    }
+    buffer += pad;
+  }
+
+  // Make sure the final pixels also get counted
+  if (!info->palette.insert(colour, count))
+    return false;
+  if (info->palette.size() > maxColours)
+    return false;
+
+  return true;
+}
index f8201c34623b4c7525de441c0c22bb24a4399ccd..fc2b97d2970d4f7efab683763bcae11fd7488fe7 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2014-2018 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -97,22 +97,13 @@ namespace rfb {
                      struct RectInfo *info, int maxColours);
 
   protected:
-    // Preprocessor generated, optimised methods
-    inline bool checkSolidTile(const Rect& r, rdr::U8 colourValue,
+    // Templated, optimised methods
+    template<class T>
+    inline bool checkSolidTile(const Rect& r, const T,
                                const PixelBuffer *pb);
-    inline bool checkSolidTile(const Rect& r, rdr::U16 colourValue,
-                               const PixelBuffer *pb);
-    inline bool checkSolidTile(const Rect& r, rdr::U32 colourValue,
-                               const PixelBuffer *pb);
-
-    inline bool analyseRect(int width, int height,
-                            const rdr::U8* buffer, int stride,
-                            struct RectInfo *info, int maxColours);
-    inline bool analyseRect(int width, int height,
-                            const rdr::U16* buffer, int stride,
-                            struct RectInfo *info, int maxColours);
+    template<class T>
     inline bool analyseRect(int width, int height,
-                            const rdr::U32* buffer, int stride,
+                            const T* buffer, int stride,
                             struct RectInfo *info, int maxColours);
 
   protected:
diff --git a/common/rfb/EncodeManagerBPP.cxx b/common/rfb/EncodeManagerBPP.cxx
deleted file mode 100644 (file)
index 0361291..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
- * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-
-#define UBPP CONCAT2E(U,BPP)
-
-inline bool EncodeManager::checkSolidTile(const Rect& r,
-                                          rdr::UBPP colourValue,
-                                          const PixelBuffer *pb)
-{
-  int w, h;
-  const rdr::UBPP* buffer;
-  int stride, pad;
-
-  w = r.width();
-  h = r.height();
-
-  buffer = (const rdr::UBPP*)pb->getBuffer(r, &stride);
-  pad = stride - w;
-
-  while (h--) {
-    int w_ = w;
-    while (w_--) {
-      if (*buffer != colourValue)
-        return false;
-      buffer++;
-    }
-    buffer += pad;
-  }
-
-  return true;
-}
-
-inline bool EncodeManager::analyseRect(int width, int height,
-                                       const rdr::UBPP* buffer, int stride,
-                                       struct RectInfo *info, int maxColours)
-{
-  int pad;
-
-  rdr::UBPP colour;
-  int count;
-
-  info->rleRuns = 0;
-  info->palette.clear();
-
-  pad = stride - width;
-
-  // For efficiency, we only update the palette on changes in colour
-  colour = buffer[0];
-  count = 0;
-  while (height--) {
-    int w_ = width;
-    while (w_--) {
-      if (*buffer != colour) {
-        if (!info->palette.insert(colour, count))
-          return false;
-        if (info->palette.size() > maxColours)
-          return false;
-
-        // FIXME: This doesn't account for switching lines
-        info->rleRuns++;
-
-        colour = *buffer;
-        count = 0;
-      }
-      buffer++;
-      count++;
-    }
-    buffer += pad;
-  }
-
-  // Make sure the final pixels also get counted
-  if (!info->palette.insert(colour, count))
-    return false;
-  if (info->palette.size() > maxColours)
-    return false;
-
-  return true;
-}
index 73655da08ed1b08af03e56bee5f883217ec9e1df..4275a0493234aa09981f1312535e9b2aeea28267 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <rdr/MemInStream.h>
 #include <rdr/OutStream.h>
 
+#include <rfb/Exception.h>
 #include <rfb/ServerParams.h>
 #include <rfb/PixelBuffer.h>
 #include <rfb/HextileDecoder.h>
+#include <rfb/hextileConstants.h>
 
 using namespace rfb;
 
-#define BPP 8
-#include <rfb/hextileDecode.h>
-#undef BPP
-#define BPP 16
-#include <rfb/hextileDecode.h>
-#undef BPP
-#define BPP 32
-#include <rfb/hextileDecode.h>
-#undef BPP
-
 HextileDecoder::HextileDecoder() : Decoder(DecoderPlain)
 {
 }
@@ -127,8 +120,87 @@ void HextileDecoder::decodeRect(const Rect& r, const void* buffer,
   rdr::MemInStream is(buffer, buflen);
   const PixelFormat& pf = server.pf();
   switch (pf.bpp) {
-  case 8:  hextileDecode8 (r, &is, pf, pb); break;
-  case 16: hextileDecode16(r, &is, pf, pb); break;
-  case 32: hextileDecode32(r, &is, pf, pb); break;
+  case 8:  hextileDecode<rdr::U8 >(r, &is, pf, pb); break;
+  case 16: hextileDecode<rdr::U16>(r, &is, pf, pb); break;
+  case 32: hextileDecode<rdr::U32>(r, &is, pf, pb); break;
+  }
+}
+
+template<class T>
+inline T HextileDecoder::readPixel(rdr::InStream* is)
+{
+  if (sizeof(T) == 1)
+    return is->readOpaque8();
+  if (sizeof(T) == 2)
+    return is->readOpaque16();
+  if (sizeof(T) == 4)
+    return is->readOpaque32();
+}
+
+template<class T>
+void HextileDecoder::hextileDecode(const Rect& r, rdr::InStream* is,
+                                   const PixelFormat& pf,
+                                   ModifiablePixelBuffer* pb)
+{
+  Rect t;
+  T bg = 0;
+  T fg = 0;
+  T buf[16 * 16];
+
+  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
+
+    t.br.y = __rfbmin(r.br.y, t.tl.y + 16);
+
+    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
+
+      t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
+
+      int tileType = is->readU8();
+
+      if (tileType & hextileRaw) {
+        is->readBytes(buf, t.area() * sizeof(T));
+        pb->imageRect(pf, t, buf);
+        continue;
+      }
+
+      if (tileType & hextileBgSpecified)
+        bg = readPixel<T>(is);
+
+      int len = t.area();
+      T* ptr = buf;
+      while (len-- > 0) *ptr++ = bg;
+
+      if (tileType & hextileFgSpecified)
+        fg = readPixel<T>(is);
+
+      if (tileType & hextileAnySubrects) {
+        int nSubrects = is->readU8();
+
+        for (int i = 0; i < nSubrects; i++) {
+
+          if (tileType & hextileSubrectsColoured)
+            fg = readPixel<T>(is);
+
+          int xy = is->readU8();
+          int wh = is->readU8();
+
+          int x = ((xy >> 4) & 15);
+          int y = (xy & 15);
+          int w = ((wh >> 4) & 15) + 1;
+          int h = (wh & 15) + 1;
+          if (x + w > 16 || y + h > 16) {
+            throw rfb::Exception("HEXTILE_DECODE: Hextile out of bounds");
+          }
+          T* ptr = buf + y * t.width() + x;
+          int rowAdd = t.width() - w;
+          while (h-- > 0) {
+            int len = w;
+            while (len-- > 0) *ptr++ = fg;
+            ptr += rowAdd;
+          }
+        }
+      }
+      pb->imageRect(pf, t, buf);
+    }
   }
 }
index 2c42be54b19f65af8c9b6648a37e4fc07c862046..e8961d731c409664198fc2b53ca298ca54aaf91a 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +23,8 @@
 
 namespace rfb {
 
+  class PixelFormat;
+
   class HextileDecoder : public Decoder {
   public:
     HextileDecoder();
@@ -31,6 +34,13 @@ namespace rfb {
     virtual void decodeRect(const Rect& r, const void* buffer,
                             size_t buflen, const ServerParams& server,
                             ModifiablePixelBuffer* pb);
+  private:
+    template<class T>
+    inline T readPixel(rdr::InStream* is);
+    template<class T>
+    void hextileDecode(const Rect& r, rdr::InStream* is,
+                       const PixelFormat& pf,
+                       ModifiablePixelBuffer* pb);
   };
 }
 #endif
index f9db06b827c37ad4c75ab3184423582e8a86006c..b2b0f3a4ac0752a8f3b6225dda7b83f127cafa88 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright (C) 2005 Constantin Kaplinsky.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <rfb/encodings.h>
 #include <rfb/SConnection.h>
 #include <rfb/HextileEncoder.h>
+#include <rfb/Palette.h>
 #include <rfb/PixelBuffer.h>
 #include <rfb/Configuration.h>
+#include <rfb/hextileConstants.h>
 
 using namespace rfb;
 
@@ -36,19 +38,6 @@ BoolParameter improvedHextile("ImprovedHextile",
                               "ratios by the cost of using more CPU time",
                               true);
 
-#define BPP 8
-#include <rfb/hextileEncode.h>
-#include <rfb/hextileEncodeBetter.h>
-#undef BPP
-#define BPP 16
-#include <rfb/hextileEncode.h>
-#include <rfb/hextileEncodeBetter.h>
-#undef BPP
-#define BPP 32
-#include <rfb/hextileEncode.h>
-#include <rfb/hextileEncodeBetter.h>
-#undef BPP
-
 HextileEncoder::HextileEncoder(SConnection* conn) :
   Encoder(conn, encodingHextile, EncoderPlain)
 {
@@ -70,23 +59,23 @@ void HextileEncoder::writeRect(const PixelBuffer* pb,
   switch (pb->getPF().bpp) {
   case 8:
     if (improvedHextile) {
-      hextileEncodeBetter8(os, pb);
+      hextileEncodeBetter<rdr::U8>(os, pb);
     } else {
-      hextileEncode8(os, pb);
+      hextileEncode<rdr::U8>(os, pb);
     }
     break;
   case 16:
     if (improvedHextile) {
-      hextileEncodeBetter16(os, pb);
+      hextileEncodeBetter<rdr::U16>(os, pb);
     } else {
-      hextileEncode16(os, pb);
+      hextileEncode<rdr::U16>(os, pb);
     }
     break;
   case 32:
     if (improvedHextile) {
-      hextileEncodeBetter32(os, pb);
+      hextileEncodeBetter<rdr::U32>(os, pb);
     } else {
-      hextileEncode32(os, pb);
+      hextileEncode<rdr::U32>(os, pb);
     }
     break;
   }
@@ -110,3 +99,496 @@ void HextileEncoder::writeSolidRect(int width, int height,
   while (tiles--)
       os->writeU8(0);
 }
+
+template<class T>
+inline void HextileEncoder::writePixel(rdr::OutStream* os, T pixel)
+{
+  if (sizeof(T) == 1)
+    os->writeOpaque8(pixel);
+  else if (sizeof(T) == 2)
+    os->writeOpaque16(pixel);
+  else if (sizeof(T) == 4)
+    os->writeOpaque32(pixel);
+}
+
+template<class T>
+void HextileEncoder::hextileEncode(rdr::OutStream* os,
+                                   const PixelBuffer* pb)
+{
+  Rect t;
+  T buf[256];
+  T oldBg = 0, oldFg = 0;
+  bool oldBgValid = false;
+  bool oldFgValid = false;
+  rdr::U8 encoded[256*sizeof(T)];
+
+  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
+
+    t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
+
+    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
+
+      t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
+
+      pb->getImage(buf, t);
+
+      T bg = 0, fg = 0;
+      int tileType = testTileType(buf, t.width(), t.height(), &bg, &fg);
+
+      if (!oldBgValid || oldBg != bg) {
+        tileType |= hextileBgSpecified;
+        oldBg = bg;
+        oldBgValid = true;
+      }
+
+      int encodedLen = 0;
+
+      if (tileType & hextileAnySubrects) {
+
+        if (tileType & hextileSubrectsColoured) {
+          oldFgValid = false;
+        } else {
+          if (!oldFgValid || oldFg != fg) {
+            tileType |= hextileFgSpecified;
+            oldFg = fg;
+            oldFgValid = true;
+          }
+        }
+
+        encodedLen = hextileEncodeTile(buf, t.width(), t.height(),
+                                       tileType, encoded, bg);
+
+        if (encodedLen < 0) {
+          pb->getImage(buf, t);
+          os->writeU8(hextileRaw);
+          os->writeBytes(buf, t.width() * t.height() * sizeof(T));
+          oldBgValid = oldFgValid = false;
+          continue;
+        }
+      }
+
+      os->writeU8(tileType);
+      if (tileType & hextileBgSpecified) writePixel(os, bg);
+      if (tileType & hextileFgSpecified) writePixel(os, fg);
+      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
+    }
+  }
+}
+
+template<class T>
+int HextileEncoder::hextileEncodeTile(T* data, int w, int h,
+                                      int tileType, rdr::U8* encoded,
+                                      T bg)
+{
+  rdr::U8* nSubrectsPtr = encoded;
+  *nSubrectsPtr = 0;
+  encoded++;
+
+  for (int y = 0; y < h; y++)
+  {
+    int x = 0;
+    while (x < w) {
+      if (*data == bg) {
+        x++;
+        data++;
+        continue;
+      }
+
+      // Find horizontal subrect first
+      T* ptr = data+1;
+      T* eol = data+w-x;
+      while (ptr < eol && *ptr == *data) ptr++;
+      int sw = ptr - data;
+
+      ptr = data + w;
+      int sh = 1;
+      while (sh < h-y) {
+        eol = ptr + sw;
+        while (ptr < eol)
+          if (*ptr++ != *data) goto endOfSubrect;
+        ptr += w - sw;
+        sh++;
+      }
+    endOfSubrect:
+
+      (*nSubrectsPtr)++;
+
+      if (tileType & hextileSubrectsColoured) {
+        if (encoded - nSubrectsPtr + sizeof(T) > w*h*sizeof(T))
+          return -1;
+
+        if (sizeof(T) == 1) {
+          *encoded++ = *data;
+        } else if (sizeof(T) == 2) {
+          *encoded++ = ((rdr::U8*)data)[0];
+          *encoded++ = ((rdr::U8*)data)[1];
+        } else if (sizeof(T) == 4) {
+          *encoded++ = ((rdr::U8*)data)[0];
+          *encoded++ = ((rdr::U8*)data)[1];
+          *encoded++ = ((rdr::U8*)data)[2];
+          *encoded++ = ((rdr::U8*)data)[3];
+        }
+      }
+
+      if ((size_t)(encoded - nSubrectsPtr + 2) > w*h*sizeof(T))
+        return -1;
+      *encoded++ = (x << 4) | y;
+      *encoded++ = ((sw-1) << 4) | (sh-1);
+
+      ptr = data+w;
+      T* eor = data+w*sh;
+      while (ptr < eor) {
+        eol = ptr + sw;
+        while (ptr < eol) *ptr++ = bg;
+        ptr += w - sw;
+      }
+      x += sw;
+      data += sw;
+    }
+  }
+  return encoded - nSubrectsPtr;
+}
+
+template<class T>
+int HextileEncoder::testTileType(T* data, int w, int h, T* bg, T* fg)
+{
+  T pix1 = *data;
+  T* end = data + w * h;
+
+  T* ptr = data + 1;
+  while (ptr < end && *ptr == pix1)
+    ptr++;
+
+  if (ptr == end) {
+    *bg = pix1;
+    return 0;                   // solid-color tile
+  }
+
+  int count1 = ptr - data;
+  int count2 = 1;
+  T pix2 = *ptr++;
+  int tileType = hextileAnySubrects;
+
+  for (; ptr < end; ptr++) {
+    if (*ptr == pix1) {
+      count1++;
+    } else if (*ptr == pix2) {
+      count2++;
+    } else {
+      tileType |= hextileSubrectsColoured;
+      break;
+    }
+  }
+
+  if (count1 >= count2) {
+    *bg = pix1; *fg = pix2;
+  } else {
+    *bg = pix2; *fg = pix1;
+  }
+  return tileType;
+}
+
+//
+// This class analyzes a separate tile and encodes its subrectangles.
+//
+
+template<class T>
+class HextileTile {
+
+ public:
+
+  HextileTile ();
+
+  //
+  // Initialize existing object instance with new tile data.
+  //
+  void newTile(const T *src, int w, int h);
+
+  //
+  // Flags can include: hextileRaw, hextileAnySubrects and
+  // hextileSubrectsColoured. Note that if hextileRaw is set, other
+  // flags make no sense. Also, hextileSubrectsColoured is meaningful
+  // only when hextileAnySubrects is set as well.
+  //
+  int getFlags() const { return m_flags; }
+
+  //
+  // Returns the size of encoded subrects data, including subrect count.
+  // The size is zero if flags do not include hextileAnySubrects.
+  //
+  size_t getSize() const { return m_size; }
+
+  //
+  // Return optimal background.
+  //
+  int getBackground() const { return m_background; }
+
+  //
+  // Return foreground if flags include hextileSubrectsColoured.
+  //
+  int getForeground() const { return m_foreground; }
+
+  //
+  // Encode subrects. This function may be called only if
+  // hextileAnySubrects bit is set in flags. The buffer size should be
+  // big enough to store at least the number of bytes returned by the
+  // getSize() method.
+  //
+  void encode(rdr::U8* dst) const;
+
+ protected:
+
+  //
+  // Analyze the tile pixels, fill in all the data fields.
+  //
+  void analyze();
+
+  const T *m_tile;
+  int m_width;
+  int m_height;
+
+  size_t m_size;
+  int m_flags;
+  T m_background;
+  T m_foreground;
+
+  int m_numSubrects;
+  rdr::U8 m_coords[256 * 2];
+  T m_colors[256];
+
+ private:
+
+  bool m_processed[16][16];
+  Palette m_pal;
+};
+
+template<class T>
+HextileTile<T>::HextileTile()
+  : m_tile(NULL), m_width(0), m_height(0),
+    m_size(0), m_flags(0), m_background(0), m_foreground(0),
+    m_numSubrects(0)
+{
+}
+
+template<class T>
+void HextileTile<T>::newTile(const T *src, int w, int h)
+{
+  m_tile = src;
+  m_width = w;
+  m_height = h;
+
+  analyze();
+}
+
+template<class T>
+void HextileTile<T>::analyze()
+{
+  assert(m_tile && m_width && m_height);
+
+  const T *ptr = m_tile;
+  const T *end = &m_tile[m_width * m_height];
+  T color = *ptr++;
+  while (ptr != end && *ptr == color)
+    ptr++;
+
+  // Handle solid tile
+  if (ptr == end) {
+    m_background = m_tile[0];
+    m_flags = 0;
+    m_size = 0;
+    return;
+  }
+
+  // Compute number of complete rows of the same color, at the top
+  int y = (ptr - m_tile) / m_width;
+
+  T *colorsPtr = m_colors;
+  rdr::U8 *coordsPtr = m_coords;
+  m_pal.clear();
+  m_numSubrects = 0;
+
+  // Have we found the first subrect already?
+  if (y > 0) {
+    *colorsPtr++ = color;
+    *coordsPtr++ = 0;
+    *coordsPtr++ = (rdr::U8)(((m_width - 1) << 4) | ((y - 1) & 0x0F));
+    m_pal.insert(color, 1);
+    m_numSubrects++;
+  }
+
+  memset(m_processed, 0, 16 * 16 * sizeof(bool));
+
+  int x, sx, sy, sw, sh, max_x;
+
+  for (; y < m_height; y++) {
+    for (x = 0; x < m_width; x++) {
+      // Skip pixels that were processed earlier
+      if (m_processed[y][x]) {
+        continue;
+      }
+      // Determine dimensions of the horizontal subrect
+      color = m_tile[y * m_width + x];
+      for (sx = x + 1; sx < m_width; sx++) {
+        if (m_tile[y * m_width + sx] != color)
+          break;
+      }
+      sw = sx - x;
+      max_x = sx;
+      for (sy = y + 1; sy < m_height; sy++) {
+        for (sx = x; sx < max_x; sx++) {
+          if (m_tile[sy * m_width + sx] != color)
+            goto done;
+        }
+      }
+    done:
+      sh = sy - y;
+
+      // Save properties of this subrect
+      *colorsPtr++ = color;
+      *coordsPtr++ = (rdr::U8)((x << 4) | (y & 0x0F));
+      *coordsPtr++ = (rdr::U8)(((sw - 1) << 4) | ((sh - 1) & 0x0F));
+
+      if (!m_pal.insert(color, 1) ||
+          ((size_t)m_pal.size() > (48 + 2 * sizeof(T)*8))) {
+        // Handle palette overflow
+        m_flags = hextileRaw;
+        m_size = 0;
+        return;
+      }
+
+      m_numSubrects++;
+
+      // Mark pixels of this subrect as processed, below this row
+      for (sy = y + 1; sy < y + sh; sy++) {
+        for (sx = x; sx < x + sw; sx++)
+          m_processed[sy][sx] = true;
+      }
+
+      // Skip processed pixels of this row
+      x += (sw - 1);
+    }
+  }
+
+  // Save number of colors in this tile (should be no less than 2)
+  int numColors = m_pal.size();
+  assert(numColors >= 2);
+
+  m_background = (T)m_pal.getColour(0);
+  m_flags = hextileAnySubrects;
+  int numSubrects = m_numSubrects - m_pal.getCount(0);
+
+  if (numColors == 2) {
+    // Monochrome tile
+    m_foreground = (T)m_pal.getColour(1);
+    m_size = 1 + 2 * numSubrects;
+  } else {
+    // Colored tile
+    m_flags |= hextileSubrectsColoured;
+    m_size = 1 + (2 + sizeof(T)) * numSubrects;
+  }
+}
+
+template<class T>
+void HextileTile<T>::encode(rdr::U8 *dst) const
+{
+  assert(m_numSubrects && (m_flags & hextileAnySubrects));
+
+  // Zero subrects counter
+  rdr::U8 *numSubrectsPtr = dst;
+  *dst++ = 0;
+
+  for (int i = 0; i < m_numSubrects; i++) {
+    if (m_colors[i] == m_background)
+      continue;
+
+    if (m_flags & hextileSubrectsColoured) {
+      if (sizeof(T) == 1) {
+        *dst++ = m_colors[i];
+      } else if (sizeof(T) == 2) {
+        *dst++ = ((rdr::U8*)&m_colors[i])[0];
+        *dst++ = ((rdr::U8*)&m_colors[i])[1];
+      } else if (sizeof(T) == 4) {
+        *dst++ = ((rdr::U8*)&m_colors[i])[0];
+        *dst++ = ((rdr::U8*)&m_colors[i])[1];
+        *dst++ = ((rdr::U8*)&m_colors[i])[2];
+        *dst++ = ((rdr::U8*)&m_colors[i])[3];
+      }
+    }
+    *dst++ = m_coords[i * 2];
+    *dst++ = m_coords[i * 2 + 1];
+
+    (*numSubrectsPtr)++;
+  }
+
+  assert((size_t)(dst - numSubrectsPtr) == m_size);
+}
+
+//
+// Main encoding function.
+//
+
+template<class T>
+void HextileEncoder::hextileEncodeBetter(rdr::OutStream* os,
+                                         const PixelBuffer* pb)
+{
+  Rect t;
+  T buf[256];
+  T oldBg = 0, oldFg = 0;
+  bool oldBgValid = false;
+  bool oldFgValid = false;
+  rdr::U8 encoded[256*sizeof(T)];
+
+  HextileTile<T> tile;
+
+  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
+
+    t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
+
+    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
+
+      t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
+
+      pb->getImage(buf, t);
+
+      tile.newTile(buf, t.width(), t.height());
+      int tileType = tile.getFlags();
+      size_t encodedLen = tile.getSize();
+
+      if ( (tileType & hextileRaw) != 0 ||
+           encodedLen >= t.width() * t.height() * sizeof(T)) {
+        os->writeU8(hextileRaw);
+        os->writeBytes(buf, t.width() * t.height() * sizeof(T));
+        oldBgValid = oldFgValid = false;
+        continue;
+      }
+
+      T bg = tile.getBackground();
+      T fg = 0;
+
+      if (!oldBgValid || oldBg != bg) {
+        tileType |= hextileBgSpecified;
+        oldBg = bg;
+        oldBgValid = true;
+      }
+
+      if (tileType & hextileAnySubrects) {
+        if (tileType & hextileSubrectsColoured) {
+          oldFgValid = false;
+        } else {
+          fg = tile.getForeground();
+          if (!oldFgValid || oldFg != fg) {
+            tileType |= hextileFgSpecified;
+            oldFg = fg;
+            oldFgValid = true;
+          }
+        }
+        tile.encode(encoded);
+      }
+
+      os->writeU8(tileType);
+      if (tileType & hextileBgSpecified) writePixel(os, bg);
+      if (tileType & hextileFgSpecified) writePixel(os, fg);
+      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
+    }
+  }
+}
index 393ab23b333584debc24619098ec4e4836899523..64cc0de3494b457ed7211cad0083a4b27b5c8f7d 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +32,20 @@ namespace rfb {
     virtual void writeSolidRect(int width, int height,
                                 const PixelFormat& pf,
                                 const rdr::U8* colour);
+  private:
+    template<class T>
+    inline void writePixel(rdr::OutStream* os, T pixel);
+
+    template<class T>
+    void hextileEncode(rdr::OutStream* os, const PixelBuffer* pb);
+    template<class T>
+    int hextileEncodeTile(T* data, int w, int h, int tileType,
+                          rdr::U8* encoded, T bg);
+    template<class T>
+    int testTileType(T* data, int w, int h, T* bg, T* fg);
+
+    template<class T>
+    void hextileEncodeBetter(rdr::OutStream* os, const PixelBuffer* pb);
   };
 }
 #endif
index 0abf53b61ad5407df8bb9889ece46c3a5a7113a3..5a3f01477dbe5a49d69fb637cd7dd337f9d3147b 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2009-2014 Pierre Ossman for Cendio AB
+ * Copyright 2009-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -710,41 +710,133 @@ bool PixelFormat::isSane(void)
   return true;
 }
 
-// Preprocessor generated, optimised methods
-
-#define INBPP 8
-#define OUTBPP 8
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 16
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 32
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#undef INBPP
-
-#define INBPP 16
-#define OUTBPP 8
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 16
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 32
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#undef INBPP
-
-#define INBPP 32
-#define OUTBPP 8
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 16
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#define OUTBPP 32
-#include "PixelFormatBPP.cxx"
-#undef OUTBPP
-#undef INBPP
+static inline uint8_t swap(uint8_t n)
+{
+  return n;
+}
+
+static inline uint16_t swap(uint16_t n)
+{
+  return (((n) & 0xff) << 8) | (((n) >> 8) & 0xff);
+}
+
+static inline uint32_t swap(uint32_t n)
+{
+  return ((n) >> 24) | (((n) & 0x00ff0000) >> 8) |
+         (((n) & 0x0000ff00) << 8) | ((n) << 24);
+}
+
+template<class T>
+void PixelFormat::directBufferFromBufferFrom888(T* dst,
+                                                const PixelFormat &srcPF,
+                                                const uint8_t* src,
+                                                int w, int h,
+                                                int dstStride,
+                                                int srcStride) const
+{
+  const uint8_t *r, *g, *b;
+  int dstPad, srcPad;
+
+  const uint8_t *redDownTable, *greenDownTable, *blueDownTable;
+
+  redDownTable = &downconvTable[(redBits-1)*256];
+  greenDownTable = &downconvTable[(greenBits-1)*256];
+  blueDownTable = &downconvTable[(blueBits-1)*256];
+
+  if (srcPF.bigEndian) {
+    r = src + (24 - srcPF.redShift)/8;
+    g = src + (24 - srcPF.greenShift)/8;
+    b = src + (24 - srcPF.blueShift)/8;
+  } else {
+    r = src + srcPF.redShift/8;
+    g = src + srcPF.greenShift/8;
+    b = src + srcPF.blueShift/8;
+  }
+
+  dstPad = (dstStride - w);
+  srcPad = (srcStride - w) * 4;
+  while (h--) {
+    int w_ = w;
+    while (w_--) {
+      T d;
+
+      d = redDownTable[*r] << redShift;
+      d |= greenDownTable[*g] << greenShift;
+      d |= blueDownTable[*b] << blueShift;
+
+      if (endianMismatch)
+        d = swap(d);
+
+      *dst = d;
 
+      dst++;
+      r += 4;
+      g += 4;
+      b += 4;
+    }
+    dst += dstPad;
+    r += srcPad;
+    g += srcPad;
+    b += srcPad;
+  }
+}
+
+template<class T>
+void PixelFormat::directBufferFromBufferTo888(uint8_t* dst,
+                                              const PixelFormat &srcPF,
+                                              const T* src,
+                                              int w, int h,
+                                              int dstStride,
+                                              int srcStride) const
+{
+  uint8_t *r, *g, *b, *x;
+  int dstPad, srcPad;
+
+  const uint8_t *redUpTable, *greenUpTable, *blueUpTable;
+
+  redUpTable = &upconvTable[(srcPF.redBits-1)*256];
+  greenUpTable = &upconvTable[(srcPF.greenBits-1)*256];
+  blueUpTable = &upconvTable[(srcPF.blueBits-1)*256];
+
+  if (bigEndian) {
+    r = dst + (24 - redShift)/8;
+    g = dst + (24 - greenShift)/8;
+    b = dst + (24 - blueShift)/8;
+    x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;
+  } else {
+    r = dst + redShift/8;
+    g = dst + greenShift/8;
+    b = dst + blueShift/8;
+    x = dst + (48 - redShift - greenShift - blueShift)/8;
+  }
+
+  dstPad = (dstStride - w) * 4;
+  srcPad = (srcStride - w);
+  while (h--) {
+    int w_ = w;
+    while (w_--) {
+      T s;
+
+      s = *src;
+
+      if (srcPF.endianMismatch)
+        s = swap(s);
+
+      *r = redUpTable[(s >> srcPF.redShift) & 0xff];
+      *g = greenUpTable[(s >> srcPF.greenShift) & 0xff];
+      *b = blueUpTable[(s >> srcPF.blueShift) & 0xff];
+      *x = 0;
+
+      r += 4;
+      g += 4;
+      b += 4;
+      x += 4;
+      src++;
+    }
+    r += dstPad;
+    g += dstPad;
+    b += dstPad;
+    x += dstPad;
+    src += srcPad;
+  }
+}
index 5b4b6332390a97c9ccd2467b17efdb1e476cbced..ceb6c01082996554e13e1a3616a9cfc516c7530d 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2009-2014 Pierre Ossman for Cendio AB
+ * Copyright 2009-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -91,26 +91,14 @@ namespace rfb {
     bool isSane(void);
 
   private:
-    // Preprocessor generated, optimised methods
-
-    void directBufferFromBufferFrom888(rdr::U8* dst, const PixelFormat &srcPF,
-                                       const rdr::U8* src, int w, int h,
-                                       int dstStride, int srcStride) const;
-    void directBufferFromBufferFrom888(rdr::U16* dst, const PixelFormat &srcPF,
-                                       const rdr::U8* src, int w, int h,
-                                       int dstStride, int srcStride) const;
-    void directBufferFromBufferFrom888(rdr::U32* dst, const PixelFormat &srcPF,
+    // Templated, optimised methods
+    template<class T>
+    void directBufferFromBufferFrom888(T* dst, const PixelFormat &srcPF,
                                        const rdr::U8* src, int w, int h,
                                        int dstStride, int srcStride) const;
-
-    void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
-                                     const rdr::U8* src, int w, int h,
-                                     int dstStride, int srcStride) const;
-    void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
-                                     const rdr::U16* src, int w, int h,
-                                     int dstStride, int srcStride) const;
+    template<class T>
     void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF,
-                                     const rdr::U32* src, int w, int h,
+                                     const T* src, int w, int h,
                                      int dstStride, int srcStride) const;
 
   public:
diff --git a/common/rfb/PixelFormatBPP.cxx b/common/rfb/PixelFormatBPP.cxx
deleted file mode 100644 (file)
index c8e432d..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Copyright 2014 Pierre Ossman for Cendio AB
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-
-#define UIN CONCAT2E(U,INBPP)
-#define UOUT CONCAT2E(U,OUTBPP)
-
-#define SWAP16(n) ((((n) & 0xff) << 8) | (((n) >> 8) & 0xff))
-#define SWAP32(n) (((n) >> 24) | (((n) & 0x00ff0000) >> 8) | \
-                   (((n) & 0x0000ff00) << 8) | ((n) << 24))
-
-#define SWAPIN CONCAT2E(SWAP,INBPP)
-#define SWAPOUT CONCAT2E(SWAP,OUTBPP)
-
-#if INBPP == 32
-
-void PixelFormat::directBufferFromBufferFrom888(rdr::UOUT* dst,
-                                                const PixelFormat &srcPF,
-                                                const rdr::U8* src,
-                                                int w, int h,
-                                                int dstStride,
-                                                int srcStride) const
-{
-  const rdr::U8 *r, *g, *b;
-  int dstPad, srcPad;
-
-  const rdr::U8 *redDownTable, *greenDownTable, *blueDownTable;
-
-  redDownTable = &downconvTable[(redBits-1)*256];
-  greenDownTable = &downconvTable[(greenBits-1)*256];
-  blueDownTable = &downconvTable[(blueBits-1)*256];
-
-  if (srcPF.bigEndian) {
-    r = src + (24 - srcPF.redShift)/8;
-    g = src + (24 - srcPF.greenShift)/8;
-    b = src + (24 - srcPF.blueShift)/8;
-  } else {
-    r = src + srcPF.redShift/8;
-    g = src + srcPF.greenShift/8;
-    b = src + srcPF.blueShift/8;
-  }
-
-  dstPad = (dstStride - w);
-  srcPad = (srcStride - w) * 4;
-  while (h--) {
-    int w_ = w;
-    while (w_--) {
-      rdr::UOUT d;
-
-      d = redDownTable[*r] << redShift;
-      d |= greenDownTable[*g] << greenShift;
-      d |= blueDownTable[*b] << blueShift;
-
-#if OUTBPP != 8
-      if (endianMismatch)
-        d = SWAPOUT(d);
-#endif
-
-      *dst = d;
-
-      dst++;
-      r += 4;
-      g += 4;
-      b += 4;
-    }
-    dst += dstPad;
-    r += srcPad;
-    g += srcPad;
-    b += srcPad;
-  }
-}
-
-#endif /* INBPP == 32 */
-
-#if OUTBPP == 32
-
-void PixelFormat::directBufferFromBufferTo888(rdr::U8* dst,
-                                              const PixelFormat &srcPF,
-                                              const rdr::UIN* src,
-                                              int w, int h,
-                                              int dstStride,
-                                              int srcStride) const
-{
-  rdr::U8 *r, *g, *b, *x;
-  int dstPad, srcPad;
-
-  const rdr::U8 *redUpTable, *greenUpTable, *blueUpTable;
-
-  redUpTable = &upconvTable[(srcPF.redBits-1)*256];
-  greenUpTable = &upconvTable[(srcPF.greenBits-1)*256];
-  blueUpTable = &upconvTable[(srcPF.blueBits-1)*256];
-
-  if (bigEndian) {
-    r = dst + (24 - redShift)/8;
-    g = dst + (24 - greenShift)/8;
-    b = dst + (24 - blueShift)/8;
-    x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;
-  } else {
-    r = dst + redShift/8;
-    g = dst + greenShift/8;
-    b = dst + blueShift/8;
-    x = dst + (48 - redShift - greenShift - blueShift)/8;
-  }
-
-  dstPad = (dstStride - w) * 4;
-  srcPad = (srcStride - w);
-  while (h--) {
-    int w_ = w;
-    while (w_--) {
-      rdr::UIN s;
-
-      s = *src;
-
-#if INBPP != 8
-      if (srcPF.endianMismatch)
-        s = SWAPIN(s);
-#endif
-
-      *r = redUpTable[(s >> srcPF.redShift) & 0xff];
-      *g = greenUpTable[(s >> srcPF.greenShift) & 0xff];
-      *b = blueUpTable[(s >> srcPF.blueShift) & 0xff];
-      *x = 0;
-
-      r += 4;
-      g += 4;
-      b += 4;
-      x += 4;
-      src++;
-    }
-    r += dstPad;
-    g += dstPad;
-    b += dstPad;
-    x += dstPad;
-    src += srcPad;
-  }
-}
-
-#endif /* OUTBPP == 32 */
index a01cbe74efe1482ad9edc735f78fd056e48a595f..1384a2be90967a08dda153a7c39990b5d2b809f1 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <rdr/MemInStream.h>
 #include <rdr/OutStream.h>
 
+#include <rfb/Exception.h>
 #include <rfb/ServerParams.h>
 #include <rfb/PixelBuffer.h>
 #include <rfb/RREDecoder.h>
 
 using namespace rfb;
 
-#define BPP 8
-#include <rfb/rreDecode.h>
-#undef BPP
-#define BPP 16
-#include <rfb/rreDecode.h>
-#undef BPP
-#define BPP 32
-#include <rfb/rreDecode.h>
-#undef BPP
-
 RREDecoder::RREDecoder() : Decoder(DecoderPlain)
 {
 }
@@ -81,8 +73,42 @@ void RREDecoder::decodeRect(const Rect& r, const void* buffer,
   rdr::MemInStream is(buffer, buflen);
   const PixelFormat& pf = server.pf();
   switch (pf.bpp) {
-  case 8:  rreDecode8 (r, &is, pf, pb); break;
-  case 16: rreDecode16(r, &is, pf, pb); break;
-  case 32: rreDecode32(r, &is, pf, pb); break;
+  case 8:  rreDecode<rdr::U8 >(r, &is, pf, pb); break;
+  case 16: rreDecode<rdr::U16>(r, &is, pf, pb); break;
+  case 32: rreDecode<rdr::U32>(r, &is, pf, pb); break;
+  }
+}
+
+template<class T>
+inline T RREDecoder::readPixel(rdr::InStream* is)
+{
+  if (sizeof(T) == 1)
+    return is->readOpaque8();
+  if (sizeof(T) == 2)
+    return is->readOpaque16();
+  if (sizeof(T) == 4)
+    return is->readOpaque32();
+}
+
+template<class T>
+void RREDecoder::rreDecode(const Rect& r, rdr::InStream* is,
+                           const PixelFormat& pf,
+                           ModifiablePixelBuffer* pb)
+{
+  int nSubrects = is->readU32();
+  T bg = readPixel<T>(is);
+  pb->fillRect(pf, r, &bg);
+
+  for (int i = 0; i < nSubrects; i++) {
+    T pix = readPixel<T>(is);
+    int x = is->readU16();
+    int y = is->readU16();
+    int w = is->readU16();
+    int h = is->readU16();
+
+    if (((x+w) > r.width()) || ((y+h) > r.height()))
+      throw Exception ("RRE decode error");
+
+    pb->fillRect(pf, Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), &pix);
   }
 }
index b8ec18f6e30d77deea45e8c47265c94a797d480f..05acbc242dded4e399bfed82d1076afdbd3bdd85 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +23,8 @@
 
 namespace rfb {
 
+  class PixelFormat;
+
   class RREDecoder : public Decoder {
   public:
     RREDecoder();
@@ -31,6 +34,12 @@ namespace rfb {
     virtual void decodeRect(const Rect& r, const void* buffer,
                             size_t buflen, const ServerParams& server,
                             ModifiablePixelBuffer* pb);
+  private:
+    template<class T>
+    inline T readPixel(rdr::InStream* is);
+    template<class T>
+    void rreDecode(const Rect& r, rdr::InStream* is,
+                   const PixelFormat& pf, ModifiablePixelBuffer* pb);
   };
 }
 #endif
index 31f94e7cbb61cd7c061cbf0ef6ffe9e31a84e2a2..bbad7c7eb1fd638299be61374ee5adb22b71d287 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 using namespace rfb;
 
-#define BPP 8
-#include <rfb/rreEncode.h>
-#undef BPP
-#define BPP 16
-#include <rfb/rreEncode.h>
-#undef BPP
-#define BPP 32
-#include <rfb/rreEncode.h>
-#undef BPP
-
 RREEncoder::RREEncoder(SConnection* conn) :
   Encoder(conn, encodingRRE, EncoderPlain)
 {
@@ -89,13 +79,13 @@ void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
   int nSubrects = -1;
   switch (pb->getPF().bpp) {
   case 8:
-    nSubrects = rreEncode8((rdr::U8*)imageBuf, w, h, &mos, bg);
+    nSubrects = rreEncode<rdr::U8>((rdr::U8*)imageBuf, w, h, &mos, bg);
     break;
   case 16:
-    nSubrects = rreEncode16((rdr::U16*)imageBuf, w, h, &mos, bg);
+    nSubrects = rreEncode<rdr::U16>((rdr::U16*)imageBuf, w, h, &mos, bg);
     break;
   case 32:
-    nSubrects = rreEncode32((rdr::U32*)imageBuf, w, h, &mos, bg);
+    nSubrects = rreEncode<rdr::U32>((rdr::U32*)imageBuf, w, h, &mos, bg);
     break;
   }
 
@@ -118,3 +108,93 @@ void RREEncoder::writeSolidRect(int /*width*/, int /*height*/,
   os->writeU32(0);
   os->writeBytes(colour, pf.bpp/8);
 }
+
+template<class T>
+inline void RREEncoder::writePixel(rdr::OutStream* os, T pixel)
+{
+  if (sizeof(T) == 1)
+    os->writeOpaque8(pixel);
+  else if (sizeof(T) == 2)
+    os->writeOpaque16(pixel);
+  else if (sizeof(T) == 4)
+    os->writeOpaque32(pixel);
+}
+
+template<class T>
+int RREEncoder::rreEncode(T* data, int w, int h,
+                          rdr::OutStream* os, T bg)
+{
+  writePixel(os, bg);
+
+  int nSubrects = 0;
+
+  for (int y = 0; y < h; y++)
+  {
+    int x = 0;
+    while (x < w) {
+      if (*data == bg) {
+        x++;
+        data++;
+        continue;
+      }
+
+      // Find horizontal subrect first
+      T* ptr = data+1;
+      T* eol = data+w-x;
+      while (ptr < eol && *ptr == *data) ptr++;
+      int sw = ptr - data;
+
+      ptr = data + w;
+      int sh = 1;
+      while (sh < h-y) {
+        eol = ptr + sw;
+        while (ptr < eol)
+          if (*ptr++ != *data) goto endOfHorizSubrect;
+        ptr += w - sw;
+        sh++;
+      }
+    endOfHorizSubrect:
+
+      // Find vertical subrect
+      int vh;
+      for (vh = sh; vh < h-y; vh++)
+        if (data[vh*w] != *data) break;
+
+      if (vh != sh) {
+        ptr = data+1;
+        int vw;
+        for (vw = 1; vw < sw; vw++) {
+          for (int i = 0; i < vh; i++)
+            if (ptr[i*w] != *data) goto endOfVertSubrect;
+          ptr++;
+        }
+      endOfVertSubrect:
+
+        // If vertical subrect bigger than horizontal then use that.
+        if (sw*sh < vw*vh) {
+          sw = vw;
+          sh = vh;
+        }
+      }
+
+      nSubrects++;
+      writePixel(os, *data);
+      os->writeU16(x);
+      os->writeU16(y);
+      os->writeU16(sw);
+      os->writeU16(sh);
+
+      ptr = data+w;
+      T* eor = data+w*sh;
+      while (ptr < eor) {
+        eol = ptr + sw;
+        while (ptr < eol) *ptr++ = bg;
+        ptr += w - sw;
+      }
+      x += sw;
+      data += sw;
+    }
+  }
+
+  return nSubrects;
+}
index c0de9995f66e9222628afc5b58f06c7a3a45c808..767e7348cca296710315673d2198b17453ec2972 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +34,11 @@ namespace rfb {
     virtual void writeSolidRect(int width, int height,
                                 const PixelFormat& pf,
                                 const rdr::U8* colour);
+  private:
+    template<class T>
+    inline void writePixel(rdr::OutStream* os, T pixel);
+    template<class T>
+    int rreEncode(T* data, int w, int h, rdr::OutStream* os, T bg);
   private:
     rdr::MemOutStream mos;
     ManagedPixelBuffer bufferCopy;
index 69971dbcdd08de3fb89f00c5d8068c03c7f11591..f56a4284daeb9dc366bffff07e79ac8496659f41 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright 2004-2005 Cendio AB.
- * Copyright 2009-2015 Pierre Ossman for Cendio AB
+ * Copyright 2009-2022 Pierre Ossman for Cendio AB
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
  *    
  * This is free software; you can redistribute it and/or modify
@@ -40,16 +40,6 @@ using namespace rfb;
 static const int TIGHT_MAX_WIDTH = 2048;
 static const int TIGHT_MIN_TO_COMPRESS = 12;
 
-#define BPP 8
-#include <rfb/tightDecode.h>
-#undef BPP
-#define BPP 16
-#include <rfb/tightDecode.h>
-#undef BPP
-#define BPP 32
-#include <rfb/tightDecode.h>
-#undef BPP
-
 TightDecoder::TightDecoder() : Decoder(DecoderPartiallyOrdered)
 {
 }
@@ -509,3 +499,144 @@ rdr::U32 TightDecoder::readCompact(rdr::InStream* is)
 
   return result;
 }
+
+void
+TightDecoder::FilterGradient24(const rdr::U8 *inbuf,
+                               const PixelFormat& pf, rdr::U32* outbuf,
+                               int stride, const Rect& r)
+{
+  int x, y, c;
+  rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
+  rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
+  rdr::U8 pix[3]; 
+  int est[3]; 
+
+  memset(prevRow, 0, sizeof(prevRow));
+
+  // Set up shortcut variables
+  int rectHeight = r.height();
+  int rectWidth = r.width();
+
+  for (y = 0; y < rectHeight; y++) {
+    for (x = 0; x < rectWidth; x++) {
+      /* First pixel in a row */
+      if (x == 0) {
+        for (c = 0; c < 3; c++) {
+          pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];
+          thisRow[c] = pix[c];
+        }
+        pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+        continue;
+      }
+
+      for (c = 0; c < 3; c++) {
+        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
+        if (est[c] > 0xff) {
+          est[c] = 0xff;
+        } else if (est[c] < 0) {
+          est[c] = 0;
+        }
+        pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c];
+        thisRow[x*3+c] = pix[c];
+      }
+      pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
+    }
+
+    memcpy(prevRow, thisRow, sizeof(prevRow));
+  }
+}
+
+template<class T>
+void TightDecoder::FilterGradient(const rdr::U8* inbuf,
+                                  const PixelFormat& pf, T* outbuf,
+                                  int stride, const Rect& r)
+{
+  int x, y, c;
+  static rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
+  static rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
+  rdr::U8 pix[3]; 
+  int est[3]; 
+
+  memset(prevRow, 0, sizeof(prevRow));
+
+  // Set up shortcut variables
+  int rectHeight = r.height();
+  int rectWidth = r.width();
+
+  for (y = 0; y < rectHeight; y++) {
+    for (x = 0; x < rectWidth; x++) {
+      /* First pixel in a row */
+      if (x == 0) {
+        pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);
+        for (c = 0; c < 3; c++)
+          pix[c] += prevRow[c];
+
+        memcpy(thisRow, pix, sizeof(pix));
+
+        pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+
+        continue;
+      }
+
+      for (c = 0; c < 3; c++) {
+        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
+        if (est[c] > 255) {
+          est[c] = 255;
+        } else if (est[c] < 0) {
+          est[c] = 0;
+        }
+      }
+
+      pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1);
+      for (c = 0; c < 3; c++)
+        pix[c] += est[c];
+
+      memcpy(&thisRow[x*3], pix, sizeof(pix));
+
+      pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
+    }
+
+    memcpy(prevRow, thisRow, sizeof(prevRow));
+  }
+}
+
+template<class T>
+void TightDecoder::FilterPalette(const T* palette, int palSize,
+                                 const rdr::U8* inbuf, T* outbuf,
+                                 int stride, const Rect& r)
+{
+  // Indexed color
+  int x, h = r.height(), w = r.width(), b, pad = stride - w;
+  T* ptr = outbuf;
+  rdr::U8 bits;
+  const rdr::U8* srcPtr = inbuf;
+  if (palSize <= 2) {
+    // 2-color palette
+    while (h > 0) {
+      for (x = 0; x < w / 8; x++) {
+        bits = *srcPtr++;
+        for (b = 7; b >= 0; b--) {
+          *ptr++ = palette[bits >> b & 1];
+        }
+      }
+      if (w % 8 != 0) {
+        bits = *srcPtr++;
+        for (b = 7; b >= 8 - w % 8; b--) {
+          *ptr++ = palette[bits >> b & 1];
+        }
+      }
+      ptr += pad;
+      h--;
+    }
+  } else {
+    // 256-color palette
+    while (h > 0) {
+      T *endOfRow = ptr + w;
+      while (ptr < endOfRow) {
+        *ptr++ = palette[*srcPtr++];
+      }
+      ptr += pad;
+      h--;
+    }
+  }
+}
index 763c82d6642e32dad152f5b302743026b3b4a1e6..47d65d6f7aa0e6f2396ed9631d4cd75f0d77abd9 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2009-2015 Pierre Ossman for Cendio AB
+ * Copyright 2009-2022 Pierre Ossman for Cendio AB
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -50,19 +50,13 @@ namespace rfb {
     void FilterGradient24(const rdr::U8* inbuf, const PixelFormat& pf,
                           rdr::U32* outbuf, int stride, const Rect& r);
 
+    template<class T>
     void FilterGradient(const rdr::U8* inbuf, const PixelFormat& pf,
-                        rdr::U16* outbuf, int stride, const Rect& r);
-    void FilterGradient(const rdr::U8* inbuf, const PixelFormat& pf,
-                        rdr::U32* outbuf, int stride, const Rect& r);
+                        T* outbuf, int stride, const Rect& r);
 
-    void FilterPalette(const rdr::U8* palette, int palSize,
-                       const rdr::U8* inbuf, rdr::U8* outbuf,
-                       int stride, const Rect& r);
-    void FilterPalette(const rdr::U16* palette, int palSize,
-                       const rdr::U8* inbuf, rdr::U16* outbuf,
-                       int stride, const Rect& r);
-    void FilterPalette(const rdr::U32* palette, int palSize,
-                       const rdr::U8* inbuf, rdr::U32* outbuf,
+    template<class T>
+    void FilterPalette(const T* palette, int palSize,
+                       const rdr::U8* inbuf, T* outbuf,
                        int stride, const Rect& r);
 
   private:
index 94acd3d123572589e880f26b75f8213118f2b640..fe987e154f86a062399e85998b3daf963a0388b0 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -274,16 +274,143 @@ void TightEncoder::flushZlibOutStream(rdr::OutStream* os_)
   memStream.clear();
 }
 
-//
-// Including BPP-dependent implementation of the encoder.
-//
+template<class T>
+void TightEncoder::writeMonoRect(int width, int height,
+                                 const T* buffer, int stride,
+                                 const PixelFormat& pf,
+                                 const Palette& palette)
+{
+  rdr::OutStream* os;
+
+  const int streamId = 1;
+  T pal[2];
+
+  int length;
+  rdr::OutStream* zos;
+
+  assert(palette.size() == 2);
+
+  os = conn->getOutStream();
+
+  os->writeU8((streamId | tightExplicitFilter) << 4);
+  os->writeU8(tightFilterPalette);
 
-#define BPP 8
-#include <rfb/TightEncoderBPP.cxx>
-#undef BPP
-#define BPP 16
-#include <rfb/TightEncoderBPP.cxx>
-#undef BPP
-#define BPP 32
-#include <rfb/TightEncoderBPP.cxx>
-#undef BPP
+  // Write the palette
+  pal[0] = (T)palette.getColour(0);
+  pal[1] = (T)palette.getColour(1);
+
+  os->writeU8(1);
+  writePixels((rdr::U8*)pal, pf, 2, os);
+
+  // Set up compression
+  length = (width + 7)/8 * height;
+  zos = getZlibOutStream(streamId, monoZlibLevel, length);
+
+  // Encode the data
+  T bg;
+  unsigned int value, mask;
+  int pad, aligned_width;
+  int x, y, bg_bits;
+
+  bg = pal[0];
+  aligned_width = width - width % 8;
+  pad = stride - width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < aligned_width; x += 8) {
+      for (bg_bits = 0; bg_bits < 8; bg_bits++) {
+        if (*buffer++ != bg)
+          break;
+      }
+      if (bg_bits == 8) {
+        zos->writeU8(0);
+        continue;
+      }
+      mask = 0x80 >> bg_bits;
+      value = mask;
+      for (bg_bits++; bg_bits < 8; bg_bits++) {
+        mask >>= 1;
+        if (*buffer++ != bg) {
+          value |= mask;
+        }
+      }
+      zos->writeU8(value);
+    }
+
+    if (x < width) {
+      mask = 0x80;
+      value = 0;
+
+      for (; x < width; x++) {
+        if (*buffer++ != bg) {
+          value |= mask;
+        }
+        mask >>= 1;
+      }
+      zos->writeU8(value);
+    }
+
+    buffer += pad;
+  }
+
+  // Finish the zlib stream
+  flushZlibOutStream(zos);
+}
+
+template<class T>
+void TightEncoder::writeIndexedRect(int width, int height,
+                                    const T* buffer, int stride,
+                                    const PixelFormat& pf,
+                                    const Palette& palette)
+{
+  rdr::OutStream* os;
+
+  const int streamId = 2;
+  T pal[256];
+
+  rdr::OutStream* zos;
+
+  int pad;
+  T prevColour;
+  unsigned char idx;
+
+  assert(palette.size() > 0);
+  assert(palette.size() <= 256);
+
+  os = conn->getOutStream();
+
+  os->writeU8((streamId | tightExplicitFilter) << 4);
+  os->writeU8(tightFilterPalette);
+
+  // Write the palette
+  for (int i = 0; i < palette.size(); i++)
+    pal[i] = (T)palette.getColour(i);
+
+  os->writeU8(palette.size() - 1);
+  writePixels((rdr::U8*)pal, pf, palette.size(), os);
+
+  // Set up compression
+  zos = getZlibOutStream(streamId, idxZlibLevel, width * height);
+
+  // Encode the data
+  pad = stride - width;
+
+  prevColour = *buffer;
+  idx = palette.lookup(*buffer);
+
+  while (height--) {
+    int w = width;
+    while (w--) {
+      if (*buffer != prevColour) {
+        prevColour = *buffer;
+        idx = palette.lookup(*buffer);
+      }
+      zos->writeU8(idx);
+      buffer++;
+    }
+    buffer += pad;
+  }
+
+  // Finish the zlib stream
+  flushZlibOutStream(zos);
+}
index b96bc4c63c80517ffd3ab4dd94202e5af0952aad..2be2f6d4e002795d7c66e1f12f8fb199417564d2 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2011 D. R. Commander
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,22 +54,14 @@ namespace rfb {
     void flushZlibOutStream(rdr::OutStream* os);
 
   protected:
-    // Preprocessor generated, optimised methods
+    // Templated, optimised methods
+    template<class T>
     void writeMonoRect(int width, int height,
-                       const rdr::U8* buffer, int stride,
+                       const T* buffer, int stride,
                        const PixelFormat& pf, const Palette& palette);
-    void writeMonoRect(int width, int height,
-                       const rdr::U16* buffer, int stride,
-                       const PixelFormat& pf, const Palette& palette);
-    void writeMonoRect(int width, int height,
-                       const rdr::U32* buffer, int stride,
-                       const PixelFormat& pf, const Palette& palette);
-
-    void writeIndexedRect(int width, int height,
-                          const rdr::U16* buffer, int stride,
-                          const PixelFormat& pf, const Palette& palette);
+    template<class T>
     void writeIndexedRect(int width, int height,
-                          const rdr::U32* buffer, int stride,
+                          const T* buffer, int stride,
                           const PixelFormat& pf, const Palette& palette);
 
     rdr::ZlibOutStream zlibStreams[4];
diff --git a/common/rfb/TightEncoderBPP.cxx b/common/rfb/TightEncoderBPP.cxx
deleted file mode 100644 (file)
index 8874662..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
- * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-
-#define UBPP CONCAT2E(U,BPP)
-
-void TightEncoder::writeMonoRect(int width, int height,
-                                 const rdr::UBPP* buffer, int stride,
-                                 const PixelFormat& pf,
-                                 const Palette& palette)
-{
-  rdr::OutStream* os;
-
-  const int streamId = 1;
-  rdr::UBPP pal[2];
-
-  int length;
-  rdr::OutStream* zos;
-
-  assert(palette.size() == 2);
-
-  os = conn->getOutStream();
-
-  os->writeU8((streamId | tightExplicitFilter) << 4);
-  os->writeU8(tightFilterPalette);
-
-  // Write the palette
-  pal[0] = (rdr::UBPP)palette.getColour(0);
-  pal[1] = (rdr::UBPP)palette.getColour(1);
-
-  os->writeU8(1);
-  writePixels((rdr::U8*)pal, pf, 2, os);
-
-  // Set up compression
-  length = (width + 7)/8 * height;
-  zos = getZlibOutStream(streamId, monoZlibLevel, length);
-
-  // Encode the data
-  rdr::UBPP bg;
-  unsigned int value, mask;
-  int pad, aligned_width;
-  int x, y, bg_bits;
-
-  bg = pal[0];
-  aligned_width = width - width % 8;
-  pad = stride - width;
-
-  for (y = 0; y < height; y++) {
-    for (x = 0; x < aligned_width; x += 8) {
-      for (bg_bits = 0; bg_bits < 8; bg_bits++) {
-        if (*buffer++ != bg)
-          break;
-      }
-      if (bg_bits == 8) {
-        zos->writeU8(0);
-        continue;
-      }
-      mask = 0x80 >> bg_bits;
-      value = mask;
-      for (bg_bits++; bg_bits < 8; bg_bits++) {
-        mask >>= 1;
-        if (*buffer++ != bg) {
-          value |= mask;
-        }
-      }
-      zos->writeU8(value);
-    }
-
-    if (x < width) {
-      mask = 0x80;
-      value = 0;
-
-      for (; x < width; x++) {
-        if (*buffer++ != bg) {
-          value |= mask;
-        }
-        mask >>= 1;
-      }
-      zos->writeU8(value);
-    }
-
-    buffer += pad;
-  }
-
-  // Finish the zlib stream
-  flushZlibOutStream(zos);
-}
-
-#if (BPP != 8)
-void TightEncoder::writeIndexedRect(int width, int height,
-                                    const rdr::UBPP* buffer, int stride,
-                                    const PixelFormat& pf,
-                                    const Palette& palette)
-{
-  rdr::OutStream* os;
-
-  const int streamId = 2;
-  rdr::UBPP pal[256];
-
-  rdr::OutStream* zos;
-
-  int pad;
-  rdr::UBPP prevColour;
-  unsigned char idx;
-
-  assert(palette.size() > 0);
-  assert(palette.size() <= 256);
-
-  os = conn->getOutStream();
-
-  os->writeU8((streamId | tightExplicitFilter) << 4);
-  os->writeU8(tightFilterPalette);
-
-  // Write the palette
-  for (int i = 0; i < palette.size(); i++)
-    pal[i] = (rdr::UBPP)palette.getColour(i);
-
-  os->writeU8(palette.size() - 1);
-  writePixels((rdr::U8*)pal, pf, palette.size(), os);
-
-  // Set up compression
-  zos = getZlibOutStream(streamId, idxZlibLevel, width * height);
-
-  // Encode the data
-  pad = stride - width;
-
-  prevColour = *buffer;
-  idx = palette.lookup(*buffer);
-
-  while (height--) {
-    int w = width;
-    while (w--) {
-      if (*buffer != prevColour) {
-        prevColour = *buffer;
-        idx = palette.lookup(*buffer);
-      }
-      zos->writeU8(idx);
-      buffer++;
-    }
-    buffer += pad;
-  }
-
-  // Finish the zlib stream
-  flushZlibOutStream(zos);
-}
-#endif  // #if (BPP != 8)
index f5120e9c454209250d02a6900de632d534ffffde..c61b66bff187a786c2918300f8d2ed67048720a0 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2009-2017 Pierre Ossman for Cendio AB
+ * Copyright 2009-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -50,28 +50,23 @@ static inline rdr::U32 readOpaque24B(rdr::InStream* is)
   return r;
 }
 
+template<class T>
+static inline T readPixel(rdr::ZlibInStream* zis)
+{
+  if (sizeof(T) == 1)
+    return zis->readOpaque8();
+  if (sizeof(T) == 2)
+    return zis->readOpaque16();
+  if (sizeof(T) == 4)
+    return zis->readOpaque32();
+}
+
 static inline void zlibHasData(rdr::ZlibInStream* zis, size_t length)
 {
   if (!zis->hasData(length))
     throw Exception("ZRLE decode error");
 }
 
-#define BPP 8
-#include <rfb/zrleDecode.h>
-#undef BPP
-#define BPP 16
-#include <rfb/zrleDecode.h>
-#undef BPP
-#define BPP 32
-#include <rfb/zrleDecode.h>
-#define CPIXEL 24A
-#include <rfb/zrleDecode.h>
-#undef CPIXEL
-#define CPIXEL 24B
-#include <rfb/zrleDecode.h>
-#undef CPIXEL
-#undef BPP
-
 ZRLEDecoder::ZRLEDecoder() : Decoder(DecoderOrdered)
 {
 }
@@ -111,32 +106,185 @@ void ZRLEDecoder::decodeRect(const Rect& r, const void* buffer,
   rdr::MemInStream is(buffer, buflen);
   const rfb::PixelFormat& pf = server.pf();
   switch (pf.bpp) {
-  case 8:  zrleDecode8 (r, &is, &zis, pf, pb); break;
-  case 16: zrleDecode16(r, &is, &zis, pf, pb); break;
-  case 32:
-    {
-      if (pf.depth <= 24) {
-        Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
-        bool fitsInLS3Bytes = maxPixel < (1<<24);
-        bool fitsInMS3Bytes = (maxPixel & 0xff) == 0;
-
-        if ((fitsInLS3Bytes && pf.isLittleEndian()) ||
-            (fitsInMS3Bytes && pf.isBigEndian()))
-        {
-          zrleDecode24A(r, &is, &zis, pf, pb);
-          break;
+  case 8:  zrleDecode<rdr::U8>(r, &is, &zis, pf, pb); break;
+  case 16: zrleDecode<rdr::U16>(r, &is, &zis, pf, pb); break;
+  case 32: zrleDecode<rdr::U32>(r, &is, &zis, pf, pb); break;
+  }
+}
+
+template<class T>
+void ZRLEDecoder::zrleDecode(const Rect& r, rdr::InStream* is,
+                             rdr::ZlibInStream* zis,
+                             const PixelFormat& pf,
+                             ModifiablePixelBuffer* pb)
+{
+  int length = is->readU32();
+  zis->setUnderlying(is, length);
+  Rect t;
+  T buf[64 * 64];
+
+  Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
+  bool fitsInLS3Bytes = maxPixel < (1<<24);
+  bool fitsInMS3Bytes = (maxPixel & 0xff) == 0;
+  bool isLowCPixel = (sizeof(T) == 4) &&
+                     ((fitsInLS3Bytes && pf.isLittleEndian()) ||
+                      (fitsInMS3Bytes && pf.isBigEndian()));
+  bool isHighCPixel = (sizeof(T) == 4) &&
+                      ((fitsInLS3Bytes && pf.isBigEndian()) ||
+                       (fitsInMS3Bytes && pf.isLittleEndian()));
+
+  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {
+
+    t.br.y = __rfbmin(r.br.y, t.tl.y + 64);
+
+    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
+
+      t.br.x = __rfbmin(r.br.x, t.tl.x + 64);
+
+      zlibHasData(zis, 1);
+      int mode = zis->readU8();
+      bool rle = mode & 128;
+      int palSize = mode & 127;
+      T palette[128];
+
+      if (isLowCPixel || isHighCPixel)
+        zlibHasData(zis, 3 * palSize);
+      else
+        zlibHasData(zis, sizeof(T) * palSize);
+
+      for (int i = 0; i < palSize; i++) {
+        if (isLowCPixel)
+          palette[i] = readOpaque24A(zis);
+        else if (isHighCPixel)
+          palette[i] = readOpaque24B(zis);
+        else
+          palette[i] = readPixel<T>(zis);
+      }
+
+      if (palSize == 1) {
+        T pix = palette[0];
+        pb->fillRect(pf, t, &pix);
+        continue;
+      }
+
+      if (!rle) {
+        if (palSize == 0) {
+
+          // raw
+
+          if (isLowCPixel || isHighCPixel)
+            zlibHasData(zis, 3 * t.area());
+          else
+            zlibHasData(zis, sizeof(T) * t.area());
+
+          if (isLowCPixel || isHighCPixel) {
+            for (T* ptr = buf; ptr < buf+t.area(); ptr++) {
+              if (isLowCPixel)
+                *ptr = readOpaque24A(zis);
+              else
+                *ptr = readOpaque24B(zis);
+            }
+          } else {
+            zis->readBytes(buf, t.area() * sizeof(T));
+          }
+
+        } else {
+
+          // packed pixels
+          int bppp = ((palSize > 16) ? 8 :
+                      ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
+
+          T* ptr = buf;
+
+          for (int i = 0; i < t.height(); i++) {
+            T* eol = ptr + t.width();
+            rdr::U8 byte = 0;
+            rdr::U8 nbits = 0;
+
+            while (ptr < eol) {
+              if (nbits == 0) {
+                zlibHasData(zis, 1);
+                byte = zis->readU8();
+                nbits = 8;
+              }
+              nbits -= bppp;
+              rdr::U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127;
+              *ptr++ = palette[index];
+            }
+          }
         }
 
-        if ((fitsInLS3Bytes && pf.isBigEndian()) ||
-            (fitsInMS3Bytes && pf.isLittleEndian()))
-        {
-          zrleDecode24B(r, &is, &zis, pf, pb);
-          break;
+      } else {
+
+        if (palSize == 0) {
+
+          // plain RLE
+
+          T* ptr = buf;
+          T* end = ptr + t.area();
+          while (ptr < end) {
+            T pix;
+            if (isLowCPixel || isHighCPixel)
+              zlibHasData(zis, 3);
+            else
+              zlibHasData(zis, sizeof(T));
+            if (isLowCPixel)
+              pix = readOpaque24A(zis);
+            else if (isHighCPixel)
+              pix = readOpaque24B(zis);
+            else
+              pix = readPixel<T>(zis);
+            int len = 1;
+            int b;
+            do {
+              zlibHasData(zis, 1);
+              b = zis->readU8();
+              len += b;
+            } while (b == 255);
+
+            if (end - ptr < len) {
+              throw Exception ("ZRLE decode error");
+            }
+
+            while (len-- > 0) *ptr++ = pix;
+
+          }
+        } else {
+
+          // palette RLE
+
+          T* ptr = buf;
+          T* end = ptr + t.area();
+          while (ptr < end) {
+            zlibHasData(zis, 1);
+            int index = zis->readU8();
+            int len = 1;
+            if (index & 128) {
+              int b;
+              do {
+                zlibHasData(zis, 1);
+                b = zis->readU8();
+                len += b;
+              } while (b == 255);
+
+              if (end - ptr < len) {
+                throw Exception ("ZRLE decode error");
+              }
+            }
+
+            index &= 127;
+
+            T pix = palette[index];
+
+            while (len-- > 0) *ptr++ = pix;
+          }
         }
       }
 
-      zrleDecode32(r, &is, &zis, pf, pb);
-      break;
+      pb->imageRect(pf, t, buf);
     }
   }
+
+  zis->flushUnderlying();
+  zis->setUnderlying(NULL, 0);
 }
index 115f8fb8ca2cea0fc8fb782b66ce751f115252f4..3885124a96e5755503ee0d5361c4f2234a81cc9a 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,6 +24,8 @@
 
 namespace rfb {
 
+  class PixelFormat;
+
   class ZRLEDecoder : public Decoder {
   public:
     ZRLEDecoder();
@@ -32,6 +35,13 @@ namespace rfb {
     virtual void decodeRect(const Rect& r, const void* buffer,
                             size_t buflen, const ServerParams& server,
                             ModifiablePixelBuffer* pb);
+
+  private:
+    template<class T>
+    void zrleDecode(const Rect& r, rdr::InStream* is,
+                    rdr::ZlibInStream* zis,
+                    const PixelFormat& pf, ModifiablePixelBuffer* pb);
+
   private:
     rdr::ZlibInStream zis;
   };
index 7d98540159f732279b866c8e19fa5ba99b7dcb62..d257d05c9ae5617ef8c36a0dd041f43f7967280a 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -239,16 +239,110 @@ void ZRLEEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf,
   }
 }
 
-//
-// Including BPP-dependent implementation of the encoder.
-//
-
-#define BPP 8
-#include <rfb/ZRLEEncoderBPP.cxx>
-#undef BPP
-#define BPP 16
-#include <rfb/ZRLEEncoderBPP.cxx>
-#undef BPP
-#define BPP 32
-#include <rfb/ZRLEEncoderBPP.cxx>
-#undef BPP
+template<class T>
+void ZRLEEncoder::writePaletteTile(int width, int height,
+                                   const T* buffer, int stride,
+                                   const PixelFormat& pf,
+                                   const Palette& palette)
+{
+  const int bitsPerPackedPixel[] = {
+    0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+  };
+
+  int bppp;
+  int pad;
+
+  assert(palette.size() > 1);
+  assert(palette.size() <= 16);
+
+  zos.writeU8(palette.size());
+  writePalette(pf, palette);
+
+  bppp = bitsPerPackedPixel[palette.size()-1];
+  pad = stride - width;
+
+  for (int i = 0; i < height; i++) {
+    int w;
+
+    rdr::U8 nbits = 0;
+    rdr::U8 byte = 0;
+
+    w = width;
+    while (w--) {
+      T pix = *buffer++;
+      rdr::U8 index = palette.lookup(pix);
+      byte = (byte << bppp) | index;
+      nbits += bppp;
+      if (nbits >= 8) {
+        zos.writeU8(byte);
+        nbits = 0;
+      }
+    }
+    if (nbits > 0) {
+      byte <<= 8 - nbits;
+      zos.writeU8(byte);
+    }
+
+    buffer += pad;
+  }
+}
+
+template<class T>
+void ZRLEEncoder::writePaletteRLETile(int width, int height,
+                                      const T* buffer, int stride,
+                                      const PixelFormat& pf,
+                                      const Palette& palette)
+{
+  int pad;
+
+  T prevColour;
+  int runLength;
+
+  assert(palette.size() > 1);
+  assert(palette.size() <= 127);
+
+  zos.writeU8(palette.size() | 0x80);
+  writePalette(pf, palette);
+
+  pad = stride - width;
+
+  prevColour = *buffer;
+  runLength = 0;
+
+  while (height--) {
+    int w = width;
+    while (w--) {
+      if (prevColour != *buffer) {
+        if (runLength == 1)
+          zos.writeU8(palette.lookup(prevColour));
+        else {
+          zos.writeU8(palette.lookup(prevColour) | 0x80);
+
+          while (runLength > 255) {
+            zos.writeU8(255);
+            runLength -= 255;
+          }
+          zos.writeU8(runLength - 1);
+        }
+
+        prevColour = *buffer;
+        runLength = 0;
+      }
+
+      runLength++;
+      buffer++;
+    }
+    buffer += pad;
+  }
+  if (runLength == 1)
+    zos.writeU8(palette.lookup(prevColour));
+  else {
+    zos.writeU8(palette.lookup(prevColour) | 0x80);
+
+    while (runLength > 255) {
+      zos.writeU8(255);
+      runLength -= 255;
+    }
+    zos.writeU8(runLength - 1);
+  }
+}
index 37a3be2db3b3d31f447a850449d9d21b2e0c291e..a1f35533ba3c9b7a88512d93464747bb6f8978f9 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2022 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -50,26 +50,14 @@ namespace rfb {
                      unsigned int count);
 
   protected:
-    // Preprocessor generated, optimised methods
-
-    void writePaletteTile(int width, int height,
-                          const rdr::U8* buffer, int stride,
-                          const PixelFormat& pf, const Palette& palette);
-    void writePaletteTile(int width, int height,
-                          const rdr::U16* buffer, int stride,
-                          const PixelFormat& pf, const Palette& palette);
+    // Templated, optimised methods
+    template<class T>
     void writePaletteTile(int width, int height,
-                          const rdr::U32* buffer, int stride,
+                          const T* buffer, int stride,
                           const PixelFormat& pf, const Palette& palette);
-
-    void writePaletteRLETile(int width, int height,
-                             const rdr::U8* buffer, int stride,
-                             const PixelFormat& pf, const Palette& palette);
-    void writePaletteRLETile(int width, int height,
-                             const rdr::U16* buffer, int stride,
-                             const PixelFormat& pf, const Palette& palette);
+    template<class T>
     void writePaletteRLETile(int width, int height,
-                             const rdr::U32* buffer, int stride,
+                             const T* buffer, int stride,
                              const PixelFormat& pf, const Palette& palette);
 
   protected:
diff --git a/common/rfb/ZRLEEncoderBPP.cxx b/common/rfb/ZRLEEncoderBPP.cxx
deleted file mode 100644 (file)
index 90f395b..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-
-#define UBPP CONCAT2E(U,BPP)
-
-void ZRLEEncoder::writePaletteTile(int width, int height,
-                                   const rdr::UBPP* buffer, int stride,
-                                   const PixelFormat& pf,
-                                   const Palette& palette)
-{
-  const int bitsPerPackedPixel[] = {
-    0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
-  };
-
-  int bppp;
-  int pad;
-
-  assert(palette.size() > 1);
-  assert(palette.size() <= 16);
-
-  zos.writeU8(palette.size());
-  writePalette(pf, palette);
-
-  bppp = bitsPerPackedPixel[palette.size()-1];
-  pad = stride - width;
-
-  for (int i = 0; i < height; i++) {
-    int w;
-
-    rdr::U8 nbits = 0;
-    rdr::U8 byte = 0;
-
-    w = width;
-    while (w--) {
-      rdr::UBPP pix = *buffer++;
-      rdr::U8 index = palette.lookup(pix);
-      byte = (byte << bppp) | index;
-      nbits += bppp;
-      if (nbits >= 8) {
-        zos.writeU8(byte);
-        nbits = 0;
-      }
-    }
-    if (nbits > 0) {
-      byte <<= 8 - nbits;
-      zos.writeU8(byte);
-    }
-
-    buffer += pad;
-  }
-}
-
-void ZRLEEncoder::writePaletteRLETile(int width, int height,
-                                      const rdr::UBPP* buffer, int stride,
-                                      const PixelFormat& pf,
-                                      const Palette& palette)
-{
-  int pad;
-
-  rdr::UBPP prevColour;
-  int runLength;
-
-  assert(palette.size() > 1);
-  assert(palette.size() <= 127);
-
-  zos.writeU8(palette.size() | 0x80);
-  writePalette(pf, palette);
-
-  pad = stride - width;
-
-  prevColour = *buffer;
-  runLength = 0;
-
-  while (height--) {
-    int w = width;
-    while (w--) {
-      if (prevColour != *buffer) {
-        if (runLength == 1)
-          zos.writeU8(palette.lookup(prevColour));
-        else {
-          zos.writeU8(palette.lookup(prevColour) | 0x80);
-
-          while (runLength > 255) {
-            zos.writeU8(255);
-            runLength -= 255;
-          }
-          zos.writeU8(runLength - 1);
-        }
-
-        prevColour = *buffer;
-        runLength = 0;
-      }
-
-      runLength++;
-      buffer++;
-    }
-    buffer += pad;
-  }
-  if (runLength == 1)
-    zos.writeU8(palette.lookup(prevColour));
-  else {
-    zos.writeU8(palette.lookup(prevColour) | 0x80);
-
-    while (runLength > 255) {
-      zos.writeU8(255);
-      runLength -= 255;
-    }
-    zos.writeU8(runLength - 1);
-  }
-}
diff --git a/common/rfb/hextileDecode.h b/common/rfb/hextileDecode.h
deleted file mode 100644 (file)
index 402cd03..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-//
-// Hextile decoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-#include <rdr/InStream.h>
-#include <rfb/Exception.h>
-#include <rfb/hextileConstants.h>
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL CONCAT2E(readOpaque,BPP)
-#define HEXTILE_DECODE CONCAT2E(hextileDecode,BPP)
-
-static void HEXTILE_DECODE (const Rect& r, rdr::InStream* is,
-                            const PixelFormat& pf,
-                            ModifiablePixelBuffer* pb)
-{
-  Rect t;
-  PIXEL_T bg = 0;
-  PIXEL_T fg = 0;
-  PIXEL_T buf[16 * 16];
-
-  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
-
-    t.br.y = __rfbmin(r.br.y, t.tl.y + 16);
-
-    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
-
-      t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
-
-      int tileType = is->readU8();
-
-      if (tileType & hextileRaw) {
-        is->readBytes(buf, t.area() * (BPP/8));
-        pb->imageRect(pf, t, buf);
-        continue;
-      }
-
-      if (tileType & hextileBgSpecified)
-        bg = is->READ_PIXEL();
-
-      int len = t.area();
-      PIXEL_T* ptr = buf;
-      while (len-- > 0) *ptr++ = bg;
-
-      if (tileType & hextileFgSpecified)
-        fg = is->READ_PIXEL();
-
-      if (tileType & hextileAnySubrects) {
-        int nSubrects = is->readU8();
-
-        for (int i = 0; i < nSubrects; i++) {
-
-          if (tileType & hextileSubrectsColoured)
-            fg = is->READ_PIXEL();
-
-          int xy = is->readU8();
-          int wh = is->readU8();
-
-          int x = ((xy >> 4) & 15);
-          int y = (xy & 15);
-          int w = ((wh >> 4) & 15) + 1;
-          int h = (wh & 15) + 1;
-          if (x + w > 16 || y + h > 16) {
-            throw rfb::Exception("HEXTILE_DECODE: Hextile out of bounds");
-          }
-          PIXEL_T* ptr = buf + y * t.width() + x;
-          int rowAdd = t.width() - w;
-          while (h-- > 0) {
-            int len = w;
-            while (len-- > 0) *ptr++ = fg;
-            ptr += rowAdd;
-          }
-        }
-      }
-      pb->imageRect(pf, t, buf);
-    }
-  }
-}
-
-#undef PIXEL_T
-#undef READ_PIXEL
-#undef HEXTILE_DECODE
-}
diff --git a/common/rfb/hextileEncode.h b/common/rfb/hextileEncode.h
deleted file mode 100644 (file)
index aa5926c..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2005 Constantin Kaplinsky.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-//
-// Hextile encoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-#include <rdr/OutStream.h>
-#include <rfb/hextileConstants.h>
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP)
-#define HEXTILE_ENCODE CONCAT2E(hextileEncode,BPP)
-#define HEXTILE_ENCODE_TILE CONCAT2E(hextileEncodeTile,BPP)
-#define TEST_TILE_TYPE CONCAT2E(hextileTestTileType,BPP)
-
-int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg);
-int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
-                         rdr::U8* encoded, PIXEL_T bg);
-
-void HEXTILE_ENCODE(rdr::OutStream* os, const PixelBuffer* pb)
-{
-  Rect t;
-  PIXEL_T buf[256];
-  PIXEL_T oldBg = 0, oldFg = 0;
-  bool oldBgValid = false;
-  bool oldFgValid = false;
-  rdr::U8 encoded[256*(BPP/8)];
-
-  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
-
-    t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
-
-    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
-
-      t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
-
-      pb->getImage(buf, t);
-
-      PIXEL_T bg = 0, fg = 0;
-      int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg);
-
-      if (!oldBgValid || oldBg != bg) {
-        tileType |= hextileBgSpecified;
-        oldBg = bg;
-        oldBgValid = true;
-      }
-
-      int encodedLen = 0;
-
-      if (tileType & hextileAnySubrects) {
-
-        if (tileType & hextileSubrectsColoured) {
-          oldFgValid = false;
-        } else {
-          if (!oldFgValid || oldFg != fg) {
-            tileType |= hextileFgSpecified;
-            oldFg = fg;
-            oldFgValid = true;
-          }
-        }
-
-        encodedLen = HEXTILE_ENCODE_TILE(buf, t.width(), t.height(), tileType,
-                                         encoded, bg);
-
-        if (encodedLen < 0) {
-          pb->getImage(buf, t);
-          os->writeU8(hextileRaw);
-          os->writeBytes(buf, t.width() * t.height() * (BPP/8));
-          oldBgValid = oldFgValid = false;
-          continue;
-        }
-      }
-
-      os->writeU8(tileType);
-      if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg);
-      if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg);
-      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
-    }
-  }
-}
-
-
-int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
-                         rdr::U8* encoded, PIXEL_T bg)
-{
-  rdr::U8* nSubrectsPtr = encoded;
-  *nSubrectsPtr = 0;
-  encoded++;
-
-  for (int y = 0; y < h; y++)
-  {
-    int x = 0;
-    while (x < w) {
-      if (*data == bg) {
-        x++;
-        data++;
-        continue;
-      }
-
-      // Find horizontal subrect first
-      PIXEL_T* ptr = data+1;
-      PIXEL_T* eol = data+w-x;
-      while (ptr < eol && *ptr == *data) ptr++;
-      int sw = ptr - data;
-
-      ptr = data + w;
-      int sh = 1;
-      while (sh < h-y) {
-        eol = ptr + sw;
-        while (ptr < eol)
-          if (*ptr++ != *data) goto endOfSubrect;
-        ptr += w - sw;
-        sh++;
-      }
-    endOfSubrect:
-
-      (*nSubrectsPtr)++;
-
-      if (tileType & hextileSubrectsColoured) {
-        if (encoded - nSubrectsPtr + (BPP/8) > w*h*(BPP/8)) return -1;
-#if (BPP == 8)
-        *encoded++ = *data;
-#elif (BPP == 16)
-        *encoded++ = ((rdr::U8*)data)[0];
-        *encoded++ = ((rdr::U8*)data)[1];
-#elif (BPP == 32)
-        *encoded++ = ((rdr::U8*)data)[0];
-        *encoded++ = ((rdr::U8*)data)[1];
-        *encoded++ = ((rdr::U8*)data)[2];
-        *encoded++ = ((rdr::U8*)data)[3];
-#endif
-      }
-
-      if (encoded - nSubrectsPtr + 2 > w*h*(BPP/8)) return -1;
-      *encoded++ = (x << 4) | y;
-      *encoded++ = ((sw-1) << 4) | (sh-1);
-
-      ptr = data+w;
-      PIXEL_T* eor = data+w*sh;
-      while (ptr < eor) {
-        eol = ptr + sw;
-        while (ptr < eol) *ptr++ = bg;
-        ptr += w - sw;
-      }
-      x += sw;
-      data += sw;
-    }
-  }
-  return encoded - nSubrectsPtr;
-}
-
-
-int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg)
-{
-  PIXEL_T pix1 = *data;
-  PIXEL_T* end = data + w * h;
-
-  PIXEL_T* ptr = data + 1;
-  while (ptr < end && *ptr == pix1)
-    ptr++;
-
-  if (ptr == end) {
-    *bg = pix1;
-    return 0;                   // solid-color tile
-  }
-
-  int count1 = ptr - data;
-  int count2 = 1;
-  PIXEL_T pix2 = *ptr++;
-  int tileType = hextileAnySubrects;
-
-  for (; ptr < end; ptr++) {
-    if (*ptr == pix1) {
-      count1++;
-    } else if (*ptr == pix2) {
-      count2++;
-    } else {
-      tileType |= hextileSubrectsColoured;
-      break;
-    }
-  }
-
-  if (count1 >= count2) {
-    *bg = pix1; *fg = pix2;
-  } else {
-    *bg = pix2; *fg = pix1;
-  }
-  return tileType;
-}
-
-#undef PIXEL_T
-#undef WRITE_PIXEL
-#undef HEXTILE_ENCODE
-#undef HEXTILE_ENCODE_TILE
-#undef TEST_TILE_TYPE
-}
diff --git a/common/rfb/hextileEncodeBetter.h b/common/rfb/hextileEncodeBetter.h
deleted file mode 100644 (file)
index bc9dcac..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2005 Constantin Kaplinsky.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-//
-// Hextile encoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-#include <rdr/OutStream.h>
-#include <rfb/hextileConstants.h>
-#include <rfb/Palette.h>
-
-#include <assert.h>
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP)
-#define HEXTILE_TILE CONCAT2E(HextileTile,BPP)
-#define HEXTILE_ENCODE CONCAT2E(hextileEncodeBetter,BPP)
-
-//
-// This class analyzes a separate tile and encodes its subrectangles.
-//
-
-class HEXTILE_TILE {
-
- public:
-
-  HEXTILE_TILE ();
-
-  //
-  // Initialize existing object instance with new tile data.
-  //
-  void newTile(const PIXEL_T *src, int w, int h);
-
-  //
-  // Flags can include: hextileRaw, hextileAnySubrects and
-  // hextileSubrectsColoured. Note that if hextileRaw is set, other
-  // flags make no sense. Also, hextileSubrectsColoured is meaningful
-  // only when hextileAnySubrects is set as well.
-  //
-  int getFlags() const { return m_flags; }
-
-  //
-  // Returns the size of encoded subrects data, including subrect count.
-  // The size is zero if flags do not include hextileAnySubrects.
-  //
-  int getSize() const { return m_size; }
-
-  //
-  // Return optimal background.
-  //
-  int getBackground() const { return m_background; }
-
-  //
-  // Return foreground if flags include hextileSubrectsColoured.
-  //
-  int getForeground() const { return m_foreground; }
-
-  //
-  // Encode subrects. This function may be called only if
-  // hextileAnySubrects bit is set in flags. The buffer size should be
-  // big enough to store at least the number of bytes returned by the
-  // getSize() method.
-  //
-  void encode(rdr::U8* dst) const;
-
- protected:
-
-  //
-  // Analyze the tile pixels, fill in all the data fields.
-  //
-  void analyze();
-
-  const PIXEL_T *m_tile;
-  int m_width;
-  int m_height;
-
-  int m_size;
-  int m_flags;
-  PIXEL_T m_background;
-  PIXEL_T m_foreground;
-
-  int m_numSubrects;
-  rdr::U8 m_coords[256 * 2];
-  PIXEL_T m_colors[256];
-
- private:
-
-  bool m_processed[16][16];
-  Palette m_pal;
-};
-
-HEXTILE_TILE::HEXTILE_TILE()
-  : m_tile(NULL), m_width(0), m_height(0),
-    m_size(0), m_flags(0), m_background(0), m_foreground(0),
-    m_numSubrects(0)
-{
-}
-
-void HEXTILE_TILE::newTile(const PIXEL_T *src, int w, int h)
-{
-  m_tile = src;
-  m_width = w;
-  m_height = h;
-
-  analyze();
-}
-
-void HEXTILE_TILE::analyze()
-{
-  assert(m_tile && m_width && m_height);
-
-  const PIXEL_T *ptr = m_tile;
-  const PIXEL_T *end = &m_tile[m_width * m_height];
-  PIXEL_T color = *ptr++;
-  while (ptr != end && *ptr == color)
-    ptr++;
-
-  // Handle solid tile
-  if (ptr == end) {
-    m_background = m_tile[0];
-    m_flags = 0;
-    m_size = 0;
-    return;
-  }
-
-  // Compute number of complete rows of the same color, at the top
-  int y = (ptr - m_tile) / m_width;
-
-  PIXEL_T *colorsPtr = m_colors;
-  rdr::U8 *coordsPtr = m_coords;
-  m_pal.clear();
-  m_numSubrects = 0;
-
-  // Have we found the first subrect already?
-  if (y > 0) {
-    *colorsPtr++ = color;
-    *coordsPtr++ = 0;
-    *coordsPtr++ = (rdr::U8)(((m_width - 1) << 4) | ((y - 1) & 0x0F));
-    m_pal.insert(color, 1);
-    m_numSubrects++;
-  }
-
-  memset(m_processed, 0, 16 * 16 * sizeof(bool));
-
-  int x, sx, sy, sw, sh, max_x;
-
-  for (; y < m_height; y++) {
-    for (x = 0; x < m_width; x++) {
-      // Skip pixels that were processed earlier
-      if (m_processed[y][x]) {
-        continue;
-      }
-      // Determine dimensions of the horizontal subrect
-      color = m_tile[y * m_width + x];
-      for (sx = x + 1; sx < m_width; sx++) {
-        if (m_tile[y * m_width + sx] != color)
-          break;
-      }
-      sw = sx - x;
-      max_x = sx;
-      for (sy = y + 1; sy < m_height; sy++) {
-        for (sx = x; sx < max_x; sx++) {
-          if (m_tile[sy * m_width + sx] != color)
-            goto done;
-        }
-      }
-    done:
-      sh = sy - y;
-
-      // Save properties of this subrect
-      *colorsPtr++ = color;
-      *coordsPtr++ = (rdr::U8)((x << 4) | (y & 0x0F));
-      *coordsPtr++ = (rdr::U8)(((sw - 1) << 4) | ((sh - 1) & 0x0F));
-
-      if (!m_pal.insert(color, 1) || (m_pal.size() > (48 + 2 * BPP))) {
-        // Handle palette overflow
-        m_flags = hextileRaw;
-        m_size = 0;
-        return;
-      }
-
-      m_numSubrects++;
-
-      // Mark pixels of this subrect as processed, below this row
-      for (sy = y + 1; sy < y + sh; sy++) {
-        for (sx = x; sx < x + sw; sx++)
-          m_processed[sy][sx] = true;
-      }
-
-      // Skip processed pixels of this row
-      x += (sw - 1);
-    }
-  }
-
-  // Save number of colors in this tile (should be no less than 2)
-  int numColors = m_pal.size();
-  assert(numColors >= 2);
-
-  m_background = (PIXEL_T)m_pal.getColour(0);
-  m_flags = hextileAnySubrects;
-  int numSubrects = m_numSubrects - m_pal.getCount(0);
-
-  if (numColors == 2) {
-    // Monochrome tile
-    m_foreground = (PIXEL_T)m_pal.getColour(1);
-    m_size = 1 + 2 * numSubrects;
-  } else {
-    // Colored tile
-    m_flags |= hextileSubrectsColoured;
-    m_size = 1 + (2 + (BPP/8)) * numSubrects;
-  }
-}
-
-void HEXTILE_TILE::encode(rdr::U8 *dst) const
-{
-  assert(m_numSubrects && (m_flags & hextileAnySubrects));
-
-  // Zero subrects counter
-  rdr::U8 *numSubrectsPtr = dst;
-  *dst++ = 0;
-
-  for (int i = 0; i < m_numSubrects; i++) {
-    if (m_colors[i] == m_background)
-      continue;
-
-    if (m_flags & hextileSubrectsColoured) {
-#if (BPP == 8)
-      *dst++ = m_colors[i];
-#elif (BPP == 16)
-      *dst++ = ((rdr::U8*)&m_colors[i])[0];
-      *dst++ = ((rdr::U8*)&m_colors[i])[1];
-#elif (BPP == 32)
-      *dst++ = ((rdr::U8*)&m_colors[i])[0];
-      *dst++ = ((rdr::U8*)&m_colors[i])[1];
-      *dst++ = ((rdr::U8*)&m_colors[i])[2];
-      *dst++ = ((rdr::U8*)&m_colors[i])[3];
-#endif
-    }
-    *dst++ = m_coords[i * 2];
-    *dst++ = m_coords[i * 2 + 1];
-
-    (*numSubrectsPtr)++;
-  }
-
-  assert(dst - numSubrectsPtr == m_size);
-}
-
-//
-// Main encoding function.
-//
-
-void HEXTILE_ENCODE(rdr::OutStream* os, const PixelBuffer* pb)
-{
-  Rect t;
-  PIXEL_T buf[256];
-  PIXEL_T oldBg = 0, oldFg = 0;
-  bool oldBgValid = false;
-  bool oldFgValid = false;
-  rdr::U8 encoded[256*(BPP/8)];
-
-  HEXTILE_TILE tile;
-
-  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
-
-    t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
-
-    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
-
-      t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
-
-      pb->getImage(buf, t);
-
-      tile.newTile(buf, t.width(), t.height());
-      int tileType = tile.getFlags();
-      int encodedLen = tile.getSize();
-
-      if ( (tileType & hextileRaw) != 0 ||
-           encodedLen >= t.width() * t.height() * (BPP/8)) {
-        os->writeU8(hextileRaw);
-        os->writeBytes(buf, t.width() * t.height() * (BPP/8));
-        oldBgValid = oldFgValid = false;
-        continue;
-      }
-
-      PIXEL_T bg = tile.getBackground();
-      PIXEL_T fg = 0;
-
-      if (!oldBgValid || oldBg != bg) {
-        tileType |= hextileBgSpecified;
-        oldBg = bg;
-        oldBgValid = true;
-      }
-
-      if (tileType & hextileAnySubrects) {
-        if (tileType & hextileSubrectsColoured) {
-          oldFgValid = false;
-        } else {
-          fg = tile.getForeground();
-          if (!oldFgValid || oldFg != fg) {
-            tileType |= hextileFgSpecified;
-            oldFg = fg;
-            oldFgValid = true;
-          }
-        }
-        tile.encode(encoded);
-      }
-
-      os->writeU8(tileType);
-      if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg);
-      if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg);
-      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
-    }
-  }
-}
-
-#undef PIXEL_T
-#undef WRITE_PIXEL
-#undef HEXTILE_TILE
-#undef HEXTILE_ENCODE
-}
diff --git a/common/rfb/rreDecode.h b/common/rfb/rreDecode.h
deleted file mode 100644 (file)
index f9fdcfc..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-//
-// RRE decoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-#include <rdr/InStream.h>
-#include <rfb/Exception.h>
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL CONCAT2E(readOpaque,BPP)
-#define RRE_DECODE CONCAT2E(rreDecode,BPP)
-
-void RRE_DECODE (const Rect& r, rdr::InStream* is,
-                 const PixelFormat& pf, ModifiablePixelBuffer* pb)
-{
-  int nSubrects = is->readU32();
-  PIXEL_T bg = is->READ_PIXEL();
-  pb->fillRect(pf, r, &bg);
-
-  for (int i = 0; i < nSubrects; i++) {
-    PIXEL_T pix = is->READ_PIXEL();
-    int x = is->readU16();
-    int y = is->readU16();
-    int w = is->readU16();
-    int h = is->readU16();
-
-    if (((x+w) > r.width()) || ((y+h) > r.height()))
-      throw Exception ("RRE decode error");
-
-    pb->fillRect(pf, Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), &pix);
-  }
-}
-
-#undef PIXEL_T
-#undef READ_PIXEL
-#undef RRE_DECODE
-}
diff --git a/common/rfb/rreEncode.h b/common/rfb/rreEncode.h
deleted file mode 100644 (file)
index c8bbee7..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-//
-// RRE encoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-//
-// The data argument to RRE_ENCODE contains the pixel data, and it writes the
-// encoded version to the given OutStream.  If the encoded version exceeds w*h
-// it aborts and returns -1, otherwise it returns the number of subrectangles.
-//
-
-#include <rdr/OutStream.h>
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP)
-#define RRE_ENCODE CONCAT2E(rreEncode,BPP)
-
-int RRE_ENCODE (PIXEL_T* data, int w, int h, rdr::OutStream* os, PIXEL_T bg)
-{
-  os->WRITE_PIXEL(bg);
-
-  int nSubrects = 0;
-
-  for (int y = 0; y < h; y++)
-  {
-    int x = 0;
-    while (x < w) {
-      if (*data == bg) {
-        x++;
-        data++;
-        continue;
-      }
-
-      // Find horizontal subrect first
-      PIXEL_T* ptr = data+1;
-      PIXEL_T* eol = data+w-x;
-      while (ptr < eol && *ptr == *data) ptr++;
-      int sw = ptr - data;
-
-      ptr = data + w;
-      int sh = 1;
-      while (sh < h-y) {
-        eol = ptr + sw;
-        while (ptr < eol)
-          if (*ptr++ != *data) goto endOfHorizSubrect;
-        ptr += w - sw;
-        sh++;
-      }
-    endOfHorizSubrect:
-
-      // Find vertical subrect
-      int vh;
-      for (vh = sh; vh < h-y; vh++)
-        if (data[vh*w] != *data) break;
-
-      if (vh != sh) {
-        ptr = data+1;
-        int vw;
-        for (vw = 1; vw < sw; vw++) {
-          for (int i = 0; i < vh; i++)
-            if (ptr[i*w] != *data) goto endOfVertSubrect;
-          ptr++;
-        }
-      endOfVertSubrect:
-
-        // If vertical subrect bigger than horizontal then use that.
-        if (sw*sh < vw*vh) {
-          sw = vw;
-          sh = vh;
-        }
-      }
-
-      nSubrects++;
-      os->WRITE_PIXEL(*data);
-      os->writeU16(x);
-      os->writeU16(y);
-      os->writeU16(sw);
-      os->writeU16(sh);
-
-      ptr = data+w;
-      PIXEL_T* eor = data+w*sh;
-      while (ptr < eor) {
-        eol = ptr + sw;
-        while (ptr < eol) *ptr++ = bg;
-        ptr += w - sw;
-      }
-      x += sw;
-      data += sw;
-    }
-  }
-
-  return nSubrects;
-}
-
-#undef PIXEL_T
-#undef WRITE_PIXEL
-#undef RRE_ENCODE
-}
diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h
deleted file mode 100644 (file)
index 8f77aeb..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.
- * Copyright 2004-2005 Cendio AB.
- * Copyright 2009-2015 Pierre Ossman for Cendio AB
- * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
- *    
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-//
-// Tight decoding functions.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-
-#if BPP == 32
-
-void
-TightDecoder::FilterGradient24(const rdr::U8 *inbuf,
-                               const PixelFormat& pf, PIXEL_T* outbuf,
-                               int stride, const Rect& r)
-{
-  int x, y, c;
-  rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
-  rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
-  rdr::U8 pix[3]; 
-  int est[3]; 
-
-  memset(prevRow, 0, sizeof(prevRow));
-
-  // Set up shortcut variables
-  int rectHeight = r.height();
-  int rectWidth = r.width();
-
-  for (y = 0; y < rectHeight; y++) {
-    for (x = 0; x < rectWidth; x++) {
-      /* First pixel in a row */
-      if (x == 0) {
-        for (c = 0; c < 3; c++) {
-          pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];
-          thisRow[c] = pix[c];
-        }
-        pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
-        continue;
-      }
-
-      for (c = 0; c < 3; c++) {
-        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
-        if (est[c] > 0xff) {
-          est[c] = 0xff;
-        } else if (est[c] < 0) {
-          est[c] = 0;
-        }
-        pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c];
-        thisRow[x*3+c] = pix[c];
-      }
-      pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
-    }
-
-    memcpy(prevRow, thisRow, sizeof(prevRow));
-  }
-}
-
-#endif
-
-#if BPP != 8
-
-void TightDecoder::FilterGradient(const rdr::U8* inbuf,
-                                  const PixelFormat& pf, PIXEL_T* outbuf,
-                                  int stride, const Rect& r)
-{
-  int x, y, c;
-  static rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
-  static rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
-  rdr::U8 pix[3]; 
-  int est[3]; 
-
-  memset(prevRow, 0, sizeof(prevRow));
-
-  // Set up shortcut variables
-  int rectHeight = r.height();
-  int rectWidth = r.width();
-
-  for (y = 0; y < rectHeight; y++) {
-    for (x = 0; x < rectWidth; x++) {
-      /* First pixel in a row */
-      if (x == 0) {
-        pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);
-        for (c = 0; c < 3; c++)
-          pix[c] += prevRow[c];
-
-        memcpy(thisRow, pix, sizeof(pix));
-
-        pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
-
-        continue;
-      }
-
-      for (c = 0; c < 3; c++) {
-        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
-        if (est[c] > 255) {
-          est[c] = 255;
-        } else if (est[c] < 0) {
-          est[c] = 0;
-        }
-      }
-
-      pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1);
-      for (c = 0; c < 3; c++)
-        pix[c] += est[c];
-
-      memcpy(&thisRow[x*3], pix, sizeof(pix));
-
-      pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
-    }
-
-    memcpy(prevRow, thisRow, sizeof(prevRow));
-  }
-}
-
-#endif
-
-void TightDecoder::FilterPalette(const PIXEL_T* palette, int palSize,
-                                 const rdr::U8* inbuf, PIXEL_T* outbuf,
-                                 int stride, const Rect& r)
-{
-  // Indexed color
-  int x, h = r.height(), w = r.width(), b, pad = stride - w;
-  PIXEL_T* ptr = outbuf;
-  rdr::U8 bits;
-  const rdr::U8* srcPtr = inbuf;
-  if (palSize <= 2) {
-    // 2-color palette
-    while (h > 0) {
-      for (x = 0; x < w / 8; x++) {
-        bits = *srcPtr++;
-        for (b = 7; b >= 0; b--) {
-          *ptr++ = palette[bits >> b & 1];
-        }
-      }
-      if (w % 8 != 0) {
-        bits = *srcPtr++;
-        for (b = 7; b >= 8 - w % 8; b--) {
-          *ptr++ = palette[bits >> b & 1];
-        }
-      }
-      ptr += pad;
-      h--;
-    }
-  } else {
-    // 256-color palette
-    while (h > 0) {
-      PIXEL_T *endOfRow = ptr + w;
-      while (ptr < endOfRow) {
-        *ptr++ = palette[*srcPtr++];
-      }
-      ptr += pad;
-      h--;
-    }
-  }
-}
-
-#undef PIXEL_T
-}
diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h
deleted file mode 100644 (file)
index 998e51e..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-//
-// ZRLE decoding function.
-//
-// This file is #included after having set the following macro:
-// BPP                - 8, 16 or 32
-
-namespace rfb {
-
-// CONCAT2E concatenates its arguments, expanding them if they are macros
-
-#ifndef CONCAT2E
-#define CONCAT2(a,b) a##b
-#define CONCAT2E(a,b) CONCAT2(a,b)
-#endif
-
-#ifdef CPIXEL
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL(is) CONCAT2E(readOpaque,CPIXEL)(is)
-#define ZRLE_DECODE CONCAT2E(zrleDecode,CPIXEL)
-#else
-#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL(is) is->CONCAT2E(readOpaque,BPP)()
-#define ZRLE_DECODE CONCAT2E(zrleDecode,BPP)
-#endif
-
-void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
-                  rdr::ZlibInStream* zis,
-                  const PixelFormat& pf, ModifiablePixelBuffer* pb)
-{
-  int length = is->readU32();
-  zis->setUnderlying(is, length);
-  Rect t;
-  PIXEL_T buf[64 * 64];
-
-  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {
-
-    t.br.y = __rfbmin(r.br.y, t.tl.y + 64);
-
-    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
-
-      t.br.x = __rfbmin(r.br.x, t.tl.x + 64);
-
-      zlibHasData(zis, 1);
-      int mode = zis->readU8();
-      bool rle = mode & 128;
-      int palSize = mode & 127;
-      PIXEL_T palette[128];
-
-#ifdef CPIXEL
-      zlibHasData(zis, 3 * palSize);
-#else
-      zlibHasData(zis, BPP/8 * palSize);
-#endif
-      for (int i = 0; i < palSize; i++) {
-        palette[i] = READ_PIXEL(zis);
-      }
-
-      if (palSize == 1) {
-        PIXEL_T pix = palette[0];
-        pb->fillRect(pf, t, &pix);
-        continue;
-      }
-
-      if (!rle) {
-        if (palSize == 0) {
-
-          // raw
-
-#ifdef CPIXEL
-          zlibHasData(zis, 3 * t.area());
-          for (PIXEL_T* ptr = buf; ptr < buf+t.area(); ptr++) {
-            *ptr = READ_PIXEL(zis);
-          }
-#else
-          zlibHasData(zis, BPP/8 * t.area());
-          zis->readBytes(buf, t.area() * (BPP / 8));
-#endif
-
-        } else {
-
-          // packed pixels
-          int bppp = ((palSize > 16) ? 8 :
-                      ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
-
-          PIXEL_T* ptr = buf;
-
-          for (int i = 0; i < t.height(); i++) {
-            PIXEL_T* eol = ptr + t.width();
-            rdr::U8 byte = 0;
-            rdr::U8 nbits = 0;
-
-            while (ptr < eol) {
-              if (nbits == 0) {
-                zlibHasData(zis, 1);
-                byte = zis->readU8();
-                nbits = 8;
-              }
-              nbits -= bppp;
-              rdr::U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127;
-              *ptr++ = palette[index];
-            }
-          }
-        }
-
-      } else {
-
-        if (palSize == 0) {
-
-          // plain RLE
-
-          PIXEL_T* ptr = buf;
-          PIXEL_T* end = ptr + t.area();
-          while (ptr < end) {
-#ifdef CPIXEL
-            zlibHasData(zis, 3);
-#else
-            zlibHasData(zis, BPP/8);
-#endif
-            PIXEL_T pix = READ_PIXEL(zis);
-            int len = 1;
-            int b;
-            do {
-              zlibHasData(zis, 1);
-              b = zis->readU8();
-              len += b;
-            } while (b == 255);
-
-            if (end - ptr < len) {
-              throw Exception ("ZRLE decode error");
-            }
-
-            while (len-- > 0) *ptr++ = pix;
-
-          }
-        } else {
-
-          // palette RLE
-
-          PIXEL_T* ptr = buf;
-          PIXEL_T* end = ptr + t.area();
-          while (ptr < end) {
-            zlibHasData(zis, 1);
-            int index = zis->readU8();
-            int len = 1;
-            if (index & 128) {
-              int b;
-              do {
-                zlibHasData(zis, 1);
-                b = zis->readU8();
-                len += b;
-              } while (b == 255);
-
-              if (end - ptr < len) {
-                throw Exception ("ZRLE decode error");
-              }
-            }
-
-            index &= 127;
-
-            PIXEL_T pix = palette[index];
-
-            while (len-- > 0) *ptr++ = pix;
-          }
-        }
-      }
-
-      pb->imageRect(pf, t, buf);
-    }
-  }
-
-  zis->flushUnderlying();
-  zis->setUnderlying(NULL, 0);
-}
-
-#undef ZRLE_DECODE
-#undef READ_PIXEL
-#undef PIXEL_T
-}