Index: DefaultMapContextDrawer.java
===================================================================
--- DefaultMapContextDrawer.java	(revision 44452)
+++ DefaultMapContextDrawer.java	(revision 44453)
@@ -25,7 +25,6 @@
 
 import java.awt.Graphics2D;
 import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -36,7 +35,6 @@
 import org.gvsig.compat.print.PrintAttributes;
 import org.gvsig.fmap.dal.exception.ReadException;
 import org.gvsig.fmap.geom.primitive.Envelope;
-import org.gvsig.fmap.mapcontext.ExtentHistory;
 import org.gvsig.fmap.mapcontext.MapContext;
 import org.gvsig.fmap.mapcontext.MapContextDrawer;
 import org.gvsig.fmap.mapcontext.MapContextException;
@@ -53,10 +51,6 @@
 import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
 import org.gvsig.fmap.mapcontext.layers.vectorial.VectorLayer;
 import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelable;
-import org.gvsig.tools.ToolsLocator;
-import org.gvsig.tools.dynobject.DynStruct;
-import org.gvsig.tools.library.LibraryException;
-import org.gvsig.tools.persistence.PersistenceManager;
 import org.gvsig.tools.task.Cancellable;
 import org.gvsig.tools.util.Callable;
 import org.slf4j.Logger;
@@ -64,737 +58,745 @@
 
 public class DefaultMapContextDrawer implements MapContextDrawer {
 
-	private static final Logger LOG = LoggerFactory
-			.getLogger(DefaultMapContextDrawer.class);
+    private static final Logger LOG = LoggerFactory
+            .getLogger(DefaultMapContextDrawer.class);
 
-	private MapContext mapContext = null;
-	private ViewPort viewPort = null;
-	private CachedImage cachedImage = null;
-	private DrawList previousDrawList = null;
+    private MapContext mapContext = null;
+    private ViewPort viewPort = null;
+    private CachedImage cachedImage = null;
+    private DrawList previousDrawList = null;
 
-	protected void checkInitialized() {
-		if (mapContext == null || viewPort == null) {
-			throw new IllegalStateException(
-					"MapContext and ViewPort must be set");
-		}
-	}
+    protected void checkInitialized() {
+        if (mapContext == null || viewPort == null) {
+            throw new IllegalStateException(
+                    "MapContext and ViewPort must be set");
+        }
+    }
 
-	public void draw(FLayers root, BufferedImage image, Graphics2D g,
-			Cancellable cancel, double scale) throws ReadException {
+    public void draw(FLayers root, BufferedImage image, Graphics2D g,
+            Cancellable cancel, double scale) throws ReadException {
 
-		this.checkInitialized();
+        this.checkInitialized();
 
-		// With viewport changes all layers must be redrawn, discard cache
-		if (cachedImage != null && cachedImage.hasChangedViewPortDrawVersion()) {
-			cachedImage = null;
-		}
+        // With viewport changes all layers must be redrawn, discard cache
+        if (cachedImage != null && cachedImage.hasChangedViewPortDrawVersion()) {
+            cachedImage = null;
+        }
 
-		AffineTransform aux_at = null;
-		
-		if (isValidFullCachedImage()) {
-		    
-		    aux_at = g.getTransform();
-			g.drawImage(
-			    cachedImage.getFullDrawnImage(),
-			    (int) -aux_at.getTranslateX(),
-			    (int) -aux_at.getTranslateY(),
-			    null);
-			LOG.debug("Drawn full image from the cache, all layers cached");
-			return;
-		}
+        AffineTransform aux_at = null;
 
-		DrawList drawList = this.createDrawList(root, cancel, scale);
-		if (drawList == null || drawList.size() == 0) {
-			return;
-		}
+        if (isValidFullCachedImage()) {
 
-		if (cancel.isCanceled()) {
-			cachedImage = null;
-			return;
-		}
+            aux_at = g.getTransform();
+            g.drawImage(
+                    cachedImage.getFullDrawnImage(),
+                    (int) -aux_at.getTranslateX(),
+                    (int) -aux_at.getTranslateY(),
+                    null);
+            LOG.debug("Drawn full image from the cache, all layers cached");
+            return;
+        }
 
-		int firstLayerToDraw;
-		int lastLayerToDraw;
-		if (isValidPartialCachedImage(drawList)) {
-			firstLayerToDraw = 0;
-			lastLayerToDraw = cachedImage.getLastDrawnLayerPosition();
-			
-			aux_at = g.getTransform();
-			g.drawImage(
-	                cachedImage.getPartialDrawnImage(),
-	                (int) -aux_at.getTranslateX(),
-	                (int) -aux_at.getTranslateY(),
-	                null);
-			
-			cachedImage.updateVersions(mapContext, viewPort);
-			LOG.debug("Reused image of cached layers from 0 to {}",
-					new Integer(lastLayerToDraw));
-		} else {
-			if (cachedImage == null) {
-				cachedImage = new CachedImage();
-				// Draw all layers
-				firstLayerToDraw = 0;
-				//lastLayerToDraw = drawList.getLayerCount() - 1;
-				lastLayerToDraw = drawList.getLastLayerVisible(viewPort);
-			} else {
-				// Draw the first group of layers without changes to be cached
-				// next time
-				firstLayerToDraw = 0;
-				int firstChangedLayer = drawList.getFirstChangedLayer();
-				// If negative nothing has changed, so draw all the layers
-				lastLayerToDraw = firstChangedLayer < 0 ? drawList
-						.getLayerCount() - 1 : firstChangedLayer - 1;
-			}
-			drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
-					cancel, scale);
-			cachedImage.setPartialDrawnImage(image, mapContext, viewPort,
-					lastLayerToDraw);
-		}
+        DrawList drawList = this.createDrawList(root, cancel, scale);
+        if (drawList == null || drawList.size() == 0) {
+            return;
+        }
 
-		if (cancel.isCanceled()) {
-			cachedImage = null;
-			return;
-		}
+        if (cancel.isCanceled()) {
+            cachedImage = null;
+            return;
+        }
 
-		// Draw the second group of layers not cached
-		firstLayerToDraw = lastLayerToDraw + 1;
-		lastLayerToDraw = drawList.getLayerCount() - 1;
-		drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
-				cancel, scale);
-		cachedImage.setFullDrawnImage(image);
+        int firstLayerToDraw;
+        int lastLayerToDraw;
+        if (isValidPartialCachedImage(drawList)) {
+            firstLayerToDraw = 0;
+            lastLayerToDraw = cachedImage.getLastDrawnLayerPosition();
 
-		this.previousDrawList = drawList;
-	}
+            aux_at = g.getTransform();
+            g.drawImage(
+                    cachedImage.getPartialDrawnImage(),
+                    (int) -aux_at.getTranslateX(),
+                    (int) -aux_at.getTranslateY(),
+                    null);
 
-	private boolean isValidPartialCachedImage(DrawList drawList) {
-		return cachedImage != null
-				&& cachedImage.isValidPartialDrawnImage(mapContext, drawList);
-	}
+            cachedImage.updateVersions(mapContext, viewPort);
+            LOG.debug("Reused image of cached layers from 0 to {}",
+                    new Integer(lastLayerToDraw));
+        } else {
+            if (cachedImage == null) {
+                cachedImage = new CachedImage();
+                // Draw all layers
+                firstLayerToDraw = 0;
+                //lastLayerToDraw = drawList.getLayerCount() - 1;
+                lastLayerToDraw = drawList.getLastLayerVisible(viewPort);
+            } else {
+                // Draw the first group of layers without changes to be cached
+                // next time
+                firstLayerToDraw = 0;
+                int firstChangedLayer = drawList.getFirstChangedLayer();
+                // If negative nothing has changed, so draw all the layers
+                lastLayerToDraw = firstChangedLayer < 0 ? drawList
+                        .getLayerCount() - 1 : firstChangedLayer - 1;
+            }
+            drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
+                    cancel, scale);
+            cachedImage.setPartialDrawnImage(image, mapContext, viewPort,
+                    lastLayerToDraw);
+        }
 
