KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > svggen > DOMTreeManager


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.svggen;
19
20 import java.util.Iterator JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import org.apache.batik.ext.awt.g2d.GraphicContext;
27 import org.w3c.dom.Comment JavaDoc;
28 import org.w3c.dom.Document JavaDoc;
29 import org.w3c.dom.Element JavaDoc;
30 import org.w3c.dom.NodeList JavaDoc;
31
32 /**
33  * This class is used by the SVGGraphics2D SVG Generator to manage
34  * addition of new Nodes to the SVG DOM Tree. This class handles
35  * a set of DOMGroupManager objects that can all append to the
36  * top level group managed by this class. This allows multiple
37  * SVGGraphics2D instances, created from the same SVGGraphics2D
38  * through the various create methods, to append to the same
39  * SVG document and keep the rendering order correct.
40  *
41  * The root node managed by this DOMTreeManager contains two children:
42  * a top level group node and a top level defs node. The top level
43  * defs node contains the definition of common SVG entities such as
44  * the various AlphaComposite rules. Note that other defs can also be
45  * created under the top level group, for example to represent
46  * gradient or pattern paints.
47  * <br>
48  * [svg]
49  * |
50  * +-- [defs] Contain generic definitions
51  * +-- [g] Top level group
52  * |
53  * +-- [defs] Contains definitions specific to rendering
54  * +-- [g] Group 1
55  * +-- ...
56  * +-- [g] Group n
57  *
58  * @author <a HREF="mailto:cjolif">Christophe Jolif</a>
59  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
60  * @version $Id: DOMTreeManager.java,v 1.21 2005/04/02 12:58:17 deweese Exp $
61  */

