Revision 40673
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/placements/PlacementManager.java | ||
---|---|---|
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
2 |
* |
|
3 |
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana. |
|
4 |
* |
|
5 |
* This program is free software; you can redistribute it and/or |
|
6 |
* modify it under the terms of the GNU General Public License |
|
7 |
* as published by the Free Software Foundation; either version 2 |
|
8 |
* of the License, or (at your option) any later version. |
|
9 |
* |
|
10 |
* This program is distributed in the hope that it will be useful, |
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
* GNU General Public License for more details. |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License |
|
16 |
* along with this program; if not, write to the Free Software |
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
18 |
* |
|
19 |
* For more information, contact: |
|
20 |
* |
|
21 |
* Generalitat Valenciana |
|
22 |
* Conselleria d'Infraestructures i Transport |
|
23 |
* Av. Blasco Ib??ez, 50 |
|
24 |
* 46010 VALENCIA |
|
25 |
* SPAIN |
|
26 |
* |
|
27 |
* +34 963862235 |
|
28 |
* gvsig@gva.es |
|
29 |
* www.gvsig.gva.es |
|
30 |
* |
|
31 |
* or |
|
32 |
* |
|
33 |
* IVER T.I. S.A |
|
34 |
* Salamanca 50 |
|
35 |
* 46005 Valencia |
|
36 |
* Spain |
|
37 |
* |
|
38 |
* +34 963163400 |
|
39 |
* dac@iver.es |
|
40 |
*/ |
|
41 |
package org.gvsig.labeling.placements; |
|
42 |
|
|
43 |
import java.util.ArrayList; |
|
44 |
import java.util.Iterator; |
|
45 |
|
|
46 |
import org.apache.log4j.Logger; |
|
47 |
import org.gvsig.symbology.fmap.labeling.placements.CannotPlaceLabel; |
|
48 |
import org.gvsig.symbology.fmap.labeling.placements.CompoundLabelPlacement; |
|
49 |
import org.gvsig.symbology.fmap.labeling.placements.ILabelPlacement; |
|
50 |
import org.gvsig.symbology.fmap.labeling.placements.LinePlacementConstraints; |
|
51 |
import org.gvsig.symbology.fmap.labeling.placements.MultiShapePlacement; |
|
52 |
import org.gvsig.symbology.fmap.labeling.placements.MultiShapePlacementConstraints; |
|
53 |
import org.gvsig.symbology.fmap.labeling.placements.PointPlacementConstraints; |
|
54 |
import org.gvsig.symbology.fmap.labeling.placements.PolygonPlacementConstraints; |
|
55 |
|
|
56 |
import com.hardcode.gdbms.engine.data.driver.DriverException; |
|
57 |
import com.iver.cit.gvsig.fmap.core.FShape; |
|
58 |
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IPlacementConstraints; |
|
59 |
import com.iver.utiles.IPersistence; |
|
60 |
import com.iver.utiles.NotExistInXMLEntity; |
|
61 |
import com.iver.utiles.XMLEntity; |
|
62 |
|
|
63 |
/** |
|
64 |
* |
|
65 |
* PlacementManager.java |
|
66 |
* |
|
67 |
* |
|
68 |
* @author jaume dominguez faus - jaume.dominguez@iver.es Jan 3, 2008 |
|
69 |
* |
|
70 |
*/ |
|
71 |
public class PlacementManager { |
|
72 |
private static Logger logger = Logger.getLogger(PlacementManager.class.getName()); |
|
73 |
private static ArrayList<Class<?>> installedLabelPlacements = new ArrayList<Class<?>>(); |
|
74 |
private static ArrayList<ILabelPlacement> availableLabelPlacements; |
|
75 |
private static final CannotPlaceLabel cantPlaceLabel = new CannotPlaceLabel(); |
|
76 |
private PlacementManager() {} |
|
77 |
|
|
78 |
public static ILabelPlacement getPlacement(IPlacementConstraints placementConstraints, int shapeType) { |
|
79 |
|
|
80 |
ArrayList<ILabelPlacement> suitablePlacements = new ArrayList<ILabelPlacement>(); |
|
81 |
if (placementConstraints.getClass().equals(MultiShapePlacementConstraints.class)) { |
|
82 |
MultiShapePlacementConstraints msp = (MultiShapePlacementConstraints) placementConstraints; |
|
83 |
|
|
84 |
return new MultiShapePlacement( |
|
85 |
getPlacement(msp.getPointConstraints(), FShape.POINT), |
|
86 |
getPlacement(msp.getLineConstraints(), FShape.LINE), |
|
87 |
getPlacement(msp.getPolygonConstraints(), FShape.POLYGON) |
|
88 |
); |
|
89 |
} else { |
|
90 |
for (Iterator<ILabelPlacement> iterator = getAvailablePlacements().iterator(); iterator.hasNext();) { |
|
91 |
ILabelPlacement placement = iterator.next(); |
|
92 |
if (placement.isSuitableFor(placementConstraints, shapeType)) { |
|
93 |
suitablePlacements.add(placement); |
|
94 |
} |
|
95 |
} |
|
96 |
|
|
97 |
if (suitablePlacements.size() == 0) |
|
98 |
return cantPlaceLabel; |
|
99 |
else if (suitablePlacements.size() == 1) |
|
100 |
return suitablePlacements.get(0); |
|
101 |
else |
|
102 |
return new CompoundLabelPlacement( |
|
103 |
(ILabelPlacement[]) suitablePlacements. |
|
104 |
toArray(new ILabelPlacement[suitablePlacements.size()])); |
|
105 |
|
|
106 |
} |
|
107 |
|
|
108 |
} |
|
109 |
|
|
110 |
public static void addLabelPlacement(Class<?> labelPlacementClass) { |
|
111 |
// if (!labelPlacementClass.isInstance(ILabelPlacement.class)) |
|
112 |
// throw new IllegalArgumentException( |
|
113 |
// labelPlacementClass.getName()+" is not an valid label placement algorithm."); |
|
114 |
installedLabelPlacements.add(labelPlacementClass); |
|
115 |
|
|
116 |
// invalidate current list of available placements |
|
117 |
if (availableLabelPlacements != null) |
|
118 |
availableLabelPlacements.clear(); |
|
119 |
availableLabelPlacements = null; |
|
120 |
} |
|
121 |
|
|
122 |
private static ArrayList<ILabelPlacement> getAvailablePlacements() { |
|
123 |
if (availableLabelPlacements == null) { |
|
124 |
availableLabelPlacements = new ArrayList<ILabelPlacement>(installedLabelPlacements.size()); |
|
125 |
for (Iterator<Class<?>> iterator = installedLabelPlacements.iterator(); iterator.hasNext();) { |
|
126 |
Class<?> clazz = null; |
|
127 |
try { |
|
128 |
clazz = iterator.next(); |
|
129 |
availableLabelPlacements.add((ILabelPlacement) clazz.newInstance()); |
|
130 |
} catch (Exception e) { |
|
131 |
Logger.getLogger(PlacementManager.class).error("couldn't install label placement '"+clazz.getName(), e); |
|
132 |
} |
|
133 |
} |
|
134 |
} |
|
135 |
|
|
136 |
return availableLabelPlacements; |
|
137 |
} |
|
138 |
|
|
139 |
|
|
140 |
/** |
|
141 |
* Creates a new instance of placement constraints from a vector layer. The |
|
142 |
* placement constraints are created according the layer shape type. |
|
143 |
* @param layerDest |
|
144 |
* @return |
|
145 |
* @throws DriverException |
|
146 |
*/ |
|
147 |
public static IPlacementConstraints createPlacementConstraints(int shapeType) { |
|
148 |
switch (shapeType % FShape.Z) { |
|
149 |
case FShape.LINE: |
|
150 |
return new LinePlacementConstraints(); |
|
151 |
case FShape.POLYGON: |
|
152 |
return new PolygonPlacementConstraints(); |
|
153 |
case FShape.POINT: |
|
154 |
case FShape.MULTIPOINT: // TODO (09/01/08) is this correct??? if not fix it also in PlacementProperties (twice), , MarkerPlacementAroundPoint |
|
155 |
return new PointPlacementConstraints(); |
|
156 |
case FShape.MULTI: |
|
157 |
return new MultiShapePlacementConstraints( |
|
158 |
createPlacementConstraints(FShape.POINT), |
|
159 |
createPlacementConstraints(FShape.LINE), |
|
160 |
createPlacementConstraints(FShape.POLYGON)); |
|
161 |
} |
|
162 |
throw new Error("Shape type not yet supported"); |
|
163 |
// return null; |
|
164 |
} |
|
165 |
|
|
166 |
public static IPlacementConstraints createPlacementConstraints(XMLEntity entity) { |
|
167 |
String className = null; |
|
168 |
try { |
|
169 |
className = entity.getStringProperty("className"); |
|
170 |
} catch (NotExistInXMLEntity e) { |
|
171 |
logger.error("Symbol class name not set.\n" + |
|
172 |
" Maybe you forgot to add the" + |
|
173 |
" putProperty(\"className\", yourClassName)" + |
|
174 |
" call in the getXMLEntity method of your symbol", e); |
|
175 |
} |
|
176 |
|
|
177 |
|
|
178 |
Class clazz = null; |
|
179 |
Object obj = null; |
|
180 |
try { |
|
181 |
clazz = Class.forName(className); |
|
182 |
obj = clazz.newInstance(); |
|
183 |
((IPersistence) obj).setXMLEntity(entity); |
|
184 |
|
|
185 |
} catch (InstantiationException e) { |
|
186 |
logger.error("Trying to instantiate an interface" + |
|
187 |
" or abstract class + "+className+"\n"+e.getMessage(), e); |
|
188 |
} catch (IllegalAccessException e) { |
|
189 |
logger.error(null, e); |
|
190 |
} catch (ClassNotFoundException e) { |
|
191 |
logger.error("No class called " + className + |
|
192 |
" was found.\nCheck the following.\n<br>" + |
|
193 |
"\t- The fullname of the class you're looking " + |
|
194 |
"for matches the value in the className " + |
|
195 |
"property of the XMLEntity ("+className+").\n<br>" + |
|
196 |
"\t- The jar file containing your symbol class is in" + |
|
197 |
"the application classpath<br>", e); |
|
198 |
} |
|
199 |
return (IPlacementConstraints) obj; |
|
200 |
} |
|
201 |
|
|
202 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/placements/LinePlacementConstraints.java | ||
---|---|---|
80 | 80 |
*/ |
81 | 81 |
package org.gvsig.labeling.placements; |
82 | 82 |
|
83 |
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.IPlacementConstraints;
|
|
84 |
import com.iver.utiles.XMLEntity; |
|
83 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints;
|
|
84 |
|
|
85 | 85 |
/** |
86 | 86 |
* |
87 | 87 |
* @author jaume dominguez faus - jaume.dominguez@iver.es |
... | ... | |
98 | 98 |
setPageOriented(false); |
99 | 99 |
} |
100 | 100 |
|
101 |
public String getClassName() { |
|
102 |
return getClass().getName(); |
|
103 |
} |
|
104 | 101 |
|
105 |
public XMLEntity getXMLEntity() { |
|
106 |
XMLEntity xml = super.getXMLEntity(); |
|
107 |
xml.putProperty("className", getClassName()); |
|
108 |
return xml; |
|
109 |
} |
|
110 |
|
|
111 |
|
|
112 |
// private TextPath getTreePath(Integer index, Graphics2D g, FShape shp, char[] text) { |
|
113 |
// TextPath tp = (TextPath) textPaths.get(index); |
|
114 |
// if (tp == null) { |
|
115 |
// tp = new TextPath(g, shp, text); |
|
116 |
// textPaths.put(index, tp); |
|
117 |
// } |
|
118 |
// return tp; |
|
119 |
// } |
|
120 | 102 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/placements/PolygonPlacementConstraints.java | ||
---|---|---|
80 | 80 |
*/ |
81 | 81 |
package org.gvsig.labeling.placements; |
82 | 82 |
|
83 |
import com.iver.utiles.XMLEntity; |
|
84 | 83 |
/** |
85 | 84 |
* |
86 | 85 |
* @author jaume dominguez faus - jaume.dominguez@iver.es |
... | ... | |
91 | 90 |
setPlacementMode(HORIZONTAL); |
92 | 91 |
} |
93 | 92 |
|
94 |
public String getClassName() { |
|
95 |
return getClass().getName(); |
|
96 |
} |
|
97 | 93 |
|
98 |
public XMLEntity getXMLEntity() { |
|
99 |
XMLEntity xml = super.getXMLEntity(); |
|
100 |
xml.putProperty("className", getClassName()); |
|
101 |
return xml; |
|
102 |
} |
|
103 | 94 |
|
104 | 95 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/symbol/SmartTextSymbol.java | ||
---|---|---|
1 |
package org.gvsig.labeling.symbol; |
|
2 |
|
|
3 |
import java.awt.BasicStroke; |
|
4 |
import java.awt.BorderLayout; |
|
5 |
import java.awt.Color; |
|
6 |
import java.awt.Dimension; |
|
7 |
import java.awt.Font; |
|
8 |
import java.awt.Graphics; |
|
9 |
import java.awt.Graphics2D; |
|
10 |
import java.awt.Rectangle; |
|
11 |
import java.awt.Shape; |
|
12 |
import java.awt.Stroke; |
|
13 |
import java.awt.event.ActionEvent; |
|
14 |
import java.awt.event.ActionListener; |
|
15 |
import java.awt.font.FontRenderContext; |
|
16 |
import java.awt.font.GlyphVector; |
|
17 |
import java.awt.font.LineMetrics; |
|
18 |
import java.awt.geom.AffineTransform; |
|
19 |
import java.util.ArrayList; |
|
20 |
|
|
21 |
import javax.print.attribute.PrintRequestAttributeSet; |
|
22 |
import javax.swing.JCheckBox; |
|
23 |
import javax.swing.JFrame; |
|
24 |
import javax.swing.JPanel; |
|
25 |
import javax.swing.JTextField; |
|
26 |
|
|
27 |
import org.gvsig.compat.print.PrintAttributes; |
|
28 |
import org.gvsig.fmap.dal.feature.Feature; |
|
29 |
import org.gvsig.fmap.geom.Geometry; |
|
30 |
import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
|
31 |
import org.gvsig.fmap.geom.GeometryLocator; |
|
32 |
import org.gvsig.fmap.geom.GeometryManager; |
|
33 |
import org.gvsig.fmap.geom.Geometry.TYPES; |
|
34 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
|
35 |
import org.gvsig.fmap.geom.primitive.Curve; |
|
36 |
import org.gvsig.fmap.geom.primitive.Point; |
|
37 |
import org.gvsig.fmap.geom.primitive.Surface; |
|
38 |
import org.gvsig.fmap.mapcontext.ViewPort; |
|
39 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints; |
|
40 |
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
|
41 |
import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol; |
|
42 |
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException; |
|
43 |
import org.gvsig.gui.beans.swing.GridBagLayoutPanel; |
|
44 |
import org.gvsig.gui.beans.swing.JComboBoxFonts; |
|
45 |
import org.gvsig.gui.beans.swing.JIncrementalNumberField; |
|
46 |
import org.gvsig.labeling.placements.PointPlacementConstraints; |
|
47 |
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.TextPath; |
|
48 |
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol; |
|
49 |
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit; |
|
50 |
import org.gvsig.tools.persistence.PersistentState; |
|
51 |
import org.gvsig.tools.persistence.exception.PersistenceException; |
|
52 |
import org.gvsig.tools.task.Cancellable; |
|
53 |
import org.slf4j.Logger; |
|
54 |
import org.slf4j.LoggerFactory; |
|
55 |
|
|
56 |
|
|
57 |
/** |
|
58 |
* Class used to create symbols composed using a text defined by |
|
59 |
* the user.This text can be edited (changing the color, the font of the characters, and |
|
60 |
* the rotation of the text)and has the property that can follow a path.If this path |
|
61 |
* does not exist, the text is treated as a simpletextsymbol (when is drawn). |
|
62 |
* @author jaume dominguez faus - jaume.dominguez@iver.es |
|
63 |
*/ |
|
64 |
public class SmartTextSymbol implements ITextSymbol { |
|
65 |
|
|
66 |
private static final Logger logger = LoggerFactory.getLogger( |
|
67 |
SmartTextSymbol.class); |
|
68 |
|
|
69 |
public static final int SYMBOL_STYLE_TEXTALIGNMENT_LEFT = 0; |
|
70 |
public static final int SYMBOL_STYLE_TEXTALIGNMENT_RIGHT = 1; |
|
71 |
public static final int SYMBOL_STYLE_TEXTALIGNMENT_CENTERED = 2; |
|
72 |
|
|
73 |
// =========================== |
|
74 |
private static GeometryManager geoman = GeometryLocator.getGeometryManager(); |
|
75 |
|
|
76 |
private char[] charText; |
|
77 |
// Background: ITextBackground |
|
78 |
// Case |
|
79 |
private double characterSpacing; |
|
80 |
private double characterWidth; |
|
81 |
// Direction |
|
82 |
private IFillSymbol fillSymbol; |
|
83 |
private double flipAngle; |
|
84 |
// boolean kerning; |
|
85 |
private double leading; |
|
86 |
// Position: textPosition |
|
87 |
private Color ShadowColor; |
|
88 |
private double ShadowXOffset; |
|
89 |
private double ShadowYOffset; |
|
90 |
// TypeSetting: Boolean |
|
91 |
private double wordSpacing; |
|
92 |
// ISimpleTextSymbol : ITextSymbol |
|
93 |
// BreakCharacter: Long |
|
94 |
// Clip: Boolean |
|
95 |
private TextPath textPath; |
|
96 |
private double xOffset; |
|
97 |
private double yOffset; |
|
98 |
private double angle; |
|
99 |
// Color: IColor |
|
100 |
|
|
101 |
// HorizontalAlignment: |
|
102 |
// esriTextHorizontalAlignment |
|
103 |
private boolean rightToLeft; |
|
104 |
// VerticalAlignment |
|
105 |
private double maskSize; |
|
106 |
// MaskStyle |
|
107 |
private IFillSymbol maskSymbol; |
|
108 |
private double margin; |
|
109 |
private int alignment; |
|
110 |
private boolean kerning = false; |
|
111 |
private TextPath tp; |
|
112 |
private IPlacementConstraints constraints; |
|
113 |
|
|
114 |
private boolean shapeVisible = true; |
|
115 |
private int unit = CartographicSupportToolkit.DefaultMeasureUnit; |
|
116 |
private int referenceSystem = CartographicSupportToolkit.DefaultReferenceSystem; |
|
117 |
private double rotation = 0; |
|
118 |
|
|
119 |
// ======================= |
|
120 |
private Surface auxSurface = null; |
|
121 |
|
|
122 |
|
|
123 |
public SmartTextSymbol(ITextSymbol sym, IPlacementConstraints constraints) { |
|
124 |
|
|
125 |
// if(sym instanceof SimpleTextSymbol){ |
|
126 |
// SimpleTextSymbol mySym = (SimpleTextSymbol)sym; |
|
127 |
|
|
128 |
this.setAutoresizeEnabled(sym.isAutoresizeEnabled()); |
|
129 |
this.setDescription(sym.getDescription()); |
|
130 |
this.setFont(sym.getFont()); |
|
131 |
this.setFontSize(sym.getFont().getSize()); |
|
132 |
this.setIsShapeVisible(sym.isShapeVisible()); |
|
133 |
this.setText(sym.getText()); |
|
134 |
this.setTextColor(sym.getTextColor()); |
|
135 |
this.constraints = constraints; |
|
136 |
|
|
137 |
setCharacterSpacing(2); //??? |
|
138 |
setWordSpacing(TextPath.DEFAULT_WORD_SPACING); |
|
139 |
boolean rtl = false; // right to left text |
|
140 |
if (constraints.isAtTheBeginingOfLine()) { |
|
141 |
if (rtl) { |
|
142 |
setAlignment(SYMBOL_STYLE_TEXTALIGNMENT_RIGHT); |
|
143 |
} |
|
144 |
else { |
|
145 |
setAlignment(SYMBOL_STYLE_TEXTALIGNMENT_LEFT); |
|
146 |
} |
|
147 |
} |
|
148 |
else if (constraints.isAtTheEndOfLine()) { |
|
149 |
if (rtl) { |
|
150 |
setAlignment(SYMBOL_STYLE_TEXTALIGNMENT_LEFT); |
|
151 |
} |
|
152 |
else { |
|
153 |
setAlignment(SYMBOL_STYLE_TEXTALIGNMENT_RIGHT); |
|
154 |
} |
|
155 |
} |
|
156 |
else { //constraints.isInTheMiddleOfLine() or constraints.isAtBestOfLine() |
|
157 |
setAlignment(SYMBOL_STYLE_TEXTALIGNMENT_CENTERED); |
|
158 |
} |
|
159 |
setKerning(false); |
|
160 |
setRightToLeft(rtl); |
|
161 |
// } |
|
162 |
} |
|
163 |
|
|
164 |
|
|
165 |
public void setIsShapeVisible(boolean v) { |
|
166 |
this.shapeVisible = v; |
|
167 |
} |
|
168 |
|
|
169 |
public boolean isShapeVisible() { |
|
170 |
return shapeVisible; |
|
171 |
} |
|
172 |
|
|
173 |
|
|
174 |
|
|
175 |
public SmartTextSymbol() { |
|
176 |
PointPlacementConstraints pc = new PointPlacementConstraints(); |
|
177 |
this.constraints = pc; |
|
178 |
|
|
179 |
} |
|
180 |
|
|
181 |
/** |
|
182 |
* Draws the text according. If this symbol has the text path set, then |
|
183 |
* it is used as the text line, otherwise shp <b>must be an FPoint2D</b> |
|
184 |
* indicating the starting point of the text and then the text will |
|
185 |
* be rendered from there and following the rotation previously set. |
|
186 |
*/ |
|
187 |
|
|
188 |
public void draw(Graphics2D g, AffineTransform affineTransform, |
|
189 |
Geometry geom, Feature f, Cancellable cancel) { |
|
190 |
|
|
191 |
if (!isShapeVisible()) return; |
|
192 |
|
|
193 |
setMargin(0); |
|
194 |
|
|
195 |
|
|
196 |
tp = new TextPath(g, geom, charText, getFont(), |
|
197 |
(float) characterSpacing, (float) characterWidth, kerning, |
|
198 |
(float) leading, alignment, (float) wordSpacing, (float) margin, rightToLeft); |
|
199 |
Font font = getFont(); |
|
200 |
g.setFont(font); |
|
201 |
FontRenderContext frc = g.getFontRenderContext(); |
|
202 |
LineMetrics lineMetrics = font.getLineMetrics(getText(), frc); |
|
203 |
|
|
204 |
// GlyphVector glyph = font.layoutGlyphVector(frc, charText, 0, charText.length, Font.LAYOUT_NO_START_CONTEXT); |
|
205 |
double cons = 0; |
|
206 |
|
|
207 |
/* Repartimos el leading (espacio de separaci?n entre lineas) |
|
208 |
* arriba y abajo para que exista la misma separaci?n entre la |
|
209 |
* caja de la letra y la linea tanto si se dibuja por abajo como |
|
210 |
* si se dibuja por arriba. |
|
211 |
*/ |
|
212 |
if(this.constraints.isAboveTheLine()) { |
|
213 |
cons = lineMetrics.getDescent()+lineMetrics.getLeading()/2; |
|
214 |
} |
|
215 |
else if (this.constraints.isBelowTheLine()) { |
|
216 |
cons = -(lineMetrics.getAscent()+lineMetrics.getLeading()/2); |
|
217 |
} |
|
218 |
/* Dibujamos la letra de tal manera que el centro de la caja de letra |
|
219 |
* coincida con la linea |
|
220 |
*/ |
|
221 |
else if(this.constraints.isOnTheLine()) { |
|
222 |
// cons = lineMetrics.getDescent()+(lineMetrics.getLeading()/2)-(lineMetrics.getHeight()/2); |
|
223 |
cons = lineMetrics.getDescent()+lineMetrics.getLeading()-(lineMetrics.getHeight()/2); |
|
224 |
} |
|
225 |
|
|
226 |
double[] coords = tp.nextPosForGlyph(0); |
|
227 |
Stroke haloStroke = new BasicStroke(getHaloWidth(), BasicStroke.CAP_ROUND, |
|
228 |
BasicStroke.JOIN_ROUND); |
|
229 |
|
|
230 |
for (int i = 0; i < tp.getGlyphCount(); i++) { |
|
231 |
coords = tp.nextPosForGlyph(i); |
|
232 |
if (coords[0] == TextPath.NO_POS || coords[1] == TextPath.NO_POS) |
|
233 |
continue; |
|
234 |
|
|
235 |
// move the label 'cons" units above/below the line |
|
236 |
double xOffset = cons * Math.sin(coords[2]); |
|
237 |
double yOffset = cons * Math.cos(coords[2]); |
|
238 |
|
|
239 |
g.translate(coords[0]+xOffset, coords[1]-yOffset); |
|
240 |
g.rotate(coords[2]); |
|
241 |
|
|
242 |
char[] aux = new char[1]; |
|
243 |
aux[0] = charText[i]; |
|
244 |
if (isDrawWithHalo()) { |
|
245 |
GlyphVector glyph = font.createGlyphVector(frc, aux); |
|
246 |
Shape outlineChar = glyph.getOutline(); |
|
247 |
g.setStroke(haloStroke); |
|
248 |
g.setColor(getHaloColor()); |
|
249 |
g.draw(outlineChar); |
|
250 |
} |
|
251 |
|
|
252 |
g.setColor(this.getTextColor()); |
|
253 |
g.drawString(String.valueOf(charText[i]), 0, 0); |
|
254 |
g.rotate(-coords[2]); |
|
255 |
g.translate(-coords[0]-xOffset, -coords[1]+yOffset); |
|
256 |
} |
|
257 |
} |
|
258 |
|
|
259 |
public void getPixExtentPlus( |
|
260 |
Geometry shp, float[] distances, ViewPort viewPort, int dpi) { |
|
261 |
// TODO Implement it |
|
262 |
throw new RuntimeException("Not yet implemented!"); |
|
263 |
} |
|
264 |
|
|
265 |
public int getOnePointRgb() { |
|
266 |
return getTextColor().getRGB(); |
|
267 |
} |
|
268 |
|
|
269 |
/* |
|
270 |
public XMLEntity getXMLEntity() { |
|
271 |
XMLEntity xml = new XMLEntity(); |
|
272 |
xml.putProperty("className", getClassName()); |
|
273 |
xml.putProperty("desc", getDescription()); |
|
274 |
xml.putProperty("isShapeVisible", isShapeVisible()); |
|
275 |
return xml; |
|
276 |
} |
|
277 |
*/ |
|
278 |
|
|
279 |
public int getSymbolType() { |
|
280 |
return Geometry.TYPES.GEOMETRY; |
|
281 |
} |
|
282 |
|
|
283 |
public boolean isSuitableFor(Geometry geom) { |
|
284 |
return geom.getGeometryType().isTypeOf(TYPES.CURVE); |
|
285 |
} |
|
286 |
|
|
287 |
public void drawInsideRectangle( |
|
288 |
Graphics2D g, |
|
289 |
AffineTransform scaleInstance, |
|
290 |
Rectangle r, |
|
291 |
PrintAttributes properties) throws SymbolDrawingException { |
|
292 |
// let's take the bottom segment of the rectangle as the line |
|
293 |
|
|
294 |
Surface surf = null; |
|
295 |
try { |
|
296 |
surf = geoman.createSurface(SUBTYPES.GEOM2D); |
|
297 |
} catch (CreateGeometryException e) { |
|
298 |
logger.info("Error while creating surface.", e); |
|
299 |
throw new SymbolDrawingException( |
|
300 |
SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS); |
|
301 |
} |
|
302 |
surf.addVertex(r.getX(), r.getY()); |
|
303 |
surf.addVertex(r.getX() + r.getWidth(), r.getY()); |
|
304 |
|
|
305 |
if (properties == null) { |
|
306 |
draw(g, scaleInstance, surf, null, null); |
|
307 |
} else { |
|
308 |
print(g, scaleInstance, surf, properties); |
|
309 |
} |
|
310 |
} |
|
311 |
|
|
312 |
|
|
313 |
/* |
|
314 |
public void setXMLEntity(XMLEntity xml) { |
|
315 |
setFont(new Font("Arial", Font.PLAIN, 18)); |
|
316 |
setText("this is my TEST text that follows a line"); |
|
317 |
setDescription(xml.getStringProperty("desc")); |
|
318 |
setIsShapeVisible(xml.getBooleanProperty("isShapeVisible")); |
|
319 |
|
|
320 |
} |
|
321 |
*/ |
|
322 |
|
|
323 |
public void setText(String text) { |
|
324 |
this.charText = text.toCharArray(); |
|
325 |
} |
|
326 |
|
|
327 |
public String getText() { |
|
328 |
return new String(charText); |
|
329 |
} |
|
330 |
|
|
331 |
public void setCharacterSpacing(double charSpacing) { |
|
332 |
this.characterSpacing = charSpacing; |
|
333 |
} |
|
334 |
|
|
335 |
public void setWordSpacing(double wordSpacing) { |
|
336 |
this.wordSpacing = wordSpacing; |
|
337 |
} |
|
338 |
|
|
339 |
public void setAlignment(int alignment) { |
|
340 |
this.alignment = alignment; |
|
341 |
} |
|
342 |
|
|
343 |
public void setKerning(boolean kerning) { |
|
344 |
this.kerning = kerning; |
|
345 |
} |
|
346 |
|
|
347 |
public void setMargin(double margin) { |
|
348 |
this.margin = margin; |
|
349 |
} |
|
350 |
|
|
351 |
public void setRightToLeft(boolean rightToLeft) { |
|
352 |
this.rightToLeft = rightToLeft; |
|
353 |
} |
|
354 |
|
|
355 |
// ============================================== |
|
356 |
// ============================================== |
|
357 |
// ============================================== |
|
358 |
|
|
359 |
|
|
360 |
public ISymbol getSymbolForSelection() { |
|
361 |
// TODO Auto-generated method stub |
|
362 |
return null; |
|
363 |
} |
|
364 |
|
|
365 |
|
|
366 |
|
|
367 |
public boolean isOneDotOrPixel(Geometry geom, |
|
368 |
double[] positionOfDotOrPixel, ViewPort viewPort, int dpi) { |
|
369 |
// TODO Auto-generated method stub |
|
370 |
return false; |
|
371 |
} |
|
372 |
|
|
373 |
|
|
374 |
public String getDescription() { |
|
375 |
// TODO Auto-generated method stub |
|
376 |
return null; |
|
377 |
} |
|
378 |
|
|
379 |
|
|
380 |
public void setDescription(String desc) { |
|
381 |
// TODO Auto-generated method stub |
|
382 |
|
|
383 |
} |
|
384 |
|
|
385 |
|
|
386 |
public Color getColor() { |
|
387 |
// TODO Auto-generated method stub |
|
388 |
return null; |
|
389 |
} |
|
390 |
|
|
391 |
|
|
392 |
public void setColor(Color color) { |
|
393 |
// TODO Auto-generated method stub |
|
394 |
|
|
395 |
} |
|
396 |
|
|
397 |
|
|
398 |
public void loadFromState(PersistentState arg0) throws PersistenceException { |
|
399 |
// TODO Auto-generated method stub |
|
400 |
|
|
401 |
} |
|
402 |
|
|
403 |
|
|
404 |
public void saveToState(PersistentState arg0) throws PersistenceException { |
|
405 |
// TODO Auto-generated method stub |
|
406 |
|
|
407 |
} |
|
408 |
|
|
409 |
|
|
410 |
public void print(Graphics2D g, AffineTransform at, Geometry shape, |
|
411 |
PrintAttributes properties) { |
|
412 |
// TODO Auto-generated method stub |
|
413 |
|
|
414 |
} |
|
415 |
|
|
416 |
|
|
417 |
public void setFont(Font font) { |
|
418 |
// TODO Auto-generated method stub |
|
419 |
|
|
420 |
} |
|
421 |
|
|
422 |
|
|
423 |
public Font getFont() { |
|
424 |
// TODO Auto-generated method stub |
|
425 |
return null; |
|
426 |
} |
|
427 |
|
|
428 |
|
|
429 |
public Color getTextColor() { |
|
430 |
// TODO Auto-generated method stub |
|
431 |
return null; |
|
432 |
} |
|
433 |
|
|
434 |
|
|
435 |
public void setTextColor(Color color) { |
|
436 |
// TODO Auto-generated method stub |
|
437 |
|
|
438 |
} |
|
439 |
|
|
440 |
|
|
441 |
public void setFontSize(double d) { |
|
442 |
// TODO Auto-generated method stub |
|
443 |
|
|
444 |
} |
|
445 |
|
|
446 |
|
|
447 |
public Geometry getTextWrappingShape(Point p) { |
|
448 |
// TODO Auto-generated method stub |
|
449 |
return null; |
|
450 |
} |
|
451 |
|
|
452 |
|
|
453 |
public Rectangle getBounds() { |
|
454 |
// TODO Auto-generated method stub |
|
455 |
return null; |
|
456 |
} |
|
457 |
|
|
458 |
|
|
459 |
public void setAutoresizeEnabled(boolean autoresizeFlag) { |
|
460 |
// TODO Auto-generated method stub |
|
461 |
|
|
462 |
} |
|
463 |
|
|
464 |
|
|
465 |
public boolean isAutoresizeEnabled() { |
|
466 |
// TODO Auto-generated method stub |
|
467 |
return false; |
|
468 |
} |
|
469 |
|
|
470 |
|
|
471 |
public Color getHaloColor() { |
|
472 |
// TODO Auto-generated method stub |
|
473 |
return null; |
|
474 |
} |
|
475 |
|
|
476 |
|
|
477 |
public void setHaloColor(Color haloColor) { |
|
478 |
// TODO Auto-generated method stub |
|
479 |
|
|
480 |
} |
|
481 |
|
|
482 |
|
|
483 |
public float getHaloWidth() { |
|
484 |
// TODO Auto-generated method stub |
|
485 |
return 0; |
|
486 |
} |
|
487 |
|
|
488 |
|
|
489 |
public void setHaloWidth(float haloWidth) { |
|
490 |
// TODO Auto-generated method stub |
|
491 |
|
|
492 |
} |
|
493 |
|
|
494 |
|
|
495 |
public boolean isDrawWithHalo() { |
|
496 |
// TODO Auto-generated method stub |
|
497 |
return false; |
|
498 |
} |
|
499 |
|
|
500 |
|
|
501 |
public void setDrawWithHalo(boolean drawWithHalo) { |
|
502 |
// TODO Auto-generated method stub |
|
503 |
|
|
504 |
} |
|
505 |
|
|
506 |
// ======================== |
|
507 |
|
|
508 |
public Object clone() throws CloneNotSupportedException { |
|
509 |
return this; |
|
510 |
} |
|
511 |
|
|
512 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/symbol/SmartTextSymbolLabelClass.java | ||
---|---|---|
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
2 |
* |
|
3 |
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana. |
|
4 |
* |
|
5 |
* This program is free software; you can redistribute it and/or |
|
6 |
* modify it under the terms of the GNU General Public License |
|
7 |
* as published by the Free Software Foundation; either version 2 |
|
8 |
* of the License, or (at your option) any later version. |
|
9 |
* |
|
10 |
* This program is distributed in the hope that it will be useful, |
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
* GNU General Public License for more details. |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License |
|
16 |
* along with this program; if not, write to the Free Software |
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
18 |
* |
|
19 |
* For more information, contact: |
|
20 |
* |
|
21 |
* Generalitat Valenciana |
|
22 |
* Conselleria d'Infraestructures i Transport |
|
23 |
* Av. Blasco Ib??ez, 50 |
|
24 |
* 46010 VALENCIA |
|
25 |
* SPAIN |
|
26 |
* |
|
27 |
* +34 963862235 |
|
28 |
* gvsig@gva.es |
|
29 |
* www.gvsig.gva.es |
|
30 |
* |
|
31 |
* or |
|
32 |
* |
|
33 |
* IVER T.I. S.A |
|
34 |
* Salamanca 50 |
|
35 |
* 46005 Valencia |
|
36 |
* Spain |
|
37 |
* |
|
38 |
* +34 963163400 |
|
39 |
* dac@iver.es |
|
40 |
*/ |
|
41 |
package org.gvsig.labeling.symbol; |
|
42 |
|
|
43 |
import java.awt.Color; |
|
44 |
import java.awt.Dimension; |
|
45 |
import java.awt.Graphics2D; |
|
46 |
import java.awt.Rectangle; |
|
47 |
import java.awt.Shape; |
|
48 |
import java.awt.geom.PathIterator; |
|
49 |
|
|
50 |
import org.gvsig.symbology.fmap.symbols.SmartTextSymbol; |
|
51 |
|
|
52 |
import com.iver.cit.gvsig.fmap.core.FPoint2D; |
|
53 |
import com.iver.cit.gvsig.fmap.core.FShape; |
|
54 |
import com.iver.cit.gvsig.fmap.core.styles.ILabelStyle; |
|
55 |
import com.iver.cit.gvsig.fmap.core.symbols.ITextSymbol; |
|
56 |
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException; |
|
57 |
import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
|
58 |
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelClass; |
|
59 |
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelLocationMetrics; |
|
60 |
import com.iver.utiles.XMLEntity; |
|
61 |
|
|
62 |
/** |
|
63 |
* <p> |
|
64 |
* SmartTextSymbolLabelClass.java<br> |
|
65 |
* </p> |
|
66 |
* |
|
67 |
* <p> |
|
68 |
* |
|
69 |
* This is a <b>wrapper</b> to be able to use a SmartTextSymbol as a |
|
70 |
* LabelClass. A SmartTextSymbol uses a line instead of a point. |
|
71 |
* Being in fact a Line and not a Marker, it does not make any sense |
|
72 |
* to have label styles since the label styles are well-defined rectangle |
|
73 |
* areas where texts are placed in fields backgrounded by an image. In this |
|
74 |
* contexts, the area is defined dinamically for each line, and there is no |
|
75 |
* sense to have texts fields. They will be rendered as a single string |
|
76 |
* along a line.<br> |
|
77 |
* </p> |
|
78 |
* <p> The label itself is the SmartTextSymbol, |
|
79 |
* the geometry (the line), the label expression, |
|
80 |
* and the text applied to the symbol.<br> |
|
81 |
* </p> |
|
82 |
* <p> |
|
83 |
* Most of the operations performed by this LabelClass are in fact |
|
84 |
* delegated to the symbol.<br> |
|
85 |
* </p> |
|
86 |
* |
|
87 |
* |
|
88 |
* @author jaume dominguez faus - jaume.dominguez@iver.es Mar 6, 2008 |
|
89 |
* |
|
90 |
*/ |
|
91 |
public class SmartTextSymbolLabelClass extends LabelClass { |
|
92 |
private SmartTextSymbol smartTextSymbol; |
|
93 |
|
|
94 |
@Override |
|
95 |
public void draw(Graphics2D graphics, LabelLocationMetrics llm, FShape shp) { |
|
96 |
|
|
97 |
getTextSymbol().draw(graphics, null, shp, null); |
|
98 |
|
|
99 |
|
|
100 |
} |
|
101 |
|
|
102 |
@Override |
|
103 |
public void drawInsideRectangle(Graphics2D graphics, Rectangle bounds) |
|
104 |
throws SymbolDrawingException { |
|
105 |
getTextSymbol().drawInsideRectangle(graphics, null, bounds, null); |
|
106 |
} |
|
107 |
|
|
108 |
|
|
109 |
@Override |
|
110 |
public String getClassName() { |
|
111 |
return getClass().getName(); |
|
112 |
} |
|
113 |
|
|
114 |
@Override |
|
115 |
public ILabelStyle getLabelStyle() { |
|
116 |
// label style not allowed in this context |
|
117 |
return null; |
|
118 |
} |
|
119 |
|
|
120 |
|
|
121 |
// @Override |
|
122 |
// public FShape getShape(LabelLocationMetrics llm) { |
|
123 |
// // TODO Auto-generated method stub |
|
124 |
// throw new Error("Not yet implemented!"); |
|
125 |
// } |
|
126 |
|
|
127 |
|
|
128 |
@Override |
|
129 |
public ITextSymbol getTextSymbol() { |
|
130 |
if (smartTextSymbol == null) { |
|
131 |
smartTextSymbol = new SmartTextSymbol(); |
|
132 |
} |
|
133 |
return smartTextSymbol; |
|
134 |
} |
|
135 |
|
|
136 |
|
|
137 |
@Override |
|
138 |
public XMLEntity getXMLEntity() { |
|
139 |
XMLEntity xml = super.getXMLEntity(); |
|
140 |
xml.putProperty("className", getClassName()); |
|
141 |
return xml; |
|
142 |
} |
|
143 |
|
|
144 |
@Override |
|
145 |
public void setLabelStyle(ILabelStyle labelStyle) { |
|
146 |
// operation don't supported in this context |
|
147 |
} |
|
148 |
|
|
149 |
|
|
150 |
@Override |
|
151 |
public void setTextSymbol(ITextSymbol textSymbol) { |
|
152 |
//// if (! (textSymbol instanceof SmartTextSymbol)) throw new IllegalArgumentException("Only SmartTextSymbol allowed in this context"); |
|
153 |
// if (! (textSymbol instanceof SmartTextSymbol)) { |
|
154 |
// // transform it into a SmartTextSymbol |
|
155 |
// SmartTextSymbol aux = new SmartTextSymbol(); |
|
156 |
// if (textSymbol != null) { |
|
157 |
// aux.setDescription(textSymbol.getDescription()); |
|
158 |
// aux.setText(textSymbol.getText()); |
|
159 |
// aux.setFont(textSymbol.getFont()); |
|
160 |
// aux.setTextColor(textSymbol.getTextColor()); |
|
161 |
// aux.setFontSize(textSymbol.getFont().getSize()); |
|
162 |
// |
|
163 |
// } |
|
164 |
// textSymbol = aux; |
|
165 |
// } |
|
166 |
this.smartTextSymbol = (SmartTextSymbol) textSymbol; |
|
167 |
super.setTextSymbol(textSymbol); |
|
168 |
} |
|
169 |
|
|
170 |
|
|
171 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/parse/ITextParser.java | ||
---|---|---|
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
2 |
* |
|
3 |
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana. |
|
4 |
* |
|
5 |
* This program is free software; you can redistribute it and/or |
|
6 |
* modify it under the terms of the GNU General Public License |
|
7 |
* as published by the Free Software Foundation; either version 2 |
|
8 |
* of the License, or (at your option) any later version. |
|
9 |
* |
|
10 |
* This program is distributed in the hope that it will be useful, |
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
* GNU General Public License for more details. |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License |
|
16 |
* along with this program; if not, write to the Free Software |
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
18 |
* |
|
19 |
* For more information, contact: |
|
20 |
* |
|
21 |
* Generalitat Valenciana |
|
22 |
* Conselleria d'Infraestructures i Transport |
|
23 |
* Av. Blasco Ib??ez, 50 |
|
24 |
* 46010 VALENCIA |
|
25 |
* SPAIN |
|
26 |
* |
|
27 |
* +34 963862235 |
|
28 |
* gvsig@gva.es |
|
29 |
* www.gvsig.gva.es |
|
30 |
* |
|
31 |
* or |
|
32 |
* |
|
33 |
* IVER T.I. S.A |
|
34 |
* Salamanca 50 |
|
35 |
* 46005 Valencia |
|
36 |
* Spain |
|
37 |
* |
|
38 |
* +34 963163400 |
|
39 |
* dac@iver.es |
|
40 |
*/ |
|
41 |
|
|
42 |
/* CVS MESSAGES: |
|
43 |
* |
|
44 |
* $Id: ITextParser.java 10671 2007-03-09 08:33:43Z jaume $ |
|
45 |
* $Log$ |
|
46 |
* Revision 1.2 2007-03-09 08:33:43 jaume |
|
47 |
* *** empty log message *** |
|
48 |
* |
|
49 |
* Revision 1.1.2.1 2007/02/09 07:47:05 jaume |
|
50 |
* Isymbol moved |
|
51 |
* |
|
52 |
* |
|
53 |
*/ |
|
54 |
package org.gvsig.labeling.parse; |
|
55 |
|
|
56 |
public interface ITextParser { |
|
57 |
public final String REGEX_FIELD = "[.+]"; |
|
58 |
public final String REGEX_TAG_SEPARATOR = "[^\\],"; |
|
59 |
|
|
60 |
/** |
|
61 |
* Returns true if the label has at least one tag. |
|
62 |
* |
|
63 |
* @return boolean |
|
64 |
*/ |
|
65 |
public boolean hasTags(); |
|
66 |
|
|
67 |
/** |
|
68 |
* Returns the next text for the tag |
|
69 |
*/ |
|
70 |
public String next(); |
|
71 |
|
|
72 |
} |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/ExtendedLabelingExtension.java | ||
---|---|---|
23 | 23 |
import org.gvsig.labeling.placements.LinePlacementInTheMiddle; |
24 | 24 |
import org.gvsig.labeling.placements.MarkerPlacementAroundPoint; |
25 | 25 |
import org.gvsig.labeling.placements.MarkerPlacementOnPoint; |
26 |
import org.gvsig.labeling.placements.PlacementManager; |
|
26 | 27 |
import org.gvsig.labeling.placements.PolygonPlacementInside; |
27 | 28 |
import org.gvsig.labeling.placements.PolygonPlacementOnCentroid; |
28 | 29 |
import org.gvsig.labeling.placements.PolygonPlacementParallel; |
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.labeling.app/org.gvsig.labeling.app.mainplugin/src/main/java/org/gvsig/labeling/label/GeneralLabelingStrategy.java | ||
---|---|---|
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
2 |
* |
|
3 |
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana. |
|
4 |
* |
|
5 |
* This program is free software; you can redistribute it and/or |
|
6 |
* modify it under the terms of the GNU General Public License |
|
7 |
* as published by the Free Software Foundation; either version 2 |
|
8 |
* of the License, or (at your option) any later version. |
|
9 |
* |
|
10 |
* This program is distributed in the hope that it will be useful, |
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
* GNU General Public License for more details. |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License |
|
16 |
* along with this program; if not, write to the Free Software |
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
18 |
* |
|
19 |
* For more information, contact: |
|
20 |
* |
|
21 |
* Generalitat Valenciana |
|
22 |
* Conselleria d'Infraestructures i Transport |
|
23 |
* Av. Blasco Ib??ez, 50 |
|
24 |
* 46010 VALENCIA |
|
25 |
* SPAIN |
|
26 |
* |
|
27 |
* +34 963862235 |
|
28 |
* gvsig@gva.es |
|
29 |
* www.gvsig.gva.es |
|
30 |
* |
|
31 |
* or |
|
32 |
* |
|
33 |
* IVER T.I. S.A |
|
34 |
* Salamanca 50 |
|
35 |
* 46005 Valencia |
|
36 |
* Spain |
|
37 |
* |
|
38 |
* +34 963163400 |
|
39 |
* dac@iver.es |
|
40 |
*/ |
|
41 |
|
|
42 |
/* CVS MESSAGES: |
|
43 |
* |
|
44 |
* $Id: GeneralLabelingStrategy.java 13749 2007-09-17 14:16:11Z jaume $ |
|
45 |
* $Log$ |
|
46 |
* Revision 1.2 2007-09-17 14:16:11 jaume |
|
47 |
* multilayer symbols sizing bug fixed |
|
48 |
* |
|
49 |
* Revision 1.1 2007/05/22 12:17:41 jaume |
|
50 |
* *** empty log message *** |
|
51 |
* |
|
52 |
* Revision 1.1 2007/05/22 10:05:31 jaume |
|
53 |
* *** empty log message *** |
|
54 |
* |
|
55 |
* Revision 1.10 2007/05/17 09:32:06 jaume |
|
56 |
* *** empty log message *** |
|
57 |
* |
|
58 |
* Revision 1.9 2007/05/09 11:04:58 jaume |
|
59 |
* refactored legend hierarchy |
|
60 |
* |
|
61 |
* Revision 1.8 2007/04/13 11:59:30 jaume |
|
62 |
* *** empty log message *** |
|
63 |
* |
|
64 |
* Revision 1.7 2007/04/12 14:28:43 jaume |
|
65 |
* basic labeling support for lines |
|
66 |
* |
|
67 |
* Revision 1.6 2007/04/11 16:01:08 jaume |
|
68 |
* maybe a label placer refactor |
|
69 |
* |
|
70 |
* Revision 1.5 2007/04/10 16:34:01 jaume |
|
71 |
* towards a styled labeling |
|
72 |
* |
|
73 |
* Revision 1.4 2007/04/02 16:34:56 jaume |
|
74 |
* Styled labeling (start commiting) |
|
75 |
* |
|
76 |
* Revision 1.3 2007/03/28 16:48:01 jaume |
|
77 |
* *** empty log message *** |
|
78 |
* |
|
79 |
* Revision 1.2 2007/03/26 14:40:38 jaume |
|
80 |
* added print method (BUT UNIMPLEMENTED) |
|
81 |
* |
|
82 |
* Revision 1.1 2007/03/20 16:16:20 jaume |
|
83 |
* refactored to use ISymbol instead of FSymbol |
|
84 |
* |
|
85 |
* Revision 1.2 2007/03/09 11:20:57 jaume |
|
86 |
* Advanced symbology (start committing) |
|
87 |
* |
|
88 |
* Revision 1.1 2007/03/09 08:33:43 jaume |
|
89 |
* *** empty log message *** |
|
90 |
* |
|
91 |
* Revision 1.1.2.5 2007/02/21 07:34:08 jaume |
|
92 |
* labeling starts working |
|
93 |
* |
|
94 |
* Revision 1.1.2.4 2007/02/15 16:23:44 jaume |
|
95 |
* *** empty log message *** |
|
96 |
* |
|
97 |
* Revision 1.1.2.3 2007/02/09 07:47:05 jaume |
|
98 |
* Isymbol moved |
|
99 |
* |
|
100 |
* Revision 1.1.2.2 2007/02/02 16:21:24 jaume |
|
101 |
* start commiting labeling stuff |
|
102 |
* |
|
103 |
* Revision 1.1.2.1 2007/02/01 17:46:49 jaume |
|
104 |
* *** empty log message *** |
|
105 |
* |
|
106 |
* |
|
107 |
*/ |
|
108 |
package org.gvsig.labeling.label; |
|
109 |
|
|
110 |
import java.awt.Graphics2D; |
|
111 |
import java.awt.Shape; |
|
112 |
import java.awt.geom.Point2D; |
|
113 |
import java.awt.geom.Rectangle2D; |
|
114 |
import java.awt.image.BufferedImage; |
|
115 |
import java.io.StringReader; |
|
116 |
import java.text.NumberFormat; |
|
117 |
import java.util.ArrayList; |
|
118 |
import java.util.Hashtable; |
|
119 |
import java.util.Iterator; |
|
120 |
import java.util.TreeMap; |
|
121 |
import java.util.TreeSet; |
|
122 |
|
|
123 |
import javax.print.attribute.PrintRequestAttributeSet; |
|
124 |
import javax.print.attribute.standard.PrintQuality; |
|
125 |
|
|
126 |
import org.gvsig.fmap.dal.exception.ReadException; |
|
127 |
import org.gvsig.fmap.dal.feature.Feature; |
|
128 |
import org.gvsig.fmap.dal.feature.FeatureSet; |
|
129 |
import org.gvsig.fmap.geom.Geometry; |
|
130 |
import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
|
131 |
import org.gvsig.fmap.geom.GeometryLocator; |
|
132 |
import org.gvsig.fmap.geom.Geometry.TYPES; |
|
133 |
import org.gvsig.fmap.geom.GeometryManager; |
|
134 |
import org.gvsig.fmap.geom.primitive.Envelope; |
|
135 |
import org.gvsig.fmap.geom.primitive.Point; |
|
136 |
import org.gvsig.fmap.geom.type.GeometryType; |
|
137 |
import org.gvsig.fmap.mapcontext.ViewPort; |
|
138 |
import org.gvsig.fmap.mapcontext.layers.FLayer; |
|
139 |
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect; |
|
140 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass; |
|
141 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingMethod; |
|
142 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy; |
|
143 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints; |
|
144 |
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IZoomConstraints; |
|
145 |
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport; |
|
146 |
import org.gvsig.i18n.Messages; |
|
147 |
import org.gvsig.labeling.operations.Expression; |
|
148 |
import org.gvsig.labeling.operations.ExpressionException; |
|
149 |
import org.gvsig.labeling.parse.LabelExpressionParser; |
|
150 |
import org.gvsig.labeling.placements.ILabelPlacement; |
|
151 |
import org.gvsig.labeling.placements.LinePlacementConstraints; |
|
152 |
import org.gvsig.labeling.placements.MultiShapePlacementConstraints; |
|
153 |
import org.gvsig.labeling.placements.PlacementManager; |
|
154 |
import org.gvsig.labeling.placements.PointPlacementConstraints; |
|
155 |
import org.gvsig.labeling.placements.PolygonPlacementConstraints; |
|
156 |
import org.gvsig.labeling.placements.RemoveDuplicatesComparator; |
|
157 |
import org.gvsig.labeling.symbol.SmartTextSymbolLabelClass; |
|
158 |
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.LabelLocationMetrics; |
|
159 |
import org.gvsig.tools.dispose.DisposableIterator; |
|
160 |
import org.gvsig.tools.task.Cancellable; |
|
161 |
import org.slf4j.Logger; |
|
162 |
import org.slf4j.LoggerFactory; |
|
163 |
|
|
164 |
import com.vividsolutions.jts.geom.CoordinateSequence; |
|
165 |
import com.vividsolutions.jts.geom.CoordinateSequences; |
|
166 |
import com.vividsolutions.jts.geom.GeometryFactory; |
|
167 |
import com.vividsolutions.jts.geom.LineString; |
|
168 |
import com.vividsolutions.jts.geom.Lineal; |
|
169 |
|
|
170 |
/** |
|
171 |
* |
|
172 |
* GeneralLabelingStrategy.java |
|
173 |
* |
|
174 |
* |
|
175 |
* @author jaume dominguez faus - jaume.dominguez@iver.es Jan 4, 2008 |
|
176 |
* |
|
177 |
*/ |
|
178 |
public class GeneralLabelingStrategy implements |
|
179 |
ILabelingStrategy, Cloneable, CartographicSupport { |
|
180 |
|
|
181 |
private static final Logger logger = LoggerFactory.getLogger( |
|
182 |
GeneralLabelingStrategy.class); |
|
183 |
|
|
184 |
public static IPlacementConstraints DefaultPointPlacementConstraints = |
|
185 |
new PointPlacementConstraints(); |
|
186 |
public static IPlacementConstraints DefaultLinePlacementConstraints = |
|
187 |
new LinePlacementConstraints(); |
|
188 |
public static IPlacementConstraints DefaultPolygonPlacementConstraints = |
|
189 |
new PolygonPlacementConstraints(); |
|
190 |
|
|
191 |
private static String[] NO_TEXT = { Messages.getText("text_field") }; |
|
192 |
|
|
193 |
private static MultiShapePlacementConstraints DefaultMultiShapePlacementConstratints = |
|
194 |
new MultiShapePlacementConstraints(); |
|
195 |
|
|
196 |
private ILabelingMethod method; |
|
197 |
private IPlacementConstraints placementConstraints; |
|
198 |
protected FLyrVect layer; |
|
199 |
private IZoomConstraints zoomConstraints; |
|
200 |
private boolean allowOverlapping; |
|
201 |
private long parseTime; |
|
202 |
private int unit; |
|
203 |
private int referenceSystem; |
|
204 |
private double sizeAfter; |
|
205 |
private boolean printMode = false; /* indicate whether output is for a print product (PDF, PS, ...) */ |
|
206 |
|
|
207 |
public void setLayer(FLayer layer) { |
|
208 |
FLyrVect l = (FLyrVect) layer; |
|
209 |
this.layer = l; |
|
210 |
} |
|
211 |
|
|
212 |
public ILabelingMethod getLabelingMethod() { |
|
213 |
return method; |
|
214 |
} |
|
215 |
|
|
216 |
public void setLabelingMethod(ILabelingMethod method) { |
|
217 |
this.method = method; |
|
218 |
} |
|
219 |
|
|
220 |
private class GeometryItem{ |
|
221 |
public Geometry geom = null; |
|
222 |
public int weigh = 0; |
|
223 |
public double savedPerimeter; |
|
224 |
|
|
225 |
public GeometryItem(Geometry geom, int weigh){ |
|
226 |
this.geom = geom; |
|
227 |
this.weigh = weigh; |
|
228 |
this.savedPerimeter = 0; |
|
229 |
} |
|
230 |
} |
|
231 |
public void draw(BufferedImage mapImage, Graphics2D mapGraphics, |
|
232 |
ViewPort viewPort, |
|
233 |
Cancellable cancel, |
|
234 |
double dpi) throws ReadException { |
|
235 |
|
|
236 |
int x = (int)viewPort.getOffset().getX(); |
|
237 |
int y = (int)viewPort.getOffset().getY(); |
|
238 |
// boolean bVisualFXEnabled = false; // if true, the user can see how the labeling is drawing up |
|
239 |
|
|
240 |
//offsets for page generation (PDF, PS, direct printing) |
|
241 |
int print_offset_x = x; |
|
242 |
int print_offset_y = y; |
|
243 |
if (printMode) { |
|
244 |
//for printing, we never offset the labels themselves |
|
245 |
x = 0; |
|
246 |
y = 0; |
|
247 |
printMode = false; |
|
248 |
} |
|
249 |
|
|
250 |
TreeMap<String[], GeometryItem> labelsToPlace = null; |
|
251 |
parseTime =0; |
|
252 |
// long t1 = System.currentTimeMillis(); |
|
253 |
String[] usedFields = getUsedFields(); |
|
254 |
|
|
255 |
int notPlacedCount = 0; |
|
256 |
int placedCount = 0; |
|
257 |
|
|
258 |
/* |
|
259 |
* Get the label placement solvers according the user's settings |
|
260 |
*/ |
|
261 |
ILabelPlacement placement = PlacementManager.getPlacement( |
|
262 |
getPlacementConstraints(), layer.getShapeType()); |
|
263 |
|
|
264 |
|
|
265 |
BufferedImage targetBI; |
|
266 |
Graphics2D targetGr; |
|
267 |
|
|
268 |
|
|
269 |
/* |
|
270 |
* get an ordered set of the LabelClasses up on the |
|
271 |
* label priority |
|
272 |
*/ |
|
273 |
ILabelClass[] lcs = method.getLabelClasses(); |
|
274 |
TreeSet<ILabelClass> ts = new TreeSet<ILabelClass>( |
|
275 |
new LabelClassComparatorByPriority()); |
|
276 |
|
|
277 |
for (int i = 0; i < lcs.length; i++) ts.add(lcs[i]); |
|
278 |
|
|
279 |
if (ts.size()==0) return; |
|
280 |
|
|
281 |
/* |
|
282 |
* now we have an ordered set, it is only need to give a pass |
|
283 |
* for each label class to render by priorities. |
|
284 |
* |
|
285 |
* If no priorities were defined, the following loop only executes |
|
286 |
* once |
|
287 |
*/ |
|
288 |
for (ILabelClass lc : ts) { |
|
289 |
|
|
290 |
FeatureSet fset = method.getFeatureIteratorByLabelClass(layer, lc, viewPort, usedFields); |
|
291 |
|
|
292 |
// duplicates treatment stuff |
|
293 |
/* handle the duplicates mode */ |
|
294 |
int duplicateMode = getDuplicateLabelsMode(); |
|
295 |
if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) { |
|
296 |
// we need to register the labels already placed |
|
297 |
|
|
298 |
labelsToPlace = new TreeMap<String[], GeometryItem>( |
|
299 |
new RemoveDuplicatesComparator()); |
|
300 |
} |
|
301 |
|
|
302 |
boolean bLabelsReallocatable = !isAllowingOverlap(); |
|
303 |
|
|
304 |
BufferedImage overlapDetectImage = null; |
|
305 |
Graphics2D overlapDetectGraphics = null; |
|
306 |
if (bLabelsReallocatable) { |
|
307 |
int width = viewPort.getImageWidth() + print_offset_x; |
|
308 |
|
|
309 |
if(width<0){ |
|
310 |
width = 1; |
|
311 |
} |
|
312 |
int height = viewPort.getImageHeight() + print_offset_y; |
|
313 |
if(height<0){ |
|
314 |
height = 1; |
|
315 |
} |
|
316 |
if (mapImage!=null) |
|
317 |
overlapDetectImage = new BufferedImage( |
|
318 |
mapImage.getWidth() + print_offset_x, |
|
319 |
mapImage.getHeight() + print_offset_y, |
|
320 |
BufferedImage.TYPE_INT_ARGB |
|
321 |
); |
|
322 |
else |
|
323 |
overlapDetectImage = new BufferedImage( |
|
324 |
viewPort.getImageWidth() + print_offset_x, |
|
325 |
viewPort.getImageHeight() + print_offset_y, |
|
326 |
BufferedImage.TYPE_INT_ARGB |
|
327 |
); |
|
328 |
|
|
329 |
overlapDetectGraphics = overlapDetectImage.createGraphics(); |
|
330 |
overlapDetectGraphics.setRenderingHints(mapGraphics.getRenderingHints()); |
|
331 |
} |
|
332 |
if (bLabelsReallocatable) { |
|
333 |
targetBI = overlapDetectImage; |
|
334 |
targetGr = overlapDetectGraphics; |
|
335 |
targetGr.translate(-x, -y); |
|
336 |
} else { |
|
337 |
targetBI = mapImage; |
|
338 |
targetGr = mapGraphics; |
|
339 |
} |
|
340 |
|
|
341 |
DisposableIterator diter = fset.fastIterator(); |
|
342 |
Feature featu = null; |
|
343 |
Geometry geome = null; |
|
344 |
while ( !cancel.isCanceled() && diter.hasNext()) { |
|
345 |
|
|
346 |
featu = (Feature) diter.next(); |
|
347 |
geome = featu.getDefaultGeometry(); |
|
348 |
if (geome == null || geome.getType() == Geometry.TYPES.NULL) { |
|
349 |
continue; |
|
350 |
} |
|
351 |
|
|
352 |
|
|
353 |
if (!setupLabel(featu, lc, cancel, |
|
354 |
usedFields, viewPort, dpi, duplicateMode)) { |
|
355 |
continue; |
|
356 |
} |
|
357 |
|
|
358 |
String[] texts = lc.getTexts(); |
|
359 |
// System.out.println(texts[0]); |
|
360 |
if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) { |
|
361 |
// check if this text (so label) is already present in the map |
|
362 |
|
|
363 |
GeometryItem item = labelsToPlace.get(texts); |
|
364 |
if (item == null){ |
|
365 |
item = new GeometryItem(geome, 0); |
|
366 |
labelsToPlace.put(texts, item); |
|
367 |
} |
|
368 |
if (item.geom != null) { |
|
369 |
|
|
370 |
notPlacedCount++; |
|
371 |
if (geome.getType() != Geometry.TYPES.POINT) { |
|
372 |
// FJP: Cambiamos la uni?n por una comprobaci?n de longitud, por ejemplo. |
|
373 |
// La geometr?a con mayor longitud del bounding box ser? la que etiquetamos. |
|
374 |
// Ser? inexacto, pero m?s r?pido. Solo lo queremos para saber qu? entidad etiquetamos |
|
375 |
// El problema con la uni?n es que para l?neas va muy mal (no sabes lo que te va |
|
376 |
// a etiquetar, y para pol?gonos ser? muy lenta. De todas formas, habr?a que evitar |
|
377 |
// la conversi?n al JTS. |
|
378 |
// Geometry jtsGeom = item.geom.toJTSGeometry().union(geom.toJTSGeometry()); |
|
379 |
// if (jtsGeom instanceof LineString) { |
|
380 |
// CoordinateSequence cs = ((LineString) (jtsGeom)).getCoordinateSequence(); |
|
381 |
// CoordinateSequences.reverse(cs); |
|
382 |
// jtsGeom = new LineString(cs, null); |
|
383 |
// } |
|
384 |
// item.geom = FConverter.jts_to_igeometry(jtsGeom); |
|
385 |
|
|
386 |
Envelope auxBox = geome.getEnvelope(); |
|
387 |
double perimeterAux = 2 * (auxBox.getLength(0)+auxBox.getLength(1)); |
|
388 |
if (perimeterAux > item.savedPerimeter) { |
|
389 |
item.geom = geome; //FConverter.jts_to_igeometry(jtsGeom); |
|
390 |
item.savedPerimeter = perimeterAux; |
|
391 |
} |
|
392 |
} else { |
|
393 |
int weigh = item.weigh; |
|
394 |
Point pointFromLabel = item.geom.centroid(); |
|
395 |
Point pointGeome = geome.centroid(); |
|
396 |
item.geom = GeometryLocator.getGeometryManager().createPoint( |
|
397 |
(pointFromLabel.getX()*weigh + pointGeome.getX())/(weigh+1), |
|
398 |
(pointFromLabel.getY()*weigh + pointGeome.getY())/(weigh+1), |
|
399 |
Geometry.SUBTYPES.GEOM2D); |
|
400 |
} |
|
401 |
} else { |
|
402 |
item.geom = geome; |
|
403 |
} |
|
404 |
item.weigh++; |
|
405 |
} else { |
|
406 |
// Check if size is a pixel |
|
407 |
if (isOnePoint(viewPort, geom)) { |
|
408 |
continue; |
|
409 |
} |
|
410 |
// lc.toCartographicSize(viewPort, dpi, null); |
|
411 |
|
|
412 |
drawLabelInGeom(targetBI, targetGr, lc, placement, viewPort, geom, cancel, dpi, bLabelsReallocatable); |
|
413 |
placedCount++; |
|
414 |
} |
|
415 |
} |
|
416 |
|
|
417 |
// ======= End iteration in feature set ==================== |
|
418 |
|
|
419 |
if (duplicateMode == IPlacementConstraints.REMOVE_DUPLICATE_LABELS) { |
|
420 |
Iterator<String[]> textsIt = labelsToPlace.keySet().iterator(); |
|
421 |
while ( !cancel.isCanceled() && textsIt.hasNext()) { |
|
422 |
notPlacedCount++; |
|
423 |
String[] texts = textsIt.next(); |
|
424 |
|
|
425 |
GeometryItem item = labelsToPlace.get(texts); |
|
426 |
if(item != null){ |
|
427 |
lc.setTexts(texts); |
|
428 |
// Check if size is a pixel |
|
429 |
if (isOnePoint(viewPort, item.geom)) { |
|
430 |
continue; |
|
431 |
} |
|
432 |
|
|
433 |
// lc.toCartographicSize(viewPort, dpi, null); |
|
434 |
drawLabelInGeom(targetBI, targetGr, lc, placement, viewPort, item.geom, cancel, dpi, bLabelsReallocatable); |
|
435 |
} |
|
436 |
} |
|
437 |
} |
|
438 |
|
|
439 |
if (bLabelsReallocatable) { |
|
440 |
targetGr.translate(x, y); |
|
441 |
if (mapImage!=null) |
Also available in: Unified diff