diff --git a/src/gui/qgsmaptoolzoom.cpp b/src/gui/qgsmaptoolzoom.cpp
index 586e64f..ef8b3de 100644
--- a/src/gui/qgsmaptoolzoom.cpp
+++ b/src/gui/qgsmaptoolzoom.cpp
@@ -50,7 +50,7 @@ void QgsMapToolZoom::canvasMoveEvent( QMouseEvent * e )
     mDragging = true;
     delete mRubberBand;
     mRubberBand = new QgsRubberBand( mCanvas, true );
-    mZoomRect.setTopLeft( e->pos() );
+    // the starting point is already captured
   }
   mZoomRect.setBottomRight( e->pos() );
   if ( mRubberBand )
@@ -66,7 +66,8 @@ void QgsMapToolZoom::canvasPressEvent( QMouseEvent * e )
   if ( e->button() != Qt::LeftButton )
     return;
 
-  mZoomRect.setRect( 0, 0, 0, 0 );
+  // store the starting point
+  mZoomRect.setRect( e->pos().x(), e->pos().y(), 0, 0 );
 }
 
 
@@ -75,6 +76,9 @@ void QgsMapToolZoom::canvasReleaseEvent( QMouseEvent * e )
   if ( e->button() != Qt::LeftButton )
     return;
 
+  // ctrl key reverses zoom direction
+  bool isZoomOut = ( e->modifiers() & Qt::ControlModifier ) ? ! mZoomOut : mZoomOut;
+
   if ( mDragging )
   {
     mDragging = false;
@@ -82,43 +86,51 @@ void QgsMapToolZoom::canvasReleaseEvent( QMouseEvent * e )
     mRubberBand = 0;
 
     // store the rectangle
-    mZoomRect.setRight( e->pos().x() );
-    mZoomRect.setBottom( e->pos().y() );
-
-    const QgsMapToPixel* coordinateTransform = mCanvas->getCoordinateTransform();
-
-    // set the extent to the zoomBox
-    QgsPoint ll = coordinateTransform->toMapCoordinates( mZoomRect.left(), mZoomRect.bottom() );
-    QgsPoint ur = coordinateTransform->toMapCoordinates( mZoomRect.right(), mZoomRect.top() );
+    mZoomRect.setBottomRight( e->pos() );
 
-    QgsRectangle r;
-    r.setXMinimum( ll.x() );
-    r.setYMinimum( ll.y() );
-    r.setXMaximum( ur.x() );
-    r.setYMaximum( ur.y() );
-    r.normalize();
+    // before getting map coords
+    mZoomRect = mZoomRect.normalized();
 
     // prevent zooming to an empty extent
-    if ( r.width() == 0 || r.height() == 0 )
+    if ( mZoomRect.width() == 0)
+    {
+      mZoomRect.setWidth( 1 );
+    }
+    if ( mZoomRect.height() == 0 )
     {
-      return;
+      mZoomRect.setHeight( 1 );
     }
 
-    if ( mZoomOut )
+    const QgsMapToPixel* coordinateTransform = mCanvas->getCoordinateTransform();
+
+    // set the extent to the zoomBox
+    // Need to adjust the right and bottom to account for integer values equating to one edge of a pixel.
+    // This gets the outside of the zoom rectangle.
+    QgsPoint ll = coordinateTransform->toMapCoordinates( mZoomRect.left(), mZoomRect.bottom() + 1 );
+    QgsPoint ur = coordinateTransform->toMapCoordinates( mZoomRect.right() + 1, mZoomRect.top() );
+
+    QgsRectangle r( ll, ur );
+
+    if ( isZoomOut )
     {
       QgsPoint cer = r.center();
       QgsRectangle extent = mCanvas->extent();
 
-      double sf;
-      if ( mZoomRect.width() > mZoomRect.height() )
-      {
-        sf = extent.width() / r.width();
-      }
-      else
-      {
-        sf = extent.height() / r.height();
-      }
-      r.expand( sf );
+      // calculate the ratios: width, height - of old to new rectangles
+      double wRatio = extent.width() / r.width();
+      double hRatio = extent.height() / r.height();
+
+      // take the smaller ratio (the direction the zoom rect is closer to the edges of the map)
+      double sf = wRatio < hRatio ? wRatio : hRatio;
+
+      //set the rectangle representing the new location to the original extent's size
+      double w2 = extent.width() / 2.0;
+      double h2 = extent.height() / 2.0;
+      r.set( QgsPoint( cer.x() - w2, cer.y() - h2 ),
+             QgsPoint( cer.x() + w2, cer.y() + h2 ) );
+
+      // then scale it
+      r.scale( sf );
 
       QgsDebugMsg( QString( "Extent scaled by %1 to %2" ).arg( sf ).arg( r.toString().toLocal8Bit().constData() ) );
       QgsDebugMsg( QString( "Center of currentExtent after scaling is %1" ).arg( r.center().toString().toLocal8Bit().constData() ) );
@@ -131,7 +143,7 @@ void QgsMapToolZoom::canvasReleaseEvent( QMouseEvent * e )
   else // not dragging
   {
     // change to zoom in/out by the default multiple
-    mCanvas->zoomWithCenter( e->x(), e->y(), !mZoomOut );
+    mCanvas->zoomWithCenter( e->x(), e->y(), !isZoomOut );
   }
 }
 
