Move image encoding logic into a central EncodeManager class

This allows us to apply a lot more server logic
independently of which encoder is in use.

Most of this class are things moved over from the
Tight encoder.
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index e1424b7..618048a 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -73,7 +73,7 @@
     ackedOffset(0), sentOffset(0), congWindow(0), congestionTimer(this),
     server(server_), updates(false),
     drawRenderedCursor(false), removeRenderedCursor(false),
-    continuousUpdates(false),
+    continuousUpdates(false), encodeManager(this),
     updateTimer(this), pointerEventTime(0),
     accessRights(AccessDefault), startTime(time(0))
 {
@@ -81,8 +81,6 @@
   peerEndpoint.buf = sock->getPeerEndpoint();
   VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf);
 
-  memset(encoders, 0, sizeof(encoders));
-
   // Configure the socket
   setSocketTimeouts();
   lastEventTime = time(0);
@@ -108,9 +106,6 @@
   // Remove this client from the server
   server->clients.remove(this);
 
-  for (int i = 0; i <= encodingMax; i++)
-    delete encoders[i];
-
   delete [] fenceData;
 }
 
@@ -1027,72 +1022,19 @@
   }
 
   if (!ui.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {
-    std::vector<Rect> rects;
-    std::vector<Rect>::const_iterator i;
-    int encoding;
+    RenderedCursor *cursor;
 
-    Encoder* encoder;
-    PixelBuffer* pb;
-
-    // Make sure the encoder has the latest settings
-    encoding = cp.currentEncoding();
-
-    if (!encoders[encoding])
-      encoders[encoding] = Encoder::createEncoder(encoding, this);
-
-    encoder = encoders[encoding];
-
-    encoder->setCompressLevel(cp.compressLevel);
-    encoder->setQualityLevel(cp.qualityLevel);
-    encoder->setFineQualityLevel(cp.fineQualityLevel, cp.subsampling);
-
-    // Compute the number of rectangles. Tight encoder makes the things more
-    // complicated as compared to the original VNC4.
-    int nRects = (ui.copied.numRects() +
-                  (drawRenderedCursor ? 1 : 0));
-
-    ui.changed.get_rects(&rects);
-    for (i = rects.begin(); i != rects.end(); i++) {
-      if (i->width() && i->height()) {
-        int nUpdateRects = encoder->getNumRects(*i);
-        if (nUpdateRects == 0 && cp.currentEncoding() == encodingTight) {
-          // With Tight encoding and LastRect support, the client does not
-          // care about the number of rectangles in the update - it will
-          // stop parsing when it encounters a LastRect "rectangle".
-          // In this case, pretend to send 65535 rectangles.
-          nRects = 0xFFFF;  break;
-        }
-        else
-          nRects += nUpdateRects;
-      }
-    }
-
-    writeRTTPing();
-    
-    writer()->writeFramebufferUpdateStart(nRects);
-
-    ui.copied.get_rects(&rects);
-    for (i = rects.begin(); i != rects.end(); i++)
-      writer()->writeCopyRect(*i, i->tl.x - ui.copy_delta.x,
-                              i->tl.y - ui.copy_delta.y);
-
-    pb = server->getPixelBuffer();
-
-    ui.changed.get_rects(&rects);
-    for (i = rects.begin(); i != rects.end(); i++)
-      encoder->writeRect(*i, pb);
-
-    if (drawRenderedCursor) {
-      renderedCursorRect = server->renderedCursor.getEffectiveRect();
-      encoder->writeRect(renderedCursorRect, &server->renderedCursor);
-
-      drawRenderedCursor = false;
-    }
-
-    writer()->writeFramebufferUpdateEnd();
+    cursor = NULL;
+    if (drawRenderedCursor)
+      cursor = &server->renderedCursor;
 
     writeRTTPing();
 
+    encodeManager.writeUpdate(ui, server->getPixelBuffer(), cursor);
+
+    writeRTTPing();
+
+    drawRenderedCursor = false;
     requested.clear();
     updates.clear();
   }