Fixed the bug with crashing vncviewer when it works in the 
scaling mode and scale < 10%.
Scale part of vncviewer code improvements.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2232 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/ScaleFilters.cxx b/common/rfb/ScaleFilters.cxx
index cd08f67..2e6b88d 100644
--- a/common/rfb/ScaleFilters.cxx
+++ b/common/rfb/ScaleFilters.cxx
@@ -87,9 +87,10 @@
   return filter;

 }

 

-void ScaleFilters::makeWeightTabs(int filter_id, int src_x, int dst_x, double ratio, SFilterWeightTab **pWeightTabs) {

+void ScaleFilters::makeWeightTabs(int filter_id, int src_x, int dst_x, SFilterWeightTab **pWeightTabs) {

   double sxc;

   double offset = 0.5;

+  double ratio = (double)dst_x / src_x;

 

   SFilter sFilter = filters[filter_id];

   

diff --git a/common/rfb/ScaleFilters.h b/common/rfb/ScaleFilters.h
index 75b1e7f..62075d5 100644
--- a/common/rfb/ScaleFilters.h
+++ b/common/rfb/ScaleFilters.h
@@ -60,7 +60,7 @@
 

     SFilter &operator[](unsigned int filter_id);

 

-    void makeWeightTabs(int filter, int src_x, int dst_x, double ratio, SFilterWeightTab **weightTabs);

+    void makeWeightTabs(int filter, int src_x, int dst_x, SFilterWeightTab **weightTabs);

 

   protected:

     void initFilters();

diff --git a/common/rfb/ScaledPixelBuffer.cxx b/common/rfb/ScaledPixelBuffer.cxx
index 6b95058..1be029d 100644
--- a/common/rfb/ScaledPixelBuffer.cxx
+++ b/common/rfb/ScaledPixelBuffer.cxx
@@ -30,7 +30,7 @@
 
 ScaledPixelBuffer::ScaledPixelBuffer(U8 **src_data_, int src_width_,
                                      int src_height_, int scale, PixelFormat pf_)
-  : scale_ratio(1), scaleFilterID(scaleFilterBicubic),
+  : scale(100), scale_ratio_x(1), scale_ratio_y(1), scaleFilterID(scaleFilterBicubic),
     xWeightTabs(0), yWeightTabs(0), scaled_data(0) {
 
   setSourceBuffer(src_data_, src_width_, src_height_);
@@ -38,8 +38,8 @@
 }
 
 ScaledPixelBuffer::ScaledPixelBuffer() 
-  : src_width(0), src_height(0), scaled_width(0), scaled_height(0),
-    scale_ratio(1), scaleFilterID(scaleFilterBicubic),
+  : src_width(0), src_height(0), scaled_width(0), scaled_height(0), scale(100), 
+    scale_ratio_x(1), scale_ratio_y(1), scaleFilterID(scaleFilterBicubic),
     xWeightTabs(0), yWeightTabs(0), src_data(0), scaled_data(0) {
   memset(&pf, 0, sizeof(pf));
 }
@@ -67,8 +67,8 @@
   src_width  = w;
   src_height = h;
   calculateScaledBufferSize();
-  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, scale_ratio, &xWeightTabs);
-  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, scale_ratio, &yWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
 }
 
 void ScaledPixelBuffer::setPF(const PixelFormat &pf_) {
@@ -76,13 +76,13 @@
   pf = pf_;
 }
 
-void ScaledPixelBuffer::setScaleRatio(double scale_ratio_) {
-  if (scale_ratio != scale_ratio_) {
+void ScaledPixelBuffer::setScale(int scale_) {
+  if (scale != scale_ && scale_ > 0) {
     freeWeightTabs();
-    scale_ratio = scale_ratio_;
+    scale = scale_;
     calculateScaledBufferSize();
-    scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, scale_ratio, &xWeightTabs);
-    scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, scale_ratio, &yWeightTabs);
+    scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
+    scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
   }
 }
 
