Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / symbols / PictureFillSymbol.java @ 29244

History | View | Annotate | Download (12 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.iver.cit.gvsig.fmap.Messages;
63
import com.iver.cit.gvsig.fmap.ViewPort;
64
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
65
import com.iver.cit.gvsig.fmap.core.FShape;
66
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
67
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
68
import com.iver.cit.gvsig.fmap.core.styles.IMarkerFillPropertiesStyle;
69
import com.iver.cit.gvsig.fmap.core.symbols.AbstractFillSymbol;
70
import com.iver.cit.gvsig.fmap.core.symbols.ILineSymbol;
71
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
72
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException;
73
import com.iver.utiles.StringUtilities;
74
import com.iver.utiles.XMLEntity;
75
import com.iver.utiles.swing.threads.Cancellable;
76

    
77
/**
78
 * PictureFillSymbol allows to use an image file suported by gvSIG as a padding
79
 * for the polygons.This image can be modified using methods to scale or rotate it.
80
 * @author jaume dominguez faus - jaume.dominguez@iver.es
81
 */
82
public class PictureFillSymbol extends AbstractFillSymbol {
83
        private double angle = 0;
84
        private double xScale = 1;
85
        private double yScale = 1;
86
        transient private PictureFillSymbol selectionSym;
87
        private boolean selected;
88
        private IMarkerFillPropertiesStyle markerFillProperties = new SimpleMarkerFillPropertiesStyle();
89
        private String imagePath;
90
        private String selImagePath;
91
        private BackgroundFileStyle bgImage;
92
        private BackgroundFileStyle bgSelImage;
93
        private PrintRequestAttributeSet properties;
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(fillColor);
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(0,0,sizeW,sizeH);
110
                Paint resulPatternFill = null;
111
                BufferedImage sample= null;
112

    
113
                sample= new BufferedImage(sizeW,sizeH,BufferedImage.TYPE_INT_ARGB);
114
                Graphics2D gAux = sample.createGraphics();
115

    
116
                double xSeparation = markerFillProperties.getXSeparation(); // TODO apply CartographicSupport
117
                double ySeparation = markerFillProperties.getYSeparation(); // TODO apply CartographicSupport
118
                double xOffset = markerFillProperties.getXOffset();
119
                double yOffset = markerFillProperties.getYOffset();
120

    
121
                try {
122
                        bg.drawInsideRectangle(gAux, rProv);
123
                } catch (SymbolDrawingException e) {
124
                        Logger.getLogger(getClass()).warn(Messages.getString("label_style_could_not_be_painted"), e);
125
                }
126

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

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

    
136
                rProv.x = rProv.x+(int)xOffset;
137
                rProv.y = rProv.y+(int)yOffset;
138
                resulPatternFill = new TexturePaint(bi,rProv);
139

    
140
                g.setColor(null);
141
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
142
                                RenderingHints.VALUE_ANTIALIAS_ON);
143

    
144
                g.setPaint(resulPatternFill);
145
                g.rotate(-angle);
146
                AffineTransform at = new AffineTransform();
147
                at.rotate(angle);
148
                shp.transform(at);
149
                g.fill(shp);
150
                at.rotate(-angle*2);
151
                shp.transform(at);
152
                g.rotate(angle);
153
                g.setClip(null);
154
                if (getOutline()!=null) {
155
                        getOutline().draw(g, affineTransform, shp, cancel);
156
                }
157
        }
158

    
159
        /**
160
         * Constructor method
161
         *
162
         */
163
        public PictureFillSymbol() {
164
                super();
165
        }
166
        /**
167
         * Constructor method
168
         * @param imageURL, URL of the normal image
169
         * @param selImageURL, URL of the image when it is selected in the map
170
         * @throws IOException
171
         */
172

    
173
        public PictureFillSymbol(URL imageURL, URL selImageURL) throws IOException {
174
                setImage(imageURL);
175
                if (selImageURL!=null)
176
                        setSelImage(selImageURL);
177
                else setSelImage(imageURL);
178
        }
