-
Notifications
You must be signed in to change notification settings - Fork 155
Expand file tree
/
Copy pathGVTBuilder.java
More file actions
261 lines (240 loc) · 9.64 KB
/
GVTBuilder.java
File metadata and controls
261 lines (240 loc) · 9.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.batik.bridge;
import org.apache.batik.gvt.CompositeGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.RootGraphicsNode;
import org.apache.batik.util.HaltingThread;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* This class is responsible for creating a GVT tree using an SVG DOM tree.
*
* @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
* @version $Id$
*/
public class GVTBuilder implements SVGConstants {
/**
* Constructs a new builder.
*/
public GVTBuilder() { }
/**
* Builds using the specified bridge context the specified SVG document.
*
* @param ctx the bridge context
* @param document the SVG document to build
* @exception BridgeException if an error occurred while constructing
* the GVT tree
*/
public GraphicsNode build(BridgeContext ctx, Document document) {
// the bridge context is now associated to one document
ctx.setDocument(document);
ctx.initializeDocument(document);
// inform the bridge context the builder to use
ctx.setGVTBuilder(this);
// build the GVT tree
DocumentBridge dBridge = ctx.getDocumentBridge();
RootGraphicsNode rootNode = null;
try {
// create the root node
rootNode = dBridge.createGraphicsNode(ctx, document);
Element svgElement = document.getDocumentElement();
GraphicsNode topNode = null;
// get the appropriate bridge according to the specified element
Bridge bridge = ctx.getBridge(svgElement);
if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
return null;
}
// create the associated composite graphics node
GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
topNode = gnBridge.createGraphicsNode(ctx, svgElement);
if (topNode == null) {
return null;
}
rootNode.getChildren().add(topNode);
buildComposite(ctx, svgElement, (CompositeGraphicsNode)topNode);
gnBridge.buildGraphicsNode(ctx, svgElement, topNode);
// finally, build the root node
dBridge.buildGraphicsNode(ctx, document, rootNode);
} catch (BridgeException ex) {
// update the exception with the missing parameters
ex.setGraphicsNode(rootNode);
//ex.printStackTrace();
throw ex; // re-throw the udpated exception
}
// For cursor handling
if (ctx.isInteractive()) {
ctx.addUIEventListeners(document);
// register GVT listeners for AWT event support
ctx.addGVTListener(document);
}
// <!> FIXME: TO BE REMOVED
if (ctx.isDynamic()) {
// register DOM listeners for dynamic support
ctx.addDOMListeners();
}
return rootNode;
}
/**
* Builds using the specified bridge context the specified Element.
*
* @param ctx the bridge context
* @param e the element to build
* @exception BridgeException if an error occurred while constructing
* the GVT tree
*/
public GraphicsNode build(BridgeContext ctx, Element e) {
// get the appropriate bridge according to the specified element
Bridge bridge = ctx.getBridge(e);
if (bridge instanceof GenericBridge) {
// If it is a GenericBridge just handle it and any GenericBridge
// descendents and return.
((GenericBridge) bridge).handleElement(ctx, e);
handleGenericBridges(ctx, e);
return null;
} else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
handleGenericBridges(ctx, e);
return null;
}
// create the associated graphics node
GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
// check the display property
if (!gnBridge.getDisplay(e)) {
handleGenericBridges(ctx, e);
return null;
}
GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
if (gn != null) {
if (gnBridge.isComposite()) {
buildComposite(ctx, e, (CompositeGraphicsNode)gn);
} else {
handleGenericBridges(ctx, e);
}
gnBridge.buildGraphicsNode(ctx, e, gn);
}
// <!> FIXME: see build(BridgeContext, Element)
// + may load the script twice (for example
// outside 'use' is ok versus local 'use' maybe wrong).
if (ctx.isDynamic()) {
//BridgeEventSupport.loadScripts(ctx, e);
}
return gn;
}
/**
* Builds a composite Element.
*
* @param ctx the bridge context
* @param e the element to build
* @param parentNode the composite graphics node, parent of the
* graphics node to build
* @exception BridgeException if an error occurred while constructing
* the GVT tree
*/
protected void buildComposite(BridgeContext ctx,
Element e,
CompositeGraphicsNode parentNode) {
for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
if (n.getNodeType() == Node.ELEMENT_NODE) {
buildGraphicsNode(ctx, (Element)n, parentNode);
}
}
}
/**
* Builds a 'leaf' Element.
*
* @param ctx the bridge context
* @param e the element to build
* @param parentNode the composite graphics node, parent of the
* graphics node to build
* @exception BridgeException if an error occurred while constructing
* the GVT tree
*/
protected void buildGraphicsNode(BridgeContext ctx,
Element e,
CompositeGraphicsNode parentNode) {
// Check If we should halt early.
if (HaltingThread.hasBeenHalted()) {
throw new InterruptedBridgeException();
}
// get the appropriate bridge according to the specified element
Bridge bridge = ctx.getBridge(e);
if (bridge instanceof GenericBridge) {
// If it is a GenericBridge just handle it and any GenericBridge
// descendents and return.
((GenericBridge) bridge).handleElement(ctx, e);
handleGenericBridges(ctx, e);
return;
} else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
handleGenericBridges(ctx, e);
return;
}
// check the display property
if (!CSSUtilities.convertDisplay(e)) {
handleGenericBridges(ctx, e);
return;
}
GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
try {
// create the associated graphics node
GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
if (gn != null) {
// attach the graphics node to the GVT tree now !
parentNode.getChildren().add(gn);
// check if the element has children to build
if (gnBridge.isComposite()) {
buildComposite(ctx, e, (CompositeGraphicsNode)gn);
} else {
// if not then still handle the GenericBridges
handleGenericBridges(ctx, e);
}
gnBridge.buildGraphicsNode(ctx, e, gn);
} else {
handleGenericBridges(ctx, e);
}
} catch (BridgeException ex) {
// some bridge may decide that the node in error can be
// displayed (e.g. polyline, path...)
// In this case, the exception contains the GraphicsNode
GraphicsNode errNode = ex.getGraphicsNode();
if (errNode != null) {
parentNode.getChildren().add(errNode);
gnBridge.buildGraphicsNode(ctx, e, errNode);
ex.setGraphicsNode(null);
}
//ex.printStackTrace();
throw ex;
}
}
/**
* Handles any GenericBridge elements which are children of the
* specified element.
* @param ctx the bridge context
* @param e the element whose child elements should be handled
*/
protected void handleGenericBridges(BridgeContext ctx, Element e) {
for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
if (n instanceof Element) {
Element e2 = (Element) n;
Bridge b = ctx.getBridge(e2);
if (b instanceof GenericBridge) {
((GenericBridge) b).handleElement(ctx, e2);
}
handleGenericBridges(ctx, e2);
}
}
}
}