@@ -166,11 +166,12 @@
 Rect ScaledPixelBuffer::calculateScaleBoundary(const Rect& r) {
   int x_start, y_start, x_end, y_end;
   double radius = scaleFilters[scaleFilterID].radius;
-  double translate = 0.5*scale_ratio - 0.5;
-  x_start = (int)ceil(scale_ratio*(r.tl.x-radius) + translate);
-  y_start = (int)ceil(scale_ratio*(r.tl.y-radius) + translate);
-  x_end = (int)ceil(scale_ratio*(r.br.x+radius) + translate);
-  y_end = (int)ceil(scale_ratio*(r.br.y+radius) + translate);
+  double translate_x = 0.5*scale_ratio_x - 0.5;
+  double translate_y = 0.5*scale_ratio_y - 0.5;
+  x_start = (int)ceil(scale_ratio_x*(r.tl.x-radius) + translate_x);
+  y_start = (int)ceil(scale_ratio_y*(r.tl.y-radius) + translate_y);
+  x_end = (int)ceil(scale_ratio_x*(r.br.x+radius) + translate_x);
+  y_end = (int)ceil(scale_ratio_y*(r.br.y+radius) + translate_y);
   if (x_start < 0) x_start = 0;
   if (y_start < 0) y_start = 0;
   if (x_end > scaled_width) x_end = scaled_width;
@@ -179,6 +180,9 @@
 }
 
 void ScaledPixelBuffer::calculateScaledBufferSize() {
+  double scale_ratio = (double)scale / 100;
   scaled_width  = (int)ceil(src_width  * scale_ratio);
   scaled_height = (int)ceil(src_height * scale_ratio);
+  scale_ratio_x = (double)scaled_width / src_width;
+  scale_ratio_y = (double)scaled_height / src_height;
 }
diff --git a/common/rfb/ScaledPixelBuffer.h b/common/rfb/ScaledPixelBuffer.h
index ca0ddf5..b41c59a 100644
--- a/common/rfb/ScaledPixelBuffer.h
+++ b/common/rfb/ScaledPixelBuffer.h
@@ -49,8 +49,9 @@
     int getSrcWidth()  const { return src_width; }
     int getSrcHeight() const { return src_height; }
     int area() const { return scaled_width * scaled_height; }
-    int getScale() const { return int(scale_ratio * 100 + 0.5); }
-    double getScaleRatio() const { return scale_ratio; }
+    int getScale() const { return scale; }
+    double getScaleRatioX() const { return scale_ratio_x; }
+    double getScaleRatioY() const { return scale_ratio_y; }
 
     // Pixel manipulation routines
     inline U32 getSourcePixel(int x, int y);
@@ -74,8 +75,7 @@
     void setPF(const PixelFormat &pf);
 
     // Set the new scale, in percent
-    virtual void setScale(int scale) { setScaleRatio(double(scale)/100.0); }
-    virtual void setScaleRatio(double scale_ratio);
+    virtual void setScale(int scale);
 
     // Scale rect from the source image buffer to the destination buffer
     // using the current interpolation method
@@ -99,8 +99,10 @@
     int src_height;
     int scaled_width;
     int scaled_height;
+    int scale;
+    double scale_ratio_x;
+    double scale_ratio_y;
     PixelFormat pf;
-    double scale_ratio;
     unsigned int scaleFilterID;
     ScaleFilters scaleFilters;
     SFilterWeightTab *xWeightTabs;
diff --git a/win/rfb_win32/ScaledDIBSectionBuffer.cxx b/win/rfb_win32/ScaledDIBSectionBuffer.cxx
index 1a287c0..5ac8361 100644
--- a/win/rfb_win32/ScaledDIBSectionBuffer.cxx
+++ b/win/rfb_win32/ScaledDIBSectionBuffer.cxx
@@ -39,19 +39,19 @@
   if (src_buffer) delete src_buffer;
 }
 
-void ScaledDIBSectionBuffer::setScaleRatio(double scale_ratio_) {
-  if (scale_ratio == scale_ratio_ || scale_ratio <= 0) return;
+void ScaledDIBSectionBuffer::setScale(int scale_) {
+  if (scale == scale_ || scale_ <= 0) return;
 
-  scale_ratio = scale_ratio_;
-  if (scale_ratio == 1) scaling = false;
+  scale = scale_;
+  if (scale == 100) scaling = false;
   else scaling = true;
   
   // FIXME:
   // Calculate the scale weight tabs must be in the ScalePixelBuffer class
   freeWeightTabs();
   calculateScaledBufferSize();
-  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, scale_ratio, &xWeightTabs);
-  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, scale_ratio, &yWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
 
   recreateBuffers();
 }
