Statistics
| Revision:

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

History | View | Annotate | Download (12.3 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.File;
53
import java.io.IOException;
54
import java.net.MalformedURLException;
55
import java.net.URL;
56

    
57
import javax.print.attribute.PrintRequestAttributeSet;
58

    
59
import org.apache.log4j.Logger;
60
import org.gvsig.symbology.fmap.styles.BackgroundFileStyle;
61
import org.gvsig.symbology.fmap.styles.SimpleMarkerFillPropertiesStyle;
62
import org.gvsig.tools.file.PathGenerator;
63

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

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

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

    
105
                g.setClip(shp);
106
                BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage ;
107
                if (bg != null && bg.getBounds() != null){
108
                        int sizeW=(int) ((int)bg.getBounds().getWidth() * xScale);
109
                        int sizeH=(int) ((int)bg.getBounds().getHeight() * yScale);
110
                        Rectangle rProv = new Rectangle();
111
                        rProv.setFrame(0,0,sizeW,sizeH);
112
                        Paint resulPatternFill = null;
113
                        BufferedImage sample= null;
114

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

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

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

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

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

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

    
142
                        g.setColor(null);
143
                        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
144
                                        RenderingHints.VALUE_ANTIALIAS_ON);
145

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

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

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

    
183

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

    
191
                bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
192
                selImagePath = selImageUrl.toString();
193
        }
194

    
195

    
196

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

    
204
                bgImage = BackgroundFileStyle.createStyleByURL(imageUrl);
205
                imagePath = imageUrl.toString();
206
        }
207

    
208

    
209

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

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

    
226
        }
227

    
228
        public int getSymbolType() {
229
                return FShape.POLYGON;
230
        }
231

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

    
240
                xml.putProperty("angle", angle);
241
                xml.putProperty("scaleX", xScale);
242
                xml.putProperty("scaleY", yScale);
243
                xml.putProperty("imagePath", pathGenerator.getPath(imagePath));
244
                xml.putProperty("selImagePath", pathGenerator.getPath(selImagePath));
245
                if (getFillColor()!=null)
246
                        xml.putProperty("fillColor", StringUtilities.color2String(getFillColor()));
247

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

    
261
        public void setXMLEntity(XMLEntity xml) {
262

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

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

    
285
                }
286

    
287
                if (xml.contains("hasFill"))
288
                        setHasFill(xml.getBooleanProperty("hasFill"));
289

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

    
295
                if (xml.contains("unit")) { // remove this line when done
296
                        // measure unit (for outline)
297
                        setUnit(xml.getIntProperty("unit"));
298

    
299
                        // reference system (for outline)
300
                        setReferenceSystem(xml.getIntProperty("referenceSystem"));
301
                }
302

    
303
                if (xml.contains("hasOutline"))
304
                        setHasOutline(xml.getBooleanProperty("hasOutline"));
305

    
306

    
307

    
308
        }
309

    
310
        public String getClassName() {
311
                return getClass().getName();
312
        }
313

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

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

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

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

    
403

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

    
410

    
411
}