View Javadoc

1   /**********************************************
2    * Copyright (C) 2010 Lukas Laag
3    * This file is part of vectomatic2.
4    * 
5    * vectomatic2 is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * vectomatic2 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 vectomatic2.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client.engine;
19  
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.vectomatic.dom.svg.OMSVGSVGElement;
29  import org.vectomatic.dom.svg.impl.Attr;
30  import org.vectomatic.dom.svg.impl.NamedNodeMap;
31  import org.vectomatic.dom.svg.utils.DOMHelper;
32  import org.vectomatic.dom.svg.utils.SVGConstants;
33  
34  import com.google.gwt.core.client.GWT;
35  import com.google.gwt.dom.client.Element;
36  import com.google.gwt.dom.client.Node;
37  import com.google.gwt.dom.client.NodeList;
38  
39  /**
40   * Class to normalize id and idrefs in an SVG document
41   * @author laaglu
42   */
43  public class SVGProcessor {
44  	static int docId;
45  	public static void main(String[] args) {
46  		for (int i = 0; i < args.length; i++) {
47  			IdRefTokenizer tokenizer = new IdRefTokenizer();
48  			StringBuilder builder = new StringBuilder();
49  			tokenizer.tokenize(args[i]);
50  			IdRefTokenizer.IdRefToken token;
51  			while ((token = tokenizer.nextToken()) != null) {
52  				String txt = (token.getKind() == IdRefTokenizer.IdRefToken.DATA) ? token.getValue() : ("{" + token.getValue() + "}");
53  				builder.append(txt);
54  			}
55  			System.out.println("\"" + args[i] + "\" ==> \"" + builder.toString() + "\"");
56  		}
57  	}
58  	
59  	public static int normalizeIds(OMSVGSVGElement srcSvg) {
60  		docId++;
61  		// Collect all the original element ids and replace them with a
62  		// normalized id
63  		int idIndex = 0;
64  		Map<String, Element> idToElement = new HashMap<String, Element>();
65  		Map<String, String> idToNormalizedId = new HashMap<String, String>();
66  		List<Element> queue = new ArrayList<Element>();
67  		queue.add(srcSvg.getElement());
68  		while (queue.size() > 0) {
69  			Element element = queue.remove(0);
70  			String id = element.getId();
71  			if (id != null) {
72  				idToElement.put(id, element);
73  				String normalizedId = "d" + docId + "_" + idIndex++;
74  				idToNormalizedId.put(id, normalizedId);
75  				element.setId(normalizedId);
76  			}
77  			NodeList<Node> childNodes =  element.getChildNodes();
78  			for (int i = 0, length = childNodes.getLength(); i < length; i++) {
79  				Node childNode = childNodes.getItem(i);
80  				if (childNode.getNodeType() == Node.ELEMENT_NODE) {
81  					queue.add((Element)childNode.cast());
82  				}
83  			}
84  		}
85  		
86  		// Change all the attributes which are URI references
87  		Set<String> attNames = new HashSet<String>(Arrays.asList(
88  			new String[] { "clip-path",
89  			 "mask",
90  			 "marker-start",
91  			 "marker-mid",
92  			 "marker-end",
93  			 "fill",
94  			 "stroke",
95  			 "filter",
96  			 "cursor",
97  			 "style"}));
98  		queue.add(srcSvg.getElement());
99  		IdRefTokenizer tokenizer = GWT.create(IdRefTokenizer.class);
100 		while (queue.size() > 0) {
101 			Element element = queue.remove(0);
102 			if (DOMHelper.hasAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE)) {
103 				String idRef = DOMHelper.getAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE).substring(1);
104 				String normalizeIdRef = idToNormalizedId.get(idRef);
105 				DOMHelper.setAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE, "#" + normalizeIdRef);
106 			}
107 			NamedNodeMap<Attr> attrs = DOMHelper.getAttributes(element);
108 			for (int i = 0, length = attrs.getLength(); i < length; i++) {
109 				Attr attr = attrs.item(i);
110 				if (attNames.contains(attr.getName())) {
111 					StringBuilder builder = new StringBuilder();
112 					tokenizer.tokenize(attr.getValue());
113 					IdRefTokenizer.IdRefToken token;
114 					while ((token = tokenizer.nextToken()) != null) {
115 						String value = token.getValue();
116 						if (token.getKind() == IdRefTokenizer.IdRefToken.DATA) {
117 							builder.append(value);
118 						} else {
119 							value = idToNormalizedId.get(value);
120 							builder.append(value == null ? token.getValue() : value);
121 						}
122 					}
123 					attr.setValue(builder.toString());
124 				}
125 			}
126 			NodeList<Node> childNodes =  element.getChildNodes();
127 			for (int i = 0, length = childNodes.getLength(); i < length; i++) {
128 				Node childNode = childNodes.getItem(i);
129 				if (childNode.getNodeType() == Node.ELEMENT_NODE) {
130 					queue.add((Element)childNode.cast());
131 				}
132 			}
133 		}
134 		return docId;
135 	}
136 }
137