Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / style / SVGStyle.java @ 35927

History | View | Annotate | Download (8.98 KB)

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.symbology.fmap.mapcontext.rendering.symbol.style;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.Rectangle;
45
import java.awt.RenderingHints;
46
import java.awt.geom.AffineTransform;
47
import java.awt.geom.Rectangle2D;
48
import java.io.IOException;
49
import java.net.URISyntaxException;
50
import java.net.URL;
51

    
52
import org.apache.batik.bridge.BridgeContext;
53
import org.apache.batik.bridge.DocumentLoader;
54
import org.apache.batik.bridge.GVTBuilder;
55
import org.apache.batik.bridge.UserAgentAdapter;
56
import org.apache.batik.bridge.ViewBox;
57
import org.apache.batik.dom.svg.SVGOMDocument;
58
import org.apache.batik.gvt.GraphicsNode;
59
import org.apache.batik.gvt.renderer.StaticRenderer;
60
import org.w3c.dom.Document;
61
import org.w3c.dom.Element;
62

    
63
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
64
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
65
import org.gvsig.tools.ToolsLocator;
66
import org.gvsig.tools.dynobject.DynStruct;
67
import org.gvsig.tools.persistence.PersistenceManager;
68
import org.gvsig.tools.persistence.PersistentState;
69
import org.gvsig.tools.persistence.exception.PersistenceException;
70
import org.gvsig.tools.util.Callable;
71

    
72
/**
73
 * Style for a SVG files.This is a XML specification and file format for
74
 * describing two-dimensional vector graphics, both static and animated.
75
 * SVG can be purely declarative or may include scripting. Images can contain
76
 * hyperlinks using outbound simple XLinks.It is an open standard created
77
 * by the World Wide Web Consortium..
78
 * 
79
 * @author jaume dominguez faus - jaume.dominguez@iver.es
80
 * 
81
 */