62 public class DOMTreeManager implements SVGSyntax, ErrorConstants {
63     /**
64      * Maximum of Graphic Context attributes overrides
65      * in children of the current group.
66      */

67     int maxGCOverrides;
68
69     /**
70      * Set of group managers that build groups for
71      * this manager
72      */

73     protected Vector JavaDoc groupManagers = new Vector JavaDoc();
74
75     /**
76      * Set of definitions that are to be placed at the top of the
77      * document tree
78      */

79     protected List JavaDoc genericDefSet = new LinkedList JavaDoc();
80
81     /**
82      * Default SVG GraphicContext state
83      */

84     SVGGraphicContext defaultGC;
85
86     /**
87      * Top level group
88      */

89     protected Element JavaDoc topLevelGroup;
90
91     /**
92      * Used to convert the Java 2D API graphic context state
93      * into the SVG equivalent set of attributes and related
94      * definitions
95      */

96     SVGGraphicContextConverter gcConverter;
97
98     /**
99      * The context that stores the domFactory, the imageHandler
100      * and the extensionHandler.
101      */

102     protected SVGGeneratorContext generatorContext;
103
104     /**
105      * Converters used bVy this object to translate graphic context
106      * attributes
107      */

108     protected SVGBufferedImageOp filterConverter;
109
110     /**
111      * Set of definitions which can be used by custom extensions
112      */

113     protected List JavaDoc otherDefs;
114
115     /**
116      * Constructor
117      * @param gc default graphic context state
118      * @param generatorContext the SVG generator context
119      * @param maxGCOverrides defines how many overrides are allowed
120      * in children nodes of the current group.
121      */

122     public DOMTreeManager(GraphicContext gc,
123                           SVGGeneratorContext generatorContext,
124                           int maxGCOverrides){
125         if (gc == null)
126             throw new SVGGraphics2DRuntimeException(ERR_GC_NULL);
127
128         if (maxGCOverrides <= 0)
129             throw new SVGGraphics2DRuntimeException(ERR_MAXGCOVERRIDES_OUTOFRANGE);
130
131         if (generatorContext == null)
132             throw new SVGGraphics2DRuntimeException(ERR_CONTEXT_NULL);
133
134         this.generatorContext = generatorContext;
135         this.maxGCOverrides = maxGCOverrides;
136
137         // Start with a new Top Level Group
138
recycleTopLevelGroup();
139
140         // Build the default GC descriptor
141
defaultGC = gcConverter.toSVG(gc);
142     }
143
144     /**
145      * @param groupManager new DOMGroupManager to add to the list of
146      * managers that collaborate with this tree manager.
147      */

148     public void addGroupManager(DOMGroupManager groupManager){
149         if(groupManager != null)
150             groupManagers.addElement(groupManager);
151     }
152
153     /**
154      * @param groupManager DOMGroupManager to remove from the list of
155      * managers that collaborate with this tree manager
156      */

157     public void removeGroupManager(DOMGroupManager groupManager){
158         if(groupManager != null)
159             groupManagers.removeElement(groupManager);
160     }
161
162     /**
163      * When a group is appended to the tree by this call, all the
164      * other group managers are requested to start new groups, in
165      * order to preserve the Z-order.
166      *
167      * @param group new group to be appended to the topLevelGroup
168      * @param groupManager DOMTreeManager that produced the group.
169      */

170     public void appendGroup(Element JavaDoc group, DOMGroupManager groupManager){
171         topLevelGroup.appendChild(group);
172         int nManagers = groupManagers.size();
173         for(int i=0; i<nManagers; i++){
174             DOMGroupManager gm = (DOMGroupManager)groupManagers.elementAt(i);
175             if( gm != groupManager )
176                 gm.recycleCurrentGroup();
177         }
178     }
179
180     /**
181      * Reset the state of this object to handler a new topLevelGroup
182      */

183     protected void recycleTopLevelGroup(){
184         recycleTopLevelGroup(true);
185     }
186
187
188     /**
189      * Reset the state of this object to handler a new topLevelGroup
190      */

191     protected void recycleTopLevelGroup(boolean recycleConverters){
192         // First, recycle group managers
193
int nManagers = groupManagers.size();
194         for(int i=0; i<nManagers; i++){
195             DOMGroupManager gm = (DOMGroupManager)groupManagers.elementAt(i);
196             gm.recycleCurrentGroup();
197         }
198
199         // Create top level group node
200
topLevelGroup = generatorContext.domFactory.
201             createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
202
203         // Build new converters
204
if (recycleConverters) {
205             filterConverter =
206                 new SVGBufferedImageOp(generatorContext);
207             gcConverter =
208                 new SVGGraphicContextConverter(generatorContext);
209         }
210     }
211
212     /**
213      * Sets the topLevelGroup to the input element. This will throw an
214      * exception if the input element is not of type 'g' or if it is
215      * null.
216      */

217     public void setTopLevelGroup(Element JavaDoc topLevelGroup){
218         if(topLevelGroup == null)
219             throw new SVGGraphics2DRuntimeException(ERR_TOP_LEVEL_GROUP_NULL);
220
221         if(!SVG_G_TAG.equalsIgnoreCase(topLevelGroup.getTagName()))
222             throw new SVGGraphics2DRuntimeException(ERR_TOP_LEVEL_GROUP_NOT_G);
223
224         recycleTopLevelGroup(false);
225         this.topLevelGroup = topLevelGroup;
226     }
227
228     /**
229      * Returns the root element with the generic definitions and
230      * the topLevelGroup.
231      */

232     public Element JavaDoc getRoot(){
233         return getRoot(null);
234     }
235
236     /**
237      * Returns the root element with the generic definitions and
238      * the topLevelGroup.
239      */

240     public Element JavaDoc getRoot(Element JavaDoc svgElement){
241         Element JavaDoc svg = svgElement;
242
243         if (svg == null) {
244             svg = generatorContext.domFactory.
245                 createElementNS(SVG_NAMESPACE_URI, SVG_SVG_TAG);
246         }
247
248         // Enable background if required by AlphaComposite convertion
249
if (gcConverter.getCompositeConverter().
250             getAlphaCompositeConverter().requiresBackgroundAccess())
251             svg.setAttributeNS
252                 (null, SVG_ENABLE_BACKGROUND_ATTRIBUTE, SVG_NEW_VALUE);
253
254         if (generatorContext.generatorComment != null) {
255             Comment JavaDoc generatorComment = generatorContext.domFactory.
256                 createComment(generatorContext.generatorComment);
257             svg.appendChild(generatorComment);
258         }
259
260         // Set default rendering context attributes in node
261
applyDefaultRenderingStyle(svg);
262
263         svg.appendChild(getGenericDefinitions());
264         svg.appendChild(getTopLevelGroup());
265
266         return svg;
267     }
268
269     public void applyDefaultRenderingStyle(Element JavaDoc element) {
270         Map JavaDoc groupDefaults = defaultGC.getGroupContext();
271         generatorContext.styleHandler.setStyle(element, groupDefaults, generatorContext);
272     }
273
274     /**
275      * @return a defs element that contains all the generic
276      * definitions
277      */

278     public Element JavaDoc getGenericDefinitions() {
279         // when called several times, this will create several generic
280
// definition elements... not sure it is desired behavior...
281
Element JavaDoc genericDefs =
282             generatorContext.domFactory.createElementNS(SVG_NAMESPACE_URI,
283                                                         SVG_DEFS_TAG);
284         Iterator JavaDoc iter = genericDefSet.iterator();
285         while (iter.hasNext()) {
286             genericDefs.appendChild((Element JavaDoc)iter.next());
287         }
288
289         genericDefs.setAttributeNS(null, ATTR_ID, ID_PREFIX_GENERIC_DEFS);
290         return genericDefs;
291     }
292
293     /**
294      * @return the extension handler used by the DOMTreeManager.
295      */

296     public ExtensionHandler getExtensionHandler(){
297         return generatorContext.getExtensionHandler();
298     }
299
300     /**
301      * This will change the extension handler on the
302      * <code>SVGGeneratorContext</code>.
303      * @param extensionHandler new extension handler this object should use
304      */

305     void setExtensionHandler(ExtensionHandler extensionHandler) {
306         generatorContext.setExtensionHandler(extensionHandler);
307     }
308
309     /**
310      * Invoking this method will return a set of definition element that
311      * contain all the definitions referenced by the attributes generated by
312      * the various converters. This also resets the converters.
313      */

314     public List JavaDoc getDefinitionSet(){
315         //
316
// The definition set contains all the definitions minus
317
// any definition that has been placed in the generic definition set
318
//
319
List JavaDoc defSet = gcConverter.getDefinitionSet();
320         defSet.removeAll(genericDefSet);
321         defSet.addAll(filterConverter.getDefinitionSet());
322         if (otherDefs != null){
323             defSet.addAll(otherDefs);
324             otherDefs = null;
325         }
326
327         // Build new converters
328
filterConverter = new SVGBufferedImageOp(generatorContext);
329         gcConverter = new SVGGraphicContextConverter(generatorContext);
330
331         return defSet;
332     }
333
334     /**
335      * Lets custom implementations for various extensions add
336      * elements to the <defs> sections.
337      */

338     public void addOtherDef(Element JavaDoc definition){
339         if (otherDefs == null){
340             otherDefs = new LinkedList JavaDoc();
341         }
342
343         otherDefs.add(definition);
344     }
345
346     /**
347      * Invoking this method will return a reference to the topLevelGroup
348      * Element managed by this object. It will also cause this object
349      * to start working with a new topLevelGroup.
350      *
351      * @return top level group
352      */

353     public Element JavaDoc getTopLevelGroup(){
354         boolean includeDefinitionSet = true;
355         return getTopLevelGroup(includeDefinitionSet);
356     }
357
358     /**
359      * Invoking this method will return a reference to the topLevelGroup
360      * Element managed by this object. It will also cause this object
361      * to start working with a new topLevelGroup.
362      *
363      * @param includeDefinitionSet if true, the definition set is included and
364      * the converters are reset (i.e., they start with an empty set
365      * of definitions).
366      * @return top level group
367      */

368     public Element JavaDoc getTopLevelGroup(boolean includeDefinitionSet){
369         Element JavaDoc topLevelGroup = this.topLevelGroup;
370
371         //
372
// Include definition set if requested
373
//
374
if(includeDefinitionSet){
375             List JavaDoc defSet = getDefinitionSet();
376             if(defSet.size() > 0){
377                 Element JavaDoc defElement = null;
378
379                 NodeList JavaDoc defsElements =
380                     topLevelGroup.getElementsByTagName(SVG_DEFS_TAG);
381                 if (defsElements.getLength() > 0)
382                     defElement = (Element JavaDoc)defsElements.item(0);
383
384                 if (defElement == null) {
385                     defElement =
386                         generatorContext.domFactory.
387                         createElementNS(SVG_NAMESPACE_URI,
388                                         SVG_DEFS_TAG);
389                     defElement.
390                         setAttributeNS(null, ATTR_ID,
391                                        generatorContext.idGenerator.
392                                        generateID(ID_PREFIX_DEFS));
393                     topLevelGroup.insertBefore(defElement,
394                                                topLevelGroup.getFirstChild());
395                 }
396
397                 Iterator JavaDoc iter = defSet.iterator();
398                 while(iter.hasNext())
399                     defElement.appendChild((Element JavaDoc)iter.next());
400             }
401         }
402
403         // If the definition set is included, then the converters have already
404
// been recycled in getDefinitionSet. Otherwise, they should not be
405
// recycled. So, in all cases, do not recycle the converters here.
406
recycleTopLevelGroup(false);
407
408         return topLevelGroup;
409     }
410
411     public SVGBufferedImageOp getFilterConverter() {
412         return filterConverter;
413     }
414
415     public SVGGraphicContextConverter getGraphicContextConverter() {
416         return gcConverter;
417     }
418
419     SVGGeneratorContext getGeneratorContext() {
420         return generatorContext;
421     }
422
423     Document JavaDoc getDOMFactory() {
424         return generatorContext.domFactory;
425     }
426
427     StyleHandler getStyleHandler() {
428         return generatorContext.styleHandler;
429     }
430 }
431
Popular Tags