-	private boolean isValidFullCachedImage() {
-		return cachedImage != null
-				&& cachedImage.isValidFullDrawnImage(mapContext);
-	}
+        if (cancel.isCanceled()) {
+            cachedImage = null;
+            return;
+        }
 
-	private void print(Object layerOrComposed, Graphics2D g,
-			Cancellable cancel, double scale, PrintAttributes properties)
-			throws ReadException {
-		ILabelable labelable = null;
-		ILabelable tmp = null;
-		if (layerOrComposed instanceof ILabelable) {
+        // Draw the second group of layers not cached
+        firstLayerToDraw = lastLayerToDraw + 1;
+        lastLayerToDraw = drawList.getLayerCount() - 1;
+        drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
+                cancel, scale);
+        cachedImage.setFullDrawnImage(image);
 
-			tmp = (ILabelable) layerOrComposed;
+        this.previousDrawList = drawList;
+    }
 
-			if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
-					&& tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
-				labelable = tmp;
-			}
-		}
+    private boolean isValidPartialCachedImage(DrawList drawList) {
+        return cachedImage != null
+                && cachedImage.isValidPartialDrawnImage(mapContext, drawList);
+    }
 
-		if (layerOrComposed instanceof FLayer) {
-			FLayer layer = (FLayer) layerOrComposed;
-			layer.print(g, viewPort, cancel, scale, properties);
-		} else {
-			ComposedLayer composed = (ComposedLayer) layerOrComposed;
-			composed.print(g, viewPort, cancel, scale, properties);
-		}
-		if (labelable != null) {
-			labelable.printLabels(g, viewPort, cancel, scale, properties);
-		}
+    private boolean isValidFullCachedImage() {
+        return cachedImage != null
+                && cachedImage.isValidFullDrawnImage(mapContext);
+    }
 
-	}
+    private void print(Object layerOrComposed, Graphics2D g,
+            Cancellable cancel, double scale, PrintAttributes properties)
+            throws ReadException {
+        ILabelable labelable = null;
+        ILabelable tmp = null;
+        if (layerOrComposed instanceof ILabelable) {
 
-	public void setMapContext(MapContext mapContext) {
-		if (this.mapContext == mapContext) {
-			return;
-		}
-		this.clean();
-		this.mapContext = mapContext;
+            tmp = (ILabelable) layerOrComposed;
 
-	}
+            if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
+                    && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
+                labelable = tmp;
+            }
+        }
 
-	public void setViewPort(ViewPort viewPort) {
-		if (this.viewPort == viewPort) {
-			return;
-		}
-		this.clean();
-		this.viewPort = viewPort;
+        if (layerOrComposed instanceof FLayer) {
+            FLayer layer = (FLayer) layerOrComposed;
+            layer.print(g, viewPort, cancel, scale, properties);
+        } else {
+            ComposedLayer composed = (ComposedLayer) layerOrComposed;
+            composed.print(g, viewPort, cancel, scale, properties);
+        }
+        if (labelable != null) {
+            labelable.printLabels(g, viewPort, cancel, scale, properties);
+        }
 
-	}
+    }
 
