Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / org.gvsig.symbology / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / text / impl / SimpleTextSymbol.java @ 31544

History | View | Annotate | Download (12.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22
package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.impl;
23

    
24
import java.awt.Color;
25
import java.awt.Font;
26
import java.awt.FontMetrics;
27
import java.awt.Graphics2D;
28
import java.awt.Rectangle;
29
import java.awt.RenderingHints;
30
import java.awt.Shape;
31
import java.awt.font.FontRenderContext;
32
import java.awt.font.GlyphVector;
33
import java.awt.geom.AffineTransform;
34
import java.awt.geom.Rectangle2D;
35

    
36
import org.gvsig.compat.print.PrintAttributes;
37
import org.gvsig.fmap.dal.feature.Feature;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
42
import org.gvsig.fmap.geom.exception.CreateGeometryException;
43
import org.gvsig.fmap.geom.primitive.GeneralPathX;
44
import org.gvsig.fmap.mapcontext.MapContextLocator;
45
import org.gvsig.fmap.mapcontext.ViewPort;
46
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
47
import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
50
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.AbstractSymbol;
51
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.impl.CartographicSupportToolkit;
52
import org.gvsig.tools.ToolsLocator;
53
import org.gvsig.tools.dynobject.DynClass;
54
import org.gvsig.tools.persistence.PersistenceException;
55
import org.gvsig.tools.persistence.PersistentState;
56
import org.gvsig.tools.task.Cancellable;
57
import org.slf4j.Logger;
58
import org.slf4j.LoggerFactory;
59

    
60
/**
61
 * SimpleTextSymbol is a class used to create symbols composed using a text defined by
62
 * the user.This text can be edited (changing the color, the font of the characters, and
63
 * the rotation of the text).
64
 * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
65
 * @author 2009-     <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
66
 */
67
public class SimpleTextSymbol extends AbstractSymbol implements ITextSymbol {
68
        public static final String SIMPLE_TEXT_SYMBOL_DYNCLASS_NAME = "SimpleTextSymbol";
69
        
70
        private static final String FIELD_TEXT = "text";
71
        private static final String FIELD_FONT = "font";
72
        private static final String FIELD_TEXT_COLOR = "textColor";
73
        private static final String FIELD_ROTATION = "rotation";
74
        private static final String FIELD_AUTO_RESIZE = "autoResize";
75

    
76
        private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
77
        private String text = "";
78

    
79
        private Font font;
80

    
81
        private Color textColor;
82
        private double rotation;
83
        private FontRenderContext frc = new FontRenderContext(
84
                        new AffineTransform(), false, true);
85
        private boolean autoresize;
86
        final static private Logger logger = LoggerFactory.getLogger(SimpleTextSymbol.class);
87

    
88
        public SimpleTextSymbol() {
89
                super();
90
                SymbolPreferences preferences =
91
                                MapContextLocator.getSymbolManager().getSymbolPreferences();
92
                font = preferences.getDefaultSymbolFont();
93
                textColor = preferences.getDefaultSymbolColor();
94
        }
95

    
96
        public void draw(Graphics2D g, AffineTransform affineTransform,
97
                        Geometry geom, Feature feature, Cancellable cancel) {
98
                if (!isShapeVisible()) {
99
                        return;
100
                }
101
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
102
                g.setColor(textColor);
103
                g.setFont(font);
104
                g.translate(((org.gvsig.fmap.geom.primitive.Point) geom).getX(), ((org.gvsig.fmap.geom.primitive.Point) geom).getY());
105

    
106
                g.rotate(rotation);
107
                Rectangle2D bounds = getBounds();
108
//                 getBounds devuelve el bounds de un texto dibujado de manera que
109
                // la linea base de la primera letra est? en el punto (0,0).
110
                // Por eso, si queremos alinear el texto de manera que la parte superior
111
                // izquierda de la primera letra est? en (0,0) debemos moverlo seg?n
112
                // el valor de la ordenada, en lugar de seg?n su altura.
113
                g.drawString(getText(), 0, (int)-bounds.getY());//(int) bounds.getHeight());
114
                g.rotate(-rotation);
115
                g.translate(-((org.gvsig.fmap.geom.primitive.Point) geom).getX(), -((org.gvsig.fmap.geom.primitive.Point) geom).getY());
116
        }
117

    
118
        public void drawInsideRectangle(Graphics2D g,
119
                        AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
120
                int s = getFont().getSize();
121
                if (autoresize) {
122
                        if (s==0) {
123
                                s =1;
124
                                setFontSize(s);
125
                        }
126
                        g.setFont(getFont());
127
                    FontMetrics fm = g.getFontMetrics();
128
                    Rectangle2D rect = fm.getStringBounds(text, g);
129
                    double width = rect.getWidth();
130
                    double height = rect.getHeight();
131
                    double rWidth = r.getWidth();
132
                    double rHeight = r.getHeight();
133
                    double ratioText = width/height;
134
                    double ratioRect = rWidth/rHeight;
135

    
136
                    if (ratioText>ratioRect) {
137
                            s = (int) (s*(rWidth/width));
138
                    } else {
139
                            s = (int) (s*(rHeight/height));
140
                    }
141
//                    r.setLocation(r.x, (int) Math.round(r.getY()+r.getHeight()));
142
                }
143
                setFontSize(s);
144
//                g.setColor(Color.red);
145
//                g.draw(r);
146
                try {
147
                        if (properties==null)
148
                                draw(g, null, geomManager.createPoint(r.getX(), r.getY(),
149
                                                SUBTYPES.GEOM2D), null, null);
150
                        else
151
                                print(g, new AffineTransform(), geomManager.createPoint(r.getX(), r.getY(), SUBTYPES.GEOM2D), properties);
152
                } catch (CreateGeometryException e) {
153
                        logger.error("Error creatint a point", e);
154
                        e.printStackTrace();
155
                }
156

    
157

    
158
        }
159

    
160
        public int getOnePointRgb() {
161
                return textColor.getRGB();
162
        }
163

    
164
        public void getPixExtentPlus(org.gvsig.fmap.geom.Geometry geom, float[] distances,
165
                        ViewPort viewPort, int dpi) {
166
                throw new Error("Not yet implemented!");
167

    
168
        }
169

    
170
        public ISymbol getSymbolForSelection() {
171
                return this; // a text is not selectable
172
        }
173

    
174
        public int getSymbolType() {
175
                return Geometry.TYPES.TEXT;
176
        }
177

    
178
        public boolean isSuitableFor(Geometry geom) {
179
                return true;
180
        }
181

    
182
        public String getClassName() {
183
                return getClass().getName();
184
        }
185

    
186
        public void print(Graphics2D g, AffineTransform at, org.gvsig.fmap.geom.Geometry geom, PrintAttributes properties){
187
                float originalSize = getFont().getSize2D();
188
                float size=originalSize;
189
                // scale it to size
190
                int pq = properties.getPrintQuality();
191
                if (pq == PrintAttributes.PRINT_QUALITY_NORMAL){
192
                        size *= (double) 300/72;
193
                }else if (pq == PrintAttributes.PRINT_QUALITY_HIGH){
194
                        size *= (double) 600/72;
195
                }else if (pq == PrintAttributes.PRINT_QUALITY_DRAFT){
196
                        // d *= 72/72; // (which is the same than doing nothing)
197
                }
198
                setFont(getFont().deriveFont(size));
199
                draw(g,at,geom, null, null);
200
                setFont(getFont().deriveFont(originalSize));
201
        }
202

    
203
        public String getText() {
204
                return text;
205
        }
206

    
207
        public Font getFont() {
208
                return font;
209
        }
210

    
211
        public Color getTextColor() {
212
                return textColor;
213
        }
214

    
215
        public void setText(String text) {
216
                this.text = text;
217
        }
218

    
219
        public void setFont(Font font) {
220
                if (font == null) {
221
                        logger.warn("font <-- null");
222

    
223
                        return;
224
                }
225
                this.font = font;
226
        }
227

    
228
        public void setTextColor(Color color) {
229
                this.textColor = color;
230
        }
231
        
232
        public Color getColor() {
233
                return getTextColor();
234
        }
235
        
236
        public void setColor(Color color) {
237
                setTextColor(color);
238
        }
239

    
240
        public void setFontSize(double size) {
241
                Font newFont = new Font(font.getName(), font.getStyle(), (int) size);
242
                if (newFont == null) {
243
                        logger.warn(
244
                                        "Font(" + font.getName() + ", "
245
                                        + font.getStyle() + ", " + (int) size + " --> null");
246
                } else {
247
                        this.font = newFont;
248
                }
249
        }
250

    
251
        public double getRotation() {
252
                return rotation;
253
        }
254

    
255
        /**
256
         * Defines the angle of rotation for the text that composes the symbol
257
         *
258
         * @param rotation
259
         */
260
        public void setRotation(double rotation) {
261
                this.rotation = rotation;
262
        }
263

    
264
        /**
265
         * Returns an Geometry which represents a rectangle containing the text in
266
         * <b>screen</b> units.
267
         */
268
        public Geometry getTextWrappingShape(org.gvsig.fmap.geom.primitive.Point p) {
269
                Font font = getFont();
270
                GlyphVector gv = font.createGlyphVector(frc, text);
271

    
272
                Shape shape = gv.getOutline((float) p.getX(), (float) p.getY());
273
                Geometry myFShape;
274
                try {
275
                        myFShape = geomManager.createSurface(new GeneralPathX(shape
276
                                        .getBounds2D().getPathIterator(null)), SUBTYPES.GEOM2D);
277
                        myFShape.transform(AffineTransform.getTranslateInstance(p.getX(), p.getY()));
278

    
279
                        if (rotation != 0) {
280
                                myFShape.transform(AffineTransform.getRotateInstance(rotation));
281
                        }
282
                        return myFShape;
283
                } catch (CreateGeometryException e) {
284
                        logger.error("Error creating a surface", e);
285
                        e.printStackTrace();
286
                }
287
                return null;
288
        }
289

    
290
        public Rectangle getBounds() {
291
//                FontMetrics fm = g.getFontMetrics();
292
//                Rectangle2D rect = fm.getStringBounds("graphics", g);
293

    
294
                Rectangle bounds = null;
295
                try {
296
                        bounds = getTextWrappingShape(geomManager.createPoint(0,0, SUBTYPES.GEOM2D)).getBounds();
297
                } catch (CreateGeometryException e) {
298
                        logger.error("Error creating a point", e);
299
                }
300
                return bounds;
301
        }
302

    
303
        public void setCartographicSize(double cartographicSize, Geometry geom) {
304
                setFontSize(cartographicSize);
305
        }
306

    
307
        public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
308
                double oldSize = getFont().getSize();
309
                setCartographicSize(getCartographicSize(
310
                                                                viewPort,
311
                                                                dpi,
312
                                                                geom),
313
                                                        geom);
314
                return oldSize;
315
        }
316

    
317
        public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
318
                return CartographicSupportToolkit.
319
                                        getCartographicLength(this,
320
                                                                                  getFont().getSize(),
321
                                                                                  viewPort,
322
                                                                                  dpi);
323
        }
