Statistics
| Revision:

root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / symbols / PictureFillSymbol.java @ 22457

History | View | Annotate | Download (11.7 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 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.symbology.fmap.symbols;
42

    
43
import java.awt.Color;
44
import java.awt.Dimension;
45
import java.awt.Graphics2D;
46
import java.awt.Paint;
47
import java.awt.Rectangle;
48
import java.awt.RenderingHints;
49
import java.awt.TexturePaint;
50
import java.awt.geom.AffineTransform;
51
import java.awt.image.BufferedImage;
52
import java.io.IOException;
53
import java.net.MalformedURLException;
54
import java.net.URL;
55

    
56
import javax.print.attribute.PrintRequestAttributeSet;
57

    
58
import org.apache.log4j.Logger;
59
import org.gvsig.symbology.fmap.styles.BackgroundFileStyle;
60
import org.gvsig.symbology.fmap.styles.SimpleMarkerFillPropertiesStyle;
61

    
62
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
63
import com.iver.cit.gvsig.fmap.Messages;
64
import com.iver.cit.gvsig.fmap.ViewPort;
65
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
66
import com.iver.cit.gvsig.fmap.core.FShape;
67
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
68
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
69
import com.iver.cit.gvsig.fmap.core.styles.IMarkerFillPropertiesStyle;
70
import com.iver.cit.gvsig.fmap.core.symbols.AbstractFillSymbol;
71
import com.iver.cit.gvsig.fmap.core.symbols.ILineSymbol;
72
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
73
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException;
74
import com.iver.utiles.StringUtilities;
75
import com.iver.utiles.XMLEntity;
76
import com.iver.utiles.swing.threads.Cancellable;
77

    
78
/**
79
 * PictureFillSymbol allows to use an image file suported by gvSIG as a padding
80
 * for the polygons.This image can be modified using methods to scale or rotate it.
81
 * @author jaume dominguez faus - jaume.dominguez@iver.es
82
 */
83
public class PictureFillSymbol extends AbstractFillSymbol {
84
        private double angle = 0;
85
        private double xScale = 1;
86
        private double yScale = 1;
87
        transient private PictureFillSymbol selectionSym;
88
        private boolean selected;
89
        private IMarkerFillPropertiesStyle markerFillProperties = new SimpleMarkerFillPropertiesStyle();
90
        private String imagePath;
91
        private String selImagePath;
92
        private BackgroundFileStyle bgImage;
93
        private BackgroundFileStyle bgSelImage;
94

    
95

    
96
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp, Cancellable cancel) {
97
                Color fillColor = getFillColor();
98
                if (fillColor != null) {
99
                        g.setColor(getFillColor());
100
                        g.fill(shp);
101
                }
102

    
103
                g.setClip(shp);
104
                BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage ;
105

    
106
                int sizeW=(int) ((int)bg.getBounds().getWidth() * xScale);
107
                int sizeH=(int) ((int)bg.getBounds().getHeight() * yScale);
108
                Rectangle rProv = new Rectangle();
109
                rProv.setFrame(shp.getBounds2D().getX(), 
110
                                shp.getBounds2D().getY(),
111
                                sizeW,
112
                                sizeH);
113
                Paint resulPatternFill = null;
114
                BufferedImage sample= null;
115

    
116
                sample= new BufferedImage(sizeW,sizeH,BufferedImage.TYPE_INT_ARGB);
117
                Graphics2D gAux = sample.createGraphics();
118

    
119
                double xSeparation = markerFillProperties.getXSeparation(); // TODO apply CartographicSupport
120
                double ySeparation = markerFillProperties.getYSeparation(); // TODO apply CartographicSupport
121
                double xOffset = markerFillProperties.getXOffset();
122
                double yOffset = markerFillProperties.getYOffset();
123

    
124
                bg.drawInsideRectangle(gAux, rProv);
125

    
126
                Dimension sz = rProv.getSize();
127
                sz = new Dimension((int) Math.round(sz.getWidth()+(xSeparation)),
128
                                (int) Math.round(sz.getHeight() + (ySeparation)));
129
                rProv.setSize(sz);
130

    
131
                BufferedImage bi = new BufferedImage(rProv.width, rProv.height, BufferedImage.TYPE_INT_ARGB);
132
                gAux = bi.createGraphics();
133
                gAux.drawImage(sample, null, (int) (xSeparation*0.5), (int) (ySeparation*0.5));
134

    
135
                resulPatternFill = new TexturePaint(bi,rProv);
136

    
137
                g.setColor(null);
138
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
139
                                RenderingHints.VALUE_ANTIALIAS_ON);
140

    
141
                g.translate(xOffset, yOffset);
142
                g.setPaint(resulPatternFill);
143
                g.fill(shp);
144
                g.translate(-xOffset, -yOffset);
145
                g.setClip(null);
146
                if (getOutline()!=null) {
147
                        getOutline().draw(g, affineTransform, shp, cancel);
148
                }
149
        }