-	protected void clean() {
-		this.cachedImage = null;
-	}
+    public void setMapContext(MapContext mapContext) {
+        if (this.mapContext == mapContext) {
+            return;
+        }
+        this.clean();
+        this.mapContext = mapContext;
 
-	public class CachedImage {
-		private BufferedImage partialDrawnImage;
-		private BufferedImage fullDrawnImage;
-		private long lastMapContextVersion;
-		private long lastViewPortVersion;
-		private int lastDrawnLayerPosition;
+    }
 
-		public void setPartialDrawnImage(BufferedImage partialDrawnImage,
-				MapContext mapContext, ViewPort viewPort,
-				int lastDrawnLayerPosition) {
-			this.partialDrawnImage = CompatLocator.getGraphicsUtils()
-					.copyBufferedImage(partialDrawnImage);
-			this.lastDrawnLayerPosition = lastDrawnLayerPosition;
-			updateVersions(mapContext, viewPort);
-		}
-		
-		public void updateVersions(MapContext mapContext, ViewPort viewPort) {
-			this.lastMapContextVersion = mapContext.getDrawVersion();
-			this.lastViewPortVersion = viewPort.getDrawVersion();			
-		}
+    public void setViewPort(ViewPort viewPort) {
+        if (this.viewPort == viewPort) {
+            return;
+        }
+        this.clean();
+        this.viewPort = viewPort;
 
-		public void setFullDrawnImage(BufferedImage fullDrawnImage) {
-			this.fullDrawnImage = CompatLocator.getGraphicsUtils()
-					.copyBufferedImage(fullDrawnImage);
-		}
+    }
 
-		public BufferedImage getPartialDrawnImage() {
-			return partialDrawnImage;
-		}
+    protected void clean() {
+        this.cachedImage = null;
+    }
 
-		public BufferedImage getFullDrawnImage() {
-			return fullDrawnImage;
-		}
+    public class CachedImage {
 
-		public long getMapContextVersion() {
-			return lastMapContextVersion;
-		}
+        private BufferedImage partialDrawnImage;
+        private BufferedImage fullDrawnImage;
+        private long lastMapContextVersion;
+        private long lastViewPortVersion;
+        private int lastDrawnLayerPosition;
 
-		public int getLastDrawnLayerPosition() {
-			return this.lastDrawnLayerPosition;
-		}
+        public void setPartialDrawnImage(BufferedImage partialDrawnImage,
+                MapContext mapContext, ViewPort viewPort,
+                int lastDrawnLayerPosition) {
+            this.partialDrawnImage = CompatLocator.getGraphicsUtils()
+                    .copyBufferedImage(partialDrawnImage);
+            this.lastDrawnLayerPosition = lastDrawnLayerPosition;
+            updateVersions(mapContext, viewPort);
+        }
 
-		public boolean isValidFullDrawnImage(MapContext context) {
-			// If the MapContext version has not changed, there are not any
-			// changes that require redrawing any of the layers.
-			return fullDrawnImage != null && !hasChangedMapContextDrawVersion();
-		}
+        public void updateVersions(MapContext mapContext, ViewPort viewPort) {
+            this.lastMapContextVersion = mapContext.getDrawVersion();
+            this.lastViewPortVersion = viewPort.getDrawVersion();
+        }
 
-		public boolean hasChangedMapContextDrawVersion() {
-			// This change detects changes in layers and the viewport also
-			return mapContext.getDrawVersion() != this.lastMapContextVersion;
-		}
+        public void setFullDrawnImage(BufferedImage fullDrawnImage) {
+            this.fullDrawnImage = CompatLocator.getGraphicsUtils()
+                    .copyBufferedImage(fullDrawnImage);
+        }
 
-		public boolean hasChangedViewPortDrawVersion() {
-			// This change detects changes in the viewport
-			return viewPort.getDrawVersion() != this.lastViewPortVersion;
-		}
+        public BufferedImage getPartialDrawnImage() {
+            return partialDrawnImage;
+        }
 
-		public boolean isValidPartialDrawnImage(MapContext context,
-				DrawList drawList) {
-			if (!hasChangedMapContextDrawVersion()) {
-				// Nothing has changed
-				return true;
-			}
+        public BufferedImage getFullDrawnImage() {
+            return fullDrawnImage;
+        }
 
-			if (partialDrawnImage == null || hasChangedViewPortDrawVersion()) {
-				// No image available or changes in view port
-				return false;
-			}
+        public long getMapContextVersion() {
+            return lastMapContextVersion;
+        }
 
-			if (drawList.size() < lastDrawnLayerPosition + 1) {
-				// New list has fewer layers than before
-				return false;
-			}
+        public int getLastDrawnLayerPosition() {
+            return this.lastDrawnLayerPosition;
+        }
 
-			// There is any change in the layers drawn in the partial drawn
-			// image?
-			return drawList.getFirstChangedLayer() > lastDrawnLayerPosition;
-		}
-	}
+        public boolean isValidFullDrawnImage(MapContext context) {
+            // If the MapContext version has not changed, there are not any
+            // changes that require redrawing any of the layers.
+            return fullDrawnImage != null && !hasChangedMapContextDrawVersion();
+        }
 
-	public class DrawList {
-		private List layers = new ArrayList();
-		private List all = new ArrayList();
-		private List versions = new ArrayList();
-		private DrawList previosList = null;
-		private int firstLayerChanged = -1;
+        public boolean hasChangedMapContextDrawVersion() {
+            // This change detects changes in layers and the viewport also
+            return mapContext.getDrawVersion() != this.lastMapContextVersion;
+        }
 
-		public DrawList() {
-		}
+        public boolean hasChangedViewPortDrawVersion() {
+            // This change detects changes in the viewport
+            return viewPort.getDrawVersion() != this.lastViewPortVersion;
+        }
 
-		public DrawList(DrawList previousList) {
-			if (previousList != null) {
-				this.firstLayerChanged = previousList.getLayerCount();
-				this.previosList = previousList;
-			}
-		}
+        public boolean isValidPartialDrawnImage(MapContext context,
+                DrawList drawList) {
+            if (!hasChangedMapContextDrawVersion()) {
+                // Nothing has changed
+                return true;
+            }
 
-		public int getLayerCount() {
-			return this.layers.size();
-		}
+            if (partialDrawnImage == null || hasChangedViewPortDrawVersion()) {
+                // No image available or changes in view port
+                return false;
+            }
 
-		public int getLastLayerVisible(ViewPort viewPort) {
-			Envelope area = viewPort.getAdjustedEnvelope();
-			for( int n=0; n<this.layers.size()-1; n++ ) {
-				FLayer layer = (FLayer) this.layers.get(n);
-				if( layer instanceof FLayerHidesArea ) {
-					if( ((FLayerHidesArea)(layer)).hidesThisArea(area) ) {
-						return n;
-					}
-				}
-			}
-			return this.layers.size()-1;
-		}
+            if (drawList.size() < lastDrawnLayerPosition + 1) {
+                // New list has fewer layers than before
+                return false;
+            }
 
-		private boolean hasChanged(FLayer layer, int pos) {
-			FLayer previous = (FLayer) this.previosList.layers.get(pos);
-			// String previousName = previous.getName();
-			// String layerName = layer.getName();
-			if (previous != layer) {
-				return true;
-			}
-			long previousVersion = ((Long) this.previosList.versions.get(pos))
-					.longValue();
-			long layerVersion = layer.getDrawVersion();
+            // There is any change in the layers drawn in the partial drawn
+            // image?
+            return drawList.getFirstChangedLayer() > lastDrawnLayerPosition;
+        }
+    }
 
-			return previousVersion != layerVersion;
-		}
+    public class DrawList {
 
-		public void add(Object obj) {
-			if (obj instanceof FLayer) {
-				FLayer layer = (FLayer) obj;
-				int curIndex = this.layers.size();
-				if (this.firstLayerChanged >= curIndex) {
-					if (this.previosList.getLayerCount() > curIndex) {
-						if (this.hasChanged(layer, curIndex)) {
-							this.firstLayerChanged = curIndex;
-						}
-					} else if (this.previosList.getLayerCount() == curIndex) {
-						this.firstLayerChanged = curIndex;
-					}
-				}
-				this.layers.add(layer);
-				this.versions.add(new Long(layer.getDrawVersion()));
-			} else if (!(obj instanceof LayersGroupEvent)) {
-				throw new UnsupportedOperationException();
-			}
+        private List layers = new ArrayList();
+        private List all = new ArrayList();
+        private List versions = new ArrayList();
+        private DrawList previosList = null;
+        private int firstLayerChanged = -1;
 
-			this.all.add(obj);
-		}
+        public DrawList() {
+        }
 
-		public int size() {
-			return this.all.size();
-		}
+        public DrawList(DrawList previousList) {
+            if (previousList != null) {
+                this.firstLayerChanged = previousList.getLayerCount();
+                this.previosList = previousList;
+            }
+        }
 
-		public int getFirstChangedLayer() {
-			if (this.firstLayerChanged > this.layers.size()) {
-				this.firstLayerChanged = this.layers.size();
-			}
-			return this.firstLayerChanged;
-		}
+        public int getLayerCount() {
+            return this.layers.size();
+        }
 
-		public FLayer getLayer(int pos) {
-			return (FLayer) this.layers.get(pos);
-		}
+        public int getLastLayerVisible(ViewPort viewPort) {
+            Envelope area = viewPort.getAdjustedEnvelope();
+            for (int n = 0; n < this.layers.size() - 1; n++) {
+                FLayer layer = (FLayer) this.layers.get(n);
+                if (layer instanceof FLayerHidesArea) {
+                    if (((FLayerHidesArea) (layer)).hidesThisArea(area)) {
+                        return n;
+                    }
+                }
+            }
+            return this.layers.size() - 1;
+        }
 
-		public Object get(int pos) {
-			return this.all.get(pos);
-		}
+        private boolean hasChanged(FLayer layer, int pos) {
+            FLayer previous = (FLayer) this.previosList.layers.get(pos);
+            // String previousName = previous.getName();
+            // String layerName = layer.getName();
+            if (previous != layer) {
+                return true;
+            }
+            long previousVersion = ((Long) this.previosList.versions.get(pos))
+                    .longValue();
+            long layerVersion = layer.getDrawVersion();
 
-		public void drawLayers(BufferedImage image, Graphics2D g,
-				int firstLayerToDraw, int lastLayerToDraw, Cancellable cancel,
-				double scale) throws ReadException {
+            return previousVersion != layerVersion;
+        }
 
-			if (firstLayerToDraw > lastLayerToDraw) {
-				LOG.debug("Nothing to draw");
-				return;
-			}
+        public void add(Object obj) {
+            if (obj instanceof FLayer) {
+                FLayer layer = (FLayer) obj;
+                int curIndex = this.layers.size();
+                if (this.firstLayerChanged >= curIndex) {
+                    if (this.previosList.getLayerCount() > curIndex) {
+                        if (this.hasChanged(layer, curIndex)) {
+                            this.firstLayerChanged = curIndex;
+                        }
+                    } else if (this.previosList.getLayerCount() == curIndex) {
+                        this.firstLayerChanged = curIndex;
+                    }
+                }
+                this.layers.add(layer);
+                this.versions.add(new Long(layer.getDrawVersion()));
+            } else if (!(obj instanceof LayersGroupEvent)) {
+                throw new UnsupportedOperationException();
+            }
 
-			// Find the real layer positions excluding LayersGroupEvents
-			FLayer firstLayer = (FLayer) layers.get(firstLayerToDraw);
-			int firstLayerPos = all.indexOf(firstLayer);
-			// Look if it belongs to a group and start it
-			if (firstLayerPos > 0) {
-				for (int i = firstLayerPos - 1; i < all.size(); i++) {
-                                        // firstLayer
-					Object group = all.get(i);
-					if (group instanceof LayersGroupEvent) {
-						LayersGroupEvent event = (LayersGroupEvent) group;
-						if (event.type == LayersGroupEvent.IN_Event) {
-							event.group.beginDraw(g, viewPort);
-						}
-						break;
-					}
-				}
-			}
-			FLayer lastLayer = (FLayer) layers.get(lastLayerToDraw);
-			int lastLayerPos = all.indexOf(lastLayer);
+            this.all.add(obj);
+        }
 
-			LOG.debug("Drawing from layer {} in position (layers: {}, all: {})"
-					+ " to layer {} in position (layers: {}, all: {})",
-					new Object[] { firstLayer, new Integer(firstLayerToDraw),
-							new Integer(firstLayerPos), lastLayer,
-							new Integer(lastLayerToDraw),
-							new Integer(lastLayerPos) });
+        public int size() {
+            return this.all.size();
+        }
 
-			ComposedLayer composed = null;
-			for (int pos = firstLayerPos; pos <= lastLayerPos; pos++) {
-				if (cancel.isCanceled()) {
-					return;
-				}
+        public int getFirstChangedLayer() {
+            if (this.firstLayerChanged > this.layers.size()) {
+                this.firstLayerChanged = this.layers.size();
+            }
+            return this.firstLayerChanged;
+        }
 
-				Object layerOrGroup = get(pos);
+        public FLayer getLayer(int pos) {
+            return (FLayer) this.layers.get(pos);
+        }
 
-				// Group drawing events management
-				if (layerOrGroup instanceof LayersGroupEvent) {
-					LayersGroupEvent event = (LayersGroupEvent) layerOrGroup;
-					if (event.type == LayersGroupEvent.IN_Event) {
-						event.group.beginDraw(g, viewPort);
-					} else {
-						event.group.endDraw(g, viewPort);
-					}
-				} else {
-					FLayer layer = (FLayer) layerOrGroup;
-					if (composed != null && composed.canAdd(layer)) {
-						// Previous or current layer could be composed
-						// Add current layer
-						addToComposedLayer(composed, layer);
-					} else {
-						if (composed != null) {
-							// Current layer can't be composed on the previous
-							// composedlayer. Draw previous composed
-							LOG.debug("Drawing composed layer {} ", composed);
-							draw(composed, image, g, cancel, scale);
-							composed = null;
-						}
+        public Object get(int pos) {
+            return this.all.get(pos);
+        }
 
-						// Try if the current layer can be composed
-						// Create new composed or draw current layer
-						composed = layer.newComposedLayer();
-						if (composed == null) {
-							LOG.debug("Drawing layer {} ", layer);
-							draw(layer, image, g, cancel, scale);
-						} else {
-							addToComposedLayer(composed, layer);
-						}
-					}
-				}
-			}
-			if (composed != null) {
-				// Draw the pending composed
-				draw(composed, image, g, cancel, scale);
-			}
+        public void drawLayers(BufferedImage image, Graphics2D g,
+                int firstLayerToDraw, int lastLayerToDraw, Cancellable cancel,
+                double scale) throws ReadException {
 
-			// Check if the last layer is the last of a group and close it
-			for (int i = lastLayerPos + 1; i < all.size(); i++) {
-				Object group = all.get(i);
-				if (group instanceof LayersGroupEvent) {
-					LayersGroupEvent event = (LayersGroupEvent) group;
-					if (event.type == LayersGroupEvent.OUT_Event) {
-						event.group.endDraw(g, viewPort);
-					}
-					break;
-				}
-			}
-		}
+            if (firstLayerToDraw > lastLayerToDraw) {
+                LOG.debug("Nothing to draw");
+                return;
+            }
 
-		private void addToComposedLayer(ComposedLayer composed, FLayer layer)
-				throws ReadException {
-			try {
-				LOG.debug("Adding layer {} to composed layer ", layer, composed);
-				composed.add(layer);
-			} catch (Exception e) {
-				throw new ReadException("DefalutMapContexDrawer exception", e);
-			}
-		}
+            // Find the real layer positions excluding LayersGroupEvents
+            FLayer firstLayer = (FLayer) layers.get(firstLayerToDraw);
+            int firstLayerPos = all.indexOf(firstLayer);
+            // Look if it belongs to a group and start it
+            if (firstLayerPos > 0) {
+                for (int i = firstLayerPos - 1; i < all.size(); i++) {
+                    // firstLayer
+                    Object group = all.get(i);
+                    if (group instanceof LayersGroupEvent) {
+                        LayersGroupEvent event = (LayersGroupEvent) group;
+                        if (event.type == LayersGroupEvent.IN_Event) {
+                            event.group.beginDraw(g, viewPort);
+                        }
+                        break;
+                    }
+                }
+            }
+            FLayer lastLayer = (FLayer) layers.get(lastLayerToDraw);
+            int lastLayerPos = all.indexOf(lastLayer);
 
-		private void draw(Object layerOrComposed, BufferedImage image,
-				Graphics2D g, Cancellable cancel, double scale)
-				throws ReadException {
-			ILabelable labelable = null;
-			ILabelable tmp = null;
-			if (layerOrComposed instanceof ILabelable) {
+            LOG.debug("Drawing from layer {} in position (layers: {}, all: {})"
+                    + " to layer {} in position (layers: {}, all: {})",
+                    new Object[]{firstLayer, new Integer(firstLayerToDraw),
+                        new Integer(firstLayerPos), lastLayer,
+                        new Integer(lastLayerToDraw),
+                        new Integer(lastLayerPos)});
 
-				tmp = (ILabelable) layerOrComposed;
+            ComposedLayer composed = null;
+            for (int pos = firstLayerPos; pos <= lastLayerPos; pos++) {
+                if (cancel.isCanceled()) {
+                    return;
+                }
 
-				if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
-						&& tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
-					labelable = tmp;
-				}
-			}
-				
-			if (layerOrComposed instanceof FLayer) {
-				int beforeDrawEventType;
-				int afterDrawEventType;
-				if (layerOrComposed instanceof GraphicLayer) {
-					beforeDrawEventType = LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW;
-					afterDrawEventType = LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW;
-				} else {
-					beforeDrawEventType = LayerDrawEvent.LAYER_BEFORE_DRAW;
-					afterDrawEventType = LayerDrawEvent.LAYER_AFTER_DRAW;
-				}
-				FLayer layer = (FLayer) layerOrComposed;
-				drawLayer(layer, image, g, cancel, scale, beforeDrawEventType,
-						afterDrawEventType);
-			} else {
-				ComposedLayer composed = (ComposedLayer) layerOrComposed;
-				composed.draw(image, g, viewPort, cancel, scale);
-			}
-			if (labelable != null) {
-				labelable.drawLabels(image, g, viewPort, cancel, scale,
-						mapContext.getViewPort().getDPI());
-			}
+                Object layerOrGroup = get(pos);
 
-		}
+                // Group drawing events management
+                if (layerOrGroup instanceof LayersGroupEvent) {
+                    LayersGroupEvent event = (LayersGroupEvent) layerOrGroup;
+                    if (event.type == LayersGroupEvent.IN_Event) {
+                        event.group.beginDraw(g, viewPort);
+                    } else {
+                        event.group.endDraw(g, viewPort);
+                    }
+                } else {
+                    FLayer layer = (FLayer) layerOrGroup;
+                    if (composed != null && composed.canAdd(layer)) {
+                        // Previous or current layer could be composed
+                        // Add current layer
+                        addToComposedLayer(composed, layer);
+                    } else {
+                        if (composed != null) {
+                            // Current layer can't be composed on the previous
+                            // composedlayer. Draw previous composed
+                            LOG.debug("Drawing composed layer {} ", composed);
+                            draw(composed, image, g, cancel, scale);
+                            composed = null;
+                        }
 
-		protected void drawLayer(FLayer layer, BufferedImage image,
-				Graphics2D g, Cancellable cancel, double scale,
-				int beforeDrawEventType, int afterDrawEventType)
-				throws ReadException {
-			LayerDrawEvent event = new LayerDrawEvent(layer, g, viewPort, beforeDrawEventType);
-			mapContext.fireLayerDrawingEvent(event);
-			layer.draw(image, g, viewPort, cancel, scale);
-			event = new LayerDrawEvent(layer, g, viewPort, afterDrawEventType);
-			mapContext.fireLayerDrawingEvent(event);
-		}
+                        // Try if the current layer can be composed
+                        // Create new composed or draw current layer
+                        composed = layer.newComposedLayer();
+                        if (composed == null) {
+                            LOG.debug("Drawing layer {} ", layer);
+                            draw(layer, image, g, cancel, scale);
+                        } else {
+                            addToComposedLayer(composed, layer);
+                        }
+                    }
+                }
+            }
+            if (composed != null) {
+                // Draw the pending composed
+                draw(composed, image, g, cancel, scale);
+            }
 
-	}
+            // Check if the last layer is the last of a group and close it
+            for (int i = lastLayerPos + 1; i < all.size(); i++) {
+                Object group = all.get(i);
+                if (group instanceof LayersGroupEvent) {
+                    LayersGroupEvent event = (LayersGroupEvent) group;
+                    if (event.type == LayersGroupEvent.OUT_Event) {
+                        event.group.endDraw(g, viewPort);
+                    }
+                    break;
+                }
+            }
+        }
 