324
        public boolean isAutoresizeEnabled() {
325
                return autoresize;
326
        }
327

    
328
        public void setAutoresizeEnabled(boolean autoresizeFlag) {
329
                this.autoresize = autoresizeFlag;
330
        }
331

    
332
        public void loadFromState(PersistentState state)
333
                        throws PersistenceException {
334
                // Set parent fill symbol properties
335
                super.loadFromState(state);
336

    
337
                // Set own properties
338
                setAutoresizeEnabled(state.getBoolean(FIELD_AUTO_RESIZE));
339
                setFont((Font) state.get(FIELD_FONT));
340
                setRotation(state.getDouble(FIELD_ROTATION));
341
                setText(state.getString(FIELD_TEXT));
342
                setTextColor((Color) state.get(FIELD_TEXT_COLOR));
343
        }
344

    
345
        public void saveToState(PersistentState state) throws PersistenceException {
346
                // Save parent fill symbol properties
347
                super.saveToState(state);
348

    
349
                // Save own properties
350
                state.set(FIELD_AUTO_RESIZE, isAutoresizeEnabled());
351
                state.set(FIELD_FONT, getFont());
352
                state.set(FIELD_ROTATION, getRotation());
353
                state.set(FIELD_TEXT, getText());
354
                state.set(FIELD_TEXT_COLOR, getTextColor());
355
        }
356

    
357
        public static void registerPersistence() {
358
                // Add the SimpleTextSymbol DynClass definition.
359
                DynClass dynClass = ToolsLocator.getDynObjectManager().add(
360
                                SIMPLE_TEXT_SYMBOL_DYNCLASS_NAME);
361

    
362
                // Extend the Symbol base definition
363
                dynClass.extend(SYMBOL_DYNCLASS_NAME);
364

    
365
                // Auto resize?
366
                dynClass.addDynFieldBoolean(FIELD_AUTO_RESIZE).setMandatory(true);
367
                // Font
368
                dynClass.addDynFieldObject(FIELD_FONT).setMandatory(true);
369
                // Rotation
370
                dynClass.addDynFieldDouble(FIELD_ROTATION).setMandatory(true);
371
                // Text
372
                dynClass.addDynFieldString(FIELD_TEXT);
373
                // Text color
374
                dynClass.addDynFieldObject(FIELD_TEXT_COLOR).setMandatory(true);
375

    
376
                // Register in persistence
377
                ToolsLocator.getPersistenceManager().registerClass(
378
                                SimpleTextSymbol.class, dynClass);
379
        }
380
}