150

    
151
        /**
152
         * Constructor method
153
         *
154
         */
155
        public PictureFillSymbol() {
156
                super();
157
        }
158
        /**
159
         * Constructor method
160
         * @param imageURL, URL of the normal image
161
         * @param selImageURL, URL of the image when it is selected in the map
162
         * @throws IOException
163
         */
164

    
165
        public PictureFillSymbol(URL imageURL, URL selImageURL) throws IOException {
166
                setImage(imageURL);
167
                if (selImageURL!=null)
168
                        setSelImage(selImageURL);
169
                else setSelImage(imageURL);
170
        }
171

    
172

    
173
        /**
174
         * Sets the URL for the image to be used as a picture fill symbol (when it is selected in the map)
175
         * @param imageFile, File
176
         * @throws IOException
177
         */
178
        public void setSelImage(URL selImageUrl) throws IOException{
179

    
180
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
181
                selImagePath = selImageUrl.toString();
182
        }
183

    
184

    
185

    
186
        /**
187
         * Defines the URL from where the picture to fill the polygon is taken.
188
         * @param imageFile
189
         * @throws IOException
190
         */
191
        public void setImage(URL imageUrl) throws IOException{
192

    
193
                bgImage = BackgroundFileStyle.createStyleByURL(imageUrl);
194
                imagePath = imageUrl.toString();
195
        }
196

    
197

    
198

    
199
        public void drawInsideRectangle(Graphics2D g,
200
                        AffineTransform scaleInstance, Rectangle r) throws SymbolDrawingException {
201
                draw(g, null, new FPolygon2D(new GeneralPathX(r)), null);
202
        }
203

    
204
        public ISymbol getSymbolForSelection() {
205
                if (selectionSym == null) {
206
                        selectionSym = (PictureFillSymbol) SymbologyFactory.createSymbolFromXML(getXMLEntity(), getDescription());
207
                        selectionSym.selected=true;
208
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
209
                }
210
                return selectionSym;
211

    
212
        }
213

    
214
        public int getSymbolType() {
215
                return FShape.POLYGON;
216
        }
217

    
218
        public XMLEntity getXMLEntity() {
219
                XMLEntity xml = new XMLEntity();
220
                xml.putProperty("desc", getDescription());
221
                xml.putProperty("className", getClassName());
222
                xml.putProperty("isShapeVisible", isShapeVisible());
223
                xml.putProperty("referenceSystem", getReferenceSystem());
224
                xml.putProperty("unit", getUnit());
225

    
226
                xml.putProperty("angle", angle);
227
                xml.putProperty("scaleX", xScale);
228
                xml.putProperty("scaleY", yScale);
229
                xml.putProperty("imagePath", imagePath);
230
                xml.putProperty("selImagePath", selImagePath);
231
                if (getFillColor()!=null)
232
                        xml.putProperty("fillColor", StringUtilities.color2String(getFillColor()));
233

    
234
                xml.putProperty("hasFill", hasFill());
235
                XMLEntity fillPropertiesXML = markerFillProperties.getXMLEntity();
236
                fillPropertiesXML.putProperty("id", "fillProperties");
237
                xml.addChild(fillPropertiesXML);
238
                if (getOutline()!=null) {
239
                        XMLEntity outlineXML = getOutline().getXMLEntity();
240
                        outlineXML.putProperty("id", "outline symbol");
241
                        xml.addChild(outlineXML);
242
                }
243
                xml.putProperty("hasOutline", hasOutline());
244
                return xml;
245
        }
