1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.svg.edit.client.engine;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.vectomatic.dom.svg.OMNode;
30 import org.vectomatic.dom.svg.OMSVGElement;
31 import org.vectomatic.dom.svg.impl.Attr;
32 import org.vectomatic.dom.svg.impl.NamedNodeMap;
33 import org.vectomatic.dom.svg.impl.SVGElement;
34 import org.vectomatic.dom.svg.itf.ISVGTransformable;
35 import org.vectomatic.dom.svg.utils.DOMHelper;
36 import org.vectomatic.dom.svg.utils.SVGConstants;
37
38 import com.google.gwt.core.client.GWT;
39 import com.google.gwt.dom.client.Element;
40 import com.google.gwt.dom.client.Node;
41 import com.google.gwt.dom.client.NodeList;
42
43
44
45
46
47 public class SVGProcessor {
48
49
50
51
52
53
54
55
56
57 protected static Set<String> definitionElementNames;
58
59
60
61 protected static Set<String> graphicalElementNames;
62
63
64
65 protected static Set<String> groupElementNames;
66
67 public static boolean isGroupElement(SVGElement element) {
68 if (groupElementNames == null) {
69 groupElementNames = new HashSet<String>(Arrays.asList(new String[] {
70 SVGConstants.SVG_G_TAG,
71 SVGConstants.SVG_DEFS_TAG
72 }));
73 }
74 return groupElementNames.contains(DOMHelper.getLocalName(element));
75 }
76
77
78
79
80
81
82 public static boolean isDefinitionElement(SVGElement element) {
83 if (definitionElementNames == null) {
84 definitionElementNames = new HashSet<String>(Arrays.asList(new String[] {
85 SVGConstants.SVG_SYMBOL_TAG,
86 SVGConstants.SVG_DEFS_TAG,
87 SVGConstants.SVG_PATTERN_TAG,
88 SVGConstants.SVG_MARKER_TAG,
89 SVGConstants.SVG_CLIP_PATH_TAG,
90 SVGConstants.SVG_MASK_TAG,
91 SVGConstants.SVG_GLYPH_TAG,
92 SVGConstants.SVG_MISSING_GLYPH_TAG
93 }));
94 }
95 return definitionElementNames.contains(DOMHelper.getLocalName(element));
96 }
97
98
99
100
101
102
103 public static boolean isGraphicalElement(SVGElement element) {
104 if (graphicalElementNames == null) {
105 graphicalElementNames = new HashSet<String>(Arrays.asList(new String[] {
106 SVGConstants.SVG_CIRCLE_TAG,
107 SVGConstants.SVG_ELLIPSE_TAG,
108 SVGConstants.SVG_G_TAG,
109 SVGConstants.SVG_IMAGE_TAG,
110 SVGConstants.SVG_LINE_TAG,
111 SVGConstants.SVG_PATH_TAG,
112 SVGConstants.SVG_POLYLINE_TAG,
113 SVGConstants.SVG_POLYGON_TAG,
114 SVGConstants.SVG_RECT_TAG,
115 SVGConstants.SVG_TEXT_TAG,
116 SVGConstants.SVG_T_REF_TAG,
117 SVGConstants.SVG_T_SPAN_TAG,
118 SVGConstants.SVG_USE_TAG
119 }));
120 }
121 return graphicalElementNames.contains(DOMHelper.getLocalName(element));
122 }
123
124
125
126
127
128
129 public static boolean isSvgElement(Node node) {
130 return node.getNodeType() == Node.ELEMENT_NODE
131 && SVGConstants.SVG_NAMESPACE_URI.equals(DOMHelper.getNamespaceURI(node));
132 }
133
134
135
136
137
138
139 public static boolean isTitleDescElement(SVGElement element) {
140 String localName = DOMHelper.getLocalName(element);
141 return SVGConstants.SVG_TITLE_TAG.equals(localName) || SVGConstants.SVG_DESC_TAG.equals(localName);
142 }
143
144
145
146
147
148
149 public static boolean isTransformable(Node node) {
150 return OMNode.convert(node) instanceof ISVGTransformable;
151 }
152
153
154
155
156
157
158
159 static Set<String> IDREF_ATTS = new HashSet<String>(Arrays.asList(
160 new String[] { "clip-path",
161 "mask",
162 "marker-start",
163 "marker-mid",
164 "marker-end",
165 "fill",
166 "stroke",
167 "filter",
168 "cursor",
169 "style"}));
170 static IdRefTokenizer TOKENIZER = GWT.create(IdRefTokenizer.class);
171
172
173
174
175
176
177
178
179
180 public static void getIdReferences(Collection<String> refs, Element element) {
181 NamedNodeMap<Attr> attrs = DOMHelper.getAttributes(element);
182 for (int i = 0, length = attrs.getLength(); i < length; i++) {
183 Attr attr = attrs.item(i);
184 if (IDREF_ATTS.contains(attr.getName())) {
185 TOKENIZER.tokenize(attr.getValue());
186 IdRefTokenizer.IdRefToken token;
187 while ((token = TOKENIZER.nextToken()) != null) {
188 if (token.getKind() == IdRefTokenizer.IdRefToken.IDREF) {
189 refs.add(token.getValue());
190 }
191 }
192 }
193 }
194 }
195
196
197
198
199
200
201
202
203 static int docId;
204 public static void main(String[] args) {
205 for (int i = 0; i < args.length; i++) {
206 IdRefTokenizer tokenizer = new IdRefTokenizer();
207 StringBuilder builder = new StringBuilder();
208 tokenizer.tokenize(args[i]);
209 IdRefTokenizer.IdRefToken token;
210 while ((token = tokenizer.nextToken()) != null) {
211 String txt = (token.getKind() == IdRefTokenizer.IdRefToken.DATA) ? token.getValue() : ("{" + token.getValue() + "}");
212 builder.append(txt);
213 }
214 System.out.println("\"" + args[i] + "\" ==> \"" + builder.toString() + "\"");
215 }
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230 public static String newIdPrefix() {
231 docId++;
232 return "d" + docId;
233 }
234
235
236
237
238
239
240
241 public static String newPrefixExtension(String base, String extension) {
242 return base + "/" + extension;
243 }
244
245 public static String makeId(String idPrefix, String localId) {
246 return "{" + idPrefix + "}" + localId;
247 }
248
249
250
251
252
253
254
255 public static void normalizeIds(OMSVGElement srcSvg, String idPrefix) {
256
257
258 int idIndex = 0;
259 Map<String, String> idToNormalizedId = new HashMap<String, String>();
260 List<Element> queue = new ArrayList<Element>();
261 queue.add(srcSvg.getElement());
262 while (queue.size() > 0) {
263 Element element = queue.remove(0);
264 String id = element.getId();
265 if (id != null) {
266 String normalizedId = makeId(idPrefix, Integer.toString(idIndex++));
267 idToNormalizedId.put(id, normalizedId);
268 element.setId(normalizedId);
269 }
270 NodeList<Node> childNodes = element.getChildNodes();
271 for (int i = 0, length = childNodes.getLength(); i < length; i++) {
272 Node childNode = childNodes.getItem(i);
273 if (childNode.getNodeType() == Node.ELEMENT_NODE) {
274 queue.add((Element)childNode.cast());
275 }
276 }
277 }
278
279
280 queue.add(srcSvg.getElement());
281 while (queue.size() > 0) {
282 Element element = queue.remove(0);
283 if (DOMHelper.hasAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE)) {
284 String idRef = DOMHelper.getAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE);
285
286 if (idRef.startsWith("#")) {
287
288
289 String normalizeIdRef = idToNormalizedId.get(idRef.substring(1));
290 DOMHelper.setAttributeNS(element, SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE, "#" + normalizeIdRef);
291 }
292 }
293 NamedNodeMap<Attr> attrs = DOMHelper.getAttributes(element);
294 for (int i = 0, length = attrs.getLength(); i < length; i++) {
295 Attr attr = attrs.item(i);
296 if (IDREF_ATTS.contains(attr.getName())) {
297 StringBuilder builder = new StringBuilder();
298 TOKENIZER.tokenize(attr.getValue());
299 IdRefTokenizer.IdRefToken token;
300 while ((token = TOKENIZER.nextToken()) != null) {
301 String value = token.getValue();
302 if (token.getKind() == IdRefTokenizer.IdRefToken.DATA) {
303 builder.append(value);
304 } else {
305 value = idToNormalizedId.get(value);
306 builder.append(value == null ? token.getValue() : value);
307 }
308 }
309 attr.setValue(builder.toString());
310 }
311 }
312 NodeList<Node> childNodes = element.getChildNodes();
313 for (int i = 0, length = childNodes.getLength(); i < length; i++) {
314 Node childNode = childNodes.getItem(i);
315 if (childNode.getNodeType() == Node.ELEMENT_NODE) {
316 queue.add((Element)childNode.cast());
317 }
318 }
319 }
320 }
321
322
323
324
325
326
327 public static void reparent(OMSVGElement src, OMSVGElement dest) {
328 Element srcElement = src.getElement();
329 Element destElement = dest.getElement();
330 Node node;
331 while((node = srcElement.getFirstChild()) != null) {
332 destElement.appendChild(srcElement.removeChild(node));
333 }
334 }
335
336 }
337