-	private class SimpleLayerIterator extends LayersIterator {
+        private void addToComposedLayer(ComposedLayer composed, FLayer layer)
+                throws ReadException {
+            try {
+                LOG.debug("Adding layer {} to composed layer ", layer, composed);
+                composed.add(layer);
+            } catch (Exception e) {
+                throw new ReadException("DefalutMapContexDrawer exception", e);
+            }
+        }
 
-		public SimpleLayerIterator(FLayer layer) {
-			this.appendLayer(layer);
-		}
+        private void draw(Object layerOrComposed, BufferedImage image,
+                Graphics2D g, Cancellable cancel, double scale)
+                throws ReadException {
+            ILabelable labelable = null;
+            ILabelable tmp = null;
+            if (layerOrComposed instanceof ILabelable) {
 
-		public boolean evaluate(FLayer layer) {
-			if (layer instanceof FLayers) {
-				return false;
-			}
-			return layer.isAvailable() && layer.isVisible();
-		}
+                tmp = (ILabelable) layerOrComposed;
 
-	}
+                if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
+                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
+                    labelable = tmp;
+                }
+            }
 
-	public void dispose() {
-		this.mapContext = null;
-		this.viewPort = null;
-		this.cachedImage = null;
-		this.previousDrawList = null;
-	}
+            if (layerOrComposed instanceof FLayer) {
+                int beforeDrawEventType;
+                int afterDrawEventType;
+                if (layerOrComposed instanceof GraphicLayer) {
+                    beforeDrawEventType = LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW;
+                    afterDrawEventType = LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW;
+                } else {
+                    beforeDrawEventType = LayerDrawEvent.LAYER_BEFORE_DRAW;
+                    afterDrawEventType = LayerDrawEvent.LAYER_AFTER_DRAW;
+                }
+                FLayer layer = (FLayer) layerOrComposed;
+                drawLayer(layer, image, g, cancel, scale, beforeDrawEventType,
+                        afterDrawEventType);
+            } else {
+                ComposedLayer composed = (ComposedLayer) layerOrComposed;
+                composed.draw(image, g, viewPort, cancel, scale);
+            }
+            if (labelable != null) {
+                labelable.drawLabels(image, g, viewPort, cancel, scale,
+                        mapContext.getViewPort().getDPI());
+            }
 