246

    
247
        public void setXMLEntity(XMLEntity xml) {
248

    
249
                imagePath = xml.getStringProperty("imagePath");
250
                selImagePath = xml.getStringProperty("selImagePath");
251
                setDescription(xml.getStringProperty("desc"));
252
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
253
                setAngle(xml.getDoubleProperty("angle"));
254
                setXScale(xml.getDoubleProperty("scaleX"));
255
                setYScale(xml.getDoubleProperty("scaleY"));
256
                if (xml.contains("fillColor"))
257
                        setFillColor(StringUtilities.string2Color(
258
                                        xml.getStringProperty("fillColor")));
259
                markerFillProperties = (IMarkerFillPropertiesStyle) SymbologyFactory.
260
                createStyleFromXML(
261
                                xml.firstChild("id", "fillProperties"), "fill properties");
262

    
263
                try {
264
                        setImage(new URL(imagePath));
265
                        setSelImage(new URL(selImagePath));
266
                } catch (MalformedURLException e) {
267
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
268
                } catch (IOException e) {
269
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
270
                                        
271
                }
272

    
273
                if (xml.contains("hasFill"))
274
                        setHasFill(xml.getBooleanProperty("hasFill"));
275

    
276
                XMLEntity outlineXML = xml.firstChild("id", "outline symbol");
277
                if (outlineXML != null) {
278
                        setOutline((ILineSymbol) SymbologyFactory.createSymbolFromXML(outlineXML, "outline"));
279
                }
280

    
281
                if (xml.contains("unit")) { // remove this line when done
282
                        // measure unit (for outline)
283
                        setUnit(xml.getIntProperty("unit"));
284

    
285
                        // reference system (for outline)
286
                        setReferenceSystem(xml.getIntProperty("referenceSystem"));
287
                }
288

    
289
                if (xml.contains("hasOutline"))
290
                        setHasOutline(xml.getBooleanProperty("hasOutline"));
291

    
292

    
293

    
294
        }
295

    
296
        public String getClassName() {
297
                return getClass().getName();
298
        }
299

    
300
        public void print(Graphics2D g, AffineTransform at, FShape shape,
301
                        PrintRequestAttributeSet properties) throws ReadDriverException {
302
                // TODO Auto-generated method stub
303
                throw new Error("Not yet implemented!");
304
        }
305
        /**
306
         * Returns the IMarkerFillProperties that allows this class to treat the picture as
307
         * a marker in order to scale it, rotate it and so on.
308
         * @return markerFillProperties,IMarkerFillPropertiesStyle
309
         */
310
        public IMarkerFillPropertiesStyle getMarkerFillProperties() {
311
                return markerFillProperties;
312
        }
313

    
314
        /**
315
         * Sets the MarkerFillProperties in order to allow the user to modify the picture as
316
         * a marker (it is possible to scale it, rotate it and so on)
317
         * @param prop
318
         */
319
        public void setMarkerFillProperties(IMarkerFillPropertiesStyle prop) {
320
                this.markerFillProperties = prop;
321
        }
322
        /**
323
         * Defines the angle for the rotation of the image when it is added to create the
324
         * padding
325
         *
326
         * @return angle
327
         */
328
        public double getAngle() {
329
                return angle;
330
        }
331
        /**
332
         * Sets the angle for the rotation of the image when it is added to create the padding
333
         * @param angle
334
         */
335
        public void setAngle(double angle) {
336
                this.angle = angle;
337
        }
338

    
339
        /**
340
         * Defines the scale for the x axis of the image when it is added to create the
341
         * padding
342
         * @return xScale
343
         */
344
        public double getXScale() {
345
                return xScale;
346
        }
347
        /**
348
         * Returns the scale for the x axis of the image when it is added to create the
349
         * padding
350
         * @param xScale
351
         */
352
        public void setXScale(double xScale) {
353
                this.xScale = xScale;
354
        }
355
        /**
356
         * Defines the scale for the y axis of the image when it is added to create the
357
         * padding
358
         * @return yScale
359
         */
360
        public double getYScale() {
361
                return yScale;
362
        }
363
        /**
364
         * Returns the scale for the y axis of the image when it is added to create the
365
         * padding
366
         * @param yScale
367
         */
368
        public void setYScale(double yScale) {
369
                this.yScale = yScale;
370
        }
371
        /**
372
         * Returns the path of the image that is used to create the padding to fill the
373
         * polygon
374
         * @return imagePath
375
         */
376
        public String getImagePath() {
377
                return imagePath;
378
        }
379

    
380
        /**
381
         * Returns the path of the image used when the polygon is selected
382
         * @return
383
         */
384
        public String getSelImagePath(){
385
                return selImagePath;
386
        }
387

    
388
        
389
        @Override
390
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
391
                return super.toCartographicSize(viewPort, dpi, shp);
392
                // this symbol cannot apply any cartographic transfomation to its filling
393
        }
394

    
395

    
396
}