@@ -86,8 +86,8 @@
   // Calculate the scale weight tabs must be in the ScalePixelBuffer class
   freeWeightTabs();
   calculateScaledBufferSize();
-  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, scale_ratio, &xWeightTabs);
-  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, scale_ratio, &yWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
+  scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
 
   recreateBuffers();
 }
diff --git a/win/rfb_win32/ScaledDIBSectionBuffer.h b/win/rfb_win32/ScaledDIBSectionBuffer.h
index eb1d093..509411c 100644
--- a/win/rfb_win32/ScaledDIBSectionBuffer.h
+++ b/win/rfb_win32/ScaledDIBSectionBuffer.h
@@ -50,9 +50,8 @@
       virtual const PixelFormat& getPixelFormat() const { return pf; }
       virtual const PixelFormat& getScaledPixelFormat() const { return getPF(); }
       virtual void setSize(int w, int h);
-      virtual void setScale(int scale) { setScaleRatio(double(scale)/100.0); };
-      virtual void setScaleRatio(double scale_ratio);
-
+      virtual void setScale(int scale);
+      
       virtual void calculateScaledBufferSize();
 
       Rect getRect() const { return ScaledPixelBuffer::getRect(); }
diff --git a/win/vncviewer/DesktopWindow.cxx b/win/vncviewer/DesktopWindow.cxx
index 5aba780..4a316ad 100644
--- a/win/vncviewer/DesktopWindow.cxx
+++ b/win/vncviewer/DesktopWindow.cxx
@@ -858,8 +858,8 @@
     // Send a pointer event to the server
     oldpos = p;
     if (buffer->isScaling()) {
-      p.x /= buffer->getScaleRatio();
-      p.y /= buffer->getScaleRatio();
+      p.x /= buffer->getScaleRatioX();
+      p.y /= buffer->getScaleRatioY();
     }
     ptr.pointerEvent(callback, p, mask);
 #ifdef WM_MOUSEWHEEL
@@ -1005,13 +1005,15 @@
 
 void DesktopWindow::setAutoScaling(bool as) { 
   autoScaling = as;
+  if (isToolbarEnabled()) refreshToolbarButtons();
   if (as) fitBufferToWindow();
 }
 
-void DesktopWindow::setDesktopScaleRatio(double scale_ratio) {
-  buffer->setScaleRatio(scale_ratio);
-  if (!isAutoScaling()) resizeDesktopWindowToBuffer();
+void DesktopWindow::setDesktopScale(int scale_) {
+  if (buffer->getScale() == scale_ || scale_ <= 0) return;
+  buffer->setScale(scale_);
   if (isToolbarEnabled()) refreshToolbarButtons();
+  if (!isAutoScaling()) resizeDesktopWindowToBuffer();
   char *newTitle = new char[strlen(desktopName)+20];
   sprintf(newTitle, "%s @ %i%%", desktopName, getDesktopScale());
   SetWindowText(handle, TStr(newTitle));
@@ -1037,7 +1039,7 @@
   } else { 
     scale_ratio = double(client_size.width()) / buffer->getSrcWidth();
   }
-  setDesktopScaleRatio(scale_ratio);
+  setDesktopScale(int(scale_ratio * 100));
 }
 
 void
diff --git a/win/vncviewer/DesktopWindow.h b/win/vncviewer/DesktopWindow.h
index bce7cf7..7a8fa2c 100644
--- a/win/vncviewer/DesktopWindow.h
+++ b/win/vncviewer/DesktopWindow.h
@@ -88,8 +88,7 @@
       void setColour(int i, int r, int g, int b) {buffer->setColour(i, r, g, b);}
       void setAutoScaling(bool as);
       bool isAutoScaling() const { return autoScaling; }
-      void setDesktopScaleRatio(double scale_ratio);
-      void setDesktopScale(int scale) { setDesktopScaleRatio(double(scale)/100); }
+      void setDesktopScale(int scale);
       int  getDesktopScale() const { return buffer->getScale(); }
       void fitBufferToWindow(bool repaint = true);