179

    
180

    
181
        /**
182
         * Sets the URL for the image to be used as a picture fill symbol (when it is selected in the map)
183
         * @param imageFile, File
184
         * @throws IOException
185
         */
186
        public void setSelImage(URL selImageUrl) throws IOException{
187

    
188
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
189
                selImagePath = selImageUrl.toString();
190
        }
191

    
192

    
193

    
194
        /**
195
         * Defines the URL from where the picture to fill the polygon is taken.
196
         * @param imageFile
197
         * @throws IOException
198
         */
199
        public void setImage(URL imageUrl) throws IOException{
200

    
201
                bgImage = BackgroundFileStyle.createStyleByURL(imageUrl);
202
                imagePath = imageUrl.toString();
203
        }
204

    
205

    
206

    
207
        public void drawInsideRectangle(Graphics2D g,
208
                        AffineTransform scaleInstance, Rectangle r, PrintRequestAttributeSet properties) throws SymbolDrawingException {
209
                if (properties==null)
210
                        draw(g, null, new FPolygon2D(new GeneralPathX(r)), null);
211
                else
212
                        print(g, new AffineTransform(), new FPolygon2D(new GeneralPathX(r)), properties);
213
        }
214

    
215
        public ISymbol getSymbolForSelection() {
216
                if (selectionSym == null) {
217
                        selectionSym = (PictureFillSymbol) SymbologyFactory.createSymbolFromXML(getXMLEntity(), getDescription());
218
                        selectionSym.selected=true;
219
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
220
                }
221
                return selectionSym;
222

    
223
        }
224

    
225
        public int getSymbolType() {
226
                return FShape.POLYGON;
227
        }
228

    
229
        public XMLEntity getXMLEntity() {
230
                XMLEntity xml = new XMLEntity();
231
                xml.putProperty("desc", getDescription());
232
                xml.putProperty("className", getClassName());
233
                xml.putProperty("isShapeVisible", isShapeVisible());
234
                xml.putProperty("referenceSystem", getReferenceSystem());
235
                xml.putProperty("unit", getUnit());
236

    
237
                xml.putProperty("angle", angle);
238
                xml.putProperty("scaleX", xScale);
239
                xml.putProperty("scaleY", yScale);
240
                xml.putProperty("imagePath", imagePath);
241
                xml.putProperty("selImagePath", selImagePath);
242
                if (getFillColor()!=null)
243
                        xml.putProperty("fillColor", StringUtilities.color2String(getFillColor()));
244

    
245
                xml.putProperty("hasFill", hasFill());
246
                XMLEntity fillPropertiesXML = markerFillProperties.getXMLEntity();
247
                fillPropertiesXML.putProperty("id", "fillProperties");
248
                xml.addChild(fillPropertiesXML);
249
                if (getOutline()!=null) {
250
                        XMLEntity outlineXML = getOutline().getXMLEntity();
251
                        outlineXML.putProperty("id", "outline symbol");
252
                        xml.addChild(outlineXML);
253
                }
254
                xml.putProperty("hasOutline", hasOutline());
255
                return xml;
256
        }