-	public void print(FLayers root, Graphics2D g, Cancellable cancel,
-			double scale, PrintAttributes properties) throws ReadException {
-		this.checkInitialized();
+        }
 
-		List printList = this.createPrintList(root, cancel);
-		if (cancel.isCanceled()) {
-			return;
-		}
+        protected void drawLayer(FLayer layer, BufferedImage image,
+                Graphics2D g, Cancellable cancel, double scale,
+                int beforeDrawEventType, int afterDrawEventType)
+                throws ReadException {
+            LayerDrawEvent event = new LayerDrawEvent(layer, g, viewPort, beforeDrawEventType);
+            mapContext.fireLayerDrawingEvent(event);
+            layer.draw(image, g, viewPort, cancel, scale);
+            event = new LayerDrawEvent(layer, g, viewPort, afterDrawEventType);
+            mapContext.fireLayerDrawingEvent(event);
+        }
 
-		ComposedLayer composed = null;
-		int pos;
-		FLayer layer;
-		int layerPos = -1;
-		Object obj;
-		LayersGroupEvent event;
-		for (pos = 0; pos < printList.size(); pos++) {
-			if (cancel.isCanceled()) {
-				return;
-			}
+    }
 
-			obj = printList.get(pos);
-			if (obj instanceof LayersGroupEvent) {
-				event = (LayersGroupEvent) obj;
-				if (event.type == LayersGroupEvent.IN_Event) {
-					// System.out.println("=======Empiza a pintar grupo de capas "+
-					// ((FLayers)event.group).getName() +"============");
-					event.group.beginDraw(g, viewPort);
-				} else {
-					event.group.endDraw(g, viewPort);
-					// System.out.println("=======Fin a pintar grupo de capas "+
-					// ((FLayers)event.group).getName() +"============");
+    private class SimpleLayerIterator extends LayersIterator {
 
-				}
-				continue;
-			}
-			layerPos++;
+        public SimpleLayerIterator(FLayer layer) {
+            this.appendLayer(layer);
+        }
 
-			layer = (FLayer) obj;
+        public boolean evaluate(FLayer layer) {
+            if (layer instanceof FLayers) {
+                return false;
+            }
+            return layer.isAvailable() && layer.isVisible();
+        }
 
-			// *** Pintado de capa/composicion de capa ***
-			if (composed == null) {
-				composed = layer.newComposedLayer();
-				if (composed != null) {
-					try {
-						composed.add(layer);
-						// System.out.println("=======Imprimiendo composicion de pintado "+
-						// (layerPos-1)+" ============");
-						continue;
-					} catch (Exception e) {
-						throw new ReadException(
-								"DefaultMapContexDrawer exception", e);
-					}
-				}
-			} else {
-				if (composed.canAdd(layer)) {
-					try {
-						composed.add(layer);
-						// System.out.println("=== añadiendo a composicion de pintado "+
-						// layerPos+ " "+layer.getName());
-						continue;
-					} catch (Exception e) {
-						throw new ReadException(
-								"DefaultMapContexDrawer exception", e);
-					}
-				} else {
-					// System.out.println("=======Imprimiendo composicion de pintado "+
-					// (layerPos-1)+" ============");
-					this.print(composed, g, cancel, scale, properties);
-					// composed.print( g, viewPort, cancel, scale,properties);
-					composed = layer.newComposedLayer();
-					if (composed != null) {
-						try {
-							composed.add(layer);
-							// System.out.println("=== añadiendo a composicion de pintado "+
-							// layerPos+ " "+layer.getName());
-							continue;
-						} catch (Exception e) {
-							throw new ReadException(
-									"DefaultMapContexDrawer exception", e);
-						}
-					}
-				}
-			}
-			// System.out.println("=== imprimiendo "+ layerPos+
-			// " "+layer.getName());
-			this.print(layer, g, cancel, scale, properties);
-			// layer.print(g, viewPort, cancel, scale,properties);
-			// *** Pintado de capa/composicion de capa ***
-			if (composed != null) {
-				// si la composicion no se ha pintado la pintamos
-				// System.out.println("=======Imprimiendo composicion de pintado "+
-				// (layerPos-1)+" (ultimo) ============");
-				this.print(composed, g, cancel, scale, properties);
-				// composed.print(g, viewPort, cancel, scale, properties);
-				composed = null;
-			}
-		}
+    }
 