82
public class SVGStyle extends BackgroundFileStyle {
83

    
84
    public static final String SVG_STYLE_PERSISTENCE_DEFINITION_NAME =
85
        "SVGStyle";
86
    private static final String SOURCE = "source";
87
    private GVTBuilder gvtBuilder = new GVTBuilder();
88
    private UserAgentAdapter userAgent;
89
    private DocumentLoader loader;
90
    private StaticRenderer renderer = new StaticRenderer();
91
    private GraphicsNode gvtRoot;
92
    private BridgeContext ctx;
93
    private Element elt;
94

    
95
    protected static RenderingHints defaultRenderingHints;
96
    static {
97
        defaultRenderingHints = new RenderingHints(null);
98
        defaultRenderingHints.put(RenderingHints.KEY_ANTIALIASING,
99
            RenderingHints.VALUE_ANTIALIAS_ON);
100

    
101
        defaultRenderingHints.put(RenderingHints.KEY_INTERPOLATION,
102
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
103
    }
104

    
105
    /**
106
     * Constructor method
107
     * 
108
     */
109
    public SVGStyle() {
110
        userAgent = new UserAgentAdapter();
111
        loader = new DocumentLoader(userAgent);
112
        ctx = new BridgeContext(userAgent, loader);
113
        renderer.setDoubleBuffered(true);
114
    }
115

    
116
    public void drawInsideRectangle(Graphics2D g,
117
        Rectangle rect,
118
        boolean keepAspectRatio) throws SymbolDrawingException {
119
        if (keepAspectRatio) {
120
            AffineTransform ataux;
121
            if (elt.hasAttribute("viewBox")) {
122

    
123
                try {
124
                    ataux =
125
                        ViewBox.getViewTransform(null,
126
                            elt,
127
                            (float) rect.getWidth(),
128
                            (float) rect.getHeight(),
129
                            ctx);
130
                } catch (NullPointerException e) {
131
                    throw new SymbolDrawingException(SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS);
132
                }
133
            } else {
134
                Rectangle2D bounds = gvtRoot.getBounds();
135
                double xOffset = 0;
136
                double yOffset = 0;
137
                double scale;
138
                scale =
139
                    Math.min(rect.getWidth() / bounds.getWidth(),
140
                        rect.getHeight() / bounds.getHeight());
141
                xOffset = 0.5 * (rect.getWidth() - bounds.getWidth() * scale);
142
                yOffset = 0.5 * (rect.getHeight() - bounds.getHeight() * scale);
143

    
144
                ataux = AffineTransform.getTranslateInstance(xOffset, yOffset);
145

    
146
                ataux.concatenate(AffineTransform.getScaleInstance(scale, scale));
147

    
148
            }
149
            RenderingHints renderingHints = new RenderingHints(null);
150
            renderingHints.putAll(defaultRenderingHints);
151
            g.setRenderingHints(renderingHints);
152
            gvtRoot.setTransform(ataux);
153
            gvtRoot.paint(g);
154

    
155
        } else {
156

    
157
            Rectangle2D bounds = gvtRoot.getBounds();
158

    
159
            double xOffset = 0;
160
            double yOffset = 0;
161
            double xScale = 1;
162
            double yScale = 1;
163
            xScale = rect.getWidth() / bounds.getWidth();
164
            yScale = rect.getHeight() / bounds.getHeight();
165
            xOffset = 0.5 * (rect.getWidth() - bounds.getWidth() * xScale);
166
            yOffset = 0.5 * (rect.getHeight() - bounds.getHeight() * yScale);
167

    
168
            AffineTransform ataux;
169

    
170
            ataux = AffineTransform.getTranslateInstance(xOffset, yOffset);
171

    
172
            ataux.concatenate(AffineTransform.getScaleInstance(xScale, yScale));
173

    
174
            RenderingHints renderingHints = new RenderingHints(null);
175
            renderingHints.putAll(defaultRenderingHints);
176
            g.setRenderingHints(renderingHints);
177
            gvtRoot.setTransform(ataux);
178
            gvtRoot.paint(g);
179
        }
180
    }
181

    
182
    public boolean isSuitableFor(ISymbol symbol) {
183
        return true;
184
    }
185

    
186
    public void setSource(URL url) throws IOException {
187

    
188
            source = url;
189
            Document svgDoc;
190
            try {
191
                    svgDoc = loader.loadDocument(url.toURI().toString());
192
            } catch (URISyntaxException e) {
193
            throw new IOException(e.getMessage());
194
            }
195
            gvtRoot = gvtBuilder.build(ctx, svgDoc);
196
            renderer.setTree(gvtRoot);
197
            elt = ((SVGOMDocument) svgDoc).getRootElement();
198
    }
199

    
200
    public Rectangle getBounds() {
201
        try {
202
            Rectangle2D r = gvtRoot.getBounds();
203
            return new Rectangle((int) r.getX(),
204
                (int) r.getY(),
205
                (int) r.getWidth(),
206
                (int) r.getHeight());
207
        } catch (Exception e) {
208
            return new Rectangle();
209
        }
210
    }
211

    
212
    public void drawOutline(Graphics2D g, Rectangle r) throws SymbolDrawingException {
213
        drawInsideRectangle(g, r);
214
    }
215

    
216
    
217
    public void loadFromState(PersistentState state) throws PersistenceException {
218
            try {
219
                    String sourceSymbolInLibrary = state.getString(SOURCE_SYMBOL_IN_LIBRARY);
220
                    if (sourceSymbolInLibrary != null){
221
                            setSource(new URL(getSymbolLibraryURL().toString()+sourceSymbolInLibrary));
222
                    } else {
223
                            setSource(state.getURL(SOURCE));
224
                    }
225
            } catch (Exception e) {
226
                    throw new PersistenceCantSetSourceException(e);
227
            }
228
    }
229

    
230
    public void saveToState(PersistentState state) throws PersistenceException {
231
            if (isLibrarySymbol()){
232
                    state.set(SOURCE_SYMBOL_IN_LIBRARY, getSourceSymbolInLibrary());
233
            } else {
234
                    state.setNull(SOURCE_SYMBOL_IN_LIBRARY);
235
            }
236
        state.set(SOURCE, source);
237
    }
238

    
239
    public static class RegisterPersistence implements Callable {
240

    
241
        public Object call() throws Exception {
242
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
243
            if (manager.getDefinition(SVG_STYLE_PERSISTENCE_DEFINITION_NAME) == null) {
244
                DynStruct definition =
245
                    manager.addDefinition(SVGStyle.class,
246
                        SVG_STYLE_PERSISTENCE_DEFINITION_NAME,
247
                        SVG_STYLE_PERSISTENCE_DEFINITION_NAME
248
                            + " Persistence definition",
249
                        null,
250
                        null);
251

    
252
                // Extend the Style base definition
253
                definition.extend(manager.getDefinition(BACKGROUND_FILE_STYLE_PERSISTENCE_DEFINITION_NAME));
254

    
255
                definition.addDynFieldURL(SOURCE).setMandatory(true);
256
                definition.addDynFieldString(SOURCE_SYMBOL_IN_LIBRARY).setMandatory(false);
257
            }
258
            return Boolean.TRUE;
259
        }
260

    
261
    }
262
}