Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text.properties
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text.properties	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text.properties	(revision 33580)
@@ -0,0 +1,6 @@
+# Resource bundle texts for the Spanish language locale (es)
+Centrar_la_Vista_sobre_un_punto=Centrar la vista sobre un punto
+debe_seleccionar_las_capas_de_las_que_quiera_obtener_informacion=Debe seleccionar las capas de las que quiera obtener informaci\u00f3n.
+formato_de_numero_incorrecto=Formato de n\u00famero incorrecto.
+no_hay_ninguna_capa_seleccionada=No hay ninguna capa seleccionada
+Vista=Vista
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text_en.properties
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text_en.properties	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/locale/text_en.properties	(revision 33580)
@@ -0,0 +1,6 @@
+# Resource bundle texts for the English language locale (en)
+Centrar_la_Vista_sobre_un_punto=Center view to point
+debe_seleccionar_las_capas_de_las_que_quiera_obtener_informacion=Select the layers you want to get information from
+formato_de_numero_incorrecto=Incorrect number format
+no_hay_ninguna_capa_seleccionada=No layer has been selected
+Vista=View
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/config/config.xml
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/config/config.xml	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/config/config.xml	(revision 33580)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<plugin-config>
+	<libraries library-dir="lib"/>
+	<depends plugin-name="org.gvsig.app"/>
+	<resourceBundle name="text"/>
+	<extensions>
+		<extension class-name="org.gvsig.symbology.ExampleExtension"
+			description="Extensi�n plantilla con ejemplo que permite hacer zooms en funci�n de un par de coordenadas introducidas por el usuario."
+			active="true">
+			<menu text="Vista/Centrar_la_Vista_sobre_un_punto"
+				  tooltip="Centrar_la_Vista_sobre_un_punto"
+				  action-command="CENTERVIEWTOPOINT"
+				  icon="view-center-to-point" />
+			<tool-bar name="Herramientas">
+				<action-tool icon="view-center-to-point"
+					         action-command="CENTERVIEWTOPOINT" 
+					         tooltip="Centrar_la_Vista_sobre_un_punto"
+					         enable-text="deber�a de estar activada"
+					         last="true"/>
+			</tool-bar>
+		</extension>
+	</extensions>
+</plugin-config>
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/images/centerviewtopoint.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/images/centerviewtopoint.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/images/logo_horiz_bicolor_gva.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/images/logo_horiz_bicolor_gva.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/build.number
===================================================================
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/about/about.htm
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/about/about.htm	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/about/about.htm	(revision 33580)
@@ -0,0 +1,20 @@
+<html>
+  <head>
+    <title>Extensi�n de ejemplo para GvSIG</title>
+    <meta content="">
+    <style></style>
+  </head>
+  <body>
+<table width="60%" border="0">
+  <tr>
+    <td width="64%"><img src="images/logo_horiz_bicolor_gva.png" width="329" height="50"></td>
+  </tr>
+  <tr>
+    <td colspan="2"><font face="Arial, Helvetica, sans-serif">&copy; Copyright
+      Generalitat Valenciana 2005.</font></td>
+  </tr>
+</table>
+  <h3>Extensi&oacute;n de Ejemplo</h3>
+  <b>Code name: org.gvsig.symbology-0.1.0-#build.number#</b>
+  </body>
+</html>
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/README.txt
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/README.txt	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/resources/README.txt	(revision 33580)
@@ -0,0 +1,15 @@
+Put into this folder the resources needed by your extension classes.
+
+This folder is added to the runtime classpath, so you can load any resources 
+through the ClassLoader.
+
+By default, into this folder you can find:
+
+- about: the HTML content for the gvSIG about panel.
+
+- config: the Andami plugin config.xml file.
+
+- images: some images and icons used by the extension. 
+
+- org.gvsig.template.extension.i18n: resource bundle property files with the 
+  translated texts.
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLocator.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLocator.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLocator.java	(revision 33580)
@@ -0,0 +1,74 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ */
+package org.gvsig.symbology;
+
+import org.gvsig.tools.locator.BaseLocator;
+import org.gvsig.tools.locator.Locator;
+import org.gvsig.tools.locator.LocatorException;
+
+public class SymbologyLocator extends BaseLocator {
+
+	public static final String SYMBOLOGY_MANAGER_NAME = "SymbologyManager";
+
+	private static final String SYMBOLOGY_MANAGER_DESCRIPTION =
+			"Manager of the basic symbology library";
+
+	/**
+	 * Unique instance.
+	 */
+	private static final SymbologyLocator instance = new SymbologyLocator();
+
+	/**
+	 * Return the singleton instance.
+	 * 
+	 * @return the singleton instance
+	 */
+	public static SymbologyLocator getInstance() {
+		return instance;
+	}
+
+	/**
+	 * Return a reference to the SymbologyManager.
+	 * 
+	 * @return a reference to the SymbologyManager
+	 * @throws LocatorException
+	 *             if there is no access to the class or the class cannot be
+	 *             instantiated
+	 * @see Locator#get(String)
+	 */
+	public static SymbologyManager getSymbologyManager()
+			throws LocatorException {
+		return (SymbologyManager) getInstance().get(SYMBOLOGY_MANAGER_NAME);
+	}
+
+	/**
+	 * Registers the Class implementing the SymbologyManager interface.
+	 * 
+	 * @param clazz
+	 *            implementing the SymbologyManager interface
+	 */
+	@SuppressWarnings("unchecked")
+	public static void registerSymbologyManager(Class clazz) {
+		getInstance().register(SYMBOLOGY_MANAGER_NAME,
+				SYMBOLOGY_MANAGER_DESCRIPTION, clazz);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLibrary.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLibrary.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyLibrary.java	(revision 33580)
@@ -0,0 +1,59 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+/*
+ * AUTHORS (In addition to CIT):
+ * 2009 {gvSIG}  {{Task}}
+ */
+package org.gvsig.symbology;
+
+import org.gvsig.fmap.mapcontext.MapContextLibrary;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.MapContextManager;
+import org.gvsig.fmap.mapcontext.rendering.legend.ISingleSymbolLegend;
+import org.gvsig.tools.library.AbstractLibrary;
+import org.gvsig.tools.library.Library;
+import org.gvsig.tools.library.LibraryException;
+
+/**
+ * Library for the Basic Symbology extended API.
+ * 
+ * @author <a href="mailto:cordinyana@gvsig.org">C�sar Ordi�ana</a>
+ */
+public class SymbologyLibrary extends AbstractLibrary {
+
+	public SymbologyLibrary() {
+		super(SymbologyLibrary.class,Library.TYPE.API);
+		require(MapContextLibrary.class);
+	}
+	
+	protected void doInitialize() throws LibraryException {
+		// Nothing to do
+	}
+
+	protected void doPostInitialize() throws LibraryException {
+		MapContextManager manager = MapContextLocator.getMapContextManager();
+
+		// Default vector legend
+		manager.setDefaultVectorLegend(ISingleSymbolLegend.LEGEND_NAME);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/package.html
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/package.html	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/package.html	(revision 33580)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>org.gvsig.template.extension package documentation</title>
+</head>
+<body>
+
+	<p>TODO: Example extension description.</p>
+	
+	<p>See the <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#packagecomment">Javadoc Tool documentation about the package file</a></p>
+
+</body>
+</html>
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyManager.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyManager.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/SymbologyManager.java	(revision 33580)
@@ -0,0 +1,50 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+*
+* Copyright (C) 2007-2008 Infrastructures and Transports Department
+* of the Valencian Government (CIT)
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+* MA  02110-1301, USA.
+* 
+*/
+
+/*
+* AUTHORS (In addition to CIT):
+* 2009 {}  {{Task}}
+*/
+package org.gvsig.symbology;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
+
+
+/**
+ * Basic symbology manager.
+ * 
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public interface SymbologyManager {
+
+	/**
+	 * Creates a new interval with the given limit values
+	 * 
+	 * @param min
+	 *            the minimum included interval value
+	 * @param max
+	 *            the maximum included interval value
+	 * @return a new interval
+	 */
+	IInterval createInterval(double min, double max);
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/SymbologyDefaultImplLibrary.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/SymbologyDefaultImplLibrary.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/SymbologyDefaultImplLibrary.java	(revision 33580)
@@ -0,0 +1,289 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+/*
+ * AUTHORS (In addition to CIT):
+ * 2009 {gvSIG}  {{Task}}
+ */
+package org.gvsig.symbology.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.MapContextException;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.MapContextManager;
+import org.gvsig.fmap.mapcontext.rendering.legend.ISingleSymbolLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialIntervalLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
+import org.gvsig.symbology.SymbologyLocator;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractClassifiedVectorLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractIntervalLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractVectorialLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.FInterval;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.SingleSymbolLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.VectorialIntervalLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.VectorialUniqueValueLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.AttrInTableLabelingStrategy;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.DefaultLabelingMethod;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.LabelClass;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.ZoomConstraintsImpl;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.AbstractFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.MultiLayerFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.SimpleFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.MultiShapeSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.AbstractLineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.MultiLayerLineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.SimpleLineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.AbstractMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.ArrowMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.MultiLayerMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.SimpleMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.AbstractStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ArrowDecoratorStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.DefaultMask;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.SimpleLineStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.warning.impl.WarningSymbol;
+import org.gvsig.tools.exception.ListBaseException;
+import org.gvsig.tools.library.AbstractLibrary;
+import org.gvsig.tools.library.LibraryException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Library for the Basic Symbology implementation.
+ * 
+ * @author <a href="mailto:cordinyana@gvsig.org">C�sar Ordi�ana</a>
+ */
+public class SymbologyDefaultImplLibrary extends AbstractLibrary {
+
+    private Logger LOG =
+        LoggerFactory.getLogger(SymbologyDefaultImplLibrary.class);
+
+    protected void doInitialize() throws LibraryException {
+        // Nothing to do
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected void doPostInitialize() throws LibraryException {
+        List exs = new ArrayList();
+
+        MapContextManager manager = MapContextLocator.getMapContextManager();
+        try {
+            registerSymbols(manager);
+        } catch (Exception e) {
+            exs.add(e);
+        }
+        try {
+            registerSymbolsPersistence();
+        } catch (Exception e) {
+            exs.add(e);
+        }
+
+        try {
+            registerLegends(manager);
+        } catch (Exception e) {
+            exs.add(e);
+        }
+
+        try {
+            registerLegendsPersistence();
+        } catch (Exception e) {
+            exs.add(e);
+        }
+
+        try {
+            registerLabelingPersistence();
+        } catch (Exception e) {
+            exs.add(e);
+        }
+
+        try {
+            SymbologyLocator.registerSymbologyManager(DefaultSymbologyManager.class);
+        } catch (Exception e) {
+            exs.add(e);
+        }
+
+        if (exs.size() > 0) {
+            LibraryException ex = new LibraryException(this.getClass(), exs);
+            LOG.warn(((ListBaseException) (ex.getCause())).getMessageStack());
+            throw ex;
+        }
+    }
+
+    /**
+     * Registers symbol implementations in the {@link MapContextManager}.
+     */
+    private void registerSymbols(MapContextManager manager) throws MapContextException {
+
+        SymbolManager symbolManager = manager.getSymbolManager();
+
+        // Fill
+        int[] shapeTypes =
+            new int[] { Geometry.TYPES.SURFACE, Geometry.TYPES.CIRCLE,
+                Geometry.TYPES.ELLIPSE, Geometry.TYPES.MULTISURFACE };
+        symbolManager.registerSymbol(IFillSymbol.SYMBOL_NAME,
+            shapeTypes,
+            SimpleFillSymbol.class);
+        symbolManager.registerMultiLayerSymbol(IFillSymbol.SYMBOL_NAME,
+            shapeTypes,
+            MultiLayerFillSymbol.class);
+
+        // Line
+        shapeTypes =
+            new int[] { Geometry.TYPES.CURVE, Geometry.TYPES.ARC,
+                Geometry.TYPES.ELLIPTICARC, Geometry.TYPES.MULTICURVE };
+        symbolManager.registerSymbol(ILineSymbol.SYMBOL_NAME,
+            shapeTypes,
+            SimpleLineSymbol.class);
+        symbolManager.registerMultiLayerSymbol(ILineSymbol.SYMBOL_NAME,
+            shapeTypes,
+            MultiLayerLineSymbol.class);
+
+        // Marker
+        shapeTypes =
+            new int[] { Geometry.TYPES.POINT, Geometry.TYPES.MULTIPOINT };
+        symbolManager.registerSymbol(IMarkerSymbol.SYMBOL_NAME,
+            shapeTypes,
+            SimpleMarkerSymbol.class);
+        symbolManager.registerMultiLayerSymbol(IMarkerSymbol.SYMBOL_NAME,
+            shapeTypes,
+            MultiLayerMarkerSymbol.class);
+
+        // Text
+        shapeTypes = new int[] { Geometry.TYPES.TEXT };
+        symbolManager.registerSymbol(ITextSymbol.SYMBOL_NAME,
+            shapeTypes,
+            SimpleTextSymbol.class);
+
+        // MultiShape
+        shapeTypes = new int[] { Geometry.TYPES.GEOMETRY };
+        symbolManager.registerSymbol(MultiShapeSymbol.SYMBOL_NAME,
+            shapeTypes,
+            MultiShapeSymbol.class);
+
+        // Warning
+        symbolManager.registerSymbol(IWarningSymbol.SYMBOL_NAME,
+            WarningSymbol.class);
+    }
+
+    /**
+     * Registers legend implementations in the {@link MapContextManager}.
+     */
+    private void registerLegends(MapContextManager manager) {
+        List<Exception> exceptions = new ArrayList<Exception>();
+
+        try {
+            manager.registerLegend(IVectorialUniqueValueLegend.LEGEND_NAME,
+                VectorialUniqueValueLegend.class);
+        } catch (Exception ex) {
+            exceptions.add(ex);
+        }
+        try {
+            manager.registerLegend(IVectorialIntervalLegend.LEGEND_NAME,
+                VectorialIntervalLegend.class);
+        } catch (Exception ex) {
+            exceptions.add(ex);
+        }
+        try {
+            manager.registerLegend(ISingleSymbolLegend.LEGEND_NAME,
+                SingleSymbolLegend.class);
+
+        } catch (Exception ex) {
+            exceptions.add(ex);
+        }
+        if (exceptions.size() > 0) {
+            throw new LibraryException(this.getClass(), exceptions);
+        }
+
+    }
+
+    private void registerLabelingPersistence() {
+        ZoomConstraintsImpl.registerPersistence();
+        LabelClass.registerPersistence();
+        DefaultLabelingMethod.registerPersistence();
+        AttrInTableLabelingStrategy.registerPersistence();
+    }
+
+    /**
+     * Register dynclass and persistence definitions for Legend classes.
+     */
+    private void registerLegendsPersistence() {
+        AbstractLegend.registerPersistence();
+        AbstractVectorialLegend.registerPersistence();
+        AbstractClassifiedVectorLegend.registerPersistence();
+        FInterval.registerPersistence();
+        AbstractIntervalLegend.registerPersistence();
+        VectorialIntervalLegend.registerPersistence();
+        VectorialUniqueValueLegend.registerPersistence();
+        SingleSymbolLegend.registerPersistence();
+    }
+
+    /**
+     * Register dynclass and persistence definitions for Symbol classes.
+     */
+    private void registerSymbolsPersistence() {
+        // Styles
+        AbstractStyle.registerPersistence();
+        ArrowDecoratorStyle.registerPersistence();
+        DefaultMask.registerPersistence();
+        SimpleLineStyle.registerPersistence();
+
+        // Base symbol
+        AbstractSymbol.registerPersistence();
+
+        // Fill symbols
+        AbstractFillSymbol.registerPersistence();
+        SimpleFillSymbol.registerPersistence();
+        MultiLayerFillSymbol.registerPersistence();
+
+        // Line symbols
+        AbstractLineSymbol.registerPersistence();
+        SimpleLineSymbol.registerPersistence();
+        MultiLayerLineSymbol.registerPersistence();
+
+        // Marker symbols
+        AbstractMarkerSymbol.registerPersistence();
+        SimpleMarkerSymbol.registerPersistence();
+        ArrowMarkerSymbol.registerPersistence();
+        MultiLayerMarkerSymbol.registerPersistence();
+
+        // Text symbols
+        SimpleTextSymbol.registerPersistence();
+
+        // MultiShape symbol
+        MultiShapeSymbol.registerPersistence();
+
+        // Warning symbol
+        WarningSymbol.registerPersistence();
+    }
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/DefaultSymbologyManager.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/DefaultSymbologyManager.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/impl/DefaultSymbologyManager.java	(revision 33580)
@@ -0,0 +1,44 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+*
+* Copyright (C) 2007-2008 Infrastructures and Transports Department
+* of the Valencian Government (CIT)
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+* MA  02110-1301, USA.
+* 
+*/
+
+/*
+* AUTHORS (In addition to CIT):
+* 2009 {}  {{Task}}
+*/
+package org.gvsig.symbology.impl;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
+import org.gvsig.symbology.SymbologyManager;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.FInterval;
+
+/**
+ * Default {@link SymbologyManager} implementation.
+ * 
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class DefaultSymbologyManager implements SymbologyManager {
+
+	public IInterval createInterval(double min, double max) {
+		return new FInterval(min, max);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/AbstractStyle.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/AbstractStyle.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/AbstractStyle.java	(revision 33580)
@@ -0,0 +1,82 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.styles.IStyle;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Implements the IStyle interface in order to complete the methods ot the
+ * IStyle interface that allow the users to add the description of an object or
+ * obtain it.
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+
+public abstract class AbstractStyle implements IStyle {
+
+	public static final String STYLE_PERSISTENCE_DEFINITION_NAME = "Style";
+
+	private static final String FIELD_DESCRIPTION = "description";
+
+	private String desc;
+
+	public final void setDescription(String desc) {
+		this.desc = desc;
+	}
+
+	public final String getDescription() {
+		return desc;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		return super.clone();
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setDescription(state.getString(FIELD_DESCRIPTION));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_DESCRIPTION, getDescription());
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				ArrowDecoratorStyle.class,
+				STYLE_PERSISTENCE_DEFINITION_NAME,
+				STYLE_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		// Description
+		definition.addDynFieldString(FIELD_DESCRIPTION);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMask.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMask.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMask.java	(revision 33580)
@@ -0,0 +1,65 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.Shape;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.rendering.symbols.styles.IStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+
+/**
+ * Interface for the style of a mask.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public interface IMask extends IStyle {
+
+	public double getSize();
+
+	public void setSize(double size);
+
+	public IFillSymbol getFillSymbol();
+
+	public void setFillSymbol(IFillSymbol fill);
+
+	public Geometry getHaloShape(Shape shp);
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/Line2DOffset.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/Line2DOffset.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/Line2DOffset.java	(revision 33580)
@@ -0,0 +1,662 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.Shape;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.LineSegment;
+/**
+ *
+ * Line2DOffset.java
+ *
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es Jan 3, 2008
+ *
+ */
+
+public class Line2DOffset {
+	final static private Logger logger = LoggerFactory.getLogger(Line2DOffset.class);
+
+	public static GeneralPathX offsetLine(Shape p, double offset) {
+
+		if (Math.abs(offset) < 1) {
+			return new GeneralPathX(p.getPathIterator(null));
+		}
+		PathIterator pi = p.getPathIterator(null);
+		double[] dataCoords = new double[6];
+		Coordinate from = null, first = null;
+		List<LineSegment> segments = new ArrayList<LineSegment>();
+		GeneralPathX offsetSegments = new GeneralPathX();
+		LineSegment line;
+		try {
+			while (!pi.isDone()) {
+				// while not done
+				int type = pi.currentSegment(dataCoords);
+
+				switch (type) {
+				case PathIterator.SEG_MOVETO:
+					if(from == null){
+						from = new Coordinate(dataCoords[0], dataCoords[1]);
+						first = from;
+						break;
+					} else {
+						/* Puede significar un agujero en un pol�gono o un salto en una linea.
+						 * Entonces, consumimos los segmentos que llevamos
+						 * y empezamos un nuevo pol�gono o una nueva linea.
+						 */
+						try {
+							if(((Geometry)p).getType() == Geometry.TYPES.SURFACE){
+								offsetSegments.append(offsetAndConsumeClosedSegments(offset, segments).getPathIterator(null),
+										false);
+							} else {
+								offsetSegments.append(offsetAndConsumeSegments(offset, segments).getPathIterator(null),
+										false);
+							}
+						} catch (NotEnoughSegmentsToClosePathException e) {
+							logger.error(
+									e.getMessage(), e);
+						}
+						segments.clear();
+						from = new Coordinate(dataCoords[0], dataCoords[1]);
+						first = from;
+						break;
+					}
+
+				case PathIterator.SEG_LINETO:
+
+					// System.out.println("SEG_LINETO");
+					Coordinate to = new Coordinate(dataCoords[0], dataCoords[1]);
+					if(from.compareTo(to)!=0){
+						line = new LineSegment(from, to);
+						segments.add(line);
+						from = to;
+					}
+					break;
+				case PathIterator.SEG_CLOSE:
+					line = new LineSegment(from, first);
+					segments.add(line);
+					//					from = first;
+					try {
+						offsetSegments.append(offsetAndConsumeClosedSegments(
+								offset, segments).getPathIterator(null), false);
+					} catch (NotEnoughSegmentsToClosePathException e) {
+						logger.error(
+								e.getMessage(), e);
+					}
+					segments.clear();
+					first =null;
+					from = null;
+
+					break;
+
+				} // end switch
+
+				pi.next();
+			}
+			offsetSegments.append(offsetAndConsumeSegments(offset, segments)
+					.getPathIterator(null), false);
+
+			return offsetSegments;
+		} catch (ParallelLinesCannotBeResolvedException e) {
+			logger.error(e.getMessage(), e);
+			return new GeneralPathX(p.getPathIterator(null));
+		}
+	}
+
+	private static GeneralPathX offsetAndConsumeSegments(double offset,
+			List<LineSegment> segments)
+	throws ParallelLinesCannotBeResolvedException {
+		Map<LineSegment, LineEquation> offsetLines =
+			new HashMap<LineSegment, LineEquation>();
+		int segmentCount = segments.size();
+		// first calculate offset lines with the starting point
+		for (int i = 0; i < segmentCount; i++) {
+			LineSegment segment = (LineSegment)segments.get(i);
+			double theta = segment.angle();
+			//FIXME: �Esto para qu� es?
+			//			if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){
+			//				theta=theta+0.00000000000001;
+			//			}
+
+			double xOffset = offset * Math.sin(theta);
+			double yOffset = offset * Math.cos(theta);
+
+			Coordinate p0 = segment.p0;
+			double x0 = p0.x + xOffset;
+			double y0 = p0.y - yOffset;
+
+			Coordinate p1 = segment.p1;
+			double x1 = p1.x + xOffset;
+			double y1 = p1.y - yOffset;
+
+			LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1);
+			offsetLines.put(segment, offsetLine);
+		}
+
+		/*
+		 * let's now calculate the end point of each segment with the point
+		 * where each line crosses the next one. this point will be the end
+		 * point of the first line, and the start point of its next one.
+		 */
+		Point2D pIni = null;
+		Point2D pEnd = null;
+		GeneralPathX gpx = new GeneralPathX();
+		for (int i = 0; i < segmentCount; i++) {
+			LineSegment segment = (LineSegment)segments.get(0);
+			LineEquation eq = (LineEquation)offsetLines.get(segment);
+			if (i == 0) {
+				pIni = new Point2D.Double(eq.x, eq.y);
+			} else {
+				pIni = pEnd;
+			}
+
+			if (i < segmentCount - 1) {
+				LineEquation eq1 = (LineEquation) offsetLines.get(segments.get(1));
+				try{
+					pEnd = eq.resolve(eq1);
+				} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
+					pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
+					gpx.append(new Line2D.Double(pIni, pEnd)
+					.getPathIterator(null), true); // a�adimos una linea
+					// hasta el final
+					// del primer
+					// segmento
+					//					 y asignamos como punto final el principio del siguiente segmento
+					//					 para que en la siguiente iteraci�n lo tome como punto inicial.
+					pIni = pEnd;
+					pEnd = new Point2D.Double(eq1.x, eq1.y);
+					segments.remove(0);
+					continue;
+				}
+			} else {
+				pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
+			}
+
+			gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true);
+			segments.remove(0);
+		}
+		return gpx;
+	}
+
+	private static GeneralPathX offsetAndConsumeClosedSegments(double offset,
+			List<LineSegment> segments)
+	throws ParallelLinesCannotBeResolvedException, NotEnoughSegmentsToClosePathException {
+		int segmentCount = segments.size();
+		if (segmentCount > 1) {
+			Map<LineSegment, LineEquation> offsetLines = new HashMap<LineSegment, LineEquation>();
+			// first calculate offset lines with the starting point
+			for (int i = 0; i < segmentCount; i++) {
+				LineSegment segment = (LineSegment)segments.get(i);
+				double theta = segment.angle();
+				//FIXME: �Esto para qu� es?
+				//			if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){
+				//				theta=theta+0.00000000000001;
+				//			}
+
+				double xOffset = offset * Math.sin(theta);
+				double yOffset = offset * Math.cos(theta);
+
+				Coordinate p0 = segment.p0;
+				double x0 = p0.x + xOffset;
+				double y0 = p0.y - yOffset;
+
+				Coordinate p1 = segment.p1;
+				double x1 = p1.x + xOffset;
+				double y1 = p1.y - yOffset;
+
+				LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1);
+				offsetLines.put(segment, offsetLine);
+			}
+
+			/*
+			 * let's now calculate the end point of each segment with the point
+			 * where each line crosses the next one. this point will be the end
+			 * point of the first line, and the start point of its next one.
+			 */
+			Point2D pIni = null;
+			Point2D pEnd = null;
+			Point2D firstP = null;
+			GeneralPathX gpx = new GeneralPathX();
+			for (int i = 0; i < segmentCount; i++) {
+				LineSegment segment = (LineSegment)segments.get(0);
+				LineEquation eq = offsetLines.get(segment);
+				if (i == 0) { //Calculo de la intersecci�n entre el primer segmento y el �ltimo
+					LineEquation eq0 = offsetLines.get((LineSegment)segments.get(segmentCount-1));
+					try{
+						pIni = eq0.resolve(eq);
+					} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
+						//						pIni = new Point2D.Double(eq0.xEnd, eq0.yEnd);
+						pIni = new Point2D.Double(eq.x, eq.y);
+					}
+					firstP = pIni;
+				} else {
+					pIni = pEnd;
+				}
+
+				if (i < segmentCount - 1) {
+					LineEquation eq1 = offsetLines.get((LineSegment)segments.get(1));
+					try{
+						pEnd = eq.resolve(eq1);
+					} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
+						pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
+						gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true); // a�adimos una linea hasta el final del primer segmento
+						//					 y asignamos como punto final el principio del siguiente segmento
+						//					 para que en la siguiente iteraci�n lo tome como punto inicial.
+						pIni = pEnd;
+						pEnd = new Point2D.Double(eq1.x, eq1.y);
+						segments.remove(0);
+						continue;
+					}
+				} else {
+					//					pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
+					pEnd = new Point2D.Double(firstP.getX(), firstP.getY());
+				}
+
+				gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true);
+				segments.remove(0);
+			}
+			return gpx;
+		}
+		throw new NotEnoughSegmentsToClosePathException(segments);
+
+	}
+
+	//	private static GeneralPathX offsetAndConsumeClosedSegments(double offset,
+	//			List<LineSegment> segments)
+	//	throws ParallelLinesCannotBeResolvedException,
+	//	NotEnoughSegmentsToClosePathException {
+	//		int segmentCount = segments.size();
+	//		if (segmentCount > 1) {
+	//			GeneralPathX openPath = offsetAndConsumeSegments(offset, segments);
+	//			openPath.closePath();
+	//			return openPath;
+	//		}
+	//		throw new NotEnoughSegmentsToClosePathException(segments);
+	//	}
+}
+
+class LineEquation {
+	double theta, m, x, y;
+
+	double xEnd, yEnd; // just for simplicity of code
+
+	public LineEquation(double theta, double x, double y, double xEnd,
+			double yEnd) {
+		//		this.theta = Math.tan(theta); //Esto es un error, no podemos confundir el angulo de la recta con su pendiente
+		this.theta = theta;
+		this.m = Math.tan(theta);
+		this.x = x;
+		this.y = y;
+		this.xEnd = xEnd;
+		this.yEnd = yEnd;
+	}
+
+	public Point2D resolve(LineEquation otherLine)
+	throws ParallelLinesCannotBeResolvedException {
+		/*
+		 * line1 (this): y - y0 = m*(x - x0)
+		 * line2 (otherLine): y' - y'0 = m'*(x' - x'0)
+		 */
+
+		double X;
+		double Y;
+		if(Math.abs(this.x - this.xEnd)<0.00001) { //Esta linea es vertical
+			//			System.out.println("1 VERTICAL");
+			X = this.xEnd;
+			if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
+				//				System.out.println("    2 PERPENDICULAR");
+				if(Math.abs(this.x - otherLine.x)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea.
+					//					System.out.println("        MISMA LINEA");
+					Y = otherLine.y;
+				} else { //No son la misma linea, entonces son paralelas, excepcion.
+					//					System.out.println("        CASCO POR 1");
+					throw new ParallelLinesCannotBeResolvedException(this, otherLine);
+				}
+			} else if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
+				//				System.out.println("    2 HORIZONTAL");
+				Y = otherLine.y;
+			} else { //Si no
+				//				System.out.println("    2 CUALQUIERA");
+				Y = otherLine.m*(X - otherLine.x)+otherLine.y;
+			}
+
+		} else if (Math.abs(this.y - this.yEnd)<0.00001) { //Esta linea es horizontal
+			//			System.out.println("1 HORIZONTAL");
+			Y = this.yEnd;
+			if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
+				//				System.out.println("    2 HORIZONTAL");
+				if(Math.abs(this.y - otherLine.y)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea.
+					//					System.out.println("        MISMA LINEA");
+					X = otherLine.x;
+				} else { //No son la misma linea, entonces son paralelas, excepcion.
+					//					System.out.println("        CASCO POR 2");
+					throw new ParallelLinesCannotBeResolvedException(this, otherLine);
+				}
+			} else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
+				//				System.out.println("    2 VERTICAL");
+				X = otherLine.x;
+			} else { //Si no
+				//				System.out.println("    2 CUALQUIERA");
+				X = (Y - otherLine.y)/otherLine.m +otherLine.x;
+			}
+		} else { //Esta linea no es ni vertical ni horizontal
+			//			System.out.println("1 CUALQUIERA");
+			if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
+				//				System.out.println("    2 HORIZONTAL");
+				Y = otherLine.y;
+				X = (Y - this.y)/this.m +this.x;
+			} else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
+				//				System.out.println("    2 VERTICAL");
+				X = otherLine.x;
+				Y = this.m*(X - this.x)+this.y;
+			} else if ((Math.abs(otherLine.m - this.m)<0.00001)) { //Tienen la misma pendiente
+				//				System.out.println("    MISMA PENDIENTE");
+				Y = otherLine.m*(this.x - otherLine.x)+otherLine.y;
+				if (Math.abs(this.y - Y)<0.00001){ //Las lineas son la misma
+					//					System.out.println("        MISMA LINEA");
+					X = otherLine.x;
+					Y = otherLine.y;
+				} else {
+					//					System.out.println("        CASCO POR 3");
+					throw new ParallelLinesCannotBeResolvedException(this, otherLine);
+				}
+			} else {
+				//				System.out.println("    AMBAS CUALESQUIERA");
+				double mTimesX = this.m * this.x;
+				X = (mTimesX - this.y - otherLine.m * otherLine.x + otherLine.y) / (this.m - otherLine.m);
+				Y = this.m * X - mTimesX + this.y;
+			}
+		}
+
+		//		System.out.println("DEVOLVEMOS X = "+X+" Y = "+Y);
+		return new Point2D.Double(X, Y);
+
+	}
+
+	public String toString() {
+		return "Y - " + y + " = " + m + "*(X - " + x + ")";
+	}
+}
+
+class NotEnoughSegmentsToClosePathException extends Exception {
+	private static final long serialVersionUID = 95503944546535L;
+
+	public NotEnoughSegmentsToClosePathException(List<LineSegment> segments) {
+		super("Need at least 2 segments to close a path. I've got "
+				+ segments.size() + ".");
+	}
+}
+
+class ParallelLinesCannotBeResolvedException extends Exception {
+	private static final long serialVersionUID = 8322556508820067641L;
+
+	public ParallelLinesCannotBeResolvedException(LineEquation eq1,
+			LineEquation eq2) {
+		super("Lines '" + eq1 + "' and '" + eq2
+				+ "' are parallel and don't share any point!");
+	}
+}
+//public class Line2DOffset {
+
+//private static final double TOL = 1E-8;
+//private static final double ANGLE_TOL = 0.01/180*Math.PI;
+
+//public static GeneralPathX offsetLine(Shape p, double offset) {
+
+//PathIterator pi = p.getPathIterator(null);
+//double[] dataCoords = new double[6];
+//Coordinate from = null, first = null;
+//ArrayList<LineSegment> segments = new ArrayList<LineSegment>();
+//GeneralPathX offsetSegments = new GeneralPathX();
+//try {
+//while (!pi.isDone()) {
+//// while not done
+//int type = pi.currentSegment(dataCoords);
+
+//switch (type) {
+//case PathIterator.SEG_MOVETO:
+//from = new Coordinate(dataCoords[0], dataCoords[1]);
+//first = from;
+//break;
+
+//case PathIterator.SEG_LINETO:
+
+//// System.out.println("SEG_LINETO");
+//Coordinate to = new Coordinate(dataCoords[0], dataCoords[1]);
+//LineSegment line = new LineSegment(from, to);
+//int size = segments.size();
+//if (size>0) {
+//LineSegment prev = segments.get(size-1);
+//if (line.angle() == prev.angle()) {
+//if (Math.abs(line.p0.x - prev.p1.x) < TOL &&
+//Math.abs(line.p0.y - prev.p1.y) < TOL) {
+//prev.p1 = line.p1;
+//break;
+//}
+//}
+//}
+//from = to;
+//segments.add(line);
+
+//break;
+//case PathIterator.SEG_CLOSE:
+//line = new LineSegment(from, first);
+//segments.add(line);
+//from = first;
+//try {
+//offsetSegments.append(offsetAndConsumeClosedSegments(offset, segments), false);
+//} catch (NotEnoughSegmentsToClosePathException e) {
+//Logger.getLogger(Line2DOffset.class).error(e.getMessage(), e);
+//}
+//break;
+
+//} // end switch
+
+//pi.next();
+//}
+//offsetSegments.append(offsetAndConsumeSegments(offset, segments), true);
+
+//return offsetSegments;
+//} catch (ParallelLinesCannotBeResolvedException e) {
+//Logger.getLogger(Line2DOffset.class).error(e.getMessage(), e);
+//return new GeneralPathX(p);
+//}
+//}
+
+//private static GeneralPathX offsetAndConsumeSegments(double offset, ArrayList<LineSegment> segments)  {
+//Hashtable<LineSegment, LineEquation> offsetLines = new Hashtable<LineSegment, LineEquation>();
+//int segmentCount = segments.size();
+//// first calculate offset lines with the starting point
+//for (int i = 0; i < segmentCount; i++) {
+//LineSegment segment = segments.get(i);
+//double theta = segment.angle();
+
+//double xOffset = offset*Math.sin(theta);
+//double yOffset = offset*Math.cos(theta);
+
+//Coordinate p0 = segment.p0;
+//double x0 = p0.x + xOffset;
+//double y0 = p0.y - yOffset;
+
+//Coordinate p1 = segment.p1;
+//double x1 = p1.x + xOffset;
+//double y1 = p1.y - yOffset;
+
+//LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1, offset);
+//offsetLines.put(segment, offsetLine);
+//}
+
+///*
+//* let's now calculate the end point of each segment with
+//* the point where each line crosses the next one.
+//* this point will be the end point of the first line, and
+//* the start point of its next one.
+//*/
+//Point2D pIni = null;
+//Point2D pEnd = null;
+//GeneralPathX gpx = new GeneralPathX();
+//for (int i = 0; i < segmentCount; i++) {
+//LineSegment segment = segments.get(0);
+//LineEquation eq = offsetLines.get(segment);
+//Point2D pAux = null;
+//if (i < segmentCount -1) {
+//try {
+//pAux = eq.resolve(offsetLines.get(segments.get(1)));
+//if (i == 0) {
+//pIni = new Point2D.Double(eq.x, eq.y);
+//} else {
+//pIni = pEnd;
+//}
+//} catch (ParallelLinesCannotBeResolvedException e) {
+//segments.remove(0);
+//continue;
+//}
+//}
+
+
+//if (pAux != null) {
+//pEnd = pAux;
+//} else {
+//pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
+//}
+
+//gpx.append(new Line2D.Double(pIni, pEnd), true);
+//segments.remove(0);
+//}
+//return gpx;
+//}
+
+//private static GeneralPathX offsetAndConsumeClosedSegments(double offset, ArrayList<LineSegment> segments) throws ParallelLinesCannotBeResolvedException, NotEnoughSegmentsToClosePathException {
+//int segmentCount = segments.size();
+//if (segmentCount > 1) {
+//GeneralPathX openPath = offsetAndConsumeSegments(offset, segments);
+//openPath.closePath();
+//return openPath;
+//}
+//throw new NotEnoughSegmentsToClosePathException(segments);
+//}
+//}
+
+//class LineEquation {
+//double theta, x, y;
+//double xEnd, yEnd; // just for simplicity of code
+//double offset;
+
+//public LineEquation(double theta, double x, double y, double xEnd, double yEnd, double offset) {
+//this.theta = theta;
+//this.x = x;
+//this.y = y;
+//this.xEnd = xEnd;
+//this.yEnd = yEnd;
+//this.offset = offset;
+//}
+
+//public Point2D resolve(LineEquation otherLine) throws ParallelLinesCannotBeResolvedException {
+//double X;
+//double Y;
+
+
+///*
+//* line1 (this):      y  -  y0 =  m*(x  - x0)
+//* line2 (otherLine): y' - y'0 = m'*(x' - x'0)
+//*/
+//if (otherLine.theta == this.theta)
+//throw new ParallelLinesCannotBeResolvedException(this, otherLine);
+
+//if (Math.cos(theta) == 0) {
+
+//X = otherLine.x + offset*Math.cos(otherLine.theta);
+//Y = otherLine.y + offset*Math.sin(otherLine.theta);
+//} else if (Math.cos(otherLine.theta) == 0) {
+//X = x + offset*Math.cos(theta);
+//Y = y + offset*Math.sin(theta);
+//} else {
+///*
+//* m*(X - x0) + y0 = m'*(X - x'0) + y0'
+//* X = (m*x0 - y0 - m'*x0' + y'0) / (m - m')
+//*/
+//double tanTheta = Math.tan(theta);
+//double otherTanTheta = Math.tan(otherLine.theta);
+//double thetaTimesX = tanTheta*this.x;
+//X = (thetaTimesX - this.y - otherTanTheta*otherLine.x + otherLine.y) / (tanTheta - otherTanTheta);
+
+///*
+//* Y - y0 = m*(X - x0)
+//* Y = m*X - m*x0 + y0
+//*/
+//Y = tanTheta*X - thetaTimesX + this.y;
+//}
+//return new Point2D.Double(X, Y);
+//}
+
+//@Override
+//public String toString() {
+//return "Y - "+y+" = "+theta+"*(X - "+x+")";
+//}
+//}
+
+//class NotEnoughSegmentsToClosePathException extends Exception {
+//private static final long serialVersionUID = 95503944546535L;
+//public NotEnoughSegmentsToClosePathException(ArrayList<LineSegment> segments) {
+//super("Need at least 2 segments to close a path. I've got "+segments.size()+".");
+//}
+//}
+
+//class ParallelLinesCannotBeResolvedException extends Exception {
+//private static final long serialVersionUID = 8322556508820067641L;
+
+//public ParallelLinesCannotBeResolvedException(LineEquation eq1, LineEquation eq2) {
+//super("Lines '"+eq1+"' and '"+eq2+"' are parallel and don't share any point!");
+//}
+//}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ArrowDecoratorStyle.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ArrowDecoratorStyle.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ArrowDecoratorStyle.java	(revision 33580)
@@ -0,0 +1,355 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import org.apache.batik.ext.awt.geom.PathLength;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.ArrowMarkerSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Class ArrowDecoratorStyle. It is used to store the information about the
+ * different options to draw an arrow in a line (and draw it too). This
+ * information is taken from the panel.
+ *
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class ArrowDecoratorStyle extends AbstractStyle {
+	public static final String ARROR_DECORATOR_STYLE_PERSISTENCE_DEFINITION_NAME = "ArrowDecoratorStyle";
+
+	private static final String FIELD_FLIP_ALL = "flipAll";
+	private static final String FIELD_FLIP_FIRST = "flipFirst";
+	private static final String FIELD_ARROW_MARKER_COUNT = "arrowMarkerCount";
+	private static final String FIELD_FOLLOW_LINE_ANGLE = "followLineAngle";
+	private static final String FIELD_MARKER = "marker";
+
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private boolean flipAll = false;
+	private boolean flipFirst = false;
+	private int arrowMarkerCount = 2;
+	private boolean followLineAngle = true;
+	private IMarkerSymbol marker = new ArrowMarkerSymbol();
+
+	public ArrowDecoratorStyle() {
+		marker.setSize(10);
+		((ArrowMarkerSymbol) marker).setSharpness(30);
+	}
+
+	/**
+	 * Obtains the number of arrows that the user wants to draw in the same line.
+	 * @return
+	 */
+	public int getArrowMarkerCount() {
+		return arrowMarkerCount;
+	}
+
+	/**
+	 * Defines the number of arrows that the user wants to draw in the same line.
+	 * @return
+	 */
+	public void setArrowMarkerCount(int arrowMarkerCount) {
+		this.arrowMarkerCount = arrowMarkerCount;
+	}
+
+	/**
+	 * Defines the flipAll attribute.If the value of this attribute is true all the
+	 * arrows that we had drawn in the same line will be flipped.
+	 * @return
+	 */
+	public boolean isFlipAll() {
+		return flipAll;
+	}
+
+	/**
+	 * Obtains the flipAll attribute.If the value of this attribute is true all the
+	 * arrows that we had drawn in the same line will be flipped.
+	 * @return
+	 */
+	public void setFlipAll(boolean flipAll) {
+		this.flipAll = flipAll;
+	}
+
+	/**
+	 * Obtains the flipFirst attribute.If it is true only the first arrow of the line
+	 * will be flipped.The rest will keep the same orientation.
+	 * @return
+	 */
+	public boolean isFlipFirst() {
+		return flipFirst;
+	}
+
+	/**
+	 * Sets the flipFirst attribute.If it is true only the first arrow of the line
+	 * will be flipped.The rest will keep the same orientation.
+	 * @return
+	 */
+	public void setFlipFirst(boolean flipFirst) {
+		this.flipFirst = flipFirst;
+	}
+
+	/**
+	 * Gets the followLineAngle attribute.This attribute allows the arrow that we are
+	 * going to draw to be more or less aligned with the line where it will be included (depending on the angle) .
+	 * @return
+	 */
+	public boolean isFollowLineAngle() {
+		return followLineAngle;
+	}
+
+	/**
+	 * Sets the followLineAngle attribute.This attribute allows the arrow that we are
+	 * going to draw to be more or less aligned with the line where it will be included.
+	 * (depending on the angle).
+	 * @param followingLineAngle
+	 * @return
+	 */
+	public void setFollowLineAngle(boolean followLineAngle) {
+		this.followLineAngle = followLineAngle;
+	}
+	/**
+	 * Draws an arrow(or other symbol that substitutes an arrow selected by the user)
+	 * in a line.When the line is drawn, the symbol is added and takes care of the different
+	 * options of the user(for example if he wants to flip the first symbol or all and
+	 * the number of symbols per line to be drawn)
+	 * @param g
+	 * @param affineTransform
+	 * @param feature 
+	 * @param shp
+	 * @throws CreateGeometryException 
+	 */
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature) throws CreateGeometryException {
+		if (arrowMarkerCount <= 0) return;
+
+		PathLength pl = new PathLength(geom);
+		float size = (float) marker.getSize();
+		float myLineLength = pl.lengthOfPath()-size; // length without the first and last arrow
+		float step = arrowMarkerCount>2 ? myLineLength/(arrowMarkerCount-1) : pl.lengthOfPath();
+		float rotation1; // rotation at the arrow's vertex
+		float rotation2; // rotation at the arrow's back;
+
+		Point startP;
+
+		// the first arrow at the end of the line
+		{
+			float theLength = pl.lengthOfPath();
+
+			if ((flipFirst || flipAll) && (flipFirst != flipAll)) { // logical XOR
+				Point2D p = pl.pointAtLength(theLength-size);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+				rotation1 = pl.angleAtLength(theLength-size);
+				rotation2 = pl.angleAtLength(theLength);
+			} else {
+				Point2D p = pl.pointAtLength(theLength);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+				rotation1 = pl.angleAtLength(theLength-size)+(float) Math.PI;
+				rotation2 = pl.angleAtLength(theLength)+(float) Math.PI;
+
+			}
+
+			if (rotation1 == rotation2)	{
+				marker.setRotation(rotation1);
+				marker.draw(g, affineTransform, startP, feature, null);
+			}
+		}
+		// the other arrows but the first and the last
+		float aLength;
+		for (int i = 1; i < arrowMarkerCount-1; i++) {
+			aLength = (float) (step*i);
+
+			rotation1 = (float) pl.angleAtLength(aLength);
+			rotation2 = (float) pl.angleAtLength((float)(aLength+size));
+
+			if (flipAll) {
+				Point2D p = pl.pointAtLength(aLength);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+
+			} else {
+				Point2D p = pl.pointAtLength(aLength+size);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+				rotation1 += Math.PI;
+				rotation2 += Math.PI;
+			}
+			/*
+			 *  the following are just visualization improvements,
+			 *  being rigurous it just be only these two lines
+			 *
+			 *  marker.setRotation(rotation1);
+			 *  marker.draw(g, affineTransform, startP);
+			 *
+			 *  but it produces ugly results at the line edges
+			 */
+			if (rotation1 == rotation2)	{
+				marker.setRotation(rotation1);
+				marker.draw(g, affineTransform, startP, feature, null);
+			} else {
+				rotation1 = (float) pl.angleAtLength(aLength+1);
+				rotation2 = (float) pl.angleAtLength((float)(aLength+size+1));
+				if (flipAll) {
+					Point2D p = pl.pointAtLength(aLength+1);
+					startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+
+				} else {
+					Point2D p = pl.pointAtLength(aLength+size+1);
+					startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+					rotation1 += Math.PI;
+					rotation2 += Math.PI;
+				}
+
+				if (rotation1 == rotation2)	{
+					marker.setRotation(rotation1);
+					marker.draw(g, affineTransform, startP, feature, null);
+				}
+			}
+
+		}
+
+		// and the last arrow at the begining of the line
+		if (arrowMarkerCount>1) {
+			rotation1 = (float) pl.angleAtLength(size);
+			rotation2 = (float) pl.angleAtLength(0);
+
+			if (flipAll) {
+				Point2D p = pl.pointAtLength(0);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+				
+			} else {
+				Point2D p = pl.pointAtLength(size);
+				startP = geomManager.createPoint(p.getX(), p.getY(), SUBTYPES.GEOM2D);
+				rotation1 += Math.PI;
+				rotation2 += Math.PI;
+			}
+
+			if (rotation1 == rotation2)	{
+				marker.setRotation(rotation1);
+				marker.draw(g, affineTransform, startP, feature, null);
+			}
+		}
+	}
+
+	public void drawInsideRectangle(Graphics2D g, Rectangle r) {
+		// TODO Auto-generated method stub
+		throw new Error("Not yet implemented!");
+	}
+
+	public void drawOutline(Graphics2D g, Rectangle r) {
+		// TODO Auto-generated method stub
+		throw new Error("Not yet implemented!");
+	}
+
+	public boolean isSuitableFor(ISymbol symbol) {
+		return symbol instanceof ILineSymbol;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public IMarkerSymbol getMarker() {
+		return marker;
+	}
+
+	public void setMarker(IMarkerSymbol marker) {
+		this.marker = marker;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		ArrowDecoratorStyle copy  = (ArrowDecoratorStyle) super.clone();
+		if (marker != null) {
+			copy.marker = (IMarkerSymbol) marker.clone();
+		}
+		return copy;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent style properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setArrowMarkerCount(state.getInt(FIELD_ARROW_MARKER_COUNT));
+		setFlipAll(state.getBoolean(FIELD_FLIP_ALL));
+		setFlipFirst(state.getBoolean(FIELD_FLIP_FIRST));
+		setFollowLineAngle(state.getBoolean(FIELD_FOLLOW_LINE_ANGLE));
+		setMarker((IMarkerSymbol) state.get(FIELD_MARKER));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		state.set(FIELD_ARROW_MARKER_COUNT, getArrowMarkerCount());
+		state.set(FIELD_FLIP_ALL, isFlipAll());
+		state.set(FIELD_FLIP_FIRST, isFlipFirst());
+		state.set(FIELD_FOLLOW_LINE_ANGLE, isFollowLineAngle());
+		state.set(FIELD_MARKER, getMarker());
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				ArrowDecoratorStyle.class,
+				ARROR_DECORATOR_STYLE_PERSISTENCE_DEFINITION_NAME,
+				ARROR_DECORATOR_STYLE_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		
+		// Extend the Style base definition
+		definition.extend(STYLE_PERSISTENCE_DEFINITION_NAME);
+
+		// Arrow marker count
+		definition.addDynFieldInt(FIELD_ARROW_MARKER_COUNT).setMandatory(true);
+		// Flip all
+		definition.addDynFieldBoolean(FIELD_FLIP_ALL).setMandatory(true);
+		// flip first
+		definition.addDynFieldBoolean(FIELD_FLIP_FIRST).setMandatory(true);
+		// Follow line angles
+		definition.addDynFieldBoolean(FIELD_FOLLOW_LINE_ANGLE).setMandatory(true);
+		// Marker
+		definition.addDynFieldObject(FIELD_MARKER)
+			.setClassOfValue(IMarkerSymbol.class)
+			.setMandatory(true);
+
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMarkerFillPropertiesStyle.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMarkerFillPropertiesStyle.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/IMarkerFillPropertiesStyle.java	(revision 33580)
@@ -0,0 +1,92 @@
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.styles.IStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+/**
+ * IMarkerFillPropertiesStyle is an interface used by classes that are trying to fill a
+ * polygon using marker symbols for that. In order to permit a big mount of possibilities for
+ * the filling, this interface has the options to modify the rotation of the markers that
+ * compose the padding, the x and y offset, the x and y separation,and the style of the fill.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public interface IMarkerFillPropertiesStyle extends IStyle {
+	public static final int RANDOM_FILL = 3;
+	public static final int GRID_FILL = 1;
+	public static final int SINGLE_CENTERED_SYMBOL = 2;
+
+	/**
+	 * <p>
+	 * Defines an utility symbol to show up a thumbnail
+	 * by default, this symbol is a SimpleMarkerSymbol.
+	 * Thus, the drawInsideRectangle will always work. But
+	 * it can be changed with setSampleSymbol(IMakerSymbol).<br>
+	 * </p>
+	 * <p>
+	 * If <b>marker</b> is null, it does nothing
+	 * </p>
+	 */
+	public void setSampleSymbol(IMarkerSymbol marker) ;
+
+	/**
+	 * Obtains the rotation of the marker symbol that compose the padding.
+	 * @return the rotation of a marker
+	 */
+	public double getRotation();
+	/**
+	 * Sets the rotation of the marker symbol that compose the padding.
+	 * @param rotation
+	 */
+	public void setRotation(double rotation) ;
+	/**
+	 * Returns the x offset of the markers that compose the padding
+	 * @return xoffset of the marker
+	 */
+	public double getXOffset();
+	/**
+	 * Establishes de x offset of the markers that compose the padding
+	 * @param offset
+	 */
+	public void setXOffset(double offset) ;
+	/**
+	 * Return the separation (x axis) between the markers that compose the padding
+	 * @return x separation
+	 */
+	public double getXSeparation() ;
+	/**
+	 * Sets the separation (x axis) between the markers that compose the padding
+	 * @param separation
+	 */
+	public void setXSeparation(double separation);
+
+	/**
+	 * Returns the y offset of the markers that compose the padding
+	 * @return yoffset of the marker
+	 */
+	public double getYOffset();
+	/**
+	 * Establishes the y offset of the markers that compose the padding
+	 * @param offset
+	 */
+	public void setYOffset(double offset) ;
+	/**
+	 * Return the separation (y axis) between the markers that compose the padding
+	 * @return y separation
+	 */
+	public double getYSeparation() ;
+	/**
+	 * Sets the separation (y axis) between the markers that compose the padding
+	 * @param separation
+	 */
+	public void setYSeparation(double separation);
+	/**
+	 * Sets the style for the fill that use marker symbols to do it(the filled).
+	 * @param fillStyle
+	 */
+	public void setFillStyle(int fillStyle);
+	/**
+	 * Returns the style of the fill that use marker symbols to do it(the filled).
+	 * @return int, fill style
+	 */
+	public int getFillStyle();
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/DefaultMask.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/DefaultMask.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/DefaultMask.java	(revision 33580)
@@ -0,0 +1,167 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class DefaultMask extends AbstractStyle implements IMask {
+
+	public static final String DEFAULT_MASK_PERSISTENCE_DEFINITION_NAME = "DefaultMask";
+
+	private static final String FIELD_SIZE = "size";
+	private static final String FIELD_FILL_SYMBOL = "fillSymbol";
+
+	private static final GeometryManager geomManager = GeometryLocator
+			.getGeometryManager();
+	private static final Logger logger = LoggerFactory
+			.getLogger(DefaultMask.class);
+	private double size;
+	private IFillSymbol fill;
+
+	public double getSize() {
+		return size;
+	}
+
+	public void setSize(double size) {
+		this.size = size;
+	}
+
+	public IFillSymbol getFillSymbol() {
+		return fill;
+
+	}
+
+	public void setFillSymbol(IFillSymbol fill) {
+		this.fill = fill;
+	}
+
+	public void drawInsideRectangle(Graphics2D g, Rectangle r) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public Geometry getHaloShape(Shape shp) {
+		BasicStroke stroke = new BasicStroke(
+				(int) /* falta CartographicSupport */getSize());
+		Shape myShp = stroke.createStrokedShape(shp);
+		Geometry haloShape = null;
+		;
+		try {
+			haloShape = geomManager.createSurface(new GeneralPathX(myShp
+					.getBounds2D().getPathIterator(null)), SUBTYPES.GEOM2D);
+		} catch (CreateGeometryException e) {
+			logger.error("Error creating a surface", e);
+		}
+
+		return haloShape;
+	}
+
+	public boolean isSuitableFor(ISymbol symbol) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public void drawOutline(Graphics2D g, Rectangle r) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public String getClassName() {
+		return this.getClass().getName();
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		DefaultMask copy = (DefaultMask) super.clone();
+		if (fill != null) {
+			copy.fill = (IFillSymbol) fill.clone();
+		}
+		return copy;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent style properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setFillSymbol((IFillSymbol) state.get(FIELD_FILL_SYMBOL));
+		setSize(state.getDouble(FIELD_SIZE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		if (getFillSymbol() != null) {
+			state.set(FIELD_FILL_SYMBOL, getFillSymbol());
+		}
+		state.set(FIELD_SIZE, getSize());
+	}
+
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				DefaultMask.class,
+				DEFAULT_MASK_PERSISTENCE_DEFINITION_NAME,
+				DEFAULT_MASK_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		
+		// Extend the Style base definition
+		definition.extend(STYLE_PERSISTENCE_DEFINITION_NAME);
+
+		// Fill symbol
+		definition.addDynFieldObject(FIELD_FILL_SYMBOL)
+			.setClassOfValue(IFillSymbol.class);
+		// size
+		definition.addDynFieldDouble(FIELD_SIZE).setMandatory(true);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ILineStyle.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ILineStyle.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/ILineStyle.java	(revision 33580)
@@ -0,0 +1,133 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+ *
+ * $Id: ILineStyle.java 20989 2008-05-28 11:05:57Z jmvivo $
+ * $Log$
+ * Revision 1.7  2007-08-13 11:36:30  jvidal
+ * javadoc
+ *
+ * Revision 1.6  2007/07/26 12:36:52  jaume
+ * character encoding mispell
+ *
+ * Revision 1.5  2007/07/23 06:53:56  jaume
+ * Added support for arrow line decorator (start commiting)
+ *
+ * Revision 1.4  2007/05/09 16:07:26  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.3  2007/05/08 08:47:39  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.2  2007/03/09 11:20:56  jaume
+ * Advanced symbology (start committing)
+ *
+ * Revision 1.1.2.3  2007/02/15 16:23:44  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/02/12 15:15:20  jaume
+ * refactored interval legend and added graduated symbol legend
+ *
+ * Revision 1.1.2.1  2007/02/09 07:47:04  jaume
+ * Isymbol moved
+ *
+ *
+ */
+
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.Stroke;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.styles.IStyle;
+
+
+
+
+/**
+ * Interface that controls the properties that define the style of a line.This
+ * properties are the width, stroke, offset and arrow decorator style( for example
+ * if the line includes markers as an arrow to specify an orientation).
+ * @author   jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public interface ILineStyle extends IStyle {
+	/**
+	 * Returns the width of the line
+	 * @return
+	 */
+	public abstract float getLineWidth();
+	/**
+	 * Establishes the width of the line
+	 * @param width of the line
+	 */
+	public abstract void setLineWidth(float width);
+	/**
+	 * Returns the stroke of the line
+	 * @return Stroke of the line
+	 */
+	public abstract Stroke getStroke();
+	/**
+	 * Sets the stroke of the line
+	 * @param stroke,stroke to be established
+	 */
+	public abstract void setStroke(Stroke stroke);
+	/**
+	 * Gets the arrow decorator style that has the line
+	 * @return ArrowDecoratorStyle
+	 */
+	public abstract ArrowDecoratorStyle getArrowDecorator();
+	/**
+	 * Sets the arrow decorator style of the line
+	 * @param arrowDecoratorStyle, ArrowDecoratorStyle
+	 */
+	public abstract void setArrowDecorator(ArrowDecoratorStyle arrowDecoratorStyle);
+	/**
+	 * Returns the offset of the line
+	 * @return
+	 */
+	public abstract double getOffset();
+	/**
+	 * Establishes the offset of the line
+	 * @param offset
+	 */
+	public abstract void setOffset(double offset);
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/SimpleLineStyle.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/SimpleLineStyle.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/SimpleLineStyle.java	(revision 33580)
@@ -0,0 +1,408 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * @see http://www.oreilly.com/catalog/java2d/chapter/ch04.html
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SimpleLineStyle extends AbstractStyle implements ILineStyle, CartographicSupport {
+	public static final String SIMPLE_LINE_STYLE_PERSISTENCE_DEFINITION_NAME = "SimpleLineStyle";
+
+	private static final String FIELD_DASH_ARRAY = "dashArray";
+	private static final String FIELD_TEMP_DASH_ARRAY = "tempDashArray";
+	private static final String FIELD_LINE_WIDTH = "lineWidth";
+	private static final String FIELD_DASH_PHASE = "dashPhase";
+	private static final String FIELD_END_CAP = "endCap";
+	private static final String FIELD_LINE_JOIN = "lineJoin";
+	private static final String FIELD_MITER_LIMIT = "miterLimit";
+	private static final String FIELD_OFFSET = "offset";
+	private static final String FIELD_UNIT = "unit";
+	private static final String FIELD_ARROW_DECORATOR = "arrowDecorator";
+
+	private final static Color PREVIEW_COLOR_1= new Color(150, 255, 200); //light blue
+	private final static Color PREVIEW_COLOR_2 = new Color(255, 200, 100); //orange
+	private final static int COLOR1_STROKE = 1;
+	private final static int COLOR2_STROKE = 3;
+	private float[] dashArray, tempDashArray;
+	private float dashPhase;
+	private int endCap = BasicStroke.CAP_BUTT;
+	private int lineJoin;
+	private float miterlimit;
+	private float lineWidth = 1f;
+	private int measureUnit;// for the offset distance
+	private double offset = 0, csOffset = 0;
+	private int referenceSystem;
+	private ArrowDecoratorStyle arrowDecorator;
+	/**
+	 * Constructor method
+	 *
+	 */
+	public SimpleLineStyle() {
+		BasicStroke dummy = new BasicStroke();
+		dashArray = dummy.getDashArray();
+		tempDashArray = dummy.getDashArray();
+		dashPhase = dummy.getDashPhase();
+		endCap = BasicStroke.CAP_BUTT;
+		lineJoin = BasicStroke.JOIN_BEVEL;
+		miterlimit = dummy.getMiterLimit();
+	}
+	/**
+	 * Constructor method
+	 *
+	 * @param width
+	 * @param cap
+	 * @param join
+	 * @param miterlimit
+	 * @param dash
+	 * @param dash_phase
+	 */
+	public SimpleLineStyle(float width, int cap, int join, float miterlimit, float[] dash, float dash_phase) {
+		this.lineWidth = width;
+		this.endCap = cap;
+		this.lineJoin = join;
+		this.miterlimit = miterlimit;
+		this.dashArray = dash;
+		this.tempDashArray = dash;
+		this.dashPhase = dash_phase;
+	}
+
+	public void drawInsideRectangle(Graphics2D g, Rectangle r) {
+		Stroke oldStroke = g.getStroke();
+		int h = (int) (r.getHeight() / 2);
+		int margins = 2;
+
+		BasicStroke stroke;
+		stroke = new BasicStroke(COLOR1_STROKE, endCap, lineJoin, miterlimit, tempDashArray, dashPhase);
+		g.setStroke(stroke);
+		g.setColor(PREVIEW_COLOR_1);
+		g.drawLine(margins, h, r.width-margins-margins, h);
+
+		stroke = new BasicStroke(COLOR2_STROKE, endCap, lineJoin, miterlimit, tempDashArray, dashPhase);
+		g.setStroke(stroke);
+		g.setColor(PREVIEW_COLOR_2);
+		g.drawLine(margins, h, r.width-margins-margins, h);
+		g.setStroke(oldStroke);
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public Stroke getStroke() {
+		return new BasicStroke((float) lineWidth, endCap, lineJoin, miterlimit, tempDashArray, dashPhase);
+	}
+
+	public float getLineWidth() {
+		return lineWidth;
+	}
+
+
+	public void setLineWidth(float width) {
+		if (lineWidth != 0) {
+			double scale = width / this.lineWidth;
+			if (dashArray != null) {
+				for (int i = 0; scale > 0 && i < dashArray.length; i++) {
+					tempDashArray[i] = (float) (dashArray[i] * scale);
+				}
+			}
+			this.csOffset = offset * scale;
+		}
+		this.lineWidth = width;
+
+	}
+
+	public boolean isSuitableFor(ISymbol symbol) {
+		return symbol instanceof ILineSymbol;
+	}
+
+	public void setStroke(Stroke stroke) {
+		if (stroke != null) {
+			BasicStroke dummy = (BasicStroke) stroke;
+			dashArray = dummy.getDashArray();
+			if (dashArray != null) {
+				tempDashArray = new float[dashArray.length];
+				for (int i = 0; i < dashArray.length; i++) {
+					tempDashArray[i] = dashArray[i];
+				}
+			} else
+				tempDashArray = null;
+
+
+			dashPhase = dummy.getDashPhase();
+			endCap = dummy.getEndCap();
+			lineJoin = dummy.getLineJoin();
+			miterlimit = dummy.getMiterLimit();
+			lineWidth = dummy.getLineWidth();
+			offset = getOffset();
+			csOffset = offset;
+		}
+	}
+
+	public void drawOutline(Graphics2D g, Rectangle r) {
+		drawInsideRectangle(g, r);
+	}
+
+	public double getOffset() {
+		return csOffset;
+	}
+
+	public void setOffset(double offset) {
+		this.offset = offset;
+		this.csOffset = offset;
+	}
+
+	public ArrowDecoratorStyle getArrowDecorator() {
+		return arrowDecorator;
+
+	}
+
+	public void setArrowDecorator(ArrowDecoratorStyle arrowDecoratorStyle) {
+		this.arrowDecorator = arrowDecoratorStyle;
+	}
+
+	public void setUnit(int unitIndex) {
+		this.measureUnit = unitIndex;
+	}
+
+	public int getUnit() {
+		return measureUnit;
+	}
+
+	public int getReferenceSystem() {
+		return referenceSystem;
+	}
+
+	public void setReferenceSystem(int referenceSystem) {
+		this.referenceSystem = referenceSystem;
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		double oldWidth = getLineWidth();
+		setCartographicSize(getCartographicSize(viewPort, dpi, geom), geom);
+		return oldWidth;
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		setLineWidth((float) cartographicSize);
+
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		return CartographicSupportToolkit.
+		getCartographicLength(this,
+				getOffset(),
+				viewPort,
+				dpi);
+
+	}
+	
+
+	public Object clone() throws CloneNotSupportedException {
+		SimpleLineStyle copy = (SimpleLineStyle) super.clone();
+		if (arrowDecorator != null) {
+			copy.arrowDecorator = (ArrowDecoratorStyle) arrowDecorator.clone();
+		}
+
+		if (dashArray != null) {
+			copy.dashArray = new float[dashArray.length];
+			System.arraycopy(dashArray, 0, copy.dashArray, 0, dashArray.length);
+		}
+		if (tempDashArray != null) {
+			copy.tempDashArray = new float[tempDashArray.length];
+			System.arraycopy(tempDashArray, 0, copy.tempDashArray, 0,
+					tempDashArray.length);
+		}
+
+		return copy;
+	}
+
+	/**
+	 * @return the dashArray
+	 */
+	private float[] getDashArray() {
+		return dashArray;
+	}
+
+	/**
+	 * @param dashArray
+	 *            the dashArray to set
+	 */
+	private void setDashArray(float[] dashArray) {
+		this.dashArray = dashArray;
+	}
+
+	/**
+	 * @return the dashPhase
+	 */
+	private float getDashPhase() {
+		return dashPhase;
+	}
+
+	/**
+	 * @param dashPhase
+	 *            the dashPhase to set
+	 */
+	private void setDashPhase(float dashPhase) {
+		this.dashPhase = dashPhase;
+	}
+
+	/**
+	 * @return the endCap
+	 */
+	private int getEndCap() {
+		return endCap;
+	}
+
+	/**
+	 * @param endCap
+	 *            the endCap to set
+	 */
+	private void setEndCap(int endCap) {
+		this.endCap = endCap;
+	}
+
+	/**
+	 * @return the lineJoin
+	 */
+	private int getLineJoin() {
+		return lineJoin;
+	}
+
+	/**
+	 * @param lineJoin
+	 *            the lineJoin to set
+	 */
+	private void setLineJoin(int lineJoin) {
+		this.lineJoin = lineJoin;
+	}
+
+	/**
+	 * @return the miterlimit
+	 */
+	private float getMiterlimit() {
+		return miterlimit;
+	}
+
+	/**
+	 * @param miterlimit
+	 *            the miterlimit to set
+	 */
+	private void setMiterlimit(float miterlimit) {
+		this.miterlimit = miterlimit;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent style properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setArrowDecorator((ArrowDecoratorStyle) state
+				.get(FIELD_ARROW_DECORATOR));
+		setDashArray(state.getFloatArray(FIELD_DASH_ARRAY));
+		tempDashArray = state.getFloatArray(FIELD_TEMP_DASH_ARRAY);
+		setDashPhase(state.getFloat(FIELD_DASH_PHASE));
+		setEndCap(state.getInt(FIELD_END_CAP));
+		setLineJoin(state.getInt(FIELD_LINE_JOIN));
+		setLineWidth(state.getFloat(FIELD_LINE_WIDTH));
+		setMiterlimit(state.getFloat(FIELD_MITER_LIMIT));
+		setOffset(state.getDouble(FIELD_OFFSET));
+		setUnit(state.getInt(FIELD_UNIT));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		state.set(FIELD_ARROW_DECORATOR, getArrowDecorator());
+		state.set(FIELD_DASH_ARRAY, getDashArray());
+		state.set(FIELD_TEMP_DASH_ARRAY, tempDashArray);
+		state.set(FIELD_DASH_PHASE, getDashPhase());
+		state.set(FIELD_END_CAP, getEndCap());
+		state.set(FIELD_LINE_JOIN, getLineJoin());
+		state.set(FIELD_LINE_WIDTH, getLineWidth());
+		state.set(FIELD_MITER_LIMIT, getMiterlimit());
+		state.set(FIELD_OFFSET, getOffset());
+		state.set(FIELD_UNIT, getUnit());
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleLineStyle DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SimpleLineStyle.class,
+				SIMPLE_LINE_STYLE_PERSISTENCE_DEFINITION_NAME,
+				SIMPLE_LINE_STYLE_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		// Extend the Style base definition
+		definition.extend(STYLE_PERSISTENCE_DEFINITION_NAME);
+
+		// Arrow decorator
+		definition.addDynFieldObject(FIELD_ARROW_DECORATOR)
+			.setClassOfValue(ArrowDecoratorStyle.class);
+		// Dash array
+		definition.addDynFieldArray(FIELD_DASH_ARRAY)
+			.setClassOfItems(float.class);
+		// Temporal dash array
+		definition.addDynFieldArray(FIELD_TEMP_DASH_ARRAY)
+			.setClassOfItems(float.class);
+		// Dash phase
+		definition.addDynFieldFloat(FIELD_DASH_PHASE).setMandatory(true);
+		// End cap
+		definition.addDynFieldInt(FIELD_END_CAP).setMandatory(true);
+		// Line join
+		definition.addDynFieldInt(FIELD_LINE_JOIN).setMandatory(true);
+		// Line width
+		definition.addDynFieldFloat(FIELD_LINE_WIDTH).setMandatory(true);
+		// Miter limit
+		definition.addDynFieldFloat(FIELD_MITER_LIMIT).setMandatory(true);
+		// Offset
+		definition.addDynFieldDouble(FIELD_OFFSET).setMandatory(true);
+		// Unit
+		definition.addDynFieldInt(FIELD_UNIT).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbol.java	(revision 33580)
@@ -0,0 +1,1150 @@
+/*
+ * Created on 19-feb-2004
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.StringTokenizer;
+
+import javax.swing.ImageIcon;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.gvsig.utils.StringUtilities;
+import org.gvsig.utils.XMLEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+/**
+ * S�mbolo utilizado para guardar las caracter�sticas que se deben de aplicar a
+ * los Shapes a dibujar.
+ *
+ * @author Vicente Caballero Navarro
+ * @deprecated (jaume)
+ */
+public class FSymbol implements ISymbol{
+	private static final Logger logger = LoggerFactory.getLogger(FSymbol.class);
+//	 Para s�mbolos de tipo pol�gono.
+	public final static int SYMBOL_STYLE_FILL_SOLID = 1;
+	public final static int SYMBOL_STYLE_FILL_TRANSPARENT = 2;
+	public final static int SYMBOL_STYLE_FILL_HORIZONTAL = 3;
+	public final static int SYMBOL_STYLE_FILL_VERTICAL = 4;
+	public final static int SYMBOL_STYLE_FILL_CROSS = 5;
+	public final static int SYMBOL_STYLE_FILL_UPWARD_DIAGONAL = 6;
+	public final static int SYMBOL_STYLE_FILL_DOWNWARD_DIAGONAL = 7;
+	public final static int SYMBOL_STYLE_FILL_CROSS_DIAGONAL = 8;
+	public final static int SYMBOL_STYLE_FILL_GRAYFILL = 9;
+	public final static int SYMBOL_STYLE_FILL_LIGHTGRAYFILL = 10;
+	public final static int SYMBOL_STYLE_FILL_DARKGRAYFILL = 11;
+
+	//	Para s�mbolos de tipo Punto
+	public final static int SYMBOL_STYLE_MARKER_CIRCLE = 30;
+	public final static int SYMBOL_STYLE_MARKER_SQUARE = 31;
+	public final static int SYMBOL_STYLE_MARKER_TRIANGLE = 32;
+	public final static int SYMBOL_STYLE_MARKER_CROSS = 33;
+	public final static int SYMBOL_STYLE_MARKER_TRUETYPE = 34;
+	public final static int SYMBOL_STYLE_MARKER_IMAGEN = 35;
+	public final static int SYMBOL_STYLE_DGNSPECIAL = 40;
+
+	// Para s�mbolos de l�neas
+	public final static int SYMBOL_STYLE_LINE_SOLID = 60;
+	public final static int SYMBOL_STYLE_LINE_DASH = 61;
+	public final static int SYMBOL_STYLE_LINE_DOT = 62;
+	public final static int SYMBOL_STYLE_LINE_DASHDOT = 63;
+	public final static int SYMBOL_STYLE_LINE_DASHDOTDOT = 64;
+	public final static int SYMBOL_STYLE_LINE_RAIL = 65;
+	public final static int SYMBOL_STYLE_LINE_ARROW = 66;
+
+	// Para s�mbolos de tipo texto
+	public final static int SYMBOL_STYLE_TEXT_NORMAL = 90;
+	public final static int SYMBOL_STYLE_TEXT_CURSIVE = 91;
+	public final static int SYMBOL_STYLE_TEXT_BOLD = 92;
+	public final static int SYMBOL_STYLE_TEXT_BOLDCURSIVE = 93;
+
+
+
+	private static BufferedImage img =
+		CompatLocator.getGraphicsUtils().createBufferedImage(1, 1,
+			BufferedImage.TYPE_INT_ARGB);
+	
+	private static Rectangle rect = new Rectangle(0, 0, 1, 1);
+	private int m_symbolType;
+	private int m_Style;
+	private boolean m_useOutline;
+	private Color m_Color;
+	private Color m_outlineColor;
+	private Font m_Font;
+	private Color m_FontColor;
+	private float m_FontSize;
+	private int rgb;
+	private ImageObserver imgObserver;
+
+	/**
+	 * Si <code>m_bUseFontSize</code> viene a false entonces m_FontSize viene
+	 * en unidades de mapa (metros)
+	 */
+	private boolean m_bUseFontSizeInPixels;
+
+	/**
+	 * <code>m_bDrawShape</code> indica si queremos dibujar el shape de fondo.
+	 * Es �til cuando est�s etiquetando y no quieres que se dibuje el s�mbolo
+	 * que te sirve de base para etiquetar.
+	 */
+	private boolean m_bDrawShape = true;
+	private int m_Size;
+	private Image m_Icon;
+	private URI m_IconURI;
+	private int m_Rotation;
+	private Paint m_Fill;
+	public String m_LinePattern = "0"; // Solo para poder mostrarlo cuando vamos a seleccionar un s�mbolo
+
+	// En realidad lo podemos ver de BasicStroke, pero....
+	// ya veremos si luego lo quitamos.
+	private Stroke m_Stroke;
+
+	//private float m_stroke=0;
+	// public int m_Transparency; // Ya la lleva dentro del Color
+	private boolean m_bUseSize; // Si est� a true, m_Size viene en coordenadas de mundo real.
+	private int m_AlingVert;
+	private int m_AlingHoriz;
+	private String m_Descrip;
+	public Color m_BackColor;
+	public Paint m_BackFill;
+
+	// private int resolutionPrinting=300;
+
+    /**
+     * Converts the comma-delimited string into a List of trimmed strings.
+     *
+     * @param linePattern a String with comma-delimited values
+     * @param lineWidth DOCUMENT ME!
+     *
+     * @return a List of the Strings that were delimited by commas
+     *
+     * @throws IllegalArgumentException DOCUMENT ME!
+     */
+    public static float[] toArray(String linePattern, float lineWidth) {
+        StringTokenizer st = new StringTokenizer(linePattern, ",");
+        int numTokens = st.countTokens();
+
+        float[] array = new float[numTokens];
+
+        for (int i = 0; i < numTokens; i++) {
+            String string = st.nextToken();
+            array[i] = Float.parseFloat(string) * lineWidth;
+
+            if (array[i] <= 0) {
+                return null;
+            }
+        }
+
+        return array;
+    }
+
+	/**
+	 * Crea un nuevo FSymbol.
+	 * @deprecated use SymbologyFactory.createDefaultSymbol() instead
+	 */
+//    FSymbol() {
+	private FSymbol() {
+		// Nothing to do
+	}
+
+	/**
+	 * Creates a new FSymbol object.
+	 *
+	 * @param tipoSymbol Tipo de s�mbolo.
+	 * @param c Color.
+	 * @deprecated use SymbologyFactory.createDefaultSymbol(shapeType, color) instead
+	 */
+//	public FSymbol(int tipoSymbol, Color c) {
+	// private FSymbol(int tipoSymbol, Color c) {
+	// createSymbol(tipoSymbol, c);
+	// }
+
+	/**
+	 * Crea un nuevo FSymbol.
+	 *
+	 * @param tipoSymbol Tipo de S�mbolo.
+	 * 			case FConstant.SYMBOL_TYPE_POINT:
+			case FConstant.SYMBOL_TYPE_POINTZ:
+			case FConstant.SYMBOL_TYPE_MULTIPOINT:
+				m_bUseSize = true; // Esto es lo primero que hay que hacer siempre
+
+				// para evitar un StackOverflow
+				m_useOutline = false;
+				setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE);
+				setSize(5); //pixels
+
+				break;
+
+			case FConstant.SYMBOL_TYPE_LINE:
+			case FConstant.SYMBOL_TYPE_POLYLINEZ:
+			case FConstant.SYMBOL_TYPE_POLYGONZ:
+				setStroke(new BasicStroke());
+				setStyle(FConstant.SYMBOL_STYLE_LINE_SOLID);
+
+				break;
+
+			case FConstant.SYMBOL_TYPE_FILL:
+			    setStroke(new BasicStroke());
+				setStyle(FConstant.SYMBOL_STYLE_FILL_SOLID);
+
+				break;
+			case FShape.MULTI:
+				m_bUseSize = true;
+			    setStroke(new BasicStroke());
+				setStyle(FConstant.SYMBOL_STYLE_FILL_SOLID);
+
+				// setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE);
+				setSize(5); //pixels
+				break;
+
+			case FConstant.SYMBOL_TYPE_TEXT:
+				setStroke(new BasicStroke());
+				setStyle(FConstant.SYMBOL_STYLE_TEXT_NORMAL);
+				setFont(new Font("Dialog",Font.PLAIN,12));
+				break;
+
+	 */
+	public FSymbol(int tipoSymbol) {
+//	private FSymbol(int tipoSymbol) {
+		int numreg = (int) (Math.random() * 100);
+		Color colorAleatorio = new Color(((numreg * numreg) + 100) % 255,
+				(numreg + ((3 * numreg) + 100)) % 255, numreg % 255);
+
+		createSymbol(tipoSymbol, colorAleatorio);
+	}
+
+	/**
+	 * A partir de un s�mbolo devuelve otro similar pero con el color de
+	 * selecci�n.
+	 *
+	 * @param sym S�mbolo a modificar.
+	 *
+	 * @return S�mbolo modificado.
+	 */
+	public static FSymbol getSymbolForSelection(FSymbol sym) {
+		FSymbol selecSymbol = sym.fastCloneSymbol();
+		selecSymbol.setColor(MapContext.getSelectionColor());
+
+		selecSymbol.setFill(null);
+		// 050215, jmorell: Si en los drivers cambiamos el estilo, aqu� tenemos que
+		// actualizar los cambios. SYMBOL_STYLE_MARKER_SQUARE --> SYMBOL_STYLE_DGNSPECIAL.
+		if ((selecSymbol.getStyle() == SYMBOL_STYLE_FILL_TRANSPARENT)
+		        || (selecSymbol.getStyle() == SYMBOL_STYLE_DGNSPECIAL)) {
+			selecSymbol.setStyle(SYMBOL_STYLE_FILL_SOLID);
+		} else if (selecSymbol.getStyle() == SYMBOL_STYLE_TEXT_BOLD ||
+				selecSymbol.getStyle() == SYMBOL_STYLE_TEXT_BOLDCURSIVE ||
+				selecSymbol.getStyle() == SYMBOL_STYLE_TEXT_CURSIVE ||
+				selecSymbol.getStyle() == SYMBOL_STYLE_TEXT_NORMAL){
+			selecSymbol.setFontColor(MapContext.getSelectionColor());
+		}
+		selecSymbol.rgb = MapContext.getSelectionColor().getRGB();
+
+		return selecSymbol;
+	}
+
+	/**
+	 * Clona el s�mbolo actual.
+	 *
+	 * @return Nuevo s�mbolo clonado.
+	 */
+	public FSymbol cloneSymbol() {
+		return createFromXML(getXMLEntity());
+	}
+
+	/**
+	 * Se usa para el s�mbolo de selecci�n. Es una forma
+	 * r�pida de clonar un s�mbolo, sin hacerlo via XML.
+	 * Vicente, no lo borres!!!
+	 * @return
+	 */
+	public FSymbol fastCloneSymbol()
+	{
+		FSymbol nS = new FSymbol();
+
+
+		nS.m_symbolType = m_symbolType;
+		nS.m_Style = m_Style;
+		nS.m_useOutline = m_useOutline;
+		nS.m_Color = m_Color;
+		nS.m_outlineColor = m_outlineColor;
+		nS.m_Font = m_Font;
+		nS.m_FontColor = m_FontColor;
+		nS.m_FontSize = m_FontSize;
+		nS.m_bUseFontSizeInPixels = m_bUseFontSizeInPixels;
+		nS.m_bDrawShape = m_bDrawShape;
+		nS.m_Size = m_Size;
+		nS.m_Icon = m_Icon;
+		nS.m_IconURI = m_IconURI;
+		nS.m_Rotation = m_Rotation;
+		nS.m_Fill = m_Fill;
+		nS.m_Stroke = m_Stroke;
+		// nS.m_Transparency =m_Transparency ;
+		nS.m_bUseSize = m_bUseSize;
+		nS.m_AlingVert = m_AlingVert;
+		nS.m_AlingHoriz = m_AlingHoriz;
+		nS.m_Descrip = m_Descrip;
+		nS.m_BackColor = m_BackColor;
+		nS.m_BackFill = m_BackFill;
+
+		nS.m_LinePattern = m_LinePattern;
+
+		return nS;
+	}
+
+
+	/**
+	 * Crea un s�mbolo a partir del tipo y el color.
+	 *
+	 * @param tipoSymbol Tipo de s�mbolo.
+	 * @param c Color del s�mbolo a crear.
+	 */
+	private void createSymbol(int tipoSymbol, Color c) {
+		// OJO: HE HECHO COINCIDIR LOS TIPOS DE SIMBOLO
+		//FConstant.SYMBOL_TYPE_POINT, LINE Y FILL CON
+		// FShape.POINT, LINE, POLYGON. EL .MULTI SE REFIERE
+		// A MULTIPLES TIPO DENTRO DEL SHAPE, AS� QUE SER� UN
+		// MULTISIMBOLO
+		// Tipo de simbolo
+		m_symbolType = tipoSymbol; // Para no recalcular el pixel, no usamos los set
+
+		// Ponemos un estilo por defecto
+		m_useOutline = true;
+		m_Color = c;
+		m_Stroke = null;
+		m_Fill = null;
+
+		m_FontColor = Color.BLACK;
+		m_FontSize = 10;
+		m_bUseFontSizeInPixels = true;
+
+		m_Size = 2;
+
+		switch (getSymbolType()) {
+			case Geometry.TYPES.POINT:
+			case Geometry.TYPES.MULTIPOINT:
+				m_bUseSize = true; // Esto es lo primero que hay que hacer siempre
+
+				// para evitar un StackOverflow
+				m_useOutline = false;
+				setStyle(SYMBOL_STYLE_MARKER_SQUARE);
+				setSize(5); //pixels
+
+				break;
+
+			case Geometry.TYPES.CURVE:			
+				setStroke(new BasicStroke());
+				setStyle(SYMBOL_STYLE_LINE_SOLID);
+
+				break;
+
+			case Geometry.TYPES.SURFACE:
+			    setStroke(new BasicStroke());
+				setStyle(SYMBOL_STYLE_FILL_SOLID);
+
+				break;
+			case Geometry.TYPES.GEOMETRY:
+				m_bUseSize = true;
+			    setStroke(new BasicStroke());
+				setStyle(SYMBOL_STYLE_FILL_SOLID);
+
+				// setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE);
+				setSize(5); //pixels
+				break;
+
+			case Geometry.TYPES.TEXT:
+				setStroke(new BasicStroke());
+				setStyle(SYMBOL_STYLE_TEXT_NORMAL);
+				setFont(new Font("Dialog",Font.PLAIN,12));
+				break;
+		}
+
+		m_outlineColor = c.darker();
+
+		calculateRgb();
+	}
+
+	/**
+	 * Calcula el RGB del s�mbolo.
+	 */
+	public void calculateRgb() {
+		// Recalculamos el RGB
+		Graphics2D g2 = img.createGraphics();
+
+		try {
+			FGraphicUtilities.DrawSymbol(g2, g2.getTransform(), rect, this);
+		} catch (CreateGeometryException e) {
+			logger.error("Creating a geometry", e);
+			e.printStackTrace();
+		}
+		rgb = img.getRGB(0, 0);
+	}
+
+	/**
+	 * Devuelve el rgb del s�mbolo.
+	 *
+	 * @return rgb del s�mbolo.
+	 */
+	public int getOnePointRgb() {
+		return rgb;
+	}
+
+	/**
+	 * @see com.iver.cit.gvsig.gui.layout.fframes.IFFrame#getXMLEntity()
+	 */
+	public XMLEntity getXMLEntity() {
+		XMLEntity xml = new XMLEntity();
+		xml.putProperty("className",this.getClass().getName());
+		xml.putProperty("m_symbolType", getSymbolType());
+		xml.putProperty("m_Style", getStyle());
+		xml.putProperty("m_useOutline", isOutlined());
+
+		if (getColor() != null) {
+			xml.putProperty("m_Color", StringUtilities.color2String(getColor()));
+		}
+
+		if (getOutlineColor() != null) {
+			xml.putProperty("m_outlineColor",
+				StringUtilities.color2String(getOutlineColor()));
+		}
+
+		if (getFont() != null) {
+			xml.putProperty("fontname", getFont().getName());
+			xml.putProperty("fontstyle", getFont().getStyle());
+
+			xml.putProperty("m_FontSize", getFontSize());
+			xml.putProperty("m_FontColor",
+				StringUtilities.color2String(getFontColor()));
+
+		}
+		xml.putProperty("m_bUseFontSize", isFontSizeInPixels());
+		xml.putProperty("m_bDrawShape", isShapeVisible());
+		xml.putProperty("m_Size", getSize());
+
+		//xml.putProperty("m_Icon",m_Icon.);
+		xml.putProperty("m_Rotation", getRotation());
+
+		if (getFill() instanceof Color) {
+			xml.putProperty("m_Fill",
+				StringUtilities.color2String((Color) getFill()));
+		}
+		else
+			if (getFill() != null)
+			{
+			    xml.putProperty("m_Fill", "WithFill");
+			}
+
+
+		xml.putProperty("m_LinePattern", m_LinePattern);
+
+		//Ancho del stroke en float
+		if (getStroke() != null) {
+			xml.putProperty("m_stroke",
+				((BasicStroke) getStroke()).getLineWidth());
+		} else {
+			xml.putProperty("m_stroke", 0f);
+		}
+
+		xml.putProperty("m_bUseSize", isSizeInPixels());
+		xml.putProperty("m_AlingVert", getAlingVert());
+		xml.putProperty("m_AlingHoriz", getAlingHoriz());
+		xml.putProperty("m_Descrip", getDescription());
+
+		if (m_BackColor != null) {
+			xml.putProperty("m_BackColor",
+				StringUtilities.color2String(m_BackColor));
+		}
+
+		if (m_BackFill instanceof Color) {
+			xml.putProperty("m_BackFill",
+				StringUtilities.color2String((Color) m_BackFill));
+		}
+
+		xml.putProperty("rgb", rgb);
+
+		if (m_Icon != null)
+		{
+		    xml.putProperty("m_IconURI", m_IconURI);
+		}
+
+		return xml;
+	}
+	/**
+	 * Crea el s�mbolo a partir del xml.
+	 *
+	 * @param xml xml que contiene la informaci�n para crear el s�mbolo.
+	 *
+	 * @return S�mbolo creado a partir del XML.
+	 */
+	public static FSymbol createFromXML(XMLEntity xml) {
+		FSymbol symbol = new FSymbol();
+		symbol.setSymbolType(xml.getIntProperty("m_symbolType"));
+		symbol.setStyle(xml.getIntProperty("m_Style"));
+		// System.out.println("createFromXML: m_Style=" + xml.getIntProperty("m_Style"));
+
+		symbol.setOutlined(xml.getBooleanProperty("m_useOutline"));
+
+		if (xml.contains("m_Color")) {
+			symbol.setColor(StringUtilities.string2Color(xml.getStringProperty(
+						"m_Color")));
+		}
+
+		if (xml.contains("m_outlineColor")) {
+			symbol.setOutlineColor(StringUtilities.string2Color(
+					xml.getStringProperty("m_outlineColor")));
+		}
+
+		if (xml.contains("fontname")) {
+			symbol.setFont(new Font(xml.getStringProperty("fontname"),
+					xml.getIntProperty("fontstyle"),
+					(int) xml.getFloatProperty("m_FontSize")));
+
+			symbol.setFontColor(StringUtilities.string2Color(
+					xml.getStringProperty("m_FontColor")));
+			symbol.setFontSize(xml.getFloatProperty("m_FontSize"));
+
+		}
+		symbol.setFontSizeInPixels(xml.getBooleanProperty("m_bUseFontSize"));
+		symbol.setShapeVisible(xml.getBooleanProperty("m_bDrawShape"));
+		symbol.setSize(xml.getIntProperty("m_Size"));
+
+		//xml.putProperty("m_Icon",m_Icon.);
+		symbol.setRotation(xml.getIntProperty("m_Rotation"));
+
+		if (xml.contains("m_Fill")) {
+		    // TODO: Si es un Fill de tipo imagen, deber�amos recuperar la imagen.
+		    String strFill = xml.getStringProperty("m_Fill");
+		    if (strFill.compareTo("WithFill") == 0) {
+				symbol.setFill(FSymbolFactory.createPatternFill(symbol.getStyle(), symbol.getColor()));
+			} else {
+				symbol.setFill(StringUtilities.string2Color(strFill));
+			}
+		}
+
+
+		symbol.m_LinePattern = xml.getStringProperty("m_LinePattern");
+
+		//Ancho del stroke en float
+        float lineWidth = xml.getFloatProperty("m_stroke");
+        if (symbol.m_LinePattern.compareTo("0") == 0)
+        {
+            symbol.setStroke(new BasicStroke(lineWidth));
+        }
+        else
+        {
+            symbol.setStroke(new BasicStroke(lineWidth, BasicStroke.CAP_ROUND,
+                    BasicStroke.JOIN_BEVEL, 1.0f,
+                        toArray(symbol.m_LinePattern, lineWidth), 0));
+        }
+
+		symbol.setSizeInPixels(xml.getBooleanProperty("m_bUseSize"));
+		symbol.setAlingVert(xml.getIntProperty("m_AlingVert"));
+		symbol.setAlingHoriz(xml.getIntProperty("m_AlingHoriz"));
+		symbol.setDescription(xml.getStringProperty("m_Descrip"));
+
+		if (xml.contains("m_BackColor")) {
+			symbol.m_BackColor = StringUtilities.string2Color(xml.getStringProperty(
+						"m_BackColor"));
+		}
+
+		if (xml.contains("m_BackFill")) {
+			symbol.m_BackFill = StringUtilities.string2Color(xml.getStringProperty(
+						"m_BackFill"));
+		}
+
+		symbol.rgb = xml.getIntProperty("rgb");
+
+		if (xml.contains("m_IconURI")) {
+		    try {
+                symbol.setIconURI(new URI(xml.getStringProperty("m_IconURI")));
+            } catch (URISyntaxException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+		}
+
+		return symbol;
+	}
+
+	/**
+	 * Introduce el estilo del s�mbolo.
+	 *
+	 * @param m_Style The m_Style to set.
+	 */
+	public void setStyle(int m_Style) {
+		this.m_Style = m_Style;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el estilo del s�mbolo.
+	 *
+	 * @return Returns the m_Style.
+	 */
+	public int getStyle() {
+		return m_Style;
+	}
+
+	/**
+	 * Introduce el tipo de s�mbolo.
+	 *
+	 * @param m_symbolType The m_symbolType to set.
+	 */
+	public void setSymbolType(int m_symbolType) {
+		this.m_symbolType = m_symbolType;
+	}
+
+	/**
+	 * Devuelve el tipo de s�mbolo.
+	 *
+	 * @return Returns the m_symbolType.
+	 */
+	public int getSymbolType() {
+		return m_symbolType;
+	}
+
+	/**
+	 * Introduce si el s�mbolo contiene linea de brode o no.
+	 *
+	 * @param m_useOutline The m_useOutline to set.
+	 */
+	public void setOutlined(boolean m_useOutline) {
+		this.m_useOutline = m_useOutline;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve si el s�mbolo contiene o no linea de borde.
+	 *
+	 * @return Returns the m_useOutline.
+	 */
+	public boolean isOutlined() {
+		return m_useOutline;
+	}
+
+	/**
+	 * Introduce el color del s�mbolo.
+	 *
+	 * @param m_Color The m_Color to set.
+	 */
+	public void setColor(Color m_Color) {
+		this.m_Color = m_Color;
+		calculateRgb();
+	}
+
+	/**
+	 * Devuelve el color del s�mbolo.
+	 *
+	 * @return Returns the m_Color.
+	 */
+	public Color getColor() {
+		return m_Color;
+	}
+
+	/**
+	 * Introduce el color de la l�nea de borde.
+	 *
+	 * @param m_outlineColor The m_outlineColor to set.
+	 */
+	public void setOutlineColor(Color m_outlineColor) {
+		this.m_outlineColor = m_outlineColor;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el color de la l�nea de borde.
+	 *
+	 * @return Returns the m_outlineColor.
+	 */
+	public Color getOutlineColor() {
+		return m_outlineColor;
+	}
+
+	/**
+	 * Introduce el Font del s�mbolo.
+	 *
+	 * @param m_Font The m_Font to set.
+	 */
+	public void setFont(Font m_Font) {
+		this.m_Font = m_Font;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el Font del s�mbolo.
+	 *
+	 * @return Returns the m_Font.
+	 */
+	public Font getFont() {
+		return m_Font;
+	}
+
+	/**
+	 * Introduce el color de la fuente.
+	 *
+	 * @param m_FontColor The m_FontColor to set.
+	 */
+	public void setFontColor(Color m_FontColor) {
+		this.m_FontColor = m_FontColor;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el color de la fuente.
+	 *
+	 * @return Returns the m_FontColor.
+	 */
+	public Color getFontColor() {
+		return m_FontColor;
+	}
+
+	/**
+	 * Introduce si se usa el tama�o de la fuente en pixels.
+	 *
+	 * @param m_bUseFontSize The m_bUseFontSize to set.
+	 */
+	public void setFontSizeInPixels(boolean m_bUseFontSize) {
+		this.m_bUseFontSizeInPixels = m_bUseFontSize;
+
+		// calculateRgb();
+	}
+
+	/**
+	 * Devuelve true si el tama�o de la fuente esta seleccionado en pixels.
+	 *
+	 * @return Returns the m_bUseFontSize.
+	 */
+	public boolean isFontSizeInPixels() {
+		return m_bUseFontSizeInPixels;
+	}
+
+	/**
+	 * Introduce si el shape e visible o no lo es.
+	 *
+	 * @param m_bDrawShape The m_bDrawShape to set.
+	 */
+	public void setShapeVisible(boolean m_bDrawShape) {
+		this.m_bDrawShape = m_bDrawShape;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve true si el shape es visible.
+	 *
+	 * @return Returns the m_bDrawShape.
+	 */
+	public boolean isShapeVisible() {
+		return m_bDrawShape;
+	}
+
+	/**
+	 * Introduce el tama�o del s�mbolo.
+	 *
+	 * @param m_Size The m_Size to set.
+	 */
+	public void setSize(int m_Size) {
+		this.m_Size = m_Size;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el tama�o del s�mbolo.
+	 *
+	 * @return Returns the m_Size.
+	 */
+	public int getSize() {
+		return m_Size;
+	}
+
+	/**
+	 * Introduce la imagen que hace de icono.
+	 *
+	 * @param m_Icon The m_Icon to set.
+	 */
+	public void setIcon(Image m_Icon) {
+		this.m_Icon = m_Icon;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el icono.
+	 *
+	 * @return Returns the m_Icon.
+	 */
+	public Image getIcon() {
+		return m_Icon;
+	}
+
+	/**
+	 * Introduce la rotaci�n.
+	 *
+	 * @param m_Rotation The m_Rotation to set.
+	 */
+	public void setRotation(int m_Rotation) {
+		this.m_Rotation = m_Rotation;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve la rotaci�n.
+	 *
+	 * @return Returns the m_Rotation.
+	 */
+	public int getRotation() {
+		return m_Rotation;
+	}
+
+	/**
+	 * Introduce el relleno.
+	 *
+	 * @param m_Fill The m_Fill to set.
+	 */
+	public void setFill(Paint m_Fill) {
+		this.m_Fill = m_Fill;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el relleno.
+	 *
+	 * @return Returns the m_Fill.
+	 */
+	public Paint getFill() {
+		return m_Fill;
+	}
+
+	/**
+	 * Introduce el Stroke.
+	 *
+	 * @param m_Stroke The m_Stroke to set.
+	 */
+	public void setStroke(Stroke m_Stroke) {
+		this.m_Stroke = m_Stroke;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve el Stroke.
+	 *
+	 * @return Returns the m_Stroke.
+	 */
+	public Stroke getStroke() {
+		return m_Stroke;
+	}
+
+	/**
+	 * Introduce si el tama�o del simbolo est� en pixels.
+	 *
+	 * @param m_bUseSize The m_bUseSize to set.
+	 */
+	public void setSizeInPixels(boolean m_bUseSize) {
+		this.m_bUseSize = m_bUseSize;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve si el tama�o del s�mbolo est� en pixels.
+	 *
+	 * @return Returns the m_bUseSize.
+	 */
+	public boolean isSizeInPixels() {
+		return m_bUseSize;
+	}
+
+	/**
+	 * Introduce la descripci�n del s�mbolo.
+	 *
+	 * @param m_Descrip The m_Descrip to set.
+	 */
+	public void setDescription(String m_Descrip) {
+		this.m_Descrip = m_Descrip;
+	}
+
+	/**
+	 * Devuelve la descripci�n del s�mbolo.
+	 *
+	 * @return Returns the m_Descrip.
+	 */
+	public String getDescription() {
+		return m_Descrip != null ? m_Descrip : "Default";
+	}
+
+	/**
+	 * Introduce la alineaci�n en vertical.
+	 *
+	 * @param m_AlingVert The m_AlingVert to set.
+	 */
+	public void setAlingVert(int m_AlingVert) {
+		this.m_AlingVert = m_AlingVert;
+
+		//		 calculateRgb();
+	}
+
+	/**
+	 * Devuelve la alineaci�n en vertical.
+	 *
+	 * @return Returns the m_AlingVert.
+	 */
+	public int getAlingVert() {
+		return m_AlingVert;
+	}
+
+	/**
+	 * Introduce la alineaci�n en horizontal.
+	 *
+	 * @param m_AlingHoriz The m_AlingHoriz to set.
+	 */
+	public void setAlingHoriz(int m_AlingHoriz) {
+		this.m_AlingHoriz = m_AlingHoriz;
+
+		// calculateRgb();
+	}
+
+	/**
+	 * Devuelve la alineaci�n en horizontal.
+	 *
+	 * @return Returns the m_AlingHoriz.
+	 */
+	public int getAlingHoriz() {
+		return m_AlingHoriz;
+	}
+
+
+	/**
+	 * Introduce el tama�o de la fuente.
+	 *
+	 * @param m_FontSize The m_FontSize to set.
+	 */
+	public void setFontSize(float m_FontSize) {
+		this.m_FontSize = m_FontSize;
+	}
+
+	/**
+	 * Devuelve el tama�o de la fuente.
+	 *
+	 * @return Returns the m_FontSize.
+	 */
+	public float getFontSize() {
+		return m_FontSize;
+	}
+    public URI getIconURI() {
+        return m_IconURI;
+    }
+    public void setIconURI(URI iconURI) {
+        m_IconURI = iconURI;
+        ImageIcon prov;
+        try {
+            prov = new ImageIcon(iconURI.toURL());
+            m_Icon = prov.getImage();
+        } catch (MalformedURLException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+    }
+   	/**
+	 * @return Returns the imgObserver.
+	 */
+	public ImageObserver getImgObserver() {
+		return imgObserver;
+	}
+
+	/**
+	 * @param imgObserver The imgObserver to set.
+	 */
+	public void setImgObserver(ImageObserver imgObserver) {
+		this.imgObserver = imgObserver;
+	}
+
+	public ISymbol getSymbolForSelection() {
+		return getSymbolForSelection(this);
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		FGraphicUtilities.DrawShape(g, affineTransform, geom, this);
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
+		// Nothing to do
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return true;
+	}
+
+	public void drawInsideRectangle(Graphics2D g2, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		try {
+			FGraphicUtilities.DrawSymbol(g2, scaleInstance, r, this);
+		} catch (CreateGeometryException e) {
+			
+			throw new SymbolDrawingException(getSymbolType());
+		}
+	}
+
+	public String getClassName() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void setXMLEntity(XMLEntity xml) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void print(Graphics2D g, AffineTransform at, Geometry shape, PrintAttributes properties){
+		int strokeValue=0;
+		BasicStroke stroke=(BasicStroke)this.getStroke();
+		if (stroke != null && stroke.getLineWidth()!=0) {
+			strokeValue=(int)stroke.getLineWidth();
+			double d = strokeValue;
+			
+			int pq = properties.getPrintQuality();
+			if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
+				d *= (double) 300/72;
+			}else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
+				d *= (double) 600/72;
+			}else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
+				// d *= 72/72; // (which is the same than doing nothing)
+			}
+			this.setStroke(new BasicStroke((int)d,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
+		}
+		draw(g, at, shape, null, null);
+		this.setStroke(new BasicStroke(strokeValue));
+	}
+	
+	public boolean isOneDotOrPixel(Geometry geom,
+			double[] positionOfDotOrPixel, ViewPort viewPort, int dpi) {
+		int type = geom.getType();
+		switch (type) {
+		case Geometry.TYPES.NULL:
+		case Geometry.TYPES.POINT:
+		case Geometry.TYPES.MULTIPOINT:
+			return false;
+		default:
+			org.gvsig.fmap.geom.primitive.Envelope geomBounds = geom
+			.getEnvelope();
+
+			double dist1Pixel = viewPort.getDist1pixel();
+
+			float[] distances = new float[2];
+			this.getPixExtentPlus(geom, distances, viewPort, dpi);
+
+			boolean onePoint =
+					(geomBounds.getLength(0) + distances[0] <= dist1Pixel && geomBounds
+					.getLength(1)
+					+ distances[1] <= dist1Pixel);
+
+			if (onePoint) {
+				Rectangle bounds = geom.getBounds();
+				positionOfDotOrPixel[0] = bounds.x;
+				positionOfDotOrPixel[1] = bounds.y;
+			}
+			return onePoint;
+		}
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		// TODO Auto-generated method stub
+		return super.clone();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#loadFromState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#saveToState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// TODO Auto-generated method stub
+		
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FConstant.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FConstant.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FConstant.java	(revision 33580)
@@ -0,0 +1,140 @@
+/*
+ * Created on 02-mar-2004
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+
+/**
+  * Clase utilizada para almacenar las variables est�ticas.
+ *
+ * @author Vicente Caballero Navarro
+ * @deprecated
+ */
+public class FConstant {
+	/** Nombre de las unidades de medida, utilizadas. */
+//	public static String[] NAMES = null;
+	public final static int SHAPE_TYPE_NULL = 0;
+	public final static int SHAPE_TYPE_POINT = 1;
+	public final static int SHAPE_TYPE_POLYLINE = 3;
+	public final static int SHAPE_TYPE_POLYGON = 5;
+	public final static int SHAPE_TYPE_MULTIPOINT = 8;
+	public final static int SHAPE_TYPE_POINTZ = 11;
+	public final static int SHAPE_TYPE_POLYLINEZ = 13;
+	public final static int SHAPE_TYPE_POLYGONZ = 15;
+	public final static int SHAPE_TYPE_MULTIPOINTZ = 18;
+	public final static int SHAPE_TYPE_POINTM = 21;
+	public final static int SHAPE_TYPE_POLYLINEM = 23;
+	public final static int SHAPE_TYPE_POLYGONM = 25;
+	public final static int SHAPE_TYPE_MULTIPOINTM = 28;
+	public final static int LAYER_TYPE_DGN = 1;
+	public final static int LAYER_TYPE_DWG = 2;
+	public final static int LAYER_TYPE_DXF = 3;
+	public final static int LAYER_TYPE_JPEG2000 = 4;
+	public final static int LAYER_TYPE_SHP = 5;
+	public final static int LAYER_TYPE_WMS = 6;
+	public final static int LEGEND_TYPE_BREAK = 3;
+	public final static int LEGEND_TYPE_DEFAULT = 1;
+	public final static int LEGEND_TYPE_VALUE = 2;
+	public final static int SYMBOL_TYPE_DEFAULT = 5;
+	public final static int SYMBOL_TYPE_POINT = 1;
+	public final static int SYMBOL_TYPE_LINE = 2;
+	public final static int SYMBOL_TYPE_FILL = 4;
+	public final static int SYMBOL_TYPE_TEXT = 7;
+	public final static int SYMBOL_TYPE_ICON = 9;
+	public final static int SYMBOL_TYPE_POINTZ = 11;
+	public final static int SYMBOL_TYPE_MULTIPOINT = 8;
+	public final static int SYMBOL_STYLE_POINTZ = 0;
+	public final static int SYMBOL_TYPE_POLYLINEZ = 13;
+	public final static int SYMBOL_TYPE_POLYGONZ = 15;
+
+
+
+
+	/**
+	 * If you want to obtain a 12-pixel height font you have to apply this
+	 * scale factor. <br>
+	 * So, it would be: <br>
+	 * 	<b> font.setSize(FONT_SCALE_FACTOR*size)</b>
+	 */
+//	public static final double FONT_HEIGHT_SCALE_FACTOR = 1.4;
+	/*
+	 * Esto parece un error, tal vez se pens� s�lo en el tama�o de las
+	 * may�sculas, sin tener en cuenta que alguna letras (j, g, q) tienen
+	 * descendente y que si medimos un texto en vertical desde la parte
+	 * superior de una may�scula a la parte inferior de una min�scula con
+	 * descendente no es necesario aplicar este factor de correcci�n.
+	 */
+
+
+
+	public static final double DEGREE_TO_RADIANS = Math.PI/180D;
+
+
+	static {
+		new FConstant();
+	}
+
+	/**
+	 * 050211, jmorell: Se han a�adido los Grados.
+	 * Crea un nuevo FConstant.
+	 */
+//	public FConstant() {
+//		if (NAMES == null) {
+//			int i = 0;
+//			NAMES = new String[10];
+//			NAMES[i++] = "Kilometros";
+//			NAMES[i++] = "Metros";
+//			NAMES[i++] = "Centimetros";
+//			NAMES[i++] = "Milimetros";
+//			NAMES[i++] = "Millas";
+//			NAMES[i++] = "Yardas";
+//			NAMES[i++] = "Pies";
+//			NAMES[i++] = "Pulgadas";
+//			NAMES[i++] = "Grados";
+//			NAMES[i++] = "Coordenadas";
+//		}
+//	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FGraphicUtilities.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FGraphicUtilities.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FGraphicUtilities.java	(revision 33580)
@@ -0,0 +1,889 @@
+/*
+ * Created on 28-abr-2004
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import org.apache.batik.ext.awt.geom.PathLength;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.handler.Handler;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.geom.util.Converter;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.vividsolutions.jts.geom.Point;
+
+/**
+ * Clase con m�todos est�ticos para dibujar sobre el Graphics que se les pase
+ * como par�metro.
+ *
+ * Esta clase deber�a ser privada. Las clases que la usan son GraphicLayer
+ * y AnnotationStrategy, pero hay que revisarlas para que no sea necesario.
+ * Lo m�s urgente ser�a lo del dibujado de textos, para que sea
+ * Hay que quitar las dependecias de FSymbol, y trabajar SIEMPRE con ISymbol.
+ * Recordar: Que sea ISymbol el que renderiza.
+ * extensible el s�mbolo a usar. NOTA: Ver tambi�n comentario en ISymbol
+ *
+ * @author fjp
+ * @deprecated
+ */
+public class FGraphicUtilities {
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final Logger logger = LoggerFactory.getLogger(FGraphicUtilities.class);
+
+	/**
+	 * Dibuja el s�mbolo que se le pasa como par�metro en el Graphics.
+	 *
+	 * @param g2 Graphics2D sobre el que dibujar.
+	 * @param mT2 Matriz de transformaci�n.
+	 * @param r Rect�ngulo.
+	 * @param symbol S�mbolo a dibujar.
+	 * @throws CreateGeometryException 
+	 */
+	public static void DrawSymbol(Graphics2D g2, AffineTransform mT2,
+		Rectangle r, FSymbol symbol) throws CreateGeometryException {
+		Geometry geom;
+
+		AffineTransform mT = new AffineTransform();
+		mT.setToIdentity();
+
+		Rectangle r2 = new Rectangle(r.x + 2 + (r.width / 3), r.y, r.width / 3,
+				r.height);
+		Rectangle r3 = new Rectangle(r.x + 2 + ((2 * r.width) / 3), r.y,
+				r.width / 3, r.height);
+
+		// g2.clearRect(r.x, r.y, r.width, r.height);
+		// System.out.println("r = " + r.toString() + " Color preview:" + symbol.m_Color.toString());
+		// System.out.println("symbol.m_symbolType= "+symbol.m_symbolType);
+		switch (symbol.getSymbolType()) {
+			case Geometry.TYPES.POINT:
+				geom = geomManager.createPoint(r.x + (r.width / 2), r.y + (r.height / 2), SUBTYPES.GEOM2D);
+
+				//  Para no tener que clonarlo si viene en unidades de mapa
+				boolean bAux2 = symbol.isSizeInPixels();
+				int alturaMetros = symbol.getSize(); // Nota: Cambiar m_Size a float
+
+				if (!bAux2) {
+					symbol.setSizeInPixels(true);
+					symbol.setSize(8); // tama�o fijo
+				}
+
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+
+				if (!bAux2) {
+					symbol.setSize(alturaMetros);
+					symbol.setSizeInPixels(bAux2);
+				}
+
+				if (symbol.getFont() != null) {
+					// Para no tener que clonarlo si viene en unidades de mapa
+					boolean bAux = symbol.isFontSizeInPixels();
+					symbol.setFontSizeInPixels(true);
+					FGraphicUtilities.DrawLabel(g2, mT, geom, symbol,
+						new FLabel("Abcd"));
+					symbol.setFontSizeInPixels(bAux);
+				}
+
+				break;
+
+			case Geometry.TYPES.CURVE:
+
+				Rectangle rect = mT2.createTransformedShape(r).getBounds();
+				GeneralPathX line = new GeneralPathX();
+				line.moveTo(rect.x, rect.y + (rect.height / 2));
+
+				// line.lineTo(rect.x + rect.width/3, rect.y + rect.height);
+				// line.lineTo(rect.x + 2*rect.width/3, rect.y);
+				// line.lineTo(rect.x + rect.width, rect.y + rect.height/2);
+				line.curveTo(rect.x + (rect.width / 3),
+					rect.y + (2 * rect.height),
+					rect.x + ((2 * rect.width) / 3), rect.y - rect.height,
+					rect.x + rect.width, rect.y + (rect.height / 2));
+
+				geom = geomManager.createSurface(line, SUBTYPES.GEOM2D);
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+				break;
+
+			case Geometry.TYPES.SURFACE:
+
+				GeneralPathX rectAux = new GeneralPathX(r.getPathIterator(null));
+				rectAux.transform(mT2);
+				geom = geomManager.createSurface(rectAux, SUBTYPES.GEOM2D);
+
+				// System.out.println("rect = "+rectAux.getBounds());
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+				break;
+
+			case Geometry.TYPES.GEOMETRY:
+
+				// Pol�gono
+				r.setSize(r.width / 3, r.height);
+
+				GeneralPathX rectAux2 = new GeneralPathX(r.getPathIterator(null));
+				rectAux2.transform(mT2);
+				geom = geomManager.createSurface(rectAux2, SUBTYPES.GEOM2D);
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+				// L�nea
+				rect = mT2.createTransformedShape(r2).getBounds();
+				line = new GeneralPathX();
+				line.moveTo(rect.x, rect.y + (rect.height / 2));
+
+				line.curveTo(rect.x + (rect.width / 3),
+					rect.y + (2 * rect.height),
+					rect.x + ((2 * rect.width) / 3), rect.y - rect.height,
+					rect.x + rect.width, rect.y + (rect.height / 2));
+
+				geom = geomManager.createCurve(line, SUBTYPES.GEOM2D);
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+				// Punto:
+				geom = geomManager.createPoint(r3.x + (r3.width / 2), r3.y +
+						(r3.height / 2), SUBTYPES.GEOM2D);
+
+				//  Para no tener que clonarlo si viene en unidades de mapa
+				bAux2 = symbol.isSizeInPixels();
+				alturaMetros = symbol.getSize(); // Nota: Cambiar m_Size a float
+
+				if (!bAux2) {
+					symbol.setSizeInPixels(true);
+					symbol.setSize(4); // tama�o fijo
+				}
+				symbol.draw(g2, mT, geom, null, null);
+				// FGraphicUtilities.DrawShape(g2, mT, shp, symbol);
+
+				if (!bAux2) {
+					symbol.setSize(alturaMetros);
+					symbol.setSizeInPixels(bAux2);
+				}
+
+				if (symbol.getFont() != null) {
+					// Para no tener que clonarlo si viene en unidades de mapa
+					boolean bAux = symbol.isFontSizeInPixels();
+					symbol.setFontSizeInPixels(true);
+					FGraphicUtilities.DrawLabel(g2, mT, geom, symbol,
+						new FLabel("Abcd"));
+					symbol.setFontSizeInPixels(bAux);
+				}
+
+				break;
+			case Geometry.TYPES.TEXT:
+				geom = geomManager.createPoint(r3.x + (r3.width / 2), r3.y +
+						(r3.height / 2), SUBTYPES.GEOM2D);
+				boolean bAux = symbol.isFontSizeInPixels();
+				symbol.setFontSizeInPixels(true);
+				FGraphicUtilities.DrawLabel(g2, mT, geom, symbol,
+					new FLabel("Abcd"));
+				symbol.setFontSizeInPixels(bAux);
+				break;
+		}
+	}
+
+	/**
+	 * Dibuja el shape que se pasa como par�metro con las caracter�sticas que
+	 * aporta el s�mbolo sobre el Graphics2D.
+	 *
+	 * @param g2 Graphics2D sobre el que dibujar.
+	 * @param mT Matriz de transformaci�n.
+	 * @param shp FShape a dibujar.
+	 * @param theSymbol S�mbolo.
+	 * @deprecated
+	 */
+	public static void DrawShape(Graphics2D g2, AffineTransform mT, Geometry geom,
+		FSymbol theSymbol) {
+		// Hacemos la transformaci�n del shape aqu� dentro... por ahora.
+		if (geom == null || theSymbol == null || (!theSymbol.isShapeVisible())) {
+			return;
+		}
+        g2.setColor(theSymbol.getColor());
+
+		/* if (shp instanceof FPolygon2D)
+		   {
+		           System.out.println("Entra pol�gono");
+		   } */
+		int type=geom.getType();
+		/* if (shp.getShapeType()>=FShape.Z){
+			type=shp.getShapeType()-FShape.Z;
+		} */
+		switch (type) {
+			case Geometry.TYPES.POINT: //Tipo punto            
+				drawSymbolPoint(g2, mT, (org.gvsig.fmap.geom.primitive.Point) geom, theSymbol);
+
+				break;
+
+			case Geometry.TYPES.CURVE:           
+			case Geometry.TYPES.ARC:			
+				// Shape theShp = mT.createTransformedShape(shp.m_Polyline);
+				// g2.setColor(theSymbol.m_Color);
+				if (theSymbol.getStroke() != null) {
+					g2.setStroke(theSymbol.getStroke());
+				}
+
+				g2.draw(geom);
+
+				break;
+
+			case Geometry.TYPES.SURFACE:
+       		case Geometry.TYPES.ELLIPSE:
+		    case Geometry.TYPES.CIRCLE:
+		
+			    if (theSymbol.getFill() != null)
+			        g2.setPaint(theSymbol.getFill());
+
+			    if (theSymbol.getColor() != null)
+				    if (theSymbol.getStyle() != FSymbol.SYMBOL_STYLE_DGNSPECIAL) {
+				        g2.fill(geom);
+				}
+
+				if (theSymbol.isOutlined()) {
+					g2.setColor(theSymbol.getOutlineColor());
+
+					if (theSymbol.getStroke() != null) {
+						g2.setStroke(theSymbol.getStroke());
+					}
+
+					g2.draw(geom);
+				}
+
+				break;
+
+		}
+	}
+//	public static double toMapDistance(AffineTransform at,int d) {
+//		double dist = d / at.getScaleX();
+//
+//		return dist;
+//	}
+//	public static int fromMapDistance(AffineTransform at,double d) {
+//		Point2D.Double pWorld = new Point2D.Double(1, 1);
+//		Point2D.Double pScreen = new Point2D.Double();
+//
+//		try {
+//			at.deltaTransform(pWorld, pScreen);
+//		} catch (Exception e) {
+//			System.err.print(e.getMessage());
+//		}
+//
+//		return (int) (d * pScreen.x);
+//	}
+	/**
+	 * Dibuja el FLabel que se pasa como par�metro sobre el Graphics2D.
+	 *
+	 * @param g2 Graphics2D sobre el que dibujar.
+	 * @param mT Matriz de transformaci�n.
+	 * @param shp FShape a dibujar.
+	 * @param theSymbol S�mbolo para aplicar.
+	 * @param theLabel FLabel que contiene el texto que se debe dibujar.
+	 */
+	public static void DrawLabel(Graphics2D g2, AffineTransform mT, Geometry geom,
+		FSymbol theSymbol, FLabel theLabel) {
+		float angle;
+		float x;
+		float y;
+		Point2D pAux = null;
+
+		// USAR TEXTLAYOUT SI QUEREMOS PERMITIR SELECCIONAR UN TEXTO
+		// Y/O EDITARLO "IN SITU"
+
+		/* if (m_labelValues[numReg].length() > 0)
+		   {
+		           TextLayout layout = new TextLayout(m_labelValues[numReg], font, frc);
+		           layout.draw(g2, x, y);
+		   } */
+		if (geom == null) {
+			return;
+		}
+
+		// Las etiquetas que pongamos a nulo ser� porque no la queremos dibujar.
+		// �til para cuando queramos eliminar duplicados.
+		if (theLabel.getString() == null) {
+			return;
+		}
+
+		FontMetrics metrics;// = g2.getFontMetrics();
+		int width;// = metrics.stringWidth(theLabel.getString());
+		int height;// = metrics.getMaxAscent();
+
+		// int height = metrics.getHeight();
+		//g2.setFont(theSymbol.getFont());
+		//g2.setColor(theSymbol.getFontColor());
+
+		// Aqu� hay que mirar m_Size y m_useSize...
+		if (!theSymbol.isFontSizeInPixels()) {
+			// Suponemos que m_Size viene en coordenadas de mundo real
+			// Esto habr� que cambiarlo. Probablemente usar Style2d de geotools en lugar
+			// de FSymbol.
+			// CAMBIO: La altura del texto la miramos en FLabel
+			// float alturaPixels = (float) (theSymbol.m_FontSize * mT.getScaleX());
+			float alturaPixels = (float) (theLabel.getHeight() * mT.getScaleX());
+
+			/* System.out.println("m_bUseSize = " + theSymbol.m_bUseSize +
+			   " Escala: " + mT.getScaleX() + " alturaPixels = " + alturaPixels); */
+			if (alturaPixels < 3) {
+				return; // No leemos nada
+			}
+
+			Font nuevaFuente = theSymbol.getFont().deriveFont(theSymbol.getFont().getStyle(),alturaPixels);
+			g2.setFont(nuevaFuente);
+			g2.setColor(theSymbol.getFontColor());
+			metrics=g2.getFontMetrics();
+			height= metrics.getMaxAscent();
+			width = metrics.stringWidth(theLabel.getString());
+		}else {
+			metrics = g2.getFontMetrics();
+			width = metrics.stringWidth(theLabel.getString());
+			height = metrics.getMaxAscent();
+			g2.setFont(theSymbol.getFont());
+			g2.setColor(theSymbol.getFontColor());
+		}
+		int type=geom.getType();
+		switch (type) {
+			case Geometry.TYPES.POINT: //Tipo punto
+				pAux = new Point2D.Double(((org.gvsig.fmap.geom.primitive.Point) geom).getX(),
+						((org.gvsig.fmap.geom.primitive.Point) geom).getY());
+				pAux = mT.transform(pAux, null);
+
+				break;
+
+			case Geometry.TYPES.CURVE:
+
+				//
+				if (theLabel.getOrig() == null) // Calculamos el punto y la orientaci�n solo la primera vez
+				 {
+					PathLength pathLen = new PathLength(geom);
+
+					// if (pathLen.lengthOfPath() < width / mT.getScaleX()) return;
+					float midDistance = pathLen.lengthOfPath() / 2;
+					pAux = pathLen.pointAtLength(midDistance);
+					angle = pathLen.angleAtLength(midDistance);
+
+					if (angle < 0) {
+						angle = angle + (float) (2 * Math.PI);
+					}
+
+					if ((angle > (Math.PI / 2)) &&
+							(angle < ((3 * Math.PI) / 2))) {
+						angle = angle - (float) Math.PI;
+					}
+
+					theLabel.setRotation(Math.toDegrees(angle));
+					theLabel.setOrig(pAux);
+				}
+
+				pAux = mT.transform(theLabel.getOrig(), null);
+
+				// pAux = theLabel.getOrig();
+				// GlyphVector theGlyphs = theSymbol.m_Font.createGlyphVector(g2.getFontRenderContext(), theLabel);
+				// Shape txtShp = TextPathLayout.layoutGlyphVector(theGlyphs, shp.m_Polyline,TextPathLayout.ALIGN_MIDDLE);
+				// g2.draw(txtShp);
+				// System.out.println("Pintando etiqueta " + theLabel );
+				break;
+
+			case Geometry.TYPES.SURFACE:
+
+				if (theLabel.getOrig() == null) // Calculamos el punto solo la primera vez
+				 {
+					com.vividsolutions.jts.geom.Geometry geo = Converter.geometryToJts(geom);
+
+					// System.out.println("Area de " + m_labelValues[numReg] + " = "
+					//   + geo.getArea());
+					//   System.out.println(geo.toText());
+					Point pJTS = geo.getInteriorPoint();
+					Geometry pLabel;
+					try {
+						pLabel = (Geometry)Converter.jtsToGeometry(pJTS);
+						theLabel.setRotation(0);
+						theLabel.setOrig(new Point2D.Double(
+								((org.gvsig.fmap.geom.primitive.Point) pLabel).getX(),
+								((org.gvsig.fmap.geom.primitive.Point) pLabel).getX()));
+					} catch (CreateGeometryException e) {
+						logger.error("Impossible to create the label", e);
+					}				
+				}
+
+				pAux = mT.transform(theLabel.getOrig(), null);
+
+				break;
+		}
+
+		AffineTransform ant = g2.getTransform();
+
+		x = (float) pAux.getX();
+		y = (float) pAux.getY();
+
+		AffineTransform Tx = (AffineTransform) ant.clone();
+		Tx.translate(x, y); // S3: final translation
+		Tx.rotate(theLabel.getRotation()); // S2: rotate around anchor
+		g2.setTransform(Tx);
+
+		switch (theLabel.getJustification()) {
+			case FLabel.LEFT_BOTTOM:
+				g2.drawString(theLabel.getString(), 0, 0 - 3);
+
+				break;
+
+			case FLabel.LEFT_CENTER:
+				g2.drawString(theLabel.getString(), 0, 0 - (height / 2));
+
+				break;
+
+			case FLabel.LEFT_TOP:
+				g2.drawString(theLabel.getString(), 0, 0 - height);
+
+				break;
+
+			case FLabel.CENTER_BOTTOM:
+				g2.drawString(theLabel.getString(), 0 - (width / 2), 0 - 3);
+
+				break;
+
+			case FLabel.CENTER_CENTER:
+				g2.drawString(theLabel.getString(), 0 - (width / 2),
+					0 - (height / 2));
+
+				break;
+
+			case FLabel.CENTER_TOP:
+				g2.drawString(theLabel.getString(), 0 - (width / 2), 0 -
+					height);
+
+				break;
+
+			case FLabel.RIGHT_BOTTOM:
+				g2.drawString(theLabel.getString(), 0 - width, 0 - 3);
+
+				break;
+
+			case FLabel.RIGHT_CENTER:
+				g2.drawString(theLabel.getString(), 0 - width, 0 -
+					(height / 2));
+
+				break;
+
+			case FLabel.RIGHT_TOP:
+				g2.drawString(theLabel.getString(), 0 - width, 0 - height);
+
+				break;
+		}
+
+		// Restauramos
+		g2.setTransform(ant);
+	}
+	/**
+	 * Dibuja el FLabel que se pasa como par�metro sobre el Graphics2D.
+	 *
+	 * @param g2 Graphics2D sobre el que dibujar.
+	 * @param mT Matriz de transformaci�n.
+	 * @param shp FShape a dibujar.
+	 * @param theSymbol S�mbolo para aplicar.
+	 * @param theLabel FLabel que contiene el texto que se debe dibujar.
+	 */
+	public static void DrawAnnotation(Graphics2D g2, AffineTransform at,
+		FSymbol theSymbol, FLabel theLabel,FontMetrics metrics,boolean isSelected) {
+		float x;
+		float y;
+		Point2D pAux = null;
+		// Las etiquetas que pongamos a nulo ser� porque no la queremos dibujar.
+		// �til para cuando queramos eliminar duplicados.
+		if (theLabel.getString() == null) {
+			return;
+		}
+
+//		 Aqu� hay que mirar m_Size y m_useSize...
+		if (!theSymbol.isFontSizeInPixels()) {
+			// Suponemos que m_Size viene en coordenadas de mundo real
+			// Esto habr� que cambiarlo. Probablemente usar Style2d de geotools en lugar
+			// de FSymbol.
+			// CAMBIO: La altura del texto la miramos en FLabel
+			// float alturaPixels = (float) (theSymbol.m_FontSize * mT.getScaleX());
+			float alturaPixels = (float) (theLabel.getHeight() * at.getScaleX()*FLabel.SQUARE);
+			if (alturaPixels < 3) {
+				return; // No leemos nada
+			}
+			Font nuevaFuente = theSymbol.getFont().deriveFont(theSymbol.getFont().getStyle(),alturaPixels);
+			g2.setFont(nuevaFuente);
+		}
+
+
+		if (isSelected){
+			g2.setColor(MapContext.getSelectionColor());
+		}else{
+			g2.setColor(theSymbol.getFontColor());
+		}
+		pAux = at.transform(theLabel.getOrig(), null);
+		AffineTransform ant = g2.getTransform();
+
+		x = (float) pAux.getX();
+		y = (float) pAux.getY();
+
+		AffineTransform Tx = (AffineTransform) ant.clone();
+		Tx.translate(x, y); // S3: final translation
+		Tx.rotate(theLabel.getRotation()); // S2: rotate around anchor
+		g2.setTransform(Tx);
+
+
+		String s=theLabel.getString();
+
+
+		//switch (theLabel.getJustification()) {
+
+		 //case FLabel.LEFT_BOTTOM:
+				g2.drawString(s, 0, 0 - 3);
+/*
+				break;
+
+			case FLabel.LEFT_CENTER:
+				float height = metrics.getMaxAscent();
+				g2.drawString(s, 0, 0 - (height / 2));
+
+				break;
+
+			case FLabel.LEFT_TOP:
+				height = metrics.getMaxAscent();
+				g2.drawString(s, 0, 0 - height);
+
+				break;
+
+			case FLabel.CENTER_BOTTOM:
+				float width = metrics.stringWidth(s);
+				g2.drawString(s, 0 - (width / 2), 0 - 3);
+
+				break;
+
+			case FLabel.CENTER_CENTER:
+				height = metrics.getMaxAscent();
+				width = metrics.stringWidth(s);
+				g2.drawString(s, 0 - (width / 2),
+					0 - (height / 2));
+
+				break;
+
+			case FLabel.CENTER_TOP:
+				width = metrics.stringWidth(s);
+				height = metrics.getMaxAscent();
+				g2.drawString(s, 0 - (width / 2), 0 -
+					height);
+
+				break;
+
+			case FLabel.RIGHT_BOTTOM:
+				width = metrics.stringWidth(s);
+				g2.drawString(s, 0 - width, 0 - 3);
+
+				break;
+
+			case FLabel.RIGHT_CENTER:
+				width = metrics.stringWidth(s);
+				height = metrics.getMaxAscent();
+				g2.drawString(s, 0 - width, 0 -
+					(height / 2));
+
+				break;
+
+			case FLabel.RIGHT_TOP:
+				width = metrics.stringWidth(s);
+				height = metrics.getMaxAscent();
+				g2.drawString(s, 0 - width, 0 - height);
+
+				break;
+		}
+		*/
+		///Rectangle2D borde=vp.fromMapRectangle(theLabel.getBoundBox());//theLabel.getBoundingBox();
+		///g2.setColor(Color.blue);
+		///g2.drawRect((int)borde.getX(),(int)borde.getY(),(int)borde.getWidth(),(int)borde.getHeight());
+		// Restauramos
+		g2.setTransform(ant);
+	}
+
+	/**
+	 * Dibuja un punto sobre el Graphics2D que se pasa como par�metro.
+	 *
+	 * @param g2 Graphics2D sobre el que dibujar.
+	 * @param mT MAtriz de transformaci�n.
+	 * @param pAux punto a dibujar.
+	 * @param theSymbol S�mbolo a aplicar.
+	 */
+	private static void drawSymbolPoint(Graphics2D g2, AffineTransform mT,
+		org.gvsig.fmap.geom.primitive.Point pAux, FSymbol theSymbol) {
+		int x;
+		int y;
+		x = (int) pAux.getX();
+		y = (int) pAux.getY();
+
+		/*if (x==0){
+		   x=100;
+		   }
+		   if (y==0){
+		           y=100;
+		   }
+		 */
+		Rectangle rectAux = new Rectangle();
+
+		// Aqu� hay que mirar m_Size y m_useSize...
+		float radio_simbolo;
+		radio_simbolo = theSymbol.getSize() / 2;
+		// theSymbol.setSizeInPixels(true);
+
+		if (!theSymbol.isSizeInPixels()) {
+			// Suponemos que m_Size viene en coordenadas de mundo real
+			radio_simbolo = (float) (theSymbol.getSize() * mT.getScaleX());
+
+			/* System.out.println("m_bUseSize = " + theSymbol.m_bUseSize +
+			   " Escala: " + mT.getScaleX() + " alturaPixels = " + alturaPixels); */
+			// if (radio_simbolo < 1) return; // No dibujamos nada
+			rectAux.setRect(x - radio_simbolo, y - radio_simbolo,
+				radio_simbolo * 2, radio_simbolo * 2);
+		} else {
+			// m_Size viene en pixels
+			rectAux.setRect(x - radio_simbolo, y - radio_simbolo,
+				theSymbol.getSize(), theSymbol.getSize());
+		}
+
+		// 	continue; //radioSimbolo_en_pixels = 3;
+		if (theSymbol.getFill() != null) {
+			g2.setPaint(theSymbol.getFill());
+		}
+
+		if (theSymbol.getStroke() != null) {
+			g2.setStroke(theSymbol.getStroke());
+		}
+
+		if (radio_simbolo < 2) {
+			g2.fillRect(rectAux.x, rectAux.y, rectAux.width, rectAux.height);
+
+			return;
+		}
+
+		switch (theSymbol.getStyle()) {
+			case FSymbol.SYMBOL_STYLE_MARKER_CIRCLE: // Circulito
+
+				if (theSymbol.getColor() != null) {
+					g2.fillOval(rectAux.x, rectAux.y, rectAux.width,
+						rectAux.height);
+				}
+
+				if (theSymbol.isOutlined()) {
+					g2.setColor(theSymbol.getOutlineColor());
+					g2.drawOval(rectAux.x, rectAux.y, rectAux.width,
+						rectAux.height);
+				}
+
+				break;
+
+			case FSymbol.SYMBOL_STYLE_MARKER_SQUARE: // Cuadrado
+			case FSymbol.SYMBOL_STYLE_FILL_SOLID:
+				g2.fillRect(rectAux.x, rectAux.y, rectAux.width, rectAux.height);
+
+				if (theSymbol.isOutlined()) {
+					g2.setColor(theSymbol.getOutlineColor());
+					g2.drawRect(rectAux.x, rectAux.y, rectAux.width,
+						rectAux.height);
+				}
+
+				break;
+
+			case FSymbol.SYMBOL_STYLE_MARKER_TRIANGLE: // Triangulo
+
+				// y = r*sin30, x = r*cos30
+				GeneralPathX genPath = new GeneralPathX();
+				genPath.moveTo(x - (int) (radio_simbolo * 0.866),
+					y + (int) (radio_simbolo * 0.5));
+				genPath.lineTo(x + (int) (radio_simbolo * 0.866),
+					y + (int) (radio_simbolo * 0.5));
+				genPath.lineTo(x, y - (float) radio_simbolo);
+				genPath.closePath();
+
+				g2.fill(genPath);
+
+				break;
+
+			case FSymbol.SYMBOL_STYLE_MARKER_CROSS: // cruz
+			case FSymbol.SYMBOL_STYLE_DGNSPECIAL: // Cruz
+
+				GeneralPathX genPathCruz = new GeneralPathX();
+				genPathCruz.moveTo(x, y - radio_simbolo);
+				genPathCruz.lineTo(x, y + radio_simbolo);
+				genPathCruz.moveTo(x - radio_simbolo, y);
+				genPathCruz.lineTo(x + radio_simbolo, y);
+				g2.draw(genPathCruz);
+
+				break;
+
+			case 34: // TrueType marker
+
+			/* lf.lfHeight = -radioSimbolo_en_pixels;
+			   angulo = pSimbolo->m_Rotation;  // En radianes, de -pi a pi
+			   angulo = -180.0 * angulo / PI;
+
+			   lf.lfEscapement = (long) angulo*10;
+			   lf.lfOrientation = (long) angulo*10;
+
+			   fuente.CreateFontIndirect(&lf);
+			   pOldFont = pDC->SelectObject(&fuente);
+
+			   pDC->TextOut(pAPI.x, pAPI.y+radioSimbolo_en_pixels/2,elChar,1);
+
+			   pDC->SelectObject(pOldFont);
+			   fuente.DeleteObject();
+
+			   break; */
+			case FSymbol.SYMBOL_STYLE_MARKER_IMAGEN: // Icono
+			 {
+				if (theSymbol.getIcon() != null) {
+					float w;
+					float h;
+
+					if (!theSymbol.isSizeInPixels()) {
+						// Suponemos que m_Size viene en coordenadas de mundo real
+						// Por ejemplo, nos valemos del ancho para fijar la escala
+						w = (float) (theSymbol.getSize() * mT.getScaleX());
+						h = (theSymbol.getIcon().getHeight(null) * w) / theSymbol.getIcon()
+																				 .getWidth(null);
+
+						rectAux.setRect(x - w, y - h, w * 2, h * 2);
+					} else {
+						// m_Size viene en pixels
+						w = theSymbol.getSize();
+						h = (theSymbol.getIcon().getHeight(null) * w) / theSymbol.getIcon()
+																				 .getWidth(null);
+						rectAux.setRect(x - w/2, y - h/2, w, h);
+					}
+					/* if (theSymbol.getImgObserver() != null)
+					{
+						g2.setColor(Color.WHITE);
+						g2.fillRect(rectAux.x, rectAux.y, rectAux.width, rectAux.height);
+					} */
+					g2.drawImage(theSymbol.getIcon(), rectAux.x, rectAux.y,
+						rectAux.width, rectAux.height, theSymbol.getImgObserver());
+				} else {
+					String strImg = "Image"; // Utilities.getMessage(FGraphicUtilities.class,"imagen");
+					FontMetrics metrics = g2.getFontMetrics();
+					int width = metrics.stringWidth(strImg);
+					int height = metrics.getMaxAscent();
+
+					g2.drawString(strImg, x - (width / 2), y - 2 +
+						(height / 2));
+				}
+
+				break;
+			}
+
+			/* DrawIconEx(pDC->m_hDC, pAPI.x-(pSimbolo->m_widthIco/2), pAPI.y-(pSimbolo->m_heightIco/2),
+			   pSimbolo->m_hIcon, pSimbolo->m_widthIco, pSimbolo->m_heightIco, 0 , NULL, DI_NORMAL);
+			   break; */
+// TODO This case has been commented: check it!!!
+//			case Geometry.TYPES.POINT|Geometry.TYPES.Z: // Circulito
+//
+//				if (theSymbol.getColor() != null) {
+//					g2.fillOval(rectAux.x, rectAux.y, rectAux.width,
+//						rectAux.height);
+//				}
+//
+//				if (theSymbol.isOutlined()) {
+//					g2.setColor(theSymbol.getOutlineColor());
+//					g2.drawOval(rectAux.x, rectAux.y, rectAux.width,
+//						rectAux.height);
+//				}
+//
+//				break;
+		} // del switch estilo
+	}
+	public static void DrawHandlers(Graphics2D g, AffineTransform at,
+			Handler[] handlers,ISymbol symbol) {
+
+			for (int i = 0; i < handlers.length; i++) {
+				Point2D point = handlers[i].getPoint();
+				at.transform(point, point);
+				g.setColor(((IFillSymbol)symbol).getFillColor());
+				g.fillRect((int) (point.getX() - 3), (int) (point.getY() - 3), 7, 7);
+				g.setColor(((ILineSymbol)symbol).getColor());
+				g.drawRect((int) (point.getX() - 5), (int) (point.getY() - 5), 10, 10);
+				g.drawString( "" + i, (int) (point.getX() - 5), (int) (point.getY() - 5));
+			}
+		}
+
+	public static void DrawVertex(Graphics2D g, AffineTransform at, Handler handlers) {
+		//for (int i = 0; i < handlers.length; i++) {
+			Point2D point = handlers.getPoint();
+			at.transform(point, point);
+			g.setColor(Color.black);
+			g.drawLine((int)point.getX()-2,(int)point.getY()-10,(int)point.getX()-2,(int)point.getY()+10);
+			g.drawLine((int)point.getX()+2,(int)point.getY()-10,(int)point.getX()+2,(int)point.getY()+10);
+			g.drawLine((int)point.getX()-10,(int)point.getY()-2,(int)point.getX()+10,(int)point.getY()-2);
+			g.drawLine((int)point.getX()-10,(int)point.getY()+2,(int)point.getX()+10,(int)point.getY()+2);
+			g.setColor(Color.red);
+			g.drawLine((int)point.getX()-1,(int)point.getY()-10,(int)point.getX()-1,(int)point.getY()+10);
+			g.drawLine((int)point.getX()+1,(int)point.getY()-10,(int)point.getX()+1,(int)point.getY()+10);
+			g.drawLine((int)point.getX()-10,(int)point.getY()-1,(int)point.getX()+10,(int)point.getY()-1);
+			g.drawLine((int)point.getX()-10,(int)point.getY()+1,(int)point.getX()+10,(int)point.getY()+1);
+
+		//}
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/MultiShapeSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/MultiShapeSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/MultiShapeSymbol.java	(revision 33580)
@@ -0,0 +1,658 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.aggregate.Aggregate;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ILineStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MultiShapeSymbol class allows to create a composition of several symbols with
+ * different shapes and be treated as a single symbol.These shapes can be
+ * marker,line or fill.
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class MultiShapeSymbol implements ILineSymbol, IMarkerSymbol, IFillSymbol {
+
+	public static final String MULTI_SHAPE_SYMBOL_DYNCLASS_NAME = "MultiShapeSymbol";
+	
+	private static final String FIELD_MARKER = "marker";
+	private static final String FIELD_LINE = "line";
+	private static final String FIELD_FILL = "fill";
+	private static final String FIELD_DESCRIPTION = "description";
+
+	public static final String SYMBOL_NAME = "multiShape";
+	
+	private static final Logger LOGGER = LoggerFactory
+			.getLogger(MultiShapeSymbol.class); 
+	
+	private SymbolManager manager = MapContextLocator.getSymbolManager();
+	
+	private IMarkerSymbol marker;
+	private ILineSymbol line;
+	private IFillSymbol fill;
+	private IMask mask;
+	private String desc;
+	private int referenceSystem;
+	private MultiShapeSymbol symSelect;
+	
+	public MultiShapeSymbol() {
+		marker = (IMarkerSymbol) createSymbol(IMarkerSymbol.SYMBOL_NAME);
+		line = (ILineSymbol) createSymbol(ILineSymbol.SYMBOL_NAME);
+		fill = (IFillSymbol) createSymbol(IFillSymbol.SYMBOL_NAME);
+	}
+	
+	private ISymbol createSymbol(String symbolName) {
+		return manager.createSymbol(symbolName);
+	}
+
+	public Color getLineColor() {
+		return line.getColor();
+	}
+
+	public void setLineColor(Color color) {
+		line.setLineColor(color);
+	}
+
+	public ILineStyle getLineStyle() {
+		return line.getLineStyle();
+	}
+
+	public void setLineStyle(ILineStyle lineStyle) {
+		line.setLineStyle(lineStyle);
+	}
+
+	public void setLineWidth(double width) {
+		line.setLineWidth(width);
+	}
+
+	public double getLineWidth() {
+		return line.getLineWidth();
+	}
+
+	public int getAlpha() {
+		return line.getAlpha();
+	}
+
+	public void setAlpha(int outlineAlpha) {
+		line.setAlpha(outlineAlpha);
+	}
+
+	public ISymbol getSymbolForSelection() {
+		if (symSelect == null) {
+			symSelect = new MultiShapeSymbol();
+		}
+
+		if (marker!=null){
+			symSelect.setMarkerSymbol((IMarkerSymbol) marker.getSymbolForSelection());
+		}
+
+		if (line!=null){
+			symSelect.setLineSymbol((ILineSymbol) line.getSymbolForSelection());
+		}
+
+		if (fill!=null ){
+			symSelect.setFillSymbol((IFillSymbol) fill.getSymbolForSelection());
+		}
+
+		return symSelect;
+
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+           	if (marker != null) {
+				marker.draw(g, affineTransform, geom, feature, cancel);
+			}
+			break;
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+		case Geometry.TYPES.SPLINE:
+		if (line != null) {
+				line.draw(g, affineTransform, geom, feature, cancel);
+			}
+			break;
+
+		case Geometry.TYPES.SURFACE:
+        case Geometry.TYPES.ELLIPSE:
+		case Geometry.TYPES.CIRCLE:
+			if (fill != null) {
+				fill.draw(g, affineTransform, geom, feature, cancel);
+			}
+			break;
+		}
+
+
+	}
+	
+	public boolean isOneDotOrPixel(Geometry geom,
+			double[] positionOfDotOrPixel, ViewPort viewPort, int dpi) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+           	if (marker != null) {
+				return marker.isOneDotOrPixel(geom, positionOfDotOrPixel, viewPort, dpi);
+			}
+			break;
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+		case Geometry.TYPES.SPLINE:
+		if (line != null) {
+				return line.isOneDotOrPixel(geom, positionOfDotOrPixel, viewPort, dpi);
+			}
+			break;
+
+		case Geometry.TYPES.SURFACE:
+        case Geometry.TYPES.ELLIPSE:
+		case Geometry.TYPES.CIRCLE:
+			if (fill != null) {
+				return fill.isOneDotOrPixel(geom, positionOfDotOrPixel, viewPort, dpi);
+			}
+			break;
+		}
+		if (!geom.isSimple()){
+			Aggregate aggregate = (Aggregate)geom;			
+			for (int i=0 ; i<aggregate.getPrimitivesNumber() ; i++){
+				if (!isOneDotOrPixel(aggregate.getPrimitiveAt(i), positionOfDotOrPixel, viewPort, dpi)){
+					return false;
+				}
+			}
+			return true;
+		}
+		return true;
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public int getOnePointRgb() {
+		// will return a mixture of all symbol's getOnePointRgb() value
+
+		int rMarker = 0;
+		int gMarker = 0;
+		int bMarker = 0;
+		int aMarker = 0;
+
+		if (marker!=null && marker.getColor() != null) {
+			rMarker = marker.getColor().getRed();
+			gMarker = marker.getColor().getGreen();
+			bMarker = marker.getColor().getBlue();
+			aMarker = marker.getColor().getAlpha();
+		}
+
+		int rLine = 0;
+		int gLine = 0;
+		int bLine = 0;
+		int aLine = 0;
+
+		if (line != null  && line.getColor() != null) {
+			rLine = line.getColor().getRed();
+			gLine = line.getColor().getGreen();
+			bLine = line.getColor().getBlue();
+			aLine = line.getColor().getAlpha();
+		}
+
+		int rFill = 0;
+		int gFill = 0;
+		int bFill = 0;
+		int aFill = 0;
+
+		if (fill != null ) {
+			Color colorOfFill = null;
+			if (fill.getOutline()!=null) {
+				colorOfFill = fill.getOutline().getColor();
+			} else if (fill.getFillColor()!=null) {
+				colorOfFill = fill.getFillColor();
+			}
+			if (colorOfFill != null) {
+				rFill = colorOfFill.getRed();
+				gFill = colorOfFill.getGreen();
+				bFill = colorOfFill.getBlue();
+				aFill = colorOfFill.getAlpha();
+
+			}
+		}
+
+		int red = (rMarker + rLine + rFill) / 3;
+		int green = (gMarker + gLine + gFill) / 3;
+		int blue = (bMarker + bLine + bFill) / 3;
+		int alpha = (aMarker + aLine + aFill) / 3;
+
+		return (alpha) << 24 + (red << 16) + (green << 8) + blue;
+	}
+
+	public String getDescription() {
+		return desc;
+	}
+
+	public boolean isShapeVisible() {
+		if (marker!=null) {
+			return marker.isShapeVisible();
+		}
+
+		if (line != null) {
+			return line.isShapeVisible();
+		}
+
+		if (fill != null) {
+			fill.isShapeVisible();
+		}
+
+		return false;
+	}
+
+	public void setDescription(String desc) {
+		this.desc = desc ;
+	}
+
+	public int getSymbolType() {
+		return Geometry.TYPES.GEOMETRY;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		// suitable for everything (why else does it exist?)
+		return true;
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		double myWidth =  (r.getWidth()/3);
+
+		Rectangle rect = new Rectangle(0, r.y, (int) myWidth, r.height);
+
+		if (marker != null) {
+			g.translate(r.x, r.y);
+			marker.drawInsideRectangle(g, scaleInstance, rect, properties);
+			g.translate(-(r.x), -(r.y));
+		}
+
+		if (line != null) {
+			g.translate(r.x+myWidth, r.y);
+			line.drawInsideRectangle(g, scaleInstance, rect, properties);
+			g.translate(-(r.x+myWidth), -(r.y));
+		}
+
+		if (fill != null) {
+			g.translate(r.x+myWidth+myWidth, r.y);
+			fill.drawInsideRectangle(g, scaleInstance, rect, properties);
+			g.translate(-(r.x+myWidth+myWidth), -(r.y));
+
+		}
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+           	if (marker != null) {
+				marker.print(g, at, geom, properties);
+			}
+			break;
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			if (line != null) {
+				line.print(g, at, geom, properties);
+			}
+			break;
+
+		case Geometry.TYPES.SURFACE:
+		case Geometry.TYPES.ELLIPSE:
+        case Geometry.TYPES.CIRCLE:
+			if (fill != null) {
+				fill.print(g, at, geom, properties);
+			}
+			break;
+		}
+	}
+
+	public double getRotation() {
+		if (marker != null) {
+			return marker.getRotation();
+		}
+		return 0;
+	}
+
+	public void setRotation(double rotation) {
+		if (marker != null) {
+			marker.setRotation(rotation);
+		}
+	}
+
+	public Point2D getOffset() {
+		if (marker != null) {
+			return marker.getOffset();
+		}
+		return new Point2D.Double();
+	}
+
+	public void setOffset(Point2D offset) {
+		if (marker != null) {
+			marker.setOffset(offset);
+		}
+	}
+
+	public double getSize() {
+		if (marker != null) {
+			return marker.getSize();
+		}
+		return 0;
+	}
+
+	public void setSize(double size) {
+		if (marker != null) {
+			marker.setSize(size);
+		}
+
+	}
+
+	public Color getColor() {
+		if (marker != null) {
+			return marker.getColor();
+		}
+		return null;
+	}
+
+	public void setColor(Color color) {
+		if (marker != null) {
+			marker.setColor(color);
+		}
+	}
+
+	public void setFillColor(Color color) {
+		if (fill != null) {
+			fill.setFillColor(color);
+		}
+	}
+
+	public void setOutline(ILineSymbol outline) {
+		if (fill != null) {
+			fill.setOutline(outline);
+		}
+	}
+
+	public Color getFillColor() {
+		if (fill != null) {
+			return fill.getFillColor();
+		}
+		return null;
+	}
+
+	public ILineSymbol getOutline() {
+		if (fill != null) {
+			return fill.getOutline();
+		}
+		return null;
+	}
+
+	public int getFillAlpha() {
+		if (fill != null) {
+			return fill.getFillAlpha();
+		}
+		return 255;
+	}
+
+	public IMask getMask() {
+		return mask;
+	}
+
+	public void setUnit(int unitIndex) {
+		if (marker != null) {
+			marker.setUnit(unitIndex);
+		}
+		if (line != null) {
+			line.setUnit(unitIndex);
+		}
+	}
+
+	public int getUnit() {
+		if (marker != null) {
+			return marker.getUnit();
+		}
+		if (line != null) {
+			return line.getUnit();
+		}
+		return -1;
+	}
+
+	public void setMask(IMask mask) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public int getReferenceSystem() {
+		return this.referenceSystem;
+	}
+
+	public void setReferenceSystem(int system) {
+		this.referenceSystem = system;
+
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+        	if (marker != null) {
+				return marker.toCartographicSize(viewPort, dpi, geom);
+			}
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			if (line != null) {
+				return line.toCartographicSize(viewPort, dpi, geom);
+			}
+		case Geometry.TYPES.SURFACE:
+		case Geometry.TYPES.ELLIPSE:
+		case Geometry.TYPES.CIRCLE:
+			LOGGER.warn("Cartographic size does not have any sense for fill symbols");
+
+		}
+		return -1;
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+        	if (marker != null) {
+				marker.setCartographicSize(cartographicSize, null);
+			}
+        	break;
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			if (line != null) {
+				line.setCartographicSize(cartographicSize, null);
+			}
+        	break;
+		case Geometry.TYPES.SURFACE:
+		case Geometry.TYPES.ELLIPSE:
+	    case Geometry.TYPES.CIRCLE:
+	    	LOGGER.warn("Cartographic size does not have any sense for fill symbols");
+		}
+	}
+
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		switch (geom.getType()) {
+		case Geometry.TYPES.POINT: //Tipo punto
+        	return CartographicSupportToolkit.
+			getCartographicLength(marker,
+								  getSize(),
+								  viewPort,
+								  dpi);
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			return CartographicSupportToolkit.
+			getCartographicLength(line,
+								  getSize(),
+								  viewPort,
+								  dpi);
+		case Geometry.TYPES.SURFACE:
+     	case Geometry.TYPES.ELLIPSE:
+	    case Geometry.TYPES.CIRCLE:
+	    	LOGGER.warn("Cartographic size does not have any sense for fill symbols");
+		}
+		return -1;
+	}
+
+	public IMarkerSymbol getMarkerSymbol() {
+		return marker;
+	}
+
+	public ILineSymbol getLineSymbol() {
+		return line;
+	}
+
+	public IFillSymbol getFillSymbol() {
+		return fill;
+	}
+
+	public void setMarkerSymbol(IMarkerSymbol markerSymbol) {
+		this.marker = markerSymbol;
+	}
+
+	public void setLineSymbol(ILineSymbol lineSymbol) {
+		this.line = lineSymbol;
+	}
+
+	public void setFillSymbol(IFillSymbol fillFillSymbol) {
+		this.fill = fillFillSymbol;
+	}
+
+	public boolean hasFill() {
+	if (fill == null) {
+		return false;
+	}
+	return fill.hasFill();
+	}
+
+	public void setHasFill(boolean hasFill) {
+		if (fill != null) {
+			fill.setHasFill(hasFill);
+//			this.hasFill = hasFill;
+		}
+	}
+
+	public boolean hasOutline() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void setHasOutline(boolean hasOutline) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		MultiShapeSymbol copy = (MultiShapeSymbol) super.clone();
+
+		// Clone inner symbols
+		if (marker != null) {
+			copy.marker = (IMarkerSymbol) marker.clone();
+		}
+		if (line != null) {
+			copy.line = (ILineSymbol) line.clone();
+		}
+		if (fill != null) {
+			copy.fill = (IFillSymbol) fill.clone();
+		}
+		
+		if (mask != null) {
+			copy.mask = (IMask) mask.clone();
+		}
+		
+		// Clone selection symbol
+		if (symSelect != null) {
+			copy.symSelect = (MultiShapeSymbol) symSelect.clone();
+		}
+		
+		return copy;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setDescription(state.getString(FIELD_DESCRIPTION));
+		setFillSymbol((IFillSymbol) state.get(FIELD_FILL));
+		setMarkerSymbol((IMarkerSymbol) state.get(FIELD_MARKER));
+		setLineSymbol((ILineSymbol) state.get(FIELD_LINE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_DESCRIPTION, getDescription());
+		state.set(FIELD_FILL, getFillSymbol());
+		state.set(FIELD_MARKER, getMarkerSymbol());
+		state.set(FIELD_LINE, getLineSymbol());
+	}
+
+	public static void registerPersistence() {
+		// Add the MultiShapeSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				MultiShapeSymbol.class,
+				MULTI_SHAPE_SYMBOL_DYNCLASS_NAME,
+				MULTI_SHAPE_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Description
+		definition.addDynFieldString(FIELD_DESCRIPTION).setMandatory(true);
+		// Fill symbol
+		definition.addDynFieldObject(FIELD_FILL);
+		// Line symbol
+		definition.addDynFieldObject(FIELD_LINE);
+		// Marker symbol
+		definition.addDynFieldObject(FIELD_MARKER);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbolFactory.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbolFactory.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FSymbolFactory.java	(revision 33580)
@@ -0,0 +1,230 @@
+/*
+ * Created on 04-may-2004
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.TexturePaint;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import org.gvsig.compat.CompatLocator;
+
+/**
+ * @author fjp
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ * @deprecated
+ */
+public class FSymbolFactory {
+	static int w, h;
+
+	// Podr�amos pasarle tambi�n un color de fondo, y usarlo como background del
+	// graphics2D.
+	static private Graphics2D createG2(Color cRef, BufferedImage bi)
+	{
+		   Graphics2D big = bi.createGraphics();
+		   Color color=new Color(0,0,0,0);
+		   big.setBackground(color);
+		   big.clearRect(0, 0, w, h);
+		   big.setColor(new Color(cRef.getRed(),cRef.getGreen(), cRef.getBlue(),cRef.getAlpha()));
+		   big.setStroke(new BasicStroke());
+
+		   return big;
+
+	}
+
+
+	static public Paint createPatternFill(int style, Color cRef)
+	{
+		/* public final static int SYMBOL_STYLE_FILL_SOLID = 1;
+		public final static int SYMBOL_STYLE_FILL_TRANSPARENT = 2;
+		public final static int SYMBOL_STYLE_FILL_HORIZONTAL = 3;
+		public final static int SYMBOL_STYLE_FILL_VERTICAL = 4;
+		public final static int SYMBOL_STYLE_FILL_CROSS = 5;
+		public final static int SYMBOL_STYLE_FILL_UPWARD_DIAGONAL = 6;
+		public final static int SYMBOL_STYLE_FILL_DOWNWARD_DIAGONAL = 7;
+		public final static int SYMBOL_STYLE_FILL_CROSS_DIAGONAL = 8;
+		public final static int SYMBOL_STYLE_FILL_GRAYFILL = 9;
+		public final static int SYMBOL_STYLE_FILL_LIGHTGRAYFILL = 10;
+		public final static int SYMBOL_STYLE_FILL_DARKGRAYFILL = 11; */
+
+
+		w=7; h=7;
+
+		BufferedImage bi = null;
+		Graphics2D big = null;
+
+		Rectangle2D rProv = new Rectangle();
+		rProv.setFrame(0, 0,w,h);
+
+		Paint resulPatternFill = null;
+		bi= CompatLocator.getGraphicsUtils().createBufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+		big = createG2(cRef, bi);
+
+		switch (style)
+		{
+			case FSymbol.SYMBOL_STYLE_FILL_SOLID:
+			    return null;
+			case FSymbol.SYMBOL_STYLE_FILL_TRANSPARENT:
+			    return null;
+			case FSymbol.SYMBOL_STYLE_FILL_UPWARD_DIAGONAL:
+			    big.drawLine(0,0,w,h);
+				break;
+			case FSymbol.SYMBOL_STYLE_FILL_CROSS:
+				big.drawLine(w/2,0,w/2,h);
+				big.drawLine(0,h/2,w,h/2);
+				break;
+			case FSymbol.SYMBOL_STYLE_FILL_CROSS_DIAGONAL:
+				big.drawLine(0,0,w,h);
+				big.drawLine(0,h,w,0);
+				break;
+			case FSymbol.SYMBOL_STYLE_FILL_VERTICAL:
+				big.drawLine(w/2,0,w/2,h);
+				break;
+			case FSymbol.SYMBOL_STYLE_FILL_HORIZONTAL:
+				big.drawLine(0,h/2,w,h/2);
+				break;
+			case FSymbol.SYMBOL_STYLE_FILL_DOWNWARD_DIAGONAL:
+				// DOWNWARD_DIAGONAL m�s ancho
+				w=15;h=15;
+				rProv.setFrame(0, 0,w,h);
+				bi= CompatLocator.getGraphicsUtils().createBufferedImage(
+						w, h, BufferedImage.TYPE_INT_ARGB);
+				big = createG2(cRef, bi);
+				big.drawLine(-1,h,w,-1);
+				break;
+
+		}
+
+		resulPatternFill = new TexturePaint(bi,rProv);
+
+		return resulPatternFill;
+
+	}
+
+	/**
+	 * Al crear esto lo mejor ser�a mirar en un directorio y cargar todas las
+	 * imagenes que tengamos predise�adas.
+	 *
+	 * @param cRef
+	 * @return
+	 */
+//	static public Paint[] createPatternFills(Color cRef)
+//	{
+//
+//		int aux = 3;
+//
+//		w=7; h=7;
+//
+//		BufferedImage bi = null;
+//		Graphics2D big = null;
+//
+//		Rectangle2D rProv = new Rectangle();
+//		rProv.setFrame(0, 0,w,h);
+//
+//		Paint[] patternFills = new Paint[8];
+//
+//		// UPWARD_DIAGONAL
+//		bi= new Bu-f-f-eredImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		big.drawLine(0,0,w,h);
+//		patternFills[FStyle2D.SYMBOL_STYLE_FILL_UPWARD_DIAGONAL-aux] =
+//				new TexturePaint(bi,rProv);
+//
+//		// CROSS
+//		bi= new Bu-f-f-eredImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		big.drawLine(w/2,0,w/2,h);
+//		big.drawLine(0,h/2,w,h/2);
+//		patternFills[FConstant.SYMBOL_STYLE_FILL_CROSS-aux] =
+//				new TexturePaint(bi,rProv);
+//
+//		// CROSS
+//		bi= new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		big.drawLine(0,0,w,h);
+//		big.drawLine(0,h,w,0);
+//		patternFills[FConstant.SYMBOL_STYLE_FILL_CROSS_DIAGONAL-aux] =
+//				new TexturePaint(bi,rProv);
+//
+//
+//		// VERTICAL
+//		bi= new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		big.drawLine(w/2,0,w/2,h);
+//		patternFills[FConstant.SYMBOL_STYLE_FILL_VERTICAL-aux] =
+//				new TexturePaint(bi,rProv);
+//
+//		// HORIZONTAL
+//		bi= new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		big.drawLine(0,h/2,w,h/2);
+//		patternFills[FConstant.SYMBOL_STYLE_FILL_HORIZONTAL-aux] =
+//				new TexturePaint(bi,rProv);
+//
+//		// DOWNWARD_DIAGONAL m�s ancho
+//		w=15;h=15;
+//		rProv.setFrame(0, 0,w,h);
+//		bi= new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+//		big = createG2(cRef, bi);
+//		// big.setColor(Color.BLUE);
+//		big.drawLine(-1,h,w,-1);
+//		// big.setColor(Color.RED);
+//		// big.drawLine(0,0,w,h);
+//		patternFills[FConstant.SYMBOL_STYLE_FILL_DOWNWARD_DIAGONAL-aux] =
+//				new TexturePaint(bi,rProv);
+//		int trans=((TexturePaint)patternFills[FConstant.SYMBOL_STYLE_FILL_DOWNWARD_DIAGONAL-aux]).getTransparency();
+//
+//		return patternFills;
+//	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FLabel.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FLabel.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/FLabel.java	(revision 33580)
@@ -0,0 +1,432 @@
+/*
+ * Created on 13-jul-2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.batik.ext.awt.geom.PathLength;
+import org.gvsig.fmap.geom.aggregate.MultiPoint;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.util.Converter;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.utils.XMLEntity;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.Point;
+
+
+/**
+ * Se utiliza para etiquetar. Las capas vectoriales tienen un arrayList
+ * (m_labels) de FLabel, un FLabel por cada registro.
+ *
+ * @author FJP
+ * @deprecated
+ */
+public class FLabel implements Cloneable {
+	public final static byte LEFT_TOP = 0;
+	public final static byte LEFT_CENTER = 1;
+	public final static byte LEFT_BOTTOM = 2;
+	public final static byte CENTER_TOP = 6;
+	public final static byte CENTER_CENTER = 7;
+	public final static byte CENTER_BOTTOM = 8;
+	public final static byte RIGHT_TOP = 12;
+	public final static byte RIGHT_CENTER = 13;
+	public final static byte RIGHT_BOTTOM = 14;
+	private String m_Str = null;
+	private Point2D m_Orig = null;
+	private double m_Height;
+	public static final double SQUARE = Math.sqrt(2.0);
+	/**
+	 * <code>m_rotation</code> en grados, NO en radianes. Se convierte en
+	 * radianes al dibujar.
+	 */
+	private double m_rotation;
+
+	/**
+	 * Valores posibles para <code>m_Justification</code>: Left/Top = 0
+	 * Center/Top = 6                Right/Top = 12 Left/Center = 1
+	 * Center/Center = 7            Right/Center = 13 Left/Bottom = 2
+	 * Center/Bottom = 8            Right/Bottom = 14
+	 */
+	private byte m_Justification = LEFT_BOTTOM; // Por defecto
+	private int m_Style;
+	private Rectangle2D boundBox;
+	private Color color;
+	private static Font font=new Font("Dialog",Font.PLAIN,12);
+	/**
+	 * Crea un nuevo FLabel.
+	 */
+	public FLabel() {
+		// nothing to do
+	}
+
+	/**
+	 * Crea un nuevo FLabel.
+	 *
+	 * @param str DOCUMENT ME!
+	 */
+	public FLabel(String str) {
+		m_Str = str;
+	}
+
+	/**
+	 * Crea un nuevo FLabel.
+	 *
+	 * @param str
+	 * @param pOrig
+	 * @param heightText
+	 * @param rotation
+	 */
+	public FLabel(String str, Point2D pOrig, double heightText, double rotation) {
+		m_Str = str;
+		m_Orig = pOrig;
+		m_Height = heightText;
+		m_rotation = rotation;
+	}
+
+	/**
+	 * Introduce un nuevo FLabel al ya existente.
+	 *
+	 * @param label
+	 */
+	public void setFLabel(FLabel label) {
+		m_Str = label.m_Str;
+		m_Orig = label.m_Orig;
+		m_Height = label.m_Height;
+		m_rotation = label.m_rotation;
+	}
+
+	/**
+	 * Clona el FLabel.
+	 *
+	 * @return Object clonado.
+	 */
+	public Object clone() {
+		FLabel label=new FLabel(m_Str, m_Orig, m_Height, m_rotation);
+		label.boundBox=(Rectangle2D)boundBox.clone();
+		return label;
+	}
+
+	/**
+	 * Devuelve la altura del Label.
+	 *
+	 * @return Returns the m_Height.
+	 */
+	public double getHeight() {
+		return m_Height;
+	}
+
+	/**
+	 * Devuelve el punto de origen.
+	 *
+	 * @return Returns the m_Orig.
+	 */
+	public Point2D getOrig() {
+		return m_Orig;
+	}
+
+	/**
+	 * Devuelve la rotaci�n.
+	 *
+	 * @return Returns the m_rotation.
+	 */
+	public double getRotation() {
+		return m_rotation;
+	}
+
+	/**
+	 * Devuelve un String con el texto del Label.
+	 *
+	 * @return Returns the m_Str.
+	 */
+	public String getString() {
+		return m_Str;
+	}
+
+	/**
+	 * Introduce la altura del Label.
+	 *
+	 * @param height The m_Height to set.
+	 */
+	public void setHeight(double height) {
+		m_Height = height;
+	}
+
+	/**
+	 * Introduce el punto de origen del Label.
+	 *
+	 * @param orig The m_Orig to set.
+	 */
+	public void setOrig(Point2D orig) {
+		m_Orig = orig;
+	}
+
+	/**
+	 * Introduce la rotaci�n a aplicar al Label.
+	 *
+	 * @param m_rotation The m_rotation to set.
+	 */
+	public void setRotation(double m_rotation) {
+		this.m_rotation = Math.toRadians(-m_rotation);
+	}
+
+	/**
+	 * Introduce el texto del Label.
+	 *
+	 * @param str The m_Str to set.
+	 */
+	public void setString(String str) {
+		m_Str = str;
+	}
+
+	/**
+	 * Valores posibles para <code>m_Justification</code>: Left/Top = 0
+	 * Center/Top = 6                Right/Top = 12 Left/Center = 1
+	 * Center/Center = 7            Right/Center = 13 Left/Bottom = 2
+	 * Center/Bottom = 8            Right/Bottom = 14
+	 *
+	 * @return byte.
+	 */
+	public byte getJustification() {
+		return m_Justification;
+	}
+
+	/**
+	 * Valores posibles para <code>m_Justification</code>: Left/Top = 0
+	 * Center/Top = 6                Right/Top = 12 Left/Center = 1
+	 * Center/Center = 7            Right/Center = 13 Left/Bottom = 2
+	 * Center/Bottom = 8            Right/Bottom = 14
+	 *
+	 * @param justification byte
+	 */
+	public void setJustification(byte justification) {
+		m_Justification = justification;
+	}
+
+	/**
+	 * Devuelve un Objeto XMLEntity con la informaci�n los atributos necesarios
+	 * para poder despu�s volver a crear el objeto original.
+	 *
+	 * @return XMLEntity.
+	 */
+	public XMLEntity getXMLEntity() {
+		XMLEntity xml = new XMLEntity();
+		xml.putProperty("className",this.getClass().getName());
+		xml.setName("flabel");
+		xml.putProperty("m_Height", m_Height);
+		xml.putProperty("m_Justification", (int) m_Justification);
+		xml.putProperty("m_OrigX", m_Orig.getX());
+		xml.putProperty("m_OrigY", m_Orig.getY());
+		xml.putProperty("m_rotation", m_rotation);
+		xml.putProperty("m_Str", m_Str);
+
+		return xml;
+	}
+
+	/**
+	 * Crea un Objeto de esta clase a partir de la informaci�n del XMLEntity.
+	 *
+	 * @param xml XMLEntity
+	 *
+	 * @return Objeto de esta clase.
+	 */
+	public static FLabel createFLabel(XMLEntity xml) {
+		FLabel label = new FLabel();
+		label.setHeight(xml.getDoubleProperty("m_Height"));
+		label.setJustification((byte) xml.getIntProperty("m_Justification"));
+		label.setOrig(new Point2D.Double(xml.getDoubleProperty("m_OrigX"),
+				xml.getDoubleProperty("m_OrigY")));
+		label.setString("m_Str");
+
+		return label;
+	}
+
+	/**
+	 * M�todo est�tico que crea un FLabel a partir de una Geometry.
+	 *
+	 * @param geom Geometry.
+	 *
+	 * @return nuevo FLabel creado.
+	 * @throws CreateGeometryException 
+	 */
+	public static FLabel createFLabel(org.gvsig.fmap.geom.Geometry geom) throws CreateGeometryException {
+		float angle;
+		Point2D pAux = createLabelPoint(geom);
+
+		FLabel label = new FLabel();
+		label.setOrig(pAux);
+		switch (geom.getType()) {
+			case org.gvsig.fmap.geom.Geometry.TYPES.CURVE:
+           		PathLength pathLen = new PathLength(geom);
+				float midDistance = pathLen.lengthOfPath() / 2;
+				angle = pathLen.angleAtLength(midDistance);
+
+				if (angle < 0) {
+					angle = angle + (float) (2 * Math.PI);
+				}
+				if ((angle > (Math.PI / 2)) && (angle < ((3 * Math.PI) / 2))) {
+					angle = angle - (float) Math.PI;
+				}
+				label.setRotation(Math.toDegrees(angle));
+				break;
+		} // switch
+
+		return label;
+	}
+	public static Point2D createLabelPoint(org.gvsig.fmap.geom.Geometry geom) throws CreateGeometryException {
+		Point2D pAux = null;
+		switch (geom.getType()) {
+			case org.gvsig.fmap.geom.Geometry.TYPES.POINT:
+            	pAux = new Point2D.Double(((org.gvsig.fmap.geom.primitive.Point) geom).getX(),
+						((org.gvsig.fmap.geom.primitive.Point) geom).getY());
+				return pAux;
+
+			case org.gvsig.fmap.geom.Geometry.TYPES.CURVE:
+            	PathLength pathLen = new PathLength(geom);
+
+				// if (pathLen.lengthOfPath() < width / mT.getScaleX()) return;
+				float midDistance = pathLen.lengthOfPath() / 2;
+				pAux = pathLen.pointAtLength(midDistance);
+				return pAux;
+
+			case org.gvsig.fmap.geom.Geometry.TYPES.SURFACE:
+            	Geometry geo = Converter.geometryToJts(geom);
+
+				if (geo == null) {
+					return null;
+				}
+
+				Point pJTS = geo.getCentroid();
+
+				if (pJTS != null) {
+					org.gvsig.fmap.geom.Geometry pLabel = Converter.jtsToGeometry(pJTS);
+					return new Point2D.Double(((org.gvsig.fmap.geom.primitive.Point) pLabel).getX(),
+							((org.gvsig.fmap.geom.primitive.Point) pLabel).getY());
+				}
+				break;
+            case org.gvsig.fmap.geom.Geometry.TYPES.MULTIPOINT:
+            	int num=((MultiPoint)geom).getPrimitivesNumber();
+    			Rectangle2D r=null;
+    			if (num>0){
+    				r= ((MultiPoint)geom).getPointAt(0).getBounds2D();
+    				for (int i=1;i<num;i++){
+    					org.gvsig.fmap.geom.primitive.Point fp=((MultiPoint)geom).getPointAt(i);
+    					r.add(new Point2D.Double(fp.getX(),fp.getY()));
+    				}
+    			}
+    			if (r!=null)
+    			return new Point2D.Double(r.getCenterX(),r.getCenterY());
+    			break;
+
+		} // switch
+				return null;
+	}
+	public void setTypeFont(String t) {
+		font=Font.getFont(t,font);
+	}
+	public int getStyle() {
+		return m_Style;
+	}
+
+	public void setBoundBox(Rectangle2D boundBox) {
+		this.boundBox=boundBox;
+
+	}
+	public Rectangle2D getBoundBox(){
+		return boundBox;
+	}
+
+	public Rectangle2D getBoundingBox(ViewPort vp) {
+		return vp.fromMapRectangle(boundBox);
+	}
+
+	public void setColor(int i) {
+		color=new Color(i);
+	}
+
+	public Color getColor() {
+		return color;
+	}
+	/*public Font getFont(AffineTransform at,boolean isInPixels){
+		if (!isInPixels) {
+			float alturaPixels = (float) ((getHeight() * at.getScaleX())*SQUARE);
+			//Font nuevaFuente = font.deriveFont(alturaPixels);//new Font(getTypeFont(),getStyle(),(int)alturaPixels);
+			return font.deriveFont(alturaPixels);
+		}
+		//Font nuevaFuente = font.deriveFont((float)(getHeight()*SQUARE));//new Font(getTypeFont(),getStyle(),(int)(getHeight()*SQUARE));
+		return font;//font.deriveFont((float)(getHeight()*SQUARE));
+	}*/
+	public Font getFont(AffineTransform at,Font font){
+		float alturaPixels = (float) ((getHeight() * at.getScaleX())*SQUARE);
+		//return font.deriveFont(alturaPixels);
+        return font.deriveFont(font.getStyle(),alturaPixels);
+	}
+
+	/**
+	 * Por ahora, para extender el renderizado de etiquetas, habr�a que
+	 * crear otro FLabel y reimplementar este m�todo para que haga caso
+	 * a otros s�mbolos. Es decir, NO usar FGraphicUtilities
+	 * @param g
+	 * @param affineTransform
+	 * @param theShape
+	 * @param theSymbol
+	 */
+	public void draw(Graphics2D g, AffineTransform affineTransform, Shape theShape, ISymbol theSymbol) {
+        FGraphicUtilities.DrawLabel(g, affineTransform,
+                (org.gvsig.fmap.geom.Geometry) theShape, (FSymbol) theSymbol, this);
+
+
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/AbstractSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/AbstractSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/AbstractSymbol.java	(revision 33580)
@@ -0,0 +1,228 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import java.awt.Rectangle;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class that implements the interface the interface for symbols.It is
+ * considered as the father of all XXXSymbols and will implement all the methods
+ * that these classes had not developed (and correspond with one of the methods
+ * of AbstractSymbol class)
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractSymbol implements ISymbol, CartographicSupport {
+
+	public static final String SYMBOL_PERSISTENCE_DEFINITION_NAME = "Symbol";
+	
+	private static final String FIELD_UNIT = "unit";
+
+	private static final String FIELD_REFERENCE_SYSTEM = "referenceSystem";
+
+	private static final String FIELD_IS_SHAPE_VISIBLE = "isShapeVisible";
+
+	private static final String FIELD_DESCRIPTION = "description";
+
+	private static final Logger LOGGER =
+			LoggerFactory.getLogger(AbstractSymbol.class);
+
+	private String desc;
+	private int unit;
+	private int referenceSystem;
+
+	private boolean isShapeVisible = true;
+
+	public AbstractSymbol() {
+		SymbolPreferences preferences =
+				MapContextLocator.getSymbolManager().getSymbolPreferences();
+		unit =
+				preferences.getDefaultCartographicSupportMeasureUnit();
+		referenceSystem =
+				preferences.getDefaultCartographicSupportReferenceSystem();
+	}
+
+	public final void setDescription(String desc) {
+		this.desc = desc;
+	}
+
+	public final String getDescription() {
+		return desc;
+	}
+
+	/**
+	 * @return
+	 * @uml.property name="isShapeVisible"
+	 */
+	public final boolean isShapeVisible() {
+		return isShapeVisible;
+	}
+
+	/**
+	 * Sets this symbol to visible
+	 * 
+	 * @param isShapeVisible
+	 */
+	public final void setIsShapeVisible(boolean isShapeVisible) {
+		this.isShapeVisible = isShapeVisible;
+	}
+
+	public void setUnit(int unitIndex) {
+		this.unit = unitIndex;
+	}
+
+	public int getUnit() {
+		return this.unit;
+	}
+
+	public int getReferenceSystem() {
+		return this.referenceSystem;
+	}
+
+	public void setReferenceSystem(int system) {
+		this.referenceSystem = system;
+
+	}
+
+	public boolean equals(Object obj) {
+		if (!obj.getClass().equals(getClass())) {
+			return false;
+		}
+		if (((ISymbol) obj).getOnePointRgb() != getOnePointRgb()) {
+			return false;
+		}
+		if (getDescription() != null
+				&& ((ISymbol) obj).getDescription() != null) {
+			if (!((ISymbol) obj).getDescription().equals(getDescription())) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	public boolean isOneDotOrPixel(Geometry geom,
+			double[] positionOfDotOrPixel, ViewPort viewPort, int dpi) {
+
+		int type = geom.getType();
+		switch (type) {
+		case Geometry.TYPES.NULL:
+		case Geometry.TYPES.POINT:
+		case Geometry.TYPES.MULTIPOINT:
+			return false;
+		default:
+			org.gvsig.fmap.geom.primitive.Envelope geomBounds = geom
+			.getEnvelope();
+
+			double dist1Pixel = viewPort.getDist1pixel();
+
+			float[] distances = new float[2];
+			this.getPixExtentPlus(geom, distances, viewPort, dpi);
+
+			boolean onePoint =
+					(geomBounds.getLength(0) + distances[0] <= dist1Pixel && geomBounds
+					.getLength(1)
+					+ distances[1] <= dist1Pixel);
+
+			if (onePoint) {
+				Rectangle bounds = geom.getBounds();
+				positionOfDotOrPixel[0] = bounds.x;
+				positionOfDotOrPixel[1] = bounds.y;
+			}
+			return onePoint;
+		}
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		return super.clone();	
+	}
+
+	protected ISymbol cloneForSelection() {
+		try {
+			ISymbol selectionSymbol = (ISymbol) clone();
+			selectionSymbol.setColor(MapContext.getSelectionColor());
+			if (getDescription() != null){
+				selectionSymbol.setDescription(getDescription().concat(
+				" version for selection"));
+			}else{
+				selectionSymbol.setDescription("version for selection");
+			}
+			return selectionSymbol;
+		} catch (CloneNotSupportedException e) {
+			LOGGER.error(
+					"Error creating the selection symbol for the symbol "
+					+ this, e);
+		}
+		return null;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setDescription(state.getString(FIELD_DESCRIPTION));
+		setIsShapeVisible(state.getBoolean(FIELD_IS_SHAPE_VISIBLE));
+		setReferenceSystem(state.getInt(FIELD_REFERENCE_SYSTEM));
+		setUnit(state.getInt(FIELD_UNIT));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_DESCRIPTION, getDescription());
+		state.set(FIELD_IS_SHAPE_VISIBLE, isShapeVisible());
+		state.set(FIELD_REFERENCE_SYSTEM, getReferenceSystem());
+		state.set(FIELD_UNIT, getUnit());
+	}
+
+	public static void registerPersistence() {
+		// Add the AbstractSymbol DynClass definition
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				AbstractSymbol.class, 
+				SYMBOL_PERSISTENCE_DEFINITION_NAME, 
+				SYMBOL_PERSISTENCE_DEFINITION_NAME+" persistence definition", 
+				null, 
+				null
+		);
+		// Description
+		definition.addDynFieldString(FIELD_DESCRIPTION);
+		// Is Shape Visible
+		definition.addDynFieldBoolean(FIELD_IS_SHAPE_VISIBLE).setMandatory(true);
+		// Reference system
+		definition.addDynFieldInt(FIELD_REFERENCE_SYSTEM).setMandatory(true);
+		// Unit
+		definition.addDynFieldInt(FIELD_UNIT).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/CartographicSupportToolkit.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/CartographicSupportToolkit.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/impl/CartographicSupportToolkit.java	(revision 33580)
@@ -0,0 +1,103 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl;
+
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+
+
+
+/**
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class CartographicSupportToolkit {
+
+	/**
+	 * Calculates the distance in pixels corresponding to the provided length,
+	 * according to the current rendering context (output dpi, map scale, map units) and the
+	 * symbol cartographic settings (unit, size, and unit reference system).
+	 *
+	 * @param cartographicElement CartographicSupport object which contains the reference system
+	 * and the measuring units for the provided length
+	 * @param length The length to be computed in pixels. The length is supposed to be
+	 * provided in the units defined in the cartographicElement
+	 * @param viewPort The viewport, which defines the relationship between pixels and maps units
+	 * @param dpi The resolution (dots per inch) of the target display device
+	 * (printer, screen, etc)
+	 * @return The distance in pixels corresponding to the provided length
+	 */
+	public static double getCartographicLength(CartographicSupport cartographicElement, double length, ViewPort viewPort, double dpi) {
+		int unit = cartographicElement.getUnit();
+		double lengthInPixel = length;
+
+		if (unit != -1) {
+			double[] trans2Meter=MapContext.getDistanceTrans2Meter();
+			if (cartographicElement.getReferenceSystem() == CartographicSupport.WORLD) {
+				double dist1PixelInMeters = viewPort.getDist1pixel()*trans2Meter[viewPort.getMapUnits()];
+				double realWidthMeter = length*trans2Meter[unit];
+				lengthInPixel = realWidthMeter/dist1PixelInMeters;
+			} else if (cartographicElement.getReferenceSystem() == CartographicSupport.PAPER) {
+				double lengthInInches = 1/trans2Meter[7]*trans2Meter[unit]*length;
+				lengthInPixel = lengthInInches*dpi;
+			}
+		} else{
+			double scale=dpi/72;
+			lengthInPixel=lengthInPixel*scale;
+		}
+		return  (lengthInPixel);
+
+	}
+
+	/**
+	 * The unit that will be used when creating new symbols.<br>
+	 * <b>Factory defaults to pixel.</b>
+	 */
+	public static int DefaultMeasureUnit = -1;
+	/**
+	 * The reference system that will be used when creating new symbols.<br>
+	 * <b>Factory defaults to pixel.</b>
+	 */
+	public static int DefaultReferenceSystem = CartographicSupport.WORLD;
+
+}
+
+
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/IMarkerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/IMarkerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/IMarkerSymbol.java	(revision 33580)
@@ -0,0 +1,112 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker;
+
+import java.awt.Color;
+import java.awt.geom.Point2D;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
+
+/**
+ * Represents an ISymbol that draws a <b>marker symbol</b>.It has the different methods to obtain or
+ * define the attributes of a marker such as rotation, offset, size, color and
+ * IMask.
+ *
+ * @author   jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public interface IMarkerSymbol extends ISymbol, CartographicSupport {
+	
+	public static final String SYMBOL_NAME = "marker";
+
+	public static final int CIRCLE_STYLE = 0;
+	public static final int SQUARE_STYLE = 1;
+	public static final int CROSS_STYLE = 2;
+	public static final int DIAMOND_STYLE = 3;
+	public static final int X_STYLE = 4;
+	public static final int TRIANGLE_STYLE = 5;
+	public static final int STAR_STYLE = 6;
+
+	/**
+	 * Returns the rotation of the marker symbol
+	 * @return double (rotation)
+	 */
+	public abstract double getRotation();
+	/**
+	 * Sets the rotation of the marker symbol
+	 * @param rotation
+	 */
+	public abstract void setRotation(double rotation);
+	/**
+	 * Gets the offset for a marker symbol
+	 * @return Point2D
+	 */
+	public abstract Point2D getOffset();
+	/**
+	 * Establishes the offset currently set for the marker symbol.
+	 * @param offset
+	 */
+	public abstract void setOffset(Point2D offset);
+	/**
+	 * Obtains the size of a marker symbol
+	 *
+	 */
+	public abstract double getSize();
+	/**
+	 * Sets the size of marker symbol
+	 * @param size
+	 */
+	public abstract void setSize(double size);
+
+	/**
+	 * Returns the color of the marker symbol.
+	 * @return Color
+	 */
+	public abstract Color getColor();
+
+	/**
+	 * Establishes a color for the marker symbol
+	 * @param color
+	 */
+	public abstract void setColor(Color color);
+	
+	/**
+	 * Defines the transparency of a line symbol.
+	 * 
+	 * @param outlineAlpha
+	 *            , the transparency
+	 */
+	void setAlpha(int alpha);
+	
+	/**
+	 *
+	 * @return the mask of the symbol
+	 */
+	public abstract IMask getMask();
+	/**
+	 * Defines a mask for the symbol
+	 * @param mask,IMask
+	 */
+	public abstract void setMask(IMask mask);
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/SimpleMarkerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/SimpleMarkerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/SimpleMarkerSymbol.java	(revision 33580)
@@ -0,0 +1,355 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+
+/**
+ * SimpleMarkerSymbol is the most basic symbol for the representation of point objects
+ * which can define its size and color apart from the rotation and the offset from a point
+ * in the map.
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SimpleMarkerSymbol extends AbstractMarkerSymbol {
+
+	public static final String SIMPLE_MARKER_SYMBOL_DYNCLASS_NAME = "SimpleMarkerSymbol";
+	
+	private static final String FIELD_OUTLINED = "outlined"; 
+	private static final String FIELD_OUTLINECOLOR = "outlineColor"; 
+	private static final String FIELD_OUTLINESIZE = "outlineSize"; 
+	private static final String FIELD_MARKERSTYLE = "markerStyle"; 
+
+	private boolean outlined;
+	private Color outlineColor;
+	private double outlineSize;
+	private ISymbol selectionSymbol;
+	private int markerStyle;
+
+	public ISymbol getSymbolForSelection() {
+		if (selectionSymbol == null) {
+			selectionSymbol = (SimpleMarkerSymbol) cloneForSelection();
+		}
+		return selectionSymbol;
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		int x, y;
+//		Point2D p = new Point2D.Double(((FPoint2D) shp).getX(), ((FPoint2D) shp)
+//				.getY());
+		org.gvsig.fmap.geom.primitive.Point p = (org.gvsig.fmap.geom.primitive.Point) geom;
+
+		int size = (int) getSize();
+
+		int halfSize = size/2;
+		x = ((int) (p.getX() + getOffset().getX()) - halfSize);
+		y = ((int) (p.getY() + getOffset().getY()) - halfSize);
+
+		// IMask mask = getMask();
+		// if (mask != null) {
+		// IFillSymbol maskShape = mask.getFillSymbol();
+		// // maskShape.draw(g, null, mask.getHaloShape(shp));
+		// }
+
+		g.setColor(getColor());
+		GeneralPathX genPath = null;
+		g.setStroke(new BasicStroke(1));
+
+		switch (markerStyle) {
+		case CIRCLE_STYLE:
+			g.fillOval(x, y, size, size);
+			break;
+		case SQUARE_STYLE:
+			g.fillRect(x, y, size, size);
+			break;
+		case CROSS_STYLE:
+			x = x + halfSize;
+			y = y + halfSize;
+			genPath = new GeneralPathX();
+			genPath.moveTo(x, y - halfSize);
+			genPath.lineTo(x, y + halfSize);
+			genPath.moveTo(x - halfSize, y);
+			genPath.lineTo(x + halfSize, y);
+			g.draw(genPath);
+			break;
+		case DIAMOND_STYLE:
+			x = x + halfSize;
+			y = y + halfSize;
+			genPath = new GeneralPathX();
+			genPath.moveTo(x-halfSize, y);
+			genPath.lineTo(x, y+halfSize);
+			genPath.lineTo(x+halfSize, y);
+			genPath.lineTo(x, y-halfSize);
+			genPath.lineTo(x-halfSize, y);
+			genPath.closePath();
+			g.fill(genPath);
+			break;
+		case X_STYLE:
+			x = x + halfSize;
+			y = y + halfSize;
+			genPath = new GeneralPathX();
+			genPath.moveTo(x-halfSize, y - halfSize);
+			genPath.lineTo(x+halfSize, y + halfSize);
+			genPath.moveTo(x - halfSize, y + halfSize);
+			genPath.lineTo(x + halfSize, y - halfSize);
+			g.draw(genPath);
+			break;
+		case TRIANGLE_STYLE:
+			x = x + halfSize;
+			y = y + halfSize;
+			int otherSize = (int) (size * 0.55);
+			genPath = new GeneralPathX();
+			genPath.moveTo(x - halfSize,
+				y + halfSize);
+			genPath.lineTo(x + halfSize,
+				y + halfSize);
+			genPath.lineTo(x, y - otherSize);
+			genPath.closePath();
+
+			g.fill(genPath);
+			break;
+		case STAR_STYLE:
+			x = x + halfSize;
+			y = y + halfSize;
+			genPath = new GeneralPathX();
+			genPath.moveTo(x-halfSize, y);
+
+			genPath.lineTo(x-2*(halfSize/3), y+(halfSize/3));
+			genPath.lineTo(x-2*(halfSize/3), y+2*(halfSize/3));
+			genPath.lineTo(x-(halfSize/3), y+2*(halfSize/3));
+
+			genPath.lineTo(x, y+halfSize);
+
+			genPath.lineTo(x+(halfSize/3), y+2*(halfSize/3));
+			genPath.lineTo(x+2*(halfSize/3), y+2*(halfSize/3));
+			genPath.lineTo(x+2*(halfSize/3), y+(halfSize/3));
+
+			genPath.lineTo(x+(halfSize), y);
+
+			genPath.lineTo(x+2*(halfSize/3), y-(halfSize/3));
+			genPath.lineTo(x+2*(halfSize/3), y-2*(halfSize/3));
+			genPath.lineTo(x+(halfSize/3), y-2*(halfSize/3));
+
+			genPath.lineTo(x, y-halfSize);
+
+			genPath.lineTo(x-(halfSize/3), y-2*(halfSize/3));
+			genPath.lineTo(x-2*(halfSize/3), y-2*(halfSize/3));
+			genPath.lineTo(x-2*(halfSize/3), y-(halfSize/3));
+
+			genPath.lineTo(x-halfSize, y);
+
+			genPath.closePath();
+
+
+			g.fill(genPath);
+
+			break;
+		}
+
+
+		if (outlined) {
+			g.setColor(outlineColor);
+			switch (markerStyle) {
+			case CIRCLE_STYLE:
+				g.drawOval(x, y, size, size);
+				break;
+			case SQUARE_STYLE:
+				g.drawRect(x, y, size, size);
+				break;
+			case CROSS_STYLE:
+			case DIAMOND_STYLE:
+			case STAR_STYLE:
+			case X_STYLE:
+			case TRIANGLE_STYLE:
+				g.draw(genPath);
+				break;
+			}
+		}
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	/**
+	 * Returns true or false depending if the simple marker symbol has an outline or not.
+	 * @return Returns the outline.
+	 */
+	public boolean hasOutline() {
+		return outlined;
+	}
+
+	/**
+	 * Establishes the outline for the simple marker symbol.
+	 * @param outline  The outline to set.
+	 */
+	public void setOutlined(boolean outlined) {
+		this.outlined = outlined;
+	}
+
+	/**
+	 * Returns the outline color for the symple marker symbol
+	 *
+	 * @return Color,outlineColor.
+	 */
+	public Color getOutlineColor() {
+		return outlineColor;
+	}
+
+	/**
+	 * Sets the outline color for the simple marker symbol
+	 * @param outlineColor, Color
+	 */
+	public void setOutlineColor(Color outlineColor) {
+		this.outlineColor = outlineColor;
+	}
+
+	/**
+	 * Gets the size of the outline for the simple marker symbol
+	 * @return  Returns the outlineSize.
+	 */
+	public double getOutlineSize() {
+		return outlineSize;
+	}
+
+	/**
+	 * Establishes the size for the outline of the simple marker symbol
+	 * @param outlineSize  The outlineSize to set.
+	 */
+	public void setOutlineSize(double outlineSize) {
+		this.outlineSize = outlineSize;
+	}
+
+	/**
+	 * @return  Returns the selectionSymbol.
+	 */
+	public ISymbol getSelectionSymbol() {
+		return selectionSymbol;
+	}
+
+	/**
+	 * @param selectionSymbol  The selectionSymbol to set.
+	 */
+	public void setSelectionSymbol(ISymbol selectionSymbol) {
+		this.selectionSymbol = selectionSymbol;
+	}
+	/**
+	 * Sets the style for the simple marker symbol
+	 * @param style
+	 */
+	public void setStyle(int style) {
+		this.markerStyle = style;
+	}
+
+	/**
+	 * Obtains the style for the simple marker symbol
+	 * @return markerStyle,int
+	 */
+	public int getStyle() {
+		return markerStyle;
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		SimpleMarkerSymbol copy = (SimpleMarkerSymbol) super.clone();
+		
+		// clone selection
+		if (selectionSymbol != null) {
+			copy.selectionSymbol = (ISymbol) selectionSymbol.clone();
+		}
+		
+		return copy;
+	}
+
+	/**
+	 * Returns if the marker symbol should be drawn outlined.
+	 * @return if it is outlined
+	 */
+	public boolean isOutlined() {
+		return outlined;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setStyle(state.getInt(FIELD_MARKERSTYLE));
+		setOutlined(state.getBoolean(FIELD_OUTLINED));
+		if (isOutlined()) {
+			setOutlineColor((Color) state.get(FIELD_OUTLINECOLOR));
+			setOutlineSize(state.getDouble(FIELD_OUTLINESIZE));
+		}
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		state.set(FIELD_MARKERSTYLE, getStyle());
+		state.set(FIELD_OUTLINED, isOutlined());
+		if (isOutlined()) {
+			state.set(FIELD_OUTLINECOLOR, getOutlineColor());
+			state.set(FIELD_OUTLINESIZE, getOutlineSize());
+		}
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleFillSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SimpleMarkerSymbol.class,
+				SIMPLE_MARKER_SYMBOL_DYNCLASS_NAME,
+				SIMPLE_MARKER_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the FillSymbol base definition
+		definition.extend(MARKER_SYMBOL_DYNCLASS_NAME);
+
+		// Marker style
+		definition.addDynFieldInt(FIELD_MARKERSTYLE).setMandatory(true);
+		// Outlined?
+		definition.addDynFieldBoolean(FIELD_OUTLINED).setMandatory(true);
+		// Outline color
+		definition.addDynFieldObject(FIELD_OUTLINECOLOR);
+		// Outline size
+		definition.addDynFieldDouble(FIELD_OUTLINESIZE);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/ArrowMarkerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/ArrowMarkerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/ArrowMarkerSymbol.java	(revision 33580)
@@ -0,0 +1,166 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+
+/**
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class ArrowMarkerSymbol extends AbstractMarkerSymbol implements CartographicSupport {
+
+	public static final String ARROW_MARKER_SYMBOL_DYNCLASS_NAME = "ArrowMarkerSymbol";
+	
+	private static final String FIELD_SHARPNESS = "sharpness"; 
+
+	private ArrowMarkerSymbol symSel;
+	private double sharpeness;
+
+	public ISymbol getSymbolForSelection() {
+		if (symSel == null) {
+			symSel = new ArrowMarkerSymbol();
+			symSel.setColor(MapContext.getSelectionColor());
+
+		}
+
+		return symSel;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	/**
+	 * To get the sharpeness attribute.It will determine the final form of the arrow
+	 * @return
+	 */
+	public double getSharpness() {
+		return sharpeness;
+	}
+
+	/**
+	 * To set the sharpeness.It will determine the final form of the arrow
+	 * @param sharpeness, the value of the arrow's edge angle IN RADIANS
+	 * @see #getSharpeness()
+	 */
+	public void setSharpness(double sharpeness) {
+		this.sharpeness = sharpeness;
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+
+		Point p = (Point) geom;
+		double radian_half_sharpeness = Math.toRadians(getSharpness()*.5); //
+
+		double size = getSize();
+		double halfHeight = size * Math.tan(radian_half_sharpeness);
+		double theta = getRotation();
+
+		g.setColor(getColor());
+
+		g.setStroke(new BasicStroke());
+
+		if (p == null) {
+			return;
+		}
+		GeneralPathX gp = new GeneralPathX();
+		gp.moveTo(0, 0);
+		gp.lineTo(size, -halfHeight);
+		gp.lineTo(size, halfHeight);
+		gp.closePath();
+
+		try {
+			g.translate(p.getX(), p.getY());
+		} catch (NullPointerException npEx) {
+			return;
+		}
+		g.rotate(theta);
+
+		g.fill(gp);
+		g.rotate(-theta);
+		g.translate(-p.getX(), -p.getY());
+
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		ArrowMarkerSymbol copy  = (ArrowMarkerSymbol) super.clone();
+		
+		// Clone the selection symbol
+		if (symSel != null) {
+			copy.symSel = (ArrowMarkerSymbol) symSel.clone();
+		}
+		return copy;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setSharpness(state.getDouble(FIELD_SHARPNESS));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		state.set(FIELD_SHARPNESS, getSharpness());
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleFillSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				ArrowMarkerSymbol.class,
+				ARROW_MARKER_SYMBOL_DYNCLASS_NAME,
+				ARROW_MARKER_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the FillSymbol base definition
+		definition.extend(MARKER_SYMBOL_DYNCLASS_NAME);
+
+		// Sharpeness
+		definition.addDynFieldDouble(FIELD_SHARPNESS).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/AbstractMarkerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/AbstractMarkerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/AbstractMarkerSymbol.java	(revision 33580)
@@ -0,0 +1,280 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.Geometry.TYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Abstract class that any MARKER SYMBOL should extend.
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractMarkerSymbol extends AbstractSymbol implements IMarkerSymbol {
+    
+    public static final String MARKER_SYMBOL_DYNCLASS_NAME = "MarkerSymbol";    
+    
+    private static final String FIELD_COLOR = "color";
+
+    private static final String FIELD_ROTATION = "rotation";
+
+    private static final String FIELD_OFFSET = "offset";
+
+    private static final String FIELD_SIZE = "size";
+    
+    private static final String FIELD_MASK = "mask";
+    
+    	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private Color color;
+	private double rotation;
+	private Point2D offset = new Point2D.Double();
+	private double size = 4d;
+	private IMask mask;
+
+	public AbstractMarkerSymbol() {
+		super();
+		color =
+				MapContextLocator.getSymbolManager()
+						.getSymbolPreferences()
+						.getDefaultSymbolColor();
+	}
+
+	public final int getSymbolType() {
+		return Geometry.TYPES.POINT;
+	}
+
+	public double getRotation() {
+		return rotation;
+	}
+
+	public void setRotation(double r) {
+		this.rotation = r;
+	}
+
+	public Point2D getOffset() {
+		if (offset == null) {
+			offset = new Point();
+		}
+		return offset;
+	}
+
+	public void setOffset(Point2D offset) {
+		this.offset = offset;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return geom.getType() == Geometry.TYPES.POINT;
+	}
+
+	public int getOnePointRgb() {
+		return color.getRGB();
+	}
+
+	public double getSize() {
+		return size;
+	}
+
+	public void setSize(double size) {
+		this.size = size;
+	}
+
+	public Color getColor() {
+		return color;
+	}
+
+	public void setColor(Color color) {
+		this.color = color;
+	}
+
+	public void setAlpha(int outlineAlpha) {
+		Color color = getColor();
+		setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(),
+				outlineAlpha));
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
+		float cs = (float) getCartographicSize(viewPort, dpi, geom);
+		distances[0] = cs;
+		distances[1] = cs;
+	}
+
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		double originalSize = getSize();
+		double size=originalSize;
+		// scale it to size
+		int pq = properties.getPrintQuality();
+		if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
+			size *= (double) 300/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
+			size *= (double) 600/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
+			// size *= 72/72; // (which is the same than doing nothing)
+		}
+//		setSize(size);
+		draw(g,at,geom, null, null);
+//		setSize(originalSize);
+	}
+
+	public final IMask getMask() {
+		return mask;
+	}
+
+	public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		try {
+			if (properties==null)
+				draw(g, scaleInstance, geomManager.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), null, null);
+			else{
+				double originalSize = getSize();
+				double size=originalSize;
+				int pq = properties.getPrintQuality();
+				if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
+					size *= (double) 300/72;
+				}else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
+					size *= (double) 600/72;
+				}else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
+					// d *= 72/72; // (which is the same than doing nothing)
+				}
+				setSize(size);
+				print(g, scaleInstance, geomManager.createPoint(r.getCenterX(), r.getCenterY(), SUBTYPES.GEOM2D), properties);
+				setSize(originalSize);
+			}
+
+
+
+		} catch (CreateGeometryException e) {
+			throw new SymbolDrawingException(TYPES.POINT);
+		}
+	}
+
+	public final void setMask(IMask mask) {
+		this.mask = mask;
+	}
+
+
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		setSize(cartographicSize);
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		double oldSize = getSize();
+		setCartographicSize(getCartographicSize(
+								viewPort,
+								dpi,
+								geom),
+							geom);
+		return oldSize;
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		return CartographicSupportToolkit.
+					getCartographicLength(this,
+										  getSize(),
+										  viewPort,
+										  dpi);
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		AbstractMarkerSymbol copy  = (AbstractMarkerSymbol) super.clone();
+		
+		// Clone the offset
+		if (offset != null) {
+			copy.offset = (Point2D) offset.clone();
+		}
+		
+		// clone the mask
+		if (mask != null) {
+			copy.mask = (IMask) mask.clone();
+		}
+		return copy;
+	}
+	
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		setColor((Color) state.get(FIELD_COLOR));
+		setMask((IMask) state.get(FIELD_MASK));
+		setOffset((Point2D) state.get(FIELD_OFFSET));
+		setRotation(state.getDouble(FIELD_ROTATION));
+		setSize(state.getDouble(FIELD_SIZE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent symbol properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_COLOR, getColor());
+		state.set(FIELD_MASK, getMask());
+		state.set(FIELD_OFFSET, getOffset());
+		state.set(FIELD_ROTATION, getRotation());
+		state.set(FIELD_SIZE, getSize());
+	}
+
+	public static void registerPersistence() {
+		// Add the AbstractMarkerSymbol DynClass definition.
+		DynClass dynClass = ToolsLocator.getDynObjectManager().add(
+				MARKER_SYMBOL_DYNCLASS_NAME);
+
+		// Extend the Symbol base definition
+		dynClass.extend(SYMBOL_PERSISTENCE_DEFINITION_NAME);
+
+		// Color
+		dynClass.addDynFieldObject(FIELD_COLOR).setMandatory(true);
+		// Mask
+		dynClass.addDynFieldObject(FIELD_MASK).setMandatory(true);
+
+		// Offset
+		dynClass.addDynFieldObject(FIELD_OFFSET).setMandatory(true);
+
+		// Rotation
+		dynClass.addDynFieldDouble(FIELD_ROTATION).setMandatory(true);
+
+		// Size
+		dynClass.addDynFieldDouble(FIELD_SIZE).setMandatory(true);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/MultiLayerMarkerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/MultiLayerMarkerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/marker/impl/MultiLayerMarkerSymbol.java	(revision 33580)
@@ -0,0 +1,408 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.gvsig.utils.XMLEntity;
+import org.gvsig.utils.XMLException;
+
+/**
+ * MultiLayerMarkerSymbol allows to group several marker symbols (xxxMarkerSymbol
+ * implementing IMarkerSymbol)in one and treat it as an only one symbol.
+ *
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class MultiLayerMarkerSymbol extends AbstractMarkerSymbol implements IMarkerSymbol, IMultiLayerSymbol {
+
+    public static final String MULTILAYER_MARKER_SYMBOL_DYNCLASS_NAME = "MultiLayerMarkerSymbol";
+    
+    private static final String FIELD_LAYERS = "layers";
+    private static final String FIELD_ROTATION = "rotation";
+
+    private IMarkerSymbol[] layers = new IMarkerSymbol[0];
+	private MultiLayerMarkerSymbol selectionSymbol;
+	private double markerSize;
+	private double rotation;
+	public Color getColor() {
+		/*
+		 * a multilayer symbol does not define any color, the color
+		 * of each layer is defined by the layer itself
+		 */
+		return null;
+	}
+
+	public double getRotation() {
+		return rotation;
+	}
+
+	public void setColor(Color color) {
+		/*
+		 * will apply the color to each layer
+		 */
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setColor(color);
+		}
+	}
+
+	public void setRotation(double rotation) {
+		this.rotation = rotation;
+	}
+
+	public double getSize() {
+		double myMarkerSize = 0;
+
+		for (int i = 0; i < getLayerCount(); i++) {
+			myMarkerSize = Math.max(myMarkerSize, ((IMarkerSymbol) getLayer(i)).getSize());
+		}
+
+		if (markerSize != myMarkerSize) {
+			markerSize = myMarkerSize;
+		}
+		return markerSize;
+	}
+
+	public void setSize(double size) {
+		if (size > 0 && size != getSize()) {
+
+			double scale = size / getSize();
+			this.markerSize = size;
+			for (int i = 0; layers != null && i < layers.length; i++) {
+				double lSize = layers[i].getSize();
+				layers[i].setSize(lSize*scale);
+			}
+		}
+	}
+
+
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		Point p = (Point) geom;
+		g.rotate(rotation, p.getX(), p.getY());
+		for (int i = 0; (cancel == null || !cancel.isCanceled())
+				&& layers != null && i < layers.length; i++) {
+			layers[i].draw(g, affineTransform, geom, feature, cancel);
+		}
+		g.rotate(-rotation, p.getX(), p.getY());
+	}
+
+	public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		g.rotate(rotation, r.getCenterX(), r.getCenterY());
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].drawInsideRectangle(g, scaleInstance, r, properties);
+		}
+		g.rotate(-rotation, r.getCenterX(), r.getCenterY());
+	}
+
+	public int getOnePointRgb() {
+		// will paint only the last layer pixel
+		return layers[layers.length-1].getOnePointRgb();
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		float[] myDistances = new float[] {0,0};
+		distances[0] = 0;
+		distances[1] = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].getPixExtentPlus(geom, myDistances, viewPort, dpi);
+			distances[0] = Math.max(myDistances[0], distances[0]);
+			distances[1] = Math.max(myDistances[1], distances[1]);
+		}
+	}
+
+	public ISymbol getSymbolForSelection() {
+		if (selectionSymbol == null) {
+			selectionSymbol = new MultiLayerMarkerSymbol();
+			selectionSymbol.setDescription(getDescription());
+			for (int i = 0; layers != null && i < layers.length; i++) {
+				selectionSymbol.addLayer(layers[i].getSymbolForSelection());
+			}
+		}
+		return selectionSymbol;
+
+	}
+
+
+	public XMLEntity getXMLEntity() throws XMLException {
+		XMLEntity xml = new XMLEntity();
+
+//		xml.putProperty("className", getClass().getName());
+//		xml.putProperty("isShapeVisible", isShapeVisible());
+//		xml.putProperty("desc", getDescription());
+//		xml.putProperty("size",	getSize());
+//		xml.putProperty("unit", getUnit());
+//		xml.putProperty("referenceSystem", getReferenceSystem());
+//		for (int i = 0; i < layers.length; i++) {
+//			xml.addChild(layers[i].getXMLEntity());
+//		}
+		return xml;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return geom.getType() == Geometry.TYPES.POINT;
+	}
+
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	/**
+	 * TODO: replace with the new Persistence API
+	 */
+	public void setXMLEntity(XMLEntity xml) {
+//		setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
+//		setDescription(xml.getStringProperty("desc"));
+//		setSize(xml.getDoubleProperty("size"));
+//		setUnit(xml.getIntProperty("unit"));
+//		setReferenceSystem(xml.getIntProperty("referenceSystem"));
+//		for (int i = 0; i < xml.getChildrenCount(); i++) {
+//			addLayer(SymbologyFactory.createSymbolFromXML(xml.getChild(i), "layer" + i));
+//		}
+	}
+
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].print(g, at, geom, properties);
+		}
+
+	}
+
+	public void setLayer(int index, ISymbol layer) throws IndexOutOfBoundsException {
+		layers[index] = (IMarkerSymbol) layer;
+	}
+
+	public void swapLayers(int index1, int index2) {
+		ISymbol aux1 = getLayer(index1), aux2 = getLayer(index2);
+		layers[index2] = (IMarkerSymbol) aux1;
+		layers[index1] = (IMarkerSymbol) aux2;
+	}
+
+	public ISymbol getLayer(int layerIndex) {
+//		try{
+			return layers[layerIndex];
+//		} catch (Exception e) {
+//			return null;
+//		}
+	}
+
+	public int getLayerCount() {
+		return layers.length;
+	}
+
+	public void addLayer(ISymbol newLayer) {
+		addLayer(newLayer, layers.length);
+	}
+
+	public void addLayer(ISymbol newLayer, int layerIndex) throws IndexOutOfBoundsException {
+		if (newLayer == null ) {
+			/*|| newLayer instanceof ILabelStyle)*/ return; // null or symbols that are styles are not allowed
+		}
+
+		IMarkerSymbol newMarker = (IMarkerSymbol) newLayer;
+		if (getLayerCount() == 0) {
+			// apply the new layer properties to this multilayer
+
+			setReferenceSystem(newMarker.getReferenceSystem());
+			markerSize = newMarker.getSize();
+			//setSize(newMarker.getSize());
+			setUnit(newMarker.getUnit());
+		} else {
+			if (newMarker.getSize() > getSize()) {
+				//setSize(newMarker.getSize());
+				markerSize = newMarker.getSize();
+			}
+			newMarker.setReferenceSystem(getReferenceSystem());
+			newMarker.setUnit(getUnit());
+		}
+		selectionSymbol = null; /* forces the selection symbol to be re-created
+		 						 * next time it is required
+		 						 */
+		if (layerIndex < 0 || layers.length < layerIndex) {
+			throw new IndexOutOfBoundsException(layerIndex+" < 0 or "+layerIndex+" > "+layers.length);
+		}
+		List<ISymbol> newLayers = new ArrayList<ISymbol>();
+		for (int i = 0; i < layers.length; i++) {
+			newLayers.add(layers[i]);
+		}
+		try {
+			newLayers.add(layerIndex, newLayer);
+			layers = (IMarkerSymbol[]) newLayers.toArray(new IMarkerSymbol[0]);
+		} catch (ArrayStoreException asEx) {
+			throw new ClassCastException(newLayer.getClass().getName()+" is not an IMarkerSymbol");
+		}
+	}
+
+	public boolean removeLayer(ISymbol layer) {
+
+		int capacity = 0;
+		capacity = layers.length;
+		List<ISymbol> lst = new ArrayList<ISymbol>(capacity);
+		for (int i = 0; i < capacity; i++) {
+			lst.add(layers[i]);
+		}
+		boolean contains = lst.remove(layer);
+		layers = (IMarkerSymbol[])lst.toArray(new IMarkerSymbol[0]);
+		return contains;
+	}
+
+	public void setUnit(int unit) {
+		super.setUnit(unit);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setUnit(unit);
+		}
+	}
+
+	public void setReferenceSystem(int system) {
+		super.setReferenceSystem(system);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setReferenceSystem(system);
+		}
+	}
+
+	public void setAlpha(int alpha) {
+		// first, get the biggest alpha in the layers and the index if such layer
+		int maxAlpha = Integer.MIN_VALUE;
+		int maxAlphaLayerIndex = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			if (layers[i].getColor().getAlpha() > maxAlpha) {
+				maxAlpha = layers[i].getColor().getAlpha();
+				maxAlphaLayerIndex = i;
+			}
+		}
+
+		// now, max alpha takes the value of the desired alpha and the rest
+		// will take a scaled (to biggest alpha) alpha value
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			int r = layers[i].getColor().getRed();
+			int g = layers[i].getColor().getGreen();
+			int b = layers[i].getColor().getBlue();
+
+			if (i!=maxAlphaLayerIndex) {
+				double scaledAlpha = (double) layers[i].getColor().getAlpha()/maxAlpha;
+				int myAlpha = (int) (alpha*scaledAlpha);
+				if (myAlpha == 0) {
+					myAlpha = 1;
+				}
+				layers[i].setColor(new Color(r, g, b, myAlpha));
+			} else {
+				int myAlpha = alpha;
+				if (myAlpha == 0) {
+					myAlpha = 1;
+				}
+				layers[i].setColor(new Color(r, g, b, myAlpha));
+			}
+		}
+
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		MultiLayerMarkerSymbol copy = (MultiLayerMarkerSymbol) super.clone();
+
+		// Clone layers
+		if (layers != null) {
+			IMarkerSymbol[] layersCopy = new IMarkerSymbol[layers.length];
+			for (int i = 0; i < layers.length; i++) {
+				layersCopy[i] = (IMarkerSymbol) layers[i].clone();
+			}
+			copy.layers = layersCopy;
+		}
+
+		// Clone selection
+		if (selectionSymbol != null) {
+			copy.selectionSymbol = (MultiLayerMarkerSymbol) selectionSymbol
+					.clone();
+		}
+
+		return copy;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		List layers = state.getList(FIELD_LAYERS);
+		if (layers != null) {
+			for (int i = 0; i < layers.size(); i++) {
+				addLayer((ISymbol) layers.get(i));
+			}
+		}
+		setRotation(state.getDouble(FIELD_ROTATION));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+		// Save own properties
+		if (layers != null && layers.length > 0) {
+			state.set(FIELD_LAYERS, Arrays.asList(layers));
+		}
+		state.set(FIELD_ROTATION, getRotation());
+	}
+
+	public static void registerPersistence() {
+		// Add the MultiLayerMarkerSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				MultiLayerMarkerSymbol.class,
+				MULTILAYER_MARKER_SYMBOL_DYNCLASS_NAME,
+				MULTILAYER_MARKER_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the MarkerSymbol base definition
+		definition.extend(MARKER_SYMBOL_DYNCLASS_NAME);
+
+		// Layers
+		definition.addDynFieldList(FIELD_LAYERS);
+		// Rotation
+		definition.addDynFieldDouble(FIELD_ROTATION).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/text/impl/SimpleTextSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/text/impl/SimpleTextSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/text/impl/SimpleTextSymbol.java	(revision 33580)
@@ -0,0 +1,393 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SimpleTextSymbol is a class used to create symbols composed using a text defined by
+ * the user.This text can be edited (changing the color, the font of the characters, and
+ * the rotation of the text).
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SimpleTextSymbol extends AbstractSymbol implements ITextSymbol {
+	public static final String SIMPLE_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME = "SimpleTextSymbol";
+	
+	private static final String FIELD_TEXT = "text";
+	private static final String FIELD_FONT = "font";
+	private static final String FIELD_TEXT_COLOR = "textColor";
+	private static final String FIELD_ROTATION = "rotation";
+	private static final String FIELD_AUTO_RESIZE = "autoResize";
+
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private String text = "";
+
+	private Font font;
+
+	private Color textColor;
+	private double rotation;
+	private FontRenderContext frc = new FontRenderContext(
+			new AffineTransform(), false, true);
+	private boolean autoresize;
+	final static private Logger logger = LoggerFactory.getLogger(SimpleTextSymbol.class);
+
+	public SimpleTextSymbol() {
+		super();
+		SymbolPreferences preferences =
+				MapContextLocator.getSymbolManager().getSymbolPreferences();
+		font = preferences.getDefaultSymbolFont();
+		textColor = preferences.getDefaultSymbolColor();
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		if (!isShapeVisible()) {
+			return;
+		}
+		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+		g.setColor(textColor);
+		g.setFont(font);
+		g.translate(((org.gvsig.fmap.geom.primitive.Point) geom).getX(), ((org.gvsig.fmap.geom.primitive.Point) geom).getY());
+
+		g.rotate(rotation);
+		Rectangle2D bounds = getBounds();
+//		 getBounds devuelve el bounds de un texto dibujado de manera que
+		// la linea base de la primera letra est� en el punto (0,0).
+		// Por eso, si queremos alinear el texto de manera que la parte superior
+		// izquierda de la primera letra est� en (0,0) debemos moverlo seg�n
+		// el valor de la ordenada, en lugar de seg�n su altura.
+		g.drawString(getText(), 0, (int)-bounds.getY());//(int) bounds.getHeight());
+		g.rotate(-rotation);
+		g.translate(-((org.gvsig.fmap.geom.primitive.Point) geom).getX(), -((org.gvsig.fmap.geom.primitive.Point) geom).getY());
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		int s = getFont().getSize();
+		if (autoresize) {
+			if (s==0) {
+				s =1;
+				setFontSize(s);
+			}
+			g.setFont(getFont());
+		    FontMetrics fm = g.getFontMetrics();
+		    Rectangle2D rect = fm.getStringBounds(text, g);
+		    double width = rect.getWidth();
+		    double height = rect.getHeight();
+		    double rWidth = r.getWidth();
+		    double rHeight = r.getHeight();
+		    double ratioText = width/height;
+		    double ratioRect = rWidth/rHeight;
+
+		    if (ratioText>ratioRect) {
+		    	s = (int) (s*(rWidth/width));
+		    } else {
+		    	s = (int) (s*(rHeight/height));
+		    }
+//		    r.setLocation(r.x, (int) Math.round(r.getY()+r.getHeight()));
+		}
+		setFontSize(s);
+//		g.setColor(Color.red);
+//		g.draw(r);
+		try {
+			if (properties==null)
+				draw(g, null, geomManager.createPoint(r.getX(), r.getY(),
+						SUBTYPES.GEOM2D), null, null);
+			else
+				print(g, new AffineTransform(), geomManager.createPoint(r.getX(), r.getY(), SUBTYPES.GEOM2D), properties);
+		} catch (CreateGeometryException e) {
+			logger.error("Error creatint a point", e);
+			e.printStackTrace();
+		}
+
+
+	}
+
+	public int getOnePointRgb() {
+		return textColor.getRGB();
+	}
+
+	public void getPixExtentPlus(org.gvsig.fmap.geom.Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public ISymbol getSymbolForSelection() {
+		return this; // a text is not selectable
+	}
+
+	public int getSymbolType() {
+		return Geometry.TYPES.TEXT;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return true;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void print(Graphics2D g, AffineTransform at, org.gvsig.fmap.geom.Geometry geom, PrintAttributes properties){
+		float originalSize = getFont().getSize2D();
+		float size=originalSize;
+		// scale it to size
+		int pq = properties.getPrintQuality();
+		if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
+			size *= (double) 300/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
+			size *= (double) 600/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
+			// d *= 72/72; // (which is the same than doing nothing)
+		}
+		setFont(getFont().deriveFont(size));
+		draw(g,at,geom, null, null);
+		setFont(getFont().deriveFont(originalSize));
+	}
+
+	public String getText() {
+		return text;
+	}
+
+	public Font getFont() {
+		return font;
+	}
+
+	public Color getTextColor() {
+		return textColor;
+	}
+
+	public void setText(String text) {
+		this.text = text;
+	}
+
+	public void setFont(Font font) {
+		if (font == null) {
+			logger.warn("font <-- null");
+
+			return;
+		}
+		this.font = font;
+	}
+
+	public void setTextColor(Color color) {
+		this.textColor = color;
+	}
+	
+	public Color getColor() {
+		return getTextColor();
+	}
+	
+	public void setColor(Color color) {
+		setTextColor(color);
+	}
+
+	public void setFontSize(double size) {
+		Font newFont = new Font(font.getName(), font.getStyle(), (int) size);
+//		if (newFont == null) {
+//			logger.warn(
+//					"Font(" + font.getName() + ", "
+//					+ font.getStyle() + ", " + (int) size + " --> null");
+//		} else {
+			this.font = newFont;
+//		}
+	}
+
+	public double getRotation() {
+		return rotation;
+	}
+
+	/**
+	 * Defines the angle of rotation for the text that composes the symbol
+	 *
+	 * @param rotation
+	 */
+	public void setRotation(double rotation) {
+		this.rotation = rotation;
+	}
+
+	/**
+	 * Returns an Geometry which represents a rectangle containing the text in
+	 * <b>screen</b> units.
+	 */
+	public Geometry getTextWrappingShape(org.gvsig.fmap.geom.primitive.Point p) {
+		Font font = getFont();
+		GlyphVector gv = font.createGlyphVector(frc, text);
+
+		Shape shape = gv.getOutline((float) p.getX(), (float) p.getY());
+		Geometry myFShape;
+		try {
+			myFShape = geomManager.createSurface(new GeneralPathX(shape
+					.getBounds2D().getPathIterator(null)), SUBTYPES.GEOM2D);
+			myFShape.transform(AffineTransform.getTranslateInstance(p.getX(), p.getY()));
+
+			if (rotation != 0) {
+				myFShape.transform(AffineTransform.getRotateInstance(rotation));
+			}
+			return myFShape;
+		} catch (CreateGeometryException e) {
+			logger.error("Error creating a surface", e);
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	public Rectangle getBounds() {
+//		FontMetrics fm = g.getFontMetrics();
+//		Rectangle2D rect = fm.getStringBounds("graphics", g);
+
+		Rectangle bounds = null;
+		try {
+			bounds = getTextWrappingShape(geomManager.createPoint(0,0, SUBTYPES.GEOM2D)).getBounds();
+		} catch (CreateGeometryException e) {
+			logger.error("Error creating a point", e);
+		}
+		return bounds;
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		setFontSize(cartographicSize);
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		double oldSize = getFont().getSize();
+		setCartographicSize(getCartographicSize(
+								viewPort,
+								dpi,
+								geom),
+							geom);
+		return oldSize;
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		return CartographicSupportToolkit.
+					getCartographicLength(this,
+										  getFont().getSize(),
+										  viewPort,
+										  dpi);
+	}
+	public boolean isAutoresizeEnabled() {
+		return autoresize;
+	}
+
+	public void setAutoresizeEnabled(boolean autoresizeFlag) {
+		this.autoresize = autoresizeFlag;
+	}
+
+	public void loadFromState(PersistentState state)
+	
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+
+		// Set own properties
+		setAutoresizeEnabled(state.getBoolean(FIELD_AUTO_RESIZE));
+		setFont((Font) state.get(FIELD_FONT));
+		setRotation(state.getDouble(FIELD_ROTATION));
+		setText(state.getString(FIELD_TEXT));
+		setTextColor((Color) state.get(FIELD_TEXT_COLOR));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+
+		// Save own properties
+		state.set(FIELD_AUTO_RESIZE, isAutoresizeEnabled());
+		state.set(FIELD_FONT, getFont());
+		state.set(FIELD_ROTATION, getRotation());
+		state.set(FIELD_TEXT, getText());
+		state.set(FIELD_TEXT_COLOR, getTextColor());
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleTextSymbol persistence definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SimpleTextSymbol.class,
+				SIMPLE_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME,
+				SIMPLE_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the Symbol base definition
+		definition.extend(SYMBOL_PERSISTENCE_DEFINITION_NAME);
+
+		// Auto resize?
+		definition.addDynFieldBoolean(FIELD_AUTO_RESIZE)
+			.setMandatory(true);
+		
+		// Font
+		definition.addDynFieldObject(FIELD_FONT)
+			.setClassOfValue(Font.class)
+			.setMandatory(true);
+		
+		// Rotation
+		definition.addDynFieldDouble(FIELD_ROTATION)
+			.setMandatory(true);
+		
+		// Text
+		definition.addDynFieldString(FIELD_TEXT);
+		
+		// Text color
+		definition.addDynFieldObject(FIELD_TEXT_COLOR)
+			.setClassOfValue(Color.class)
+			.setMandatory(true);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/warning/impl/WarningSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/warning/impl/WarningSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/warning/impl/WarningSymbol.java	(revision 33580)
@@ -0,0 +1,245 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.warning.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.VectorialUniqueValueLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.MultiShapeSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+
+/**
+ * Warning symbol
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class WarningSymbol extends MultiShapeSymbol implements IWarningSymbol {
+
+	public static final String WARNING_SYMBOL_DYNCLASS_NAME = "WarningSymbol";
+
+	private static final String FIELD_DESCRIPTION = "description";
+	private static final String FIELD_MESSAGE = "message";
+	private static final String FIELD_EXCEPTION_TYPE = "exceptionType";
+
+	private String message;
+	private int exceptionType;
+	private SimpleTextSymbol text;
+
+	/**
+	 * Empty constructor, only used in persistence.
+	 */
+	public WarningSymbol() {
+		// Nothing to do
+	}
+
+	public WarningSymbol(String message, String symbolDesc,
+			int symbolDrawExceptionType) {
+		this.message = message;
+		this.exceptionType = symbolDrawExceptionType;
+		setDescription(symbolDesc);
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Cancellable cancel) {
+		try {
+			drawInsideRectangle(g, g.getTransform(), geom.getBounds(), null);
+		} catch (SymbolDrawingException e) {
+			// IMPOSSIBLE
+		}
+	}
+
+	public void setDrawExceptionType(int symbolDrawExceptionType) {
+		this.exceptionType = symbolDrawExceptionType;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	private String getMessage() {
+		return message;
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r,
+			PrintAttributes properties) throws SymbolDrawingException {
+		g.setClip(r);
+		if (message == null) {
+			message = "Symbol undrawable.\nPlease, check errors.";
+		}
+
+		String[] messageLines = CompatLocator.getStringUtils().split(message,
+				"\n");
+		int strokeWidth = (int) (Math.min(r.width, r.height) * .1);
+
+		if (strokeWidth == 0) {
+			strokeWidth = 1;
+		}
+		g.setColor(Color.red);
+		g.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_BUTT,
+				BasicStroke.JOIN_ROUND));
+		int width = r.width - (strokeWidth + strokeWidth);
+		int height = r.height - (strokeWidth + strokeWidth);
+		double radius = Math.min(width, height) * .5;
+		double centerX = r.getCenterX();
+		double centerY = r.getCenterY();
+		Ellipse2D circle = new Ellipse2D.Double(centerX - radius, centerY
+				- radius, 2 * radius, 2 * radius);
+		g.draw(circle);
+		g.setClip(circle);
+		double aux = Math.cos(Math.PI * 0.25) * radius;
+		g.drawLine((int) (centerX - aux), (int) (centerY - aux),
+				(int) (centerX + aux), (int) (centerY + aux));
+		int fontSize = 20;
+		g.setFont(new Font("Arial", fontSize, Font.PLAIN));
+		g.setColor(Color.black);
+		g.setClip(null);
+
+		if (text == null) {
+			text = new SimpleTextSymbol();
+			text.setAutoresizeEnabled(true);
+
+		}
+
+		double lineHeight = (r.getHeight() - 6) / messageLines.length;
+		Rectangle textRect = new Rectangle((int) r.getMinX(),
+				(int) r.getMinY() + 6, (int) r.getWidth(), (int) lineHeight);
+		for (int i = 0; i < messageLines.length; i++) {
+			text.setText(messageLines[i]);
+			text.drawInsideRectangle(g, null, textRect, null);
+			textRect.setLocation((int) r.getX(), (int) (r.getY() + r
+					.getHeight()));
+		}
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		WarningSymbol copy = (WarningSymbol) super.clone();
+
+		if (text != null) {
+			copy.text = (SimpleTextSymbol) text.clone();
+		}
+
+		return copy;
+	}
+
+	/**
+	 * @return the exceptionType
+	 */
+	private int getExceptionType() {
+		return exceptionType;
+	}
+
+	/**
+	 * @param exceptionType
+	 *            the exceptionType to set
+	 */
+	private void setExceptionType(int exceptionType) {
+		this.exceptionType = exceptionType;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setDescription(state.getString(FIELD_DESCRIPTION));
+		setExceptionType(state.getInt(FIELD_EXCEPTION_TYPE));
+		setMessage(state.getString(FIELD_MESSAGE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_DESCRIPTION, getDescription());
+		state.set(FIELD_EXCEPTION_TYPE, getExceptionType());
+		state.set(FIELD_MESSAGE, getMessage());
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				WarningSymbol.class,
+				WARNING_SYMBOL_DYNCLASS_NAME,
+				WARNING_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Description
+		definition.addDynFieldString(FIELD_DESCRIPTION).setMandatory(true);
+		// Exception type
+		definition.addDynFieldInt(FIELD_EXCEPTION_TYPE).setMandatory(true);
+		// Message
+		definition.addDynFieldString(FIELD_MESSAGE).setMandatory(true);
+	}
+
+	// public static void main(String[] args) {
+	// MapContextImplLibrary mapContextImplLibrary = new
+	// MapContextImplLibrary();
+	// SECompatLibrary compatLibrary = new SECompatLibrary();
+	// DefaultGeometryLibrary geometryLibrary = new DefaultGeometryLibrary();
+	//		
+	// mapContextImplLibrary.initialize();
+	// compatLibrary.initialize();
+	// geometryLibrary.initialize();
+	// mapContextImplLibrary.postInitialize();
+	// compatLibrary.postInitialize();
+	// geometryLibrary.postInitialize();
+	//		
+	// JFrame f = new JFrame();
+	// final ISymbol warning = new WarningSymbol(
+	// SymbolDrawingException.STR_UNSUPPORTED_SET_OF_SETTINGS,
+	// "a description",
+	// SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS);
+	// JPanel preview = new JPanel() {
+	// protected void paintComponent(Graphics g) {
+	// // TODO Auto-generated method stub
+	// super.paintComponent(g);
+	// Graphics2D g2 = (Graphics2D) g;
+	// try {
+	// warning.drawInsideRectangle(g2, g2.getTransform(),
+	// getBounds(), null);
+	// } catch (SymbolDrawingException e) {
+	// // TODO Auto-generated catch block
+	// e.printStackTrace();
+	// }
+	// }
+	// };
+	// f.setContentPane(preview);
+	// f.pack();
+	// f.setVisible(true);
+	// }
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/AbstractFillSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/AbstractFillSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/AbstractFillSymbol.java	(revision 33580)
@@ -0,0 +1,229 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl;
+
+import java.awt.Color;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Abstract class that any FILL SYMBOL should extend
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractFillSymbol extends AbstractSymbol implements
+		IFillSymbol {
+
+	public static final String FILL_SYMBOL_DYNCLASS_NAME = "FillSymbol";
+
+	private static final String FIELD_OUTLINE = "outline";
+
+	private static final String FIELD_HAS_OUTLINE = "hasOutline";
+
+	private static final String FIELD_HAS_FILL = "hasFill";
+
+	private static final String FIELD_COLOR = "color";
+
+	private boolean hasFill = true;
+	private boolean hasOutline = true;
+	private Color color;
+	private ILineSymbol outline;
+
+	public AbstractFillSymbol() {
+		super();
+		color =
+				MapContextLocator.getSymbolManager()
+						.getSymbolPreferences()
+						.getDefaultSymbolFillColor();
+
+		outline =
+				(ILineSymbol) MapContextLocator.getSymbolManager()
+				.createSymbol(ILineSymbol.SYMBOL_NAME);
+
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return geom.getType() == Geometry.TYPES.SURFACE;
+	}
+
+	public int getOnePointRgb() {
+		int rgb = 0;
+		if (outline != null) {
+			rgb = outline.getOnePointRgb();
+		} else if (color != null) {
+			rgb = color.getRGB();
+		}
+		return rgb;
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		if (getOutline() != null) {
+			getOutline().getPixExtentPlus(geom, distances, viewPort, dpi);
+		} else {
+			distances[0] = 0;
+			distances[1] = 0;
+		}
+	}
+
+	public void setFillColor(Color color) {
+		this.color = color;
+	}
+
+	public void setOutline(ILineSymbol outline) {
+		this.outline = outline;
+	}
+
+	public Color getFillColor() {
+		return color;
+	}
+
+	public ILineSymbol getOutline() {
+		return outline;
+	}
+
+	public int getFillAlpha() {
+		// TODO debatir si es correcto o no (por ejemplo cuando hablamos de
+		// LineFillSymbol's
+		if (color == null)
+			return 255;
+		return color.getAlpha();
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		if (getOutline() != null) {
+			getOutline().setLineWidth(cartographicSize);
+		}
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi,
+			Geometry geom) {
+		if (getOutline() != null) {
+			double oldSize = getOutline().getLineWidth();
+			setCartographicSize(getCartographicSize(viewPort, dpi, geom), geom);
+			return oldSize;
+		}
+		return 0;
+	}
+
+	public boolean hasFill() {
+		return hasFill;
+	}
+
+	public void setHasFill(boolean hasFill) {
+		this.hasFill = hasFill;
+	}
+
+	public boolean hasOutline() {
+		return hasOutline;
+	}
+
+	public void setHasOutline(boolean hasOutline) {
+		this.hasOutline = hasOutline;
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi,
+			Geometry geom) {
+		if (getOutline() != null) {
+			return CartographicSupportToolkit.getCartographicLength(this,
+					getOutline().getLineWidth(), viewPort, dpi);
+		}
+		return 0;
+	}
+
+	public void setUnit(int unitIndex) {
+		super.setUnit(unitIndex);
+		if (getOutline() != null) {
+			getOutline().setUnit(unitIndex);
+		}
+	}
+
+	public Color getColor() {
+		return getFillColor();
+	}
+
+	public void setColor(Color color) {
+		setFillColor(color);
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		IFillSymbol copy = (IFillSymbol) super.clone();
+		
+		// Clone outline
+		ILineSymbol outline = copy.getOutline();
+		if (outline != null) {
+			copy.setOutline((ILineSymbol) outline.clone());
+		}
+		return copy;
+	}
+	
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		setColor((Color) state.get(FIELD_COLOR));
+		setHasFill(state.getBoolean(FIELD_HAS_FILL));
+		setHasOutline(state.getBoolean(FIELD_HAS_OUTLINE));
+		setOutline((ILineSymbol) state.get(FIELD_OUTLINE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent symbol properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_COLOR, getColor());
+		state.set(FIELD_HAS_FILL, hasFill());
+		state.set(FIELD_HAS_OUTLINE, hasOutline());
+		state.set(FIELD_OUTLINE, getOutline());
+	}
+
+	public static void registerPersistence() {
+		// Add the AbstractFillSymbol DynClass definition.
+		DynClass dynClass = ToolsLocator.getDynObjectManager().add(
+				FILL_SYMBOL_DYNCLASS_NAME);
+
+		// Extend the Symbol base definition
+		dynClass.extend(SYMBOL_PERSISTENCE_DEFINITION_NAME);
+
+		// Color
+		dynClass.addDynFieldObject(FIELD_COLOR).setMandatory(true);
+		// Has fill?
+		dynClass.addDynFieldBoolean(FIELD_HAS_FILL).setMandatory(true);
+		// Has outline?
+		dynClass.addDynFieldBoolean(FIELD_HAS_OUTLINE).setMandatory(true);
+		// Outline
+		dynClass.addDynFieldObject(FIELD_OUTLINE);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/MultiLayerFillSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/MultiLayerFillSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/MultiLayerFillSymbol.java	(revision 33580)
@@ -0,0 +1,357 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+
+
+/**
+ * MultiLayerFillSymbol is a symbol which allows to group several kind of fill symbols
+ * (xxxFillSymbol implementing IFillSymbol)in one and treats it like single symbol.
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class MultiLayerFillSymbol extends AbstractFillSymbol implements IFillSymbol, IMultiLayerSymbol{
+    
+    public static final String MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME = "MultiLayerFillSymbol";
+//    private static final String FIELD_SYMBOL_FOR_SELECTION = "symbolForSelection";
+    private static final String FIELD_LAYERS = "layers";
+    
+	private static final double OPACITY_SELECTION_FACTOR = .8;
+	private IFillSymbol[] layers = new IFillSymbol[0];
+	private MultiLayerFillSymbol selectionSymbol;
+//	private Object symbolType;
+
+	public Color getFillColor() {
+		/*
+		 * a multilayer symbol does not define any color, the color
+		 * of each layer is defined by the layer itself
+		 */
+		return null;
+	}
+
+	public int getOnePointRgb() {
+		// will paint only the last layer pixel
+		return layers[layers.length-1].getOnePointRgb();
+	}
+
+	public ILineSymbol getOutline() {
+		/*
+		 * a multilayer symbol does not define any outline, the outline
+		 * of each layer is defined by the layer it self
+		 */
+		return null;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return geom.getType() == Geometry.TYPES.SURFACE;
+	}
+
+	public void setFillColor(Color color) {
+		/*
+		 * Will apply the color to each layer
+		 */
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setFillColor(color);
+		}
+	}
+
+	public void setOutline(ILineSymbol outline) {
+		if (layers != null && layers.length > 0) {
+			for (int i = 0; i < layers.length - 1; i++) {
+				layers[i].setOutline(null);
+			}
+			layers[layers.length - 1].setOutline(outline);
+		}
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		for (int i = 0; (cancel == null || !cancel.isCanceled())
+				&& layers != null && i < layers.length; i++) {
+			layers[i].draw(g, affineTransform, geom, feature, cancel);
+		}
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].drawInsideRectangle(g, scaleInstance, r, properties);
+		}
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		float[] myDistances = new float[] {0,0};
+		distances[0] = 0;
+		distances[1] = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].getPixExtentPlus(geom, myDistances, viewPort, dpi);
+			distances[0] = Math.max(myDistances[0], distances[0]);
+			distances[1] = Math.max(myDistances[1], distances[1]);
+		}
+	}
+
+	public ISymbol getSymbolForSelection() {
+	    // TODO: revisar
+	    
+		if (selectionSymbol == null) {
+		    	MultiLayerFillSymbol selectionSymbol = 
+		    	    new MultiLayerFillSymbol();
+			selectionSymbol.setDescription(getDescription());
+//			selectionSymbol.symbolType = symbolType;
+			for (int i = 0; layers != null && i < layers.length; i++) {
+				selectionSymbol.addLayer(layers[i].getSymbolForSelection());
+			}
+			SimpleFillSymbol selLayer = new SimpleFillSymbol();
+			Color c = MapContext.getSelectionColor();
+			c = new Color(
+					c.getRed(),
+					c.getGreen(),
+					c.getBlue(),
+					(int) (255*OPACITY_SELECTION_FACTOR));
+			selLayer.setFillColor(c);
+			selLayer.setOutline(getOutline());
+			selectionSymbol.addLayer(selLayer);
+			setSymbolForSelection(selectionSymbol);
+		}
+		return selectionSymbol;
+
+	}
+
+	public int getSymbolType() {
+		return Geometry.TYPES.SURFACE;
+	}
+
+	public void setPrintingProperties(PrintAttributes printProperties) {
+		// TODO Implement it
+		throw new Error("Not yet implemented!");
+
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].print(g, at, geom, properties);
+		}
+	}
+
+	public void setLayer(int index, ISymbol layer) throws IndexOutOfBoundsException {
+		layers[index] = (IFillSymbol) layer;
+	}
+
+	public void swapLayers(int index1, int index2) {
+		ISymbol aux1 = getLayer(index1), aux2 = getLayer(index2);
+		layers[index2] = (IFillSymbol) aux1;
+		layers[index1] = (IFillSymbol) aux2;
+	}
+
+	public ISymbol getLayer(int layerIndex) {
+//		try{
+			return layers[layerIndex];
+//		} catch (Exception e) {
+//			return null;
+//		}
+	}
+
+	public int getLayerCount() {
+		return layers.length;
+	}
+
+	public void addLayer(ISymbol newLayer) {
+		addLayer(newLayer, layers.length);
+	}
+
+	public void addLayer(ISymbol newLayer, int layerIndex) throws IndexOutOfBoundsException {
+		if (newLayer == null ) {
+			/*|| newLayer instanceof ILabelStyle)*/ return; // null or symbols that are styles are not allowed
+		}
+
+		selectionSymbol = null; /* forces the selection symbol to be re-created
+		 						 * next time it is required
+		 						 */
+		if (layerIndex < 0 || layers.length < layerIndex) {
+			throw new IndexOutOfBoundsException(layerIndex+" < 0 or "+layerIndex+" > "+layers.length);
+		}
+		List<ISymbol> newLayers = new ArrayList<ISymbol>();
+		for (int i = 0; i < layers.length; i++) {
+			newLayers.add(layers[i]);
+		}
+		try {
+			newLayers.add(layerIndex, newLayer);
+			layers = (IFillSymbol[]) newLayers.toArray(new IFillSymbol[0]);
+		} catch (ArrayStoreException asEx) {
+			throw new ClassCastException(newLayer.getClass().getName() + " is not an IFillSymbol");
+		}
+	}
+
+	public boolean removeLayer(ISymbol layer) {
+
+		int capacity = 0;
+		capacity = layers.length;
+		List<IFillSymbol> lst = new ArrayList<IFillSymbol>(capacity);
+		for (int i = 0; layers != null && i < capacity; i++) {
+			lst.add(layers[i]);
+		}
+		boolean contains = lst.remove(layer);
+		layers = (IFillSymbol[])lst.toArray(new IFillSymbol[0]);
+		return contains;
+	}
+	
+	public void setUnit(int unitIndex) {
+		super.setUnit(unitIndex);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setUnit(unitIndex);
+		}
+	}
+
+	public void setReferenceSystem(int system) {
+		super.setReferenceSystem(system);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setReferenceSystem(system);
+		}
+	}
+
+	/**
+	 *Returns the transparency of the multi layer fill symbol created
+	 */
+	public int getFillAlpha() {
+		// will compute the acumulated opacity
+		double myAlpha = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			double layerAlpha = layers[i].getFillAlpha()/255D;
+			myAlpha += (1-myAlpha)*layerAlpha;
+		}
+		int result = (int) Math.round(myAlpha * 255);
+		return (result>255) ? 255 : result;
+	}
+
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		double size = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			size = Math.max(size, layers[i].toCartographicSize(viewPort, dpi, geom));
+		}
+		return size;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		MultiLayerFillSymbol copy = (MultiLayerFillSymbol) super.clone();
+
+		// Clone layers
+		if (layers != null) {
+			IFillSymbol[] layersCopy = new IFillSymbol[layers.length];
+			for (int i = 0; i < layers.length; i++) {
+				layersCopy[i] = (IFillSymbol) layers[i].clone();
+			}
+			copy.layers = layersCopy;
+		}
+
+		// Clone selection
+		if (selectionSymbol != null) {
+			copy.selectionSymbol = (MultiLayerFillSymbol) selectionSymbol
+					.clone();
+		}
+
+		return copy;
+	}
+
+	private void setSymbolForSelection(MultiLayerFillSymbol symbolForSelection) {
+		this.selectionSymbol = symbolForSelection;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		// setSymbolForSelection((MultiLayerFillSymbol)
+		// state.get(FIELD_SYMBOL_FOR_SELECTION));
+		List layers = state.getList(FIELD_LAYERS);
+		if (layers != null) {
+			for (int i = 0; i < layers.size(); i++) {
+				addLayer((ISymbol) layers.get(i));
+			}
+		}
+
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+		// Save own properties
+
+		// Don't use the getSymbolForSelection method, as it will create it
+		// if it does not exist, and persistence will enter an infinite loop
+		// state.set(FIELD_SYMBOL_FOR_SELECTION, selectionSymbol);
+		state.set(FIELD_LAYERS, layers);
+	}
+
+	public static void registerPersistence() {
+		// Add the MultiLayerFillSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				MultiLayerFillSymbol.class,
+				MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME,
+				MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		// Extend the FillSymbol base definition
+		definition.extend(FILL_SYMBOL_DYNCLASS_NAME);
+
+		// Selection Symbol
+		// definition.addDynFieldSingle(FIELD_SYMBOL_FOR_SELECTION).setType(
+		// DataTypes.OBJECT);
+
+		// Layers
+		definition.addDynFieldList(FIELD_LAYERS);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/SimpleFillSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/SimpleFillSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/impl/SimpleFillSymbol.java	(revision 33580)
@@ -0,0 +1,276 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.gvsig.utils.XMLEntity;
+import org.gvsig.utils.XMLException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Basic fill symbol. It will allow to paint a shape with its filling color (and transparency) and the outline.
+ * @author 2005-2008  jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SimpleFillSymbol extends AbstractFillSymbol {
+	
+//	private static final String FIELD_SYMBOL_FOR_SELECTION = "symbolForSelection";
+
+	public static final String SIMPLE_FILL_SYMBOL_DYNCLASS_NAME = "SimpleFillSymbol";
+	
+	private SimpleFillSymbol symbolForSelection;
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final Logger logger = 
+	    LoggerFactory.getLogger(SimpleFillSymbol.class);
+
+	public ISymbol getSymbolForSelection() {
+		if (symbolForSelection == null) {
+			SimpleFillSymbol selectionSymbol = (SimpleFillSymbol) cloneForSelection();
+			if (selectionSymbol != null) {
+				selectionSymbol.setHasFill(true);
+				setSymbolForSelection(selectionSymbol);
+			}
+//			
+//			XMLEntity xml=null;
+//			try {
+//				xml = getXMLEntity();
+//			} catch (XMLException e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+//			xml.putProperty("hasFill", true);
+//			xml.putProperty("color", StringUtilities.color2String(MapContext.getSelectionColor()));
+//			symbolForSelection = (SimpleFillSymbol) SymbologyFactory.
+//					createSymbolFromXML(xml, getDescription()+" version for selection");
+		}
+		return symbolForSelection;
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		Color c = getFillColor();
+		if (c!=null && hasFill()) {
+			g.setColor(c);
+			g.fill(geom);
+		}
+		if (getOutline() != null && hasOutline()) {
+			getOutline().draw(g, affineTransform, geom, feature, cancel);
+		}
+	}
+
+	public XMLEntity getXMLEntity() throws XMLException {
+		XMLEntity xml = new XMLEntity();
+
+//		// the class name
+//		xml.putProperty("className", getClassName());
+//
+//		// color
+//		Color c = getFillColor();
+//		if (c!=null) {
+//			xml.putProperty("color", StringUtilities.color2String(getFillColor()));
+//		}
+//
+//		//has Fill
+//		xml.putProperty("hasFill", hasFill());
+//		// description
+//		xml.putProperty("desc", getDescription());
+//
+//		// is shape visible
+//		xml.putProperty("isShapeVisible", isShapeVisible());
+//
+//		xml.putProperty("referenceSystem", getReferenceSystem());
+//		xml.putProperty("unit", getUnit());
+//
+//		// outline
+//		if (getOutline() != null) {
+//			xml.addChild(getOutline().getXMLEntity());
+//		}
+//
+//		//has Outline
+//		xml.putProperty("hasOutline", hasOutline());
+
+		return xml;
+	}
+
+	public int getSymbolType() {
+		return Geometry.TYPES.SURFACE;
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		Rectangle rect = new Rectangle(r.x, r.y, r.width, r.height);
+		rect.setFrame(((int) rect.getMinX())+1, ((int) rect.getMinY())+1, ((int) rect.getWidth())-2, ((int) rect.getHeight())-2);
+		Geometry geom;
+		try {
+			geom = geomManager.createSurface(new GeneralPathX(rect.getPathIterator(null)), SUBTYPES.GEOM2D);
+		} catch (CreateGeometryException e) {
+			logger.error("Creating a surface", e);
+			throw new SymbolDrawingException(getSymbolType());
+		}
+
+		Color c = getFillColor();
+		if (c != null && hasFill()) {
+			g.setColor(c);
+			g.fillRect(rect.x, rect.y, rect.width, rect.height);
+		}
+
+		if (getOutline() != null && hasOutline()) {
+			if (properties==null)
+				getOutline().draw(g, scaleInstance, geom, null, null);
+			else
+				print(g, new AffineTransform(), geom, properties);
+		}
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	/**
+	 * TODO: replace with the new Persistence API
+	 */
+	public void setXMLEntity(XMLEntity xml) {
+//		// color
+//		if (xml.contains("color")) {
+//			setFillColor(StringUtilities.string2Color(xml.getStringProperty("color")));
+//		}
+//
+//		//has Fill
+//		if(xml.contains("hasFill")) {
+//			setHasFill(xml.getBooleanProperty("hasFill"));
+//		}
+//
+//		// description
+//		setDescription(xml.getStringProperty("desc"));
+//
+//		// is shape visible
+//		setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
+//
+//
+//		// outline
+//		if (xml.getChildrenCount() > 0) {
+//			setOutline((ILineSymbol) SymbologyFactory.createSymbolFromXML(xml.getChild(0), null));
+//		}
+//
+//		if (xml.contains("unit")) { // remove this line when done
+//		// measure unit (for outline)
+//		setUnit(xml.getIntProperty("unit"));
+//
+//		// reference system (for outline)
+//		setReferenceSystem(xml.getIntProperty("referenceSystem"));
+//		}
+//
+//		//has Outline
+//		if(xml.contains("hasOutline")) {
+//			setHasOutline(xml.getBooleanProperty("hasOutline"));
+//		}
+	}
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		Color c = getFillColor();
+		if (c!=null && hasFill()) {
+			g.setColor(c);
+			g.fill(geom);
+		}
+		if (getOutline() != null && hasOutline()) {
+			getOutline().print(g, at, geom, properties);
+		}
+	}
+	
+	
+	public Object clone() throws CloneNotSupportedException {
+		SimpleFillSymbol copy = (SimpleFillSymbol) super.clone();
+
+		// Clone selection
+		if (symbolForSelection != null) {
+			copy.symbolForSelection = (SimpleFillSymbol) symbolForSelection
+					.clone();
+		}
+
+		return copy;
+	}
+	
+	private void setSymbolForSelection(SimpleFillSymbol symbolForSelection) {
+		this.symbolForSelection = symbolForSelection;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		// setSymbolForSelection((SimpleFillSymbol)
+		// state.get(FIELD_SYMBOL_FOR_SELECTION));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+		// Save own properties
+
+		// Don't use the getSymbolForSelection method, as it will create it
+		// if it does not exist, and persistence will enter an infinite loop
+		// state.set(FIELD_SYMBOL_FOR_SELECTION, symbolForSelection);
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleFillSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SimpleFillSymbol.class,
+				SIMPLE_FILL_SYMBOL_DYNCLASS_NAME,
+				SIMPLE_FILL_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		// Extend the FillSymbol base definition
+		definition.extend(FILL_SYMBOL_DYNCLASS_NAME);
+
+		// Selection Symbol
+		// definition.addDynFieldSingle(FIELD_SYMBOL_FOR_SELECTION).setType(
+		// DataTypes.OBJECT);
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/IFillSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/IFillSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/fill/IFillSymbol.java	(revision 33580)
@@ -0,0 +1,124 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+ *
+ * $Id: IFillSymbol.java 21071 2008-06-02 10:55:35Z vcaballero $
+ * $Log$
+ * Revision 1.3  2007-08-13 11:36:50  jvidal
+ * javadoc
+ *
+ * Revision 1.2  2007/03/09 11:20:56  jaume
+ * Advanced symbology (start committing)
+ *
+ * Revision 1.1.2.2  2007/02/21 16:09:02  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2007/02/16 10:54:12  jaume
+ * multilayer splitted to multilayerline, multilayermarker,and  multilayerfill
+ *
+ *
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill;
+
+import java.awt.Color;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+
+
+/**
+ * Interface that extends ISymbol interface in order to define methods for
+ * fill symbols which can manage specific attributes of them.
+ *
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+
+public interface IFillSymbol extends ISymbol, CartographicSupport{
+	
+	public static final String SYMBOL_NAME = "fill";
+
+	public abstract boolean isSuitableFor(Geometry geom);
+
+	public abstract int getOnePointRgb();
+
+	/**
+	 * Sets the color that will be used to draw the filling pattern of this symbol.
+	 *
+	 * @param Color
+	 */
+	public abstract void setFillColor(Color color);
+
+	/**
+	 * Sets the color of the outline.
+	 * @deprectated will be substituted by setOutline(AbstractLineSymbol);
+	 * @param color
+	 */
+	public abstract void setOutline(ILineSymbol outline);
+
+	/**
+	 * @return Returns the color.
+	 */
+	public abstract Color getFillColor();
+
+	/**
+	 * Obtains the ILineSymbol interface of the outline
+	 * @return the outline,ILineSymbol.
+	 */
+	public abstract ILineSymbol getOutline();
+	/**
+	 * Obtains the transparency of the fill symbol
+	 * @return the transparency of the fill symbol
+	 */
+
+	public abstract int getFillAlpha();
+
+	public abstract boolean hasFill();
+
+	public abstract void setHasFill(boolean hasFill);
+
+	public abstract boolean hasOutline();
+
+	public abstract void setHasOutline(boolean hasOutline);
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/ILineSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/ILineSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/ILineSymbol.java	(revision 33580)
@@ -0,0 +1,143 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+ *
+ * $Id: ILineSymbol.java 20989 2008-05-28 11:05:57Z jmvivo $
+ * $Log$
+ * Revision 1.6  2007-08-14 11:17:31  jvidal
+ * javadoc updated
+ *
+ * Revision 1.5  2007/08/08 12:03:13  jvidal
+ * javadoc
+ *
+ * Revision 1.4  2007/05/08 08:47:39  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.3  2007/03/20 16:00:24  jaume
+ * removed unuseful comments
+ *
+ * Revision 1.2  2007/03/09 11:20:56  jaume
+ * Advanced symbology (start committing)
+ *
+ * Revision 1.1.2.5  2007/02/21 16:09:02  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.4  2007/02/15 16:23:44  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.3  2007/02/14 15:53:35  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/02/13 16:19:19  jaume
+ * graduated symbol legends (start commiting)
+ *
+ * Revision 1.1.2.1  2007/02/09 07:47:04  jaume
+ * Isymbol moved
+ *
+ *
+ */
+
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line;
+
+import java.awt.Color;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ILineStyle;
+
+
+
+/**
+ * Interface for <b>line symbols</b>.It has the different methods to obtain or define
+ * the attributes of a line such as color, style, width and alpha (transparency).
+ *
+ * @author   jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public interface ILineSymbol extends ISymbol, CartographicSupport{
+	
+	public static final String SYMBOL_NAME = "line";
+
+	/**
+	 * Returns the color of the line symbol
+	 * @return Color
+	 */
+	public abstract Color getColor();
+	/**
+	 * Sets the color for a line symbol
+	 * @param color
+	 */
+
+	public abstract void setLineColor(Color color);
+	/**
+	 * Obtains the style of the line symbol.
+	 * @return ILineStyle, the style of the line symbol
+	 */
+	public abstract ILineStyle getLineStyle();
+	/**
+	 * Defines the style of the line symbol to be used.
+	 * @param lineStyle
+	 */
+	public abstract void setLineStyle(ILineStyle lineStyle);
+	/**
+	 * Sets the width of the line symbol.
+	 * @param width, the width of the line
+	 */
+	public abstract void setLineWidth(double width);
+	/**
+	 * Returns the width of the line symbol
+	 * @return
+	 */
+
+	public abstract double getLineWidth();
+
+	/**
+	 * Obtains the transparency of the line symbol
+	 * @return
+	 */
+	public abstract int getAlpha();
+
+	/**
+	 * Defines the transparency of a line symbol.
+	 * @param outlineAlpha, the transparency
+	 */
+	public abstract void setAlpha(int outlineAlpha);
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/MultiLayerLineSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/MultiLayerLineSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/MultiLayerLineSymbol.java	(revision 33580)
@@ -0,0 +1,377 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ILineStyle;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+
+/**
+ * MultiLayerLineSymbol allows to create new symbols using a composition of several lineal
+ * symbols (xxxLineSymbol implementing ILineSymbol)and be treated as an only one symbol.
+ *
+ * @author  jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class MultiLayerLineSymbol extends AbstractLineSymbol implements
+		ILineSymbol, IMultiLayerSymbol {
+
+    public static final String MULTILAYER_LINE_SYMBOL_DYNCLASS_NAME = "MultiLayerLineSymbol";
+    private static final String FIELD_LAYERS = "layers";
+    
+    	private ILineSymbol[] layers = new ILineSymbol[0];
+	private MultiLayerLineSymbol selectionSymbol;
+	
+	// Cached greatest line width from all the layers
+	private double lineWidth;
+
+	public Color getColor() {
+		/*
+		 * a multilayer symbol does not define any color, the color
+		 * of each layer is defined by the layer itself
+		 */
+		return null;
+	}
+
+	public ILineStyle getLineStyle() {
+		/*
+		 * a multilayer symbol does not define any style, the style
+		 * of each layer is defined by the layer itself
+		 */
+		return null;
+	}
+
+    public double getLineWidth() {
+	return lineWidth;
+    }
+
+//    private double calculateLineWidth() {
+//	double myLineWidth = 0;
+//	for (int i = 0; i < getLayerCount(); i++) {
+//	    myLineWidth = Math.max(myLineWidth,
+//		    ((ILineSymbol) getLayer(i)).getLineWidth());
+//	}
+//	return myLineWidth;
+//    }
+
+    public void setLineWidth(double width) {	
+	if (width > 0 && width != lineWidth) {
+	    this.lineWidth = width;
+	    double scaleFactor = width / lineWidth;
+			for (int i = 0; layers != null && i < layers.length; i++) {
+		layers[i].setLineWidth(layers[i].getLineWidth() * scaleFactor);
+	    }
+	}
+    }
+
+	public void setLineColor(Color color) {
+		/*
+		 * will apply the color to each layer
+		 */
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setLineColor(color);
+		}
+	}
+
+	public void setLineStyle(ILineStyle lineStyle) {
+		/*
+		 * will apply the same patter to each layer
+		 */
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setLineStyle(lineStyle);
+		}
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+		for (int i = 0; (cancel == null || !cancel.isCanceled())
+				&& layers != null && i < layers.length; i++) {
+			layers[i].draw(g, affineTransform, geom, feature, cancel);
+		}
+	}
+
+	public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].drawInsideRectangle(g, scaleInstance, r, properties);
+		}
+	}
+
+	public int getOnePointRgb() {
+		// will paint only the last layer pixel
+		return layers[layers.length-1].getOnePointRgb();
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances,
+			ViewPort viewPort, int dpi) {
+		float[] myDistances = new float[] {0,0};
+		distances[0] = 0;
+		distances[1] = 0;
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].getPixExtentPlus(geom, myDistances, viewPort, dpi);
+			distances[0] = Math.max(myDistances[0], distances[0]);
+			distances[1] = Math.max(myDistances[1], distances[1]);
+		}
+	}
+
+	public ISymbol getSymbolForSelection() {
+		if (selectionSymbol == null) {
+			selectionSymbol = new MultiLayerLineSymbol();
+			selectionSymbol.setDescription(getDescription());
+			for (int i = 0; layers != null && i < layers.length; i++) {
+				selectionSymbol.addLayer(layers[i].getSymbolForSelection());
+			}
+		}
+		return selectionSymbol;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		return geom.getType() == Geometry.TYPES.CURVE;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].print(g, at, geom, properties);
+		}
+
+	}
+
+	public void setLayer(int index, ISymbol layer) throws IndexOutOfBoundsException {
+		layers[index] = (ILineSymbol) layer;
+	}
+
+	public void swapLayers(int index1, int index2) {
+		ISymbol aux1 = getLayer(index1), aux2 = getLayer(index2);
+		layers[index2] = (ILineSymbol) aux1;
+		layers[index1] = (ILineSymbol) aux2;
+	}
+
+	public ISymbol getLayer(int layerIndex) {
+		return layers[layerIndex];
+	}
+
+	public int getLayerCount() {
+		return layers.length;
+	}
+
+	public void addLayer(ISymbol newLayer) {
+		addLayer(newLayer, layers.length);
+	}
+
+	public void addLayer(ISymbol newLayer, int layerIndex) throws IndexOutOfBoundsException {
+
+		if (newLayer == null) {
+			return; // null are not allowed
+		}
+		ILineSymbol newLine = (ILineSymbol) newLayer;
+		if (getLayerCount() == 0) {
+			// apply the new layer properties to this multilayer
+
+			setReferenceSystem(newLine.getReferenceSystem());
+			setUnit(newLine.getUnit());
+			lineWidth = newLine.getLineWidth();
+		} else {
+			if (newLine.getLineWidth() > getLineWidth()) {
+				lineWidth = newLine.getLineWidth();
+			}
+			newLine.setReferenceSystem(getReferenceSystem());
+			newLine.setUnit(getUnit());
+		}
+
+		selectionSymbol = null; /* forces the selection symbol to be re-created
+		 						 * next time it is required
+		 						 */
+
+
+		if (layerIndex < 0 || layers.length < layerIndex) {
+			throw new IndexOutOfBoundsException(layerIndex+" < 0 or "+layerIndex+" > "+layers.length);
+		}
+		List<ISymbol> newLayers = new ArrayList<ISymbol>();
+		for (int i = 0; i < layers.length; i++) {
+			newLayers.add(layers[i]);
+		}
+		try {
+			newLayers.add(layerIndex, newLayer);
+			layers = (ILineSymbol[])newLayers.toArray(new ILineSymbol[0]);
+		} catch (ArrayStoreException asEx) {
+			throw new ClassCastException(newLayer.getClass().getName()+" is not an ILineSymbol");
+		}
+	}
+
+	public boolean removeLayer(ISymbol layer) {
+
+		int capacity = 0;
+		capacity = layers.length;
+		List<ILineSymbol> lst = new ArrayList<ILineSymbol>(capacity);
+		for (int i = 0; i < capacity; i++) {
+			lst.add(layers[i]);
+		}
+		boolean contains = lst.remove(layer);
+		layers = (ILineSymbol[])lst.toArray(new ILineSymbol[0]);
+		return contains;
+	}
+
+	public int getAlpha() {
+		// will compute the acumulated opacity
+		double myAlpha = 0;
+		for (int i = 0; i < layers.length; i++) {
+			double layerAlpha = layers[i].getAlpha()/255D;
+			myAlpha += (1-myAlpha)*layerAlpha;
+		}
+		int result = (int) Math.round(myAlpha * 255);
+		return (result>255) ? 255 : result;
+	}
+
+	public void setAlpha(int outlineAlpha) {
+		// first, get the biggest alpha in the layers and the index if such layer
+		int maxAlpha = Integer.MIN_VALUE;
+		int maxAlphaLayerIndex = 0;
+		for (int i = 0; i < layers.length; i++) {
+			if (layers[i].getAlpha() > maxAlpha) {
+				maxAlpha = layers[i].getAlpha();
+				maxAlphaLayerIndex = i;
+			}
+		}
+
+		// now, max alpha takes the value of the desired alpha and the rest
+		// will take a scaled (to biggest alpha) alpha value
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			if (i!=maxAlphaLayerIndex) {
+				double scaledAlpha = (double) layers[i].getAlpha()/maxAlpha;
+				int myAlpha = (int) (outlineAlpha*scaledAlpha);
+				if (myAlpha == 0) {
+					myAlpha = 1;
+				}
+				layers[i].setAlpha(myAlpha);
+			} else {
+				int myAlpha = outlineAlpha;
+				if (myAlpha == 0) {
+					myAlpha = 1;
+				}
+				layers[i].setAlpha(myAlpha);
+			}
+		}
+
+	}
+
+	public void setUnit(int unitIndex) {
+		super.setUnit(unitIndex);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setUnit(unitIndex);
+		}
+	}
+
+	public void setReferenceSystem(int system) {
+		super.setReferenceSystem(system);
+		for (int i = 0; layers != null && i < layers.length; i++) {
+			layers[i].setReferenceSystem(system);
+		}
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+//		super.setCartographicSize(cartographicSize, shp);
+		setLineWidth(cartographicSize);
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		MultiLayerLineSymbol copy = (MultiLayerLineSymbol) super.clone();
+
+		// Clone layers
+		if (layers != null && layers.length > 0) {
+			ILineSymbol[] layersCopy = new ILineSymbol[layers.length];
+			for (int i = 0; i < layers.length; i++) {
+				layersCopy[i] = (ILineSymbol) layers[i].clone();
+			}
+			copy.layers = layersCopy;
+		}
+
+		// Clone selection
+		if (selectionSymbol != null) {
+			copy.selectionSymbol = (MultiLayerLineSymbol) selectionSymbol
+					.clone();
+		}
+
+		return copy;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent fill symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		List layers = state.getList(FIELD_LAYERS);
+		if (layers != null) {
+			for (int i = 0; i < layers.size(); i++) {
+				addLayer((ISymbol) layers.get(i));
+			}
+		}
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent fill symbol properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_LAYERS, layers);
+	}
+
+	public static void registerPersistence() {
+		// Add the MultiLayerLineSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				MultiLayerLineSymbol.class,
+				MULTILAYER_LINE_SYMBOL_DYNCLASS_NAME,
+				MULTILAYER_LINE_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the LineSymbol base definition
+		definition.extend(LINE_SYMBOL_DYNCLASS_NAME);
+
+		// Layers
+		definition.addDynFieldList(FIELD_LAYERS);
+
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/SimpleLineSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/SimpleLineSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/SimpleLineSymbol.java	(revision 33580)
@@ -0,0 +1,156 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl;
+
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ArrowDecoratorStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.Line2DOffset;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.task.Cancellable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * SimpleLineSymbol is the most basic symbol for the representation of line objects.
+ * Allows to define the width of the line, the color and the drawn pattern.
+ *
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SimpleLineSymbol extends AbstractLineSymbol {
+
+    public static final String SIMPLE_LINE_SYMBOL_DYNCLASS_NAME = "SimpleLineSymbol";
+  
+	SimpleLineSymbol symbolForSelection;
+//	private double width;
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final Logger logger = LoggerFactory.getLogger(SimpleLineSymbol.class);
+
+	public SimpleLineSymbol() {
+		setLineWidth(1d);
+	}
+	
+	public ISymbol getSymbolForSelection() {
+		if (symbolForSelection == null) {
+			symbolForSelection = (SimpleLineSymbol) cloneForSelection();			
+		}
+		return symbolForSelection;
+	}
+
+	public void draw(Graphics2D g, AffineTransform affineTransform,
+			Geometry geom, Feature feature, Cancellable cancel) {
+
+		Geometry geomToDraw = geom;
+		g.setStroke(getLineStyle().getStroke());
+
+		if (getLineStyle().getOffset() != 0) {
+			double offset = getLineStyle().getOffset();
+			try {
+				geomToDraw =
+						geomManager.createSurface(Line2DOffset.offsetLine(
+								geomToDraw, offset), SUBTYPES.GEOM2D);
+			} catch (CreateGeometryException e) {
+				logger.error("Creating a Surface", e);
+				e.printStackTrace();
+			}
+		}
+		g.setColor(getColor());
+		g.draw(geomToDraw);
+
+		ArrowDecoratorStyle arrowDecorator = getLineStyle().getArrowDecorator();
+
+		if (arrowDecorator != null) {
+			try {
+				arrowDecorator.draw(g, affineTransform, geomToDraw, feature);
+			} catch (CreateGeometryException e) {
+				logger.error("Error creating a geometry");
+			}
+		}
+	}
+
+	public int getOnePointRgb() {
+		return getColor().getRGB();
+	}
+
+	public void drawInsideRectangle(Graphics2D g,
+			AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		g.setColor(getColor());
+		g.setStroke(getLineStyle().getStroke());
+		super.drawInsideRectangle(g, scaleInstance, r, properties);
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void setLineWidth(double width) {
+//		this.width = width;
+		getLineStyle().setLineWidth((float) width);
+	}
+
+	public double getLineWidth() {
+//		return width;
+		return getLineStyle().getLineWidth();
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		SimpleLineSymbol copy = (SimpleLineSymbol) super.clone();
+
+		// clone selection
+		if (symbolForSelection != null) {
+			copy.symbolForSelection = (SimpleLineSymbol) symbolForSelection
+					.clone();
+		}
+
+		return copy;
+	}
+
+	public static void registerPersistence() {
+		// Add the SimpleLineSymbol DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SimpleLineSymbol.class,
+				SIMPLE_LINE_SYMBOL_DYNCLASS_NAME,
+				SIMPLE_LINE_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the LineSymbol base definition
+		definition.extend(LINE_SYMBOL_DYNCLASS_NAME);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/AbstractLineSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/AbstractLineSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/line/impl/AbstractLineSymbol.java	(revision 33580)
@@ -0,0 +1,372 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.ILineStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.SimpleLineStyle;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+
+/**
+ * AbstractLineSymbol is the class that implements the interface for line symbols.
+ * It is considered as the father of all the XXXLineSymbols and will implement all the
+ * methods that these classes had not developed (and correspond with one of the methods
+ * of AbstractLineSymbol class).
+ *
+ *
+ * @author 2005-2009 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractLineSymbol extends AbstractSymbol implements ILineSymbol {
+
+    private static final String FIELD_LINESTYLE = "lineStyle";
+
+    private static final String FIELD_COLOR = "color";
+
+    public static final String LINE_SYMBOL_DYNCLASS_NAME = "LineSymbol";
+
+    
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private Color color;
+	private ILineStyle lineStyle = new SimpleLineStyle();
+
+	public AbstractLineSymbol() {
+		super();
+		color =
+				MapContextLocator.getSymbolManager()
+						.getSymbolPreferences()
+						.getDefaultSymbolColor();
+	}
+
+	public Color getColor() {
+		return color;
+	}
+
+	public void setLineColor(Color color) {
+		this.color = color;
+	}
+	
+	public void setColor(Color color) {
+		setLineColor(color);
+	}
+
+	public int getOnePointRgb() {
+		return color.getRGB();
+	}
+
+	public final int getSymbolType() {
+		return Geometry.TYPES.CURVE;
+	}
+
+	public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
+		float cs = (float) getCartographicSize(viewPort, dpi, geom);
+		// TODO and add the line offset
+		distances[0] = cs;
+		distances[1] = cs;
+	}
+
+	public boolean isSuitableFor(Geometry geom) {
+		switch(geom.getType()) {
+		// pasted from FSymbol
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			return true;
+		}
+		return false;
+	}
+
+	public ILineStyle getLineStyle() {
+		return lineStyle;
+	}
+
+	public void setLineStyle(ILineStyle lineStyle) {
+		this.lineStyle = lineStyle;
+	}
+
+	public int getAlpha() {
+		return color.getAlpha();
+	}
+
+	public void setAlpha(int outlineAlpha) {
+		color = new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha);
+	}
+
+	public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
+		final int hGap = (int) (r.getWidth() * 0.1); // the left and right margins
+		final int vPos = 1; 						 // the top and bottom margins
+		final int splitCount = 3; 					 // number of lines
+		final int splitHSize = (r.width - hGap - hGap) / splitCount;
+		int hPos = hGap;
+		boolean swap = false;
+
+		GeneralPathX gpx = new GeneralPathX();
+		gpx.moveTo(r.x + hPos, r.y + r.height-vPos);
+
+		for (int i = 0; i < splitCount; i++) {
+			swap = !swap;
+			gpx.lineTo(r.x + hPos + splitHSize, (swap ? vPos : r.height-vPos) + r.y);
+			hPos += splitHSize;
+		}
+
+		try {
+			if (properties==null)
+				draw(g, new AffineTransform(), geomManager.createSurface(gpx, SUBTYPES.GEOM2D), null, null);
+			else
+				print(g, new AffineTransform(), geomManager.createSurface(gpx, SUBTYPES.GEOM2D), properties);
+		} catch (Exception e) {
+			throw new SymbolDrawingException(SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS);
+		}
+
+	}
+
+
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		getLineStyle().setLineWidth((float) cartographicSize);
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		double oldSize = getLineWidth();
+		setCartographicSize(getCartographicSize(
+								viewPort,
+								dpi,
+								geom),
+							geom);
+		return oldSize;
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		return CartographicSupportToolkit.
+					getCartographicLength(this,
+										  getLineWidth(),
+										  viewPort,
+										  dpi);
+	}
+
+	public static Geometry offsetFShape(Geometry shp, double offset) {
+		Geometry offsetFShape = null;
+		if (shp != null) {
+			if (offset == 0)
+				return shp;
+
+			List<Point2D[]> segments = new ArrayList<Point2D[]>();
+			GeneralPathX gpx = new GeneralPathX(shp.getPathIterator(null));
+			PathIterator it = gpx.getPathIterator(null);
+			double[] data = new double[6];
+			Point2D segmentIni = null;
+			Point2D segmentEnd = null;
+			while (!it.isDone()) {
+				switch (it.currentSegment(data)) {
+				case PathIterator.SEG_MOVETO:
+					segmentEnd = new Point2D.Double(
+							data[0], data[1]);
+					break;
+
+				case PathIterator.SEG_LINETO:
+					segmentEnd = segmentIni;
+					segmentIni = new Point2D.Double(
+							data[0], data[1]);
+
+					segments.add(getParallel(segmentIni, segmentEnd, offset));
+					break;
+
+				case PathIterator.SEG_QUADTO:
+					break;
+
+				case PathIterator.SEG_CUBICTO:
+					break;
+
+				case PathIterator.SEG_CLOSE:
+					break;
+				}
+			}
+
+		}
+
+
+		return offsetFShape;
+	}
+
+	private static Point2D[] getParallel(Point2D p1, Point2D p2, double distance) {
+		Point2D[] pParallel=new Point2D[2];
+		pParallel[0]=getPerpendicularPoint(p1,p2,p1,distance);
+		pParallel[1]=getPerpendicularPoint(p1,p2,p2,distance);
+		return pParallel;
+	}
+
+	/**
+	 * Obtiene el punto que se encuentra a una distancia 'dist' de la recta
+	 * p1-p2 y se encuentra en la recta perpendicular que pasa por perpPoint
+	 *
+	 * @param p1 Punto de la recta p1-p2
+	 * @param p2 Punto de la recta p1-p2
+	 * @param perpPoint Punto de la recta perpendicular
+	 * @param dist Distancia del punto que se quiere obtener a la recta p1-p2
+	 *
+	 * @return DOCUMENT ME!
+	 */
+	private static Point2D getPerpendicularPoint(Point2D p1, Point2D p2,
+		Point2D perpPoint, double dist) {
+		Point2D[] p = getPerpendicular(p1, p2, perpPoint);
+		Point2D unit = getUnitVector(p[0], p[1]);
+
+		return new Point2D.Double(perpPoint.getX() + (unit.getX() * dist),
+			perpPoint.getY() + (unit.getY() * dist));
+	}
+
+
+	/**
+	 * Obtiene un par de puntos que definen la recta perpendicular a p1-p2 que
+	 * pasa por el punto perp
+	 *
+	 * @param p1 punto de la recta p1-p2
+	 * @param p2 punto de la recta p1-p2
+	 * @param perp Punto por el que pasa la recta perpendicular, debe ser
+	 * 		  distinto a p2
+	 *
+	 * @return Array con dos puntos que definen la recta resultante
+	 */
+	private static Point2D[] getPerpendicular(Point2D p1, Point2D p2,
+		Point2D perp) {
+		if ((p2.getY() - p1.getY()) == 0) {
+			return new Point2D[] {
+				new Point2D.Double(perp.getX(), 0),
+				new Point2D.Double(perp.getX(), 1)
+			};
+		}
+
+		//Pendiente de la recta perpendicular
+		double m = (p1.getX() - p2.getX()) / (p2.getY() - p1.getY());
+
+		//b de la funcion de la recta perpendicular
+		double b = perp.getY() - (m * perp.getX());
+
+		//Obtenemos un par de puntos
+		Point2D[] res = new Point2D[2];
+
+		res[0] = new Point2D.Double(0, (m * 0) + b);
+		res[1] = new Point2D.Double(1000, (m * 1000) + b);
+
+		return res;
+	}
+
+	/**
+	 * Devuelve un vector unitario en forma de punto a partir de dos puntos.
+	 *
+	 * @param p1 punto origen.
+	 * @param p2 punto destino.
+	 *
+	 * @return vector unitario.
+	 */
+	private static Point2D getUnitVector(Point2D p1, Point2D p2) {
+		Point2D paux = new Point2D.Double(p2.getX() - p1.getX(),
+				p2.getY() - p1.getY());
+		double v = Math.sqrt(Math.pow(paux.getX(), 2d) +
+				Math.pow(paux.getY(), 2d));
+		paux = new Point2D.Double(paux.getX() / v, paux.getY() / v);
+
+		return paux;
+	}
+	public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
+		double originalSize = getLineWidth();
+		double size=originalSize;
+		// scale it to size
+		int pq = properties.getPrintQuality();
+		if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
+			size *= (double) 300/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
+			size *= (double) 600/72;
+		}else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
+			// size *= 72/72; // (which is the same than doing nothing)
+		}
+		setLineWidth(size);
+		draw(g,at,geom,null, null);
+		setLineWidth(originalSize);
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		AbstractLineSymbol copy = (AbstractLineSymbol) super.clone();
+		
+		// Clone the line style
+		if (lineStyle != null) {
+			copy.lineStyle = (ILineStyle) lineStyle.clone();
+		}
+		
+		return copy;
+	}
+
+	
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent symbol properties
+		super.loadFromState(state);
+		// Set own properties
+		setColor((Color) state.get(FIELD_COLOR));
+		setLineStyle((ILineStyle) state.get(FIELD_LINESTYLE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent symbol properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_COLOR, getColor());
+		state.set(FIELD_LINESTYLE, getLineStyle());
+	}
+
+	public static void registerPersistence() {
+		// Add the AbstractLineSymbol DynClass definition.
+		DynClass dynClass = ToolsLocator.getDynObjectManager().add(
+				LINE_SYMBOL_DYNCLASS_NAME);
+
+		// Extend the Symbol base definition
+		dynClass.extend(SYMBOL_PERSISTENCE_DEFINITION_NAME);
+
+		// Color
+		dynClass.addDynFieldObject(FIELD_COLOR).setMandatory(true);
+		// LineStyle
+		dynClass.addDynFieldObject(FIELD_LINESTYLE).setMandatory(true);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/MemoryShapeInfo.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/MemoryShapeInfo.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/MemoryShapeInfo.java	(revision 33580)
@@ -0,0 +1,127 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies;
+
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+/**
+ * Estructura de datos con la informaci�n relativa a las geometr�as de una
+ * fuente de datos necesaria para acelerar el procesado de la capa en memoria.
+ *
+ * @author Vicente Caballero Navarro
+ */
+public class MemoryShapeInfo implements ShapeInfo {
+	List<Info> infos = new ArrayList<Info>();
+
+	/**
+	 * @see org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies.ShapeInfo#addShapeInfo(java.awt.geom.Rectangle2D,
+	 * 		int)
+	 */
+	public void addShapeInfo(Rectangle2D boundingBox, int type) {
+		infos.add(new Info(boundingBox, type));
+	}
+
+	/**
+	 * @see org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies.ShapeInfo#addShapeInfo(int,
+	 * 		java.awt.geom.Rectangle2D, int)
+	 */
+	public void setShapeInfo(int index, Rectangle2D boundingBox, int type)
+		throws ArrayIndexOutOfBoundsException {
+		infos.set(index, new Info(boundingBox, type));
+	}
+
+	/**
+	 * @see org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies.ShapeInfo#getBoundingBox(int)
+	 */
+	public Rectangle2D getBoundingBox(int index) {
+		return ((Info) infos.get(index)).getRect();
+	}
+
+	/**
+	 * @see org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies.ShapeInfo#getType(int)
+	 */
+	public int getType(int index) {
+		return ((Info) infos.get(index)).getType();
+	}
+
+	/**
+	 * Clase con el rect�ngulo y el tipo de shape.
+	 *
+	 * @author Vicente Caballero Navarro
+	 */
+	class Info {
+		private Rectangle2D rect;
+		private int type;
+
+		/**
+		 * Crea un nuevo Info.
+		 *
+		 * @param rect Extent del shape.
+		 * @param type Tipo de shape.
+		 */
+		public Info(Rectangle2D rect, int type) {
+			this.rect = rect;
+			this.type = type;
+		}
+
+		/**
+		 * Devuelve el extent del shape.
+		 *
+		 * @return Extent del shape.
+		 */
+		public Rectangle2D getRect() {
+			return rect;
+		}
+
+		/**
+		 * Devuelve el tipo de shape.
+		 *
+		 * @return Tipo de shape.
+		 */
+		public int getType() {
+			return type;
+		}
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/ShapeInfo.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/ShapeInfo.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/strategies/ShapeInfo.java	(revision 33580)
@@ -0,0 +1,90 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.strategies;
+
+import java.awt.geom.Rectangle2D;
+
+
+/**
+ * Estructura de datos con la informaci�n relativa a las geometr�as de una
+ * fuente de datos necesaria para acelerar el procesado de la capa
+ */
+public interface ShapeInfo {
+	/**
+	 * A�ade al final de la estructura de datos la informaci�n de una geometr�a
+	 *
+	 * @param boundingBox Extent del shape.
+	 * @param type Tipo de shape.
+	 */
+	void addShapeInfo(Rectangle2D boundingBox, int type);
+
+	/**
+	 * Establece en la posici�n index-�sima de la estructura de datos la
+	 * informaci�n de una geometr�a
+	 *
+	 * @param index �ndice.
+	 * @param boundingBox Extent del shape.
+	 * @param type Tipo de shape.
+	 *
+	 * @throws ArrayIndexOutOfBoundsException Si se intenta establecer la
+	 * 		   informaci�n para una geometr�a que no existe
+	 */
+	void setShapeInfo(int index, Rectangle2D boundingBox, int type)
+		throws ArrayIndexOutOfBoundsException;
+
+	/**
+	 * Obtiene el bounding box de la geometr�a index-�sima
+	 *
+	 * @param index �ndice de la geometr�a.
+	 *
+	 * @return Extent de la geometr�a.
+	 */
+	Rectangle2D getBoundingBox(int index);
+
+	/**
+	 * Obtiene el tipo de la geometr�a index-�sima
+	 *
+	 * @param index �ndice.
+	 *
+	 * @return Tipo de geometr�a.
+	 */
+	int getType(int index);
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/DefaultFeatureDrawnNotification.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/DefaultFeatureDrawnNotification.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/DefaultFeatureDrawnNotification.java	(revision 33580)
@@ -0,0 +1,78 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+*
+* Copyright (C) 2007-2008 Infrastructures and Transports Department
+* of the Valencian Government (CIT)
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+* MA  02110-1301, USA.
+* 
+*/
+
+/*
+* AUTHORS (In addition to CIT):
+* 2009 {DiSiD Technologies}  {{Task}}
+*/
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
+
+/**
+ * @author <a href="mailto:cordinyana@gvsig.org">C�sar Ordi�ana</a>
+ */
+public class DefaultFeatureDrawnNotification implements FeatureDrawnNotification {
+	
+	private Feature feature;
+	private Geometry drawnGeometry;
+
+	/**
+	 * Creates a new FeatureDrawnNotification.
+	 */
+	public DefaultFeatureDrawnNotification() {
+		// Nothing to do
+	}
+
+	/**
+	 * Creates a new FeatureDrawnNotification.
+	 * @param feature the {@link Feature} being drawn
+	 * @param drawnGeometry the {@link Geometry} to be finally drawn, as it may
+	 * have been reprojected
+	 */
+	public DefaultFeatureDrawnNotification(Feature feature, Geometry drawnGeometry) {
+		this.setFeature(feature);
+		this.setDrawnGeometry(drawnGeometry);
+	}
+
+	public Feature getFeature() {
+		return feature;
+	}
+
+	public void setFeature(Feature feature) {
+		this.feature = feature;
+	}
+
+	/**
+	 * @return the {@link Geometry} to be finally drawn, as it may
+	 * have been reprojected
+	 */
+	public Geometry getDrawnGeometry() {
+		return drawnGeometry;
+	}
+
+	public void setDrawnGeometry(Geometry drawnGeometry) {
+		this.drawnGeometry = drawnGeometry;
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/SingleSymbolLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/SingleSymbolLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/SingleSymbolLegend.java	(revision 33580)
@@ -0,0 +1,244 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.mapcontext.rendering.legend.ISingleSymbolLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.MultiShapeSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.utils.XMLEntity;
+import org.gvsig.utils.XMLException;
+
+/**
+ * Implements a legend composed by single symbols.
+ * 
+ * @author Vicente Caballero Navarro
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class SingleSymbolLegend extends AbstractVectorialLegend implements
+		ISingleSymbolLegend {
+
+	public static final String SINGLE_SYMBOL_DYNCLASS_NAME =
+			"SimgleSymbolLegend";
+	
+	private ISymbol defaultSymbol;
+    private int shapeType = Geometry.TYPES.SURFACE; // Por defecto, tipo pol�gono
+
+	/**
+	 * Constructor method, needed by persistence.
+	 */
+	public SingleSymbolLegend() {
+		// Nothing to do
+	}
+
+	/**
+	 * Convenience fast constructor.
+	 *
+	 * @param style S�mbolo.
+	 */
+	public SingleSymbolLegend(ISymbol style) {
+		defaultSymbol = style;
+
+		if (style instanceof MultiShapeSymbol) {
+			shapeType = Geometry.TYPES.GEOMETRY;
+		} else if (style instanceof IMarkerSymbol) {
+			shapeType = Geometry.TYPES.POINT;
+		} else if (style instanceof ILineSymbol) {
+			shapeType = Geometry.TYPES.CURVE;
+		} else if (style instanceof IFillSymbol) {
+			shapeType = Geometry.TYPES.SURFACE;
+		}
+	}
+
+
+	public void setDefaultSymbol(ISymbol s) {
+		if (s == null) throw new NullPointerException("Default symbol cannot be null");
+		setShapeType(s.getSymbolType());
+		ISymbol old = defaultSymbol;
+		defaultSymbol = s;
+		fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, s));
+	}
+
+
+	public ISymbol getSymbol(int recordIndex) {
+		return defaultSymbol;
+	}
+
+	public ISymbol getDefaultSymbol() {
+		if(defaultSymbol==null) {
+			defaultSymbol =
+					getSymbolManager().createSymbol(IFillSymbol.SYMBOL_NAME);
+		}
+		return defaultSymbol;
+	}
+
+
+	public XMLEntity getXMLEntity() throws XMLException {
+		XMLEntity xml = new XMLEntity();
+//		xml.putProperty("className",this.getClass().getName());
+//		xml.addChild(defaultSymbol.getXMLEntity());
+//
+//		if (zSort != null) {
+//			XMLEntity zSortXML = zSort.getXMLEntity();
+//			zSortXML.putProperty("id", "zSort");
+//			xml.addChild(zSortXML);
+//		}
+		return xml;
+	}
+
+	/**
+	 * TODO: replace with the new persistence API
+	 */
+	public void setXMLEntity(XMLEntity xml) {
+//        ISymbol auxSym = SymbologyFactory.createSymbolFromXML(xml.getChild(0), null);
+//		setDefaultSymbol(auxSym);
+//
+//		XMLEntity zSortXML = xml.firstChild("id", "zSort");
+//		if (zSortXML != null) {
+//			zSort = new ZSort(this);
+//			zSort.setXMLEntity(zSortXML);
+//		}
+	}
+
+
+//	public ILegend cloneLegend() throws XMLException {
+//		return (ILegend) LegendFactory.createFromXML(getXMLEntity());
+//	}
+
+
+	public int getShapeType() {
+		return shapeType;
+	}
+
+	public void setShapeType(int shapeType) {
+		if (this.shapeType != shapeType) {
+			defaultSymbol = getSymbolManager().createSymbol(shapeType);
+			this.shapeType = shapeType;
+		}
+	}
+
+    public ISymbol getSymbolByFeature(Feature feat) {
+        return defaultSymbol;
+    }
+
+	public void useDefaultSymbol(boolean b) {
+		// TODO Auto-generated method stub
+	}
+
+    public String[] getUsedFields() {
+        return new String[0];
+    }
+
+    public boolean isUseDefaultSymbol() {
+    	return true;
+
+    }
+
+
+    public String getClassName() {
+		return getClass().getName();
+	}
+
+    public boolean isSuitableForShapeType(int shapeType) {
+		return getShapeType() == shapeType;
+	}
+
+
+	public void setFeatureStore(FeatureStore fs) throws DataException {
+		// TODO Auto-generated method stub
+
+	}
+	
+	protected String[] getRequiredFeatureAttributeNames(
+			FeatureStore featureStore) throws DataException {
+		// We only need the default Geometry to draw
+		return new String[] { featureStore
+				.getDefaultFeatureType().getDefaultGeometryAttributeName() };
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		SingleSymbolLegend clone = (SingleSymbolLegend) super.clone();
+
+		// Clone default symbol
+		if (defaultSymbol != null) {
+			clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
+		}
+
+		return clone;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				SingleSymbolLegend.class,
+				SINGLE_SYMBOL_DYNCLASS_NAME,
+				SINGLE_SYMBOL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the Vectorial Legend base definition
+		definition.extend(VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractIntervalLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractIntervalLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractIntervalLegend.java	(revision 33580)
@@ -0,0 +1,653 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureReference;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.mapcontext.MapContextException;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
+import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialIntervalLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dispose.DisposableIterator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractIntervalLegend extends
+		AbstractClassifiedVectorLegend implements IVectorialIntervalLegend {
+
+	public static final String INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME = "IntervalLegend";
+
+	private static final String FIELD_KEYS = "keys";
+	private static final String FIELD_INTERVAL_TYPE = "intervalType";
+	private static final String FIELD_USE_DEFAULT_SYMBOL = "useDefaultSymbol";
+	private static final String FIELD_NULL_INTERVAL_SYMBOL =
+			"nullIntervalSymbol";
+	private static final String FIELD_SYMBOLS = "symbols";
+	
+	protected List<Object> keys = new ArrayList<Object>(); // <Object>
+	// protected int index = 0;
+	// protected int fieldId;
+	protected ISymbol defaultSymbol;
+	// protected FeatureStore featureStore;
+	protected int intervalType = NATURAL_INTERVALS;
+	protected boolean useDefaultSymbol = false;
+
+	private ISymbol nullIntervalSymbol = null;
+
+	public static final int EQUAL_INTERVALS = 0;
+	public static final int NATURAL_INTERVALS = 1;
+	public static final int QUANTILE_INTERVALS = 2;
+	protected Map<Object, ISymbol> symbols = createSymbolMap();
+	final static private Logger logger = LoggerFactory.getLogger(AbstractIntervalLegend.class);
+	
+	public void addSymbol(Object key, ISymbol symbol) {
+		if (key == null) {
+			nullIntervalSymbol = symbol;
+		}
+		else {
+			symbols.put(key, symbol);
+			keys.add(key);
+		}
+		fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(null, symbol));
+	}
+
+	/*
+	 * @see com.iver.cit.gvsig.fmap.rendering.IVectorialLegend#getSymbol(int)
+	 */
+	public ISymbol getSymbol(FeatureReference featureID)
+			throws MapContextException, DataException {
+		return getSymbolByFeature(featureID.getFeature());
+		
+//		Object val = featureStore.getFeatureByReference(featureID).get(getClassifyingFieldNames()[0]);
+//		IInterval interval = getInterval(val);
+//		ISymbol theSymbol = getSymbolByInterval(interval);
+//
+//		if (theSymbol != null) {
+//			return theSymbol;
+//		} else if (useDefaultSymbol) {
+//			return getDefaultSymbol();
+//		}
+//		return null;
+
+	}
+
+	public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
+		Object val = feat.get(getClassifyingFieldNames()[0]);
+		IInterval interval = getInterval(val);
+		ISymbol theSymbol = getSymbolByInterval(interval);
+
+		if (theSymbol != null) {
+			return theSymbol;
+		} else if (useDefaultSymbol) {
+			return getDefaultSymbol();
+		}
+		
+		return null;
+//		return theSymbol;
+	}
+
+
+	public IInterval[] calculateIntervals(FeatureStore featureStore,
+			String fieldName, int numIntervalos, int shapeType)
+	throws DataException {
+		logger.debug("elRs.start()");
+//		recordSet.start();
+
+//		int idField = -1;
+		FeatureSet set = null;
+		DisposableIterator iterator = null;
+		try {
+
+		setClassifyingFieldNames(new String[] {fieldName});
+
+		String[] fieldNames = getClassifyingFieldNames();
+		FeatureQuery featureQuery=featureStore.createFeatureQuery();
+		featureQuery.setAttributeNames(fieldNames);
+
+		set = featureStore.getFeatureSet(featureQuery);
+		iterator = set.fastIterator();
+
+
+//		for (int i = 0; i < recordSet.getFieldCount(); i++) {
+//			String nomAux = recordSet.getFieldName(i).trim();
+//
+//			if (fieldNames[0].compareToIgnoreCase(nomAux) == 0) {
+//				idField = i;
+//
+//				break;
+//			}
+//		}
+
+//		if (idField == -1) {
+//			logger.error("Campo no reconocido " + fieldNames);
+//
+//			return null;
+//		}
+
+		double minValue = Double.MAX_VALUE;
+		double maxValue = Double.NEGATIVE_INFINITY;
+
+		IVectorialIntervalLegend auxLegend = (IVectorialIntervalLegend) MapContextLocator
+					.getMapContextManager().createLegend("VectorialInterval");
+		auxLegend.setShapeType(shapeType);
+
+		Object clave;
+
+		while (iterator.hasNext()) {
+			Feature feature = (Feature) iterator.next();
+
+//		for (int j = 0; j < recordSet.getRowCount(); j++) {
+			clave = feature.get(fieldName);
+
+			IInterval interval = auxLegend.getInterval(clave);
+
+			////Comprobar que no esta repetido y no hace falta introducir en el hashtable el campo junto con el simbolo.
+			if (auxLegend.getSymbolByInterval(interval) == null) {
+				//si no esta creado el simbolo se crea
+				double valor = 0;
+
+
+				if (clave instanceof Number) {
+					valor=((Number)clave).doubleValue();
+				}else if (clave instanceof Date) {
+					//TODO POR IMPLEMENTAR
+					///valorDate = elRs.getFieldValueAsDate(idField);
+					///if (valorDate.before(minValueDate)) minValueDate = valorDate;
+					///if (valorDate.after(maxValueDate)) maxValueDate = valorDate;
+//				} else if (clave instanceof NullValue) {
+//					continue;
+				}
+
+				if (valor < minValue) {
+					minValue = valor;
+				}
+
+				if (valor > maxValue) {
+					maxValue = valor;
+				}
+			}
+		}
+
+			IInterval[] intervalArray = null;
+		switch (getIntervalType()) {
+		case VectorialIntervalLegend.EQUAL_INTERVALS:
+			intervalArray = calculateEqualIntervals(numIntervalos,
+					minValue, maxValue, fieldName);
+
+			break;
+
+		case VectorialIntervalLegend.NATURAL_INTERVALS:
+			intervalArray = calculateNaturalIntervals(featureStore, numIntervalos,
+					minValue, maxValue, fieldName);
+
+			break;
+
+		case VectorialIntervalLegend.QUANTILE_INTERVALS:
+			intervalArray = calculateQuantileIntervals(featureStore, numIntervalos,
+					minValue, maxValue, fieldName);
+
+			break;
+		}
+//		recordSet.stop();
+		return intervalArray;
+		} finally {
+			if (iterator != null) {
+				iterator.dispose();
+			}
+			if (set != null) {
+				set.dispose();
+			}
+		}
+	}
+
+
+    /**
+     * EQUAL INTERVAL Devuelve un Array con el n�mero de intervalos que se
+     * quieren crear. Los intervalos se crean con un tama�o igual entre ellos.
+     * @param numIntervals n�mero de intervalos
+     * @param minValue Valor m�nimo.
+     * @param maxValue Valor m�ximo.
+     * @param fieldName Nombre del campo
+     *
+     * @return Array con los intervalos.
+     */
+	private IInterval[] calculateEqualIntervals(int numIntervals,
+			double minValue,
+        double maxValue, String fieldName) {
+		IInterval[] theIntervalArray = new IInterval[numIntervals];
+        double step = (maxValue - minValue) / numIntervals;
+
+        if (numIntervals > 1) {
+            theIntervalArray[0] = new FInterval(minValue, minValue + step);
+
+            for (int i = 1; i < (numIntervals - 1); i++) {
+                theIntervalArray[i] = new FInterval(minValue + (i * step) +
+                        0.01, minValue + ((i + 1) * step));
+            }
+
+            theIntervalArray[numIntervals - 1] = new FInterval(minValue +
+                    ((numIntervals - 1) * step) + 0.01, maxValue);
+        } else {
+            theIntervalArray[0] = new FInterval(minValue, maxValue);
+        }
+
+        return theIntervalArray;
+    }
+
+    /**
+     * NATURAL INTERVAL Devuelve un Array con el n�mero de intervalos que se
+     * quieren crear. Los intervalos se distribuyen de forma natural.
+     *
+     * @param numIntervals n�mero de intervalos
+     * @param minValue Valor m�nimo.
+     * @param maxValue Valor m�ximo.
+     * @param fieldName Nombre del campo
+     *
+     * @return Array con los intervalos.
+     * @throws DataException 
+     * @throws LegendLayerException
+     */
+	private IInterval[] calculateNaturalIntervals(FeatureStore featureStore,
+			int numIntervals, double minValue,
+        double maxValue, String fieldName) throws DataException {
+        NaturalIntervalGenerator intervalGenerator = new NaturalIntervalGenerator(
+        		featureStore, fieldName, numIntervals);
+
+        intervalGenerator.generarIntervalos();
+
+        int numIntervalsGen = intervalGenerator.getNumIntervals() - 1;
+
+        if (numIntervalsGen == -1) {
+            //TODO cuando no puede calcular los intervalos.
+            numIntervalsGen = 1;
+        }
+
+        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
+
+        if (numIntervalsGen > 1) {
+            theIntervalArray[0] = new FInterval(minValue,
+                    intervalGenerator.getValorRuptura(0));
+
+            for (int i = 1; i < (numIntervalsGen - 1); i++) {
+                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
+                            1), intervalGenerator.getValorRuptura(i));
+            }
+
+            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
+                        2), maxValue);
+        } else {
+            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
+                    maxValue);
+        }
+
+        return theIntervalArray;
+    }
+
+    /**
+     * QUANTILE INTERVAL Devuelve un Array con el n�mero de intervalos que se
+     * quieren crear. Los intervalos se distribuyen de forma quantile.
+     * @param recordSet
+     *
+     * @param numIntervals n�mero de intervalos
+     * @param minValue Valor m�nimo.
+     * @param maxValue Valor m�ximo.
+     * @param fieldName Nombre del campo
+     *
+     * @return Array con los intervalos.
+     * @throws LegendLayerException
+     */
+	private IInterval[] calculateQuantileIntervals(FeatureStore featureStore,
+			int numIntervals, double minValue,
+        double maxValue, String fieldName) throws DataException {
+        QuantileIntervalGenerator intervalGenerator = new QuantileIntervalGenerator(
+        		featureStore, fieldName, numIntervals);
+
+        intervalGenerator.generarIntervalos();
+
+        int numIntervalsGen = intervalGenerator.getNumIntervalGen();
+        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
+
+        if (intervalGenerator.getNumIntervalGen() > 1) {
+            theIntervalArray[0] = new FInterval(minValue,
+                    intervalGenerator.getValRuptura(0));
+
+            for (int i = 1; i < (numIntervalsGen - 1); i++) {
+                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
+                            1), intervalGenerator.getValRuptura(i));
+            }
+
+            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
+                        2), maxValue);
+        } else {
+            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
+                    maxValue);
+        }
+
+        return theIntervalArray;
+    }
+
+    public ISymbol getSymbolByInterval(IInterval key) {
+
+		if (key == null){
+			if (nullIntervalSymbol != null) {
+				return nullIntervalSymbol;
+			}
+			else if (isUseDefaultSymbol()) {
+				return defaultSymbol;
+			}
+			return null;
+		}
+		if (symbols.containsKey(key)) {
+			return (ISymbol) symbols.get(key);
+		}
+
+		if (isUseDefaultSymbol()) {
+			return defaultSymbol;
+		}
+
+		return null;
+	}
+
+
+	public String[] getDescriptions() {
+		String[] descriptions = new String[symbols.size()];
+		ISymbol[] auxSym = getSymbols();
+
+		for (int i = 0; i < descriptions.length; i++) {
+			descriptions[i] = auxSym[i].getDescription();
+		}
+
+		return descriptions;
+	}
+
+
+	public Object[] getValues() {
+		return symbols.keySet().toArray();
+	}
+
+	public void clear() {
+		// index = 0;
+		keys.clear();
+		symbols.clear();
+	}
+
+	public ISymbol[] getSymbols() {
+		ISymbol[] symbolList;
+		if (nullIntervalSymbol == null) {
+			symbolList = new ISymbol[symbols.size()];
+			return (ISymbol[]) symbols.values().toArray(symbolList);
+		}
+		else {
+			symbolList = new ISymbol[symbols.size() + 1];
+			symbolList[0] = nullIntervalSymbol;
+			int i = 1;
+			for (Iterator<ISymbol> iterator = symbols.values().iterator(); iterator.hasNext();) {
+				symbolList[i] = iterator.next();
+				i++;
+			}
+			return symbolList;
+		}
+	}
+
+	public void setDefaultSymbol(ISymbol s) {
+	    ISymbol old = defaultSymbol;
+		if (s == null) {
+			throw new NullPointerException("Default symbol cannot be null");
+		}
+		defaultSymbol = s;
+		fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
+	}
+
+	public ISymbol getDefaultSymbol() {
+//		NullIntervalValue niv=new NullIntervalValue();
+//		if (symbols.containsKey(niv)) {
+//			return (ISymbol)symbols.get(niv);
+//		}
+
+		if(defaultSymbol==null) {
+			defaultSymbol = getSymbolManager().createSymbol(getShapeType());
+		}
+		return defaultSymbol;
+	}
+
+
+
+//    public void setFeatureStore(FeatureStore featureStore)
+//        throws DataException {
+//    		/*
+//    		 * when we move definitely to feature iterators this
+//    		 * method
+//    		 */
+//    		this.featureStore = featureStore;
+////    		fieldId = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(fieldNames[0]);
+//    }
+
+
+	public IInterval getInterval(Object v) {
+		if (v != null ) {
+			for (int i = 0; i < keys.size(); i++) {
+				if (((IInterval) keys.get(i)).isInInterval(v)) {
+					return (IInterval) keys.get(i);
+				}
+			}
+		}
+
+		return null;
+	}
+
+	public void setIntervalType(int intervalType) {
+		this.intervalType = intervalType;
+	}
+
+
+	public int getIntervalType() {
+		return intervalType;
+	}
+
+	public void useDefaultSymbol(boolean b) {
+		useDefaultSymbol = b;
+	}
+
+
+	public boolean isUseDefaultSymbol() {
+		return useDefaultSymbol;
+	}
+
+
+	public void delSymbol(Object obj) {
+		keys.remove(obj);
+		symbols.remove(obj);
+		fireClassifiedSymbolChangeEvent(
+				new SymbolLegendEvent(
+						(ISymbol)symbols.remove(obj),
+						null));
+	}
+
+
+	public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
+		if (symbols.containsValue(oldSymbol)) {
+			Iterator<Object> it = symbols.keySet().iterator();
+			while (it.hasNext()) {
+				Object key = it.next();
+				if (symbols.get(key).equals(oldSymbol)) {
+					symbols.remove(key);
+					symbols.put(key, newSymbol);
+					fireClassifiedSymbolChangeEvent(
+							new SymbolLegendEvent(oldSymbol, newSymbol));
+				}
+			}
+		}
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		AbstractIntervalLegend clone = (AbstractIntervalLegend) super.clone();
+
+		// Clone null interval symbol
+		if (nullIntervalSymbol != null) {
+			clone.nullIntervalSymbol = (ISymbol) nullIntervalSymbol.clone();
+		}
+		
+		// Clone default symbol
+		if (defaultSymbol != null) {
+			clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
+		}
+		// Clone keys
+		clone.keys = new ArrayList<Object>();
+		
+		// Clone symbols
+		if (symbols != null) {
+			clone.symbols = createSymbolMap();
+			for (Iterator<Entry<Object, ISymbol>> iterator =
+					symbols.entrySet().iterator(); iterator.hasNext();) {
+				Entry<Object, ISymbol> entry = iterator.next();
+				IInterval intervalClone =
+						(IInterval) ((IInterval) entry.getKey()).clone();
+				ISymbol symbolClone =
+						(ISymbol) ((ISymbol) entry.getValue()).clone();
+				clone.addSymbol(intervalClone, symbolClone);
+			}
+		}
+
+		return clone;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+		// Set own properties
+		setIntervalType(state.getInt(FIELD_INTERVAL_TYPE));
+		keys = new ArrayList<Object>(state.getList(FIELD_KEYS));
+		nullIntervalSymbol = (ISymbol) state.get(FIELD_NULL_INTERVAL_SYMBOL);
+		useDefaultSymbol(state.getBoolean(FIELD_USE_DEFAULT_SYMBOL));
+		Map persistedSymbolMap = (Map) state.get(FIELD_SYMBOLS);
+		if (persistedSymbolMap != null) {
+			symbols.putAll(persistedSymbolMap);
+		}
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_INTERVAL_TYPE, getIntervalType());
+		state.set(FIELD_KEYS, keys);
+		state.set(FIELD_NULL_INTERVAL_SYMBOL, nullIntervalSymbol);
+		state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
+		state.set(FIELD_SYMBOLS, symbols);
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				AbstractIntervalLegend.class,
+				INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME,
+				INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME+" Persistence definition (FIXME check keys type)",
+				null, 
+				null
+		);
+		
+		// Extend the Classified Vector Legend base definition
+		definition.extend(CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Interval type
+		definition.addDynFieldInt(FIELD_INTERVAL_TYPE).setMandatory(true);
+		// Keys
+		definition.addDynFieldList(FIELD_KEYS)
+			.setClassOfItems(int.class);
+		// Null interval symbol
+		definition.addDynFieldObject(FIELD_NULL_INTERVAL_SYMBOL)
+			.setClassOfValue(ISymbol.class)
+			.setMandatory(true);
+		// Use default symbol?
+		definition.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
+		// Symbols
+		definition.addDynFieldMap(FIELD_SYMBOLS).setClassOfItems(ISymbol.class);
+	}
+
+	private Map<Object, ISymbol> createSymbolMap() {
+		return new TreeMap<Object, ISymbol>
+		(new Comparator<Object>() { 
+					public int compare(Object o1, Object o2) {
+						if ((o1 != null) && (o2 != null)) {
+							// if (o1 instanceof NullIntervalValue &&
+							// o2 instanceof NullIntervalValue) {
+							// return 0;
+							// }
+							//
+							// if (o2 instanceof NullIntervalValue) {
+							// return 1;
+							// }
+							//
+							// if (o1 instanceof NullIntervalValue) {
+							// return -1;
+							// }
+
+							FInterval i2 = (FInterval) o2;
+							FInterval i1 = (FInterval) o1;
+
+							if (i1.getMin() > i2.getMin()) {
+								return 1;
+							}
+
+							if (i1.getMin() < i2.getMin()) {
+								return -1;
+							}
+							if (i1.getMax() < i2.getMax()) {
+								return -1;
+							}
+							if (i1.getMax() > i2.getMax()) {
+								return 1;
+							}
+						}
+
+						return 0;
+					}
+				});
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/LegendDrawingException.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/LegendDrawingException.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/LegendDrawingException.java	(revision 33580)
@@ -0,0 +1,54 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+*
+* Copyright (C) 2007-2008 Infrastructures and Transports Department
+* of the Valencian Government (CIT)
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+* MA  02110-1301, USA.
+* 
+*/
+
+/*
+* AUTHORS (In addition to CIT):
+* 2009 {DiSiD Technologies}  {{Task}}
+*/
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
+
+/**
+ * Exception thrown when there is an error while a {@link ILegend} is drawing.
+ * 
+ * @author <a href="mailto:cordinyana@gvsig.org">C�sar Ordi�ana</a>
+ */
+public class LegendDrawingException extends LegendException {
+	
+	private static final long serialVersionUID = 4322970061384248489L;
+
+	private static final String KEY = "legend_drawing_exception";
+
+    private static final String MESSAGE = "Error while drawing the legend";
+    
+	/**
+	 * Creates a new {@link LegendDrawingException} with the original cause.
+	 * 
+	 * @param cause
+	 *            of the exception
+	 */
+	public LegendDrawingException(Throwable cause) {
+		super(MESSAGE, cause, KEY, serialVersionUID);
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/FInterval.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/FInterval.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/FInterval.java	(revision 33580)
@@ -0,0 +1,185 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Clase intervalo.
+ * 
+ * @author Vicente Caballero Navarro
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class FInterval implements IInterval {
+	public static final String FINTERVAL_DYNCLASS_NAME = "FInterval";
+
+	private static final String FIELD_MIN = "min";
+	private static final String FIELD_MAX = "max";
+
+	private double min;
+	private double max;
+
+	/**
+	 * Creates a new empty FInterval, used to be instantiated by persistence
+	 */
+	public FInterval(){
+		// Nothing to do
+	}
+
+	/**
+	 * Crea un nuevo FInterval.
+	 *
+	 * @param from Origen.
+	 * @param to Destino.
+	 */
+	public FInterval(double from, double to) {
+		this.min = from;
+		this.max = to;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.rendering.IInterval#isInInterval(com.hardcode.gdbms.engine.values.Value)
+	 */
+	public boolean isInInterval(Object v) {
+		double valor=0;
+		if (v == null){
+			return false;
+		}else if (v instanceof Number) {
+			valor = ((Number) v).doubleValue();
+		}
+		return ((valor >= min) && (valor <= max));
+	}
+
+	/**
+	 * Devuelve el n�mero de origen.
+	 *
+	 * @return N�mero de inicio.
+	 */
+	public double getMin() {
+		return min;
+	}
+
+	/**
+	 * Devuelve el n�mero final.
+	 *
+	 * @return N�mero final.
+	 */
+	public double getMax() {
+		return max;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.rendering.IInterval#toString()
+	 */
+	public String toString() {
+		return min + "-" + max;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		min = state.getDouble(FIELD_MIN);
+		max = state.getDouble(FIELD_MAX);
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_MIN, getMin());
+		state.set(FIELD_MAX, getMax());
+	}
+
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				FInterval.class,
+				FINTERVAL_DYNCLASS_NAME,
+				FINTERVAL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		definition.addDynFieldDouble(FIELD_MIN)
+				.setMandatory(true)
+				.setDescription("Minimum interval value");
+		definition.addDynFieldDouble(FIELD_MAX).setMandatory(true).setDescription(
+				"Maximum interval value");
+
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		return super.clone();
+	}
+
+	/**
+	 * Crea un FInterval nuevo a partir de un String con el n�mero inicial un
+	 * gui�n y el n�mero final.
+	 *
+	 * @param s String.
+	 *
+	 * @return FInterval nuevo.
+	 */
+//	public static IInterval create(String s) {
+//		//String[] str = s.split("-");
+//        String[] str = CompatLocator.getStringUtils().split(s,"-");
+//		if (s.startsWith("-")) {
+//			str[0]="-"+str[1];
+//			CompatLocator.getStringUtils().replaceFirst(s,"-","");
+//			str[1]=str[2];
+//		}
+//		if (s.contentEquals(new StringBuffer("--"))) {
+//			str[1]=s.substring(s.indexOf('-')+1,s.length()-1);
+//		}
+//
+//		IInterval inter=null;
+//		try{
+//		inter = new FInterval(Double.parseDouble(str[0]),
+//				Double.parseDouble(str[1]));
+//		}catch (NumberFormatException e) {
+////			return new NullIntervalValue();
+//			return null;
+//		}
+//		return inter;
+//	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractVectorialLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractVectorialLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractVectorialLegend.java	(revision 33580)
@@ -0,0 +1,940 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+/*
+ * AUTHORS (In addition to CIT):
+ * 2009 {DiSiD Technologies}  {{Task}}
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.cresques.cts.ICoordTrans;
+import org.cresques.cts.IProjection;
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.exception.ReadException;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureSelection;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.aggregate.Aggregate;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.operation.DrawInts;
+import org.gvsig.fmap.geom.operation.DrawOperationContext;
+import org.gvsig.fmap.geom.operation.GeometryOperationException;
+import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
+import org.gvsig.fmap.geom.primitive.Envelope;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.MapContextException;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.layers.vectorial.ContainsEnvelopeEvaluator;
+import org.gvsig.fmap.mapcontext.layers.vectorial.IntersectsEnvelopeEvaluator;
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
+import org.gvsig.fmap.mapcontext.rendering.legend.ZSort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dispose.DisposableIterator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.exception.BaseException;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.gvsig.tools.visitor.VisitCanceledException;
+import org.gvsig.tools.visitor.Visitor;
+
+/**
+ * Base implementation for Vectorial data Legends.
+ * 
+ * Provides a draw method implementation which loads the {@link Feature}s and
+ * uses the {@link ISymbol} objects to draw the {@link Geometry} objects.
+ * 
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractVectorialLegend extends AbstractLegend implements
+		IVectorLegend {
+
+	public static final String VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME =
+			"VectorialLegend";
+
+	private static final String FIELD_HAS_ZSORT = "hasZSort";
+	private static final String FIELD_SHAPETYPE = "shapeType";
+	private static final String FIELD_DEFAULT_SYMBOL = "defaultSymbol";
+
+	private static final GeometryManager geomManager =
+			GeometryLocator.getGeometryManager();
+
+	protected ZSort zSort;
+
+	public ZSort getZSort() {
+		return zSort;
+	}
+
+	public void setZSort(ZSort zSort) {
+		if (zSort == null) {
+			removeLegendListener(this.zSort);
+		}
+		this.zSort = zSort;
+		addLegendListener(zSort);
+	}
+
+	@SuppressWarnings("unchecked")
+	public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
+			Cancellable cancel, double scale, Map queryParameters,
+			ICoordTrans coordTrans, FeatureStore featureStore)
+			throws LegendException {
+		double dpi = MapContext.getScreenDPI();
+		draw(image, g, viewPort, cancel, scale, queryParameters, coordTrans,
+				featureStore, dpi);
+	}
+
+	@SuppressWarnings("unchecked")
+	public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
+			double scale, Map queryParameters, ICoordTrans coordTrans,
+			FeatureStore featureStore, PrintAttributes properties)
+			throws LegendException {
+		double dpi = 72;
+
+		int resolution = properties.getPrintQuality();
+
+		if (resolution == PrintAttributes.PRINT_QUALITY_NORMAL) {
+			dpi = 300;
+		} else if (resolution == PrintAttributes.PRINT_QUALITY_HIGH) {
+			dpi = 600;
+		} else if (resolution == PrintAttributes.PRINT_QUALITY_DRAFT) {
+			dpi = 72;
+		}
+
+		FeatureSet featureSet = null;
+		DisposableIterator it = null;
+		try {
+			ZSort zSort = getZSort();
+
+			// if layer has map levels it will use a ZSort
+			boolean useZSort = zSort != null && zSort.isUsingZSort();
+
+			int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
+			for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
+				// Get the iterator over the visible features
+				String[] fieldNames =
+						getRequiredFeatureAttributeNames(featureStore);
+
+				FeatureQuery featureQuery = featureStore.createFeatureQuery();
+				featureQuery.setAttributeNames(fieldNames);
+				featureQuery.setScale(scale);
+
+				ContainsEnvelopeEvaluator iee =
+						new ContainsEnvelopeEvaluator(
+								viewPort.getAdjustedEnvelope(),
+								viewPort.getProjection(),
+								featureStore.getDefaultFeatureType(),
+								featureStore.getDefaultFeatureType()
+										.getDefaultGeometryAttributeName());
+				featureQuery.setFilter(iee);
+				featureSet = featureStore.getFeatureSet(featureQuery);
+				it = featureSet.fastIterator();
+
+				// Iteration over each feature
+				while (!cancel.isCanceled() && it.hasNext()) {
+					Feature feat = (Feature) it.next();
+					Geometry geom = feat.getDefaultGeometry();
+
+					// retrieve the symbol associated to such feature
+					ISymbol sym = getSymbolByFeature(feat);
+					if (sym == null) {
+						continue;
+					}
+					if (useZSort) {
+						int[] symLevels = zSort.getLevels(sym);
+						if (symLevels != null) {
+
+							// Check if this symbol is a multilayer
+							if (sym instanceof IMultiLayerSymbol) {
+								// if so, get the layer corresponding to the
+								// current level. If none, continue to next
+								// iteration
+								IMultiLayerSymbol mlSym =
+										(IMultiLayerSymbol) sym;
+								for (int i = 0; i < mlSym.getLayerCount(); i++) {
+									ISymbol mySym = mlSym.getLayer(i);
+									if (symLevels[i] == mapPass) {
+										sym = mySym;
+										break;
+									}
+								}
+
+							} else {
+								// else, just draw the symbol in its level
+								if (symLevels[0] != mapPass) {
+									continue;
+								}
+							}
+						}
+					}
+
+					// Check if this symbol is sized with CartographicSupport
+					CartographicSupport csSym = null;
+					int symbolType = sym.getSymbolType();
+
+					if (symbolType == Geometry.TYPES.POINT
+							|| symbolType == Geometry.TYPES.CURVE
+							|| sym instanceof CartographicSupport) {
+
+						csSym = (CartographicSupport) sym;
+					}
+
+					DrawOperationContext doc = new DrawOperationContext();
+					doc.setGraphics(g);
+					doc.setViewPort(viewPort);
+					if (csSym == null) {
+						doc.setSymbol(sym);
+					} else {
+						doc.setDPI(dpi);
+						doc.setCancellable(cancel);
+						doc.setSymbol((ISymbol) csSym);
+					}
+					geom.invokeOperation(DrawInts.CODE, doc);
+				}
+			}
+		} catch (ReadException e) {
+			throw new LegendDrawingException(e);
+		} catch (GeometryOperationNotSupportedException e) {
+			throw new LegendDrawingException(e);
+		} catch (GeometryOperationException e) {
+			throw new LegendDrawingException(e);
+		} catch (DataException e) {
+			throw new LegendDrawingException(e);
+		} catch (MapContextException e) {
+			throw new LegendDrawingException(e);
+		} finally {
+			if (it != null) {
+				it.dispose();
+			}
+			if (featureSet != null) {
+				featureSet.dispose();
+			}
+		}
+	}
+
+	/**
+	 * Draws the features from the {@link FeatureStore}, filtered with the scale
+	 * and the query parameters, with the symbols of the legend.
+	 */
+	@SuppressWarnings("unchecked")
+	protected void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
+			Cancellable cancel, double scale, Map queryParameters,
+			ICoordTrans coordTrans, FeatureStore featureStore, double dpi)
+			throws LegendException {
+
+		if (!getDefaultSymbol().isShapeVisible()) {
+			return;
+		}
+
+		if (cancel.isCanceled()) {
+			return;
+		}
+
+		IProjection dataProjection;
+		Envelope reprojectedDataEnvelop;
+
+		try {
+			if (coordTrans == null) {
+				dataProjection =
+						featureStore.getDefaultFeatureType().getDefaultSRS();
+
+				// If the data does not provide a projection, use the current
+				// view one
+				if (dataProjection == null) {
+					dataProjection = viewPort.getProjection();
+				}
+
+				reprojectedDataEnvelop = featureStore.getEnvelope();
+			} else {
+				dataProjection = coordTrans.getPOrig();
+
+				reprojectedDataEnvelop =
+						featureStore.getEnvelope().convert(coordTrans);
+			}
+		} catch (DataException e) {
+			throw new LegendDrawingException(e);
+		}
+
+		// Gets the view envelope
+		Envelope viewPortEnvelope = viewPort.getAdjustedEnvelope();
+
+		// Gets the data envelope with the viewport SRS
+		Envelope myEnvelope = reprojectedDataEnvelop;
+
+		// TODO: in some cases, the legend may need a different check to
+		// decide if the data must be drawn or not
+		// Checks if the viewport envelope intersects with the data envelope
+		if (!viewPortEnvelope.intersects(myEnvelope)) {
+			// The data is not visible in the current viewport, do nothing.
+			return;
+		}
+
+		// Check if all the data is contained into the viewport envelope
+		boolean containsAll = viewPortEnvelope.contains(myEnvelope);
+
+		// Create the drawing notification to be reused on each iteration
+		DefaultFeatureDrawnNotification drawnNotification =
+				new DefaultFeatureDrawnNotification();
+
+		if (cancel.isCanceled()) {
+			return;
+		}
+
+		FeatureSet featureSet = null;
+		try {
+			FeatureSelection selection = featureStore.getFeatureSelection();
+
+			FeatureQuery featureQuery =
+					createQuery(featureStore, scale, queryParameters,
+							coordTrans, dataProjection, viewPortEnvelope,
+							containsAll);
+
+			featureSet = featureStore.getFeatureSet(featureQuery);
+
+			if (cancel.isCanceled()) {
+				return;
+			}
+
+			drawFeatures(image, g, viewPort, cancel, coordTrans, dpi,
+					drawnNotification, featureSet, selection);
+
+		} catch (BaseException e) {
+			throw new LegendDrawingException(e);
+		} finally {
+			if (featureSet != null) {
+				featureSet.dispose();
+			}
+		}
+
+	}
+
+	/**
+	 * Creates a {@link FeatureQuery} to load the {@link Feature}s to draw.
+	 */
+	@SuppressWarnings("unchecked")
+	private FeatureQuery createQuery(FeatureStore featureStore, double scale,
+			Map queryParameters, ICoordTrans coordTrans,
+			IProjection dataProjection, Envelope viewPortEnvelope,
+			boolean containsAll) throws DataException {
+
+		FeatureQuery featureQuery = featureStore.createFeatureQuery();
+		featureQuery.setScale(scale);
+		String[] fieldNames =
+			getRequiredFeatureAttributeNames(featureStore);
+		featureQuery.setAttributeNames(fieldNames);
+		// TODO: Mobile has it's own IntersectsEnvelopeEvaluator
+		if (!containsAll) {
+			// Gets the viewport envelope with the data SRS
+			Envelope viewPortEnvelopeInMyProj = viewPortEnvelope;
+			// FIXME
+			if (coordTrans != null) {
+				viewPortEnvelopeInMyProj =
+						viewPortEnvelope.convert(coordTrans.getInverted());
+			}
+
+			if (dataProjection == null) {
+				throw new IllegalArgumentException(
+						"Error, the projection parameter value is null");
+			}
+
+			IntersectsEnvelopeEvaluator iee =
+					new IntersectsEnvelopeEvaluator(viewPortEnvelopeInMyProj,
+							dataProjection,
+							featureStore.getDefaultFeatureType(),
+							featureStore.getDefaultFeatureType()
+									.getDefaultGeometryAttributeName());
+			featureQuery.setFilter(iee);
+		}
+		if (queryParameters != null) {
+			Iterator iterEntry = queryParameters.entrySet().iterator();
+			Entry entry;
+			while (iterEntry.hasNext()) {
+				entry = (Entry) iterEntry.next();
+				featureQuery.setQueryParameter((String) entry.getKey(),
+						entry.getValue());
+			}
+		}
+		return featureQuery;
+	}
+
+	/**
+	 * Draws the features from the {@link FeatureSet}, with the symbols of the
+	 * legend.
+	 */
+	private void drawFeatures(BufferedImage image, Graphics2D g,
+			ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans,
+			double dpi, DefaultFeatureDrawnNotification drawnNotification,
+			FeatureSet featureSet, FeatureSelection selection)
+			throws BaseException {
+		if (isUseZSort()) {
+			drawFeaturesMultiLayer(image, g, viewPort, cancel, coordTrans, dpi,
+					drawnNotification, featureSet, selection);
+		} else {
+			drawFeaturesSingleLayer(image, g, viewPort, cancel, coordTrans,
+					dpi, drawnNotification, featureSet, selection);
+		}
+	}
+
+	/**
+	 * Draws the features from the {@link FeatureSet}, with the symbols of the
+	 * legend, using a single drawing layer.
+	 */
+	private void drawFeaturesSingleLayer(final BufferedImage image,
+			final Graphics2D g, final ViewPort viewPort,
+			final Cancellable cancel, final ICoordTrans coordTrans,
+			final double dpi,
+			final DefaultFeatureDrawnNotification drawnNotification,
+			FeatureSet featureSet, final FeatureSelection selection)
+			throws BaseException {
+
+		try {
+			featureSet.accept(new Visitor() {
+				public void visit(Object obj) throws VisitCanceledException,
+						BaseException {
+					Feature feat = (Feature) obj;
+					drawFeatureSingleLayer(image, g, viewPort, cancel,
+							coordTrans, dpi, drawnNotification, feat, selection);
+				}
+			});
+
+		} catch (ConcurrentDataModificationException e) {
+			cancel.setCanceled(true);
+			return;
+		}
+	}
+
+	/**
+	 * Draws a Feature with the symbols of the legend, using a single drawing
+	 * layer.
+	 */
+	private void drawFeatureSingleLayer(BufferedImage image, Graphics2D g,
+			ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans,
+			double dpi, DefaultFeatureDrawnNotification drawnNotification,
+			Feature feat, FeatureSelection selection)
+			throws MapContextException, CreateGeometryException {
+
+		Geometry geom = feat.getDefaultGeometry();
+
+		if (geom.getType() == Geometry.TYPES.NULL) {
+			return;
+		}
+
+		ISymbol sym = getSymbol(feat, selection);
+		if (sym == null) {
+			return;
+		}
+
+		if (coordTrans != null) {
+			geom = geom.cloneGeometry();
+			geom.reProject(coordTrans);
+		}
+
+		if (cancel.isCanceled()) {
+			return;
+		}
+
+		drawGeometry(geom, image, feat, sym, viewPort, g, dpi, cancel);
+
+		// Notify the drawing observers
+		drawnNotification.setFeature(feat);
+		drawnNotification.setDrawnGeometry(geom);
+		notifyObservers(drawnNotification);
+	}
+
+	/**
+	 * Draws the features from the {@link FeatureSet}, with the symbols of the
+	 * legend, using a multiple drawing layer.
+	 */
+	private void drawFeaturesMultiLayer(BufferedImage image, Graphics2D g,
+			ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans,
+			double dpi, DefaultFeatureDrawnNotification drawnNotification,
+			FeatureSet featureSet, FeatureSelection selection)
+			throws MapContextException, CreateGeometryException, DataException {
+
+		// -- visual FX stuff
+		long time = System.currentTimeMillis();
+
+		boolean bSymbolLevelError = false;
+		// render temporary map each screenRefreshRate milliseconds;
+		int screenRefreshDelay =
+				(int) ((1D / MapContext.getDrawFrameRate()) * 3 * 1000);
+		BufferedImage[] imageLevels = null;
+		Graphics2D[] graphics = null;
+
+		imageLevels = new BufferedImage[getZSort().getLevelCount()];
+		graphics = new Graphics2D[imageLevels.length];
+		for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
+
+			imageLevels[i] =
+					CompatLocator.getGraphicsUtils().createBufferedImage(
+							image.getWidth(), image.getHeight(),
+							image.getType());
+
+			graphics[i] = imageLevels[i].createGraphics();
+			graphics[i].setTransform(g.getTransform());
+			graphics[i].setRenderingHints(g.getRenderingHints());
+		}
+		// -- end visual FX stuff
+
+		DisposableIterator it = null;
+		try {
+			it = featureSet.fastIterator();
+			// Iteration over each feature
+			while (it.hasNext()) {
+				if (cancel.isCanceled()) {
+					return;
+				}
+				Feature feat = (Feature) it.next();
+
+				bSymbolLevelError |=
+						drawFeatureMultiLayer(image, g, viewPort, cancel,
+								coordTrans, dpi, drawnNotification,
+								selection, time, screenRefreshDelay,
+								imageLevels, graphics, feat);
+
+			}
+		} catch (ConcurrentDataModificationException e) {
+			cancel.setCanceled(true);
+			return;
+		} finally {
+			if (it != null) {
+				it.dispose();
+			}
+		}
+
+		g.drawImage(image, 0, 0, null);
+
+		Point2D offset = viewPort.getOffset();
+		CompatLocator.getGraphicsUtils().translate(g, offset.getX(),
+				offset.getY());
+
+		for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
+			g.drawImage(imageLevels[i], 0, 0, null);
+			imageLevels[i] = null;
+			graphics[i] = null;
+		}
+
+		CompatLocator.getGraphicsUtils().translate(g, -offset.getX(),
+				-offset.getY());
+
+		imageLevels = null;
+		graphics = null;
+
+		if (bSymbolLevelError) {
+			setZSort(null);
+		}
+	}
+
+	/**
+	 * Draws a Feature with the symbols of the legend, using a multiple drawing
+	 * layer.
+	 */
+	private boolean drawFeatureMultiLayer(BufferedImage image, Graphics2D g,
+			ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans,
+			double dpi, DefaultFeatureDrawnNotification drawnNotification,
+			FeatureSelection selection, long time,
+			int screenRefreshDelay, BufferedImage[] imageLevels,
+			Graphics2D[] graphics, Feature feat) throws MapContextException,
+			CreateGeometryException {
+
+		Geometry geom = feat.getDefaultGeometry();
+		boolean bSymbolLevelError = false;
+		long drawingTime = time;
+
+		if (geom.getType() == Geometry.TYPES.NULL) {
+			return false;
+		}
+
+		ISymbol sym = getSymbol(feat, selection);
+
+		if (sym == null) {
+			return false;
+		}
+
+		if (coordTrans != null) {
+			geom = geom.cloneGeometry();
+			geom.reProject(coordTrans);
+		}
+
+		if (cancel.isCanceled()) {
+			return false;
+		}
+
+		// Check if this symbol is a multilayer
+		int[] symLevels = getZSort().getLevels(sym);
+		if (sym instanceof IMultiLayerSymbol) {
+			// if so, treat each of its layers as a single
+			// symbol
+			// in its corresponding map level
+			IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
+			for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
+				ISymbol mySym = mlSym.getLayer(i);
+				int symbolLevel = 0;
+				if (symLevels != null) {
+					symbolLevel = symLevels[i];
+				} else {
+					/*
+					 * an error occured when managing symbol levels some of the
+					 * legend changed events regarding the symbols did not
+					 * finish satisfactory and the legend is now inconsistent.
+					 * For this drawing, it will finish as it was at the bottom
+					 * (level 0) but, when done, the ZSort will be reset to
+					 * avoid app crashes. This is a bug that has to be fixed.
+					 */
+					bSymbolLevelError = true;
+				}
+				drawGeometry(geom, imageLevels[symbolLevel], feat, mySym,
+						viewPort, graphics[symbolLevel], dpi, cancel);
+			}
+		} else {
+			// else, just draw the symbol in its level
+			int symbolLevel = 0;
+			if (symLevels != null) {
+				symbolLevel = symLevels[0];
+			}
+			drawGeometry(geom, imageLevels[symbolLevel], feat, sym, viewPort,
+					graphics[symbolLevel], dpi, cancel);
+		}
+
+		// -- visual FX stuff
+		// Cuando el offset!=0 se est� dibujando sobre el
+		// Layout y por tanto no tiene que ejecutar el
+		// siguiente c�digo.
+		Point2D offset = viewPort.getOffset();
+		if (offset.getX() == 0 && offset.getY() == 0) {
+			if ((System.currentTimeMillis() - drawingTime) > screenRefreshDelay) {
+
+				BufferedImage virtualBim =
+						CompatLocator.getGraphicsUtils().createBufferedImage(
+								image.getWidth(), image.getHeight(),
+								BufferedImage.TYPE_INT_ARGB);
+
+				Graphics2D virtualGraphics = virtualBim.createGraphics();
+				virtualGraphics.drawImage(image, 0, 0, null);
+				for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
+					virtualGraphics.drawImage(imageLevels[i], 0, 0, null);
+				}
+				g.clearRect(0, 0, image.getWidth(), image.getHeight());
+				g.drawImage(virtualBim, 0, 0, null);
+				drawingTime = System.currentTimeMillis();
+			}
+			// -- end visual FX stuff
+
+		}
+		// Notify the drawing observers
+		drawnNotification.setFeature(feat);
+		drawnNotification.setDrawnGeometry(geom);
+		notifyObservers(drawnNotification);
+		return bSymbolLevelError;
+	}
+
+	/**
+	 * Returns the symbol to use to draw a {@link Feature} taking into account
+	 * if it is selected.
+	 */
+	private ISymbol getSymbol(Feature feat, FeatureSelection selection)
+			throws MapContextException {
+		// retrieve the symbol associated to such feature
+		ISymbol sym = getSymbolByFeature(feat);
+
+		if (sym != null && selection.isSelected(feat)) {
+			sym = sym.getSymbolForSelection();
+		}
+		return sym;
+	}
+
+	/**
+	 * Returns if the legend is using a ZSort.
+	 */
+	private boolean isUseZSort() {
+		return getZSort() != null && getZSort().isUsingZSort();
+	}
+
+	/**
+	 * Draws a {@link Geometry} using the given {@link ISymbol}, over the
+	 * {@link Graphics2D} object.
+	 */
+	private void drawGeometry(Geometry geom, BufferedImage image,
+			Feature feature, ISymbol symbol, ViewPort viewPort,
+			Graphics2D graphics, double dpi, Cancellable cancellable)
+			throws CreateGeometryException {
+
+		if (geom instanceof Aggregate) {
+			drawAggregate((Aggregate) geom, image, feature, symbol, viewPort,
+					graphics, dpi, cancellable);
+		} else {
+			boolean bDrawCartographicSupport = false;
+			if (symbol instanceof CartographicSupport) {
+				bDrawCartographicSupport =
+						((CartographicSupport) symbol).getUnit() != -1;
+			}
+
+			double previousSize = 0.0d;
+
+			if (bDrawCartographicSupport) {
+				// make the symbol to resize itself with the current rendering
+				// context
+				previousSize =
+						((CartographicSupport) symbol).toCartographicSize(
+								viewPort, dpi, geom);
+			}
+
+			try {
+				// draw it as normally
+				double[] dot = new double[2];
+				boolean onePoint =
+						symbol.isOneDotOrPixel(geom, dot, viewPort, (int) dpi);
+
+				if (onePoint) {
+					if (dot[0] < 0 || dot[1] < 0 || dot[0] >= image.getWidth()
+							|| dot[1] >= image.getHeight()) {
+						return;
+					}
+					// FIXME: setRgb should change to draw
+					image.setRGB((int) dot[0], (int) dot[1],
+							symbol.getOnePointRgb());
+				} else {
+					Geometry decimatedShape =
+							transformToInts(geom, viewPort.getAffineTransform());
+					symbol.draw(graphics, viewPort.getAffineTransform(),
+							decimatedShape, feature, cancellable);
+				}
+
+			} finally {
+				if (bDrawCartographicSupport) {
+					// restore previous size
+					((CartographicSupport) symbol).setCartographicSize(
+							previousSize, geom);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Draws an {@link Aggregate} using the given {@link ISymbol}, over the
+	 * {@link Graphics2D} object.
+	 */
+	private void drawAggregate(Aggregate aggregate, BufferedImage image,
+			Feature feature, ISymbol symbol, ViewPort viewPort,
+			Graphics2D graphics, double dpi, Cancellable cancellable)
+			throws CreateGeometryException {
+		for (int i = 0; i < aggregate.getPrimitivesNumber(); i++) {
+			Geometry prim = aggregate.getPrimitiveAt(i);
+			drawGeometry(prim, image, feature, symbol, viewPort, graphics, dpi,
+					cancellable);
+		}
+	}
+
+	/**
+	 * Transforms a Geometry from map coordinates to the view coordinates.
+	 */
+	private Geometry transformToInts(Geometry gp, AffineTransform at)
+			throws CreateGeometryException {
+		GeneralPathX newGp = new GeneralPathX();
+		double[] theData = new double[6];
+		double[] aux = new double[6];
+
+		// newGp.reset();
+		PathIterator theIterator;
+		int theType;
+		int numParts = 0;
+
+		java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
+		java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
+		boolean bFirst = true;
+		int xInt, yInt, antX = -1, antY = -1;
+
+		theIterator = gp.getPathIterator(null); // , flatness);
+		int numSegmentsAdded = 0;
+		while (!theIterator.isDone()) {
+			theType = theIterator.currentSegment(theData);
+
+			switch (theType) {
+			case PathIterator.SEG_MOVETO:
+				numParts++;
+				ptSrc.setLocation(theData[0], theData[1]);
+				at.transform(ptSrc, ptDst);
+				antX = (int) ptDst.getX();
+				antY = (int) ptDst.getY();
+				newGp.moveTo(antX, antY);
+				numSegmentsAdded++;
+				bFirst = true;
+				break;
+
+			case PathIterator.SEG_LINETO:
+				ptSrc.setLocation(theData[0], theData[1]);
+				at.transform(ptSrc, ptDst);
+				xInt = (int) ptDst.getX();
+				yInt = (int) ptDst.getY();
+				if ((bFirst) || ((xInt != antX) || (yInt != antY))) {
+					newGp.lineTo(xInt, yInt);
+					antX = xInt;
+					antY = yInt;
+					bFirst = false;
+					numSegmentsAdded++;
+				}
+				break;
+
+			case PathIterator.SEG_QUADTO:
+				at.transform(theData, 0, aux, 0, 2);
+				newGp.quadTo(aux[0], aux[1], aux[2], aux[3]);
+				numSegmentsAdded++;
+				break;
+
+			case PathIterator.SEG_CUBICTO:
+				at.transform(theData, 0, aux, 0, 3);
+				newGp.curveTo(aux[0], aux[1], aux[2], aux[3], aux[4], aux[5]);
+				numSegmentsAdded++;
+				break;
+
+			case PathIterator.SEG_CLOSE:
+				if (numSegmentsAdded < 3) {
+					newGp.lineTo(antX, antY);
+				}
+				newGp.closePath();
+
+				break;
+			} // end switch
+
+			theIterator.next();
+		} // end while loop
+
+		Geometry geom = null;
+		switch (gp.getType()) {
+		case Geometry.TYPES.POINT:
+			geom =
+					geomManager.createPoint(ptDst.getX(), ptDst.getY(),
+							SUBTYPES.GEOM2D);
+			break;
+		case Geometry.TYPES.CURVE:
+		case Geometry.TYPES.ARC:
+			geom = geomManager.createCurve(newGp, SUBTYPES.GEOM2D);
+			break;
+
+		case Geometry.TYPES.SURFACE:
+		case Geometry.TYPES.CIRCLE:
+		case Geometry.TYPES.ELLIPSE:
+
+			geom = geomManager.createSurface(newGp, SUBTYPES.GEOM2D);
+			break;
+		}
+		return geom;
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		AbstractVectorialLegend clone = (AbstractVectorialLegend) super.clone();
+
+		// Clone zSort
+		ZSort zSort = getZSort();
+		if (zSort != null) {
+			clone.setZSort(new ZSort(clone));
+		}
+		return clone;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+		// Set own properties
+		
+		setShapeType(state.getInt(FIELD_SHAPETYPE));
+		if (state.getBoolean(FIELD_HAS_ZSORT)) {
+			setZSort(new ZSort(this));
+		}
+		setDefaultSymbol((ISymbol) state.get(FIELD_DEFAULT_SYMBOL));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_SHAPETYPE, getShapeType());
+		state.set(FIELD_HAS_ZSORT, this.zSort!=null);
+		state.set(FIELD_DEFAULT_SYMBOL, getDefaultSymbol());
+	}
+
+	/**
+	 * Registers the legend dynClass definition.
+	 */
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+			AbstractVectorialLegend.class, 
+			VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME, 
+			VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME + " persistence definition", 
+			null, 
+			null
+		);
+		// Extend the Legend base definition
+		definition.extend(LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Shapetype
+		definition.addDynFieldInt(FIELD_SHAPETYPE)
+			.setMandatory(true);
+		// ZSort
+		definition.addDynFieldBoolean(FIELD_HAS_ZSORT)
+			.setMandatory(true);
+		// Default symbol
+		definition.addDynFieldObject(FIELD_DEFAULT_SYMBOL)
+			.setClassOfValue(ISymbol.class)
+			.setMandatory(true);
+	}
+
+	/**
+	 * Returns the names of the {@link Feature} attributes required for the
+	 * {@link ILegend} to operate.
+	 * 
+	 * @param featureStore
+	 *            the store where the {@link Feature}s belong to
+	 * @return the names of required {@link Feature} attribute names
+	 * @throws DataException
+	 *             if there is an error getting the attribute names
+	 */
+	protected abstract String[] getRequiredFeatureAttributeNames(
+			FeatureStore featureStore) throws DataException;
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialUniqueValueLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialUniqueValueLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialUniqueValueLegend.java	(revision 33580)
@@ -0,0 +1,769 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.mapcontext.MapContextException;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.utils.XMLEntity;
+import org.gvsig.utils.XMLException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Vectorial legend for unique values
+ * 
+ * @author Vicente Caballero Navarro
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class VectorialUniqueValueLegend extends AbstractClassifiedVectorLegend implements IVectorialUniqueValueLegend {
+	public static final String VECTORIAL_UNIQUE_VALUE_LEGEND_DYNCLASS_NAME =
+			"VectorialUniqueValueLegend";
+
+	private static final String FIELD_KEYS = "keys";
+	private static final String FIELD_NULL_VALUE_SYMBOL = "nullValueSymbol";
+	private static final String FIELD_SELECTED_COLORS = "selectedColors";
+	private static final String FIELD_SYMBOLS = "symbols";
+	private static final String FIELD_USE_DEFAULT_SYMBOL = "useDefaultSymbol";
+
+	final static private Logger logger = LoggerFactory.getLogger(VectorialUniqueValueLegend.class);
+//	protected int fieldId;
+//	protected DataSource dataSource;
+//	protected FeatureStore featureStore;
+	private Map<Object, ISymbol> symbols = createSymbolMap();
+
+	// En lugar de un HashSet, para tener acceso por �ndice
+	private List<Object> keys = new ArrayList<Object>();
+
+//    private String labelFieldName;
+//    private String labelFieldHeight;
+//    private String labelFieldRotation;
+    private ISymbol defaultSymbol;
+    private int shapeType;
+//    private String valueType = NullValue.class.getName();
+    private boolean useDefaultSymbol = false;
+    private Color[] selectedColors=null;
+    
+    private ISymbol nullValueSymbol = null;
+    
+    public VectorialUniqueValueLegend() {
+		// Nothing to do
+	}
+
+    /**
+     * Constructor method
+     *
+     * @param shapeType Type of the shape.
+     */
+    public VectorialUniqueValueLegend(int shapeType) {
+    	setShapeType(shapeType);
+    }
+
+     public void setShapeType(int shapeType) {
+    	if (this.shapeType != shapeType) {
+    		ISymbol old = defaultSymbol;
+			defaultSymbol = getSymbolManager().createSymbol(shapeType);
+    		fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
+    		this.shapeType = shapeType;
+    	}
+    }
+
+    public void setValueSymbolByID(int id, ISymbol symbol) {
+        ISymbol old = (ISymbol)symbols.put(keys.get(id), symbol);
+        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(old, symbol));
+    }
+
+//    /**
+//     * Used in the table that shows the legend
+//     *
+//     * @deprecated use setValueSymbolByID(int id, ISymbol symbol);
+//     * @param reference
+//     * @param symbol
+//     */
+//    public void setValueSymbol(int id, ISymbol symbol) {
+//    	ISymbol old = symbols.put(keys.get(id), symbol);
+//        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(old, symbol));
+//    }
+
+    public Object[] getValues() {
+        return symbols.keySet().toArray(new Object[0]);
+    }
+
+    public void addSymbol(Object key, ISymbol symbol) {
+    	ISymbol resul;
+    	if (key == null) {
+    		resul = nullValueSymbol;
+    		nullValueSymbol = symbol;
+    	}
+    	else {
+			resul = (ISymbol) symbols.put(key, symbol);
+
+			if (resul != null) {
+				logger.error("Error: la clave " + key + " ya exist�a. Resul = "
+						+ resul);
+				logger.warn("symbol nuevo:" + symbol.getDescription()
+						+ " Sviejo= " + resul.getDescription());
+			} else {
+				keys.add(key);
+			}
+    	}
+    	
+        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(resul, symbol));
+    }
+
+    public void clear() {
+        keys.clear();
+        ISymbol[] olds = (ISymbol[])symbols.values().toArray(new ISymbol[0]);
+        symbols.clear();
+        removeLegendListener(getZSort());
+        setZSort(null);
+
+        fireLegendClearEvent(new LegendClearEvent(olds));
+    }
+
+    public String[] getDescriptions() {
+        String[] descriptions = new String[symbols.size()];
+        ISymbol[] auxSym = getSymbols();
+
+        for (int i = 0; i < descriptions.length; i++) {
+			descriptions[i] = auxSym[i].getDescription();
+		}
+
+        return descriptions;
+    }
+
+     public ISymbol[] getSymbols() {
+ 		ISymbol[] symbolList;
+		if (nullValueSymbol == null) {
+			symbolList = new ISymbol[symbols.size()];
+			return (ISymbol[]) symbols.values().toArray(symbolList);
+		}
+		else {
+			symbolList = new ISymbol[symbols.size() + 1];
+			symbolList[0] = nullValueSymbol;
+			int i = 1;
+			for (Iterator<ISymbol> iterator = symbols.values().iterator(); iterator
+					.hasNext();) {
+				symbolList[i] = iterator.next();
+				i++;
+			}
+			return symbolList;
+		}
+    }
+
+    public void setClassifyingFieldNames(String[] fNames) {
+    	 super.setClassifyingFieldNames(fNames);
+//    	 try {
+//    		 fieldId = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(getClassifyingFieldNames()[0]);
+//    	 } catch (NullPointerException e) {
+//    		 logger.warn("data source not set");
+//    	 } catch (DataException e) {
+//    		 logger.warn("data source not set");
+//		}
+     }
+    /*
+     * @see com.iver.cit.gvsig.fmap.rendering.IVectorialLegend#getSymbol(int)
+     */
+//    public ISymbol getSymbol(int recordIndex) throws ReadException {
+//		Object val = dataSource.getFieldValue(recordIndex, fieldId);
+//		ISymbol theSymbol = getSymbolByValue(val);
+//
+//		return theSymbol;
+//	}
+
+    /**
+	 * Devuelve un s�mbolo a partir de una IFeature. OJO!! Cuando usamos un
+	 * feature iterator de base de datos el �nico campo que vendr� rellenado es
+	 * el de fieldID. Los dem�s vendr�n a nulos para ahorra tiempo de creaci�n.
+	 *
+	 * @param feat
+	 *            IFeature
+	 *
+	 * @return S�mbolo.
+     * @throws MapContextException 
+	 */
+    public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
+
+    	Object val = feat.get(getClassifyingFieldNames()[0]);
+//        Object val = feat.get(fieldId);
+        ISymbol theSymbol = getSymbolByValue(val);
+
+        if (theSymbol != null) {
+        	return theSymbol;
+
+        }
+
+        if (isUseDefaultSymbol()) {
+			return defaultSymbol;
+		}
+
+        return null;
+    }
+
+
+    public ISymbol getDefaultSymbol() {
+
+    	if(defaultSymbol==null) {
+			defaultSymbol = getSymbolManager().createSymbol(shapeType);
+    		fireDefaultSymbolChangedEvent(new SymbolLegendEvent(null, defaultSymbol));
+    	}
+    	return defaultSymbol;
+    }
+
+    /**
+     * TODO: replace with new Persistence API
+     */
+    public XMLEntity getXMLEntity() throws XMLException {
+    	return null;
+//    	XMLEntity xml = new XMLEntity();
+//        xml.putProperty("className", this.getClass().getName());
+//        xml.putProperty("fieldNames", getClassifyingFieldNames()[0]);
+//
+//        if (getClassifyingFieldTypes()!=null)
+//        	xml.putProperty("fieldTypes", getClassifyingFieldTypes()[0]);
+//
+//        if (selectedColors != null) {
+//			String[] strColors = new String[selectedColors.length];
+//			for (int i = 0; i < strColors.length; i++) {
+//				strColors[i] = StringUtilities.color2String(selectedColors[i]);
+//			}
+//			xml.putProperty("colorScheme", strColors);
+//		}
+//
+//        xml.putProperty("labelfield", labelFieldName);
+//        xml.putProperty("labelFieldHeight", labelFieldHeight);
+//        xml.putProperty("labelFieldRotation", labelFieldRotation);
+//
+//        xml.putProperty("useDefaultSymbol", useDefaultSymbol);
+//        xml.addChild(getDefaultSymbol().getXMLEntity());
+//        xml.putProperty("numKeys", keys.size());
+//
+//
+//		if (keys.size() > 0) {
+//			xml.putProperty("tipoValueKeys", valueType);
+//
+//			String[] sk = new String[keys.size()];
+//			int[] stk = new int[keys.size()];
+//			Object[] values = getValues();
+//			String[] sv = new String[values.length];
+//			int[] stv = new int[values.length];
+//
+//			for (int i = 0; i < keys.size(); i++) {
+//				Object key = keys.get(i);
+//				sk[i] = key.toString();
+//				stk[i] = getSQLType(key);
+//			}
+//
+//			for (int i=0; i < values.length; i++){
+//				Object value = values[i];
+//				sv[i] = value.toString();
+//				stv[i] = getSQLType(value);
+//				xml.addChild(((ISymbol)symbols.get(value)).getXMLEntity());
+//			}
+//
+//			xml.putProperty("keys", sk);
+//			xml.putProperty("values", sv);
+//			xml.putProperty("typeKeys", stk);
+//			xml.putProperty("typeValues", stv);
+//		}
+//
+//
+//        if (getZSort()!=null) {
+//        	XMLEntity xmlZSort = getZSort().getXMLEntity();
+//        	xmlZSort.putProperty("id", "zSort");
+//        	xml.addChild(xmlZSort);
+//        }
+//        return xml;
+    }
+
+//    private int getSQLType(Object object) {
+//		if (object instanceof Integer){
+//			return Types.INTEGER;
+//		}else if (object instanceof Long){
+//			return Types.BIGINT;
+//		}else if (object instanceof Float){
+//			return Types.FLOAT;
+//		}else if (object instanceof Double){
+//			return Types.DOUBLE;
+//		}else if (object instanceof NullUniqueValue){
+//			return Types.OTHER;
+//		}
+//    	return Types.LONGVARCHAR;
+//	}
+
+    /**
+     * TODO: replace with the new Persistence API (libTools)
+     */
+	public void setXMLEntity(XMLEntity xml) {
+//        clear();
+//        if (xml.contains("fieldName")) {
+//			setClassifyingFieldNames(new String[] {xml.getStringProperty("fieldName")});
+//		} else {
+//			setClassifyingFieldNames(xml.getStringArrayProperty("fieldNames"));
+//		}
+//
+//        if (xml.contains("fieldTypes")) {
+//			setClassifyingFieldTypes(xml.getIntArrayProperty("fieldTypes"));
+//		}
+//        if (xml.contains("colorScheme")) {
+//			String[] strColors = xml.getStringArrayProperty("colorScheme");
+//
+//        	Color[] cc = new Color[strColors.length];
+//			for (int i = 0; i < cc.length; i++) {
+//				cc[i] = StringUtilities.string2Color(strColors[i]);
+//			}
+//			setColorScheme(cc);
+//		}
+//        useDefaultSymbol = xml.getBooleanProperty("useDefaultSymbol");
+//        setDefaultSymbol(SymbologyFactory.createSymbolFromXML(xml.getChild(0), null));
+//
+//        int numKeys = xml.getIntProperty("numKeys");
+//
+//		if (numKeys > 0) {
+//			String className = xml.getStringProperty("tipoValueKeys");
+//			String[] sk = xml.getStringArrayProperty("keys");
+//			if(sk.length == 0){
+//				sk = new String[]{""};
+//			}
+//			String[] sv = xml.getStringArrayProperty("values");
+//			if(sv.length == 0){
+//				sv = new String[]{""};
+//			}
+//			Object auxValue = null;
+//			Object auxValue2 = null;
+//			ISymbol sym;
+//			int[] stk = null;
+//			if (xml.contains("typeKeys")) {
+//				stk = xml.getIntArrayProperty("typeKeys");
+//				int[] stv = xml.getIntArrayProperty("typeValues");
+//				for (int i = 0; i < numKeys; i++) {
+//					auxValue = getValue(sk[i], stk[i]);
+//					keys.add(auxValue);
+//				}
+//
+//				boolean foundNullValue = false;
+//				for (int i = 0; i < sv.length; i++) {
+//					auxValue2 = getValue(sv[i], stv[i]);
+//					if ( auxValue2 instanceof NullValue ) {
+//						foundNullValue = true;
+//						auxValue2 = new NullUniqueValue();
+//						sym = getDefaultSymbol();
+//					} else {
+//						sym = SymbologyFactory.createSymbolFromXML(xml
+//								.getChild(i+1), null);
+//					}
+//
+//					symbols.put(auxValue2, sym);
+//				}
+//				if (!foundNullValue && useDefaultSymbol){
+//					auxValue2 = new NullUniqueValue();
+//					sym = getDefaultSymbol();
+//					symbols.put(auxValue2, sym);
+//				}
+//			} else {
+//
+//
+//				for (int i = 0; i < numKeys; i++) {
+//					auxValue = getValue(sk[i]);
+//					if ( auxValue  == null ) { //Default
+//						auxValue = new NullUniqueValue();
+//					}
+//					keys.add(auxValue);
+//				}
+//
+//				boolean foundNullValue = false;
+//				for (int i = 0; i < sv.length; i++) {
+//					auxValue2 = getValue(sv[i]);
+//					if ( auxValue2 == null ) { //Default
+//						foundNullValue = true;
+//						auxValue2 = new NullUniqueValue();
+//						sym = getDefaultSymbol();
+//					} else {
+//						sym = SymbologyFactory.createSymbolFromXML(xml
+//								.getChild(i+1), null);
+//					}
+//
+//					symbols.put(auxValue2, sym);
+//				}
+//				if (!foundNullValue && useDefaultSymbol){
+//					auxValue2 = new NullUniqueValue();
+//					sym = getDefaultSymbol();
+//					symbols.put(auxValue2, sym);
+//				}
+//			}
+//		}
+//
+//
+//
+//        XMLEntity zSortXML = xml.firstChild("id", "zSort");
+//		if (zSortXML != null) {
+//			ZSort zSort = new ZSort(this);
+//			zSort.setXMLEntity(zSortXML);
+//			addLegendListener(zSort);
+//			setZSort(zSort);
+//		}
+    }
+
+	public void setDefaultSymbol(ISymbol s) {
+    	ISymbol mySymbol = defaultSymbol;
+
+    	if (s == null) {
+			throw new NullPointerException("Default symbol cannot be null");
+		}
+
+    	ISymbol old = mySymbol;
+    	defaultSymbol = s;
+    	fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, s));
+    }
+
+    /**
+     * Returns the value using the its value in a string.
+	 *
+	 *
+	 * @param s String with the value.
+	 * @deprecated Method used until 1.0 alpha 855 You should use getValue(String s,int type);
+	 * @return Value.
+	 */
+//    private Object getValue(String s) {
+//        Object val = new NullUniqueValue();
+//        if (s.equals("Resto de Valores")) {
+//			return val;
+//		}
+////        try {
+//            try {
+//                val = new Integer(s);//(s, Types.INTEGER);
+//
+//                return val;
+//            } catch (NumberFormatException e) {
+//            }
+//
+//            try {
+//                val = new Long(s);//ValueFactory.createValueByType(s, Types.BIGINT);
+//
+//                return val;
+//            } catch (NumberFormatException e) {
+//            }
+//
+//            try {
+//                val = new Float(s);//ValueFactory.createValueByType(s, Types.FLOAT);
+//
+//                return val;
+//            } catch (NumberFormatException e) {
+//            }
+//
+//            try {
+//                val = new Double(s);//ValueFactory.createValueByType(s, Types.DOUBLE);
+//
+//                return val;
+//            } catch (NumberFormatException e) {
+//            }
+//
+//            val = s;//ValueFactory.createValueByType(s, Types.LONGVARCHAR);
+//
+////        } catch (ParseException e) {
+////           log.warn("parse exception", e);
+////        }
+//
+//        return val;
+//    }
+
+    /**
+     * Devuelve el valor a partir de su valor en un string.
+     *
+     * @param s String con el valor.
+     *
+     * @return Value.
+     * @throws MapContextException 
+     */
+//    private Object getValue(String s,int type) {
+//    	Object val = new NullUniqueValue();
+//    	if (type==Types.OTHER) {
+//			return val;
+//		}
+//    	switch (type) {
+//    	case Types.INTEGER:
+//    		val = new Integer(s);
+//    		break;
+//    	case Types.BIGINT:
+//    		val = new Long(s);
+//    		break;
+//    	case Types.FLOAT:
+//    		val = new Float(s);
+//    		break;
+//    	case Types.DOUBLE:
+//    		val = new Double(s);
+//    		break;
+//    	default:
+//    		val=s;
+//    	break;
+//    	}
+//    	return val;
+//    }
+
+	
+//    /**
+//     * TODO: replace using the new Persistence API.
+//     */
+//    public ILegend cloneLegend() throws XMLException {
+//    	// Example:
+////    	PersistenceManager manager = ToolsLocator.getPersistenceManager();
+////    	PersistentState state = manager.getState(this);
+////    	return manager.create(state);
+//    	
+//    	return null;
+//    }
+
+
+    /* (non-Javadoc)
+     * @see com.iver.cit.gvsig.fmap.rendering.VectorialLegend#setDataSource(com.hardcode.gdbms.engine.data.DataSource)
+     */
+//    public void setFeatureStore(FeatureStore fs) throws	DataException {
+//		featureStore = fs;
+////		if (getClassifyingFieldNames()!=null) {
+////			fieldId = ((FeatureType)fs.getFeatureTypes().get(0)).getIndex(getClassifyingFieldNames()[0]);
+////		}
+//	}
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.iver.cit.gvsig.fmap.rendering.UniqueValueLegend#getSymbolByValue(com.hardcode.gdbms.engine.values.Value)
+     */
+    public ISymbol getSymbolByValue(Object key) {
+    	ISymbol symbol = null; 
+    	if (key == null) {
+    		symbol = nullValueSymbol;
+    	}
+    	else {
+    		symbol = (ISymbol)symbols.get(key);
+    	}
+    	if (symbol == null && useDefaultSymbol) {
+    		symbol = getDefaultSymbol();
+    	}
+    	return symbol;
+
+    }
+
+	public Object getSymbolKey(ISymbol symbol) {
+		if (symbol != null) {
+			for (Iterator<Entry<Object, ISymbol>> iterator = symbols.entrySet()
+					.iterator(); iterator.hasNext();) {
+				Entry<Object, ISymbol> entry = iterator.next();
+				if (symbol.equals(entry.getValue())) {
+					return entry.getKey();
+				}
+			}
+		}
+		return null;
+	}
+
+    public int getShapeType() {
+        return shapeType;
+    }
+
+    public void useDefaultSymbol(boolean b) {
+        useDefaultSymbol = b;
+    }
+
+    /**
+	 * Devuelve si se utiliza o no el resto de valores para representarse.
+	 * @return  True si se utiliza el resto de valores.
+	 */
+    public boolean isUseDefaultSymbol() {
+        return useDefaultSymbol;
+    }
+
+    public void delSymbol(Object key) {
+        keys.remove(key);
+
+		ISymbol removedSymbol = (ISymbol) symbols.remove(key);
+		if (removedSymbol != null){
+			fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(removedSymbol, null));
+		}
+    }
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
+		if (symbols.containsValue(oldSymbol)) {
+			Iterator<Object> it = symbols.keySet().iterator();
+			while (it.hasNext()) {
+				Object key = it.next();
+				if (symbols.get(key).equals(oldSymbol)) {
+					fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(
+							(ISymbol)symbols.put(key, newSymbol), newSymbol));
+				}
+
+			}
+		}
+	}
+	public Color[] getColorScheme() {
+		return selectedColors;
+	}
+
+	public void setColorScheme(Color[] cc) {
+		 this.selectedColors = cc;
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		VectorialUniqueValueLegend clone =
+				(VectorialUniqueValueLegend) super.clone();
+
+		// Clone default symbol
+		if (defaultSymbol != null) {
+			clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
+		}
+		// Clone keys
+		clone.keys = new ArrayList<Object>();
+
+		// Clone symbols
+		if (symbols != null) {
+			clone.symbols = createSymbolMap();
+			for (Iterator<Entry<Object, ISymbol>> iterator =
+					symbols.entrySet().iterator(); iterator.hasNext();) {
+				Entry<Object, ISymbol> entry = iterator.next();
+				ISymbol symbolClone =
+						(ISymbol) ((ISymbol) entry.getValue()).clone();
+				// Map keys are of type Number or String, so being
+				// immutable objects, don't clone them
+				clone.addSymbol(entry.getKey(), symbolClone);
+			}
+		}
+
+		return clone;
+	}
+
+	@SuppressWarnings("unchecked")
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+		// Set own properties
+		keys = new ArrayList<Object>((List) state.get(FIELD_KEYS));
+		nullValueSymbol = (ISymbol) state.get(FIELD_NULL_VALUE_SYMBOL);
+		selectedColors =
+				(Color[]) state.getArray(FIELD_SELECTED_COLORS, Color.class);
+		Map persistedSymbolMap = (Map) state.get(FIELD_SYMBOLS);
+		if (persistedSymbolMap != null) {
+			symbols.putAll(persistedSymbolMap);
+		}
+		useDefaultSymbol(state.getBoolean(FIELD_USE_DEFAULT_SYMBOL));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_KEYS, keys);
+		state.set(FIELD_NULL_VALUE_SYMBOL, nullValueSymbol);
+		state.set(FIELD_SELECTED_COLORS, selectedColors);
+		state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
+		state.set(FIELD_SYMBOLS, symbols);
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				VectorialUniqueValueLegend.class,
+				VECTORIAL_UNIQUE_VALUE_LEGEND_DYNCLASS_NAME,
+				VECTORIAL_UNIQUE_VALUE_LEGEND_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		// Extend the Classified Vector Legend base definition
+		definition.extend(CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Keys
+		definition.addDynFieldList(FIELD_KEYS);
+		// Null interval symbol
+		definition.addDynFieldObject(FIELD_NULL_VALUE_SYMBOL);
+		// Selected colors
+		definition.addDynFieldList(FIELD_SELECTED_COLORS);
+		// Symbols
+		definition.addDynFieldMap(FIELD_SYMBOLS);
+		// Use default symbol?
+		definition.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
+	}
+
+	private Map<Object, ISymbol> createSymbolMap() {
+		return new TreeMap<Object, ISymbol>(
+				new Comparator<Object>() { 
+					public int compare(Object o1, Object o2) {
+						if ((o1 != null) && (o2 != null)) {
+							Object v2 = o2;
+							Object v1 = o1;
+							// Boolean boolVal;
+
+							// TODO estas dos comprobaciones son por evitar un
+							// bug en el gdbms, cuando se solucione se puede
+							// eliminar.
+							if (v1 == null && v2 == null) {
+								return 0;
+							}
+
+							// if (v1 instanceof NullUniqueValue && v2
+							// instanceof NullUniqueValue) {
+							// return 0;
+							// }
+							//
+							// if (v1 instanceof NullUniqueValue) {
+							// return -1;
+							// }
+							//
+							// if (v2 instanceof NullUniqueValue) {
+							// return 1;
+							// }
+
+							if (v1 instanceof Number && v2 instanceof Number) {
+								return ((Number) v1).intValue()
+										- ((Number) v2).intValue();
+							}
+							if (v1 instanceof String && v2 instanceof String) {
+								return ((String) v1).compareTo(((String) v2));
+							}
+						}
+
+						return 0;
+					}
+				}); // Para poder ordenar
+
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractClassifiedVectorLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractClassifiedVectorLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractClassifiedVectorLegend.java	(revision 33580)
@@ -0,0 +1,164 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * Abstract class that implements the interface for legends composed by
+ * classified symbols.It will have two methods that will be executed depending
+ * on the action that had been done with the legend (addition of a new symbol or
+ * clear the legend).
+ * 
+ * @author 2008- pepe vidal salvador - jose.vidal.salvador@iver.es
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractClassifiedVectorLegend extends
+		AbstractVectorialLegend implements IClassifiedVectorLegend {
+
+	public static final String CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME =
+			"ClassifiedVectorLegend";
+
+	private static final String FIELD_FIELD_NAMES = "fieldNames";
+	private static final String FIELD_FIELD_TYPES = "fieldTypes";
+
+	private String[] fieldNames;
+	private int[] fieldTypes;
+
+	/**
+	 * Looks for a change in a classified symbol of a legend. To perform it, the
+	 * Array of LegendListeners is scaned and when the corresponding listener is
+	 * true, the method is invoked and the change will be done.
+	 * 
+	 * @param event
+	 */
+	public void fireClassifiedSymbolChangeEvent(SymbolLegendEvent event) {
+		for (int i = 0; i < getListeners().length; i++) {
+			getListeners()[i].symbolChanged(event);
+		}
+	}
+
+	/**
+	 * Looks for a change in a legend of classified symbols. In this case if the
+	 * specific legend is cleared.
+	 * 
+	 * @param event
+	 */
+	public void fireLegendClearEvent(LegendClearEvent event) {
+		for (int i = 0; i < getListeners().length; i++) {
+			getListeners()[i].legendCleared(event);
+		}
+	}
+
+	public String[] getClassifyingFieldNames() {
+		return fieldNames;
+	}
+
+	public void setClassifyingFieldNames(String[] fieldNames) {
+		this.fieldNames = fieldNames;
+	}
+
+	public int[] getClassifyingFieldTypes() {
+		return fieldTypes;
+	}
+
+	public void setClassifyingFieldTypes(int[] fieldTypes) {
+		this.fieldTypes = fieldTypes;
+	}
+
+	public boolean isSuitableForShapeType(int shapeType) {
+		return getShapeType() == shapeType;
+	}
+
+	protected String[] getRequiredFeatureAttributeNames(
+			FeatureStore featureStore) throws DataException {
+		String[] requiredFieldNames = null;
+		String[] classified = getClassifyingFieldNames();
+		requiredFieldNames = new String[classified.length + 1];
+		requiredFieldNames[0] =
+				featureStore.getDefaultFeatureType()
+						.getDefaultGeometryAttributeName();
+		for (int i = 1; i < requiredFieldNames.length; i++) {
+			requiredFieldNames[i] = classified[i - 1];
+		}
+
+		return requiredFieldNames;
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		AbstractClassifiedVectorLegend clone =
+				(AbstractClassifiedVectorLegend) super.clone();
+
+		// Clone fieldNames
+		clone.fieldNames = new String[fieldNames.length];
+		System.arraycopy(fieldNames, 0, clone.fieldNames, 0, fieldNames.length);
+		// Clone fieldTypes
+		clone.fieldTypes = new int[fieldTypes.length];
+		System.arraycopy(fieldTypes, 0, clone.fieldTypes, 0, fieldTypes.length);
+
+		return clone;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+		// Set own properties
+		this.fieldNames = state.getStringArray(FIELD_FIELD_NAMES);
+		this.fieldTypes = state.getIntArray(FIELD_FIELD_TYPES);
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_FIELD_NAMES, this.fieldNames);
+		state.set(FIELD_FIELD_TYPES, this.fieldTypes);
+	}
+
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		DynClass dynClass =
+				ToolsLocator.getDynObjectManager().add(
+						CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Extend the Vector Legend base definition
+		dynClass.extend(VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Field names
+		dynClass.addDynFieldArray(FIELD_FIELD_NAMES)
+			.setClassOfItems(String.class);
+		// Field types
+		dynClass.addDynFieldArray(FIELD_FIELD_TYPES)
+			.setClassOfItems(int.class);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialIntervalLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialIntervalLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/VectorialIntervalLegend.java	(revision 33580)
@@ -0,0 +1,212 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.awt.Color;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * <p>
+ * VectorialIntervalLegend (which should be better called GraduatedColorLegend)
+ * is a legend that allows to classify ranges of values using a color gradient
+ * based on a value.<b>
+ * </p>
+ * <p>
+ * The color gradient will be calculated according the starting color, the
+ * ending color and the amount of intervals.
+ * </p>
+ * 
+ * @author Vicente Caballero Navarro
+ * @author 2009- <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public class VectorialIntervalLegend extends AbstractIntervalLegend {
+	public static final String VECTORIAL_INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME =
+			"VectorialIntervalLegend";
+
+	private static final String FIELD_START_COLOR = "startColor";
+	private static final String FIELD_END_COLOR = "endColor";
+	
+	private int shapeType;
+    private Color startColor = Color.red;
+    private Color endColor = Color.blue;
+
+    /**
+     * Constructor method
+     */
+    public VectorialIntervalLegend() {
+        //defaultSymbol = LegendFactory.DEFAULT_POLYGON_SYMBOL;
+    }
+
+    /**
+     * Constructor method
+     *
+     * @param type type of the shape.
+     */
+    public VectorialIntervalLegend(int type) {
+    	setShapeType(type);
+    }
+
+//    public ILegend cloneLegend() throws XMLException {
+//        return LegendFactory.createFromXML(getXMLEntity());
+//    }
+
+    /**
+	 * Returns the final color
+	 * @return Color  final color.
+	 * @uml.property  name="endColor"
+	 */
+    public Color getEndColor() {
+        return endColor;
+    }
+
+    /**
+	 * Inserts the final color.
+	 * @param endColor final color.
+	 * @uml.property  name="endColor"
+	 */
+    public void setEndColor(Color endColor) {
+        this.endColor = endColor;
+    }
+
+    /**
+	 * Returns the initial color.
+	 * @return  Color initial color.
+	 * @uml.property  name="startColor"
+	 */
+    public Color getStartColor() {
+        return startColor;
+    }
+
+    /**
+	 * Inserts the initial color
+	 * @param startColor initial color.
+	 * @uml.property  name="startColor"
+	 */
+    public void setStartColor(Color startColor) {
+        this.startColor = startColor;
+    }
+
+	public int getShapeType() {
+		return shapeType;
+	}
+
+	public void setShapeType(int shapeType) {
+		if (this.shapeType != shapeType) {
+			setDefaultSymbol(getSymbolManager().createSymbol(shapeType));
+			this.shapeType = shapeType;
+		}
+	}
+
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public Object clone() throws CloneNotSupportedException {
+		VectorialIntervalLegend clone = (VectorialIntervalLegend) super.clone();
+
+		// Nothing to clone, as Color objects are inmutable, keep the original
+		// references.
+
+		return clone;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// Set parent properties
+		super.loadFromState(state);
+		// Set own properties
+		setStartColor((Color) state.get(FIELD_START_COLOR));
+		setEndColor((Color) state.get(FIELD_END_COLOR));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// Save parent properties
+		super.saveToState(state);
+		// Save own properties
+		state.set(FIELD_START_COLOR, getStartColor());
+		state.set(FIELD_END_COLOR, getEndColor());
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				VectorialIntervalLegend.class,
+				VECTORIAL_INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME,
+				VECTORIAL_INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		// Extend the Interval Legend base definition
+		definition.extend(INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME);
+
+		// Start color
+		definition.addDynFieldObject(FIELD_START_COLOR)
+				.setClassOfValue(Color.class)
+				.setMandatory(true)
+				.setDescription("Start color");
+		// End color
+		definition.addDynFieldObject(FIELD_END_COLOR)
+				.setClassOfValue(Color.class)
+				.setMandatory(true)
+				.setDescription("End color");
+	}
+
+	public IInterval createInterval(double min, double max) {
+		return new FInterval(min, max);
+	}
+
+	//
+	/**
+	 * <p>This method does not exist officially. But what it does is just apply the
+	 * values of a VectorialIntervalLegend to other so, It is not needed to
+	 * replicate the code of populating the legend in every panel that produces
+	 * a legend by intervals.<br>
+	 * </p>
+	 * <p>
+	 * ok this method is messy, but it's useful ;-)
+	 * </p>
+	 */
+//	public static void initializeVectorialIntervalLegend(
+//			AbstractIntervalLegend srcLegend,
+//			AbstractIntervalLegend targetLegend) {
+//		targetLegend.shapeType        = srcLegend.shapeType;
+//		targetLegend.symbols          = srcLegend.symbols;
+//		targetLegend.keys             = srcLegend.keys;
+//		targetLegend.index            = srcLegend.index;
+//		targetLegend.setClassifyingFieldNames(srcLegend.getClassifyingFieldNames());
+//		targetLegend.setClassifyingFieldTypes(srcLegend.getClassifyingFieldTypes());
+////		targetLegend.fieldId          = srcLegend.fieldId;
+//		targetLegend.defaultSymbol    = srcLegend.defaultSymbol;
+////		targetLegend.featureStore       = srcLegend.featureStore;
+//		targetLegend.intervalType     = srcLegend.intervalType;
+//		targetLegend.useDefaultSymbol = srcLegend.useDefaultSymbol;
+//	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/QuantileIntervalGenerator.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/QuantileIntervalGenerator.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/QuantileIntervalGenerator.java	(revision 33580)
@@ -0,0 +1,286 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.tools.dispose.DisposableIterator;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+
+/**
+ * Calcula los intervalos en funci�n del n�mero de intervalos que se pidan.
+ *
+ * @author Vicente Caballero Navarro
+ */
+public class QuantileIntervalGenerator {
+//	private DataSource sds;
+	private FeatureStore featureStore;
+	private String msFieldName;
+	private int miNumIntervalosSolicitados;
+	private double[] mdaValoresRuptura;
+	private double[] mdaValInit;
+	private int num = 0;
+
+	/**
+	 * Crea un nuevo QuantileIntervalGenerator.
+	 *
+	 * @param layer DOCUMENT ME!
+	 * @param field DOCUMENT ME!
+	 * @param numIntervals DOCUMENT ME!
+	 */
+	public QuantileIntervalGenerator(FeatureStore fs, String field,
+		int numIntervals) {
+		featureStore = fs;
+		msFieldName = field;
+		miNumIntervalosSolicitados = numIntervals;
+	}
+
+	/**
+	 * Genera los intervalos.
+	 * @throws DataException TODO
+	 *
+	 */
+	public void generarIntervalos()
+		throws DataException {
+		List<Number> ordenadas = new ArrayList<Number>();
+		List<Integer> coincidencias = new ArrayList<Integer>();
+//		int pos = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(msFieldName);
+		mdaValoresRuptura = new double[miNumIntervalosSolicitados - 1];
+		mdaValInit = new double[miNumIntervalosSolicitados - 1];
+		FeatureQuery featureQuery=featureStore.createFeatureQuery();
+		featureQuery.setAttributeNames(new String[]{msFieldName});
+		FeatureSet set = null;
+		DisposableIterator iterator = null;
+		try {
+			set = featureStore.getFeatureSet(featureQuery);
+			iterator = set.fastIterator();
+			long rowCount = 0;
+			while (iterator.hasNext()) {
+				Feature feature = (Feature) iterator.next();
+				insertarEnVector(ordenadas, coincidencias, feature.get(0));// sds.getFieldValue(i,
+																			// pos));
+				rowCount++;
+			}
+			// int MARGEN = 5;
+			// for (int i = 0; i < sds.getRowCount(); i++) {
+			// insertarEnVector(ordenadas, coincidencias, sds.getFieldValue(i,
+			// pos));
+			// }
+
+			int index = 0;
+			int posj = 0;
+
+			for (int i = 1; i < miNumIntervalosSolicitados; i++) {
+				long x = ((i * rowCount) / miNumIntervalosSolicitados);
+
+				for (int j = posj; j < ordenadas.size(); j++) {
+					int auxcoin = ((Integer) coincidencias.get(j)).intValue();
+					index = index + auxcoin;
+
+					if (x <= index) {
+						mdaValoresRuptura[i - 1] = getValue(ordenadas.get(j));
+
+						/*
+						 * index = (int) ((x + (auxcoin /
+						 * miNumIntervalosSolicitados)) - 1);
+						 */
+						posj = j + 1;
+
+						if (posj < ordenadas.size()) {
+							mdaValInit[i - 1] = getValue(ordenadas.get(posj));
+						} else {
+							mdaValInit[i - 1] = getValue(ordenadas.get(j));
+						}
+
+						num++;
+
+						break;
+					}
+				}
+
+				// double value=getValue(sds.getFieldValue(x,pos));
+			}
+
+			// }
+		} finally {
+			if (iterator != null) {
+				iterator.dispose();
+			}
+			if (set != null) {
+				set.dispose();
+			}
+		}
+	}
+
+	/**
+	 * Esta funci�n busca en el vector de datos la posici�n que le corresponde
+	 * al valor almacenado en vdValor y devuelve dicha posici�n en
+	 * vdValorAInsertar. Para hallar la posici�n se realiza una b�squeda
+	 * binaria. Si se trata de un elemento que ya est� en el vector devolvemos
+	 * el �ndice que le corresponde en rlIndiceCorrespondiente y false en
+	 * rbNuevoElemento. Si se trata de un nuevo elemento que hay que
+	 * insertar... devolvemos el �ndice en el que ir�a y True en
+	 * rbNuevoElemento En caso de que ocurra alg�n error devuelve false
+	 *
+	 * @param rVectorDatos ArrayList con los datos.
+	 * @param coincidencia �ndice.
+	 * @param vdValorAInsertar Valor a insertar.
+	 */
+	private void insertarEnVector(List<Number> rVectorDatos,
+			List<Integer> coincidencia, Object vdValorAInsertar) {
+		int llIndiceIzq;
+		int llIndiceDer;
+		int llMedio;
+		int indice = -1;
+		double ldValorComparacion;
+		double valorAInsertar = getValue(vdValorAInsertar);
+
+		if (rVectorDatos.size() == 0) {
+			rVectorDatos.add((Number) vdValorAInsertar);
+			coincidencia.add(new Integer(1));
+
+			return;
+		}
+
+		llIndiceIzq = 0;
+		llIndiceDer = rVectorDatos.size() - 1;
+		llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi�n entera!
+
+		while (llIndiceIzq <= llIndiceDer) {
+			//'Coger el valor situado en la mitad de la zona de b�squeda como valor de comparaci�n
+			ldValorComparacion = getValue( rVectorDatos.get(llMedio));
+
+			//'Si el valor a insertar es mayor que el valor de comparaci�n...
+			if (valorAInsertar > ldValorComparacion) {
+				//      'La zona de b�squeda queda restringida a la parte de la derecha
+				llIndiceIzq = llMedio + 1;
+				llMedio = (llIndiceIzq + llIndiceDer) / 2;
+
+				//    'Si el valor a insertar es menor que el valor de comparaci�n...
+			} else if (valorAInsertar < ldValorComparacion) {
+				//          'La zona de b�squeda queda restringida a la parte de la derecha
+				llIndiceDer = llMedio - 1;
+				llMedio = (llIndiceIzq + llIndiceDer) / 2;
+
+				//        'Si el valor de comparaci�n coincide con el valor a insertar
+			} else if (valorAInsertar == ldValorComparacion) {
+				indice = llMedio;
+
+				int index = rVectorDatos.indexOf(vdValorAInsertar);
+				int coin = ((Integer) coincidencia.get(index)).intValue() + 1;
+				coincidencia.remove(index);
+				coincidencia.add(index, new Integer(coin));
+
+				return;
+			}
+		}
+
+		//  'Nota:
+		//  'En este caso (cuando en rbNuevoElemento se devuelve True) lo que hay que hacer al salir de esta funci�n
+		//  'es a�adir un nuevo elemento al vector y desplazar todos los valores correspondientes a partir de rlIndiceCorrespondiente
+		//  '�D�nde va el nuevo elemento?
+		//  'El �ltimo sitio estudiado viene dado por el valor de llMedio.
+		//  'Si el valor a insertar es menor que el valor almacenado en la posici�n llMedio, el nuevo valor deber� ir a su izquierda.
+		//  'Si fuera mayor deber�a ir a su derecha.
+		ldValorComparacion = getValue( rVectorDatos.get(llMedio));
+
+		if (valorAInsertar > ldValorComparacion) {
+			indice = llMedio + 1;
+		} else {
+			indice = llMedio;
+		}
+
+		rVectorDatos.add(indice, (Number) vdValorAInsertar);
+		coincidencia.add(indice, new Integer(1));
+	}
+
+	/**
+	 * Devuelve el valor en un double del Value que se pasa como par�metro.
+	 *
+	 * @param value Value.
+	 *
+	 * @return valor.
+	 */
+	private double getValue(Object value) {
+		if (value instanceof Number) {
+			return ((Number) value).doubleValue();
+		}
+		return 0;
+
+	}
+
+	/**
+	 * Devuelve el valor del punto de ruptura seg�n el �ndice que se pasa como
+	 * par�metro.
+	 *
+	 * @param index �ndice del punto de ruptura.
+	 *
+	 * @return valor.
+	 */
+	public double getValRuptura(int index) {
+		return mdaValoresRuptura[index];
+	}
+
+	/**
+	 * Devuelve el valor inicial de cada intervalo.
+	 *
+	 * @param index �ndice del intervalo.
+	 *
+	 * @return valor del intervalo.
+	 */
+	public double getValInit(int index) {
+		return mdaValInit[index];
+	}
+
+	/**
+	 * Devuelve el n�mero de intervalos que se han generado.
+	 *
+	 * @return N�mero de intervalos generados.
+	 */
+	public int getNumIntervalGen() {
+		return num + 1;
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/AbstractLegend.java	(revision 33580)
@@ -0,0 +1,247 @@
+/* gvSIG. Geographic Information System of the Valencian Government
+ *
+ * Copyright (C) 2007-2008 Infrastructures and Transports Department
+ * of the Valencian Government (CIT)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ */
+
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.lang.ref.Reference;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.MapContextManager;
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
+import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.observer.Observer;
+import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class that implements the interface for legends.It is considered as
+ * the father of all XXXLegends and will implement all the methods that these
+ * classes had not developed.
+ * 
+ * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
+ * @author 2008 -    pepe vidal salvador - jose.vidal.salvador@iver.es
+ * @author 2009-     <a href="cordinyana@gvsig.org">C�sar Ordi�ana</a> - gvSIG team
+ */
+public abstract class AbstractLegend implements ILegend {
+
+	public static final String LEGEND_PERSISTENCE_DEFINITION_NAME = "Legend";
+
+	private static final String FIELD_LISTENERS = "listeners";
+
+	private static final String FIELD_OBSERVABLE = "observable";
+
+	private static final Logger LOGGER =
+			LoggerFactory.getLogger(AbstractLegend.class);
+
+	/**
+	 * List of LegendContentsChangedListener.
+	 */
+	private List<LegendContentsChangedListener> listeners =
+			new ArrayList<LegendContentsChangedListener>();
+
+	private BaseWeakReferencingObservable delegateDrawingObservable = 
+			new BaseWeakReferencingObservable();
+	
+	private MapContextManager manager = MapContextLocator.getMapContextManager();
+
+	public MapContextManager getManager() {
+		return manager;
+	}
+
+	public SymbolManager getSymbolManager() {
+		return manager.getSymbolManager();
+	}
+
+	public void addLegendListener(LegendContentsChangedListener listener) {
+		if (listener != null && !listeners.contains(listener))
+			listeners.add(listener);
+	}
+
+	public void removeLegendListener(LegendContentsChangedListener listener) {
+		listeners.remove(listener);
+	}
+
+	public void fireDefaultSymbolChangedEvent(SymbolLegendEvent event) {
+
+		for (int i = 0; i < listeners.size(); i++) {
+			((LegendContentsChangedListener) listeners.get(i))
+					.symbolChanged(event);
+		}
+	}
+
+	public LegendContentsChangedListener[] getListeners() {
+		return (LegendContentsChangedListener[]) listeners
+				.toArray(new LegendContentsChangedListener[listeners.size()]);
+	}
+	
+	public void addDrawingObserver(Observer observer) {
+		delegateDrawingObservable.addObserver(observer);
+	}
+
+	public void deleteDrawingObserver(Observer observer) {
+		delegateDrawingObservable.deleteObserver(observer);
+	}
+
+	public void deleteDrawingObservers() {
+		delegateDrawingObservable.deleteObservers();
+	}
+
+	public void addObserver(Reference<Observer> ref) {
+		delegateDrawingObservable.addObserver(ref);
+	}
+
+	public void beginComplexNotification() {
+		delegateDrawingObservable.beginComplexNotification();
+	}
+
+	public int countObservers() {
+		return delegateDrawingObservable.countObservers();
+	}
+
+	public void deleteObserver(Reference<Observer> ref) {
+		delegateDrawingObservable.deleteObserver(ref);
+	}
+
+	public void disableNotifications() {
+		delegateDrawingObservable.disableNotifications();
+	}
+
+	public void enableNotifications() {
+		delegateDrawingObservable.enableNotifications();
+	}
+
+	public void endComplexNotification() {
+		delegateDrawingObservable.endComplexNotification();
+	}
+
+	public boolean inComplex() {
+		return delegateDrawingObservable.inComplex();
+	}
+
+	public boolean isEnabledNotifications() {
+		return delegateDrawingObservable.isEnabledNotifications();
+	}
+
+	public void notifyObservers() {
+		delegateDrawingObservable.notifyObservers();
+	}
+
+	public void notifyObservers(Object arg) {
+		delegateDrawingObservable.notifyObservers(arg);
+	}
+	
+	public ILegend cloneLegend() {
+		try {
+			return (ILegend) clone();
+		} catch (CloneNotSupportedException e) {
+			LOGGER.error("Error creating the clone of the legend: " + this, e);
+		}
+		return null;
+    }
+
+	public Object clone() throws CloneNotSupportedException {
+		AbstractLegend legendClone = (AbstractLegend) super.clone();
+
+		// // Clone listeners
+		// List<LegendContentsChangedListener> listeners = getListenersAsList();
+		// if (listeners != null) {
+		// legendClone.setListeners(new
+		// ArrayList<LegendContentsChangedListener>(
+		// listeners));
+		// }
+		//
+		// // Clone observable
+		// if (getDelegateObservable() != null) {
+		// BaseWeakReferencingObservable observableClone =
+		// (BaseWeakReferencingObservable) getDelegateObservable().clone();
+		// legendClone.setDelegateObservable(observableClone);
+		// }
+		return legendClone;
+	}
+
+	// private BaseWeakReferencingObservable getDelegateObservable() {
+	// return delegateDrawingObservable;
+	// }
+
+	// private void setDelegateObservable(BaseWeakReferencingObservable
+	// observable) {
+	// this.delegateDrawingObservable = observable;
+	// }
+
+	// private List<LegendContentsChangedListener> getListenersAsList() {
+	// return listeners;
+	// }
+
+	// private void setListeners(List<LegendContentsChangedListener> listeners)
+	// {
+	// this.listeners = listeners;
+	// }
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		// List listeners = (List) state.get(FIELD_LISTENERS);
+		// if (listeners != null) {
+		// for (int i = 0; i < listeners.size(); i++) {
+		// addLegendListener((LegendContentsChangedListener) listeners.get(i));
+		// }
+		// }
+		// BaseWeakReferencingObservable observable =
+		// (BaseWeakReferencingObservable) state.get(FIELD_OBSERVABLE);
+		// setDelegateObservable(observable);
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		// state.set(FIELD_LISTENERS, getListenersAsList());
+		// BaseWeakReferencingObservable observable = getDelegateObservable();
+		// if (observable != null && observable.countObservers() > 0) {
+		// state.set(FIELD_OBSERVABLE, observable);
+		// }
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+			AbstractLegend.class, 
+			LEGEND_PERSISTENCE_DEFINITION_NAME, 
+			LEGEND_PERSISTENCE_DEFINITION_NAME + " persistence definition", 
+			null, 
+			null
+		);
+		// Listeners
+		definition.addDynFieldList(FIELD_LISTENERS)
+			.setClassOfItems(LegendContentsChangedListener.class);
+		// Observable
+		definition.addDynFieldObject(FIELD_OBSERVABLE)
+			.setClassOfValue(BaseWeakReferencingObservable.class);
+	}
+    
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/NaturalIntervalGenerator.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/NaturalIntervalGenerator.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/impl/NaturalIntervalGenerator.java	(revision 33580)
@@ -0,0 +1,931 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.tools.dispose.DisposableIterator;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.dal.feature.FeatureType;
+
+/**
+ * Calcula los intervalos naturales.
+ *
+ * @author Vicente Caballero Navarro
+ */
+public class NaturalIntervalGenerator {
+//	private DataSource ds;
+	private String msFieldName;
+	private int miNumIntervalosSolicitados;
+	private int miNumIntervalosGenerados;
+	private double[] mdaValoresRuptura;
+	private double[] mdaValInit;
+	private FeatureStore featureStore;
+
+	/**
+	 * Crea un nuevo IntervalGenerator.
+	 *
+	 * @param layer AlphanumericData
+	 * @param field Nombre del campo.
+	 * @param numIntervals N�mero de intervalos.
+	 */
+	public NaturalIntervalGenerator(FeatureStore fs, String field,
+		int numIntervals) {
+		featureStore = fs;
+		msFieldName = field;
+		miNumIntervalosSolicitados = numIntervals;
+	}
+
+	/**
+	 * Esta funci�n busca en el vector de datos la posici�n que le corresponde
+	 * al valor almacenado en vdValor y devuelve dicha posici�n en
+	 * vdValorAInsertar. Para hallar la posici�n se realiza una b�squeda
+	 * binaria. Si se trata de un elemento que ya est� en el vector devolvemos
+	 * el �ndice que le corresponde en rlIndiceCorrespondiente y false en
+	 * rbNuevoElemento. Si se trata de un nuevo elemento que hay que
+	 * insertar... devolvemos el �ndice en el que ir�a y True en
+	 * rbNuevoElemento En caso de que ocurra alg�n error devuelve false
+	 *
+	 * @param rVectorDatos ArrayList con los datos.
+	 * @param vdValorAInsertar Valor a insertar.
+	 * @param rlIndiceCorrespondiente �ndice.
+	 * @param rbNuevoElemento True si es un nuevo elemento.
+	 *
+	 * @return True si ha conseguido correctamente la posici�n en el vector.
+	 */
+	private boolean mbObtenerPosicionEnVector(
+			List<udtDatosEstudio> rVectorDatos,
+		double vdValorAInsertar, int[] rlIndiceCorrespondiente,
+		boolean[] rbNuevoElemento) {
+		int llIndiceIzq;
+		int llIndiceDer;
+		int llMedio;
+
+		double ldValorComparacion;
+
+		rbNuevoElemento[0] = false;
+		rlIndiceCorrespondiente[0] = -1;
+
+		//'Si el vector estiviese vac�o... (tuviese un s�lo elemento y el n�mero de coincidencias fuese 0)
+		if (rVectorDatos.size() == 1) {
+			if (((udtDatosEstudio) rVectorDatos.get(0)).Coincidencias == 0) {
+				rlIndiceCorrespondiente[0] = 0;
+				rbNuevoElemento[0] = false; //'No tenemos que a�adir un nuevo elemento al vector
+
+				return true;
+			}
+		}
+
+		llIndiceIzq = 0;
+		llIndiceDer = rVectorDatos.size() - 1;
+		llMedio = (llIndiceIzq + llIndiceDer) / 2; //'Divisi�n entera!
+
+		while (llIndiceIzq <= llIndiceDer) {
+			//'Coger el valor situado en la mitad de la zona de b�squeda como valor de comparaci�n
+			ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor;
+
+			//'Si el valor a insertar es mayor que el valor de comparaci�n...
+			if (vdValorAInsertar > ldValorComparacion) {
+				//      'La zona de b�squeda queda restringida a la parte de la derecha
+				llIndiceIzq = llMedio + 1;
+				llMedio = (llIndiceIzq + llIndiceDer) / 2;
+
+				//    'Si el valor a insertar es menor que el valor de comparaci�n...
+			} else if (vdValorAInsertar < ldValorComparacion) {
+				//          'La zona de b�squeda queda restringida a la parte de la derecha
+				llIndiceDer = llMedio - 1;
+				llMedio = (llIndiceIzq + llIndiceDer) / 2;
+
+				//        'Si el valor de comparaci�n coincide con el valor a insertar
+			} else if (vdValorAInsertar == ldValorComparacion) {
+				rlIndiceCorrespondiente[0] = llMedio;
+				rbNuevoElemento[0] = false;
+
+				return true;
+			}
+		}
+
+		//  'Si llegamos a este punto es que no hemos encontrado el valor a insertar en el vector, es decir,
+		//  'seguro que tendremos que a�adir un nuevo elemento.
+		rbNuevoElemento[0] = true;
+
+		//  'Nota:
+		//  'En este caso (cuando en rbNuevoElemento se devuelve True) lo que hay que hacer al salir de esta funci�n
+		//  'es a�adir un nuevo elemento al vector y desplazar todos los valores correspondientes a partir de rlIndiceCorrespondiente
+		//  '�D�nde va el nuevo elemento?
+		//  'El �ltimo sitio estudiado viene dado por el valor de llMedio.
+		//  'Si el valor a insertar es menor que el valor almacenado en la posici�n llMedio, el nuevo valor deber� ir a su izquierda.
+		//  'Si fuera mayor deber�a ir a su derecha.
+		ldValorComparacion = ((udtDatosEstudio) rVectorDatos.get(llMedio)).Valor;
+
+		if (vdValorAInsertar > ldValorComparacion) {
+			rlIndiceCorrespondiente[0] = llMedio + 1;
+		} else {
+			rlIndiceCorrespondiente[0] = llMedio;
+		}
+
+		return true;
+	}
+
+	/**
+	 * M�todo para generar los intervalos.
+	 *
+	 * @return true si se han generado correctamente.
+	 * @throws DataException TODO
+	 */
+	public boolean generarIntervalos()
+		throws DataException {
+		List<udtDatosEstudio> lVectorDatos;
+		double[] ldMediaTotal = new double[1];
+		double[] ldSDAM = new double[1];
+
+		int[] llaIndicesRupturas;
+
+		double[] ldUltimaGVF = new double[1];
+		double[] ldNuevaGVF = new double[1];
+
+		int i;
+		int liNumClasesReales;
+		int llNumElementosPorClase;
+
+		//    'Obtener los datos a estudiar ordenados ascendentemente y obtener la media total
+		//ReDim lVectorDatos(0)
+		lVectorDatos = new ArrayList<udtDatosEstudio>();
+
+		lVectorDatos.add(new udtDatosEstudio());
+
+		if (!mbObtenerDatos(lVectorDatos, ldMediaTotal)) {
+			return false; //SalidaSinMensaje
+		}
+
+		System.out.println("Analizando datos ...");
+
+		/// Call gEstablecerDescripcionProceso("Analizando datos ...", False)
+		//  'Calcular la suma de las desviaciones t�picas del total de los datos respecto de la media total
+		ldSDAM[0] = mbGetSumSquaredDeviationArrayMean(lVectorDatos,
+				ldMediaTotal[0]);
+
+		///if (lVectorDatos.length==0){
+		if (lVectorDatos.isEmpty()) {
+			//      'S�lo se pueden generar dos intervalos -> hay un valor de ruptura
+			///ReDim mdaValoresRuptura(0)
+			mdaValoresRuptura[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
+			mdaValInit[0] = ((udtDatosEstudio) lVectorDatos.get(0)).Valor;
+			miNumIntervalosGenerados = 2;
+
+			return true;
+		}
+
+		//  'Calculamos el n�mero m�ximo de clases reales que podemos generar.
+		//  'Este n�mero ser�a igual al n� de elementos que tenga el vector de datos.
+		if (miNumIntervalosSolicitados > (lVectorDatos.size())) {
+			liNumClasesReales = lVectorDatos.size() + 1;
+		} else {
+			liNumClasesReales = miNumIntervalosSolicitados;
+		}
+
+		//  'Establecemos las clases iniciales especificando unos �ndices de ruptura en ppo. equidistantes
+		llaIndicesRupturas = new int[liNumClasesReales - 1];
+		llNumElementosPorClase = (lVectorDatos.size()) / liNumClasesReales;
+
+		for (i = 0; i < llaIndicesRupturas.length; i++) {
+			if (i == 0) {
+				llaIndicesRupturas[i] = llNumElementosPorClase - 1;
+			} else {
+				llaIndicesRupturas[i] = llaIndicesRupturas[i - 1] +
+					llNumElementosPorClase;
+			}
+		}
+
+		udtDatosClase[] ldaSDCM_Parciales = new udtDatosClase[llaIndicesRupturas.length +
+			1];
+		udtDatosClase[] ldaSDCM_Validos = new udtDatosClase[llaIndicesRupturas.length +
+			1];
+
+		///ReDim ldaSDCM_Parciales(UBound(llaIndicesRupturas()) + 1)
+		///ReDim ldaSDCM_Validos(UBound(ldaSDCM_Parciales()) + 1)
+		if (llaIndicesRupturas.length == 0) {
+			return true;
+		}
+
+		//  'Calcular la bondad inicial
+		if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales, llaIndicesRupturas,
+					ldSDAM[0], ldUltimaGVF, -1, false)) {
+//			JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),PluginServices.getText(this,"el_numero_maximo_de_intervalos_para_este_campo_es")+": "+lVectorDatos.size());
+			miNumIntervalosSolicitados=lVectorDatos.size();
+			generarIntervalos();
+			return false;
+		}
+
+		ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
+
+		boolean lbMoverADerecha;
+		boolean lbMoverAIzquierda;
+		boolean lbIntentarDesplazamiento;
+		int llIndiceRupturaOriginal;
+
+		long k;
+		double ldGVFentrepasadas;
+
+		ldGVFentrepasadas = ldUltimaGVF[0];
+
+		//'liNumClasesReales no ser� muy grande (11 es el m�ximo)
+		for (k = 1; k <= 100; k++) {
+			//      'Para cada �ndice de ruptura...
+			for (i = 0; i < (llaIndicesRupturas.length); i++) {
+				lbMoverADerecha = false;
+				lbMoverAIzquierda = false;
+				llIndiceRupturaOriginal = llaIndicesRupturas[i];
+				ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
+
+				//'Hay que decidir hacia donde hay que desplazar el �ndice de ruptura
+				//'Probamos moviendo a derecha (si se puede)
+				lbIntentarDesplazamiento = false;
+
+				if (i == (llaIndicesRupturas.length - 1)) {
+					if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
+						lbIntentarDesplazamiento = true;
+					}
+				} else {
+					if ((llaIndicesRupturas[i] + 1) < llaIndicesRupturas[i + 1]) {
+						lbIntentarDesplazamiento = true;
+					} //'If (llaIndicesRupturas(i) + 1) < llaIndicesRupturas(i + 1) Then
+				} //'If i = UBound(llaIndicesRupturas) Then
+
+				if (lbIntentarDesplazamiento) {
+					llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
+
+					if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
+								llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
+								false)) {
+						return false;
+					}
+
+					if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
+						lbMoverADerecha = true;
+						ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
+					} else {
+						//'Dejamos el �ndice de ruputura como estaba y probamos con un desplazamiento a izquierda
+						llaIndicesRupturas[i] = llIndiceRupturaOriginal;
+						ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
+					}
+				} //'If lbIntentarDesplazamiento Then
+
+				lbIntentarDesplazamiento = false;
+
+				//'Probamos moviendo a izquierda (si se puede y no estamos moviendo ya a derechas)
+				if (!lbMoverADerecha) {
+					if (i == 0) { //LBound(llaIndicesRupturas) Then
+
+						if ((llaIndicesRupturas[i] - 1) >= 0) { //LBound(lVectorDatos()) Then
+							lbIntentarDesplazamiento = true;
+						} //'If (llaIndicesRupturas(i) - 1) >= LBound(lVectorDatos()) Then
+					} else {
+						if ((llaIndicesRupturas[i] - 1) > llaIndicesRupturas[i -
+								1]) {
+							lbIntentarDesplazamiento = true;
+						} //'If (llaIndicesRupturas(i) - 1) > llaIndicesRupturas(i - 1) Then
+					} //'If i = LBound(llaIndicesRupturas) Then
+				} //'If Not lbMoverADerecha Then
+
+				if (lbIntentarDesplazamiento) {
+					llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1;
+
+					if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
+								llaIndicesRupturas, ldSDAM[0], ldNuevaGVF, i,
+								true)) {
+						return false;
+					}
+
+					if (ldNuevaGVF[0] > ldUltimaGVF[0]) {
+						lbMoverAIzquierda = true;
+						ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
+					} else {
+						//'Dejamos el �ndice de ruputura como estaba
+						llaIndicesRupturas[i] = llIndiceRupturaOriginal;
+						ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
+					}
+				} //'If lbIntentarDesplazamiento Then
+
+				lbIntentarDesplazamiento = false;
+
+				//'Si se ha decidido desplazar el �ndice ... continuamos hasta que no podamos mejorar la GVF
+				if (lbMoverAIzquierda || lbMoverADerecha) {
+					ldUltimaGVF[0] = ldNuevaGVF[0];
+
+					boolean exit = false;
+
+					while (!exit) {
+						llIndiceRupturaOriginal = llaIndicesRupturas[i];
+
+						if (lbMoverADerecha) {
+							if (i == (llaIndicesRupturas.length - 1)) {
+								if ((llaIndicesRupturas[i] + 1) >= lVectorDatos.size()) {
+									exit = true;
+								}
+							} else {
+								if ((llaIndicesRupturas[i] + 1) >= llaIndicesRupturas[i +
+										1]) {
+									exit = true;
+								}
+							} //'If i = UBound(llaIndicesRupturas) Then
+
+							llaIndicesRupturas[i] = llaIndicesRupturas[i] + 1;
+						} else { //'If lbMoverAIzquierda Then
+
+							if (i == 0) { //LBound(llaIndicesRupturas) Then
+
+								if ((llaIndicesRupturas[i] - 1) < 0) { //LBound(lVectorDatos()) Then Exit Do
+									exit = true;
+								}
+							} else {
+								if ((llaIndicesRupturas[i] - 1) <= llaIndicesRupturas[i -
+										1]) {
+									exit = true;
+								}
+							} //'If i = LBound(llaIndicesRupturas) Then
+
+							llaIndicesRupturas[i] = llaIndicesRupturas[i] - 1; //////////////////
+						} //'If lbMoverADerecha Then
+
+						if (!mbCalcularGVF(lVectorDatos, ldaSDCM_Parciales,
+									llaIndicesRupturas, ldSDAM[0], ldNuevaGVF,
+									i, lbMoverAIzquierda)) {
+							return false;
+						}
+
+						if (ldNuevaGVF[0] < ldUltimaGVF[0]) {
+							// 'Dejar el �ndice donde estaba
+							llaIndicesRupturas[i] = llIndiceRupturaOriginal;
+							ldaSDCM_Parciales = getArray(ldaSDCM_Validos);
+							exit = true;
+						} else {
+							ldUltimaGVF[0] = ldNuevaGVF[0];
+							ldaSDCM_Validos = getArray(ldaSDCM_Parciales);
+						}
+					}
+				} //'If lbMoverAIzquierda Or lbMoverADerecha Then
+			}
+
+			if (ldUltimaGVF[0] <= ldGVFentrepasadas) {
+				i = 101;
+			}
+
+			ldGVFentrepasadas = ldUltimaGVF[0];
+		}
+
+		//   'A partir de aqu� ya no se puede cancelar nada
+		mdaValoresRuptura = new double[llaIndicesRupturas.length];
+		mdaValInit = new double[llaIndicesRupturas.length];
+
+		for (i = 0; i < mdaValoresRuptura.length; i++) { // LBound(mdaValoresRuptura) To UBound(mdaValoresRuptura)
+			if (llaIndicesRupturas[i]==-1) {
+				llaIndicesRupturas[i]=1;
+			}
+			if (llaIndicesRupturas[i]>lVectorDatos.size()-1) {
+				llaIndicesRupturas[i]=lVectorDatos.size()-1;
+			}
+			mdaValoresRuptura[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
+
+			if ((llaIndicesRupturas[i] + 1) < lVectorDatos.size()) {
+				mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i] +
+						1)).Valor;
+			} else {
+				mdaValInit[i] = ((udtDatosEstudio) lVectorDatos.get(llaIndicesRupturas[i])).Valor;
+			}
+
+			//      'Hay que aplicar una peque�a correcci�n a los valores de ruptura para que los intervalos que genera
+			//    'mapobjects se aprechen en su totalidad, o lo que es lo mismo, vengan todos representados en el mapa.
+			//  'Con esto tambi�n se consigue hallar intervalos equivalentes a los de ArcView. Esta correcci�n consiste
+			//'en sumar el m�nimo incremento a los valores de ruptura. No lo hago aqu� sino en la ventana de propiedades de capa.
+		}
+
+		miNumIntervalosGenerados = mdaValoresRuptura.length + 2;
+
+		ldaSDCM_Validos = null;
+		ldaSDCM_Parciales = null;
+		lVectorDatos = null;
+
+		return true;
+	}
+
+	/**
+	 * DOCUMENT ME!
+	 *
+	 * @param array DOCUMENT ME!
+	 *
+	 * @return DOCUMENT ME!
+	 */
+	private udtDatosClase[] getArray(udtDatosClase[] array) {
+		udtDatosClase[] aux = new udtDatosClase[array.length];
+
+		for (int i = 0; i < array.length; i++) {
+			aux[i] = new udtDatosClase();
+			aux[i].Media = array[i].Media;
+			aux[i].NumElementos = array[i].NumElementos;
+			aux[i].SDCM = array[i].SDCM;
+			aux[i].SumaCuadradoTotal = array[i].SumaCuadradoTotal;
+			aux[i].SumaTotal = array[i].SumaTotal;
+		}
+
+		return aux;
+	}
+
+	/**
+	 * Devuelve la "SDAM" de un conjunto de datos que vienen almacenados en el
+	 * vector rVectorDatos
+	 *
+	 * @param rVectorDatos Datos
+	 * @param vdMedia Media
+	 *
+	 * @return suma de las desviaciones t�picas del total de los datos respecto
+	 * 		   de la media total
+	 */
+	private double mbGetSumSquaredDeviationArrayMean(
+			List<udtDatosEstudio> rVectorDatos,
+		double vdMedia) {
+		int i;
+
+		double rdSDAM = 0;
+
+		for (i = 0; i < rVectorDatos.size(); i++) { // LBound(rVectorDatos) To UBound(rVectorDatos)
+			rdSDAM = rdSDAM +
+				(Math.pow((((udtDatosEstudio) rVectorDatos.get(i)).Valor -
+					vdMedia), 2) * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
+		}
+
+		return rdSDAM;
+	}
+
+	/**
+	 * Esta funci�n obtiene los datos en los que queremos hallar las rupturas
+	 * naturales. Los datos se devuelven ordenados en un vector. Tambi�n
+	 * devuelve la media total
+	 *
+	 * @param rVectorDatos Datos
+	 * @param rdMediaTotal Media total
+	 *
+	 * @return True si se ha calculado correctamente.
+	 * @throws DataException TODO
+	 */
+	private boolean mbObtenerDatos(List<udtDatosEstudio> rVectorDatos,
+			double[] rdMediaTotal)
+		throws DataException {
+		double ldValor;
+
+//		int i;
+		long llRecordCount=0;
+
+		int[] llIndice = new int[1];
+		boolean[] lbNuevoElemento = new boolean[1];
+		//int j;
+
+//		llRecordCount = ds.getRowCount();
+
+		if (!gbExisteCampoEnRegistro(featureStore, msFieldName)) {
+			if (msFieldName == "") {
+				System.out.println(
+					"No se ha establecido el nombre del campo origen!");
+			} else {
+				System.out.println("El campo '" + msFieldName +
+					"' no pertence a la capa!");
+			}
+
+			return false;
+		}
+		FeatureQuery featureQuery=featureStore.createFeatureQuery();
+		featureQuery.setAttributeNames(new String[]{msFieldName});
+		FeatureSet set = null;
+		DisposableIterator iterator = null;
+		try {
+			set = featureStore.getFeatureSet(featureQuery);
+			iterator = set.fastIterator();
+			while (iterator.hasNext()) {
+				Feature feature = (Feature) iterator.next();
+
+				// 'Nos cuidamos de recorrer todos los registros sin consultar
+				// la propiedad EOF del recordset
+				// for (i = 0; i < llRecordCount; i++) {
+				try {
+					ldValor = feature.getDouble(0); 
+					llRecordCount++;
+				} catch (Exception e) {
+					// llRecordCount--;
+					continue;
+				}
+				rdMediaTotal[0] = rdMediaTotal[0] + ldValor;
+
+				// 'Hay que insertar el valor en la posici�n adecuada. Para
+				// ello hacemos una b�squeda binaria
+				if (!mbObtenerPosicionEnVector(rVectorDatos, ldValor, llIndice,
+						lbNuevoElemento)) {
+					return false;
+				}
+
+				if (!lbNuevoElemento[0]) {
+					if ((llIndice[0] < 0)
+							|| (llIndice[0] > rVectorDatos.size())) {
+						System.out.println("�ndice incorrecto!");
+
+						return false;
+					}
+
+					((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Valor = ldValor; // 'Por
+																						// si
+																						// fuese
+																						// el
+																						// primer
+																						// elemento
+
+					// 'Incrementamos el n� de coincidencias y damos el valor
+					// por insertado
+					((udtDatosEstudio) rVectorDatos.get(llIndice[0])).Coincidencias = ((udtDatosEstudio) rVectorDatos
+							.get(llIndice[0])).Coincidencias +
+					1;
+				} else {
+					udtDatosEstudio udt = new udtDatosEstudio();
+					udt.Valor = ldValor;
+					udt.Coincidencias = 1;
+					rVectorDatos.add(llIndice[0], udt);
+				}
+			}
+
+			rdMediaTotal[0] = rdMediaTotal[0] / llRecordCount;
+
+			return true;
+		} finally {
+			if (iterator != null) {
+				iterator.dispose();
+			}
+			if (set != null) {
+				set.dispose();
+			}
+		}
+	}
+
+	/**
+	 * Devuelve true si existe el campo en el registro.
+	 *
+	 * @param recordset Recordset.
+	 * @param msFieldName2 Nombre del campo.
+	 *
+	 * @return True si existe el campo.
+	 * @throws DataException TODO
+	 *
+	 */
+	private boolean gbExisteCampoEnRegistro(FeatureStore fs,
+		String msFieldName2) throws DataException  {
+		if (((FeatureType)fs.getFeatureTypes().get(0)).getIndex(msFieldName2) == -1) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
+	 * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
+	 * calcula todas! . En este caso no importa el valor de
+	 * vbDesplazAIzquierda
+	 *
+	 * @param rVectorDatos Datos
+	 * @param raClases Clases encontradas
+	 * @param rlaIndicesRuptura �ndices de ruptura
+	 * @param vdSDAM suma de la desviaci�n standard.
+	 * @param rdGVF Desviaci�n standard de los intervalos.
+	 * @param vlIndiceRupturaActual �ndice de ruptura actual.
+	 *
+	 * @return True si se ha calcula do correctamente.
+	 */
+	/*private boolean mbCalcularGVF(ArrayList rVectorDatos,
+		udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
+		double[] rdGVF, int vlIndiceRupturaActual ) {
+		return mbCalcularGVF(rVectorDatos, raClases, rlaIndicesRuptura, vdSDAM,
+			rdGVF, vlIndiceRupturaActual, true);
+	}
+*/
+	/**
+	 * Esta funci�n s�lo calcula las SDCM de las clases adyacentes al �ndice de
+	 * ruptura actual. Si el �ndice de ruptura actual es -1 entonces las
+	 * calcula todas! . En este caso no importa el valor de
+	 * vbDesplazAIzquierda
+	 *
+	 * @param rVectorDatos Datos
+	 * @param raClases Calses que representan a los intervalos.
+	 * @param rlaIndicesRuptura �ndices de ruptura.
+	 * @param vdSDAM Desviaci�n standard.
+	 * @param rdGVF Desviaci�n standard de los intervalos.
+	 * @param vlIndiceRupturaActual �ndice de ruptura actual.
+	 * @param vbDesplazAIzquierda Desplazamiento a la izquierda.
+	 *
+	 * @return True si se ha calculado correctamente.
+	 */
+	private boolean mbCalcularGVF(List<udtDatosEstudio> rVectorDatos,
+		udtDatosClase[] raClases, int[] rlaIndicesRuptura, double vdSDAM,
+		double[] rdGVF, int vlIndiceRupturaActual /* As Long = -1*/,
+		boolean vbDesplazAIzquierda) {
+		double ldSDCM_aux;
+
+		int i;
+
+		if (vlIndiceRupturaActual == -1) {
+			// 'Obtenemos los datos para todas las clases = intervalos
+			for (i = 0; i < rlaIndicesRuptura.length; i++) {
+				if (i == 0) { // LBound(rlaIndicesRuptura) Then
+
+					if (!mbGetDatosClase(rVectorDatos, 0, rlaIndicesRuptura[i],
+								raClases, i)) {
+						return false;
+					}
+				} else {
+					if (!mbGetDatosClase(rVectorDatos,
+								rlaIndicesRuptura[i - 1] + 1,
+								rlaIndicesRuptura[i], raClases, i)) {
+						return false;
+					}
+				}
+			}
+
+			//'Falta la �ltima clase
+			if (!mbGetDatosClase(rVectorDatos,
+						rlaIndicesRuptura[rlaIndicesRuptura.length - 1] + 1,
+						rVectorDatos.size() - 1, raClases, raClases.length - 1)) {
+				return false;
+			}
+		} else {
+			i = vlIndiceRupturaActual;
+
+			//'Hay que determinar para qu� clases debemos volver a recalcular los datos en funci�n del �ndice de ruptura que estamos modificando
+			if (vbDesplazAIzquierda) {
+				//  'Recalcular los datos de la clase izquierda
+				if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
+							rlaIndicesRuptura[i] + 1, vdSDAM, false)) {
+					return false;
+				}
+
+				//  'Recalcular los datos de la clase derecha
+				if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
+							rlaIndicesRuptura[i] + 1, vdSDAM, true)) {
+					return false;
+				}
+			} else {
+				//  'Recalcular los datos de la clase izquierda
+				if (!mbRecalcularDatosClase(raClases, i, rVectorDatos,
+							rlaIndicesRuptura[i], vdSDAM, true)) {
+					return false;
+				}
+
+				//  'Recalcular los datos de la clase derecha
+				if (!mbRecalcularDatosClase(raClases, i + 1, rVectorDatos,
+							rlaIndicesRuptura[i], vdSDAM, false)) {
+					return false;
+				}
+			}
+		}
+
+		ldSDCM_aux = 0;
+
+		for (i = 0; i < raClases.length; i++) { //LBound(raClases) To UBound(raClases)
+			ldSDCM_aux = ldSDCM_aux + raClases[i].SDCM;
+		}
+
+		rdGVF[0] = (vdSDAM - ldSDCM_aux) / vdSDAM;
+		//System.out.println(ldSDCM_aux);
+
+		return true;
+	}
+
+	/**
+	 * Devuelve la "SDCM" de un conjunto de datos que vienen almacenados en el
+	 * vector rVectorDatos y que est�n delimitados por vlLimiteInf y
+	 * vlLimiteInf
+	 *
+	 * @param rVectorDatos Datos
+	 * @param vlLimiteInf L�mite inferior.
+	 * @param vlLimiteSup L�mite superior.
+	 * @param rClase Calses que representan a los intervalos.
+	 * @param numClas N�mero de calses.
+	 *
+	 * @return True si se ha calculado correctamente.
+	 */
+	private boolean mbGetDatosClase(List<udtDatosEstudio> rVectorDatos,
+			int vlLimiteInf,
+		int vlLimiteSup, udtDatosClase[] rClase, int numClas) {
+		int i;
+
+		if (vlLimiteInf < 0) {
+			return false;
+		}
+
+		if (vlLimiteSup > rVectorDatos.size()) {
+			return false;
+		}
+
+		if (vlLimiteSup < vlLimiteInf) {
+			return false;
+		}
+
+		// 'Inicializamos los datos de la clase
+		rClase[numClas] = new udtDatosClase();
+
+		//'Hallamos la media de la clase
+		for (i = vlLimiteInf; i < (vlLimiteSup + 1); i++) {
+			rClase[numClas].NumElementos = rClase[numClas].NumElementos +
+				((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias;
+
+			//'rClase.Media = rClase.Media + (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
+			rClase[numClas].SumaTotal = rClase[numClas].SumaTotal +
+				(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(i)).Coincidencias);
+
+			//'rClase.ProductoTotal = rClase.ProductoTotal * (rVectorDatos(i).Valor * rVectorDatos(i).Coincidencias)
+			rClase[numClas].SumaCuadradoTotal = rClase[numClas].SumaCuadradoTotal +
+				(Math.pow(((udtDatosEstudio) rVectorDatos.get(i)).Valor * ((udtDatosEstudio) rVectorDatos.get(
+						i)).Coincidencias, 2));
+		}
+
+		//'rClase.Media = rClase.Media / llTotalElementos
+		rClase[numClas].Media = rClase[numClas].SumaTotal / rClase[numClas].NumElementos;
+		rClase[numClas].SDCM = (rClase[numClas].SumaCuadradoTotal) -
+			(2 * rClase[numClas].Media * rClase[numClas].SumaTotal) +
+			(rClase[numClas].NumElementos * Math.pow(rClase[numClas].Media, 2));
+		/*if (new Double(rClase[numClas].SDCM).isNaN()){
+			System.out.println(rClase[numClas].SDCM);
+		}*/
+		return true;
+	}
+
+	/**
+	 * Recalcula los datos de las clases.
+	 *
+	 * @param rClase Clases.
+	 * @param i �adir �adir �adir �adir indica si a la clase se le a�ade un
+	 * 		  elemento (True) o se le quita (False)
+	 * @param rVectorDatos Datos.
+	 * @param vlIndiceElemento es el �ndice del elemento que se le va a�adir o
+	 * 		  a quitar a la clase
+	 * @param vdSDAM desviaci�n standard.
+	 * @param vbA �adir DOCUMENT ME!
+	 *
+	 * @return True si se ha calculado correctamente.
+	 */
+	private boolean mbRecalcularDatosClase(udtDatosClase[] rClase, int i,
+			List<udtDatosEstudio> rVectorDatos, int vlIndiceElemento,
+			double vdSDAM,
+		boolean vbAnyadir) {
+		double ldValor;
+		long llNumCoincidencias;
+try{
+	if (vlIndiceElemento>rVectorDatos.size()-1) {
+		return true;
+	}
+		ldValor = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Valor;
+		llNumCoincidencias = ((udtDatosEstudio) rVectorDatos.get(vlIndiceElemento)).Coincidencias;
+
+		if (vbAnyadir) {
+			//'Actualizamos la suma total
+			rClase[i].SumaTotal = rClase[i].SumaTotal +
+				(ldValor * llNumCoincidencias);
+
+			//'Actualizamos la suma de cuadrados total
+			rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal +
+				(Math.pow((ldValor * llNumCoincidencias), 2));
+
+			//'Actualizamos el producto total
+			//'rClase.ProductoTotal = rClase.ProductoTotal * (ldValor * llNumCoincidencias)
+			//'Actualizamos el n� de elementos
+			rClase[i].NumElementos = rClase[i].NumElementos +
+				llNumCoincidencias;
+		} else {
+			//'Actualizamos la suma total
+			rClase[i].SumaTotal = rClase[i].SumaTotal -
+				(ldValor * llNumCoincidencias);
+
+			// 'Actualizamos la suma de cuadrados total
+			rClase[i].SumaCuadradoTotal = rClase[i].SumaCuadradoTotal -
+				(Math.pow((ldValor * llNumCoincidencias), 2));
+
+			// 'Actualizamos el producto total
+			// 'rClase.ProductoTotal = rClase.ProductoTotal / (ldValor * llNumCoincidencias)
+			// 'Actualizamos el n� de elementos
+			rClase[i].NumElementos = rClase[i].NumElementos -
+				llNumCoincidencias;
+		} // 'If vbA�adir Then
+		if (rClase[i].NumElementos<=0) {
+			rClase[i].NumElementos=1;
+		}
+		//'Obtenemos la nueva media
+		rClase[i].Media = rClase[i].SumaTotal / rClase[i].NumElementos;
+
+		//'Actualizamos la SDCM
+		rClase[i].SDCM = (rClase[i].SumaCuadradoTotal) -
+			(2 * rClase[i].Media * rClase[i].SumaTotal) +
+			(rClase[i].NumElementos * Math.pow(rClase[i].Media, 2));
+
+}catch (Exception e) {
+	return false;
+}
+		return true;
+	}
+
+	/**
+	 * Devuelve el valor de ruptura seg�n el �ndice que se le pasa como
+	 * par�metro.
+	 *
+	 * @param viIndice �nidice del valor de ruptura.
+	 *
+	 * @return Valor de ruptura.
+	 */
+	public double getValorRuptura(int viIndice) {
+		return mdaValoresRuptura[viIndice];
+	}
+
+	/**
+	 * Devuelve el valor inicial de cada intervalo
+	 *
+	 * @param index �ndice del intervalo
+	 *
+	 * @return valor del intervalo.
+	 */
+	public double getValInit(int index) {
+		return mdaValInit[index];
+	}
+
+	/**
+	 * Devuelve el n�mero de intervalos que se pueden representar, no tiene
+	 * porque coincidir con el n�mero de intervalos que se piden.
+	 *
+	 * @return N�mero de intervalos calculados.
+	 */
+	public int getNumIntervals() {
+		return miNumIntervalosGenerados;
+	}
+
+	/**
+	 * Clase para contener los atributos Valor y coincidencias.
+	 *
+	 * @author Vicente Caballero Navarro
+	 */
+	private class udtDatosEstudio {
+		private double Valor; //
+		private long Coincidencias;
+	}
+
+	/**
+	 * Clase para contener los atributos: N�mero de Elementos. Media.
+	 * SumaTotal. SumaCuadradoTotal. Desviaci�n standard.
+	 *
+	 * @author Vicente Caballero Navarro
+	 */
+	private class udtDatosClase {
+		private long NumElementos; //             'N� total de elementos que hay en la clase
+		private double Media; //                 'Media de la clase
+		private double SumaTotal; //              'Suma total de los elementos
+
+		//'ProductoTotal          'Producto total de los elementos '�dar� problemas de desbordamiento?
+		private double SumaCuadradoTotal; //      'Suma del total de los cuadrados de los elementos
+		private double SDCM; //                  'Suma de la desviaci�n t�pica de los elementos de la clase respecto de la media de la clase
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelLocationMetrics.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelLocationMetrics.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelLocationMetrics.java	(revision 33580)
@@ -0,0 +1,88 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import java.awt.Point;
+import java.awt.geom.Point2D;
+
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelLocationMetrics;
+
+/**
+ * 
+ * LabelLocationMetrics.java
+ *
+ * 
+ * @author jaume dominguez faus - jaume.dominguez@iver.es Dec 17, 2007
+ *
+ */
+public class LabelLocationMetrics implements ILabelLocationMetrics {
+	private Point2D anchor;
+	private double rotation;
+	private boolean isFixed;
+	
+	public LabelLocationMetrics(Point2D point2D, double rotation, boolean isFixed) {
+		this.anchor = point2D;
+		this.rotation = rotation;
+		this.isFixed = isFixed;
+	}
+	
+	public Point2D getAnchor() {
+		return anchor;
+	}
+	
+	public void setAnchor(Point anchor) {
+		this.anchor = anchor;
+	}
+	
+	public double getRotation() {
+		return rotation;
+	}
+	
+	public void setRotation(double rotation) {
+		this.rotation = rotation;
+	}
+
+	public boolean isFixed() {
+		return isFixed;
+	}
+	
+	
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/TextPath.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/TextPath.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/TextPath.java	(revision 33580)
@@ -0,0 +1,509 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+ *
+ * $Id: TextPath.java 25636 2008-12-01 08:42:11Z vcaballero $
+ * $Log$
+ * Revision 1.2  2007-03-09 11:20:57  jaume
+ * Advanced symbology (start committing)
+ *
+ * Revision 1.1.2.3  2007/02/21 07:34:09  jaume
+ * labeling starts working
+ *
+ * Revision 1.1.2.2  2007/02/09 07:47:05  jaume
+ * Isymbol moved
+ *
+ * Revision 1.1.2.1  2007/02/06 17:01:04  jaume
+ * first version (only lines)
+ *
+ *
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.Point2D;
+
+import org.apache.batik.ext.awt.geom.PathLength;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.Messages;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.vividsolutions.jts.algorithm.Angle;
+/**
+ * <p>Class that represents baseline of a string and allows the baseline to
+ * be composed as contiguous segments with distinct slope each.<br></p>
+ *
+ * <p>Once a TextPath is created for a string it is possible to know where
+ * the character at a determined position in the string is placed and
+ * rotated.<br></p>
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ *
+ */
+public class TextPath {
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
+
+	public static final int NO_POS = Integer.MIN_VALUE;
+	/**
+	 * Don't set a concrete word spacing. The word is separated using the normal
+	 * width of the separator glyph.
+	 */
+	public static final int DEFAULT_WORD_SPACING = Integer.MIN_VALUE;
+
+//	private char[] text;
+	/**
+	 * An array which contains the calculated positions for the glyphs
+	 * Each row represents a glyph, and it contains the X coord, the Y coord, and the rotation angle
+	 */
+	private double[][] posList;
+//	private int alignment;
+	private float characterSpacing;
+//	private boolean kerning;
+	private float wordSpacing;
+	private float margin;
+	private boolean rightToLeft;
+	private int numGlyphs = 0;
+	private float characterWidth;
+	private char[] wordSeparators = {' '}; // in the future, separators might be provided as parameter
+
+	/**
+	 * <p>Creates a new instance of TextPath with the current graphics
+	 * context.<br></p>
+	 *
+	 * <p>Given a <b>Graphics2D</b>, TextPath can know which Font and FontRenderContext
+	 * is in use. So, it can calculate the position and rotation of each
+	 * character in <b>char[] text</b> based in the path defined by the
+	 * <b>FShape path</b> argument.</p>
+	 * @param g, Graphics2D
+	 * @param path, FShape
+	 * @param text, char[]
+	 */
+	public TextPath(Graphics2D g, Geometry path, char[] text, Font font,
+			float characterSpacing, float characterWidth, boolean kerning,
+			float leading, int alignment, float wordSpacing, float margin,
+			boolean rightToLeft) {
+//		this.text = text;
+		if (alignment == ITextSymbol.SYMBOL_STYLE_ALIGNMENT_LEFT ||
+				alignment == ITextSymbol.SYMBOL_STYLE_ALIGNMENT_RIGHT
+				||
+				alignment == ITextSymbol.SYMBOL_STYLE_ALIGNMENT_CENTERED ||
+				alignment == ITextSymbol.SYMBOL_STYLE_ALIGNMENT_JUSTIFY) {
+//			this.alignment = alignment;
+		} else {
+			throw new IllegalArgumentException(
+					Messages.getString("invalid_value_for") + ": " +
+					Messages.getString("alignment")+" ( "+alignment+")");
+		}
+		this.characterWidth = characterWidth;
+		this.characterSpacing = characterSpacing;
+//		this.kerning = kerning;
+		this.wordSpacing = wordSpacing;
+		this.margin = margin;
+		this.rightToLeft = rightToLeft;
+
+		FontRenderContext frc = g.getFontRenderContext();
+		/* java 6 code
+		 * TODO keep this!!
+		if (kerning) {
+			HashMap<TextAttribute, Object> attrs = new HashMap<TextAttribute, Object>();
+			attrs.put(TextAttribute.KERNING , TextAttribute.KERNING_ON);
+		}
+		 */
+		GlyphVector gv = font.createGlyphVector(frc, text);
+
+		PathLength pl;
+		try {
+			pl = new PathLength(softenShape(path, gv));
+			if (alignment==ITextSymbol.SYMBOL_STYLE_ALIGNMENT_RIGHT) {
+				posList = computeAtRight(gv, pl, text);
+			}
+			else if (alignment==ITextSymbol.SYMBOL_STYLE_ALIGNMENT_CENTERED) {
+				computeAtMiddle(frc, text, font, pl);
+			}
+			else {
+				posList = computeAtLeft(gv, pl, text);
+			}
+		} catch (CreateGeometryException e) {
+			logger.error("Error creating a curve", e);
+		}		
+	}
+
+	protected Geometry softenShape(Geometry shape, GlyphVector gv) throws CreateGeometryException {
+
+		float interval = (float) gv.getVisualBounds().getWidth()/(gv.getNumGlyphs()*3);
+
+		PathLength pl = new PathLength(shape);
+
+		GeneralPathX correctedPath = new GeneralPathX();
+		int controlPoints = 16;
+		double[][] points = new double[controlPoints][2];
+		double prevX, prevY;
+		double xsum=0, ysum=0;
+		int nextPos = 0;
+		boolean bufferComplete = false;
+		boolean movedTo = false;
+		for (float curPos = 0; curPos<pl.lengthOfPath(); curPos = curPos+interval) {
+			prevX = points[nextPos][0];
+			prevY = points[nextPos][1];
+			Point2D point =pl.pointAtLength(curPos);
+			if (!movedTo) {
+				correctedPath.moveTo(point.getX(), point.getY());
+				movedTo = true;
+			}
+
+			points[nextPos][0] = point.getX();
+			points[nextPos][1] = point.getY();
+
+			if (!bufferComplete) {
+				xsum += points[nextPos][0];
+				ysum += points[nextPos][1];
+				nextPos++;
+				if (nextPos==controlPoints) {
+					nextPos = 0;
+					bufferComplete = true;
+
+
+					/**
+					 * calculate the beginning of the line
+					 */
+					// this will be the first interpolated point
+					double auxX2 = xsum/controlPoints;
+					double auxY2 = ysum/controlPoints;
+
+					for (int i=1; i<controlPoints/2-1; i++) {
+						// calculate the points from the origin of the geometry to the first interpolated point
+						double auxX = (points[0][0]+points[i][0]+auxX2)/3;
+						double auxY = (points[0][1]+points[i][1]+auxY2)/3;
+						correctedPath.lineTo(auxX, auxY);
+					}
+					correctedPath.lineTo(auxX2, auxY2);
+				}
+			}
+			else {
+
+				xsum = xsum - prevX + points[nextPos][0];
+				ysum = ysum - prevY + points[nextPos][1];
+				if (!movedTo) {
+					correctedPath.moveTo(xsum/controlPoints, ysum/controlPoints);
+					movedTo = true;
+				}
+				else {
+					correctedPath.lineTo(xsum/controlPoints, ysum/controlPoints);
+				}
+
+				nextPos = (nextPos+1)%controlPoints;
+			}
+		}
+		Point2D endPoint = pl.pointAtLength(pl.lengthOfPath());
+		// last point in the geom
+		double endPointX = endPoint.getX();
+		double endPointY = endPoint.getY();
+
+		if (bufferComplete) {
+			/**
+			 * calculate the points from the last interpolated point to the end of the geometry
+			 */
+
+			// last interpolated point
+			double auxX2 = xsum/controlPoints;
+			double auxY2 = ysum/controlPoints;
+			nextPos = (nextPos+(controlPoints/2))%controlPoints;
+			for (int i=0; i<controlPoints/2-1; i++) {
+				// calculate the points from the last interpolated point to the end of the geometry
+				double auxX = (auxX2+points[nextPos][0]+endPointX)/3;
+				double auxY = (auxY2+points[nextPos][1]+endPointY)/3;
+				correctedPath.lineTo(auxX, auxY);
+				nextPos = (nextPos+1)%controlPoints;
+			}
+		}
+		correctedPath.lineTo(endPointX, endPointY);
+
+		return geomManager.createCurve(new GeneralPathX(
+				correctedPath.getPathIterator(null)), SUBTYPES.GEOM2D);
+	}
+
+	/**
+	 * Initializes the position vector.
+	 * @param g
+	 * @param path
+	 */
+	private double[][] computeAtRight(GlyphVector gv, PathLength pl, char[] text) {
+		numGlyphs = gv.getNumGlyphs();
+		double[][] pos = new double[numGlyphs][3];
+		float[] charAnchors = new float[numGlyphs];
+
+		/**
+		 * Compute glyph positions using linear distances
+		 */
+		float lengthOfPath = pl.lengthOfPath();
+		// char distance from the right side
+		float charDistance = lengthOfPath-margin;
+		int glyphsConsumed = numGlyphs-1;
+		float previousAngle = 0.0f;
+		float angle = 0.0f;
+		boolean correction = true;
+		float charWidth = characterWidth;
+		for (int i = numGlyphs-1; i>=0; i--) {
+			if (correction && charDistance>=0) {
+				previousAngle = angle;
+				angle = pl.angleAtLength(charDistance);
+				if (i<numGlyphs-1) {
+					// correct distance according to angle between current and previous glyph
+					int turn = Angle.getTurn(previousAngle, angle);
+					if (turn==1) {  // if turn is positive => increase distance
+						float auxDistance = charDistance - (float)(charWidth*2.5f*Angle.diff(previousAngle, angle)/Math.PI);
+						float auxAngle = pl.angleAtLength(auxDistance);
+						if (Angle.getTurn(previousAngle, auxAngle)==1) { // ensure new position also has positive turn
+							charDistance = auxDistance;
+							angle = auxAngle;
+						}
+					}
+					else if (turn==-1) { // if turn is negative => decrease distance
+						float auxDistance = charDistance + (float)(charWidth*0.9f*Angle.diff(previousAngle, angle)/Math.PI);
+						float auxAngle = pl.angleAtLength(auxDistance);
+						if (Angle.getTurn(previousAngle, auxAngle)==-1) { // ensure new position also has negative turn
+							charDistance = auxDistance;
+							angle = auxAngle;
+						}
+					}
+				}
+			}
+
+			if (wordSpacing!=DEFAULT_WORD_SPACING
+					&& isWordSeparator(text[gv.getGlyphCharIndex(glyphsConsumed)], wordSeparators)) {
+				charWidth = wordSpacing;
+			}
+			else {
+				charWidth = Math.max(gv.getGlyphMetrics(glyphsConsumed).getAdvance(), characterWidth);
+
+			}
+			charDistance -= charWidth;
+			charAnchors[glyphsConsumed] = charDistance;
+			charDistance -= characterSpacing;
+			glyphsConsumed--;
+		}
+
+		/**
+		 * Calculate 2D positions for the glyphs from the calculated linear distances
+		 */
+		for (int i = numGlyphs-1; i>=0; i--) {
+			float anchor = (rightToLeft) ? charAnchors[charAnchors.length-1-i] : charAnchors[i];
+			Point2D p = pl.pointAtLength( anchor );
+			if (p == null) {
+				if (i<numGlyphs-1) { // place in a straight line the glyphs that don't fit in the shape
+					pos[i][0] = pos[i+1][0] + (charAnchors[i]-charAnchors[i+1])*Math.cos(pos[i+1][2]);
+					pos[i][1] = pos[i+1][1] + (charAnchors[i]-charAnchors[i+1])*Math.sin(pos[i+1][2]);
+					pos[i][2] = pos[i+1][2];
+				} else {
+					pos[i][0] = NO_POS;
+					pos[i][1] = NO_POS;
+				}
+				continue;
+			}
+			pos[i][0] = p.getX();
+			pos[i][1] = p.getY();
+			pos[i][2] = pl.angleAtLength( anchor );
+		}
+		return pos;
+	}
+
+	/**
+	 * Initializes the position vector.
+	 * @param g
+	 * @param path
+	 */
+	private double[][] computeAtLeft(GlyphVector gv, PathLength pl, char[] text) {
+		numGlyphs = gv.getNumGlyphs();
+		double[][] pos = new double[numGlyphs][3];
+		float[] charAnchors = new float[numGlyphs];
+		float[] charWidths = new float[numGlyphs];
+
+		/**
+		 * Compute glyph positions using linear distances
+		 */
+		float lengthOfPath = pl.lengthOfPath();
+		float charDistance = margin;
+		int glyphsConsumed = 0;
+		float previousAngle = 0.0f;
+		float angle = 0.0f;
+		boolean correction = true;
+		float charWidth = characterWidth;
+		for (int i = 0; i < gv.getNumGlyphs(); i++) {
+
+			if (correction && charDistance<=lengthOfPath) {
+				previousAngle = angle;
+				angle = pl.angleAtLength(charDistance);
+				if (i>0) {
+					// correct distance according to angle between current and previous glyph
+					int turn = Angle.getTurn(previousAngle, angle);
+					if (turn==1) {  // if turn is positive => decrease distance
+						float auxDistance = charDistance - (float)(charWidth*0.9*Angle.diff(previousAngle, angle)/Math.PI);
+						float auxAngle = pl.angleAtLength(auxDistance);
+						if (Angle.getTurn(previousAngle, auxAngle)==1) { // ensure new position also has positive turn
+							charDistance = auxDistance;
+							angle = auxAngle;
+						}
+					}
+					else if (turn == -1){ // if turn is negative => increase distance
+
+						float auxDistance = charDistance + (float)(charWidth*2.5*Angle.diff(previousAngle, angle)/Math.PI);
+						float auxAngle = pl.angleAtLength(auxDistance);
+						if (Angle.getTurn(previousAngle, auxAngle)==-1) { // ensure new position also has negative turn
+							charDistance = auxDistance;
+							angle = auxAngle;
+						}
+					}
+				}
+			}
+			if (wordSpacing!=DEFAULT_WORD_SPACING
+					&& isWordSeparator(text[gv.getGlyphCharIndex(glyphsConsumed)], wordSeparators)) {
+				// use defined wordspacing
+				charWidth = wordSpacing;
+			}
+			else {
+				charWidth = Math.max(gv.getGlyphMetrics(glyphsConsumed).getAdvance(), characterWidth);
+
+			}
+			charWidths[glyphsConsumed] = charWidth;
+			charAnchors[glyphsConsumed] = charDistance;
+			charDistance += charWidth;
+			charDistance += characterSpacing;
+			glyphsConsumed++;
+		}
+
+		/**
+		 * Calculate 2D positions for the glyphs from the calculated linear distances
+		 */
+		for (int i = 0; i < charAnchors.length; i++) {
+			float anchor = (rightToLeft) ? charAnchors[charAnchors.length-1-i] : charAnchors[i];
+			Point2D p = pl.pointAtLength( anchor );
+			if (p == null) {
+				if (i>0) { // place in a straight line the glyphs that don't fit in the shape
+					pos[i][0] = pos[i-1][0] + (charAnchors[i]-charAnchors[i-1])*Math.cos(pos[i-1][2]);
+					pos[i][1] = pos[i-1][1] + (charAnchors[i]-charAnchors[i-1])*Math.sin(pos[i-1][2]);
+					pos[i][2] = pos[i-1][2];
+				} else {
+					pos[i][0] = NO_POS;
+					pos[i][1] = NO_POS;
+				}
+				continue;
+			}
+			pos[i][2] = pl.angleAtLength( anchor );
+			//			pos[i][0] = p.getX() - charWidths[i]*Math.cos(pos[i][2]);
+			//			pos[i][1] = p.getY() - charWidths[i]*Math.sin(pos[i][2]);
+			pos[i][0] = p.getX();
+			pos[i][1] = p.getY();
+		}
+		return pos;
+	}
+
+
+	/**
+	 * Initializes the position vector.
+	 * @param g
+	 * @param path
+	 */
+	private void computeAtMiddle(FontRenderContext frc, char[] text, Font font, PathLength pl) {
+		if (text.length==0) {
+			return; // nothing to compute if text length is 0
+		}
+		int middleChar = (text.length-1)/2;
+		char[] text1 = new char[middleChar+1];
+		char[] text2 = new char[text.length-text1.length];
+		System.arraycopy(text, 0, text1, 0, text1.length);
+		System.arraycopy(text, text1.length,  text2, 0, text2.length);
+
+		float halfLength = pl.lengthOfPath()/2.0f;
+		margin = halfLength;
+		GlyphVector gv = font.createGlyphVector(frc, text1);
+		double[][] pos1 = computeAtRight(gv, pl, text1);
+		int glyphCount = numGlyphs;
+		gv = font.createGlyphVector(frc, text2);
+		margin = halfLength + characterSpacing;
+		double[][] pos2 = computeAtLeft(gv, pl, text2);
+		numGlyphs += glyphCount;
+		posList = new double[pos1.length+pos2.length][3];
+		System.arraycopy(pos1, 0, posList, 0, pos1.length);
+		System.arraycopy(pos2, 0, posList, pos1.length, pos2.length);
+	}
+
+
+	/**
+	 * <p>Returns the placement of the next character to draw and the corresponding
+	 * rotation in a double array of three elements with this order:</p><br>
+	 *
+	 * <p><b>double[0]</b> Position in X in the screen</p>
+	 * <p><b>double[1]</b> Position in Y in the screen</p>
+	 * <p><b>double[2]</b> Angle of the character.</p>
+	 * @return
+	 */
+	public double[] nextPosForGlyph(int glyphIndex) {
+		return posList[glyphIndex];
+	}
+
+	public int getGlyphCount() {
+		return numGlyphs;
+	}
+
+	protected static boolean isWordSeparator(char c, char[] wordSeparators) {
+		char separator;
+		for (int i = 0; i < wordSeparators.length; i++) {
+			separator = wordSeparators[i];
+			if (c==separator) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/DefaultLabelingMethod.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/DefaultLabelingMethod.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/DefaultLabelingMethod.java	(revision 33580)
@@ -0,0 +1,189 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+*
+* $Id: DefaultLabelingMethod.java 10815 2007-03-20 16:16:20Z jaume $
+* $Log$
+* Revision 1.1  2007-03-20 16:16:20  jaume
+* refactored to use ISymbol instead of FSymbol
+*
+* Revision 1.2  2007/03/09 08:33:43  jaume
+* *** empty log message ***
+*
+* Revision 1.1.2.2  2007/02/01 11:42:47  jaume
+* *** empty log message ***
+*
+* Revision 1.1.2.1  2007/01/30 18:10:45  jaume
+* start commiting labeling stuff
+*
+*
+*/
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+public class DefaultLabelingMethod implements ILabelingMethod {
+
+
+	private static final String FIELD_DEFAULT_LABEL = "defaultLabel";
+	private static final String DEFAULT_LABELING_METHOD_DYNCLASS_NAME =
+			"DefaultLabelingMethod";
+	private ILabelClass defaultLabel;
+
+	/**
+	 * Empty constructor for persistence.
+	 */
+	public DefaultLabelingMethod() {
+		// Nothing to do
+	}
+
+	public DefaultLabelingMethod(LabelClass defaultLabel) {
+		this();
+		this.defaultLabel = defaultLabel;
+	}
+
+
+	public void addLabelClass(ILabelClass lbl) {
+		defaultLabel = lbl;
+	}
+
+
+	public void deleteLabelClass(ILabelClass lbl) {
+		// does nothing
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public boolean allowsMultipleClass() {
+		return false;
+	}
+
+	public void renameLabelClass(ILabelClass lbl, String newName) {
+		// does nothing
+	}
+
+
+	public FeatureSet getFeatureIteratorByLabelClass(FLyrVect layer, ILabelClass lc, ViewPort viewPort, String[] usedFields)
+	throws DataException {
+		FeatureStore featureStore=layer.getFeatureStore();
+		FeatureQuery featureQuery=featureStore.createFeatureQuery();
+		featureQuery.setAttributeNames(usedFields);
+		return (FeatureSet)featureStore.getFeatureSet(featureQuery);
+//		layer.getSource().getFeatureIterator(
+//					viewPort.getAdjustedExtent(), usedFields,
+//					layer.getProjection(), true);
+	}
+
+	public boolean definesPriorities() {
+		return false;
+	}
+
+	public void setDefinesPriorities(boolean flag) {
+		/* nothing, since only one label class is suported */
+	}
+	public ILabelClass getLabelClassByName(String labelName) {
+		return defaultLabel;
+	}
+
+	public void clearAllClasses() {
+		defaultLabel = null;
+	}
+
+	public ILabelClass[] getLabelClasses() {
+		return defaultLabel == null ? new ILabelClass[0] : new ILabelClass[] { defaultLabel };
+	}
+
+	public ILabelingMethod cloneMethod() {
+//XMLENTITY-UPDATED	
+//		if (defaultLabel !=null)
+//			try {
+//				return new DefaultLabelingMethod(LabelingFactory.createLabelClassFromXML(defaultLabel.getXMLEntity()));
+//			} catch (XMLException e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+		return new DefaultLabelingMethod();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#loadFromState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		defaultLabel = (ILabelClass) state.get(FIELD_DEFAULT_LABEL);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#saveToState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_DEFAULT_LABEL, defaultLabel);
+	}
+	
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				DefaultLabelingMethod.class,
+				DEFAULT_LABELING_METHOD_DYNCLASS_NAME,
+				DEFAULT_LABELING_METHOD_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		
+		definition.addDynFieldObject(FIELD_DEFAULT_LABEL).setMandatory(true);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelClass.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelClass.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelClass.java	(revision 33580)
@@ -0,0 +1,611 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+ *
+ * $Id: LabelClass.java 13953 2007-09-21 12:26:04Z jaume $
+ * $Log$
+ * Revision 1.14  2007-09-21 12:26:04  jaume
+ * cancellation support extended down to the IGeometry and ISymbol level
+ *
+ * Revision 1.13  2007/09/17 14:16:11  jaume
+ * multilayer symbols sizing bug fixed
+ *
+ * Revision 1.12  2007/08/22 09:48:13  jvidal
+ * javadoc
+ *
+ * Revision 1.11  2007/05/09 11:04:58  jaume
+ * refactored legend hierarchy
+ *
+ * Revision 1.10  2007/05/08 08:47:40  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.9  2007/04/26 11:41:00  jaume
+ * attempting to let defining size in world units
+ *
+ * Revision 1.8  2007/04/18 15:35:11  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.7  2007/04/12 14:28:43  jaume
+ * basic labeling support for lines
+ *
+ * Revision 1.6  2007/04/11 16:01:08  jaume
+ * maybe a label placer refactor
+ *
+ * Revision 1.5  2007/04/10 16:34:01  jaume
+ * towards a styled labeling
+ *
+ * Revision 1.4  2007/04/05 16:07:14  jaume
+ * Styled labeling stuff
+ *
+ * Revision 1.3  2007/04/02 16:34:56  jaume
+ * Styled labeling (start commiting)
+ *
+ * Revision 1.2  2007/03/09 08:33:43  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.6  2007/02/15 16:23:44  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.5  2007/02/09 07:47:05  jaume
+ * Isymbol moved
+ *
+ * Revision 1.1.2.4  2007/02/02 16:21:24  jaume
+ * start commiting labeling stuff
+ *
+ * Revision 1.1.2.3  2007/02/01 17:46:49  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/02/01 11:42:47  jaume
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2007/01/30 18:10:45  jaume
+ * start commiting labeling stuff
+ *
+ *
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelLocationMetrics;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
+import org.gvsig.fmap.mapcontext.rendering.symbols.styles.ILabelStyle;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ *
+ * LabelClass is the model of the label in the new simbology of gvSIG. In this
+ * class is contained its definition, the expresion that defines the text which
+ * is going to be showed, if it will be visible or not, the text symbol that is
+ * going to paint the label and the style for its background.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class LabelClass implements ILabelClass {
+	private static final String FIELD_REFERENCE_SYSTEM = "referenceSystem";
+	private static final String FIELD_UNIT = "unit";
+	private static final String FIELD_SQL_QUERY = "sqlQuery";
+	private static final String FIELD_SCALE = "scale";
+	private static final String FIELD_PRIORITY = "priority";
+	private static final String FIELD_TEXTS = "texts";
+	private static final String FIELD_LABEL_STYLE = "labelStyle";
+	private static final String FIELD_VISIBLE = "visible";
+	private static final String FIELD_LABEL_EXPRESSION = "labelExpression";
+	private static final String FIELD_TEXT_SYMBOL = "textSymbol";
+	private static final String FIELD_NAME = "name";
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
+	private static final String LABEL_CLASS_DYNCLASS_NAME = "LabelClass";
+	private String name;
+	private ITextSymbol textSymbol;
+	private String labelExpression;
+	private boolean isVisible = true;
+	private ILabelStyle labelStyle;
+	private String[] texts;
+	private int priority;
+	private double scale = 1;
+	private String sqlQuery;
+
+	private int unit = CartographicSupportToolkit.DefaultMeasureUnit;
+	private int referenceSystem =
+			CartographicSupportToolkit.DefaultReferenceSystem;
+	
+	/**
+	 * Returns true if the label will be showed in the map
+	 *
+	 * @return isVisible boolean
+	 */
+	public boolean isVisible() {
+		return isVisible;
+	}
+
+	/**
+	 * Sets the visibility of the label in the map.
+	 *
+	 * @param isVisible boolean
+	 */
+	public void setVisible(boolean isVisible) {
+		this.isVisible = isVisible;
+	}
+
+	/**
+	 * Returns the expression that defines the text which will be showed in
+	 * the label
+	 *
+	 * @return labelExpression String
+	 */
+	public String getLabelExpression() {
+		return labelExpression;
+	}
+
+	/**
+	 * Stablishes the expresion that, when it is evaluated, returns the text
+	 * which will be showed by the label.
+	 *
+	 * @param labelExpression String
+	 */
+	public void setLabelExpression(String labelExpression) {
+		this.labelExpression = labelExpression;
+	}
+
+	/**
+	 * Returns the text symbol that is being used for the text(the font,
+	 * size,style,aligment)
+	 *
+	 * @return label ITextSymbol
+	 */
+	public ITextSymbol getTextSymbol() {
+		if (textSymbol == null) {
+			textSymbol = new SimpleTextSymbol();
+		}
+		return textSymbol;
+	}
+
+	private Dimension getSize() {
+		if (labelStyle == null) {
+			if (texts!=null && texts.length >0) {
+				String t = "";
+				for (int i = 0; i < texts.length; i++) {
+					t += texts[i];
+				}
+				getTextSymbol().setText(t);
+			}
+
+			Rectangle bounds = getTextSymbol().getBounds();
+			bounds.setLocation(
+					(int) Math.round(bounds.getX()),
+					(int) Math.round(bounds.getY()+bounds.getHeight()));
+			return new Dimension(bounds.width, bounds.height);
+		} else {
+			labelStyle.setTextFields(texts);
+			return labelStyle.getSize();
+		}
+	}
+	/**
+	 * Stablishes the text symbol that is going to be used for the text(the
+	 * font,size,style,aligment)
+	 *
+	 * @param textSymbol ITextSymbol
+	 */
+	public void setTextSymbol(ITextSymbol textSymbol) {
+		this.textSymbol = textSymbol;
+		if (textSymbol == null) {
+			this.textSymbol = new SimpleTextSymbol();
+		}
+		setReferenceSystem(referenceSystem);
+		setUnit(unit);
+	}
+
+	/**
+	 * Stablishes the style for the label.
+	 *
+	 * @param labelStyle ILabelStyle
+	 */
+	public void setLabelStyle(ILabelStyle labelStyle) {
+		this.labelStyle = labelStyle;
+	}
+
+	/**
+	 * Returns the style of the label
+	 *
+	 */
+	public ILabelStyle getLabelStyle() {
+		return this.labelStyle;
+	}
+
+	/**
+	 * Returns the name of the label
+	 *
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Stablishes the name of the label
+	 * @param name
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String toString() {
+		// for debugging
+		//		return name+"{label expression="+labelExpression+", visible="+isVisible+", priority="+priority+"}";
+		return getName();
+	}
+
+	/**
+	 * Sets the text for the label
+	 *
+	 * @param texts String[]
+	 */
+	public void setTexts(String[] texts) {
+		this.texts = texts;
+
+	}
+
+	/**
+	 * Return the text for the label
+	 *
+	 * @param texts String[]
+	 */
+	public String[] getTexts() {
+		return this.texts;
+	}
+
+	/**
+	 * <p>
+	 * LabelLocationMetrics, contains the anchor point, rotation, and some
+	 * other geometric calculations computed by the PlacementManager.
+	 * </p>
+	 *
+	 * <p>
+	 * The shp argument is passed as an accessory for subclasses of this
+	 * class in case they need futher geometric calculations
+	 * </p>
+	 * @param graphics, graphics to use to paint the label.
+	 * @param llm, concrete settings of the placement of this layer
+	 * @param shp, the Shape over whose the label is painted
+	 */
+	public void draw(Graphics2D graphics, ILabelLocationMetrics llm, Geometry geom) {
+		if (scale == 0)
+			return;
+
+
+		Dimension size = getSize();
+		int width = (int) Math.round(size.getWidth()*scale);
+		if (width  < 1)
+			return;
+
+		int height = (int) Math.round(size.getHeight()*scale);
+		if (height < 1)
+			return;
+
+		Rectangle r = new Rectangle(0,0, width, height);
+		org.gvsig.fmap.geom.primitive.Point anchor;
+		try {
+			anchor = geomManager.createPoint(llm.getAnchor().getX(), llm.getAnchor().getY(), SUBTYPES.GEOM2D);
+			double xAnchor = anchor.getX();
+			double yAnchor = anchor.getY();
+			double theta = llm.getRotation();
+
+			graphics.translate(xAnchor, yAnchor);
+			graphics.rotate(theta);
+			synchronized (this) {
+				float fontSizeBefore = textSymbol.getFont().getSize2D();
+				try {
+					textSymbol.setFontSize(fontSizeBefore*scale);
+					drawInsideRectangle(graphics, r);
+					textSymbol.setFontSize(fontSizeBefore);
+				} catch (SymbolDrawingException e) {
+					e.printStackTrace();
+				}
+			}
+			graphics.rotate(-theta);
+			graphics.translate(-xAnchor, -yAnchor);
+		} catch (CreateGeometryException e1) {
+			logger.error("Error creating a point", e1);
+			e1.printStackTrace();
+		}
+	}
+
+	private void relativeToAbsolute(double[] xy, Rectangle r, Dimension labelSz, double ratioLabel, double ratioViewPort) {
+		int x;
+		int y;
+		if (ratioViewPort > ratioLabel) {
+			// size is defined by the viewport height
+			y = (int) (r.height*xy[1]);
+			x = (int) ((0.5*r.width) - (0.5-xy[0])*(ratioLabel*r.height));
+		} else {
+			// size is defined by the viewport width
+			x = (int) (r.width * xy[0]);
+			y = (int) ((0.5 * r.height) - (0.5-xy[1])*(r.width/ratioLabel));
+		}
+		xy[0] = x;
+		xy[1] = y;
+	}
+
+	/**
+	 * Useful to render a Label with size inside little rectangles.
+	 *
+	 * @param graphics Graphics2D
+	 * @param bounds Rectangle
+	 * @throws SymbolDrawingException
+	 */
+	public void drawInsideRectangle(Graphics2D graphics, Rectangle bounds) throws SymbolDrawingException {
+		if (labelStyle != null) {
+			labelStyle.drawInsideRectangle(graphics, bounds);
+			Rectangle2D[] textBounds = labelStyle.getTextBounds();
+			Dimension labelSz = getSize();
+			final double ratioLabel = labelSz.getWidth()/labelSz.getHeight();
+			final double ratioViewPort = bounds.getWidth() / bounds.getHeight();
+			final double[] xy = new double[2];
+
+
+			// draw the text fields
+			if (textBounds.length > 0 && texts!=null) {
+				for (int i = 0; i < textBounds.length && i < texts.length; i++) {
+					getTextSymbol().setText(texts[i]);
+					Rectangle2D textFieldArea = textBounds[i];
+					xy[0] = textFieldArea.getX();
+					xy[1] = textFieldArea.getY();
+					relativeToAbsolute(xy, bounds, labelSz, ratioLabel, ratioViewPort);
+					int x = (int) Math.round(xy[0]);
+					int y = (int) Math.round(xy[1]);
+
+					xy[0] = textFieldArea.getMaxX();
+					xy[1] = textFieldArea.getMaxY();
+					relativeToAbsolute(xy, bounds, labelSz, ratioLabel, ratioViewPort);
+					int width = (int) Math.round(xy[0]) -x;
+					int height = (int) Math.round(xy[1] - y) ;
+
+					Rectangle textRect = new Rectangle(x, y, width, height);
+					Shape oldClip = graphics.getClip();
+					graphics.setClip(textRect);
+					getTextSymbol().drawInsideRectangle(graphics, null, textRect, null);
+					graphics.setClip(oldClip);
+				}
+			}
+		} else {
+
+			if (texts != null && texts.length>0)
+				getTextSymbol().setText(texts[0]);
+			getTextSymbol().drawInsideRectangle(graphics, null, bounds, null);
+		}
+	}
+
+	public int getPriority() {
+		return priority;
+	}
+
+	public void setPriority(int priority) {
+		this.priority = priority;
+	}
+
+	public Geometry getShape(ILabelLocationMetrics llm) throws CreateGeometryException {
+		if (llm==null)
+			return null;
+		Point2D anchor = llm.getAnchor();
+		org.gvsig.fmap.geom.primitive.Point p = geomManager.createPoint(anchor.getX(), anchor.getY(), SUBTYPES.GEOM2D);
+		double theta = llm.getRotation();
+
+		// 2. calculate the container shape
+		Geometry returnedValue;
+		Rectangle bounds = getBounds();
+
+		AffineTransform at = AffineTransform.getTranslateInstance(p.getX(), p.getY());
+		at.concatenate(AffineTransform.getRotateInstance(theta));
+		returnedValue = geomManager.createSurface(new GeneralPathX(bounds
+				.getPathIterator(null)), SUBTYPES.GEOM2D);
+
+		returnedValue.transform(at);
+		return returnedValue;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		Dimension sz = getSize();
+		double width = sz.getWidth();
+		double height = sz.getHeight();
+		return CartographicSupportToolkit.
+		getCartographicLength(this,
+				Math.max(width, height),
+				viewPort,
+				dpi);
+	}
+
+	public int getReferenceSystem() {
+		return referenceSystem;
+	}
+
+	public int getUnit() {
+		return unit;
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		Dimension sz = getSize();
+		double width = sz.getWidth();
+		double height = sz.getHeight();
+		if (width >= height) {
+			scale = cartographicSize / width;
+		} else {
+			scale = cartographicSize / height;
+		}
+	}
+
+	public void setReferenceSystem(int referenceSystem) {
+		this.referenceSystem = referenceSystem;
+		if (textSymbol != null && textSymbol instanceof CartographicSupport) {
+			((CartographicSupport) textSymbol).setReferenceSystem(referenceSystem);
+		}
+	}
+
+	public void setUnit(int unitIndex) {
+		this.unit = unitIndex;
+		if (textSymbol != null && textSymbol instanceof CartographicSupport) {
+			((CartographicSupport) textSymbol).setUnit(unitIndex);
+		}
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		setCartographicSize(getCartographicSize(
+				viewPort,
+				dpi,
+				geom),
+				geom);
+		return 0;
+	}
+
+	public Rectangle getBounds() {
+		Dimension cBounds = getSize();
+		return new Rectangle(
+				0,
+				0,
+				(int) Math.round(cBounds.width*scale),
+				(int) Math.round(cBounds.height*scale));
+	}
+
+	public String getSQLQuery() {
+		if (sqlQuery == null) sqlQuery = "";
+		return sqlQuery;
+	}
+
+	public void setSQLQuery(String sqlQuery) {
+		this.sqlQuery = sqlQuery;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.gvsig.tools.persistence.Persistent#saveToState(org.gvsig.tools.
+	 * persistence.PersistentState)
+	 */
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_NAME, getName());
+		state.set(FIELD_TEXT_SYMBOL, getTextSymbol());
+		state.set(FIELD_LABEL_EXPRESSION, getLabelExpression());
+		state.set(FIELD_VISIBLE, isVisible());
+		state.set(FIELD_LABEL_STYLE, getLabelStyle());
+		state.set(FIELD_TEXTS, getTexts());
+		state.set(FIELD_PRIORITY, getPriority());
+		state.set(FIELD_SCALE, scale);
+		state.set(FIELD_SQL_QUERY, getSQLQuery());
+		state.set(FIELD_UNIT, getUnit());
+		state.set(FIELD_REFERENCE_SYSTEM, getReferenceSystem());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.gvsig.tools.persistence.Persistent#loadFromState(org.gvsig.tools.
+	 * persistence.PersistentState)
+	 */
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setName(state.getString(FIELD_NAME));
+		setTextSymbol((ITextSymbol) state.get(FIELD_TEXT_SYMBOL));
+		setLabelExpression(state.getString(FIELD_LABEL_EXPRESSION));
+		setVisible(state.getBoolean(FIELD_VISIBLE));
+		setLabelStyle((ILabelStyle) state.get(FIELD_LABEL_STYLE));
+		setTexts((String[]) state.getArray(FIELD_TEXTS, String.class));
+		setPriority(state.getInt(FIELD_PRIORITY));
+		scale = state.getDouble(FIELD_SCALE);
+		setSQLQuery(state.getString(FIELD_SQL_QUERY));
+		setUnit(state.getInt(FIELD_UNIT));
+		setReferenceSystem(state.getInt(FIELD_REFERENCE_SYSTEM));
+	}
+
+	public static void registerPersistence() {
+		// Add the persistence definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				LabelClass.class,
+				LABEL_CLASS_DYNCLASS_NAME,
+				LABEL_CLASS_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+
+		definition.addDynFieldString(FIELD_NAME).setMandatory(true);
+		definition.addDynFieldObject(FIELD_TEXT_SYMBOL).setMandatory(true);
+		definition.addDynFieldString(FIELD_LABEL_EXPRESSION).setMandatory(true);
+		definition.addDynFieldBoolean(FIELD_VISIBLE).setMandatory(true);
+		definition.addDynFieldObject(FIELD_LABEL_STYLE).setMandatory(true);
+		definition.addDynFieldList(FIELD_TEXTS).setMandatory(true);
+		definition.addDynFieldInt(FIELD_PRIORITY).setMandatory(true);
+		definition.addDynFieldDouble(FIELD_SCALE).setMandatory(true);
+		definition.addDynFieldString(FIELD_SQL_QUERY).setMandatory(true);
+		definition.addDynFieldInt(FIELD_UNIT).setMandatory(true);
+		definition.addDynFieldInt(FIELD_REFERENCE_SYSTEM).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelingFactory.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelingFactory.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/LabelingFactory.java	(revision 33580)
@@ -0,0 +1,150 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+*
+* $Id: LabelingFactory.java 13913 2007-09-20 09:36:02Z jaume $
+* $Log$
+* Revision 1.9  2007-09-20 09:33:15  jaume
+* Refactored: fixed name of IPersistAnce to IPersistence
+*
+* Revision 1.8  2007/05/22 12:17:41  jaume
+* *** empty log message ***
+*
+* Revision 1.7  2007/05/22 10:05:31  jaume
+* *** empty log message ***
+*
+* Revision 1.6  2007/04/13 11:59:30  jaume
+* *** empty log message ***
+*
+* Revision 1.5  2007/03/28 16:48:01  jaume
+* *** empty log message ***
+*
+* Revision 1.4  2007/03/20 16:16:20  jaume
+* refactored to use ISymbol instead of FSymbol
+*
+* Revision 1.3  2007/03/09 11:20:57  jaume
+* Advanced symbology (start committing)
+*
+* Revision 1.2  2007/03/09 08:33:43  jaume
+* *** empty log message ***
+*
+* Revision 1.1.2.4  2007/02/21 07:34:08  jaume
+* labeling starts working
+*
+* Revision 1.1.2.3  2007/02/12 15:15:20  jaume
+* refactored interval legend and added graduated symbol legend
+*
+* Revision 1.1.2.2  2007/02/09 07:47:05  jaume
+* Isymbol moved
+*
+* Revision 1.1.2.1  2007/02/02 16:21:24  jaume
+* start commiting labeling stuff
+*
+* Revision 1.1.2.1  2007/01/30 18:10:45  jaume
+* start commiting labeling stuff
+*
+*
+*/
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import org.gvsig.fmap.mapcontext.layers.FLayer;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class LabelingFactory {
+	final static private Logger logger = LoggerFactory.getLogger(LabelingFactory.class);
+	@SuppressWarnings("unchecked")
+	private static Class defaultLabelingStrategy =
+			AttrInTableLabelingStrategy.class;
+	/**
+	 * Given a layer, a labeling method, a label placements constraints, and a label
+	 * zoom constraints it will figure out the best ILabelingStrategy that meets all
+	 * the needs.
+	 * @param layer, the target layer
+	 * @param method, the desired methods
+	 * @param placement, the desired placement constraints
+	 * @param zoom, the desired zoom constraints
+	 * @return ILabelingStrategy
+	 */
+	public static ILabelingStrategy createStrategy(FLayer layer,
+			ILabelingMethod method, IPlacementConstraints placement,
+			IZoomConstraints zoom) 	{
+		if (method == null && placement == null && zoom == null)
+			return createDefaultStrategy(layer);
+
+		ILabelingStrategy strat = createDefaultStrategy(layer);
+		if (method != null)
+			strat.setLabelingMethod(method);
+		if (placement != null)
+			strat.setPlacementConstraints(placement);
+		return strat;
+
+	}
+
+	/**
+	 * Creates a default labeling strategy from an XMLEntity.
+	 * @param layer
+	 * @return an instance of DefaultStrategy
+	 */
+	public static ILabelingStrategy createDefaultStrategy(FLayer layer) {
+		ILabelingStrategy st;
+		try {
+			st = (ILabelingStrategy) defaultLabelingStrategy.newInstance();
+			st.setLayer(layer);
+			return st;
+		} catch (Exception e) {
+			logger.error(e.getMessage());
+			return null;
+		}
+
+	}
+
+	@SuppressWarnings("unchecked")
+	public static void setDefaultLabelingStrategy(Class defaultLabelingStrategy) {
+		LabelingFactory.defaultLabelingStrategy = defaultLabelingStrategy;
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/AttrInTableLabelingStrategy.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/AttrInTableLabelingStrategy.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/AttrInTableLabelingStrategy.java	(revision 33580)
@@ -0,0 +1,727 @@
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.batik.ext.awt.geom.PathLength;
+import org.gvsig.compat.print.PrintAttributes;
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.exception.ReadException;
+import org.gvsig.tools.dispose.DisposableIterator;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.dal.feature.FeatureType;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.aggregate.MultiPoint;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.geom.util.Converter;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.layers.FLayer;
+import org.gvsig.fmap.mapcontext.layers.vectorial.ContainsEnvelopeEvaluator;
+import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints;
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.exception.BaseException;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.task.Cancellable;
+import org.slf4j.LoggerFactory;
+
+
+
+/**
+ * LabelingStrategy used when the user wants to use label sizes, rotations, etc. from
+ * the values included in fields of the datasource's table
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ *
+ */
+public class AttrInTableLabelingStrategy implements ILabelingStrategy, CartographicSupport {
+	private static final String FIELD_LABELING_METHOD = "labelingMethod";
+	private static final String FIELD_ZOOM_CONSTRAINTS = "zoomConstraints";
+	private static final String FIELD_COLOR_FONT = "colorFont";
+	private static final String FIELD_LAYER = "layer";
+	private static final String FIELD_REFERENCE_SYSTEM = "referenceSystem";
+	private static final String FIELD_FIXED_COLOR = "fixedColor";
+	private static final String FIELD_USE_FIXED_COLOR = "useFixedColor";
+	private static final String FIELD_FIXED_SIZE = "fixedSize";
+	private static final String FIELD_USE_FIXED_SIZE = "useFixedSize";
+	private static final String FIELD_FONT = "font";
+	private static final String FIELD_UNIT = "Unit";
+	private static final String FIELD_ROTATION = "RotationField";
+	private static final String FIELD_COLOR = "ColorField";
+	private static final String FIELD_HEIGHT = "HeightField";
+	private static final String FIELD_TEXT = "TextField";
+	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
+	private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AttrInTableLabelingStrategy.class);
+	public static final double MIN_TEXT_SIZE = 3;
+	private static final String ATTR_IN_TABLE_LABELING_STRATEGY_DYNCLASS_NAME =
+			"AttrInTableLabelingStrategy";
+	private ILabelingMethod method = new DefaultLabelingMethod();
+	private IZoomConstraints zoom;
+	private FLyrVect layer;
+//	private double unitFactor = 1D;
+	private double fixedSize=10;
+	private Color fixedColor;
+	private int unit = -1; //(pixel)
+	private boolean useFixedSize;
+	private boolean useFixedColor;
+	private int referenceSystem;
+//	private boolean isPrinting;
+	private String[] usedFields = null;
+	private Font font;
+	private Color colorFont;
+	private String textFieldName;
+	private String rotationFieldName;
+	private String heightFieldName;
+	private String colorFieldName;
+
+	public ILabelingMethod getLabelingMethod() {
+		return this.method;
+	}
+
+	public void setLabelingMethod(ILabelingMethod method) {
+		this.method = method;
+	}
+
+	public IPlacementConstraints getPlacementConstraints() {
+		return null; // (automatically handled by the driver)
+	}
+
+	public void setPlacementConstraints(IPlacementConstraints constraints) {
+		// nothing
+	}
+
+	public IZoomConstraints getZoomConstraints() {
+		return zoom;
+	}
+
+	public void setZoomConstraints(IZoomConstraints constraints) {
+		this.zoom = constraints;
+	}
+
+	private void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
+			Cancellable cancel, PrintAttributes props) throws ReadException {
+		double scale = viewPort.getScale();
+//		double fontScaleFactor = FConstant.FONT_HEIGHT_SCALE_FACTOR;
+
+		SimpleTextSymbol sym = new SimpleTextSymbol();
+
+		sym.setFont(getFont());
+
+		sym.setUnit(unit);
+		sym.setReferenceSystem(referenceSystem);
+		if (zoom==null ||
+			( zoom.isUserDefined() && (scale >= zoom.getMaxScale())
+			&& (scale <= zoom.getMinScale()) ) ) {
+			FeatureSet set = null;
+			DisposableIterator iterator = null;
+			try {
+				// limit the labeling to the visible extent
+				List<String> fields = new ArrayList<String>();
+				int heightPos =-1;
+				int rotationPos =-1;
+				int textPos = -1;
+				int colorPos = -1;
+//				int geomPos = -1;
+
+				if (!this.usesFixedSize()) {
+					if (getHeightField() != null) {
+						heightPos = fields.size();
+						fields.add(getHeightField());
+					}
+				}
+				if (getRotationField() != null) {
+					rotationPos = fields.size();
+					fields.add(getRotationField());
+				}
+				if (getTextField() != null) {
+					textPos = fields.size();
+					fields.add(getTextField());
+				}
+
+				if (!this.usesFixedColor() && getColorField() != null) {
+					colorPos = fields.size();
+					fields.add(getColorField());
+				}
+
+				FeatureStore featureStore=layer.getFeatureStore();
+
+//				geomPos = fields.size();
+				String geomName=featureStore.getDefaultFeatureType().getDefaultGeometryAttributeName();
+				fields.add(geomName);
+
+				FeatureQuery featureQuery=featureStore.createFeatureQuery();
+
+				featureQuery.setAttributeNames((String[]) fields.toArray(new String[fields.size()]));
+				// TODO no set filter y layer is contained totaly in viewPort
+				ContainsEnvelopeEvaluator iee=new ContainsEnvelopeEvaluator(viewPort.getAdjustedEnvelope(),viewPort.getProjection(),featureStore.getDefaultFeatureType(),geomName);
+				featureQuery.setFilter(iee);
+
+
+
+				set = featureStore
+						.getFeatureSet(featureQuery);
+
+//				ReadableVectorial source = layer.getSource();
+//				SelectableDataSource recordSet = source.getRecordset();
+				iterator = set.fastIterator();
+//				CreateLabelsOperationContext cloc=new CreateLabelsOperationContext();
+//				cloc.setDublicates(true);
+//				cloc.setPosition(0);
+				while(iterator.hasNext()){
+					if (cancel.isCanceled()){
+						return;
+					}
+					Feature feature=(Feature)iterator.next();
+//				for(int i=bs.nextSetBit(0); i>=0 && !cancel.isCanceled(); i=bs.nextSetBit(i+1)) {
+//					Value[] vv = recordSet.getRow(i);
+					double size;
+					Color color = null;
+					if (useFixedSize){
+						// uses fixed size
+						size = fixedSize;// * fontScaleFactor;
+//					} else if (idHeightField != -1) {
+					} else if (heightFieldName != null) {
+						// text size is defined in the table
+						try {
+////							Object obj=feature.get(idHeightField);
+//							Object obj=feature.get(heightPos);
+//							if (obj!=null) {
+//								size = ((Number) obj).doubleValue();// * fontScaleFactor;
+//							} else {
+//								size=0;
+//							}
+							size = feature.getDouble(heightPos);
+						} catch (ClassCastException ccEx) {
+//							if (!NullValue.class.equals(feature.get(idHeightField).getClass())) {
+//							if (!NullValue.class.equals(feature.get(heightPos).getClass())) {
+//
+//								throw new ReadException("Unknown", ccEx);
+//							}
+							// a null value
+//							Logger.getAnonymousLogger().
+//								warning("Null text height value for text '"+feature.get(idTextField).toString()+"'");
+							
+							logger.
+								warn("Null text height value for text '{}'", feature.get(textPos).toString());
+
+							continue;
+						}
+					} else {
+						// otherwise will use the size in the symbol
+						size = sym.getFont().getSize();
+					}
+
+					size = CartographicSupportToolkit.
+								getCartographicLength(this,
+													  size,
+													  viewPort,
+													  MapContext.getScreenDPI());
+//													  dpi);
+//								toScreenUnitYAxis(this,
+//												  size,
+//												  viewPort
+//												 );
+
+					if (size <= MIN_TEXT_SIZE) {
+						// label is too small to be readable, will be skipped
+						// this speeds up the rendering in wider zooms
+						continue;
+					}
+
+					sym.setFontSize(size);
+
+					if (useFixedColor){
+						color = fixedColor;
+//					} else if (idColorField != -1) {
+					} else if (colorFieldName != null) {
+						// text size is defined in the table
+						try {
+//							color = new Color(feature.getInt(idColorField));
+							color = new Color(feature.getInt(colorPos));
+						} catch (ClassCastException ccEx) {
+//							if (feature.get(idColorField) != null) {
+							if (feature.get(colorPos) != null) {
+								throw new ReadException("Unknown", ccEx);
+							}
+							// a null value
+//							Logger.getAnonymousLogger().
+//								warning(
+//									"Null color value for text '"
+//											+ feature.getString(idTextField)
+//											+ "'");
+							logger.warn(
+									"Null color value for text '{}'", 
+									feature.getString(textFieldName));
+
+							continue;
+						}
+					} else {
+						color = sym.getTextColor();
+					}
+
+					sym.setTextColor(color);
+
+					double rotation = 0D;
+//					if (idRotationField!= -1) {
+					if (rotationFieldName != null) {
+						// text rotation is defined in the table
+//						rotation = -Math.toRadians(((Number) feature.get(idRotationField)).doubleValue());
+						rotation = -Math.toRadians(((Number) feature.get(rotationPos)).doubleValue());
+					}
+
+					Geometry geom = feature.getDefaultGeometry();
+//					Object obj=feature.get(idTextField);
+//					Object obj = feature.get(textPos);
+//					if (obj!=null) {
+//						sym.setText(obj.toString());
+//					}
+					sym.setText(feature.getString(textPos));
+					sym.setRotation(rotation);
+			
+					Point2D labelPoint = createLabelPoint(geom);
+                    Point p = geomManager.createPoint(labelPoint.getX(), labelPoint.getY(), SUBTYPES.GEOM2D);
+                    p.transform(viewPort.getAffineTransform());
+					if (props == null) {
+                        sym.draw(g, null, p, feature, cancel);
+                    } else {
+						sym.print(g, null, p, props);
+                    }
+
+//					FLabel[] aux =(FLabel[])geom.invokeOperation(CreateLabels.CODE,cloc);
+////					FLabel[] aux = geom.createLabels(0, true);
+//					for (int j = 0; j < aux.length; j++) {
+//						Point p = geomManager.createPoint(aux[j].getOrig().getX(), aux[j].getOrig().getY(), SUBTYPES.GEOM2D);
+//						p.transform(viewPort.getAffineTransform());
+//						if (properties==null) {
+//							sym.draw(g, null, p, cancel);
+//						} else {
+//							sym.print(g, null, p, properties);
+//						}
+//					}
+				}
+
+//			} catch (GeometryOperationNotSupportedException e) {
+//				throw new ReadException(
+//						"Could not draw annotation in the layer.", e);
+//			} catch (GeometryOperationException e) {
+//				throw new ReadException(
+//						"Could not draw annotation in the layer.", e);
+			} catch (BaseException e) {
+				throw new ReadException(
+						"Could not draw annotation in the layer.", e);
+			} finally {
+				if (iterator != null) {
+					iterator.dispose();
+				}
+				if (set != null) {
+					set.dispose();
+				}
+
+			}
+
+		}
+	}
+	
+	public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
+			Cancellable cancel, double dpi) throws ReadException {
+		draw(image, g, viewPort, cancel, null);
+	}
+
+	private Point2D createLabelPoint(org.gvsig.fmap.geom.Geometry geom)
+			throws CreateGeometryException {
+		Point2D pAux = null;
+		switch (geom.getType()) {
+		case org.gvsig.fmap.geom.Geometry.TYPES.POINT:
+			pAux = new Point2D.Double(
+					((org.gvsig.fmap.geom.primitive.Point) geom).getX(),
+					((org.gvsig.fmap.geom.primitive.Point) geom).getY());
+			return pAux;
+
+		case org.gvsig.fmap.geom.Geometry.TYPES.CURVE:
+			PathLength pathLen = new PathLength(geom);
+
+			// if (pathLen.lengthOfPath() < width / mT.getScaleX()) return;
+			float midDistance = pathLen.lengthOfPath() / 2;
+			pAux = pathLen.pointAtLength(midDistance);
+			return pAux;
+
+		case org.gvsig.fmap.geom.Geometry.TYPES.SURFACE:
+			com.vividsolutions.jts.geom.Geometry geo = Converter
+					.geometryToJts(geom);
+
+			if (geo == null) {
+				return null;
+			}
+
+			com.vividsolutions.jts.geom.Point pJTS = geo.getCentroid();
+
+			if (pJTS != null) {
+				org.gvsig.fmap.geom.Geometry pLabel = Converter
+						.jtsToGeometry(pJTS);
+				return new Point2D.Double(
+						((org.gvsig.fmap.geom.primitive.Point) pLabel).getX(),
+						((org.gvsig.fmap.geom.primitive.Point) pLabel).getY());
+			}
+			break;
+		case org.gvsig.fmap.geom.Geometry.TYPES.MULTIPOINT:
+			int num = ((MultiPoint) geom).getPrimitivesNumber();
+			Rectangle2D r = null;
+			if (num > 0) {
+				r = ((MultiPoint) geom).getPointAt(0).getBounds2D();
+				for (int i = 1; i < num; i++) {
+					org.gvsig.fmap.geom.primitive.Point fp = ((MultiPoint) geom)
+							.getPointAt(i);
+					r.add(new Point2D.Double(fp.getX(), fp.getY()));
+				}
+			}
+			if (r != null)
+				return new Point2D.Double(r.getCenterX(), r.getCenterY());
+			break;
+		} // switch
+		return null;
+	}
+
+	public String getClassName() {
+		return getClass().getName();
+	}
+
+	public String getRotationField() throws DataException {
+		return this.rotationFieldName;
+	}
+
+	public String getTextField() throws DataException {
+		return this.textFieldName;
+	}
+
+	public String getHeightField() throws DataException {
+		return this.heightFieldName;
+	}
+
+	public String getColorField() throws DataException {
+		return this.colorFieldName;
+	}
+
+	public void setTextField(String textFieldName) {
+		this.textFieldName=textFieldName;
+		this.usedFields = null;
+	}
+
+	public void setRotationField(String rotationFieldName) {
+		this.rotationFieldName = rotationFieldName;
+		this.usedFields = null;
+	}
+
+	/**
+	 * Sets the field that contains the size of the text. The size is computed
+	 * in meters. To use any other unit, call setUnit(int) with the scale factor from meters
+	 * (for centimeters, call <b>setUnitFactor(0.01))</b>.
+	 * @param heightFieldName
+	 */
+	public void setHeightField(String heightFieldName) {
+		this.heightFieldName = heightFieldName;
+		this.usedFields = null;
+	}
+
+
+	public void setColorField(String colorFieldName) {
+		this.colorFieldName = colorFieldName;
+	}
+
+	public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
+			PrintAttributes props) throws ReadException {
+		draw(null, g, viewPort, cancel, props);
+	}
+
+	public void setUsesFixedSize(boolean b) {
+		useFixedSize = b;
+		this.usedFields = null;
+	}
+
+	public boolean usesFixedSize() {
+		return useFixedSize;
+	}
+
+	public double getFixedSize() {
+		return fixedSize;
+	}
+
+	public void setFixedSize(double fixedSize) {
+		this.fixedSize = fixedSize;
+		this.usedFields = null;
+	}
+
+	public void setUsesFixedColor(boolean b) {
+		useFixedColor = b;
+		this.usedFields = null;
+	}
+
+	public boolean usesFixedColor() {
+		return useFixedColor;
+	}
+
+	public Color getFixedColor() {
+		return fixedColor;
+	}
+
+	public void setFixedColor(Color fixedColor) {
+		this.fixedColor = fixedColor;
+	}
+
+
+	public void setUnit(int unitIndex) {
+		unit = unitIndex;
+
+	}
+
+	public int getUnit() {
+		return unit;
+	}
+
+	public String[] getUsedFields() {
+		if (this.usedFields == null) {
+			List<String> v = new ArrayList<String>(4);
+			try {
+				if (!this.usesFixedSize()) {
+					if (getHeightField() != null) {
+						v.add(getHeightField());
+					}
+				}
+				if (getRotationField() != null) {
+					v.add(getRotationField());
+				}
+				if (getTextField() != null) {
+					v.add(getTextField());
+				}
+
+				if (!this.usesFixedColor() && getColorField() != null) {
+					v.add(getColorField());
+				}
+			} catch (DataException e) {
+				logger.error("Error", e);
+			}
+			this.usedFields = (String[]) v.toArray(new String[v.size()]);
+		}
+		return this.usedFields;
+	}
+
+	public int getReferenceSystem() {
+		return referenceSystem;
+	}
+
+	public void setReferenceSystem(int referenceSystem) {
+		this.referenceSystem = referenceSystem;
+	}
+
+	public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		// not required here
+		throw new Error("Undefined in this context");
+	}
+
+	public void setCartographicSize(double cartographicSize, Geometry geom) {
+		// not required here
+		throw new Error("Undefined in this context");
+	}
+
+	public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
+		// not required here
+		throw new Error("Undefined in this context");
+
+	}
+
+	public void setLayer(FLayer layer) throws ReadException {
+		this.layer = (FLyrVect) layer;
+		if (layer == null) {
+			return;
+		}
+		FeatureType type;
+		try {
+			type = this.layer.getFeatureStore().getDefaultFeatureType();
+		} catch (DataException e) {
+			// FIXME Throw DataException
+			throw new ReadException(this.getClass().getName(), e);
+		}
+
+		if (textFieldName != null) {
+			if (type.getIndex(textFieldName) < 0) {
+				// FIXME exception ??
+			}
+		}
+		if (rotationFieldName != null) {
+			if (type.getIndex(rotationFieldName) < 0) {
+				// FIXME exception ??
+			}
+		}
+		if (heightFieldName != null) {
+			if (type.getIndex(heightFieldName) < 0) {
+				// FIXME exception ??
+			}
+		}
+		if (colorFieldName != null) {
+			if (type.getIndex(colorFieldName) < 0) {
+				// FIXME exception ??
+			}
+		}
+	}
+
+	public boolean shouldDrawLabels(double scale) {
+		return layer.isWithinScale(scale);
+	}
+	public Color getColorFont() {
+		return colorFont;
+	}
+
+	public void setColorFont(Color colorFont) {
+		this.colorFont = colorFont;
+	}
+
+	public Font getFont() {
+		return font;
+	}
+
+	public void setFont(Font selFont) {
+		this.font = selFont;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#loadFromState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+
+		setTextField(state.getString(FIELD_TEXT));
+		setHeightField(state.getString(FIELD_HEIGHT));
+		setColorField(state.getString(FIELD_COLOR));
+		setRotationField(state.getString(FIELD_ROTATION));
+		setUnit(state.getInt(FIELD_UNIT));
+		setFont((Font) state.get(FIELD_FONT));
+		useFixedSize = state.getBoolean(FIELD_USE_FIXED_SIZE);
+		setFixedSize(state.getDouble(FIELD_FIXED_SIZE));
+		useFixedColor = state.getBoolean(FIELD_USE_FIXED_COLOR);
+		setFixedColor((Color) state.get(FIELD_FIXED_COLOR));
+		setReferenceSystem(state.getInt(FIELD_REFERENCE_SYSTEM));
+		
+		try {
+			setLayer((FLayer) state.get(FIELD_LAYER));
+		} catch (ReadException e) {
+			PersistenceException ex =
+					createPersistenceException("Error loading state from persistence");
+			ex.add(e);
+			throw ex;
+		}
+		setColorFont((Color) state.get(FIELD_COLOR_FONT));
+		setZoomConstraints((IZoomConstraints) state.get(FIELD_ZOOM_CONSTRAINTS));
+		setLabelingMethod((ILabelingMethod) state.get(FIELD_LABELING_METHOD));
+	}
+
+	public static void registerPersistence() {
+		// Add the DynClass definition.
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				DefaultLabelingMethod.class,
+				ATTR_IN_TABLE_LABELING_STRATEGY_DYNCLASS_NAME,
+				ATTR_IN_TABLE_LABELING_STRATEGY_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		definition.addDynFieldString(FIELD_TEXT).setMandatory(true);
+		definition.addDynFieldString(FIELD_HEIGHT).setMandatory(true);
+		definition.addDynFieldString(FIELD_COLOR).setMandatory(true);
+		definition.addDynFieldString(FIELD_ROTATION).setMandatory(true);
+		definition.addDynFieldInt(FIELD_UNIT).setMandatory(true);
+		definition.addDynFieldObject(FIELD_FONT).setMandatory(true);
+		definition.addDynFieldBoolean(FIELD_USE_FIXED_SIZE).setMandatory(true);
+		definition.addDynFieldDouble(FIELD_FIXED_SIZE).setMandatory(true);
+		definition.addDynFieldBoolean(FIELD_USE_FIXED_COLOR).setMandatory(true);
+		definition.addDynFieldObject(FIELD_FIXED_COLOR).setMandatory(true);
+		definition.addDynFieldInt(FIELD_REFERENCE_SYSTEM).setMandatory(true);
+		definition.addDynFieldObject(FIELD_LAYER).setMandatory(true);
+		definition.addDynFieldObject(FIELD_COLOR_FONT).setMandatory(true);
+		definition.addDynFieldObject(FIELD_ZOOM_CONSTRAINTS).setMandatory(true);
+		definition.addDynFieldObject(FIELD_LABELING_METHOD).setMandatory(true);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gvsig.tools.persistence.Persistent#saveToState(org.gvsig.tools.persistence.PersistentState)
+	 */
+	public void saveToState(PersistentState state) throws PersistenceException {
+		PersistenceException ex = null;
+
+		try {
+			state.set(FIELD_TEXT, getTextField());
+		} catch (DataException e) {
+			if (ex == null) {
+				ex = createPersistenceException("Error saving to state");
+			}
+			ex.add(e);
+		}
+		try {
+			state.set(FIELD_HEIGHT, getHeightField());
+		} catch (DataException e) {
+			if (ex == null) {
+				ex = createPersistenceException("Error saving to state");
+			}
+			ex.add(e);
+		}
+		try {
+			state.set(FIELD_COLOR, getColorField());
+		} catch (DataException e) {
+			if (ex == null) {
+				ex = createPersistenceException("Error saving to state");
+			}
+			ex.add(e);
+		}
+		try {
+			state.set(FIELD_ROTATION, getRotationField());
+		} catch (DataException e) {
+			if (ex == null) {
+				ex =
+						createPersistenceException("Error saving to state for persistence");
+			}
+			ex.add(e);
+		}
+		state.set(FIELD_UNIT, getUnit());
+		state.set(FIELD_FONT, getFont());
+		state.set(FIELD_USE_FIXED_SIZE, useFixedSize);
+		state.set(FIELD_FIXED_SIZE, getFixedSize());
+		state.set(FIELD_USE_FIXED_COLOR, useFixedColor);
+		state.set(FIELD_FIXED_COLOR, getFixedColor());
+		state.set(FIELD_REFERENCE_SYSTEM, getReferenceSystem());
+		state.set(FIELD_LAYER, layer);
+		state.set(FIELD_COLOR_FONT, getColorFont());
+		state.set(FIELD_ZOOM_CONSTRAINTS, getZoomConstraints());
+		state.set(FIELD_LABELING_METHOD, getLabelingMethod());
+
+		if (ex != null) {
+			throw ex;
+		}
+	}
+
+	private PersistenceException createPersistenceException(String message) {
+		PersistenceException ex = new PersistenceException(message);
+		ex.fillInStackTrace();
+		return ex;
+	}
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/ZoomConstraintsImpl.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/ZoomConstraintsImpl.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/styling/ZoomConstraintsImpl.java	(revision 33580)
@@ -0,0 +1,170 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+
+/* CVS MESSAGES:
+*
+* $Id: ZoomConstraintsImpl.java 10671 2007-03-09 08:33:43Z jaume $
+* $Log$
+* Revision 1.2  2007-03-09 08:33:43  jaume
+* *** empty log message ***
+*
+* Revision 1.1.2.2  2007/02/15 16:23:44  jaume
+* *** empty log message ***
+*
+* Revision 1.1.2.1  2007/02/09 07:47:05  jaume
+* Isymbol moved
+*
+* Revision 1.1.2.1  2007/01/30 18:10:45  jaume
+* start commiting labeling stuff
+*
+*
+*/
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling;
+
+
+import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.dynobject.DynStruct;
+import org.gvsig.tools.persistence.PersistenceManager;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+
+/**
+ * @author  jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class ZoomConstraintsImpl implements IZoomConstraints {
+	private static final String FIELD_MIN_SCALE = "minScale";
+	private static final String FIELD_MAX_SCALE = "maxScale";
+	private static final String FIELD_MODE = "mode";
+	private static final String ZOOM_CONSTRAINTS_IMPL_DYNCLASS_NAME =
+			"ZoomConstraintsImpl";
+	/**
+	 * @uml.property  name="mode"
+	 */
+	private int mode = DEFINED_BY_THE_LAYER;
+	/**
+	 * @uml.property  name="minScale"
+	 */
+	private long minScale = -1;
+	/**
+	 * @uml.property  name="maxScale"
+	 */
+	private long maxScale = -1;
+
+	/**
+	 * @param mode
+	 * @uml.property  name="mode"
+	 */
+	public void setMode(int mode) {
+		if (mode != DEFINED_BY_THE_LAYER &&
+			mode != DEFINED_BY_THE_USER)
+			throw new IllegalArgumentException();
+		this.mode = mode;
+	}
+
+	/**
+	 * @return
+	 * @uml.property  name="maxScale"
+	 */
+	public long getMaxScale() {
+		return maxScale;
+	}
+
+	/**
+	 * @param maxScale
+	 * @uml.property  name="maxScale"
+	 */
+	public void setMaxScale(long maxScale) {
+		this.maxScale = maxScale;
+	}
+
+	/**
+	 * @return
+	 * @uml.property  name="minScale"
+	 */
+	public long getMinScale() {
+		return minScale;
+	}
+
+	/**
+	 * @param minScale
+	 * @uml.property  name="minScale"
+	 */
+	public void setMinScale(long minScale) {
+		this.minScale = minScale;
+	}
+
+	public boolean isUserDefined() {
+		return mode == DEFINED_BY_THE_USER;
+	}
+
+	public boolean isLayerDefined() {
+		return mode == DEFINED_BY_THE_LAYER;
+	}
+
+	public void loadFromState(PersistentState state)
+			throws PersistenceException {
+		setMode(state.getInt(FIELD_MODE));
+		setMaxScale(state.getLong(FIELD_MAX_SCALE));
+		setMinScale(state.getLong(FIELD_MIN_SCALE));
+	}
+
+	public void saveToState(PersistentState state) throws PersistenceException {
+		state.set(FIELD_MODE, mode);
+		state.set(FIELD_MAX_SCALE, getMaxScale());
+		state.set(FIELD_MIN_SCALE, getMinScale());
+	}
+
+	public static void registerPersistence() {
+		PersistenceManager manager = ToolsLocator.getPersistenceManager();
+		DynStruct definition = manager.addDefinition(
+				ZoomConstraintsImpl.class,
+				ZOOM_CONSTRAINTS_IMPL_DYNCLASS_NAME,
+				ZOOM_CONSTRAINTS_IMPL_DYNCLASS_NAME+" Persistence definition",
+				null, 
+				null
+		);
+		definition.addDynFieldInt(FIELD_MODE).setMandatory(true);
+		definition.addDynFieldLong(FIELD_MIN_SCALE).setMandatory(true);
+		definition.addDynFieldLong(FIELD_MAX_SCALE).setMandatory(true);
+	}
+
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/javadoc/overview.html
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/javadoc/overview.html	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/main/javadoc/overview.html	(revision 33580)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>org.gvsig.template.extension package documentation</title>
+</head>
+<body>
+
+	<p>TODO: Example extension overview.</p>
+	
+	<p>See the <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#overviewcomment">Javadoc Tool documentation about the overview file</a></p>
+
+</body>
+</html>
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/AllTests.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/AllTests.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/AllTests.java	(revision 33580)
@@ -0,0 +1,125 @@
+package org.gvsig.symbology.fmap.mapcontext.rendering;
+
+import java.io.File;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.cresques.cts.IProjection;
+import org.gvsig.fmap.crs.CRSFactory;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
+import org.gvsig.fmap.mapcontext.layers.FLayer;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestDrawFills;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestDrawLines;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestDrawMarkers;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestMultiLayerSymbol;
+
+public class AllTests extends TestCase{
+	/**
+	 * The EPSG:4326 projection
+	 */
+	public static IProjection TEST_DEFAULT_PROJECTION =
+		CRSFactory.getCRS("EPSG:4326");
+
+	/**
+	 * The EPSG:23030 projection
+	 */
+	public static IProjection TEST_DEFAULT_MERCATOR_PROJECTION =
+		CRSFactory.getCRS("EPSG:23030");
+
+	/**
+	 * The EPSG:23029 projection
+	 */
+	public static IProjection test_newProjection =
+		CRSFactory.getCRS("EPSG:23029");
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite("Test for com.iver.cit.gvsig.fmap");
+		//$JUnit-BEGIN$
+
+
+
+		/* Symbols (jaume) */
+			// integration tests
+				// ISymbol
+				suite.addTestSuite(TestISymbol.class);
+				suite.addTestSuite(TestMultiLayerSymbol.class);
+
+				// CartographicSupport
+				suite.addTestSuite(TestCartographicSupportForSymbol.class);
+
+		//
+		/*
+		 * Feature iterators
+		 * */
+//		suite.addTestSuite(FeatureIteratorTest.class);
+
+		/*
+		 * Other Tests present in FMap (cesar)
+		 * Remove them from here and the src-test dir if they are not
+		 * useful anymore.
+		 */
+
+//		suite.addTestSuite(TestAbstractIntervalLegend.class);
+		suite.addTestSuite(TestCartographicSupportForSymbol.class);
+		suite.addTestSuite(TestDrawFills.class);
+		suite.addTestSuite(TestDrawLines.class);
+		suite.addTestSuite(TestDrawMarkers.class);
+//		suite.addTestSuite(TestIClassifiedLegend.class);
+//		suite.addTestSuite(TestILegend.class);
+		suite.addTestSuite(TestMultiLayerSymbol.class);
+
+		//$JUnit-END$
+		return suite;
+	}
+
+//// jaume
+//// PASTED FROM FeatureIteratorTest.java to be globally accessible
+	static final String fwAndamiDriverPath = "../_fwAndami/gvSIG/extensiones/com.iver.cit.gvsig/drivers";
+	private static File baseDataPath;
+	private static File baseDriversPath;
+
+
+	public static void setUpDrivers() {
+//		try {
+//			URL url = AllTests.class.getResource("testdata");
+//			if (url == null)
+//				throw new Exception("No se encuentra el directorio con datos de prueba");
+//
+//			baseDataPath = new File(url.getFile());
+//			if (!baseDataPath.exists())
+//				throw new Exception("No se encuentra el directorio con datos de prueba");
+//
+//			baseDriversPath = new File(fwAndamiDriverPath);
+//			if (!baseDriversPath.exists())
+//				throw new Exception("Can't find drivers path: " + fwAndamiDriverPath);
+//
+//			LayerFactory.setDriversPath(baseDriversPath.getAbsolutePath());
+//			if (LayerFactory.getDM().getDriverNames().length < 1)
+//				throw new Exception("Can't find drivers in path: " + fwAndamiDriverPath);
+//		} catch (Exception e) {
+//			throw new RuntimeException(e);
+//		}
+	}
+
+	public static FLayer newLayer(String fileName,
+			String driverName)
+	throws LoadLayerException {
+//		File file = new File(baseDataPath, fileName);
+//		return LayerFactory.createLayer(fileName,
+//				driverName,
+//				file, TEST_DEFAULT_MERCATOR_PROJECTION);
+	return null;
+	}
+
+	public static MapContext newMapContext(IProjection projection) {
+		ViewPort vp = new ViewPort(projection);
+		return new MapContext(vp);
+	}
+
+//// end past
+}
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestIClassifiedLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestIClassifiedLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestIClassifiedLegend.java	(revision 33580)
@@ -0,0 +1,804 @@
+ /* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.cresques.cts.IProjection;
+import org.gvsig.fmap.dal.DataQuery;
+import org.gvsig.fmap.dal.DataServerExplorer;
+import org.gvsig.fmap.dal.DataServerExplorerParameters;
+import org.gvsig.fmap.dal.DataSet;
+import org.gvsig.fmap.dal.DataStoreParameters;
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.exception.ReadException;
+import org.gvsig.fmap.dal.feature.EditableFeature;
+import org.gvsig.fmap.dal.feature.EditableFeatureType;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureCache;
+import org.gvsig.fmap.dal.feature.FeatureIndex;
+import org.gvsig.fmap.dal.feature.FeatureIndexes;
+import org.gvsig.fmap.dal.feature.FeatureLocks;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureReference;
+import org.gvsig.fmap.dal.feature.FeatureSelection;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
+import org.gvsig.fmap.dal.feature.FeatureType;
+import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
+import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.Geometry.TYPES;
+import org.gvsig.fmap.geom.primitive.Curve;
+import org.gvsig.fmap.geom.primitive.Envelope;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractIntervalLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestISymbol;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.dynobject.DynObject;
+import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
+import org.gvsig.tools.dynobject.exception.DynMethodException;
+import org.gvsig.tools.exception.BaseException;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.gvsig.tools.observer.Observer;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.undo.RedoException;
+import org.gvsig.tools.undo.UndoException;
+import org.gvsig.tools.visitor.Visitor;
+
+
+/**
+ * Integration test to ensure that the legends which implements the
+ * IClassifiedLegend interface follow the rules that follow the managing of them
+ * by the application.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ * @author pepe vidal salvador - jose.vidal.salvador@iver.es
+ */
+public class TestIClassifiedLegend extends AbstractLibraryAutoInitTestCase {
+
+	private static final Integer v0 = new Integer(0);
+	private static final Integer v1 = new Integer(1);
+	private static final Integer v2 = new Integer(2);
+	private static final Integer v3 = new Integer(3);
+
+	private static final String FIELD3 = "field3";
+	private static final String FIELD2 = "field2";
+	private static final String FIELD1 = "field1";
+	private static final String FIELD0 = "field0";
+	private static final int FIELDID = 0;
+
+//	private static final Integer[] feature0Values = new Integer[] { v0, v1, v2, v3, };
+//	private static final Integer[] feature1Values = new Integer[] { v3, v0, v1, v2, };
+//	private static final Integer[] feature2Values = new Integer[] { v2, v3, v0, v1, };
+//	private static final Integer[] feature3Values = new Integer[] { v1, v2, v3, v0, };
+//
+//	private static final Integer[][] featureValues = new Integer[][] {
+//		feature0Values,
+//		feature1Values,
+//		feature2Values,
+//		feature3Values,};
+
+	private static String[] fieldNames = new String[] {FIELD0,FIELD1,FIELD2,FIELD3,};
+
+
+	// private static final Value v4 = (Value)ValueFactory.createValue(4);
+	// private static final Value v5 = (Value)ValueFactory.createValue(5);
+	// private static final Value v6 = (Value)ValueFactory.createValue(6);
+	// private static final Value v7 = (Value)ValueFactory.createValue(7);
+	// private static final Value v8 = (Value)ValueFactory.createValue(8);
+	// private static final Value v9 = (Value)ValueFactory.createValue(9);
+
+	private AbstractIntervalLegend[] intervalLegends;
+//	private MockDataSource mockDataSource = new MockDataSource();
+
+	/**
+	 * To avoid duplicated validation logic in the test a mock object is created
+	 * to use a DataSource for this test.
+	 *
+	 */
+	private class MockDataSource implements FeatureStore {
+
+		public boolean allowWrite() {
+
+			return false;
+		}
+
+		public void beginEditingGroup(String description)
+				throws NeedEditingModeException {
+
+
+		}
+
+		public boolean canWriteGeometry(int gvSIGgeometryType)
+				throws DataException {
+
+			return false;
+		}
+
+		public void cancelEditing() throws DataException {
+
+
+		}
+
+		public FeatureSelection createFeatureSelection() throws DataException {
+
+			return null;
+		}
+
+		public FeatureIndex createIndex(FeatureType featureType,
+				String attributeName, String indexName) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature() throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(FeatureType type,
+				Feature defaultValues) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(FeatureType type,
+				boolean defaultValues) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(boolean defaultValues)
+				throws DataException {
+
+			return null;
+		}
+
+		public void delete(Feature feature) throws DataException {
+
+
+		}
+
+		public void edit() throws DataException {
+
+
+		}
+
+		public void edit(int mode) throws DataException {
+
+
+		}
+
+		public void endEditingGroup() throws NeedEditingModeException {
+
+
+		}
+
+		public void finishEditing() throws DataException {
+
+
+		}
+
+		public FeatureType getDefaultFeatureType() throws DataException {
+
+			return null;
+		}
+
+		public Envelope getEnvelope() {
+
+			return null;
+		}
+
+		public Feature getFeatureByReference(FeatureReference reference)
+				throws DataException {
+
+			return null;
+		}
+
+		public Feature getFeatureByReference(FeatureReference reference,
+				FeatureType featureType) throws DataException {
+
+			return null;
+		}
+
+		public FeatureSelection getFeatureSelection() throws DataException {
+
+			return null;
+		}
+
+		public FeatureSet getFeatureSet() throws DataException {
+
+			return null;
+		}
+
+		public FeatureSet getFeatureSet(FeatureQuery featureQuery)
+				throws DataException {
+
+			return null;
+		}
+
+		public void getFeatureSet(FeatureQuery featureQuery, Observer observer)
+				throws DataException {
+
+
+		}
+
+		public void getFeatureSet(Observer observer) throws DataException {
+
+
+		}
+
+		public List getFeatureTypes() throws DataException {
+
+			return null;
+		}
+
+		public FeatureIndexes getIndexes() {
+
+			return null;
+		}
+
+		public FeatureLocks getLocks() throws DataException {
+
+			return null;
+		}
+
+		public DataStoreParameters getParameters() {
+
+			return null;
+		}
+
+		public IProjection getSRSDefaultGeometry() throws DataException {
+
+			return null;
+		}
+
+		public FeatureStoreTransforms getTransforms() {
+
+			return null;
+		}
+
+		public void insert(EditableFeature feature) throws DataException {
+
+
+		}
+
+		public boolean isAppendModeSupported() {
+
+			return false;
+		}
+
+		public boolean isAppending() {
+
+			return false;
+		}
+
+		public boolean isEditing() {
+
+			return false;
+		}
+
+		public boolean isLocksSupported() {
+
+			return false;
+		}
+
+		public void setSelection(FeatureSet selection) throws DataException {
+
+
+		}
+
+		public void update(EditableFeatureType featureType)
+				throws DataException {
+
+
+		}
+
+		public void update(EditableFeature feature) throws DataException {
+
+
+		}
+
+		public void validateFeatures(int mode) throws DataException {
+
+
+		}
+
+		public DataSet createSelection() throws DataException {
+
+			return null;
+		}
+
+		public void dispose() {
+
+
+		}
+
+		public Iterator getChildren() {
+
+			return null;
+		}
+
+		public DataSet getDataSet() throws DataException {
+
+			return null;
+		}
+
+		public DataSet getDataSet(DataQuery dataQuery) throws DataException {
+
+			return null;
+		}
+
+		public void getDataSet(Observer observer) throws DataException {
+
+
+		}
+
+		public void getDataSet(DataQuery dataQuery, Observer observer)
+				throws DataException {
+
+
+		}
+
+		public DataServerExplorer getExplorer() throws DataException {
+
+			return null;
+		}
+
+		public String getName() {
+
+			return null;
+		}
+
+		public DataSet getSelection() throws DataException {
+
+			return null;
+		}
+
+		public void refresh() throws DataException {
+
+
+		}
+
+		public void setSelection(DataSet selection) throws DataException {
+
+
+		}
+
+		public void beginComplexNotification() {
+
+
+		}
+
+		public void disableNotifications() {
+
+
+		}
+
+		public void enableNotifications() {
+
+
+		}
+
+		public void endComplexNotification() {
+
+
+		}
+
+		public void addObserver(Observer o) {
+
+
+		}
+
+		public void deleteObserver(Observer o) {
+
+
+		}
+
+		public void deleteObservers() {
+
+
+		}
+
+		public void saveToState(PersistentState state)
+				throws PersistenceException {
+
+
+		}
+
+		public void loadFromState(PersistentState state) throws PersistenceException {
+
+
+		}
+
+		public FeatureQuery createFeatureQuery() {
+
+			return null;
+		}
+
+		public boolean canRedo() {
+
+			return false;
+		}
+
+		public boolean canUndo() {
+
+			return false;
+		}
+
+		public List getRedoInfos() {
+
+			return null;
+		}
+
+		public List getUndoInfos() {
+
+			return null;
+		}
+
+		public void redo() throws RedoException {
+
+
+		}
+
+		public void redo(int num) throws RedoException {
+
+
+		}
+
+		public void undo() throws UndoException {
+
+
+		}
+
+		public void undo(int num) throws UndoException {
+
+
+		}
+
+		public FeatureIndex createIndex(FeatureType featureType,
+				String attributeName, String indexName, Observer observer)
+				throws DataException {
+
+			return null;
+		}
+
+		public Object getMetadataID() {
+
+			return null;
+		}
+
+		public void delegate(DynObject dynObject) {
+
+
+		}
+
+		public DynClass getDynClass() {
+
+			return null;
+		}
+
+		public Object getDynValue(String name) throws DynFieldNotFoundException {
+
+			return null;
+		}
+
+		public boolean hasDynValue(String name) {
+
+			return false;
+		}
+
+		public void implement(DynClass dynClass) {
+
+
+		}
+
+		public Object invokeDynMethod(String name, DynObject context)
+				throws DynMethodException {
+
+			return null;
+		}
+
+		public Object invokeDynMethod(int code, DynObject context)
+				throws DynMethodException {
+
+			return null;
+		}
+
+		public void setDynValue(String name, Object value)
+				throws DynFieldNotFoundException {
+
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.gvsig.metadata.Metadata#getMetadataChildren()
+		 */
+		public Set getMetadataChildren() {
+
+			return null;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.gvsig.metadata.Metadata#getMetadataName()
+		 */
+		public String getMetadataName() {
+
+			return null;
+		}
+
+		public FeatureType getFeatureType(String featureTypeId)
+				throws DataException {
+
+			return null;
+		}
+
+		public DataQuery createQuery() {
+
+			return null;
+		}
+
+		public long getFeatureCount() throws DataException {
+
+			return 0;
+		}
+
+		public void accept(Visitor visitor, DataQuery dataQuery)
+				throws BaseException {
+		}
+
+		public void accept(Visitor visitor) throws BaseException {
+		}
+
+		public void createCache(String name,
+				DynObject parameters) throws DataException {
+			// Do nothing
+		}
+
+		public FeatureCache getCache() {
+			return null;
+		}
+
+		public void clear() {
+			// Nothing to do
+		}
+
+		public void export(DataServerExplorer explorer, String provider,
+				NewFeatureStoreParameters params) throws DataException {
+			
+		}
+
+		public String getProviderName() {
+			return null;
+		}
+
+	}
+
+	//private static final FInterval interval0=new FInterval(0,2);
+	//private static final FInterval interval1=new FInterval(3,5);
+	//private static final FInterval interval2=new FInterval(6,2);
+	//private static final FInterval interval3=new FInterval(9,2);
+	// private static final Value interval4;
+	// private static final Value interval5;
+	// private static final Value interval6;
+	// private static final Value interval7;
+	// private static final Value interval8;
+	// private static final Value interval9;
+
+	Hashtable symTable;
+
+	private IClassifiedVectorLegend[] classifiedLegends;
+	private ISymbol[] symbols;
+	private Object[] sampleValues = new Object[] { v0, v1, v2, v3, };
+	private Feature[] features;
+
+	// private FInterval[] intervals = new FInterval[] {
+	// interval0,
+	// interval1,
+	// interval2,
+	// interval3,
+	// interval4,
+	// interval5,
+	// interval6,
+	// interval7,
+	// interval8,
+	// interval9,
+	// };
+
+	protected void doSetUp() throws Exception {
+		
+		features = new Feature[4];
+
+//		//Initializes the geometries library
+//		DefaultGeometryLibrary lib = new DefaultGeometryLibrary();
+//		lib.initialize();
+//		lib.postInitialize();
+
+		// initialize test values
+		for (int i = 0; i < features.length; i++) {
+			// create the geometry associated to the feature
+			int size = 200;
+			Dimension d = new Dimension(size, size);
+			Rectangle aShape = new Rectangle(i * size, i * size, d.width,
+					d.height);
+			GeometryManager geomManager = GeometryLocator.getGeometryManager();
+			Curve curve = (Curve)geomManager.create(TYPES.CURVE, SUBTYPES.GEOM2D);
+			curve.setGeneralPath(new GeneralPathX(aShape.getPathIterator(null)));
+
+			/*
+			 * create a full-featured Feature with randomed values at its fields
+			 * to avoid testing over the same values each time
+			 */
+//			features[i] = new DefaultFeature(geom, featureValues[i], "[" + i
+//					+ "]");
+		}
+
+		// initialize the symbol subset for this test
+		symbols = TestISymbol.getNewSymbolInstances();
+
+		// initialize the legends for this test
+		ILegend[] allLegends = TestILegend.getNewLegendInstances();
+		ArrayList clegends = new ArrayList();
+		ArrayList intervalLegends = new ArrayList();
+		for (int i = 0; i < allLegends.length; i++) {
+			if (allLegends[i] instanceof AbstractIntervalLegend) {
+				intervalLegends.add(allLegends[i]);
+			} else if (allLegends[i] instanceof IClassifiedLegend) {
+				clegends.add(allLegends[i]);
+			}
+
+			if (allLegends[i] instanceof IClassifiedVectorLegend) {
+				IClassifiedVectorLegend cvl = (IClassifiedVectorLegend) allLegends[i];
+				cvl.setClassifyingFieldNames(new String[] { fieldNames[FIELDID] });
+//				cvl.setFeatureStore(mockDataSource);
+
+			}
+		}
+
+		this.classifiedLegends = (IClassifiedVectorLegend[]) clegends
+				.toArray(new IClassifiedVectorLegend[clegends.size()]);
+		this.intervalLegends =
+				(AbstractIntervalLegend[]) intervalLegends
+				.toArray(new AbstractIntervalLegend[intervalLegends.size()]);
+	}
+
+	/**
+	 * This method is used to add symbols to a legend.That is, it takes an array
+	 * of IClassifiedVectorialLegend which is empty andm, using a second array
+	 * of objects (values), the first one is filled.Also, a hash table is filled
+	 * too using the array of objects (it will be useful in some tests to check
+	 * that a symbol can be taken using a feature) .
+	 *
+	 * @param legend
+	 * @return
+	 */
+	private void fillClassifiedLegend(IClassifiedVectorLegend legend,
+			Object[] values) {
+		// initialize the hash table
+		symTable = new Hashtable();
+
+		// to add symbols to the legend and the hash table
+		for (int j = 0; j < values.length; j++) {
+
+			ISymbol sym = symbols[j % symbols.length];
+			legend.addSymbol(values[j], sym);
+			symTable.put(values[j], sym);
+		}
+	}
+
+	/**
+	 * This test ensures that when a legend is filled, the number of symbols
+	 * added is correct. To do it, is checked that the number of symbols of a
+	 * legend is the same as the length of the array of example values that we
+	 * have.
+	 *
+	 * @throws ReadDriverException
+	 */
+	public void testICLAdittion() throws ReadException {
+
+		// Fills the legend
+		for (int i = 0; i < classifiedLegends.length; i++) {
+			fillClassifiedLegend(classifiedLegends[i], sampleValues);
+		}
+
+		for (int i = 0; i < classifiedLegends.length; i++) {
+			assertEquals(classifiedLegends[i].getClass().getName()
+					+ " fails with the comparation of the number of symbols",
+					classifiedLegends[i].getSymbols().length,
+					sampleValues.length);
+		}
+
+	}
+
+	/**
+	 * This test ensures that the symbols that we have previously added to a
+	 * legend are accessible using its features.To do it, this test compares the
+	 * symbol taken from the legend with the symbol taken from the hashTable
+	 * (using the same feature).
+	 * @throws Exception 
+	 */
+	public void testICLCheckValueSymbols() throws Exception {
+		// fills the legends
+		for (int i = 0; i < classifiedLegends.length; i++) {
+			fillClassifiedLegend(classifiedLegends[i], sampleValues);
+		}
+
+		for (int i = 0; i < classifiedLegends.length; i++) {
+			// For each feature
+			for (int j = 0; j < features.length; j++) {
+				Feature myFeature = features[i];
+				// takes the value of the field that identifies the feature
+				Object val = myFeature.get(FIELDID);
+				// the last value is used to access to the hash table to obtain
+				// a symbol
+				ISymbol tableSym = (ISymbol) symTable.get(val);
+
+				IClassifiedVectorLegend leg = classifiedLegends[i];
+				// takes the symbol from a legend using the feature
+				ISymbol legendSym = leg.getSymbolByFeature(myFeature);
+				// compares that both symbols are the same
+				assertEquals(legendSym.getClass().getName()
+						+ " fails with the comparation of the class symbols",
+						legendSym, tableSym);
+			}
+		}
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestAbstractIntervalLegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestAbstractIntervalLegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestAbstractIntervalLegend.java	(revision 33580)
@@ -0,0 +1,806 @@
+ /* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.cresques.cts.IProjection;
+import org.gvsig.fmap.dal.DataQuery;
+import org.gvsig.fmap.dal.DataServerExplorer;
+import org.gvsig.fmap.dal.DataServerExplorerParameters;
+import org.gvsig.fmap.dal.DataSet;
+import org.gvsig.fmap.dal.DataStoreParameters;
+import org.gvsig.fmap.dal.exception.DataException;
+import org.gvsig.fmap.dal.exception.ReadException;
+import org.gvsig.fmap.dal.feature.EditableFeature;
+import org.gvsig.fmap.dal.feature.EditableFeatureType;
+import org.gvsig.fmap.dal.feature.Feature;
+import org.gvsig.fmap.dal.feature.FeatureCache;
+import org.gvsig.fmap.dal.feature.FeatureIndex;
+import org.gvsig.fmap.dal.feature.FeatureIndexes;
+import org.gvsig.fmap.dal.feature.FeatureLocks;
+import org.gvsig.fmap.dal.feature.FeatureQuery;
+import org.gvsig.fmap.dal.feature.FeatureReference;
+import org.gvsig.fmap.dal.feature.FeatureSelection;
+import org.gvsig.fmap.dal.feature.FeatureSet;
+import org.gvsig.fmap.dal.feature.FeatureStore;
+import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
+import org.gvsig.fmap.dal.feature.FeatureType;
+import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
+import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.Geometry.TYPES;
+import org.gvsig.fmap.geom.primitive.Curve;
+import org.gvsig.fmap.geom.primitive.Envelope;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractIntervalLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.FInterval;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.TestISymbol;
+import org.gvsig.tools.dynobject.DynClass;
+import org.gvsig.tools.dynobject.DynObject;
+import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
+import org.gvsig.tools.dynobject.exception.DynMethodException;
+import org.gvsig.tools.exception.BaseException;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.gvsig.tools.observer.Observer;
+import org.gvsig.tools.persistence.PersistentState;
+import org.gvsig.tools.persistence.exception.PersistenceException;
+import org.gvsig.tools.undo.RedoException;
+import org.gvsig.tools.undo.UndoException;
+import org.gvsig.tools.visitor.Visitor;
+
+/**
+ * Integration test to ensure that the legends which implements the
+ * IVectorialIntervalLegend interface follow the rules that follow the managing
+ * of them by the application.
+ *
+ * @author pepe vidal salvador - jose.vidal.salvador@iver.es
+ */
+public class TestAbstractIntervalLegend extends AbstractLibraryAutoInitTestCase {
+
+	private static final Integer v0 = new Integer(0);
+	private static final Integer v1 = new Integer(1);
+	private static final Integer v2 = new Integer(2);
+	private static final Integer v3 = new Integer(3);
+
+	private static final String FIELD3 = "field3";
+	private static final String FIELD2 = "field2";
+	private static final String FIELD1 = "field1";
+	private static final String FIELD0 = "field0";
+	private static final int FIELDID = 0;
+
+	private static final Integer[] feature0Values = new Integer[] { v0, v1, v2, v3, };
+	private static final Integer[] feature1Values = new Integer[] { v3, v0, v1, v2, };
+	private static final Integer[] feature2Values = new Integer[] { v2, v3, v0, v1, };
+	private static final Integer[] feature3Values = new Integer[] { v1, v2, v3, v0, };
+
+	private static final Integer[][] featureValues = new Integer[][] {
+		feature0Values,
+		feature1Values,
+		feature2Values,
+		feature3Values,};
+
+	private static String[] fieldNames = new String[] {FIELD0,FIELD1,FIELD2,FIELD3,};
+
+
+	// private static final Value v4 = (Value)ValueFactory.createValue(4);
+	// private static final Value v5 = (Value)ValueFactory.createValue(5);
+	// private static final Value v6 = (Value)ValueFactory.createValue(6);
+	// private static final Value v7 = (Value)ValueFactory.createValue(7);
+	// private static final Value v8 = (Value)ValueFactory.createValue(8);
+	// private static final Value v9 = (Value)ValueFactory.createValue(9);
+
+	private AbstractIntervalLegend[] intervalLegends;
+	private MockDataSource mockDataSource = new MockDataSource();
+
+	/**
+	 * To avoid duplicated validation logic in the test a mock object is created
+	 * to use a DataSource for this test.
+	 *
+	 */
+	private class MockDataSource implements FeatureStore {
+
+		public boolean allowWrite() {
+
+			return false;
+		}
+
+		public void beginEditingGroup(String description)
+				throws NeedEditingModeException {
+
+
+		}
+
+		public boolean canWriteGeometry(int gvSIGgeometryType)
+				throws DataException {
+
+			return false;
+		}
+
+		public void cancelEditing() throws DataException {
+
+
+		}
+
+		public FeatureSelection createFeatureSelection() throws DataException {
+
+			return null;
+		}
+
+		public FeatureIndex createIndex(FeatureType featureType,
+				String attributeName, String indexName) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature() throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(FeatureType type,
+				Feature defaultValues) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(FeatureType type,
+				boolean defaultValues) throws DataException {
+
+			return null;
+		}
+
+		public EditableFeature createNewFeature(boolean defaultValues)
+				throws DataException {
+
+			return null;
+		}
+
+		public void delete(Feature feature) throws DataException {
+
+
+		}
+
+		public void edit() throws DataException {
+
+
+		}
+
+		public void edit(int mode) throws DataException {
+
+
+		}
+
+		public void endEditingGroup() throws NeedEditingModeException {
+
+
+		}
+
+		public void finishEditing() throws DataException {
+
+
+		}
+
+		public FeatureType getDefaultFeatureType() throws DataException {
+
+			return null;
+		}
+
+		public Envelope getEnvelope() {
+
+			return null;
+		}
+
+		public Feature getFeatureByReference(FeatureReference reference)
+				throws DataException {
+
+			return null;
+		}
+
+		public Feature getFeatureByReference(FeatureReference reference,
+				FeatureType featureType) throws DataException {
+
+			return null;
+		}
+
+		public FeatureSelection getFeatureSelection() throws DataException {
+
+			return null;
+		}
+
+		public FeatureSet getFeatureSet() throws DataException {
+
+			return null;
+		}
+
+		public FeatureSet getFeatureSet(FeatureQuery featureQuery)
+				throws DataException {
+
+			return null;
+		}
+
+		public void getFeatureSet(FeatureQuery featureQuery, Observer observer)
+				throws DataException {
+
+
+		}
+
+		public void getFeatureSet(Observer observer) throws DataException {
+
+
+		}
+
+		public List getFeatureTypes() throws DataException {
+
+			return null;
+		}
+
+		public FeatureIndexes getIndexes() {
+
+			return null;
+		}
+
+		public FeatureLocks getLocks() throws DataException {
+
+			return null;
+		}
+
+		public DataStoreParameters getParameters() {
+
+			return null;
+		}
+
+		public IProjection getSRSDefaultGeometry() throws DataException {
+
+			return null;
+		}
+
+		public FeatureStoreTransforms getTransforms() {
+
+			return null;
+		}
+
+		public void insert(EditableFeature feature) throws DataException {
+
+
+		}
+
+		public boolean isAppendModeSupported() {
+
+			return false;
+		}
+
+		public boolean isAppending() {
+
+			return false;
+		}
+
+		public boolean isEditing() {
+
+			return false;
+		}
+
+		public boolean isLocksSupported() {
+
+			return false;
+		}
+
+
+		public void setSelection(FeatureSet selection) throws DataException {
+
+
+		}
+		public void update(EditableFeatureType featureType)
+				throws DataException {
+
+
+		}
+
+		public void update(EditableFeature feature) throws DataException {
+
+
+		}
+
+		public void validateFeatures(int mode) throws DataException {
+
+
+		}
+
+		public DataSet createSelection() throws DataException {
+
+			return null;
+		}
+
+		public void dispose() {
+
+
+		}
+
+		public Iterator getChildren() {
+
+			return null;
+		}
+
+		public DataSet getDataSet() throws DataException {
+
+			return null;
+		}
+
+		public DataSet getDataSet(DataQuery dataQuery) throws DataException {
+
+			return null;
+		}
+
+		public void getDataSet(Observer observer) throws DataException {
+
+
+		}
+
+		public void getDataSet(DataQuery dataQuery, Observer observer)
+				throws DataException {
+
+
+		}
+
+		public DataServerExplorer getExplorer() throws DataException {
+
+			return null;
+		}
+
+		public String getName() {
+
+			return null;
+		}
+
+		public DataSet getSelection() throws DataException {
+
+			return null;
+		}
+
+		public void refresh() throws DataException {
+
+
+		}
+
+		public void setSelection(DataSet selection) throws DataException {
+
+
+		}
+
+		public void beginComplexNotification() {
+
+
+		}
+
+		public void disableNotifications() {
+
+
+		}
+
+		public void enableNotifications() {
+
+
+		}
+
+		public void endComplexNotification() {
+
+
+		}
+
+		public void addObserver(Observer o) {
+
+
+		}
+
+		public void deleteObserver(Observer o) {
+
+
+		}
+
+		public void deleteObservers() {
+
+
+		}
+
+		public void saveToState(PersistentState state)
+				throws PersistenceException {
+
+
+		}
+
+		public void loadFromState(PersistentState state) throws PersistenceException {
+
+
+		}
+
+		public FeatureQuery createFeatureQuery() {
+
+			return null;
+		}
+
+		public boolean canRedo() {
+
+			return false;
+		}
+
+		public boolean canUndo() {
+
+			return false;
+		}
+
+		public List getRedoInfos() {
+
+			return null;
+		}
+
+		public List getUndoInfos() {
+
+			return null;
+		}
+
+		public void redo() throws RedoException {
+
+
+		}
+
+		public void redo(int num) throws RedoException {
+
+
+		}
+
+		public void undo() throws UndoException {
+
+
+		}
+
+		public void undo(int num) throws UndoException {
+
+
+		}
+
+		public FeatureIndex createIndex(FeatureType featureType,
+				String attributeName, String indexName, Observer observer)
+				throws DataException {
+
+			return null;
+		}
+
+		public Object getMetadataID() {
+
+			return null;
+		}
+
+		public void delegate(DynObject dynObject) {
+
+
+		}
+
+		public DynClass getDynClass() {
+
+			return null;
+		}
+
+		public Object getDynValue(String name) throws DynFieldNotFoundException {
+
+			return null;
+		}
+
+		public boolean hasDynValue(String name) {
+
+			return false;
+		}
+
+		public void implement(DynClass dynClass) {
+
+
+		}
+
+		public Object invokeDynMethod(String name, DynObject context)
+				throws DynMethodException {
+
+			return null;
+		}
+
+		public Object invokeDynMethod(int code, DynObject context)
+				throws DynMethodException {
+
+			return null;
+		}
+
+		public void setDynValue(String name, Object value)
+				throws DynFieldNotFoundException {
+
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.gvsig.metadata.Metadata#getMetadataChildren()
+		 */
+		public Set getMetadataChildren() {
+
+			return null;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.gvsig.metadata.Metadata#getMetadataName()
+		 */
+		public String getMetadataName() {
+
+			return null;
+		}
+
+		public FeatureType getFeatureType(String featureTypeId)
+				throws DataException {
+
+			return null;
+		}
+
+		public DataQuery createQuery() {
+
+			return null;
+		}
+
+		public long getFeatureCount() throws DataException {
+
+			return 0;
+		}
+
+		public void accept(Visitor visitor, DataQuery dataQuery)
+				throws BaseException {
+		}
+
+		public void accept(Visitor visitor) throws BaseException {
+		}
+
+		public void createCache(String name,
+				DynObject parameters) throws DataException {
+			// Do nothing
+		}
+
+		public FeatureCache getCache() {
+			return null;
+		}
+
+		public void clear() {
+			// Nothing to do
+		}
+
+		public void export(DataServerExplorer explorer, String provider,
+				NewFeatureStoreParameters params) throws DataException {
+			// Nothing to do
+		}
+
+		public String getProviderName() {
+			return null;
+		}
+	}
+
+	 private static final FInterval interval0=new FInterval(0,2);
+	 private static final FInterval interval1=new FInterval(3,5);
+	 private static final FInterval interval2=new FInterval(6,8);
+	 private static final FInterval interval3=new FInterval(9,11);
+	// private static final Value interval4;
+	// private static final Value interval5;
+	// private static final Value interval6;
+	// private static final Value interval7;
+	// private static final Value interval8;
+	// private static final Value interval9;
+
+	Hashtable symTable;
+
+	private ISymbol[] symbols;
+	private FInterval[] sampleIntervals = new FInterval[] { interval0, interval1, interval2, interval3, };
+	private Feature[] features;
+
+	// private FInterval[] intervals = new FInterval[] {
+	// interval0,
+	// interval1,
+	// interval2,
+	// interval3,
+	// interval4,
+	// interval5,
+	// interval6,
+	// interval7,
+	// interval8,
+	// interval9,
+	// };
+
+	protected void doSetUp() throws Exception {
+		features = new Feature[4];
+
+		// initialize test values
+		for (int i = 0; i < features.length; i++) {
+
+			// create the geometry associated to the feature
+			int size = 200;
+			Dimension d = new Dimension(size, size);
+			Rectangle aShape = new Rectangle(i * size, i * size, d.width,
+					d.height);
+			GeometryManager geomManager = GeometryLocator.getGeometryManager();
+			Curve curve = (Curve)geomManager.create(TYPES.CURVE, SUBTYPES.GEOM2D);
+			curve.setGeneralPath(new GeneralPathX(aShape.getPathIterator(null)));
+
+			/*
+			 * create a full-featured Feature with randomed values at its fields
+			 * to avoid testing over the same values each time
+			 */
+			//TODO
+//			features[i] = new MemoryFeature(geom, featureValues[i], "[" + i
+//					+ "]");
+		}
+
+		// initialize the symbol subset for this test
+		TestISymbol.addSymbols();
+		symbols = TestISymbol.getNewSymbolInstances();
+
+		// initialize the legends for this test
+		ILegend[] allLegends = TestILegend.getNewLegendInstances();
+		ArrayList intervalLegends = new ArrayList();
+		for (int i = 0; i < allLegends.length; i++) {
+
+			if (allLegends[i] instanceof AbstractIntervalLegend) {
+				intervalLegends.add(allLegends[i]);
+			}
+
+			if (allLegends[i] instanceof IClassifiedVectorLegend) {
+				IClassifiedVectorLegend cvl = (IClassifiedVectorLegend) allLegends[i];
+				cvl.setClassifyingFieldNames(new String[] { fieldNames[FIELDID] });
+//				cvl.setFeatureStore(mockDataSource);
+
+			}
+		}
+
+		this.intervalLegends = (AbstractIntervalLegend[]) intervalLegends
+				.toArray(new AbstractIntervalLegend[intervalLegends.size()]);
+	}
+
+	/**
+	 * This method is used to add symbols to a legend.That is, it takes an array
+	 * of AbstractIntervalLegend which is empty and, using a second array
+	 * of FIntervals(values), the first one is filled.Also, a hash table is filled
+	 * using the array of FIntervals (it will be useful in some tests to check
+	 * that a symbol can be taken using a feature) .
+	 *
+	 * @param legend
+	 * @return
+	 */
+	private void fillClassifiedLegend(AbstractIntervalLegend legend,
+			FInterval[] values) {
+		// initialize the hash table
+		symTable = new Hashtable();
+
+		// to add symbols to the legend and the hash table
+		for (int j = 0; j < values.length; j++) {
+
+			ISymbol sym = symbols[j % symbols.length];
+			legend.addSymbol(values[j], sym);
+			symTable.put(values[j], sym);
+		}
+	}
+
+	/**
+	 * This test ensures that when a legend is filled, the number of symbols
+	 * added is correct. To do it, is checked that the number of symbols of a
+	 * legend is the same as the length of the array of example values that we
+	 * have.
+	 *
+	 * @throws ReadDriverException
+	 */
+	public void testICLAdittion() throws ReadException {
+
+		// Fills the legend
+		for (int i = 0; i < intervalLegends.length; i++) {
+			fillClassifiedLegend(intervalLegends[i], sampleIntervals);
+		}
+
+		for (int i = 0; i < intervalLegends.length; i++) {
+			assertEquals(intervalLegends[i].getClass().getName()
+					+ " fails with the comparation of the number of symbols",
+					intervalLegends[i].getSymbols().length,
+					sampleIntervals.length);
+		}
+
+	}
+
+	/**
+	 * This test ensures that the symbols that we have previously added to a
+	 * legend are accessible using its features.To do it, this test compares the
+	 * symbol taken from the legend with the symbol taken from the hashTable
+	 * (using the same feature).
+	 * @throws Exception 
+	 */
+	public void testICLCheckValueSymbols() throws Exception {
+
+		ISymbol tableSym =null;
+
+		// fills the legends
+		for (int i = 0; i < intervalLegends.length; i++) {
+			fillClassifiedLegend(intervalLegends[i], sampleIntervals);
+		}
+
+		for (int i = 0; i < intervalLegends.length; i++) {
+			// For each feature
+			for (int j = 0; j < features.length; j++) {
+				Feature myFeature = features[i];
+				// takes the value of the field that identifies the feature
+				Object val = myFeature.get(FIELDID);
+				// the last value is used to access to the hash table to obtain
+				// a symbol
+
+				if(interval0.isInInterval(val)) {
+					tableSym = (ISymbol) symTable.get(interval0);
+				} else if(interval1.isInInterval(val)) {
+					tableSym = (ISymbol) symTable.get(interval1);
+				} else if(interval2.isInInterval(val)) {
+					tableSym = (ISymbol) symTable.get(interval2);
+				} else if(interval3.isInInterval(val)) {
+					tableSym = (ISymbol) symTable.get(interval3);
+				}
+
+				AbstractIntervalLegend leg = intervalLegends[i];
+				// takes the symbol from a legend using the feature
+				ISymbol legendSym = leg.getSymbolByFeature(myFeature);
+				// compares that both symbols are the same
+				assertEquals(legendSym.getClass().getName()
+						+ " fails with the comparation of the class symbols",
+						legendSym, tableSym);
+			}
+		}
+	}
+
+}
+
+
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestILegend.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestILegend.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/legend/TestILegend.java	(revision 33580)
@@ -0,0 +1,240 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.legend;
+
+import java.awt.Color;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.gvsig.fmap.mapcontext.MapContextException;
+import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialIntervalLegend;
+import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.SingleSymbolLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.VectorialIntervalLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.VectorialUniqueValueLegend;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.SimpleFillSymbol;
+import org.gvsig.utils.XMLException;
+
+/**
+ * Integration test to ensure that the legends follow the rules that follow the
+ * managing of them by the application.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestILegend extends TestCase {
+	 private static ArrayList classesToTest;
+	 transient private ILegend[] legends;
+
+	 private static ArrayList getClassesToTest() throws MapContextException {
+	        if (classesToTest == null) {
+	            classesToTest = new ArrayList();
+
+	          TestILegend.addLegendToTest(VectorialIntervalLegend.class);
+	          TestILegend.addLegendToTest(VectorialUniqueValueLegend.class);
+	          TestILegend.addLegendToTest(SingleSymbolLegend.class);
+
+//	          TestILegend.addLegendToTest(QuantityByCategoryLegend.class);
+//	          TestILegend.addLegendToTest(DotDensityLegend.class);
+//	          TestILegend.addLegendToTest(ProportionalSymbolsLegend.class);
+//	          TestILegend.addLegendToTest(GraduatedSymbolLegend.class);
+
+
+	        }
+
+	        return classesToTest;
+	    }
+
+	 /**
+	  * This method fills the attributes of a legend.The purpose is to ensure that the new
+	  * legend is 'full' and ready to be used for a test.
+	  * @param le
+	  * @return
+	 * @throws MapContextException 
+	  */
+
+	 private static ILegend fillthelegend(ILegend le) throws MapContextException {
+
+		 SimpleFillSymbol mfs = new SimpleFillSymbol();
+		 mfs.setFillColor(Color.ORANGE.darker());
+		 mfs.setDescription("hola");
+		 mfs.setIsShapeVisible(true);
+		 String[] cad = new String[] {"Pepe","Juan"};
+
+		 if(le instanceof IVectorLegend) {
+			 IVectorLegend ssl=(IVectorLegend)le;
+			 ssl.setDefaultSymbol(mfs);
+		 }
+
+		 if(le instanceof IVectorialUniqueValueLegend) {
+			 IVectorialUniqueValueLegend ivuvl= (IVectorialUniqueValueLegend)le;
+			 ivuvl.setClassifyingFieldNames(cad);
+			 }
+
+		 if(le instanceof IVectorialIntervalLegend) {
+			 IVectorialIntervalLegend ivil=(IVectorialIntervalLegend)le;
+			 ivil.setClassifyingFieldNames(cad);
+			 }
+
+		 if(le instanceof IClassifiedVectorLegend) {
+			 IClassifiedVectorLegend icvl=(IClassifiedVectorLegend)le;
+			 icvl.setClassifyingFieldNames(cad);
+		 }
+
+
+
+		 return le;
+	 }
+
+
+	 public static void addLegendToTest(Class legendClass) throws MapContextException {
+	        try {
+	            ILegend len = (ILegend) legendClass.newInstance();
+	            fillthelegend(len);
+//	            len.getXMLEntity();
+
+	        } catch (InstantiationException e) {
+	            // TODO Auto-generated catch block
+	            fail("Instantiating class, cannot test a non-instantiable symbol");
+	        } catch (IllegalAccessException e) {
+	            // TODO Auto-generated catch block
+	            fail("Class not instantiable");
+	        } catch (ClassCastException ccEx) {
+	            fail("Cannot test a non symbol class");
+//	        } catch (XMLException e) {
+//	        	fail("Cannot test a non symbol class");
+			}
+	        getClassesToTest().add(legendClass);
+	    }
+
+	 /**
+	  * The main purpose of this method is to create new legend instances to be used for
+	  * other test methods.The new instances will be filled for the fillthelegend method.
+	  * @return
+	 * @throws MapContextException 
+	  * @throws FieldNotFoundException
+	  */
+	 public static ILegend[] getNewLegendInstances() throws MapContextException{
+	        ILegend[] legends = new ILegend[getClassesToTest().size()];
+	        for (int i = 0; i < legends.length; i++) {
+
+	            try {
+	            	legends[i] = (ILegend) ((Class) getClassesToTest().get(i)).newInstance();
+	            	fillthelegend(legends[i]);
+
+	            } catch (InstantiationException e) {
+	                fail("Instantiating class");
+	            } catch (IllegalAccessException e) {
+	                fail("Class not instantiable");
+	            }
+
+	        }
+	        return legends;
+	    }
+
+
+	  protected void setUp() throws Exception {
+	      legends = getNewLegendInstances();
+	    }
+
+	/**
+	 * this test ensures that the legend is self-defining. Checks that
+	 * the symbols contained by it can be replicated, and the rules for
+	 * such symbols as well.
+	 * @throws XMLException
+	 */
+	public void testILegendSelfDefinition() throws XMLException{
+		for (int i = 0; i < legends.length; i++) {
+			final ILegend theLegend = legends[i];
+			final ILegend cloneLegend =theLegend.cloneLegend();
+			assertTrue(theLegend.getClass().getName()+ " wrong class name declaration in getXMLEntity() ",
+					cloneLegend.getClass().equals(theLegend.getClass()));
+	        final Field[] theLegendFields = theLegend.getClass().getFields();
+            for (int j = 0; j < theLegendFields.length; j++) {
+                final Field fi = theLegendFields[j];
+                final boolean wasAccessible = fi.isAccessible();
+                fi.setAccessible(true);
+
+                try {
+                    assertTrue(theLegend.getClass().getName() + " fails or misses clonning the field " +fi.getName(),
+                            fi.get(theLegend).equals(fi.get(cloneLegend)));
+                } catch (IllegalArgumentException e) {
+                    fail();
+                } catch (IllegalAccessException e) {
+                    fail();
+                }
+                fi.setAccessible(wasAccessible);
+            }
+			}
+		}
+
+	/**
+	 * this test ensures that any legend always have a symbol ready to be used.
+	 * an empty legend is incorrect.
+	 * @throws Exception 
+	 *
+	 */
+	public void testSymbolAvailability() throws Exception {
+		for (int i = 0; i < legends.length; i++) {
+			assertNotNull("Legend no. "+i+" '"+legends[i].getClass().getName()+" does not have a symbol ready to be used", legends[i].getDefaultSymbol());
+		}
+
+		for (int i = 0; i < legends.length; i++) {
+
+			if (legends[i] instanceof IVectorLegend) {
+				IVectorLegend vectLegend = (IVectorLegend) legends[i];
+				try {
+					vectLegend.setDefaultSymbol(null);
+					fail("setDefaultSymbol(ISymbol) should not accept null values");
+				} catch (NullPointerException e) {
+					// correct
+				}
+			}
+
+		}
+	}
+
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/TestCartographicSupportForSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/TestCartographicSupportForSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/TestCartographicSupportForSymbol.java	(revision 33580)
@@ -0,0 +1,595 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering;
+
+import java.awt.Dimension;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Random;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.Envelope;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.MapContextLocator;
+import org.gvsig.fmap.mapcontext.ViewPort;
+import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.AbstractSymbolTestCase;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.SimpleFillSymbolTest;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.SimpleLineSymbolTest;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.SimpleMarkerSymbolTest;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.gvsig.utils.IPersistence;
+import org.gvsig.utils.NotExistInXMLEntity;
+import org.gvsig.utils.XMLEntity;
+import org.gvsig.utils.XMLException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestCartographicSupportForSymbol extends AbstractLibraryAutoInitTestCase {
+	private static GeometryManager geomManager;	
+	private static final Logger logger = LoggerFactory.getLogger(TestCartographicSupportForSymbol.class);
+	
+	/**
+	 * Geodesic vertex of the Micalet in Valencia (Spain) in <b>EPSG:23030</b>
+	 */
+	public static Point valenciaUTM30 = null;
+
+	/**
+	 * Geodesic vertex of the Micalet in Valencia (Spain) in <b>EPSG:4326</b>
+	 */
+	public static Point valenciaGeo = null;
+
+	public SymbolManager manager = MapContextLocator.getSymbolManager();
+	/**
+	 * Extent that covers the whole Comunitat Valenciana in  <b>EPSG:23030</b>
+	 */
+	public static final Rectangle2D TEST_UTM30_EXTENT = new Rectangle2D.Double();
+	{
+		TEST_UTM30_EXTENT.setFrameFromDiagonal(
+				4191037.369934333,
+				626674.7454557443,
+
+				4519266.460824658,
+				797903.2656794232
+		);
+	}
+	/**
+	 * Extent that covers the whole Comunitat Valenciana in  <b>EPSG:4326</b>
+	 */
+
+	public static final Rectangle2D TEST_GEO_EXTENT = new Rectangle2D.Double();
+	{
+		TEST_GEO_EXTENT.setFrameFromDiagonal(
+
+				-  (1 + (31/60) + (28.09/3600)),	// Western egde
+				37 + (50/60) + (48.05/3600),		// Southern edge
+
+				0 + (31/60) + (1.85/3600),		// Eastern edge
+				40 + (47/60) + (21.36/3600)		// Northern edge
+
+		);
+	}
+
+	public static final Rectangle2D TEST_EXTENT = new Rectangle2D.Double(
+			4191037.369934333,
+			626674.7454557443,
+
+			4519266.460824658 - 4191037.369934333,
+			797903.2656794232 -  626674.7454557443
+	);
+	private static ArrayList symbolsToTest; //<AbstractSymbolTestCase>
+	private ArrayList csSymbols; //<CartographicSupport>
+
+	/**
+	 * Acceptable pixel tolerance error. 1 pixel of error is accetable since it is probably due to
+	 * the java.awt.Graphics
+	 */
+	private static final double TOL = 1;
+
+	double zooms[] = new double[] {
+			1,
+			2,
+			1.2,
+			10,
+			0.5
+	};
+
+	protected void doSetUp() throws Exception {	
+		geomManager = GeometryLocator.getGeometryManager();
+		try {
+			valenciaUTM30 = geomManager.createPoint(725846.080, 4373022.720, SUBTYPES.GEOM2D);
+			valenciaGeo = geomManager.createPoint(- (0+ 22/60 +  27.919/3600), 39 + 28/60 + 35.4276/3600, SUBTYPES.GEOM2D);
+		} catch (CreateGeometryException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}		
+	
+		addSymbolTest(new SimpleFillSymbolTest());
+		addSymbolTest(new SimpleLineSymbolTest());
+		addSymbolTest(new SimpleMarkerSymbolTest());
+
+		init();
+	}
+
+	protected void init() {
+
+		// take the symbols added to the TestISymbol test
+		ISymbol[] symbols = getNewSymbolInstances();
+
+		csSymbols = new ArrayList(); //<CartographicSupport>
+		for (int i = 0; i < symbols.length; i++) {
+			if (symbols[i] instanceof CartographicSupport) {
+				csSymbols.add((CartographicSupport) symbols[i]);
+			}
+		}
+	}
+
+	public static void addSymbolTest(AbstractSymbolTestCase symbolTestClass) {
+		if (symbolsToTest == null) symbolsToTest = new ArrayList(); //<AbstractSymbolTestCase>
+		symbolsToTest.add(symbolTestClass);
+	}
+
+	public static ISymbol[] getNewSymbolInstances() {
+		ISymbol[] symbols = new ISymbol[symbolsToTest.size()];
+		for (int i = 0; i < symbols.length; i++) {
+			symbols[i] = (ISymbol)((AbstractSymbolTestCase)symbolsToTest.get(i)).newInstance();
+		}
+		return symbols;
+	}
+
+
+	public void testSymbolUnitDefinition() {
+		for (int i = 0; i < csSymbols.size(); i++) {
+			CartographicSupport symbol = (CartographicSupport)csSymbols.get(i);
+
+			int aRandomUnit = new Random().nextInt(7);
+
+
+			symbol.setUnit(aRandomUnit);
+			XMLEntity xml=null;
+			try {
+				xml = ((IPersistence) symbol).getXMLEntity();
+			} catch (XMLException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			String name = symbol.getClass().getName().substring(
+					symbol.getClass().getName().lastIndexOf('.')+1,
+					symbol.getClass().getName().length());
+
+			try {
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not declare units correctly",
+						symbol.getUnit() == xml.getIntProperty("unit"));
+			} catch (NotExistInXMLEntity neiXMLEx) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare field attribute in its XMLEntity");
+			}
+			symbol.setUnit(5);
+			try {
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not apply changes to symbol",symbol.getUnit()== 5);
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not declare units correctly",
+						5 == ((IPersistence) symbol).getXMLEntity().getIntProperty("unit"));
+			} catch (NotExistInXMLEntity neiXMLEx) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare field attribute in its XMLEntity");
+			} catch (XMLException e) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare field attribute in its XMLEntity");
+			}
+
+//			xml.putProperty("unit", 3);
+//			ISymbol ts = SymbologyFactory.createSymbolFromXML(xml, xml.getStringProperty("desc"));
+//			assertTrue("The application of the UNIT value to the XMLEntity didn't have any effect ("+name+")", ((CartographicSupport) ts).getUnit() == 3);
+		}
+
+	}
+
+
+	public void testSymbolReferenceSystemDefinition() {
+		for (int i = 0; i < csSymbols.size(); i++) {
+			CartographicSupport symbol = (CartographicSupport)csSymbols.get(i);
+			XMLEntity xml=null;
+			try {
+				xml = ((IPersistence) symbol).getXMLEntity();
+			} catch (XMLException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			String name = symbol.getClass().getName().substring(
+					symbol.getClass().getName().lastIndexOf('.')+1,
+					symbol.getClass().getName().length());
+			try {
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not declare units correctly",
+						symbol.getReferenceSystem() == xml.getIntProperty("referenceSystem"));
+			} catch (NotExistInXMLEntity neiXMLEx) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare referenceSystem field attribute in its XMLEntity");
+			}
+			symbol.setReferenceSystem(CartographicSupport.PAPER);
+			try {
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not apply changes to symbol",symbol.getReferenceSystem()== CartographicSupport.PAPER);
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not declare referenceSystem correctly",
+						CartographicSupport.PAPER == ((IPersistence) symbol).getXMLEntity().getIntProperty("referenceSystem"));
+			} catch (NotExistInXMLEntity neiXMLEx) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare referenceSystem field attribute in its XMLEntity ("+name+")");
+			} catch (XMLException e) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare referenceSystem field attribute in its XMLEntity ("+name+")");
+			}
+
+			symbol.setReferenceSystem(CartographicSupport.WORLD);
+			try {
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not apply changes to symbol",symbol.getReferenceSystem()== CartographicSupport.WORLD);
+				assertTrue( ((ISymbol) symbol).getClass().getName()+" does not declare referenceSystem correctly",
+						CartographicSupport.WORLD == ((IPersistence) symbol).getXMLEntity().getIntProperty("referenceSystem"));
+			} catch (NotExistInXMLEntity neiXMLEx) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare referenceSystem field attribute in its XMLEntity");
+			} catch (XMLException e) {
+				fail(((ISymbol) symbol).getClass().getName()+ " does not declare referenceSystem field attribute in its XMLEntity");
+			}
+
+//			xml.putProperty("referenceSystem", CartographicSupport.PAPER);
+//			ISymbol ts = SymbologyFactory.createSymbolFromXML(xml, xml.getStringProperty("desc"));
+//			assertTrue("The application of the REFERENCE SYSTEM value to the XMLEntity didn't have any effect ("+name+")", ((CartographicSupport) ts).getReferenceSystem() == CartographicSupport.PAPER);
+		}
+	}
+
+
+	public void testDegreesUnits_MapReferenceSystem() throws Exception {
+		for (int j = 0; j < csSymbols.size(); j++) {
+			CartographicSupport symbol = (CartographicSupport)csSymbols.get(j);
+
+			MapContext mc = AllTests.newMapContext(AllTests.TEST_DEFAULT_PROJECTION);
+			ViewPort viewPort = mc.getViewPort();
+
+			int unit = 8;
+			Dimension dim = new Dimension(600, 600);
+			viewPort.setImageSize(dim);
+
+
+			/*
+			 * will test with several extents but in the same map image size, so
+			 * the scale issue is exercised as well.
+			 */
+			for (int i = 0; i < zooms.length; i++) {
+				Envelope extent = geomManager.createEnvelope(-30, -30,dim.getWidth()/zooms[i]-30, dim.getHeight()/zooms[i]-30, SUBTYPES.GEOM2D);
+
+				viewPort.setMapUnits(unit);
+				viewPort.setEnvelope(extent);
+
+
+				String name = ((IPersistence) symbol).getClassName().substring(
+						((IPersistence) symbol).getClassName().lastIndexOf('.')+1,
+						((IPersistence) symbol).getClassName().length());
+
+				CartographicSupport csSym = (CartographicSupport) symbol;
+				csSym.setReferenceSystem(CartographicSupport.WORLD);
+				double size = 30;
+
+				csSym.setUnit(unit);
+
+
+
+				if (symbol instanceof IMarkerSymbol) {
+
+					IMarkerSymbol markerSym = (IMarkerSymbol) symbol;
+					markerSym.setSize(size);
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = markerSym.getSize();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+markerSym.getSize()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i],  Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof ILineSymbol) {
+
+					ILineSymbol lineSym = (ILineSymbol) symbol;
+					lineSym.setLineWidth(size);
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = lineSym.getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+mySize+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof IFillSymbol) {
+					// this tests if symbol applies the cartographic support to its
+					// outline, since is the only thing that may be resized
+					IFillSymbol fillSym = (IFillSymbol) symbol;
+					if (fillSym.getOutline() == null) {
+						fillSym.setOutline((ILineSymbol) manager.createSymbol(ILineSymbol.SYMBOL_NAME));
+					}
+
+					fillSym.getOutline().setLineWidth(size);
+
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = fillSym.getOutline().getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+fillSym.getOutline().getLineWidth()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+			}
+		}
+	}
+
+
+	public void testKilometersUnits_MapReferenceSystem() throws Exception {
+		for (int j = 0; j < csSymbols.size(); j++) {
+			CartographicSupport symbol = (CartographicSupport)csSymbols.get(j);
+			MapContext mc = AllTests.newMapContext(AllTests.TEST_DEFAULT_MERCATOR_PROJECTION);
+			ViewPort viewPort = mc.getViewPort();
+
+			int unit = 0;
+			Dimension dim = new Dimension(60, 60);
+			viewPort.setImageSize(dim);
+
+
+			/*
+			 * will test with several extents but in the same map image size, so
+			 * the scale issue is exercised as well.
+			 */
+			for (int i = 0; i < zooms.length; i++) {
+				Envelope extent = geomManager.createEnvelope(-30, -30, dim.getWidth()/zooms[i]-30, dim.getHeight()/zooms[i]-30, SUBTYPES.GEOM2D);
+
+				viewPort.setMapUnits(unit);
+				viewPort.setEnvelope(extent);
+
+
+				String name = ((IPersistence) symbol).getClassName().substring(
+						((IPersistence) symbol).getClassName().lastIndexOf('.')+1,
+						((IPersistence) symbol).getClassName().length());
+
+				CartographicSupport csSym = (CartographicSupport) symbol;
+				csSym.setReferenceSystem(CartographicSupport.WORLD);
+				double size = 30;
+
+				csSym.setUnit(unit);
+
+
+
+
+				if (symbol instanceof IMarkerSymbol) {
+
+					IMarkerSymbol markerSym = (IMarkerSymbol) symbol;
+					markerSym.setSize(size);
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = markerSym.getSize();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+markerSym.getSize()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i],  Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof ILineSymbol) {
+
+					ILineSymbol lineSym = (ILineSymbol) symbol;
+					lineSym.setLineWidth(size);
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D								
+							)
+					);
+					double mySize = lineSym.getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+lineSym.getLineWidth()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof IFillSymbol) {
+					// this tests if symbol applies the cartographic support to its
+					// outline, since is the only thing that may be resized
+					IFillSymbol fillSym = (IFillSymbol) symbol;
+					if (fillSym.getOutline() == null) {
+						fillSym.setOutline((ILineSymbol) manager.createSymbol(
+										ILineSymbol.SYMBOL_NAME));
+					}
+
+					fillSym.getOutline().setLineWidth(size);
+
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = fillSym.getOutline().getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+fillSym.getOutline().getLineWidth()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+			}
+		}
+
+	}
+
+	public void testMapInKilometersSymbolInMeters_MapReferenceSystem() throws Exception {
+		for (int j = 0; j < csSymbols.size(); j++) {
+			CartographicSupport symbol = (CartographicSupport)csSymbols.get(j);
+
+			MapContext mc = AllTests.newMapContext(AllTests.TEST_DEFAULT_MERCATOR_PROJECTION);
+			ViewPort viewPort = mc.getViewPort();
+
+			int mapUnit = 0;
+			int symbolUnit = 1;
+			Dimension dim = new Dimension(60, 60);
+			viewPort.setImageSize(dim);
+
+
+			/*
+			 * will test with several extents but in the same map image size, so
+			 * the scale issue is exercised as well.
+			 */
+			for (int i = 0; i < zooms.length; i++) {
+				Envelope extent = geomManager.createEnvelope(-30, -30, dim.getWidth()/zooms[i]-30, dim.getHeight()/zooms[i]-30, SUBTYPES.GEOM2D);
+				viewPort.setMapUnits(mapUnit);
+				viewPort.setEnvelope(extent);
+				double size = 30;
+
+
+				String name = ((IPersistence) symbol).getClassName().substring(
+						((IPersistence) symbol).getClassName().lastIndexOf('.')+1,
+						((IPersistence) symbol).getClassName().length());
+
+
+				CartographicSupport csSym = (CartographicSupport) symbol;
+				csSym.setReferenceSystem(CartographicSupport.WORLD);
+
+				csSym.setUnit(symbolUnit);
+
+				if (symbol instanceof IMarkerSymbol) {
+
+					IMarkerSymbol markerSym = (IMarkerSymbol) symbol;
+					markerSym.setSize(size*MapContext.CHANGEM[mapUnit]); // 30m*1000 = 30 km
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = markerSym.getSize();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+markerSym.getSize()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i],  Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof ILineSymbol) {
+
+					ILineSymbol lineSym = (ILineSymbol) symbol;
+					lineSym.setLineWidth(size*MapContext.CHANGEM[mapUnit]); // 30m*1000 = 30 km
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = lineSym.getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+lineSym.getLineWidth()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+				if (symbol instanceof IFillSymbol) {
+					// this tests if symbol applies the cartographic support to its
+					// outline, since is the only thing that may be resized
+					IFillSymbol fillSym = (IFillSymbol) symbol;
+					if (fillSym.getOutline() == null) {
+						fillSym.setOutline((ILineSymbol) manager.createSymbol(
+										ILineSymbol.SYMBOL_NAME));
+					}
+
+					fillSym.getOutline().setLineWidth(size*MapContext.CHANGEM[mapUnit]);
+
+					csSym.toCartographicSize(
+							viewPort,
+							CompatLocator.getGraphicsUtils().getScreenDPI(),
+							geomManager.createPoint(
+									viewPort.getAdjustedExtent().getCenter(0),
+									viewPort.getAdjustedExtent().getCenter(1),
+									SUBTYPES.GEOM2D
+							)
+					);
+					double mySize = fillSym.getOutline().getLineStyle().getLineWidth();
+					assertTrue("The Symbol '"+name+"' failed computing cartographic size. " +
+							"It returned "+fillSym.getOutline().getLineWidth()+" when expecting "+
+							size+"*"+zooms[i]+"="+size*zooms[i], Math.abs(mySize-size*zooms[i]) <= TOL );
+				}
+
+			}
+		}
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/IDrawFillSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/IDrawFillSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/IDrawFillSymbol.java	(revision 33580)
@@ -0,0 +1,11 @@
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+
+public interface IDrawFillSymbol {
+
+	IFillSymbol makeSymbolTransparent(IFillSymbol newSymbol);
+
+	boolean isSuitableFor(IFillSymbol newSymbol);
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleTextSymbolTest.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleTextSymbolTest.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleTextSymbolTest.java	(revision 33580)
@@ -0,0 +1,49 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl.SimpleTextSymbol;
+
+public class SimpleTextSymbolTest extends AbstractSymbolTestCase{
+	public SimpleTextSymbolTest() {
+		super(SimpleTextSymbol.class);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/AbstractSymbolTestCase.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/AbstractSymbolTestCase.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/AbstractSymbolTestCase.java	(revision 33580)
@@ -0,0 +1,63 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import junit.framework.TestCase;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+
+
+public abstract class AbstractSymbolTestCase extends TestCase {
+	protected Class symClazz;
+
+	public AbstractSymbolTestCase(Class symClazz) {
+		this.symClazz = symClazz;
+	}
+
+	public ISymbol newInstance() {
+		try {
+			return (ISymbol) symClazz.newInstance();
+		} catch (Exception e) {
+			fail("Failed installing symbol to test "+symClazz.getName());
+			return null;
+		}
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleFillSymbolTest.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleFillSymbolTest.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleFillSymbolTest.java	(revision 33580)
@@ -0,0 +1,49 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.SimpleFillSymbol;
+
+public class SimpleFillSymbolTest extends AbstractSymbolTestCase{
+	public SimpleFillSymbolTest() {
+		super(SimpleFillSymbol.class);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleLineSymbolTest.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleLineSymbolTest.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleLineSymbolTest.java	(revision 33580)
@@ -0,0 +1,49 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.SimpleLineSymbol;
+
+public class SimpleLineSymbolTest extends AbstractSymbolTestCase{
+	public SimpleLineSymbolTest() {
+		super(SimpleLineSymbol.class);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawFills.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawFills.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawFills.java	(revision 33580)
@@ -0,0 +1,243 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.imageio.ImageIO;
+
+import junit.framework.TestCase;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.MapContext;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.AllTests;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Integration test to test that Fill symbols always draw in the same
+ * place respecting size constraints.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestDrawFills extends AbstractLibraryAutoInitTestCase {
+	private GeometryManager geomManager;
+	private static final Logger logger = LoggerFactory.getLogger(TestDrawFills.class);
+	private final Dimension sz = new Dimension(400, 400);
+	private org.gvsig.fmap.geom.primitive.Point centerP = null;
+	private static final int OUTTER_TOLERANCE = 1;
+	private static final int INNER_TOLERANCE = 1;
+	private IFillSymbol[] symbols;
+	private IDrawFillSymbol[] drawFillSymbols;
+	private static ArrayList classesToTest;
+
+	private static final double sizes[] = new double[] {
+		200,
+		100,
+		50,
+		30,
+		16,
+		5,
+		3,
+		2,
+		// smaller sizes don't make any sense
+
+	};
+
+
+	private static ArrayList getClassesToTest() {
+		if (classesToTest == null) {
+			classesToTest = new ArrayList();
+//			TestDrawFills.addSymbolToTest(DrawLineFillSymbol.class);
+//			TestDrawFills.addSymbolToTest(DrawPictureFillSymbol.class);
+		}
+
+		return classesToTest;
+	}
+
+	public static void addSymbolToTest(Class symbolClass) {
+        try {
+            IDrawFillSymbol sym = (IDrawFillSymbol) symbolClass.newInstance();
+        } catch (InstantiationException e) {
+            // TODO Auto-generated catch block
+            fail("Instantiating class, cannot test a non-instantiable symbol");
+        } catch (IllegalAccessException e) {
+            // TODO Auto-generated catch block
+            fail("Class not instantiable");
+        } catch (ClassCastException ccEx) {
+            fail("Cannot test a non symbol class");
+        }
+        getClassesToTest().add(symbolClass);
+    }
+
+	protected void doSetUp() throws Exception {
+		geomManager = GeometryLocator.getGeometryManager();
+		centerP = geomManager.createPoint(sz.width/2, sz.height/2, SUBTYPES.GEOM2D);
+		
+		this.drawFillSymbols = new IDrawFillSymbol[getClassesToTest().size()];
+
+		for (int i = 0; i < drawFillSymbols.length; i++) {
+			drawFillSymbols[i] = (IDrawFillSymbol) ((Class) getClassesToTest().get(i)).newInstance();
+		}
+
+		TestISymbol.addSymbols();
+		ISymbol[] allSymbols = TestISymbol.getNewSymbolInstances();
+		// Filter the marker ones
+		ArrayList symbols = new ArrayList();
+
+		for (int i = 0; i < allSymbols.length; i++) {
+			if (allSymbols[i] instanceof IFillSymbol) {
+				IFillSymbol sym = (IFillSymbol) allSymbols[i];
+				symbols.add(sym);
+
+			}
+		}
+		this.symbols = (IFillSymbol[]) symbols.toArray(new IFillSymbol[symbols.size()]);
+
+
+
+	}
+
+	public void testDraw() {
+		MapContext mc = AllTests.newMapContext(AllTests.TEST_DEFAULT_MERCATOR_PROJECTION);
+
+	}
+
+
+	public final void testNullColorAvoidsFilling() throws CreateGeometryException {
+
+		for (int i = 0; i < symbols.length; i++) {
+
+			for (int s = 0; s < sizes.length; s++) {
+
+				BufferedImage bi = CompatLocator.getGraphicsUtils().createBufferedImage(sz.width,sz.height, BufferedImage.TYPE_INT_ARGB);
+				// the graphics for the image, so we can draw onto the buffered image
+				Graphics2D g = bi.createGraphics();
+
+				IFillSymbol newSymbol = symbols[i];
+				newSymbol.setFillColor(null);
+				newSymbol.setOutline(null);
+
+
+
+
+				String name = newSymbol.getClass().getName().substring(
+						newSymbol.getClass().getName().lastIndexOf('.')+1,
+						newSymbol.getClass().getName().length());
+
+
+				Point2D firstPoint = new Point2D.Float((float)(centerP.getX()-sizes[s]/2-3),(float)(centerP.getY()-sizes[s]/2-3));
+				Point2D lastPoint = new Point2D.Float((float)(centerP.getX()+sizes[s]/2+3),(float)(centerP.getY()+sizes[s]/2+3));
+
+
+
+				GeneralPathX gpx = new GeneralPathX();
+
+				gpx.moveTo((float)firstPoint.getX(),(float) firstPoint.getY());
+				gpx.lineTo((float)lastPoint.getX(),(float) firstPoint.getY());
+				gpx.lineTo((float)lastPoint.getX(),(float) lastPoint.getY());
+				gpx.lineTo((float)firstPoint.getX(),(float) lastPoint.getY());
+				gpx.lineTo((float)firstPoint.getX(), (float)firstPoint.getY());
+				gpx.closePath();
+
+
+				for (int j = 0; j < drawFillSymbols.length; j++) {
+					if (drawFillSymbols[j].isSuitableFor(newSymbol)) {
+						newSymbol = drawFillSymbols[j].makeSymbolTransparent(newSymbol);
+						break;
+					}
+				}
+
+
+				newSymbol.draw(g, new AffineTransform(), geomManager.createSurface(gpx, SUBTYPES.GEOM2D), null, null);
+
+				try {
+
+					File dstDir = new File (System.getProperty("java.io.tmpdir")+"/prova-imatges/");
+					if (!dstDir.exists()) dstDir.mkdir();
+					ImageIO.write(bi, "png",
+							new File(dstDir.getAbsoluteFile()+File.separator+
+									name+"_size_"+sizes[s]
+									                    +".png"));
+				} catch (IOException e) {
+					e.printStackTrace();
+					fail();
+				}
+
+				for (int j = 0; j < bi.getWidth(); j++) {
+					for (int k = 0; k < bi.getHeight(); k++) {
+						if (isInsideShape(geomManager.createSurface(gpx, SUBTYPES.GEOM2D), j, k)) {
+							assertEquals("Failed, the fill is being painted when the color is null",bi.getRGB(j, k),0);
+
+						}
+					}
+
+				}
+			}
+		}
+	}
+
+
+	private boolean isInsideShape(Geometry geom, int x, int y) {
+		Point2D p = new Point2D.Float(x,y);
+		if(geom.contains(p))return true;
+		return false;
+	}
+
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawLines.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawLines.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawLines.java	(revision 33580)
@@ -0,0 +1,215 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.Curve;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test to test that Line symbols always draw in the same
+ * place respecting size constraints.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestDrawLines extends AbstractLibraryAutoInitTestCase {
+	private GeometryManager geomManager;
+	private static final Logger logger = LoggerFactory.getLogger(TestDrawLines.class);
+	private ILineSymbol[] symbols;
+	private final Dimension sz = new Dimension(401, 401);
+	private Curve centerL;
+	
+	protected void doSetUp() throws Exception {
+		geomManager = GeometryLocator.getGeometryManager();
+
+		GeneralPathX gp = new GeneralPathX();
+		gp.moveTo(0, sz.height / 2 );
+		gp.lineTo(sz.width, sz.height /2 );
+
+		try {
+			centerL = geomManager.createCurve(gp, SUBTYPES.GEOM2D);
+		} catch (CreateGeometryException e) {
+			e.printStackTrace();
+		}
+
+		ISymbol[] allSymbols = TestISymbol.getNewSymbolInstances();
+		// Filter the marker ones
+		ArrayList symbols = new ArrayList();
+
+		for (int i = 0; i < allSymbols.length; i++) {
+			if (allSymbols[i] instanceof ILineSymbol) {
+				ILineSymbol sym = (ILineSymbol) allSymbols[i];
+				symbols.add(sym);
+
+			}
+		}
+		this.symbols = (ILineSymbol[]) symbols.toArray(new ILineSymbol[symbols.size()]);
+	}
+	private static final double sizes[] = new double[] {
+		300,
+		250,
+		225,
+		200,
+		100,
+		50,
+		30,
+		15,
+		5,
+		3,
+		2,
+		1,
+		// smaller sizes don't make any sense
+	};
+
+	private static final float INNER_TOLERANCE = 1F;
+	private static final float OUTTER_TOLERANCE = 1F;
+
+	public void testDrawingSize() {
+		for (int i = 0; i < symbols.length; i++) {
+			for (int j = 0; j < sizes.length; j++) {
+				// new blank buffered image
+				
+				BufferedImage bi = CompatLocator.getGraphicsUtils().createBufferedImage(sz.width, sz.height, BufferedImage.TYPE_INT_ARGB);
+
+				// the graphics for the image, so we can draw onto the buffered image
+				Graphics2D g = bi.createGraphics();
+
+				ILineSymbol testSymbol = symbols[i];
+				testSymbol.setLineColor(Color.YELLOW);
+				testSymbol.setLineWidth(sizes[j]);
+				String name = testSymbol.getClass().getName().substring(
+						testSymbol.getClass().getName().lastIndexOf('.')+1,
+						testSymbol.getClass().getName().length());
+
+				Point2D upperP1 = new Point2D.Double(0, centerL.getBounds().getY() - sizes[j]*0.5);
+				Point2D upperP2 = new Point2D.Double(centerL.getBounds().getWidth(), centerL.getBounds().getY() - sizes[j]*0.5);
+				GeneralPathX gpUp = new GeneralPathX();
+				gpUp.moveTo(upperP1.getX(), upperP1.getY());
+				gpUp.lineTo(upperP2.getX(), upperP2.getY());
+
+
+				GeneralPathX gpDown = new GeneralPathX();
+				Point2D lowerP1 = new Point2D.Double(0, centerL.getBounds().getY() + sizes[j]*0.5);
+				Point2D lowerP2 = new Point2D.Double(centerL.getBounds().getWidth(), centerL.getBounds().getY() + sizes[j]*0.5);
+				gpDown.moveTo(lowerP1.getX(), lowerP1.getY());
+				gpDown.lineTo(lowerP2.getX(), lowerP2.getY());
+
+
+				testSymbol.draw(g, new AffineTransform(), centerL, null, null);
+
+				/// per a borrar
+//				g.setStroke(new BasicStroke());
+//				g.setColor(Color.RED);
+//
+//				g.draw(gpUp);
+//
+//				g.setColor(Color.BLUE);
+//				g.draw(gpDown);
+//
+//				try {
+//
+//					File dstDir = new File (System.getProperty("java.io.tmpdir")+"/prova-imatges/");
+//					if (!dstDir.exists()) dstDir.mkdir();
+//				ImageIO.write(bi, "png",
+//						new File(dstDir.getAbsoluteFile()+File.separator+
+//									name+"_size_"+sizes[j]
+//									                    +".png"));
+//				} catch (IOException e) {
+//					e.printStackTrace();
+//					fail();
+//				}
+				/// fi per a borrar
+				assertFalse("fails sizing line, too big ("+name+", "+sizes[j]+"px)", isOutsideRect(bi, upperP1, lowerP1, OUTTER_TOLERANCE ));
+				assertTrue("fails sizing line, too small ("+name+", "+sizes[j]+"px) \n" +
+						"\t - forgot to enable ANTIALIASING?", fitsInsideRect(bi, upperP1, lowerP1, INNER_TOLERANCE));
+
+			}
+		}
+	}
+
+	private boolean isOutsideRect(BufferedImage bi, Point2D upper, Point2D lower, float outterTolerance) {
+		for (int i = 0; i < bi.getWidth(); i++) {
+			for (int j = 0; j < bi.getHeight(); j++) {
+				if (j<upper.getY()-outterTolerance && j>lower.getY()+outterTolerance)
+					if (bi.getRGB(i,j) != 0) {
+						System.out.println("too big In pixel ("+i+", "+j+")");
+						return true;
+					}
+
+			}
+		}
+		return false;
+	}
+
+	private boolean fitsInsideRect(BufferedImage bi,Point2D upper, Point2D lower , float innerTolerance) {
+		for (int i = 0; i < bi.getWidth(); i++) {
+			for (int j = 0; j < bi.getHeight(); j++) {
+				if (j<upper.getY()+innerTolerance && j>lower.getY()-innerTolerance)
+					if (bi.getRGB(i,j) == 0) {
+						System.out.println("does not fit big In pixel ("+i+", "+j+")");
+						return false;
+					}
+
+			}
+		}
+		return true;
+	}
+
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestMultiLayerSymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestMultiLayerSymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestMultiLayerSymbol.java	(revision 33580)
@@ -0,0 +1,422 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.MultiLayerFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.SimpleFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.MultiLayerLineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.SimpleLineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.MultiLayerMarkerSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.SimpleMarkerSymbol;
+
+/**
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestMultiLayerSymbol extends TestCase {
+	ISymbol[] symbols;
+
+	public void setUp() {
+		symbols = TestISymbol.getNewSymbolInstances();
+	}
+
+	public void testLayerTypeAdditionFor_MARKERS() {
+		MultiLayerMarkerSymbol multiLayer = new MultiLayerMarkerSymbol();
+		for (int i = 0; i < symbols.length; i++) {
+			if (symbols[i] instanceof IMarkerSymbol) {
+				try {
+				IMarkerSymbol marker = (IMarkerSymbol) symbols[i];
+				multiLayer.addLayer(marker);
+				} catch (Exception e) {
+					fail("MultiLayerMarkerSymbol failed adding a '"+symbols[i].getClass().getName());
+				}
+			} else {
+				try {
+					multiLayer.addLayer(symbols[i]);
+					fail("MultiLayerMarkerSymbol should not accept '"+symbols[i].getClass().getName()+"' symbols");
+				} catch (ClassCastException ccEx){
+					// this is right
+				}
+			}
+		}
+	}
+
+	public void testLayerTypeAdditionFor_LINES() {
+		MultiLayerLineSymbol multiLayer = new MultiLayerLineSymbol();
+		for (int i = 0; i < symbols.length; i++) {
+			if (symbols[i] instanceof ILineSymbol) {
+				try {
+				ILineSymbol line = (ILineSymbol) symbols[i];
+				multiLayer.addLayer(line);
+				} catch (Exception e) {
+					fail("MultiLayerLineSymbol failed adding a '"+symbols[i].getClass().getName());
+				}
+			} else {
+				try {
+					multiLayer.addLayer(symbols[i]);
+					fail("MultiLayerLineSymbol should not accept '"+symbols[i].getClass().getName()+"' symbols");
+				} catch (ClassCastException ccEx){
+					// this is right
+				}
+			}
+		}
+	}
+
+	public void testLayerTypeAdditionFor_FILL() {
+		MultiLayerFillSymbol multiLayer = new MultiLayerFillSymbol();
+		for (int i = 0; i < symbols.length; i++) {
+			if (symbols[i] instanceof IFillSymbol) {
+				try {
+					IFillSymbol fill = (IFillSymbol) symbols[i];
+				multiLayer.addLayer(fill);
+				} catch (Exception e) {
+					fail("MultiLayerLineSymbol failed adding a '"+symbols[i].getClass().getName());
+				}
+			} else {
+				try {
+					multiLayer.addLayer(symbols[i]);
+					fail("MultiLayerLineSymbol should not accept '"+symbols[i].getClass().getName()+"' symbols");
+				} catch (ClassCastException ccEx){
+					// this is right
+				}
+			}
+		}
+	}
+
+	public void testLayerAdditionPositionConsistencyMultiLayer_MARKER_Symbol() {
+		MultiLayerMarkerSymbol multiLayer = new MultiLayerMarkerSymbol();
+		IMarkerSymbol sym1 = new SimpleMarkerSymbol();
+		IMarkerSymbol sym2 = new SimpleMarkerSymbol();
+		sym1.setDescription("sym1");
+		sym2.setDescription("sym2");
+		try {
+			multiLayer.addLayer(sym1, 0);
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should always accept adding at index 0, even when it is empty");
+		}
+
+		try {
+			multiLayer.addLayer(sym2, 3);
+			fail("MultiLayer cannot accept adding at an index larger than the amount of layers already contained");
+		} catch (IndexOutOfBoundsException ioobEx){
+			// this is right
+		}
+
+		try {
+			multiLayer.addLayer(sym1, multiLayer.getLayerCount());
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should accept adding at index less or equal to the layer count");
+		}
+
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(1).getDescription().equals("sym2"));
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(0).getDescription().equals("sym1"));
+	}
+
+	public void testLayerAdditionPositionConsistencyMultiLayer_LINE_Symbol() {
+		MultiLayerLineSymbol multiLayer = new MultiLayerLineSymbol();
+		ILineSymbol layer1 = new SimpleLineSymbol();
+		ILineSymbol layer2 = new SimpleLineSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+
+		try {
+			multiLayer.addLayer(layer1, 0);
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should always accept adding at index 0, even when it is empty");
+		}
+
+		try {
+			multiLayer.addLayer(layer2, 3);
+			fail("MultiLayer cannot accept adding at an index larger than the amount of layers already contained");
+		} catch (IndexOutOfBoundsException ioobEx){
+			// this is right
+		}
+
+		try {
+			multiLayer.addLayer(layer2, multiLayer.getLayerCount());
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should accept adding at index less or equal to the layer count");
+		}
+
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(1).getDescription().equals("layer2"));
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(0).getDescription().equals("layer1"));
+	}
+
+	public void testLayerAdditionPositionConsistencyMultiLayer_FILL_Symbol() {
+		MultiLayerFillSymbol multiLayer = new MultiLayerFillSymbol();
+		IFillSymbol layer1 = new SimpleFillSymbol();
+		IFillSymbol layer2 = new SimpleFillSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+
+		try {
+			multiLayer.addLayer(layer1, 0);
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should always accept adding at index 0, even when it is empty");
+		}
+
+		try {
+			multiLayer.addLayer(layer2, 3);
+			fail("MultiLayer cannot accept adding at an index larger than the amount of layers already contained");
+		} catch (IndexOutOfBoundsException ioobEx){
+			// this is right
+		}
+
+		try {
+			multiLayer.addLayer(layer2, multiLayer.getLayerCount());
+		} catch (IndexOutOfBoundsException ioobEx) {
+			fail("MultiLayer should accept adding at index less or equal to the layer count");
+		}
+
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(1).getDescription().equals("layer2"));
+		assertTrue("layer returned does not correspond with the index provided", multiLayer.getLayer(0).getDescription().equals("layer1"));
+	}
+
+	public void testMultiLayer_MARKER_SymbolLayerSwapping() {
+		MultiLayerMarkerSymbol multiLayer = new MultiLayerMarkerSymbol();
+		IMarkerSymbol layer1 = new SimpleMarkerSymbol();
+		IMarkerSymbol layer2 = new SimpleMarkerSymbol();
+		IMarkerSymbol layer3 = new SimpleMarkerSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+
+		multiLayer.swapLayers(1,0);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(0).getDescription().equals("layer2")
+				&& multiLayer.getLayer(1).getDescription().equals("layer1"));
+
+		multiLayer.swapLayers(1,2);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(2).getDescription().equals("layer1")
+				&& multiLayer.getLayer(1).getDescription().equals("layer3"));
+
+		Random random = new Random(System.currentTimeMillis());
+		int numTries = 50;
+		for (int i = 0; i < numTries; i++) {
+			int n = random.nextInt(multiLayer.getLayerCount());
+			int m = random.nextInt(multiLayer.getLayerCount());
+
+			ISymbol aLayer = multiLayer.getLayer(n);
+			multiLayer.swapLayers(n, m);
+			ISymbol otherLayer = multiLayer.getLayer(m);
+			assertEquals("failed swapping layers "+n+" and "+m, aLayer, otherLayer);
+		}
+
+	}
+
+	public void testMultiLayer_LINE_SymbolLayerSwapping() {
+		MultiLayerLineSymbol multiLayer = new MultiLayerLineSymbol();
+		ILineSymbol layer1 = new SimpleLineSymbol();
+		ILineSymbol layer2 = new SimpleLineSymbol();
+		ILineSymbol layer3 = new SimpleLineSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+
+		multiLayer.swapLayers(1,0);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(0).getDescription().equals("layer2")
+				&& multiLayer.getLayer(1).getDescription().equals("layer1"));
+
+		multiLayer.swapLayers(1,2);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(2).getDescription().equals("layer1")
+				&& multiLayer.getLayer(1).getDescription().equals("layer3"));
+
+		Random random = new Random(System.currentTimeMillis());
+		int numTries = 50;
+		for (int i = 0; i < numTries; i++) {
+			int n = random.nextInt(multiLayer.getLayerCount());
+			int m = random.nextInt(multiLayer.getLayerCount());
+
+			ISymbol aLayer = multiLayer.getLayer(n);
+			multiLayer.swapLayers(n, m);
+			ISymbol otherLayer = multiLayer.getLayer(m);
+			assertEquals("failed swapping layers "+n+" and "+m, aLayer, otherLayer);
+		}
+
+	}
+
+	public void testMultiLayer_FILL_SymbolLayerSwapping() {
+		MultiLayerFillSymbol multiLayer = new MultiLayerFillSymbol();
+		IFillSymbol layer1 = new SimpleFillSymbol();
+		IFillSymbol layer2 = new SimpleFillSymbol();
+		IFillSymbol layer3 = new SimpleFillSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+
+		multiLayer.swapLayers(1,0);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(0).getDescription().equals("layer2")
+				&& multiLayer.getLayer(1).getDescription().equals("layer1"));
+
+		multiLayer.swapLayers(1,2);
+		assertTrue("failed swapping layers 0 and 1",
+				   multiLayer.getLayer(2).getDescription().equals("layer1")
+				&& multiLayer.getLayer(1).getDescription().equals("layer3"));
+
+		Random random = new Random(System.currentTimeMillis());
+		int numTries = 50;
+		for (int i = 0; i < numTries; i++) {
+			int n = random.nextInt(multiLayer.getLayerCount());
+			int m = random.nextInt(multiLayer.getLayerCount());
+
+			ISymbol aLayer = multiLayer.getLayer(n);
+			multiLayer.swapLayers(n, m);
+			ISymbol otherLayer = multiLayer.getLayer(m);
+			assertEquals("failed swapping layers "+n+" and "+m, aLayer, otherLayer);
+		}
+	}
+
+	public void testMultiLayer_MARKER_IndexOutOfBounds() {
+		MultiLayerMarkerSymbol multiLayer = new MultiLayerMarkerSymbol();
+		IMarkerSymbol layer1 = new SimpleMarkerSymbol();
+		IMarkerSymbol layer2 = new SimpleMarkerSymbol();
+		IMarkerSymbol layer3 = new SimpleMarkerSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+
+		for (int i = -4; i < multiLayer.getLayerCount()+4; i++) {
+			if (i<0 || i>=multiLayer.getLayerCount()) {
+				try {
+					multiLayer.getLayer(i);
+					fail("MultiLayerMarkerSymbol should throw an IndexOutOfBoundsException when accessing a layer at index "+i+", because layer count is "+multiLayer.getLayerCount());
+				} catch (IndexOutOfBoundsException ioobEx) {
+					// this is correct;
+				}
+			} else {
+				try {
+					multiLayer.getLayer(i);
+				} catch (IndexOutOfBoundsException ioobEx) {
+					fail("MultiLayerMarkerSymbol threw an IndexOutOfBoundsException, but it has "+multiLayer.getLayerCount()+" layers");
+				}
+			}
+		}
+	}
+
+	public void testMultiLayer_LINE_IndexOutOfBounds() {
+		MultiLayerLineSymbol multiLayer = new MultiLayerLineSymbol();
+		ILineSymbol layer1 = new SimpleLineSymbol();
+		ILineSymbol layer2 = new SimpleLineSymbol();
+		ILineSymbol layer3 = new SimpleLineSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+
+		for (int i = -4; i < multiLayer.getLayerCount()+4; i++) {
+			if (i<0 || i>=multiLayer.getLayerCount()) {
+				try {
+					multiLayer.getLayer(i);
+					fail("MultiLayerLineSymbol should throw an IndexOutOfBoundsException when accessing a layer at index "+i+", because layer count is "+multiLayer.getLayerCount());
+				} catch (IndexOutOfBoundsException ioobEx) {
+					// this is correct;
+				}
+			} else {
+				try {
+					multiLayer.getLayer(i);
+				} catch (IndexOutOfBoundsException ioobEx) {
+					fail("MultiLayerLineSymbol threw an IndexOutOfBoundsException, but it has "+multiLayer.getLayerCount()+" layers");
+				}
+			}
+		}
+	}
+
+	public void testMultiLayer_FILL_IndexOutOfBounds() {
+		MultiLayerFillSymbol multiLayer = new MultiLayerFillSymbol();
+		IFillSymbol layer1 = new SimpleFillSymbol();
+		IFillSymbol layer2 = new SimpleFillSymbol();
+		IFillSymbol layer3 = new SimpleFillSymbol();
+		layer1.setDescription("layer1");
+		layer2.setDescription("layer2");
+		layer3.setDescription("layer3");
+
+		multiLayer.addLayer(layer1);
+		multiLayer.addLayer(layer2);
+		multiLayer.addLayer(layer3);
+		for (int i = -4; i < multiLayer.getLayerCount()+4; i++) {
+			if (i<0 || i>=multiLayer.getLayerCount()) {
+				try {
+					multiLayer.getLayer(i);
+					fail("MultiLayerFillSymbol should throw an IndexOutOfBoundsException when accessing a layer at index "+i+", because layer count is "+multiLayer.getLayerCount());
+				} catch (IndexOutOfBoundsException ioobEx) {
+					// this is correct;
+				}
+			} else {
+				try {
+					multiLayer.getLayer(i);
+				} catch (IndexOutOfBoundsException ioobEx) {
+					fail("MultiLayerFillSymbol threw an IndexOutOfBoundsException, but it has "+multiLayer.getLayerCount()+" layers");
+				}
+			}
+		}
+
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestISymbol.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestISymbol.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestISymbol.java	(revision 33580)
@@ -0,0 +1,342 @@
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import java.awt.Color;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Random;
+
+import junit.framework.TestSuite;
+
+import org.gvsig.fmap.geom.Geometry;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.geom.Geometry.TYPES;
+import org.gvsig.fmap.geom.exception.CreateGeometryException;
+import org.gvsig.fmap.geom.primitive.Curve;
+import org.gvsig.fmap.geom.primitive.GeneralPathX;
+import org.gvsig.fmap.geom.primitive.Point;
+import org.gvsig.fmap.geom.primitive.Surface;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+
+/**
+ * Integration test to ensure that the symbols follow the rules that follow the
+ * managing of them by the application.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+
+
+public class TestISymbol extends AbstractLibraryAutoInitTestCase {
+    private static ArrayList classesToTest;//<AbstractSymbolTestCase>
+    transient private ISymbol[] symbols;
+
+    public static TestSuite suite() {
+    	TestSuite suite = new TestSuite("Integration test for com.iver.cit.gvsig.fmap.core.ISymbol");
+        suite.addTestSuite(TestISymbol.class);
+        suite.addTestSuite(TestDrawMarkers.class);
+        suite.addTestSuite(TestDrawLines.class);
+        suite.addTestSuite(TestDrawFills.class);
+
+        return suite;
+    }
+
+    protected void doSetUp() throws Exception {
+    	addSymbols();
+    	symbols = getNewSymbolInstances();
+    }
+    
+    public static void addSymbols() {    	
+    	addSymbolTest(new SimpleFillSymbolTest());
+    	addSymbolTest(new SimpleLineSymbolTest());
+    	addSymbolTest(new SimpleMarkerSymbolTest());
+    	addSymbolTest(new SimpleTextSymbolTest());
+    }
+    
+
+    public static void addSymbolTest(AbstractSymbolTestCase symbolTestClass) {
+    	if (classesToTest == null) classesToTest = new ArrayList(); //<AbstractSymbolTestCase>
+
+    	classesToTest.add(symbolTestClass);
+    }
+
+    public static ISymbol[] getNewSymbolInstances() {
+        ISymbol[] symbols = new ISymbol[classesToTest.size()];
+        for (int i = 0; i < symbols.length; i++) {
+        	symbols[i] = (ISymbol)((AbstractSymbolTestCase)classesToTest.get(i)).newInstance();
+        }
+        return symbols;
+    }
+
+    public void testPointSuitability() throws InstantiationException, IllegalAccessException, CreateGeometryException {
+    	GeometryManager geomManager = GeometryLocator.getGeometryManager();
+    	Point point = (Point)geomManager.create(TYPES.POINT, SUBTYPES.GEOM2D);
+    	final Geometry dummyPointGeom = point;
+        for (int i = 0; i < symbols.length; i++) {
+            // text symbols are suitable for everything
+            if (symbols[i] instanceof ITextSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyPointGeom,
+                        symbols[i].isSuitableFor(dummyPointGeom));
+            } else
+
+            // marker symbols are suitable for points
+            if (symbols[i] instanceof IMarkerSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyPointGeom,
+                        symbols[i].isSuitableFor(dummyPointGeom));
+            } else {
+                assertFalse(symbols[i].getClass().getName()+" should NOT be suitable for "+dummyPointGeom,
+                        symbols[i].isSuitableFor(dummyPointGeom));
+            }
+        }
+    }
+
+    public void testLineSuitability() throws InstantiationException, IllegalAccessException, CreateGeometryException {
+    	GeometryManager geomManager = GeometryLocator.getGeometryManager();
+    	Curve curve = (Curve)geomManager.create(TYPES.CURVE, SUBTYPES.GEOM2D);
+		curve.setGeneralPath(new GeneralPathX());
+    	final Geometry dummyLineGeom = curve;
+        for (int i = 0; i < symbols.length; i++) {
+            // text symbols are suitable for everything
+            if (symbols[i] instanceof ITextSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyLineGeom,
+                        symbols[i].isSuitableFor(dummyLineGeom));
+            } else
+
+            // line symbols are suitable for line
+            if (symbols[i] instanceof ILineSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyLineGeom,
+                        symbols[i].isSuitableFor(dummyLineGeom));
+            } else {
+                assertFalse(symbols[i].getClass().getName()+" should NOT be suitable for "+dummyLineGeom,
+                        symbols[i].isSuitableFor(dummyLineGeom));
+            }
+        }
+    }
+
+    public void testPolygonSuitability() throws InstantiationException, IllegalAccessException, CreateGeometryException {
+    	GeometryManager geomManager = GeometryLocator.getGeometryManager();
+    	Surface surface = (Surface)geomManager.create(TYPES.SURFACE, SUBTYPES.GEOM2D);
+    	surface.setGeneralPath(new GeneralPathX());
+        final Geometry dummyPolygonGeom = surface;
+        for (int i = 0; i < symbols.length; i++) {
+
+            // text symbols are suitable for everything
+            if (symbols[i] instanceof ITextSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyPolygonGeom,
+                        symbols[i].isSuitableFor(dummyPolygonGeom));
+            } else
+
+            // fill symbols are suitable for polygons
+            if (symbols[i] instanceof IFillSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+dummyPolygonGeom,
+                        symbols[i].isSuitableFor(dummyPolygonGeom));
+            } else {
+                assertFalse(symbols[i].getClass().getName()+" should NOT be suitable for "+dummyPolygonGeom,
+                        symbols[i].isSuitableFor(dummyPolygonGeom));
+            }
+        }
+    }
+
+    /**
+     * tests whether the symbols were correctly configured to work with
+     * different kinds of shapes.
+     */
+    public void testGeneralSuitability() {
+
+        for (int i = 0; i < symbols.length; i++) {
+            // text symbols are suitable for everything
+            if (symbols[i] instanceof ITextSymbol) {
+                assertTrue(symbols[i].getClass().getName()+" should be suitable for "+null,
+                        symbols[i].isSuitableFor(null));
+            } else {
+                try {
+                    symbols[i].isSuitableFor(null);
+                    fail("Exception was not thrown");
+
+                } catch (NullPointerException npEx) {
+                    // this is correct!
+                }
+            }
+        }
+    }
+
+    /**
+     * ensures that symbols defined which can of FShape is the symbol
+     */
+    public void testSymbolTypeDefinition() {
+        for (int i = 0; i < symbols.length; i++) {
+            assertFalse("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"'",
+                        symbols[i].getSymbolType() == 0);
+
+        }
+    }
+
+    /**
+     * ensures that any symbol that is suitable for markers declares its type
+     * as FShape.POINT or FShape.MULTI
+     *
+     */
+    public void testMarkerSymbolTypeDefinition() {
+        for (int i = 0; i < symbols.length; i++) {
+            if (symbols[i] instanceof IMarkerSymbol) {
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"'",
+                        symbols[i].getSymbolType() == Geometry.TYPES.POINT
+                        || symbols[i].getSymbolType() == Geometry.TYPES.GEOMETRY);
+            }
+        }
+    }
+
+    /**
+     * ensures that any symbol that is suitable for lines declares its type
+     * as FShape.LINE or FShape.MULTI
+     *
+     */
+    public void testLineSymbolTypeDefinition() {
+        for (int i = 0; i < symbols.length; i++) {
+            if (symbols[i] instanceof ILineSymbol) {
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"'",
+                        symbols[i].getSymbolType() == Geometry.TYPES.CURVE
+                        || symbols[i].getSymbolType() == Geometry.TYPES.GEOMETRY);
+            }
+        }
+    }
+
+    /**
+     * ensures that any symbol that is suitable for fills declares its type
+     * as POLYGON or Geometry.TYPES.GEOMETRY
+     *
+     */
+    public void testFillSymbolTypeDefinition() {
+        for (int i = 0; i < symbols.length; i++) {
+            if (symbols[i] instanceof IFillSymbol) {
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"'",
+                        symbols[i].getSymbolType() == Geometry.TYPES.SURFACE
+                        || symbols[i].getSymbolType() == Geometry.TYPES.GEOMETRY);
+            }
+        }
+    }
+
+//    /**
+//     * ensures that any symbol has a description in its persistence
+//     * (very important)
+//     */
+//    public void testDescription() {
+//        for (int i = 0; i < symbols.length; i++) {
+//            try {
+//				assertTrue(symbols[i].getClass().getName() + " does not declare a description in its XMLEntity",
+//				        symbols[i].getXMLEntity().contains("desc"));
+//			} catch (XMLException e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+//        }
+//    }
+
+//    /**
+//     * ensures that any symbol has an isShapeVisible field in its persistence
+//     * (very important)
+//     */
+//    public void testIsShapeVisible() {
+//        for (int i = 0; i < symbols.length; i++) {
+//            try {
+//				assertTrue(symbols[i].getClass().getName() + " does not declare the isShapeVisible field in its XMLEntity",
+//				        symbols[i].getXMLEntity().contains("isShapeVisible"));
+//			} catch (XMLException e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+//        }
+//    }
+
+    /**
+     * ensures that the symbol is self-defining
+     * @throws Exception 
+     */
+    public void testSymbolSelfDefinition() throws Exception {
+        for (int i = 0; i < symbols.length; i++) {
+            final ISymbol theSymbol = symbols[i];
+            ISymbol cloneSymbol= (ISymbol) theSymbol.clone();
+				//cloneSymbol = SymbologyFactory.createSymbolFromXML(theSymbol.getXMLEntity(), null);
+            
+            assertTrue(theSymbol.getClass().getName()+ " wrong class name declaration in getXMLEntity() ",
+                    cloneSymbol.getClass().equals(theSymbol.getClass()));
+            final Field[] theSymbolFields = theSymbol.getClass().getFields();
+            for (int j = 0; j < theSymbolFields.length; j++) {
+                final Field fi = theSymbolFields[j];
+                final boolean wasAccessible = fi.isAccessible();
+                fi.setAccessible(true);
+
+                try {
+                    assertTrue(theSymbol.getClass().getName() + " fails or misses clonning the field " +fi.getName(),
+                            fi.get(theSymbol).equals(fi.get(cloneSymbol)));
+                } catch (IllegalArgumentException e) {
+                    fail();
+                } catch (IllegalAccessException e) {
+                    fail();
+                }
+                fi.setAccessible(wasAccessible);
+            }
+        }
+    }
+
+    /**
+     * Check one pixel acceleration consistency. Checks that the color returned
+     * in RGB matches the color of the symbol set.
+     *
+     */
+    public void testOnePointRGB() {
+    	Random random = new Random(System.currentTimeMillis());
+
+        for (int i = 0; i < symbols.length; i++) {
+            if (symbols[i] instanceof IMarkerSymbol) {
+                IMarkerSymbol marker = (IMarkerSymbol) symbols[i];
+                marker.setColor(new Color(random.nextInt()>>8));
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"' RGB value mismatch for getOnePointRBG() and getColor().getRGB()",
+                        symbols[i].getOnePointRgb() == marker.getColor().getRGB());
+
+            }
+
+            if (symbols[i] instanceof ILineSymbol) {
+                ILineSymbol line = (ILineSymbol) symbols[i];
+                line.setLineColor(new Color(random.nextInt()>>8));
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"' RGB value mismatch for getOnePointRBG() and getColor().getRGB()",
+                        symbols[i].getOnePointRgb() == line.getColor().getRGB());
+            }
+
+            if (symbols[i] instanceof IFillSymbol) {
+                IFillSymbol fill = (IFillSymbol) symbols[i];
+                boolean outlined = fill.getOutline() != null;
+                if (!outlined)
+                	fill.setFillColor(new Color(random.nextInt()>>8));
+                else
+                	fill.getOutline().setLineColor(new Color(random.nextInt()>>8));
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"' RGB value mismatch for getOnePointRBG() and getColor().getRGB()",
+                        symbols[i].getOnePointRgb() == ((outlined) ? fill.getOutline().getColor().getRGB() : fill.getFillColor().getRGB()));
+            }
+
+            if (symbols[i] instanceof ITextSymbol) {
+            	ITextSymbol text = (ITextSymbol) symbols[i];
+            	text.setTextColor(new Color(random.nextInt()>>8));
+                assertTrue("Symbol no. "+i+" '"+symbols[i].getClass().getName()+"' RGB value mismatch for getOnePointRBG() and getColor().getRGB()",
+                        symbols[i].getOnePointRgb() == text.getTextColor().getRGB());
+            }
+
+        }
+    }
+
+    /**
+     * ensures that any symbol provides a version of itself to use when the
+     * feature is selected
+     *
+     */
+    public void testSymbolForSelection() {
+    	for (int i = 0; i < symbols.length; i++) {
+			assertNotNull("Symbol no. "+i+" '"+symbols[i].getClass().getName()+" does not define any derived symbol for selection", symbols[i].getSymbolForSelection());
+		}
+    }
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleMarkerSymbolTest.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleMarkerSymbolTest.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/SimpleMarkerSymbolTest.java	(revision 33580)
@@ -0,0 +1,49 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.impl.SimpleMarkerSymbol;
+
+public class SimpleMarkerSymbolTest extends AbstractSymbolTestCase{
+	public SimpleMarkerSymbolTest() {
+		super(SimpleMarkerSymbol.class);
+	}
+}
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawMarkers.java
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawMarkers.java	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/TestDrawMarkers.java	(revision 33580)
@@ -0,0 +1,266 @@
+/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
+ *
+ * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
+ *
+ * For more information, contact:
+ *
+ *  Generalitat Valenciana
+ *   Conselleria d'Infraestructures i Transport
+ *   Av. Blasco Ib��ez, 50
+ *   46010 VALENCIA
+ *   SPAIN
+ *
+ *      +34 963862235
+ *   gvsig@gva.es
+ *      www.gvsig.gva.es
+ *
+ *    or
+ *
+ *   IVER T.I. S.A
+ *   Salamanca 50
+ *   46005 Valencia
+ *   Spain
+ *
+ *   +34 963163400
+ *   dac@iver.es
+ */
+package org.gvsig.symbology.fmap.mapcontext.rendering.symbol;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Random;
+
+import org.gvsig.compat.CompatLocator;
+import org.gvsig.fmap.geom.GeometryLocator;
+import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.Geometry.SUBTYPES;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
+import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test to test that Marker symbols always draw in the same
+ * place respecting size constraints.
+ *
+ * @author jaume dominguez faus - jaume.dominguez@iver.es
+ */
+public class TestDrawMarkers extends AbstractLibraryAutoInitTestCase {
+	private GeometryManager geomManager;
+	private static final Logger logger = LoggerFactory.getLogger(TestDrawMarkers.class);
+	private IMarkerSymbol[] symbols;
+	private final Dimension sz = new Dimension(400, 400);
+	private org.gvsig.fmap.geom.primitive.Point centerP = null;
+	private static final int OUTTER_TOLERANCE = 1;
+	private static final int INNER_TOLERANCE = 1;
+
+	private static final double sizes[] = new double[] {
+		200,
+		100,
+		50,
+		30,
+		16,
+		5,
+		3,
+		2,
+		// smaller sizes don't make any sense
+
+	};
+
+	protected void doSetUp() throws Exception {
+		geomManager = GeometryLocator.getGeometryManager();
+
+		centerP = geomManager.createPoint(sz.width/2, sz.height/2, SUBTYPES.GEOM2D);
+		
+		ISymbol[] allSymbols = TestISymbol.getNewSymbolInstances();
+		// Filter the marker ones
+		ArrayList symbols = new ArrayList();
+
+		for (int i = 0; i < allSymbols.length; i++) {
+			if (allSymbols[i] instanceof IMarkerSymbol) {
+				IMarkerSymbol sym = (IMarkerSymbol) allSymbols[i];
+				symbols.add(sym);
+
+			}
+		}
+		this.symbols = (IMarkerSymbol[]) symbols.toArray(new IMarkerSymbol[symbols.size()]);
+	}
+
+	public void testDrawingSize() {
+		for (int i = 0; i < symbols.length; i++) {
+			for (int j = 0; j < sizes.length; j++) {
+				// new blank buffered image
+				BufferedImage bi = CompatLocator.getGraphicsUtils().createBufferedImage(sz.width, sz.height, BufferedImage.TYPE_INT_ARGB);
+
+				// the graphics for the image, so we can draw onto the buffered image
+				Graphics2D g = bi.createGraphics();
+
+				IMarkerSymbol testSymbol = symbols[i];
+				testSymbol.setColor(Color.YELLOW);
+				testSymbol.setSize(sizes[j]);
+				String name = testSymbol.getClass().getName().substring(
+						testSymbol.getClass().getName().lastIndexOf('.')+1,
+						testSymbol.getClass().getName().length());
+
+				testSymbol.draw(g, new AffineTransform(), centerP, null, null);
+
+				Rectangle wrappingRect = new Rectangle(
+						(int) (centerP.getX()-sizes[j]/2),
+						(int) (centerP.getY()-sizes[j]/2),
+						(int) (sizes[j]),
+						(int) (sizes[j]));
+
+//				if (testSymbol instanceof CharacterMarkerSymbol)
+//					continue;
+
+
+
+
+				assertFalse("fails sizing marker, too big ("+name+", "+sizes[j]+"px)", isOutsideRect(bi, wrappingRect, OUTTER_TOLERANCE ));
+				assertTrue("fails sizing marker, too small ("+name+", "+sizes[j]+"px) \n" +
+						"\t - forgot to enable ANTIALIASING?", fitsInsideRect(bi, wrappingRect, INNER_TOLERANCE));
+
+
+			}
+		}
+	}
+
+	public void testDrawingOffset() {
+		// TODO: uncomment this test and make it run successfully
+//		Random random = new Random(System.currentTimeMillis());
+//		for (int i = 0; i < symbols.length; i++) {
+//			for (int j = 0; j < sizes.length; j++) {
+//				// new blank buffered image
+//				BufferedImage bi = CompatLocator.getGraphicsUtils().createBufferedImage(sz.width, sz.height, BufferedImage.TYPE_INT_ARGB);
+//
+//
+//				// the graphics for the image, so we can draw onto the buffered image
+//				Graphics2D g = bi.createGraphics();
+//
+//				IMarkerSymbol testSymbol = symbols[i];
+//				testSymbol.setColor(Color.YELLOW);
+//				testSymbol.setSize(sizes[j]);
+//
+//				String name = testSymbol.getClass().getName().substring(
+//						testSymbol.getClass().getName().lastIndexOf('.')+1,
+//						testSymbol.getClass().getName().length());
+//
+//				double xOffset = (random.nextDouble()-0.5)*sz.width;
+//				double yOffset = (random.nextDouble()-0.5)*sz.height;
+//
+//				testSymbol.setOffset(new Point2D.Double(xOffset, yOffset));
+//
+//				Rectangle wrappingRect = new Rectangle(
+//						(int) ((centerP.getX()-sizes[j]/2) + xOffset),
+//						(int) ((centerP.getY()-sizes[j]/2) + yOffset),
+//						(int) (sizes[j]),
+//						(int) (sizes[j]));
+//
+////				if (testSymbol instanceof CharacterMarkerSymbol)
+////					continue;
+//
+//
+//
+//				testSymbol.draw(g, new AffineTransform(), centerP, null, null);
+//				assertFalse("fails sizing marker, too big ("+name+", "+sizes[j]+"px)", isOutsideRect(bi, wrappingRect, OUTTER_TOLERANCE ));
+//				assertTrue("fails sizing marker, too small ("+name+", "+sizes[j]+"px) \n" +
+//						"\t - forgot to enable ANTIALIASING?", fitsInsideRect(bi, wrappingRect, INNER_TOLERANCE));
+//
+//			}
+//		}
+	}
+
+	public void testDrawingRotation() {
+		// TODO implement it
+
+	}
+
+	private boolean fitsInsideRect(BufferedImage bi, Rectangle wrappingRect, int tolerance) {
+		int myTolerance = Math.min(tolerance, wrappingRect.width);
+		Rectangle myRect;
+		if (myTolerance >= INNER_TOLERANCE) {
+			myRect = new Rectangle(
+					wrappingRect.x+myTolerance,
+					wrappingRect.y+myTolerance,
+					wrappingRect.width-myTolerance-myTolerance,
+					wrappingRect.height-myTolerance-myTolerance);
+		} else {
+			myRect = new Rectangle(-1, -1, 0, 0); // just ensure it does not disturb the check
+		}
+
+		for (int i = 0; i < bi.getWidth(); i++) {
+			for (int j = 0; j < bi.getHeight(); j++) {
+				if (wrappingRect.contains(i,j)
+						&& !myRect.contains(i,j)) {
+
+					if (bi.getRGB(i,j) != 0)
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean isOutsideRect(BufferedImage bi, Rectangle wrappingRect, int tolerance) {
+		Rectangle myRect = new Rectangle(
+				wrappingRect.x-tolerance,
+				wrappingRect.y-tolerance,
+				wrappingRect.width+tolerance+tolerance,
+				wrappingRect.height+tolerance+tolerance);
+		for (int i = 0; i < bi.getWidth(); i++) {
+			for (int j = 0; j < bi.getHeight(); j++) {
+				if (!myRect.contains(i,j))
+					continue;
+
+				if (bi.getRGB(i,j) != 0) return false;
+			}
+		}
+		return true;
+	}
+}
+
+/// paste this piece of code to produce some png files to check visually what is happening
+//g.setColor(Color.BLUE);
+//Rectangle myRect = new Rectangle(
+//		wrappingRect.x+INNER_TOLERANCE,
+//		wrappingRect.y+INNER_TOLERANCE,
+//		wrappingRect.width-INNER_TOLERANCE-INNER_TOLERANCE,
+//		wrappingRect.height-INNER_TOLERANCE-INNER_TOLERANCE);
+//
+//g.draw(myRect);
+//g.setColor(Color.RED);
+//g.draw(wrappingRect);
+//try {
+//
+//	File dstDir = new File (System.getProperty("java.io.tmpdir")+"/prova-imatges/");
+//	if (!dstDir.exists()) dstDir.mkdir();
+//	ImageIO.write(bi, "png",
+//			new File(dstDir.getAbsoluteFile()+File.separator+
+//					name+"_size_"+sizes[j]
+//					                    +".png"));
+//} catch (IOException e) {
+//	e.printStackTrace();
+//	fail();
+//}
+///
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/README.txt
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/README.txt	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/java/README.txt	(revision 33580)
@@ -0,0 +1,5 @@
+For each class you are going to test, create one Test class with the same
+name as the class to test, ending with Test.
+
+For example, the unit tests of the "ExampleExtension" class are performed
+by the "ExampleExtensionTest" class.
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/README.txt
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/README.txt	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/README.txt	(revision 33580)
@@ -0,0 +1,8 @@
+Put into this folder the resources needed by your test classes.
+
+This folder is added to the Tests classpath, so you can load any resources 
+through the ClassLoader.
+
+By default, in this folder you can find an example of log4j configuration,
+prepared to log messages through the console, so logging works when you
+run your tests classes.
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/log4j.xml
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/log4j.xml	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/src/test/resources/log4j.xml	(revision 33580)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- 
+Log4J configuration file for unit tests execution.
+ -->
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+	<!-- Appender configuration to show logging messages through the console -->
+	<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+		<layout class="org.apache.log4j.PatternLayout">
+			<param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p [%c{2}.%M()]\n  %m%n" />
+		</layout>
+	</appender>
+
+	<!-- 
+	Activate logging messages of DEBUG level of higher only for the
+	InputCoordinatesPanel class.
+	You can put full classes names or packages instead, to configure
+	logging for all the classes and subpackages of the package.
+	-->
+	<category name="org.gvsig.symbology.gui.InputCoordinatesPanel">
+		<priority value="DEBUG" />
+	</category>
+
+	<!-- 
+	By default, show only logging messages of INFO level or higher, 
+	through the previously configured CONSOLE appender. 
+	-->
+	<root>
+		<priority value="INFO" />
+		<appender-ref ref="CONSOLE" />
+	</root>
+</log4j:configuration>
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/pom.xml
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/pom.xml	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/pom.xml	(revision 33580)
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+		 	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.gvsig</groupId>
+	<artifactId>org.gvsig.symbology</artifactId>
+	<packaging>jar</packaging>
+	<version>2.0-SNAPSHOT</version>
+	<name>org.gvsig.symbology</name>
+	<description>[PUT EXTENSION DESCRIPTION HERE]</description>
+	<url>http://www.gvsig.org</url>
+	<scm>
+		<connection>scm:svn:http://subversion.gvsig.org/gvSIG/branches/v2_0_0_prep/extensions/org.gvsig.symbology</connection>
+		<developerConnection>scm:svn:https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/extensions/org.gvsig.symbology</developerConnection>
+		<url>http://subversion.gvsig.org/viewvc/?root=gvSIG</url>
+		<tag>HEAD</tag>
+	</scm>
+	<parent>
+		<groupId>org.gvsig</groupId>
+		<!--artifactId>gvsig-base-extension-pom</artifactId-->
+		<artifactId>gvsig-base-library-pom</artifactId>
+		<version>2.0-SNAPSHOT</version>
+	</parent>	
+	<distributionManagement>
+		<site>
+			<id>gvsig-repository</id>
+			<url>${site-repository}/</url>
+		</site>
+	</distributionManagement>
+
+	<properties>
+		<build-dir>${basedir}/../build</build-dir>
+	</properties>
+	<developers>
+		<developer>
+			<id>developer1</id>
+			<name>Name Surname</name>
+			<email>name@domain</email>
+			<roles>
+				<role>Architect</role>
+				<role>Developer</role>
+			</roles>
+		</developer>
+		<developer>
+			<id>developer2</id>
+			<name>Name2 Surname</name>
+			<email>name2@domain</email>
+			<roles>
+				<role>Developer</role>
+			</roles>
+		</developer>
+	</developers>
+	<dependencies>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.tools.lib</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.tools.lib</artifactId>
+			<classifier>tests</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.utils</artifactId>
+			<version>2.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.i18n</artifactId>
+			<version>2.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.compat</artifactId>
+			<version>2.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.compat</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>se</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.geometry</artifactId>
+			<version>2.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.geometry</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>impl</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.mapcontext</artifactId>
+			<version>2.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.mapcontext</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>operation</classifier>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.projection</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>cresques-impl</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.dal</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>impl</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.fmap.dal</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>spi</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.gvsig</groupId>
+			<artifactId>org.gvsig.metadata</artifactId>
+			<version>2.0-SNAPSHOT</version>
+			<classifier>simple</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.xmlgraphics</groupId>
+			<artifactId>batik-awt-util</artifactId>
+		</dependency>
+	</dependencies>
+	<build>
+		<resources>
+			<resource>
+				<directory>src/main/resources</directory>
+				<excludes>
+					<exclude>config/**</exclude>
+					<exclude>about/**</exclude>
+					<exclude>images/**</exclude>
+					<exclude>locale/**</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<excludes>
+						<exclude>**/impl/**</exclude>
+					</excludes>
+				</configuration>
+				<executions>
+					<!--
+						Generates a jar file only with the mapcontext implementation
+					-->
+					<execution>
+						<id>impl</id>
+						<phase>package</phase>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+						<configuration>
+							<classifier>impl</classifier>
+							<excludes>
+								<exclude>NONE</exclude>
+							</excludes>
+							<includes>
+								<include>**/impl/**</include>
+							</includes>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<artifactId>maven-antrun-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>services</id>
+						<phase>package</phase>
+						<goals>
+							<goal>run</goal>
+						</goals>
+						<configuration>
+							<tasks>
+								<jar destfile="${project.build.directory}/${project.build.finalName}.jar"
+									update="true">
+									<fileset dir="${basedir}/resources/api" />
+								</jar>
+								<jar destfile="${project.build.directory}/${project.build.finalName}-impl.jar"
+									update="true">
+									<fileset dir="${basedir}/resources/impl" />
+								</jar>
+							</tasks>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<additionalClasspathElements>
+						<additionalClasspathElement>${basedir}/resources/api</additionalClasspathElement>
+						<additionalClasspathElement>${basedir}/resources/impl</additionalClasspathElement>
+					</additionalClasspathElements>
+					<!-- TODO: MAKE TESTS WORK AND REMOVE THIS OPTION -->
+					<skipTests>true</skipTests>
+				</configuration>
+			</plugin>
+      		<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<testExcludes>
+						<exclude>**</exclude>
+					</testExcludes>
+				</configuration>
+			</plugin>		
+			
+		</plugins>
+	</build>
+	<profiles>
+		<profile>
+			<id>eclipse-project</id>
+			<build>
+				<defaultGoal>antrun:run</defaultGoal>
+				<plugins>
+					<plugin>
+						<artifactId>maven-antrun-plugin</artifactId>
+						<configuration>
+							<tasks>
+								<ant antfile="${build-dir}/ant-tasks/eclipse-tasks.xml"
+									target="eclipse.all"/>
+							</tasks>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>				
+		</profile>		
+	</profiles>
+	<reporting>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<configuration>
+					<links>
+						<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
+						<link>http://www.slf4j.org/api/</link>
+						<link>${site-repository}/org.gvsig.tools/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.i18n/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.metadata/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.compat/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.projection/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.utils/2.0.0/apidocs/</link>
+						<link>${site-repository}/org.gvsig.fmap.dal/2.0.0/apidocs/</link>
+					</links>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+</project>
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/api/META-INF/services/org.gvsig.tools.library.Library
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/api/META-INF/services/org.gvsig.tools.library.Library	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/api/META-INF/services/org.gvsig.tools.library.Library	(revision 33580)
@@ -0,0 +1 @@
+org.gvsig.symbology.SymbologyLibrary
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/impl/META-INF/services/org.gvsig.tools.library.Library
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/impl/META-INF/services/org.gvsig.tools.library.Library	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/resources/impl/META-INF/services/org.gvsig.tools.library.Library	(revision 33580)
@@ -0,0 +1 @@
+org.gvsig.symbology.impl.SymbologyDefaultImplLibrary
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/README.txt
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/README.txt	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/README.txt	(revision 33580)
@@ -0,0 +1,15 @@
+The project structure of this project is the following:
+
+Project
+|-pom.xml:   		Maven 2 configuration file.
+`-src
+  |-main:    		Project source code, resources and configuration
+  | |-java:  		Java source code
+  | |-resources:	Resources needed by the code (resource bundles, images, etc.)   
+  |`-javadoc:		Javadoc common resources	
+  `-test:    		Unit tests source code, resources and configuration
+    |-java:  		Unit tests java source code
+    `-resources:	Resources needed by the test code (resource bundles, images, etc.)   
+
+Look at the main folders for a README.txt file with more information on the 
+contents of each folder.
\ No newline at end of file
Index: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/distribution/distribution.xml
===================================================================
--- tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/distribution/distribution.xml	(revision 0)
+++ tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology/distribution/distribution.xml	(revision 33580)
@@ -0,0 +1,46 @@
+<assembly>
+	<id>distribution</id>
+	<formats>
+		<format>dir</format>
+	</formats>
+	<fileSets>
+		<!-- Extructure for the extension -->
+		<fileSet>
+			<directory>src/main/resources/config</directory>
+			<outputDirectory>${extension.install.dir.name}
+			</outputDirectory>
+		</fileSet>
+		<fileSet>
+			<directory>src/main/resources/images</directory>
+			<outputDirectory>${extension.install.dir.name}/images
+			</outputDirectory>
+		</fileSet>
+		<fileSet>
+			<directory>src/main/resources/about</directory>
+			<outputDirectory>${extension.install.dir.name}
+			</outputDirectory>
+		</fileSet>
+		<fileSet>
+			<directory>src/main/resources/locale</directory>
+			<outputDirectory>${extension.install.dir.name}
+			</outputDirectory>
+		</fileSet>
+	</fileSets>
+	<files>
+		<file>
+			<source>src/main/resources/build.number</source>
+			<outputDirectory>${extension.install.dir.name}
+			</outputDirectory>
+		</file>
+	</files>
+
+	<dependencySets>
+		<dependencySet>
+			<outputDirectory>${extension.install.dir.name}/${library-dir}
+			</outputDirectory>
+			<includes>
+				<include>org.gvsig:org.gvsig.symbology</include>
+			</includes>
+		</dependencySet>
+	</dependencySets>
+</assembly>
\ No newline at end of file

Property changes on: tags/v2_0_0_Build_2011/extensions/org.gvsig.symbology
___________________________________________________________________
Added: svn:ignore
   + .classpath 
.project 
.settings 
maven-eclipse.xml
target
bin
hs_err_pid*
.externalToolBuilders
.settings
.classpath
.project