-	}
+    public void dispose() {
+        this.mapContext = null;
+        this.viewPort = null;
+        this.cachedImage = null;
+        this.previousDrawList = null;
+    }
 
-	private DrawList createDrawList(FLayers root, Cancellable cancel,
-			double scale) {
-		DrawList result = new DrawList(this.previousDrawList);
-		Iterator iter = new MyLayerIterator((FLayer) root, scale);
-		while (iter.hasNext()) {
-			if (cancel.isCanceled()) {
-				return null;
-			}
-			result.add(iter.next());
-		}
-		if (cancel.isCanceled()) {
-			return null;
-		}
-		// Take into account also the Graphic layer
-                for (VectorLayer graphicsLayer : mapContext.getGraphicsLayers()) {
-                    result.add(graphicsLayer);
+    public void print(FLayers root, Graphics2D g, Cancellable cancel,
+            double scale, PrintAttributes properties) throws ReadException {
+        this.checkInitialized();
+
+        List printList = this.createPrintList(root, cancel);
+        if (cancel.isCanceled()) {
+            return;
+        }
+
+        ComposedLayer composed = null;
+        int pos;
+        FLayer layer;
+        int layerPos = -1;
+        Object obj;
+        LayersGroupEvent event;
+        for (pos = 0; pos < printList.size(); pos++) {
+            if (cancel.isCanceled()) {
+                return;
+            }
+
+            obj = printList.get(pos);
+            if (obj instanceof LayersGroupEvent) {
+                event = (LayersGroupEvent) obj;
+                if (event.type == LayersGroupEvent.IN_Event) {
+                    // System.out.println("=======Empiza a pintar grupo de capas "+
+                    // ((FLayers)event.group).getName() +"============");
+                    event.group.beginDraw(g, viewPort);
+                } else {
+                    event.group.endDraw(g, viewPort);
+                    // System.out.println("=======Fin a pintar grupo de capas "+
+                    // ((FLayers)event.group).getName() +"============");
+
                 }
-		return result;
-	}
+                continue;
+            }
+            layerPos++;
 
-	private List createPrintList(FLayers root, Cancellable cancel) {
-		List result = new ArrayList();
-		Iterator iter = new SimpleLayerIterator((FLayer) root);
-		while (iter.hasNext()) {
-			if (cancel.isCanceled()) {
-				return null;
-			}
-			result.add(iter.next());
-		}
-		return result;
-	}
+            layer = (FLayer) obj;
 
-	private class MyLayerIterator implements Iterator {
-		List layersList = new ArrayList();
-		int index = 0;
-		double scale = 0;
+            // *** Pintado de capa/composicion de capa ***
+            if (composed == null) {
+                composed = layer.newComposedLayer();
+                if (composed != null) {
+                    try {
+                        composed.add(layer);
+                        // System.out.println("=======Imprimiendo composicion de pintado "+
+                        // (layerPos-1)+" ============");
+                        continue;
+                    } catch (Exception e) {
+                        throw new ReadException(
+                                "DefaultMapContexDrawer exception", e);
+                    }
+                }
+            } else {
+                if (composed.canAdd(layer)) {
+                    try {
+                        composed.add(layer);
+                        // System.out.println("=== añadiendo a composicion de pintado "+
+                        // layerPos+ " "+layer.getName());
+                        continue;
+                    } catch (Exception e) {
+                        throw new ReadException(
+                                "DefaultMapContexDrawer exception", e);
+                    }
+                } else {
+                    // System.out.println("=======Imprimiendo composicion de pintado "+
+                    // (layerPos-1)+" ============");
+                    this.print(composed, g, cancel, scale, properties);
+                    // composed.print( g, viewPort, cancel, scale,properties);
+                    composed = layer.newComposedLayer();
+                    if (composed != null) {
+                        try {
+                            composed.add(layer);
+                            // System.out.println("=== añadiendo a composicion de pintado "+
+                            // layerPos+ " "+layer.getName());
+                            continue;
+                        } catch (Exception e) {
+                            throw new ReadException(
+                                    "DefaultMapContexDrawer exception", e);
+                        }
+                    }
+                }
+            }
+            // System.out.println("=== imprimiendo "+ layerPos+
+            // " "+layer.getName());
+            this.print(layer, g, cancel, scale, properties);
+            // layer.print(g, viewPort, cancel, scale,properties);
+            // *** Pintado de capa/composicion de capa ***
+            if (composed != null) {
+                // si la composicion no se ha pintado la pintamos
+                // System.out.println("=======Imprimiendo composicion de pintado "+
+                // (layerPos-1)+" (ultimo) ============");
+                this.print(composed, g, cancel, scale, properties);
+                // composed.print(g, viewPort, cancel, scale, properties);
+                composed = null;
+            }
+        }
 
-		public MyLayerIterator(FLayer layer, double scale) {
-			this.scale = scale;
-			this.appendLayer(layer);
-		}
+    }
 
-		protected void appendLayer(FLayer layer) {
-			if (layer instanceof LayerCollection) {
-				appendLayers((LayerCollection) layer);
-			} else if (this.evaluate(layer)) {
-				layersList.add(layer);
-			}
-		}
+    private DrawList createDrawList(FLayers root, Cancellable cancel,
+            double scale) {
+        DrawList result = new DrawList(this.previousDrawList);
+        Iterator iter = new MyLayerIterator((FLayer) root, scale);
+        while (iter.hasNext()) {
+            if (cancel.isCanceled()) {
+                return null;
+            }
+            result.add(iter.next());
+        }
+        if (cancel.isCanceled()) {
+            return null;
+        }
+        // Take into account also the Graphic layer
+        for (VectorLayer graphicsLayer : mapContext.getGraphicsLayers()) {
+            if (graphicsLayer != null && 
+                    graphicsLayer.isAvailable() &&
+                    graphicsLayer.isVisible() && 
+                    graphicsLayer.isWithinScale(scale)) {
+                result.add(graphicsLayer);
+            }
+        }
+        return result;
+    }
 
-		private void appendLayers(LayerCollection layers) {
-			int i;
-			layersList.add(new LayersGroupEvent(layers,
-					LayersGroupEvent.IN_Event));
-			for (i = 0; i < layers.getLayersCount(); i++) {
-				appendLayer(layers.getLayer(i));
-			}
-			layersList.add(new LayersGroupEvent(layers,
-					LayersGroupEvent.OUT_Event));
-		}
+    private List createPrintList(FLayers root, Cancellable cancel) {
+        List result = new ArrayList();
+        Iterator iter = new SimpleLayerIterator((FLayer) root);
+        while (iter.hasNext()) {
+            if (cancel.isCanceled()) {
+                return null;
+            }
+            result.add(iter.next());
+        }
+        return result;
+    }
 
-		public void remove() {
-			throw new UnsupportedOperationException();
-		}
+    private class MyLayerIterator implements Iterator {
 
-		public boolean hasNext() {
-			return index < layersList.size();
-		}
+        List layersList = new ArrayList();
+        int index = 0;
+        double scale = 0;
 
-		public Object next() {
-			if (!this.hasNext()) {
-				throw new NoSuchElementException();
-			}
-			Object aux = layersList.get(index);
-			index++;
-			return aux;
-		}
+        public MyLayerIterator(FLayer layer, double scale) {
+            this.scale = scale;
+            this.appendLayer(layer);
+        }
 
-		public boolean evaluate(FLayer layer) {
-			if (layer instanceof LayerCollection) {
-				return false;
-			}
-			return layer.isAvailable() && layer.isVisible()
-					&& layer.isWithinScale(this.scale);
-		}
+        protected void appendLayer(FLayer layer) {
+            if (layer instanceof LayerCollection) {
+                appendLayers((LayerCollection) layer);
+            } else if (this.evaluate(layer)) {
+                layersList.add(layer);
+            }
+        }
 
-	}
+        private void appendLayers(LayerCollection layers) {
+            int i;
+            layersList.add(new LayersGroupEvent(layers,
+                    LayersGroupEvent.IN_Event));
+            for (i = 0; i < layers.getLayersCount(); i++) {
+                appendLayer(layers.getLayer(i));
+            }
+            layersList.add(new LayersGroupEvent(layers,
+                    LayersGroupEvent.OUT_Event));
+        }
 
-	private class LayersGroupEvent {
-		public static final String IN_Event = "in";
-		public static final String OUT_Event = "Out";
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
 
-		private LayerCollection group = null;
-		private String type = IN_Event;
+        public boolean hasNext() {
+            return index < layersList.size();
+        }
 
-		public LayersGroupEvent(LayerCollection group, String type) {
-			this.group = group;
-			this.type = type;
-		}
+        public Object next() {
+            if (!this.hasNext()) {
+                throw new NoSuchElementException();
+            }
+            Object aux = layersList.get(index);
+            index++;
+            return aux;
+        }
 
-		public String getType() {
-			return type;
-		}
+        public boolean evaluate(FLayer layer) {
+            if (layer instanceof LayerCollection) {
+                return false;
+            }
+            return layer.isAvailable() && layer.isVisible()
+                    && layer.isWithinScale(this.scale);
+        }
 
-		public LayerCollection getGroup() {
-			return group;
-		}
-	}
+    }
 
+    private class LayersGroupEvent {
 
+        public static final String IN_Event = "in";
+        public static final String OUT_Event = "Out";
+
+        private LayerCollection group = null;
+        private String type = IN_Event;
+
+        public LayersGroupEvent(LayerCollection group, String type) {
+            this.group = group;
+            this.type = type;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public LayerCollection getGroup() {
+            return group;
+        }
+    }
+
     public static class RegisterMapContextDrawer implements Callable {
 
         public Object call() {
             MapContextManager manager = MapContextLocator.getMapContextManager();
             try {
-                    manager.setDefaultMapContextDrawer(DefaultMapContextDrawer.class);
+                manager.setDefaultMapContextDrawer(DefaultMapContextDrawer.class);
             } catch (MapContextException ex) {
-                    throw new RuntimeException("Can't register the default MapContextDrawer", ex);
+                throw new RuntimeException("Can't register the default MapContextDrawer", ex);
             }
             return Boolean.TRUE;
         }
