efficient viewport
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxisTest.xtend b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxisTest.xtend
index c3a7bc2..287d776 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxisTest.xtend
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxisTest.xtend
@@ -105,7 +105,7 @@
 	}
 	
 	@Test
-	def void midpointToEnd() {
+	def void beforeMidpointToEnd() {
 		//    segment position: | 0 |  1  |      2      |            3            |
 		//      pixel location:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
 		// visible pixel range:                 |---------------------------------|
@@ -120,6 +120,21 @@
 	}
 	
 	@Test
+	def void afterMidpointToEnd() {
+		//    segment position: | 0 |  1  |      2      |            3            |
+		//      pixel location:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
+		// visible pixel range:                                   |-------------------|
+		//                                              |4 5 6 7 8 9 0 1 2 3 4 5 6|
+		viewportAxis.pixelOrigin = 17
+		viewportAxis.visiblePixelRange = 10
+		testAxis(
+			viewportAxis,
+			#[ 3 ],
+			#[ -5, 8 ]
+		)
+	}
+	
+	@Test
 	def void midpointToMidpoint() {
 		//    segment position: | 0 |  1  |      2      |            3            |
 		//      pixel location:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
@@ -187,8 +202,6 @@
 		testAxis(
 			"after expand",
 			viewportAxis,
-//			#[ 1, 2, 3 ],
-//			#[ -2, 1, 8, 21 ]
 			#[ 0, 1, 2, 3 ],
 			#[ -1, 1, 4, 11, 24 ]
 		)
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/geometry/PixelRectangleInvariants.xtend b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/geometry/PixelRectangleInvariants.xtend
index 4de3334..138a1b1 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/geometry/PixelRectangleInvariants.xtend
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/geometry/PixelRectangleInvariants.xtend
@@ -1,13 +1,19 @@
 package org.eclipse.nebula.widgets.nattable.core.geometry
 
+import static java.lang.Math.*
+
 class PixelRectangleInvariants {
 	
 	static def PixelRectangle intersect(PixelRectangle rect1, PixelRectangle rect2) {
-		val startX = Math::max(rect1.x, rect2.x)
-		val startY = Math::max(rect1.y, rect2.y)
-		val endX = Math::min(rect1.x + rect1.width, rect2.x + rect2.width)
-		val endY = Math::min(rect1.y + rect1.height, rect2.y + rect2.height)
-		new PixelRectangle(startX, startY, endX - startX, endY - startY)
+		val startX = max(rect1.x, rect2.x)
+		val startY = max(rect1.y, rect2.y)
+		val endX = min(rect1.x + rect1.width, rect2.x + rect2.width)
+		val endY = min(rect1.y + rect1.height, rect2.y + rect2.height)
+		new PixelRectangle(startX, startY, max(endX - startX, 0), max(endY - startY, 0))
+	}
+	
+	static def boolean isEmpty(PixelRectangle rect) {
+		rect.width == 0 || rect.height == 0
 	}
 	
 }
\ No newline at end of file
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/CellLayerPainter.xtend b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/CellLayerPainter.xtend
index f05d3d0..82371c4 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/CellLayerPainter.xtend
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/CellLayerPainter.xtend
@@ -7,6 +7,8 @@
 import org.eclipse.nebula.widgets.nattable.core.layer.cell.Cell
 import org.eclipse.nebula.widgets.nattable.core.layer.cell.impl.DefaultCellPainter
 
+import static java.lang.Math.*
+
 import static extension org.eclipse.nebula.widgets.nattable.core.geometry.PixelRectangleInvariants.*
 import static extension org.eclipse.nebula.widgets.nattable.core.layer.LayerInvariants.*
 import static extension org.eclipse.nebula.widgets.nattable.core.layer.cell.CellInvariants.*
@@ -22,25 +24,27 @@
 
 		val clipBounds = gc.clipBounds
 		
-		val fromColumnPosition = Math::max(layer.getColumnPositionOfXPixel(clipBounds.x), 0)
-		val toColumnPosition = Math::min(layer.getColumnPositionOfXPixel(clipBounds.x + clipBounds.width - 1), layer.columnCount - 1)
-		val fromRowPosition = Math::max(layer.getRowPositionOfYPixel(clipBounds.y), 0)
-		val toRowPosition = Math::min(layer.getRowPositionOfYPixel(clipBounds.y + clipBounds.height - 1), layer.rowCount - 1)
+		val fromColumnPosition = max(layer.getColumnPositionOfXPixel(clipBounds.x), 0)
+		val toColumnPosition = min(layer.getColumnPositionOfXPixel(clipBounds.x + clipBounds.width - 1), layer.columnCount - 1)
+		val fromRowPosition = max(layer.getRowPositionOfYPixel(clipBounds.y), 0)
+		val toRowPosition = min(layer.getRowPositionOfYPixel(clipBounds.y + clipBounds.height - 1), layer.rowCount - 1)
 		
-		for (columnPosition : fromColumnPosition .. toColumnPosition)
-			for (rowPosition : fromRowPosition .. toRowPosition) {
-				val cell = layer.getCell(columnPosition, rowPosition)
-				
-				gc.pushState
-				
-				val cellPaintBounds = cell.paintBounds
-				gc.clipBounds = cellPaintBounds.intersect(paintBounds)
-				gc.translate(cellPaintBounds.x, cellPaintBounds.y)
-				val localCellPaintBounds = new PixelRectangle(0, 0, cellPaintBounds.width, cellPaintBounds.height)
-				cellPainter.paintCell(cell, localCellPaintBounds, gc)
-				
-				gc.popState
-			}
+		if (fromColumnPosition <= toColumnPosition)
+			for (columnPosition : fromColumnPosition .. toColumnPosition)
+				if (fromRowPosition <= toRowPosition)
+					for (rowPosition : fromRowPosition .. toRowPosition) {
+						val cell = layer.getCell(columnPosition, rowPosition)
+						
+						gc.pushState
+						
+						val cellPaintBounds = cell.paintBounds
+						gc.clipBounds = cellPaintBounds.intersect(paintBounds)
+						gc.translate(cellPaintBounds.x, cellPaintBounds.y)
+						val localCellPaintBounds = new PixelRectangle(0, 0, cellPaintBounds.width, cellPaintBounds.height)
+						cellPainter.paintCell(cell, localCellPaintBounds, gc)
+						
+						gc.popState
+					}
 	}
 	
 	//
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/GridLineCellLayerPainter.xtend b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/GridLineCellLayerPainter.xtend
index c03f8a4..02ec24d 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/GridLineCellLayerPainter.xtend
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/GridLineCellLayerPainter.xtend
@@ -6,6 +6,8 @@
 import org.eclipse.nebula.widgets.nattable.core.layer.Layer
 import org.eclipse.nebula.widgets.nattable.core.layer.cell.Cell
 
+import static java.lang.Math.*
+
 import static extension org.eclipse.nebula.widgets.nattable.core.layer.LayerInvariants.*
 
 class GridLineCellLayerPainter extends CellLayerPainter {
@@ -41,32 +43,34 @@
 		gc.foregroundColor = new Color(0, 0, 255, 0)
 		
 		// Draw
+		val clipBounds = gc.clipBounds
+		
 		val pixelWidth = layer.getPixelWidth
 		val pixelHeight = layer.getPixelHeight
 		
-		val clipBounds = gc.clipBounds
-		
 		// Draw horizontal grid lines
-		val fromRowPosition = Math::max(layer.getRowPositionOfYPixel(clipBounds.y) + 1, 1)
-		val toRowPosition = Math::min(layer.getRowPositionOfYPixel(clipBounds.y + clipBounds.height), layer.rowCount)
-		for (rowPosition : fromRowPosition .. toRowPosition) {
-			val startY = layer.getStartYPixelOfRowPosition(rowPosition) - 1
-			gc.drawLine(
-				0,          startY,
-				pixelWidth, startY
-			)
-		}
+		val fromRowPosition = max(layer.getRowPositionOfYPixel(clipBounds.y) + 1, 1)
+		val toRowPosition = min(layer.getRowPositionOfYPixel(clipBounds.y + clipBounds.height), layer.rowCount)
+		if (fromRowPosition <= toRowPosition)
+			for (rowPosition : fromRowPosition .. toRowPosition) {
+				val y = layer.getStartYPixelOfRowPosition(rowPosition) - 1
+				gc.drawLine(
+					0,          y,
+					pixelWidth, y
+				)
+			}
 		
 		// Draw vertical grid lines
-		val fromColumnPosition = Math::max(layer.getColumnPositionOfXPixel(clipBounds.x) + 1, 1)
-		val toColumnPosition = Math::min(layer.getColumnPositionOfXPixel(clipBounds.x + clipBounds.width), layer.columnCount)
-		for (columnPosition : fromColumnPosition .. toColumnPosition) {
-			val startX = layer.getStartXPixelOfColumnPosition(columnPosition) - 1
-			gc.drawLine(
-				startX, 0,
-				startX, pixelHeight
-			)
-		}
+		val fromColumnPosition = max(layer.getColumnPositionOfXPixel(clipBounds.x) + 1, 1)
+		val toColumnPosition = min(layer.getColumnPositionOfXPixel(clipBounds.x + clipBounds.width), layer.columnCount)
+		if (fromColumnPosition <= toColumnPosition)
+			for (columnPosition : fromColumnPosition .. toColumnPosition) {
+				val x = layer.getStartXPixelOfColumnPosition(columnPosition) - 1
+				gc.drawLine(
+					x, 0,
+					x, pixelHeight
+				)
+			}
 		
 		gc.popState
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxis.xtend b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxis.xtend
index edaa6ae..71109d3 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxis.xtend
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/core/layer/impl/viewport/ViewportAxis.xtend
@@ -69,7 +69,7 @@
 	override getSegmentPositionOfPixelLocation(int pixelLocation) {
 		val underlyingPixelLocation = pixelOrigin + pixelLocation
 		if (underlyingPixelLocation < 0) return -1
-		if (underlyingPixelLocation >= pixelSize) return segmentCount
+		if (underlyingPixelLocation >= underlyingAxis.pixelSize) return segmentCount
 		underlyingAxis.getSegmentPositionOfPixelLocation(underlyingPixelLocation) - originSegmentPosition
 	}