257

    
258
        public void setXMLEntity(XMLEntity xml) {
259

    
260
                imagePath = xml.getStringProperty("imagePath");
261
                selImagePath = xml.getStringProperty("selImagePath");
262
                setDescription(xml.getStringProperty("desc"));
263
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
264
                setAngle(xml.getDoubleProperty("angle"));
265
                setXScale(xml.getDoubleProperty("scaleX"));
266
                setYScale(xml.getDoubleProperty("scaleY"));
267
                if (xml.contains("fillColor"))
268
                        setFillColor(StringUtilities.string2Color(
269
                                        xml.getStringProperty("fillColor")));
270
                markerFillProperties = (IMarkerFillPropertiesStyle) SymbologyFactory.
271
                createStyleFromXML(
272
                                xml.firstChild("id", "fillProperties"), "fill properties");
273

    
274
                try {
275
                        setImage(new URL(imagePath));
276
                        setSelImage(new URL(selImagePath));
277
                } catch (MalformedURLException e) {
278
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
279
                } catch (IOException e) {
280
                        Logger.getLogger(getClass()).error(Messages.getString("invalid_url"));
281

    
282
                }
283

    
284
                if (xml.contains("hasFill"))
285
                        setHasFill(xml.getBooleanProperty("hasFill"));
286

    
287
                XMLEntity outlineXML = xml.firstChild("id", "outline symbol");
288
                if (outlineXML != null) {
289
                        setOutline((ILineSymbol) SymbologyFactory.createSymbolFromXML(outlineXML, "outline"));
290
                }
291

    
292
                if (xml.contains("unit")) { // remove this line when done
293
                        // measure unit (for outline)
294
                        setUnit(xml.getIntProperty("unit"));
295

    
296
                        // reference system (for outline)
297
                        setReferenceSystem(xml.getIntProperty("referenceSystem"));
298
                }
299

    
300
                if (xml.contains("hasOutline"))
301
                        setHasOutline(xml.getBooleanProperty("hasOutline"));
302

    
303

    
304

    
305
        }
306

    
307
        public String getClassName() {
308
                return getClass().getName();
309
        }
310

    
311
        public void print(Graphics2D g, AffineTransform at, FShape shape,
312
                        PrintRequestAttributeSet properties) {
313
                this.properties=properties;
314
        draw(g, at, shape, null);
315
        this.properties=null;
316
        }
317
        /**
318
         * Returns the IMarkerFillProperties that allows this class to treat the picture as
319
         * a marker in order to scale it, rotate it and so on.
320
         * @return markerFillProperties,IMarkerFillPropertiesStyle
321
         */
322
        public IMarkerFillPropertiesStyle getMarkerFillProperties() {
323
                return markerFillProperties;
324
        }
325

    
326
        /**
327
         * Sets the MarkerFillProperties in order to allow the user to modify the picture as
328
         * a marker (it is possible to scale it, rotate it and so on)
329
         * @param prop
330
         */
331
        public void setMarkerFillProperties(IMarkerFillPropertiesStyle prop) {
332
                this.markerFillProperties = prop;
333
        }
334
        /**
335
         * Defines the angle for the rotation of the image when it is added to create the
336
         * padding
337
         *
338
         * @return angle
339
         */
340
        public double getAngle() {
341
                return angle;
342
        }
343
        /**
344
         * Sets the angle for the rotation of the image when it is added to create the padding
345
         * @param angle
346
         */
347
        public void setAngle(double angle) {
348
                this.angle = angle;
349
        }
350

    
351
        /**
352
         * Defines the scale for the x axis of the image when it is added to create the
353
         * padding
354
         * @return xScale
355
         */
356
        public double getXScale() {
357
                return xScale;
358
        }
359
        /**
360
         * Returns the scale for the x axis of the image when it is added to create the
361
         * padding
362
         * @param xScale
363
         */
364
        public void setXScale(double xScale) {
365
                this.xScale = xScale;
366
        }
367
        /**
368
         * Defines the scale for the y axis of the image when it is added to create the
369
         * padding
370
         * @return yScale
371
         */
372
        public double getYScale() {
373
                return yScale;
374
        }
375
        /**
376
         * Returns the scale for the y axis of the image when it is added to create the
377
         * padding
378
         * @param yScale
379
         */
380
        public void setYScale(double yScale) {
381
                this.yScale = yScale;
382
        }
383
        /**
384
         * Returns the path of the image that is used to create the padding to fill the
385
         * polygon
386
         * @return imagePath
387
         */
388
        public String getImagePath() {
389
                return imagePath;
390
        }
391

    
392
        /**
393
         * Returns the path of the image used when the polygon is selected
394
         * @return
395
         */
396
        public String getSelImagePath(){
397
                return selImagePath;
398
        }
399

    
400

    
401
        @Override
402
        public double toCartographicSize(ViewPort viewPort, double dpi, FShape shp) {
403
                return super.toCartographicSize(viewPort, dpi, shp);
404
                // this symbol cannot apply any cartographic transfomation to its filling
405
        }
406

    
407

    
408
}