Optimized the code that analyzes the tile contents.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@327 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/rfb/hextileEncodeBetter.h b/rfb/hextileEncodeBetter.h
index 78126b8..08adc7d 100644
--- a/rfb/hextileEncodeBetter.h
+++ b/rfb/hextileEncodeBetter.h
@@ -94,15 +94,9 @@
  protected:
 
   //
-  // Fill in m_coords[], m_colors[], m_pal and set m_numSubrects.
+  // Analyze the tile pixels, fill in all the data fields.
   //
-  void buildTables();
-
-  //
-  // Fill in m_size, m_flags, m_background and m_foreground.
-  // Must be called after buildTables(), before encode().
-  //
-  void computeSize();
+  void analyze();
 
   const PIXEL_T *m_tile;
   int m_width;
@@ -136,26 +130,49 @@
   m_width = w;
   m_height = h;
 
-  // NOTE: These two methods should always be called from this place
-  //       only, and exactly in this order.
-  buildTables();
-  computeSize();
+  analyze();
 }
 
-void HEXTILE_TILE::buildTables()
+void HEXTILE_TILE::analyze()
 {
   assert(m_tile && m_width && m_height);
 
-  m_numSubrects = 0;
-  memset(m_processed, 0, 16 * 16 * sizeof(bool));
+  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.reset();
+  m_numSubrects = 0;
 
-  int x, y, sx, sy, sw, sh, max_x;
-  PIXEL_T color;
-  PIXEL_T *colorsPtr = &m_colors[0];
-  rdr::U8 *coordsPtr = &m_coords[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, BPP);
+    m_numSubrects++;
+  }
 
-  for (y = 0; y < m_height; y++) {
+  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]) {
@@ -183,8 +200,12 @@
       *coordsPtr++ = (rdr::U8)((x << 4) | (y & 0x0F));
       *coordsPtr++ = (rdr::U8)(((sw - 1) << 4) | ((sh - 1) & 0x0F));
 
-      if (m_pal.insert(color, 1, BPP) == 0)
-        return;                 // palette overflow
+      if (m_pal.insert(color, 1, BPP) == 0) {
+        // Handle palette overflow
+        m_flags = hextileRaw;
+        m_size = 0;
+        return;
+      }
 
       m_numSubrects++;
 
@@ -198,45 +219,24 @@
       x += (sw - 1);
     }
   }
-}
 
-void HEXTILE_TILE::computeSize()
-{
-  // Save the number of colors
+  // Save number of colors in this tile (should be no less than 2)
   int numColors = m_pal.getNumColors();
+  assert(numColors >= 2);
 
-  // Handle solid tile
-  if (numColors == 1) {
-    m_background = m_tile[0];
-    m_flags = 0;
-    m_size = 0;
-    return;
-  }
-
-  // Handle monochrome tile - choose background and foreground
-  if (numColors == 2) {
-    int bgCount = m_pal.getCount(0);
-    m_background = (PIXEL_T)m_pal.getEntry(0);
-    m_foreground = (PIXEL_T)m_pal.getEntry(1);
-
-    m_flags = hextileAnySubrects;
-    m_size = 1 + 2 * (m_numSubrects - bgCount);
-    return;
-  }
-
-  // Handle raw-encoded tile (there was palette overflow)
-  if (numColors == 0) {
-    m_flags = hextileRaw;
-    m_size = 0;
-    return;
-  }
-
-  // Handle colored tile - choose the best background color
-  int bgCount = m_pal.getCount(0);
   m_background = (PIXEL_T)m_pal.getEntry(0);
+  m_flags = hextileAnySubrects;
+  int numSubrects = m_numSubrects - m_pal.getCount(0);
 
-  m_flags = hextileAnySubrects | hextileSubrectsColoured;
-  m_size = 1 + (2 + (BPP/8)) * (m_numSubrects - bgCount);
+  if (numColors == 2) {
+    // Monochrome tile
+    m_foreground = (PIXEL_T)m_pal.getEntry(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